codesesh 1.0.0 → 1.0.1
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/README.md +27 -4
- package/dist/{chunk-BEF6LLRG.js → chunk-JHX5OLL4.js} +4010 -2248
- package/dist/chunk-JHX5OLL4.js.map +1 -0
- package/dist/{chunk-TIHF4T3K.js → chunk-OFTTM3UD.js} +80 -16
- package/dist/chunk-OFTTM3UD.js.map +1 -0
- package/dist/{dist-3F467V44.js → dist-N2PQATP2.js} +40 -4
- package/dist/index.js +1818 -454
- package/dist/index.js.map +1 -1
- package/dist/scan-refresh-worker.js +274 -95
- package/dist/scan-refresh-worker.js.map +1 -1
- package/dist/search-index-worker.js +112 -50
- package/dist/search-index-worker.js.map +1 -1
- package/dist/smart-tag-worker.js +5 -3
- package/dist/smart-tag-worker.js.map +1 -1
- package/dist/web/assets/ErrorBoundary-D11tWzfn.js +1 -0
- package/dist/web/assets/OverviewScreen-DriPmCam.js +1 -0
- package/dist/web/assets/Projects-BPDIcUBK.js +1 -0
- package/dist/web/assets/SearchFilterBar-Bx73B5e9.js +1 -0
- package/dist/web/assets/SearchResultsPanel-A6_3TPhW.js +1 -0
- package/dist/web/assets/SessionDetail-lQz99ARH.js +54 -0
- package/dist/web/assets/agents-BkRP_ww3.js +1 -0
- package/dist/web/assets/contract-V6QuD0UY.js +1 -0
- package/dist/web/assets/index-B2RqUgZ5.css +1 -0
- package/dist/web/assets/index-BgWoUD_4.js +1410 -0
- package/dist/web/assets/panel-C-gc79Gz.js +1 -0
- package/dist/web/assets/session-indexes-0oT5HSS5.js +4 -0
- package/dist/web/assets/utils-DgUgu15E.js +1 -0
- package/dist/web/index.html +10 -32
- package/dist/web/theme-bootstrap.js +19 -0
- package/package.json +10 -10
- package/dist/chunk-BEF6LLRG.js.map +0 -1
- package/dist/chunk-TIHF4T3K.js.map +0 -1
- package/dist/web/assets/ErrorBoundary-BY-N1QzJ.js +0 -1
- package/dist/web/assets/OverviewScreen-_ZaVjhxN.js +0 -1
- package/dist/web/assets/Projects-q6cEm2dc.js +0 -1
- package/dist/web/assets/SearchFilterBar-CrVBpo40.js +0 -1
- package/dist/web/assets/SearchResultsPanel-Cg5V8Ia6.js +0 -1
- package/dist/web/assets/SessionDetail-BSSuddsZ.js +0 -54
- package/dist/web/assets/chunk-62JRHF6Z-BWRsEBnL.js +0 -4
- package/dist/web/assets/index-C3KgxGwE.js +0 -1410
- package/dist/web/assets/index-DQX42cFQ.css +0 -1
- package/dist/web/assets/panel-B7kuE60V.js +0 -1
- package/dist/web/assets/session-indexes-DmnjZ_JL.js +0 -1
- package/dist/web/assets/utils-t2u9IbNT.js +0 -1
- /package/dist/{dist-3F467V44.js.map → dist-N2PQATP2.js.map} +0 -0
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/server.ts","../src/api/routes.ts","../src/time-window-resolution.ts","../src/api/query-params.ts","../src/api/session-aliases-view.ts","../src/api/handlers.ts","../src/remote-access.ts","../src/live-scan.ts","../src/agent-operation-scheduler.ts","../src/live-session-index.ts","../src/search-index-job-runner.ts","../src/errors.ts","../src/pending-search-index-jobs.ts","../src/scan-status-model.ts","../src/agent-sync-engine.ts","../src/session-watcher.ts","../src/worker-runner.ts","../src/output.ts","../src/version.ts","../src/session-index-output.ts","../src/runtime-plan.ts","../src/ports.ts","../src/pricing-refresh.ts"],"sourcesContent":["import \"./diagnostics-bridge.js\";\nimport { defineCommand, runMain } from \"citty\";\nimport { createServer, getServerStartupErrorMessage } from \"./server.js\";\nimport { LiveScanStore } from \"./live-scan.js\";\nimport { printScanResults } from \"./output.js\";\nimport { VERSION } from \"./version.js\";\nimport { appLogger } from \"./logging.js\";\nimport { buildSessionIndexOutput } from \"./session-index-output.js\";\nimport {\n isLoopbackHostname,\n resolveRemoteTransport,\n type RemoteTransport,\n} from \"./remote-access.js\";\nimport {\n buildCliRuntimePlan,\n parseSessionUri,\n redactStartupUrl,\n resolveStartupUrl,\n} from \"./runtime-plan.js\";\nimport {\n DEFAULT_PORT,\n DEFAULT_PORT_FALLBACK_ATTEMPTS,\n hasExplicitPortArg,\n parsePort,\n} from \"./ports.js\";\nimport { createRegisteredAgents, perf } from \"@codesesh/core\";\nimport { startPricingRefresh } from \"./pricing-refresh.js\";\n\nconst main = defineCommand({\n meta: {\n name: \"codesesh\",\n description: \"Discover, aggregate, and visualize AI coding agent sessions\",\n version: VERSION,\n },\n args: {\n port: {\n type: \"string\",\n alias: \"p\",\n description: \"HTTP server port\",\n default: String(DEFAULT_PORT),\n },\n host: {\n type: \"string\",\n description: \"HTTP server bind address (default 127.0.0.1, local access only)\",\n default: \"127.0.0.1\",\n },\n \"remote-access\": {\n type: \"boolean\",\n description: \"Allow authenticated access when binding to a non-loopback address\",\n default: false,\n },\n \"tls-cert\": {\n type: \"string\",\n description: \"Path to a TLS certificate; serve remote access over HTTPS\",\n },\n \"tls-key\": {\n type: \"string\",\n description: \"Path to the TLS private key matching --tls-cert\",\n },\n \"trust-proxy\": {\n type: \"boolean\",\n description: \"A reverse proxy in front of CodeSesh terminates TLS\",\n default: false,\n },\n agent: {\n type: \"string\",\n alias: \"a\",\n description: \"Filter to specific agent(s), comma-separated\",\n },\n days: {\n type: \"string\",\n alias: \"d\",\n description: \"Only include sessions active in the last N days (0 = all time)\",\n default: \"7\",\n },\n cwd: {\n type: \"string\",\n description: \"Filter to sessions from a specific project directory (use '.' for current dir)\",\n },\n from: {\n type: \"string\",\n description: \"Sessions active after this date, YYYY-MM-DD (overrides --days)\",\n },\n to: {\n type: \"string\",\n description: \"Sessions active before this date (YYYY-MM-DD)\",\n },\n session: {\n type: \"string\",\n alias: \"s\",\n description: \"Directly open a specific session (agent://session-id)\",\n },\n json: {\n type: \"boolean\",\n alias: \"j\",\n description: \"Output session index as JSON to stdout (no server)\",\n default: false,\n },\n noOpen: {\n type: \"boolean\",\n description: \"Don't auto-open browser\",\n default: false,\n },\n trace: {\n type: \"boolean\",\n description: \"Show performance trace logs\",\n default: false,\n },\n cache: {\n type: \"boolean\",\n description: \"Use cached scan results if available\",\n default: true,\n },\n \"clear-cache\": {\n type: \"boolean\",\n description: \"Clear scan cache before starting\",\n default: false,\n },\n },\n async run({ args }) {\n const startedAt = performance.now();\n const port = parsePort(args.port as string | undefined);\n const explicitPort = hasExplicitPortArg(process.argv.slice(2));\n const noOpen = args.noOpen as boolean;\n const jsonOnly = args.json as boolean;\n const trace = args.trace as boolean;\n const useCache = args.cache as boolean;\n const clearCache = args[\"clear-cache\"] as boolean;\n const hostname = args.host as string;\n const remoteAccess = args[\"remote-access\"] as boolean;\n\n if (!isLoopbackHostname(hostname) && !remoteAccess) {\n console.error(\n `Refusing to expose CodeSesh on ${hostname} without authentication. Add --remote-access to continue.`,\n );\n process.exit(1);\n }\n\n let transport: RemoteTransport;\n try {\n transport = resolveRemoteTransport({\n hostname,\n tlsCertPath: args[\"tls-cert\"] as string | undefined,\n tlsKeyPath: args[\"tls-key\"] as string | undefined,\n trustProxy: args[\"trust-proxy\"] as boolean,\n });\n } catch (error) {\n console.error(error instanceof Error ? error.message : String(error));\n process.exit(1);\n }\n\n if (trace) {\n perf.enable();\n }\n\n appLogger.info(\"cli.start\", {\n version: VERSION,\n argv: process.argv.slice(2),\n port,\n json: jsonOnly,\n no_open: noOpen,\n cache: useCache,\n log_path: appLogger.getLogPath(),\n });\n\n if (clearCache) {\n const { clearCache: clear } = await import(\"@codesesh/core\");\n clear();\n appLogger.info(\"cache.clear\");\n console.log(\"Cache cleared.\");\n }\n\n // Owns the refresh: bounded, cancellable, and published only between scans\n // so a scan never spans two price generations.\n const pricingRefresh = startPricingRefresh();\n\n // Parse session URI if provided\n let targetSession: { agent: string; sessionId: string } | null = null;\n if (args.session) {\n targetSession = parseSessionUri(args.session as string);\n if (!targetSession) {\n console.error(`Invalid session format: ${args.session}. Expected: agent://session-id`);\n process.exit(1);\n }\n }\n\n const { listWindow, scanOptions, startupScanOptions } = buildCliRuntimePlan(\n {\n agent: args.agent as string | undefined,\n cwd: args.cwd as string | undefined,\n from: args.from as string | undefined,\n to: args.to as string | undefined,\n days: args.days as string | undefined,\n jsonOnly,\n targetSession,\n useCache,\n },\n { currentWorkingDirectory: process.cwd() },\n );\n const { from: listDefaultFrom, to: listDefaultTo, days: listDefaultDays } = listWindow;\n\n const store = new LiveScanStore({\n watchEnabled: !jsonOnly,\n scanOptions,\n startupScanOptions,\n deferInitialRefresh: !jsonOnly,\n });\n await store.initialize();\n const result = store.getSnapshot();\n appLogger.info(\"cli.scan_ready\", {\n duration_ms: Math.round(performance.now() - startedAt),\n sessions: result.sessions.length,\n agents: Object.fromEntries(\n Object.entries(result.byAgent).map(([key, value]) => [key, value.length]),\n ),\n startup_from: startupScanOptions.from,\n startup_to: startupScanOptions.to,\n });\n\n if (trace) {\n console.log(perf.getReport());\n }\n\n if (jsonOnly) {\n // Nothing will consume a later generation, so stop waiting for it.\n await pricingRefresh.cancel();\n const output = buildSessionIndexOutput(result, { from: listDefaultFrom, to: listDefaultTo });\n appLogger.info(\"cli.json_output\", {\n sessions: output.sessions.length,\n duration_ms: Math.round(performance.now() - startedAt),\n });\n console.log(JSON.stringify(output, null, 2));\n return;\n }\n\n // Print console output\n const agents = createRegisteredAgents();\n printScanResults(agents);\n\n // Start server\n let app: Awaited<ReturnType<typeof createServer>>;\n try {\n app = await createServer(port, store, {\n defaultSessionFrom: listDefaultFrom,\n defaultSessionTo: listDefaultTo,\n defaultSessionDays: listDefaultDays,\n portFallbackAttempts: explicitPort ? 1 : DEFAULT_PORT_FALLBACK_ATTEMPTS,\n hostname,\n remoteAccess,\n transport,\n });\n } catch (error) {\n console.error(getServerStartupErrorMessage(error, port));\n process.exit(1);\n }\n\n const { url } = app;\n if (!jsonOnly) {\n // The startup scan has finished and background scans have not begun.\n pricingRefresh.publish();\n store.startBackgroundRefresh();\n }\n let shuttingDown = false;\n const shutdown = async (signal: NodeJS.Signals) => {\n if (shuttingDown) return;\n shuttingDown = true;\n appLogger.info(\"cli.shutdown\", { signal });\n await pricingRefresh.cancel();\n await app.shutdown();\n process.exit(0);\n };\n process.once(\"SIGINT\", (signal) => {\n void shutdown(signal);\n });\n process.once(\"SIGTERM\", (signal) => {\n void shutdown(signal);\n });\n\n console.log(` ${url}`);\n console.log(\"\");\n appLogger.info(\"cli.ready\", {\n url: redactStartupUrl(url),\n duration_ms: Math.round(performance.now() - startedAt),\n log_path: appLogger.getLogPath(),\n });\n\n if (!noOpen) {\n const open = (await import(\"open\")).default;\n const targetUrl = resolveStartupUrl(url, targetSession);\n appLogger.info(\"browser.open\", { url: redactStartupUrl(targetUrl) });\n await open(targetUrl);\n }\n },\n});\n\nif (process.argv.slice(2).includes(\"-v\")) {\n console.log(VERSION);\n process.exit(0);\n}\n\nrunMain(main);\n","import { Hono } from \"hono\";\nimport { bodyLimit } from \"hono/body-limit\";\nimport { compress } from \"hono/compress\";\nimport { serve } from \"@hono/node-server\";\nimport type { ServerType } from \"@hono/node-server\";\nimport { serveStatic } from \"@hono/node-server/serve-static\";\nimport { existsSync } from \"node:fs\";\nimport { createServer as createHttpsServer } from \"node:https\";\nimport type { AddressInfo } from \"node:net\";\nimport { resolve, dirname } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport type { ScanResultSource } from \"./api/handlers.js\";\nimport { createApiRoutes, type ApiRouteOptions } from \"./api/routes.js\";\nimport { appLogger } from \"./logging.js\";\nimport {\n createRemoteAccessToken,\n isLoopbackHostname,\n REMOTE_ACCESS_QUERY_PARAM,\n remoteAccessAuth,\n requireProxyTls,\n type RemoteTransport,\n} from \"./remote-access.js\";\nimport type { ScanEventSource } from \"./scan-source.js\";\n\nconst MAX_API_REQUEST_BYTES = 1024 * 1024;\n\nexport interface CreateServerOptions {\n defaultSessionFrom?: number;\n defaultSessionTo?: number;\n defaultSessionDays?: number;\n portFallbackAttempts?: number;\n hostname?: string;\n remoteAccess?: boolean;\n remoteAccessToken?: string;\n /** How the listener is protected; defaults to plaintext for a non-loopback host. */\n transport?: RemoteTransport;\n /** Overrides the auto-detected web build directory; used to pin the static root in tests. */\n webDistPath?: string;\n}\n\nfunction findWebDistPath(): string | null {\n const __dirname = dirname(fileURLToPath(import.meta.url));\n\n // Priority 1: Packaged web dist (copied during build)\n const packagedPath = resolve(__dirname, \"web\");\n if (existsSync(packagedPath)) {\n return packagedPath;\n }\n\n // Priority 2: Development path (monorepo)\n const devPath = resolve(__dirname, \"../../../apps/web/dist\");\n if (existsSync(devPath)) {\n return devPath;\n }\n\n return null;\n}\n\nfunction waitForListening(server: ServerType): Promise<void> {\n return new Promise((resolve, reject) => {\n const handleListening = () => {\n server.off(\"error\", handleError);\n resolve();\n };\n const handleError = (error: Error) => {\n server.off(\"listening\", handleListening);\n reject(error);\n };\n\n server.once(\"listening\", handleListening);\n server.once(\"error\", handleError);\n });\n}\n\nexport function getServerStartupErrorMessage(error: unknown, port: number): string {\n if (\n typeof error === \"object\" &&\n error !== null &&\n \"code\" in error &&\n error.code === \"EADDRINUSE\"\n ) {\n return `Port ${port} 已被占用,请关闭现有 CodeSesh 进程或改用 --port 指定其他端口。`;\n }\n\n return error instanceof Error ? error.message : `启动服务器失败: ${String(error)}`;\n}\n\nfunction isAddressInUse(error: unknown): boolean {\n return (\n typeof error === \"object\" && error !== null && \"code\" in error && error.code === \"EADDRINUSE\"\n );\n}\n\nfunction getListeningPort(server: ServerType, fallback: number): number {\n const address = server.address();\n return typeof address === \"object\" && address !== null ? (address as AddressInfo).port : fallback;\n}\n\nexport async function createServer(\n port: number,\n store: ScanResultSource & ScanEventSource & { shutdown(): Promise<void> },\n options: CreateServerOptions = {},\n): Promise<{ url: string; shutdown: () => Promise<void> }> {\n const app = new Hono();\n const hostname = options.hostname ?? \"127.0.0.1\";\n const isLoopback = isLoopbackHostname(hostname);\n const transport: RemoteTransport =\n options.transport ?? (isLoopback ? { kind: \"loopback\" } : { kind: \"plaintext\" });\n const remoteAccessToken = !isLoopback\n ? (options.remoteAccessToken ?? (options.remoteAccess ? createRemoteAccessToken() : null))\n : null;\n\n if (!isLoopback && !remoteAccessToken) {\n throw new Error(\n `Refusing to expose CodeSesh on ${hostname} without authentication. Add --remote-access to continue.`,\n );\n }\n\n app.use(\"*\", async (c, next) => {\n const startedAt = performance.now();\n let thrown: unknown;\n\n try {\n await next();\n } catch (error) {\n thrown = error;\n throw error;\n } finally {\n const url = new URL(c.req.url);\n appLogger.info(\"http.request\", {\n method: c.req.method,\n path: url.pathname,\n query_keys: [...url.searchParams.keys()].toSorted(),\n status: c.res.status,\n duration_ms: Math.round(performance.now() - startedAt),\n error: thrown instanceof Error ? thrown.message : undefined,\n });\n }\n });\n\n // Ordered before authentication: a request that bypassed the proxy must be\n // refused outright, not given a chance to present a token in the clear.\n if (transport.kind === \"trusted-proxy\") {\n app.use(\"/api/*\", requireProxyTls());\n }\n if (remoteAccessToken) {\n app.use(\"/api/*\", remoteAccessAuth(remoteAccessToken));\n }\n app.use(\n \"/api/*\",\n bodyLimit({\n maxSize: MAX_API_REQUEST_BYTES,\n onError: (c) => c.json({ error: \"Request body too large\" }, 413),\n }),\n );\n // Hono's default filter already excludes text/event-stream, so this does not\n // interfere with the /api/events SSE stream.\n app.use(\"/api/*\", compress());\n\n // API routes\n const routeOptions: ApiRouteOptions = {\n defaultSessionFrom: options.defaultSessionFrom,\n defaultSessionTo: options.defaultSessionTo,\n defaultSessionDays: options.defaultSessionDays,\n };\n app.route(\"/api\", createApiRoutes(store, store, routeOptions));\n\n // Serve static files from web dist (if available)\n const webDistPath = options.webDistPath ?? findWebDistPath();\n\n if (webDistPath) {\n app.use(\"/*\", serveStatic({ root: webDistPath }));\n app.get(\"/*\", serveStatic({ root: webDistPath, path: \"index.html\" }));\n }\n\n const attempts = Math.max(1, options.portFallbackAttempts ?? 1);\n let server: ServerType | null = null;\n let actualPort = port;\n\n for (let offset = 0; offset < attempts; offset += 1) {\n const candidatePort = port + offset;\n server = serve({\n fetch: app.fetch,\n port: candidatePort,\n hostname,\n ...(transport.kind === \"tls\"\n ? {\n createServer: createHttpsServer,\n serverOptions: { cert: transport.cert, key: transport.key },\n }\n : {}),\n });\n\n try {\n await waitForListening(server);\n actualPort = getListeningPort(server, candidatePort);\n break;\n } catch (error) {\n appLogger.error(\"server.listen.error\", { port: candidatePort, error });\n server.close();\n\n if (isAddressInUse(error) && offset < attempts - 1) {\n continue;\n }\n\n await store.shutdown();\n\n if (isAddressInUse(error) && attempts > 1) {\n throw new Error(\n `端口 ${port}-${port + attempts - 1} 均已被占用,请关闭现有进程或改用 --port 指定其他端口。`,\n );\n }\n\n throw new Error(getServerStartupErrorMessage(error, candidatePort));\n }\n }\n\n // A trusted proxy publishes its own https origin, so only direct TLS changes\n // the scheme CodeSesh prints for itself.\n const scheme = transport.kind === \"tls\" ? \"https\" : \"http\";\n const baseUrl = isLoopback\n ? `${scheme}://localhost:${actualPort}`\n : `${scheme}://${hostname}:${actualPort}`;\n const url = remoteAccessToken\n ? `${baseUrl}/?${REMOTE_ACCESS_QUERY_PARAM}=${encodeURIComponent(remoteAccessToken)}`\n : baseUrl;\n appLogger.info(\"server.listen\", {\n port: actualPort,\n requested_port: port,\n hostname,\n remote_access: Boolean(remoteAccessToken),\n transport: transport.kind,\n });\n\n if (!isLoopback) {\n appLogger.warn(\"server.listen.remote_access\", {\n hostname,\n port: actualPort,\n transport: transport.kind,\n });\n console.warn(`\\n⚠ 远程访问已启用。任何持有启动 URL 的人都可以读取你的 AI 会话记录。\\n`);\n if (transport.kind === \"plaintext\") {\n appLogger.warn(\"server.listen.plaintext\", { hostname, port: actualPort });\n console.warn(\n `⚠ 传输未加密。访问令牌与完整会话内容以明文经过网络,URL 中的令牌还可能写入代理访问日志。\\n` +\n ` 使用 --tls-cert/--tls-key 直接启用 TLS,或在受信反向代理后使用 --trust-proxy。\\n`,\n );\n }\n }\n\n return {\n url,\n shutdown: async () => {\n appLogger.info(\"server.shutdown\", { port: actualPort });\n await new Promise<void>((resolve) => {\n if (!server) {\n resolve();\n return;\n }\n server.close(() => resolve());\n });\n await store.shutdown();\n },\n };\n}\n","import { Hono } from \"hono\";\nimport {\n handleGetAgents,\n handleGetBookmarks,\n handleGetConfig,\n handleGetDashboard,\n handleGetFileActivity,\n handleGetProjects,\n handleGetScanStatus,\n handleDeleteBookmark,\n handleDeleteSessionAlias,\n handleImportBookmarks,\n handlePostClientLog,\n handleSearchSessions,\n handleGetSessions,\n handleGetSessionData,\n handlePutBookmark,\n handlePutSessionAlias,\n type ScanResultSource,\n type SessionListDefaults,\n} from \"./handlers.js\";\nimport type { ScanEventSource } from \"../scan-source.js\";\n\nexport interface ApiRouteOptions {\n defaultSessionFrom?: number;\n defaultSessionTo?: number;\n defaultSessionDays?: number;\n}\n\nfunction createSseResponse(eventSource: ScanEventSource, signal: AbortSignal): Response {\n const encoder = new TextEncoder();\n let cancelStream = () => {};\n\n return new Response(\n new ReadableStream({\n start(controller) {\n let isClosed = false;\n const write = (event: string, data: unknown) => {\n if (isClosed) return;\n controller.enqueue(encoder.encode(`event: ${event}\\n`));\n controller.enqueue(encoder.encode(`data: ${JSON.stringify(data)}\\n\\n`));\n };\n\n write(\"connected\", { timestamp: Date.now() });\n write(\"scan-status\", eventSource.getScanStatus());\n\n const unsubscribeSessions = eventSource.subscribe((event) => {\n write(event.type, event);\n });\n const unsubscribeScanStatus = eventSource.subscribeScanStatus((event) => {\n write(event.type, event);\n });\n\n const heartbeat = setInterval(() => {\n if (!isClosed) controller.enqueue(encoder.encode(\": keepalive\\n\\n\"));\n }, 15000);\n\n const cleanup = () => {\n if (isClosed) return false;\n isClosed = true;\n clearInterval(heartbeat);\n unsubscribeSessions();\n unsubscribeScanStatus();\n signal.removeEventListener(\"abort\", abortStream);\n return true;\n };\n const abortStream = () => {\n if (cleanup()) controller.close();\n };\n cancelStream = () => {\n cleanup();\n };\n\n if (signal.aborted) abortStream();\n else signal.addEventListener(\"abort\", abortStream, { once: true });\n },\n cancel() {\n cancelStream();\n },\n }),\n {\n headers: {\n \"Cache-Control\": \"no-cache\",\n Connection: \"keep-alive\",\n \"Content-Type\": \"text/event-stream\",\n },\n },\n );\n}\n\nexport function createApiRoutes(\n scanSource: ScanResultSource,\n eventSource?: ScanEventSource,\n options: ApiRouteOptions = {},\n): Hono {\n const api = new Hono();\n const listDefaults: SessionListDefaults = {\n from: options.defaultSessionFrom,\n to: options.defaultSessionTo,\n days: options.defaultSessionDays,\n };\n\n api.get(\"/config\", (c) => handleGetConfig(c, listDefaults));\n if (eventSource) {\n api.get(\"/status\", (c) => handleGetScanStatus(c, eventSource));\n }\n api.get(\"/agents\", (c) => handleGetAgents(c, scanSource, listDefaults));\n api.get(\"/projects\", (c) => handleGetProjects(c, scanSource, listDefaults));\n api.get(\"/sessions\", (c) => handleGetSessions(c, scanSource, listDefaults));\n api.get(\"/search\", (c) => handleSearchSessions(c, scanSource, listDefaults));\n api.get(\"/file-activity\", (c) => handleGetFileActivity(c, listDefaults));\n api.get(\"/sessions/:agent/:id\", (c) => handleGetSessionData(c, scanSource));\n api.get(\"/dashboard\", (c) => handleGetDashboard(c, scanSource, listDefaults));\n api.get(\"/bookmarks\", (c) => handleGetBookmarks(c));\n api.put(\"/bookmarks\", (c) => handlePutBookmark(c));\n api.post(\"/bookmarks/import\", (c) => handleImportBookmarks(c));\n api.delete(\"/bookmarks/:agent/:id\", (c) => handleDeleteBookmark(c));\n api.put(\"/session-aliases/:agent/:id\", (c) => handlePutSessionAlias(c));\n api.delete(\"/session-aliases/:agent/:id\", (c) => handleDeleteSessionAlias(c));\n api.post(\"/logs\", (c) => handlePostClientLog(c));\n if (eventSource) {\n api.get(\"/events\", (c) => createSseResponse(eventSource, c.req.raw.signal));\n }\n\n return api;\n}\n","import { addCalendarDays, countCalendarDays, startOfCalendarDay } from \"@codesesh/core/contract\";\n\n/** Rolling duration for CLI --days, which is a span of hours, not a calendar range. */\nconst ROLLING_DAY_MS = 24 * 60 * 60 * 1000;\nconst DEFAULT_DASHBOARD_DAYS = 30;\n\nexport interface TimeWindow {\n from?: number;\n to?: number;\n /** Original relative window value used by the UI label. */\n days?: number;\n}\n\ninterface RawTimeWindow {\n from?: string;\n to?: string;\n days?: string;\n}\n\ninterface CliTimeWindowRequest extends RawTimeWindow {\n mode: \"cli\";\n now?: number;\n}\n\ninterface DashboardTimeWindowRequest {\n mode: \"dashboard\";\n query: RawTimeWindow;\n defaults?: TimeWindow;\n now?: number;\n}\n\ninterface DashboardTimeWindow extends TimeWindow {\n to: number;\n}\n\ntype TimeWindowRequest = CliTimeWindowRequest | DashboardTimeWindowRequest;\n\nexport function resolveTimeWindow(request: CliTimeWindowRequest): TimeWindow;\nexport function resolveTimeWindow(request: DashboardTimeWindowRequest): DashboardTimeWindow;\nexport function resolveTimeWindow(request: TimeWindowRequest): TimeWindow {\n return request.mode === \"cli\" ? resolveCliWindow(request) : resolveDashboardWindow(request);\n}\n\nfunction resolveCliWindow(request: CliTimeWindowRequest): TimeWindow {\n const now = request.now ?? Date.now();\n const from = parseRequiredDate(request.from);\n const to = parseRequiredDate(request.to);\n if (from != null) return { from, to };\n\n const days = parseDays(request.days);\n if (days === 0) return { to, days };\n if (days == null || days < 0) return { to };\n\n const rollingFrom = now - days * ROLLING_DAY_MS;\n return Number.isFinite(rollingFrom) ? { from: rollingFrom, to, days } : { to };\n}\n\nfunction resolveDashboardWindow(request: DashboardTimeWindowRequest): DashboardTimeWindow {\n const now = request.now ?? Date.now();\n const defaults = request.defaults ?? {};\n const to = parseOptionalDate(request.query.to) ?? defaults.to ?? now;\n const hasQueryDays = Boolean(request.query.days?.trim());\n const parsedDays = hasQueryDays ? parseDays(request.query.days) : undefined;\n let days = parsedDays != null && parsedDays > 0 ? parsedDays : defaults.days;\n\n const queryFrom = parseOptionalDate(request.query.from);\n if (queryFrom != null) {\n days ??= countCalendarDays(queryFrom, to);\n return { from: queryFrom, to, days };\n }\n\n if (parsedDays === 0 || (!hasQueryDays && defaults.days === 0)) {\n return { to, days: 0 };\n }\n\n if (defaults.from != null) {\n days ??= countCalendarDays(defaults.from, to);\n return { from: defaults.from, to, days };\n }\n\n const resolvedDays = days != null && days > 0 ? days : DEFAULT_DASHBOARD_DAYS;\n return {\n from: addCalendarDays(startOfCalendarDay(to), -(resolvedDays - 1)),\n to,\n days: resolvedDays,\n };\n}\n\nfunction parseRequiredDate(value: string | undefined): number | undefined {\n if (!value) return undefined;\n const timestamp = new Date(value).getTime();\n if (Number.isNaN(timestamp)) throw new Error(`Invalid date: ${value}`);\n return timestamp;\n}\n\nfunction parseOptionalDate(value: string | undefined): number | undefined {\n if (value == null) return undefined;\n const timestamp = new Date(value).getTime();\n return Number.isNaN(timestamp) ? undefined : timestamp;\n}\n\nfunction parseDays(value: string | undefined): number | undefined {\n if (value == null) return undefined;\n const days = Number.parseInt(value, 10);\n return Number.isSafeInteger(days) && Number.isSafeInteger(days * ROLLING_DAY_MS)\n ? days\n : undefined;\n}\n","/**\n * Request-parameter parsing for the HTTP API. Everything here turns raw query\n * strings into the option objects the domain layer expects; no domain logic,\n * no storage access.\n */\nimport type { Context } from \"hono\";\nimport type { SessionHead, SmartTag } from \"@codesesh/core\";\nimport {\n filterSessionTreeByActivityWindow,\n isProjectIdentityKind,\n type FileActivityKind,\n type ProjectIdentityRef,\n type SearchOptions,\n} from \"@codesesh/core\";\nimport type { TimeWindow } from \"../time-window-resolution.js\";\n\nexport type SessionListDefaults = TimeWindow;\n\nconst SMART_TAGS: readonly string[] = [\n \"bugfix\",\n \"refactoring\",\n \"feature-dev\",\n \"testing\",\n \"docs\",\n \"git-ops\",\n \"build-deploy\",\n \"exploration\",\n \"planning\",\n];\n\nconst SEARCH_LIMIT_MAX = 100;\nconst SEARCH_LIMIT_DEFAULT = 50;\n\nexport function searchParams(c: Context): URLSearchParams {\n return new URL(c.req.url ?? \"http://localhost/\", \"http://localhost/\").searchParams;\n}\n\n/** Collects repeated and comma-separated values across several parameter names. */\nexport function queryValues(params: URLSearchParams, ...names: string[]): string[] {\n return names.flatMap((name) =>\n params\n .getAll(name)\n .flatMap((value) => value.split(\",\"))\n .map((value) => value.trim())\n .filter(Boolean),\n );\n}\n\nexport function optionalQueryValue(value: string | undefined): string | undefined {\n const normalized = value?.trim();\n return normalized ? normalized : undefined;\n}\n\nexport function parseDateParam(\n value: string | undefined,\n fallback: number | undefined,\n): number | undefined {\n if (value == null) return fallback;\n const ts = new Date(value).getTime();\n return Number.isNaN(ts) ? fallback : ts;\n}\n\nexport function parseNumberParam(value: string | undefined): number | undefined {\n if (value == null || !value.trim()) return undefined;\n const number = Number(value);\n return Number.isFinite(number) ? number : undefined;\n}\n\nexport function parseSmartTags(values: string[]): SmartTag[] | undefined {\n const tags = values\n .map((value) => value.toLowerCase())\n .filter((value): value is SmartTag => SMART_TAGS.includes(value));\n return tags.length > 0 ? [...new Set(tags)] : undefined;\n}\n\nexport function parseFileActivityKind(value: string | undefined): FileActivityKind | undefined {\n if (value === \"read\" || value === \"edit\" || value === \"write\" || value === \"delete\") {\n return value;\n }\n return undefined;\n}\n\n/**\n * Returns the identity when both halves are present and valid, `undefined` when\n * neither is supplied, and `null` when the pair is incomplete or malformed —\n * callers turn that `null` into a 400.\n */\nexport function parseProjectIdentityFilter(\n kindValue: string | undefined,\n keyValue: string | undefined,\n): ProjectIdentityRef | null | undefined {\n const kind = optionalQueryValue(kindValue);\n const key = optionalQueryValue(keyValue);\n if (!kind && !key) return undefined;\n if (!kind || !key || !isProjectIdentityKind(kind)) return null;\n return { kind, key };\n}\n\nexport function parseSearchOptions(\n c: Context,\n defaults: SessionListDefaults,\n projectIdentity?: ProjectIdentityRef,\n): SearchOptions {\n const params = searchParams(c);\n const limitValue = parseNumberParam(params.get(\"limit\") ?? undefined);\n return {\n agent: optionalQueryValue(params.get(\"agent\") ?? undefined),\n project: optionalQueryValue(params.get(\"project\") ?? undefined),\n projectKind: projectIdentity?.kind,\n projectKey: projectIdentity?.key,\n cwd: optionalQueryValue(params.get(\"cwd\") ?? undefined),\n tags: parseSmartTags(queryValues(params, \"tag\", \"tags\", \"signal\")),\n tools: queryValues(params, \"tool\", \"tools\").map((tool) => tool.toLowerCase()),\n file: optionalQueryValue(params.get(\"file\") ?? params.get(\"path\") ?? undefined),\n fileKind: parseFileActivityKind(\n optionalQueryValue(params.get(\"fileKind\") ?? params.get(\"fileActivity\") ?? undefined),\n ),\n costMin: parseNumberParam(params.get(\"costMin\") ?? undefined),\n costMax: parseNumberParam(params.get(\"costMax\") ?? undefined),\n from: parseDateParam(params.get(\"from\") ?? undefined, defaults.from),\n to: parseDateParam(params.get(\"to\") ?? undefined, defaults.to),\n limit:\n limitValue && limitValue > 0 ? Math.min(limitValue, SEARCH_LIMIT_MAX) : SEARCH_LIMIT_DEFAULT,\n };\n}\n\nexport function filterSessionsByActivityWindow(\n sessions: SessionHead[],\n from: number | undefined,\n to: number | undefined,\n): SessionHead[] {\n return filterSessionTreeByActivityWindow(sessions, from, to);\n}\n","/**\n * Session aliases as a read model for the HTTP layer: load the user's local\n * renames once, then decorate outgoing records with `display_title`.\n */\nimport type { BookmarkRecord, SessionAlias, SessionHead } from \"@codesesh/core\";\nimport type { SearchResult, SessionReference } from \"@codesesh/core/contract\";\nimport {\n filterSessionSearchCandidates,\n getSessionActivityTime,\n listSessionAliases,\n mergeSearchQueryOptions,\n StateStorageUnavailableError,\n type FileActivityResult,\n type LiveSnapshot,\n type SearchOptions,\n} from \"@codesesh/core\";\nimport { appLogger } from \"../logging.js\";\n\n/** Anything the API returns that can carry a locally-renamed title. */\ntype Titled = { id: string; title: string; display_title?: string };\n\nexport interface AliasView {\n readonly size: number;\n get(reference: SessionReference): string | undefined;\n /** Returns the record unchanged when no alias applies, so callers can pass through freely. */\n decorate<T extends Titled>(record: T, reference: SessionReference): T;\n entries(): IterableIterator<SessionAlias>;\n}\n\nfunction aliasKey(reference: SessionReference): string {\n return `${reference.agentName.toLowerCase()}\\0${reference.sessionId}`;\n}\n\nfunction loadAliasMap(): Map<string, SessionAlias> {\n try {\n return new Map(listSessionAliases().map((alias) => [aliasKey(alias.reference), alias]));\n } catch (error) {\n if (!(error instanceof StateStorageUnavailableError)) {\n appLogger.warn(\"api.session_aliases.load_failed\", {\n error: error instanceof Error ? error.message : String(error),\n });\n }\n return new Map();\n }\n}\n\nfunction buildAliasView(): AliasView {\n const aliases = loadAliasMap();\n return {\n size: aliases.size,\n get: (reference) => aliases.get(aliasKey(reference))?.alias,\n decorate(record, reference) {\n const alias = aliases.get(aliasKey(reference))?.alias;\n return alias ? { ...record, display_title: alias } : record;\n },\n entries: () => aliases.values(),\n };\n}\n\n/**\n * Aliases change only through this process's own PUT/DELETE handlers, so the\n * read model is built once and reused until one of them invalidates it. Six read\n * handlers call this per request; without the cache each one re-queries the whole\n * table. A storage failure is cached too — it does not heal between requests, and\n * invalidateAliasView() is what lets a recovered store be retried.\n */\nlet cachedView: AliasView | null = null;\n\nexport function loadAliasView(): AliasView {\n return (cachedView ??= buildAliasView());\n}\n\nexport function invalidateAliasView(): void {\n cachedView = null;\n}\n\nexport function decorateBookmark(bookmark: BookmarkRecord, aliases: AliasView): BookmarkRecord {\n return {\n ...bookmark,\n session: aliases.decorate(bookmark.session, bookmark.reference),\n };\n}\n\nexport function decorateFileActivity(\n activity: FileActivityResult,\n aliases: AliasView,\n): FileActivityResult {\n return {\n ...activity,\n session: aliases.decorate(activity.session, activity.reference),\n };\n}\n\n/**\n * Aliases are stored outside the search index, so a query matching only a local\n * rename has to be resolved here. Hits still have to satisfy the same\n * time-window / project / agent filters as the main search, otherwise an aliased\n * session could surface outside its search scope.\n */\nexport function findAliasSearchResults(\n query: string,\n options: SearchOptions,\n scanResult: LiveSnapshot,\n aliases: AliasView,\n): SearchResult[] {\n const search = mergeSearchQueryOptions(query, options);\n const needle = search.text.trim().toLowerCase();\n if (!needle || aliases.size === 0) return [];\n\n const sessionsByAgent = new Map<string, Map<string, SessionHead>>();\n const lookupSession = (agentName: string, sessionId: string): SessionHead | undefined => {\n let byId = sessionsByAgent.get(agentName);\n if (!byId) {\n byId = new Map((scanResult.byAgent[agentName] ?? []).map((item) => [item.id, item]));\n sessionsByAgent.set(agentName, byId);\n }\n return byId.get(sessionId);\n };\n\n const results: SearchResult[] = [];\n for (const alias of aliases.entries()) {\n if (!alias.alias.toLowerCase().includes(needle)) continue;\n const { agentName, sessionId } = alias.reference;\n const session = lookupSession(agentName, sessionId);\n if (!session) continue;\n results.push({\n reference: alias.reference,\n session: aliases.decorate(session, alias.reference),\n snippet: `Alias · ${session.directory}`,\n matchType: \"title\",\n });\n }\n\n return filterSessionSearchCandidates(results, search.options).sort(\n (a, b) => getSessionActivityTime(b.session) - getSessionActivityTime(a.session),\n );\n}\n","import type { Context } from \"hono\";\nimport type {\n BookmarkRecord,\n LiveSnapshot,\n SessionDetail,\n SessionHead,\n SmartTag,\n} from \"@codesesh/core\";\nimport {\n addCalendarDays,\n countCalendarDays,\n formatSessionReference,\n getSessionAgentKey,\n getSessionRouteKey,\n normalizeSessionReference,\n type AppConfig,\n type ScanStatusEvent,\n type SearchResult,\n type SessionReference,\n startOfCalendarDay,\n} from \"@codesesh/core/contract\";\nimport {\n SessionAliasValidationError,\n StateStorageUnavailableError,\n attachProjectMetrics,\n createProjectScopeMatcher,\n deleteBookmark,\n getAgentInfoMap,\n executeSessionSearch,\n importBookmarks,\n listFileActivity,\n listCachedProjectGroups,\n listBookmarks,\n listModelCostDistribution,\n deleteSessionAlias,\n materializeSessionDetailResponse,\n upsertSessionAlias,\n upsertBookmark,\n matchesProjectScope as sessionMatchesProjectScope,\n matchesProjectIdentity,\n buildDashboard,\n type DashboardData,\n type DashboardScope,\n} from \"@codesesh/core\";\nimport { appLogger } from \"../logging.js\";\nimport { resolveTimeWindow } from \"../time-window-resolution.js\";\nimport {\n filterSessionsByActivityWindow,\n parseDateParam,\n parseFileActivityKind,\n parseProjectIdentityFilter,\n parseSearchOptions,\n optionalQueryValue,\n type SessionListDefaults,\n} from \"./query-params.js\";\nimport {\n decorateBookmark,\n decorateFileActivity,\n findAliasSearchResults,\n invalidateAliasView,\n loadAliasView,\n type AliasView,\n} from \"./session-aliases-view.js\";\n\nexport type { SessionListDefaults };\n\nexport interface ScanResultSource {\n getSnapshot(): LiveSnapshot;\n}\n\nexport interface ScanStatusSource {\n getScanStatus(): ScanStatusEvent;\n}\n\ninterface SnapshotAggregationCache {\n sessions: SessionHead[];\n values: Map<string, unknown>;\n}\n\nconst SNAPSHOT_AGGREGATION_CACHE_LIMIT = 64;\nconst snapshotAggregationCaches = new WeakMap<ScanResultSource, SnapshotAggregationCache>();\n\n/**\n * LiveScanStore replaces its canonical sessions array whenever the snapshot\n * changes, so that existing reference is the snapshot version.\n */\nfunction getSnapshotAggregation<T>(\n source: ScanResultSource,\n sessions: SessionHead[],\n key: readonly unknown[],\n build: () => T,\n): T {\n let cache = snapshotAggregationCaches.get(source);\n if (!cache || cache.sessions !== sessions) {\n cache = { sessions, values: new Map() };\n snapshotAggregationCaches.set(source, cache);\n }\n\n const cacheKey = JSON.stringify(key);\n if (cache.values.has(cacheKey)) return cache.values.get(cacheKey) as T;\n\n const value = build();\n if (cache.values.size >= SNAPSHOT_AGGREGATION_CACHE_LIMIT) {\n const oldestKey = cache.values.keys().next().value;\n if (oldestKey != null) cache.values.delete(oldestKey);\n }\n cache.values.set(cacheKey, value);\n return value;\n}\n\ninterface ClientLogPayload {\n event?: unknown;\n data?: unknown;\n}\n\ninterface SessionAliasPayload {\n alias?: unknown;\n}\n\nfunction withStorageErrors<TResult, TFallback>(\n handler: () => TResult,\n onUnavailable: () => TFallback,\n): TResult | TFallback {\n try {\n return handler();\n } catch (error) {\n if (error instanceof StateStorageUnavailableError) {\n return onUnavailable();\n }\n throw error;\n }\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null;\n}\n\nfunction isSessionStats(value: unknown): value is SessionHead[\"stats\"] {\n if (!isRecord(value)) return false;\n return (\n typeof value.message_count === \"number\" &&\n typeof value.total_input_tokens === \"number\" &&\n typeof value.total_output_tokens === \"number\" &&\n typeof value.total_cost === \"number\" &&\n (value.total_tokens == null || typeof value.total_tokens === \"number\")\n );\n}\n\ntype BookmarkInput = Omit<BookmarkRecord, \"bookmarkedAt\">;\n\nfunction parseBookmarkSession(\n value: unknown,\n reference: SessionReference,\n): BookmarkInput[\"session\"] | null {\n if (!isRecord(value)) return null;\n if (\n value.id !== reference.sessionId ||\n typeof value.slug !== \"string\" ||\n typeof value.title !== \"string\" ||\n typeof value.directory !== \"string\" ||\n typeof value.time_created !== \"number\" ||\n (value.time_updated != null && typeof value.time_updated !== \"number\") ||\n !isSessionStats(value.stats)\n ) {\n return null;\n }\n\n return {\n id: reference.sessionId,\n slug: formatSessionReference(reference),\n title: value.title,\n directory: value.directory,\n time_created: value.time_created,\n time_updated: value.time_updated ?? undefined,\n stats: value.stats,\n };\n}\n\nfunction parseSessionReferencePayload(value: unknown): SessionReference | null {\n if (\n !isRecord(value) ||\n typeof value.agentName !== \"string\" ||\n typeof value.sessionId !== \"string\" ||\n !value.agentName.trim() ||\n !value.sessionId\n ) {\n return null;\n }\n return normalizeSessionReference({\n agentName: value.agentName.trim().toLowerCase(),\n sessionId: value.sessionId,\n });\n}\n\nfunction parseBookmarkPayload(value: unknown): BookmarkInput | null {\n if (!isRecord(value)) return null;\n\n const reference = parseSessionReferencePayload(value.reference);\n if (reference) {\n const session = parseBookmarkSession(value.session, reference);\n return session ? { reference, session } : null;\n }\n\n if (\n typeof value.agentKey !== \"string\" ||\n typeof value.sessionId !== \"string\" ||\n typeof value.fullPath !== \"string\" ||\n !value.agentKey.trim() ||\n !value.sessionId\n ) {\n return null;\n }\n const legacyReference = normalizeSessionReference({\n agentName: value.agentKey.trim().toLowerCase(),\n sessionId: value.sessionId,\n });\n const session = parseBookmarkSession(\n {\n ...value,\n id: value.sessionId,\n slug: value.fullPath,\n },\n legacyReference,\n );\n return session ? { reference: legacyReference, session } : null;\n}\n\nfunction sanitizeClientLogData(value: unknown): Record<string, unknown> {\n if (!isRecord(value)) return {};\n\n return Object.fromEntries(\n Object.entries(value)\n .slice(0, 30)\n .map(([key, item]) => {\n if (typeof item === \"string\") return [key, item.slice(0, 300)];\n if (typeof item === \"number\" || typeof item === \"boolean\" || item == null) {\n return [key, item];\n }\n return [key, String(item).slice(0, 300)];\n }),\n );\n}\n\nfunction toSessionListItem(session: SessionHead): SessionHead {\n if (!session.model_usage) return session;\n const item = { ...session };\n delete item.model_usage;\n return item;\n}\n\nfunction getSessionHeadReference(session: SessionHead): SessionReference {\n return {\n agentName: getSessionAgentKey(session),\n sessionId: session.id,\n };\n}\n\nconst SESSION_DETAIL_STREAM_BATCH_CHARS = 64 * 1024;\n\nfunction createSessionDetailJsonResponse(\n data: Omit<SessionDetail, \"messages\">,\n messages: Iterable<string>,\n): Response {\n const encoder = new TextEncoder();\n const headerJson = JSON.stringify(data);\n const iterator = messages[Symbol.iterator]();\n let wroteHeader = false;\n let wroteMessage = false;\n\n return new Response(\n new ReadableStream<Uint8Array>({\n pull(controller) {\n if (!wroteHeader) {\n controller.enqueue(encoder.encode(`${headerJson.slice(0, -1)},\"messages\":[`));\n wroteHeader = true;\n return;\n }\n\n const batch: string[] = [];\n let batchLength = 0;\n let next = iterator.next();\n while (!next.done) {\n const prefix = wroteMessage ? \",\" : \"\";\n batch.push(prefix, next.value);\n batchLength += prefix.length + next.value.length;\n wroteMessage = true;\n if (batchLength >= SESSION_DETAIL_STREAM_BATCH_CHARS) break;\n next = iterator.next();\n }\n\n if (next.done) {\n batch.push(\"]}\");\n controller.enqueue(encoder.encode(batch.join(\"\")));\n controller.close();\n return;\n }\n\n controller.enqueue(encoder.encode(batch.join(\"\")));\n },\n cancel() {\n iterator.return?.();\n },\n }),\n { headers: { \"Content-Type\": \"application/json; charset=UTF-8\" } },\n );\n}\n\nexport function handleGetConfig(c: Context, defaults: SessionListDefaults) {\n const payload: AppConfig = {\n window: {\n from: defaults.from,\n to: defaults.to,\n days: defaults.days,\n },\n };\n return c.json(payload);\n}\n\nexport function handleGetScanStatus(c: Context, scanSource: ScanStatusSource) {\n return c.json(scanSource.getScanStatus());\n}\n\nexport function handleGetAgents(\n c: Context,\n scanSource: ScanResultSource,\n defaults: SessionListDefaults = {},\n) {\n const scanResult = scanSource.getSnapshot();\n const from = parseDateParam(c.req.query(\"from\"), defaults.from);\n const to = parseDateParam(c.req.query(\"to\"), defaults.to);\n const agents = getSnapshotAggregation(\n scanSource,\n scanResult.sessions,\n [\"agents\", from, to],\n () => {\n const counts = Object.fromEntries(\n Object.entries(scanResult.byAgent).map(([agentName, sessions]) => [\n agentName,\n filterSessionsByActivityWindow(sessions, from, to).length,\n ]),\n );\n return getAgentInfoMap(counts);\n },\n );\n return c.json(agents);\n}\n\nexport function handleGetProjects(\n c: Context,\n scanSource: ScanResultSource,\n defaults: SessionListDefaults = {},\n) {\n const scanResult = scanSource.getSnapshot();\n const from = parseDateParam(c.req.query(\"from\"), defaults.from);\n const to = parseDateParam(c.req.query(\"to\"), defaults.to);\n const projects = getSnapshotAggregation(\n scanSource,\n scanResult.sessions,\n [\"projects\", from, to],\n () => {\n const sessions = filterSessionsByActivityWindow(scanResult.sessions, from, to);\n return {\n projects: attachProjectMetrics(listCachedProjectGroups(sessions), sessions),\n };\n },\n );\n return c.json(projects);\n}\n\nexport function handleGetSessions(\n c: Context,\n scanSource: ScanResultSource,\n defaults: SessionListDefaults = {},\n) {\n const scanResult = scanSource.getSnapshot();\n const agent = c.req.query(\"agent\");\n const q = c.req.query(\"q\")?.toLowerCase();\n const cwd = c.req.query(\"cwd\");\n const projectIdentity = parseProjectIdentityFilter(\n c.req.query(\"projectKind\"),\n c.req.query(\"projectKey\"),\n );\n if (projectIdentity === null) {\n return c.json({ error: \"projectKind and projectKey must form a valid project identity\" }, 400);\n }\n const tag = c.req.query(\"tag\")?.toLowerCase();\n const from = parseDateParam(c.req.query(\"from\"), defaults.from);\n const to = parseDateParam(c.req.query(\"to\"), defaults.to);\n\n let sessions: SessionHead[] = [];\n\n // If agent filter is specified, use byAgent directly\n if (agent && scanResult.byAgent[agent]) {\n sessions = [...scanResult.byAgent[agent]!];\n } else {\n sessions = [...scanResult.sessions];\n }\n\n if (projectIdentity) {\n sessions = sessions.filter((session) =>\n matchesProjectIdentity(session.project_identity, projectIdentity),\n );\n } else if (cwd) {\n const projectScope = createProjectScopeMatcher(cwd);\n sessions = sessions.filter((s) => sessionMatchesProjectScope(s, projectScope));\n }\n sessions = filterSessionsByActivityWindow(sessions, from, to);\n if (tag) {\n sessions = sessions.filter((s) => s.smart_tags?.includes(tag as SmartTag));\n }\n\n const aliases = loadAliasView();\n if (q) {\n sessions = sessions.filter((session) => {\n const alias = aliases.get(getSessionHeadReference(session));\n return session.title.toLowerCase().includes(q) || alias?.toLowerCase().includes(q);\n });\n }\n return c.json({\n sessions: sessions.map((session) =>\n toSessionListItem(aliases.decorate(session, getSessionHeadReference(session))),\n ),\n });\n}\n\n/**\n * Sub-session hits render as 父 › 子, so each one needs its parent's title. The\n * index is built only when some hit actually has a parent — the common query\n * touches no sub-session at all.\n */\nfunction withParentContext(\n results: SearchResult[],\n sessions: SessionHead[],\n aliases: AliasView,\n): SearchResult[] {\n if (!results.some((result) => result.session.parent_reference)) return results;\n\n const byRouteKey = new Map(\n sessions.map((session) => [\n getSessionRouteKey(getSessionAgentKey(session), session.id),\n session,\n ]),\n );\n\n return results.map((result) => {\n const parentReference = result.session.parent_reference;\n if (!parentReference) return result;\n const parent = byRouteKey.get(formatSessionReference(parentReference));\n if (!parent) return result;\n const reference = normalizeSessionReference(parentReference);\n return { ...result, parent: { reference, title: aliases.get(reference) ?? parent.title } };\n });\n}\n\nexport function handleSearchSessions(\n c: Context,\n scanSource: ScanResultSource,\n defaults: SessionListDefaults = {},\n) {\n const query = c.req.query(\"q\")?.trim() ?? \"\";\n const scanResult = scanSource.getSnapshot();\n const projectIdentity = parseProjectIdentityFilter(\n c.req.query(\"projectKind\"),\n c.req.query(\"projectKey\"),\n );\n if (projectIdentity === null) {\n return c.json({ error: \"projectKind and projectKey must form a valid project identity\" }, 400);\n }\n const searchOptions = parseSearchOptions(c, defaults, projectIdentity);\n const aliases = loadAliasView();\n const results = executeSessionSearch(query, searchOptions, scanResult).map((result) => ({\n ...result,\n session: aliases.decorate(result.session, result.reference),\n }));\n const aliasResults = findAliasSearchResults(query, searchOptions, scanResult, aliases);\n const deduped = new Map<string, (typeof results)[number]>();\n for (const result of [...aliasResults, ...results]) {\n deduped.set(`${result.reference.agentName}\\0${result.reference.sessionId}`, result);\n }\n return c.json({\n results: withParentContext(\n [...deduped.values()].slice(0, searchOptions.limit ?? 50),\n scanResult.sessions,\n aliases,\n ),\n });\n}\n\nexport function handleGetFileActivity(c: Context, defaults: SessionListDefaults = {}) {\n const limitValue = Number(c.req.query(\"limit\"));\n const limit = Number.isFinite(limitValue) && limitValue > 0 ? Math.min(limitValue, 200) : 50;\n const projectIdentity = parseProjectIdentityFilter(\n c.req.query(\"projectKind\"),\n c.req.query(\"projectKey\"),\n );\n if (projectIdentity === null) {\n return c.json({ error: \"projectKind and projectKey must form a valid project identity\" }, 400);\n }\n\n const aliases = loadAliasView();\n return c.json({\n activity: listFileActivity({\n agent: optionalQueryValue(c.req.query(\"agent\")),\n sessionId: optionalQueryValue(c.req.query(\"sessionId\")),\n projectKind: projectIdentity?.kind,\n projectKey: projectIdentity?.key,\n project: optionalQueryValue(c.req.query(\"project\")),\n cwd: optionalQueryValue(c.req.query(\"cwd\")),\n path: optionalQueryValue(c.req.query(\"path\")),\n kind: parseFileActivityKind(optionalQueryValue(c.req.query(\"kind\"))),\n from: parseDateParam(c.req.query(\"from\"), defaults.from),\n to: parseDateParam(c.req.query(\"to\"), defaults.to),\n limit,\n }).map((activity) => decorateFileActivity(activity, aliases)),\n });\n}\n\nexport async function handleGetSessionData(c: Context, scanSource: ScanResultSource) {\n const startedAt = performance.now();\n const agentName = c.req.param(\"agent\");\n const sessionId = c.req.param(\"id\");\n\n if (!agentName) {\n return c.json({ error: \"Missing agent name\" }, 400);\n }\n\n if (!sessionId) {\n return c.json({ error: \"Missing session ID\" }, 400);\n }\n\n try {\n const result = materializeSessionDetailResponse(scanSource.getSnapshot(), {\n agentName,\n sessionId,\n });\n if (result.status === \"unknown-agent\") {\n return c.json({ error: `Unknown agent: ${agentName}` }, 404);\n }\n if (result.status === \"not-ready\") {\n appLogger.warn(\"api.session_data.cache_miss\", {\n agent: agentName,\n session_id: sessionId,\n duration_ms: Math.round(performance.now() - startedAt),\n });\n return c.json({ error: \"Session cache not ready\" }, 404);\n }\n\n appLogger.info(\"api.session_data\", {\n agent: agentName,\n session_id: sessionId,\n messages: result.status === \"found-json\" ? result.messageCount : result.data.messages.length,\n duration_ms: Math.round(performance.now() - startedAt),\n });\n const aliases = loadAliasView();\n if (result.status === \"found-json\") {\n return createSessionDetailJsonResponse(\n aliases.decorate(result.data, result.data.reference),\n result.messages,\n );\n }\n return c.json(aliases.decorate(result.data, result.data.reference));\n } catch (err) {\n const message = err instanceof Error ? err.message : \"Failed to load session\";\n appLogger.error(\"api.session_data.error\", {\n agent: agentName,\n session_id: sessionId,\n duration_ms: Math.round(performance.now() - startedAt),\n error: message,\n });\n return c.json({ error: message }, 500);\n }\n}\n\nexport async function handlePostClientLog(c: Context) {\n const payload = (await c.req.json().catch(() => null)) as ClientLogPayload | null;\n const rawEvent = payload?.event;\n\n if (typeof rawEvent !== \"string\" || !rawEvent.trim()) {\n return c.json({ ok: false }, 400);\n }\n\n const event = rawEvent\n .trim()\n .replace(/[^a-zA-Z0-9_.:-]/g, \"_\")\n .slice(0, 120);\n appLogger.info(`client.${event}`, sanitizeClientLogData(payload?.data));\n return c.json({ ok: true });\n}\n\nexport function handleGetBookmarks(c: Context) {\n return withStorageErrors(\n () => {\n const aliases = loadAliasView();\n return c.json({\n bookmarks: listBookmarks().map((bookmark) => decorateBookmark(bookmark, aliases)),\n storageAvailable: true,\n });\n },\n () => c.json({ bookmarks: [], storageAvailable: false }),\n );\n}\n\nexport async function handlePutBookmark(c: Context) {\n const payload = parseBookmarkPayload(await c.req.json().catch(() => null));\n if (!payload) {\n return c.json({ error: \"Invalid bookmark payload\" }, 400);\n }\n\n return withStorageErrors(\n () => c.json({ bookmark: upsertBookmark(payload), storageAvailable: true }),\n () => c.json({ error: \"Bookmark storage is unavailable\" }, 503),\n );\n}\n\nexport async function handleImportBookmarks(c: Context) {\n const payload = await c.req.json().catch(() => null);\n if (!Array.isArray(payload)) {\n return c.json({ error: \"Invalid bookmark payload\" }, 400);\n }\n\n const bookmarks = payload\n .map((entry) => parseBookmarkPayload(entry))\n .filter((entry): entry is NonNullable<typeof entry> => entry !== null);\n\n if (bookmarks.length !== payload.length) {\n return c.json({ error: \"Invalid bookmark payload\" }, 400);\n }\n\n return withStorageErrors(\n () => c.json({ bookmarks: importBookmarks(bookmarks), storageAvailable: true }),\n () => c.json({ error: \"Bookmark storage is unavailable\" }, 503),\n );\n}\n\nexport function handleDeleteBookmark(c: Context) {\n const agentKey = c.req.param(\"agent\");\n const sessionId = c.req.param(\"id\");\n if (!agentKey || !sessionId) {\n return c.json({ error: \"Missing bookmark identifier\" }, 400);\n }\n\n return withStorageErrors(\n () => {\n deleteBookmark({ agentName: agentKey, sessionId });\n return c.json({ ok: true, storageAvailable: true });\n },\n () => c.json({ error: \"Bookmark storage is unavailable\" }, 503),\n );\n}\n\nexport async function handlePutSessionAlias(c: Context) {\n const agentKey = c.req.param(\"agent\");\n const sessionId = c.req.param(\"id\");\n const payload = (await c.req.json().catch(() => null)) as SessionAliasPayload | null;\n const aliasValue = payload?.alias;\n if (!agentKey || !sessionId || typeof aliasValue !== \"string\") {\n return c.json({ error: \"Invalid session alias payload\" }, 400);\n }\n\n try {\n return withStorageErrors(\n () => {\n const alias = upsertSessionAlias({ agentName: agentKey, sessionId }, aliasValue);\n invalidateAliasView();\n return c.json({ alias });\n },\n () => c.json({ error: \"Session alias storage is unavailable\" }, 503),\n );\n } catch (error) {\n if (error instanceof SessionAliasValidationError) {\n return c.json({ error: \"Session alias must be non-empty and at most 160 characters\" }, 400);\n }\n throw error;\n }\n}\n\nexport function handleDeleteSessionAlias(c: Context) {\n const agentKey = c.req.param(\"agent\");\n const sessionId = c.req.param(\"id\");\n if (!agentKey || !sessionId) {\n return c.json({ error: \"Missing session alias identifier\" }, 400);\n }\n\n return withStorageErrors(\n () => {\n deleteSessionAlias({ agentName: agentKey, sessionId });\n invalidateAliasView();\n return c.json({ ok: true });\n },\n () => c.json({ error: \"Session alias storage is unavailable\" }, 503),\n );\n}\n\nexport function handleGetDashboard(\n c: Context,\n scanSource: ScanResultSource,\n defaults: SessionListDefaults = {},\n) {\n const scanResult = scanSource.getSnapshot();\n const projectIdentity = parseProjectIdentityFilter(\n c.req.query(\"projectKind\"),\n c.req.query(\"projectKey\"),\n );\n if (projectIdentity === null) {\n return c.json({ error: \"projectKind and projectKey must form a valid project identity\" }, 400);\n }\n const { from, to, days } = resolveTimeWindow({\n mode: \"dashboard\",\n query: {\n days: c.req.query(\"days\"),\n from: c.req.query(\"from\"),\n to: c.req.query(\"to\"),\n },\n defaults,\n });\n const scope: DashboardScope = {\n agent: optionalQueryValue(c.req.query(\"agent\"))?.toLowerCase(),\n projectKind: projectIdentity?.kind,\n projectKey: projectIdentity?.key,\n };\n\n const compare =\n from == null\n ? undefined\n : { from: addCalendarDays(from, -(days ?? countCalendarDays(from, to))), to: from - 1 };\n\n const fixedTo = parseDateParam(c.req.query(\"to\"), defaults.to);\n const aggregate = getSnapshotAggregation(\n scanSource,\n scanResult.sessions,\n [\n \"dashboard\",\n scope.agent,\n scope.projectKind,\n scope.projectKey,\n from,\n fixedTo ?? startOfCalendarDay(to),\n compare?.from,\n compare?.to,\n ],\n () => {\n const agentInfo = getAgentInfoMap({});\n const agentInfoMap = new Map(agentInfo.map((agent) => [agent.name, agent]));\n return buildDashboard(scanResult.sessions, {\n byAgentNames: Object.keys(scanResult.byAgent),\n scope,\n from,\n to,\n agentInfoMap,\n compare,\n });\n },\n );\n\n const data: DashboardData = {\n ...aggregate,\n recentFileActivities: listFileActivity({\n agent: scope.agent,\n projectKind: scope.projectKind,\n projectKey: scope.projectKey,\n from,\n to,\n limit: 12,\n }),\n modelCost: listModelCostDistribution({\n agent: scope.agent,\n projectKind: scope.projectKind,\n projectKey: scope.projectKey,\n from,\n to,\n }),\n window: { from, to, days, compareFrom: compare?.from, compareTo: compare?.to },\n };\n\n const aliases = loadAliasView();\n return c.json({\n ...data,\n recentSessions: data.recentSessions.map((item) => ({\n ...item,\n session: aliases.decorate(item.session, item.reference),\n })),\n recentFileActivities: data.recentFileActivities.map((activity) =>\n decorateFileActivity(activity, aliases),\n ),\n });\n}\n","import { randomBytes, timingSafeEqual } from \"node:crypto\";\nimport { readFileSync } from \"node:fs\";\nimport { isIP } from \"node:net\";\nimport type { Context, MiddlewareHandler } from \"hono\";\n\nexport const REMOTE_ACCESS_QUERY_PARAM = \"access_token\";\n\n/**\n * How a remote listener's traffic is protected. A token proves who is asking;\n * it says nothing about who else can read the answer, so confidentiality is\n * modelled separately from authentication.\n */\nexport type RemoteTransport =\n | { kind: \"loopback\" }\n /** CodeSesh terminates TLS itself. */\n | { kind: \"tls\"; cert: Buffer; key: Buffer }\n /** A reverse proxy in front of CodeSesh terminates TLS. */\n | { kind: \"trusted-proxy\" }\n /** The operator accepted plaintext on an untrusted network. */\n | { kind: \"plaintext\" };\n\nexport interface RemoteTransportRequest {\n hostname: string;\n tlsCertPath?: string;\n tlsKeyPath?: string;\n trustProxy?: boolean;\n}\n\nexport class RemoteTransportError extends Error {}\n\n/**\n * Resolves the transport from the CLI flags. Loopback stays plaintext without\n * ceremony: nothing leaves the machine.\n */\nexport function resolveRemoteTransport(request: RemoteTransportRequest): RemoteTransport {\n const hasCert = Boolean(request.tlsCertPath);\n const hasKey = Boolean(request.tlsKeyPath);\n if (hasCert !== hasKey) {\n throw new RemoteTransportError(\"TLS requires both --tls-cert and --tls-key.\");\n }\n if (hasCert && request.trustProxy) {\n throw new RemoteTransportError(\n \"Use either --tls-cert/--tls-key or --trust-proxy, not both: only one of them terminates TLS.\",\n );\n }\n\n if (hasCert) {\n try {\n return {\n kind: \"tls\",\n cert: readFileSync(request.tlsCertPath!),\n key: readFileSync(request.tlsKeyPath!),\n };\n } catch (error) {\n throw new RemoteTransportError(\n `Unable to read the TLS certificate or key: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n\n if (request.trustProxy) return { kind: \"trusted-proxy\" };\n return isLoopbackHostname(request.hostname) ? { kind: \"loopback\" } : { kind: \"plaintext\" };\n}\n\n/** Whether the transport keeps request and response bodies off the wire in the clear. */\nexport function isConfidentialTransport(transport: RemoteTransport): boolean {\n return transport.kind !== \"plaintext\";\n}\n\nconst FORWARDED_PROTO_HEADER = \"X-Forwarded-Proto\";\n\n/**\n * Behind a trusted proxy, a request arriving without the proxy's own\n * `X-Forwarded-Proto: https` did not come through it. Trusting the header is\n * only sound because the deployment is expected to make CodeSesh unreachable\n * except via that proxy — which is what --trust-proxy asserts.\n */\nexport function requireProxyTls(): MiddlewareHandler {\n return async (c, next) => {\n const proto = c.req.header(FORWARDED_PROTO_HEADER)?.split(\",\")[0]?.trim().toLowerCase();\n if (proto !== \"https\") {\n return c.json({ error: \"Requests must arrive over TLS through the trusted proxy\" }, 403);\n }\n await next();\n };\n}\n\nexport function createRemoteAccessToken(): string {\n return randomBytes(32).toString(\"base64url\");\n}\n\nexport function isLoopbackHostname(hostname: string): boolean {\n const normalized = hostname.toLowerCase().replace(/^\\[(.*)\\]$/, \"$1\");\n if (normalized === \"localhost\" || normalized === \"::1\") return true;\n return isIP(normalized) === 4 && normalized.startsWith(\"127.\");\n}\n\nfunction tokenMatches(actual: string | undefined, expected: string): boolean {\n if (!actual) return false;\n const actualBuffer = Buffer.from(actual);\n const expectedBuffer = Buffer.from(expected);\n return (\n actualBuffer.length === expectedBuffer.length && timingSafeEqual(actualBuffer, expectedBuffer)\n );\n}\n\nfunction bearerToken(c: Context): string | undefined {\n const authorization = c.req.header(\"Authorization\");\n if (!authorization?.startsWith(\"Bearer \")) return undefined;\n return authorization.slice(\"Bearer \".length);\n}\n\nfunction requestToken(c: Context): string | undefined {\n const bearer = bearerToken(c);\n if (bearer) return bearer;\n if (c.req.method !== \"GET\") return undefined;\n return c.req.query(REMOTE_ACCESS_QUERY_PARAM);\n}\n\nexport function remoteAccessAuth(expectedToken: string): MiddlewareHandler {\n return async (c, next) => {\n if (!tokenMatches(requestToken(c), expectedToken)) {\n return c.json({ error: \"Remote access authentication required\" }, 401);\n }\n await next();\n };\n}\n","import { existsSync } from \"node:fs\";\nimport { fileURLToPath } from \"node:url\";\nimport {\n createRegisteredAgents,\n scanSessions,\n type LiveSnapshot,\n type ScanOptions,\n} from \"@codesesh/core\";\nimport type {\n AgentScanStatus,\n BackfillStatus,\n ScanStatusEvent,\n SessionsUpdatedEvent,\n} from \"@codesesh/core/contract\";\nimport { mergeSessionsUpdatedEvents } from \"@codesesh/core/contract\";\nimport { AgentSyncEngine } from \"./agent-sync-engine.js\";\nimport { appLogger } from \"./logging.js\";\nimport { SessionWatcher } from \"./session-watcher.js\";\nimport { ThreadWorkerRunner, type WorkerRunner } from \"./worker-runner.js\";\n\nexport type { AgentScanStatus, BackfillStatus, ScanStatusEvent, SessionsUpdatedEvent };\n\ntype StoreListener = (event: SessionsUpdatedEvent) => void;\ntype ScanStatusListener = (event: ScanStatusEvent) => void;\n\nexport interface LiveScanStoreOptions {\n watchEnabled?: boolean;\n scanOptions?: ScanOptions;\n startupScanOptions?: Pick<ScanOptions, \"from\" | \"to\">;\n deferInitialRefresh?: boolean;\n workerRunner?: WorkerRunner;\n}\n\nconst NEW_SESSION_EVENT_WINDOW_MS = 250;\n\nexport class LiveScanStore {\n private readonly watchEnabled: boolean;\n private readonly scanOptions: ScanOptions;\n private readonly startupScanOptions: Pick<ScanOptions, \"from\" | \"to\">;\n private readonly deferInitialRefresh: boolean;\n private readonly syncEngine: AgentSyncEngine;\n private listeners = new Set<StoreListener>();\n private watcher: SessionWatcher | null = null;\n private pendingEvent: SessionsUpdatedEvent | null = null;\n private pendingEventTimer: NodeJS.Timeout | null = null;\n private shutdownPromise: Promise<void> | null = null;\n private shuttingDown = false;\n\n constructor(options: LiveScanStoreOptions = {}) {\n this.watchEnabled = options.watchEnabled ?? true;\n this.scanOptions = options.scanOptions ?? {};\n this.startupScanOptions = options.startupScanOptions ?? {};\n this.deferInitialRefresh = options.deferInitialRefresh === true;\n const workerRunner =\n options.workerRunner ??\n new ThreadWorkerRunner(new URL(\"./scan-refresh-worker.js\", import.meta.url));\n this.syncEngine = new AgentSyncEngine({\n startupScanOptions: this.startupScanOptions,\n workerRunner,\n });\n this.syncEngine.subscribeSessionsChanged((change) => {\n if (change.event) this.emit(change.event);\n });\n }\n\n async initialize(): Promise<void> {\n const startedAt = performance.now();\n appLogger.info(\"scan.initial.start\", {\n watch_enabled: this.watchEnabled,\n agents: this.scanOptions.agents,\n use_cache: this.scanOptions.useCache ?? true,\n startup_from: this.startupScanOptions.from,\n startup_to: this.startupScanOptions.to,\n deferred: this.deferInitialRefresh || undefined,\n });\n const initialResult = await scanSessions({\n ...this.scanOptions,\n useCache: this.scanOptions.useCache ?? true,\n smartRefresh: false,\n cacheOnly: this.deferInitialRefresh,\n writeCache: this.deferInitialRefresh ? false : this.scanOptions.writeCache,\n smartTagWorkerUrl: this.getSmartTagWorkerUrl() ?? undefined,\n includeSmartTags: this.deferInitialRefresh ? false : undefined,\n });\n this.syncEngine.initialize(initialResult, {\n cacheTimestamps: initialResult.cacheTimestamps,\n registeredAgents: createRegisteredAgents(),\n allowedAgents: this.getAllowedAgents(),\n });\n const snapshot = this.getSnapshot();\n const indexStartedAt = performance.now();\n if (!this.deferInitialRefresh) {\n // The snapshot is already served from memory, so an index-write failure\n // degrades search freshness rather than startup.\n await this.syncEngine.syncInitialIndex().catch((error: unknown) => {\n appLogger.error(\"scan.initial.index_failed\", { error });\n });\n }\n const indexDuration = performance.now() - indexStartedAt;\n appLogger.info(\"scan.initial.done\", {\n duration_ms: Math.round(performance.now() - startedAt),\n index_ms: this.deferInitialRefresh ? undefined : Math.round(indexDuration),\n deferred: this.deferInitialRefresh || undefined,\n sessions: snapshot.sessions.length,\n agents: Object.fromEntries(\n Object.entries(snapshot.byAgent).map(([key, value]) => [key, value.length]),\n ),\n agent_timings: initialResult.timings\n ? Object.fromEntries(\n Object.entries(initialResult.timings).map(([name, timing]) => [\n name,\n {\n total_ms: Math.round(timing.total),\n cache_load_ms: timing.cacheLoad != null ? Math.round(timing.cacheLoad) : undefined,\n check_changes_ms:\n timing.checkChanges != null ? Math.round(timing.checkChanges) : undefined,\n scan_ms: timing.scan != null ? Math.round(timing.scan) : undefined,\n identity_ms: timing.identity != null ? Math.round(timing.identity) : undefined,\n tags_ms: timing.tags != null ? Math.round(timing.tags) : undefined,\n },\n ]),\n )\n : undefined,\n });\n if (!this.watchEnabled) return;\n this.watcher = new SessionWatcher();\n this.watcher.onAgentsChanged((agentNames) => this.syncEngine.handleAgentsChanged(agentNames));\n this.watcher.start(snapshot.agents);\n }\n\n startBackgroundRefresh(): void {\n this.syncEngine.startBackgroundRefresh();\n }\n\n getSnapshot(): LiveSnapshot {\n return this.syncEngine.snapshot();\n }\n\n getScanStatus(): ScanStatusEvent {\n return this.syncEngine.status();\n }\n\n subscribe(listener: StoreListener): () => void {\n this.listeners.add(listener);\n return () => this.listeners.delete(listener);\n }\n\n subscribeScanStatus(listener: ScanStatusListener): () => void {\n return this.syncEngine.subscribeStatusChanged(listener);\n }\n\n shutdown(): Promise<void> {\n this.shutdownPromise ??= this.performShutdown();\n return this.shutdownPromise;\n }\n\n private async performShutdown(): Promise<void> {\n this.shuttingDown = true;\n if (this.pendingEventTimer) {\n clearTimeout(this.pendingEventTimer);\n this.pendingEventTimer = null;\n }\n await this.syncEngine.shutdown();\n this.pendingEvent = null;\n if (this.watcher) {\n await this.watcher.dispose();\n this.watcher = null;\n }\n }\n\n private emit(event: SessionsUpdatedEvent): void {\n if (this.shuttingDown) return;\n if (this.pendingEvent || event.newSessions > 0) {\n this.queueEvent(event);\n return;\n }\n this.emitNow(event);\n }\n\n private emitNow(event: SessionsUpdatedEvent): void {\n for (const listener of this.listeners) listener(event);\n }\n\n private queueEvent(event: SessionsUpdatedEvent): void {\n this.pendingEvent = this.pendingEvent\n ? mergeSessionsUpdatedEvents(this.pendingEvent, event)\n : event;\n if (this.pendingEventTimer) return;\n this.pendingEventTimer = setTimeout(() => {\n const pending = this.pendingEvent;\n this.pendingEvent = null;\n this.pendingEventTimer = null;\n if (pending) this.emitNow(pending);\n }, NEW_SESSION_EVENT_WINDOW_MS);\n }\n\n private getSmartTagWorkerUrl(): URL | null {\n const workerUrl = new URL(\"./smart-tag-worker.js\", import.meta.url);\n if (workerUrl.protocol === \"file:\" && !existsSync(fileURLToPath(workerUrl))) return null;\n return workerUrl;\n }\n\n private getAllowedAgents(): Set<string> | null {\n if (!this.scanOptions.agents?.length) return null;\n return new Set(this.scanOptions.agents.map((agent) => agent.toLowerCase()));\n }\n}\n","import { appLogger } from \"./logging.js\";\n\nexport type AgentOperationKind = \"backfill\" | \"refresh\";\nexport type AgentOperationResult = \"committed\" | \"failed\" | \"skipped\" | \"unchanged\";\n\ninterface AgentScheduleState {\n timer: NodeJS.Timeout | null;\n timerDeadline: number;\n isRefreshRunning: boolean;\n hasPendingRefresh: boolean;\n lastRefreshDurationMs: number;\n pendingSignalCount: number;\n}\n\ninterface AgentOperationLifecycle {\n agentName: string;\n kind: AgentOperationKind;\n generation: number;\n startedAt: number;\n}\n\nexport interface AgentOperationSchedulerSnapshot {\n activeOperations: number;\n activeRefreshes: number;\n}\n\nconst PENDING_REFRESH_DELAY_MS = 100;\nconst MAX_ADAPTIVE_REFRESH_DELAY_MS = 30_000;\nconst ADAPTIVE_REFRESH_DELAY_MULTIPLIER = 4;\n\nexport class AgentOperationScheduler {\n private readonly states = new Map<string, AgentScheduleState>();\n private readonly operationGenerations = new Map<string, number>();\n private readonly operationTails = new Map<string, Promise<void>>();\n private isStopped = false;\n\n constructor(private readonly runRefresh: (agentName: string) => Promise<AgentOperationResult>) {}\n\n notify(agentName: string, delayMs: number): void {\n if (this.isStopped) return;\n this.state(agentName).pendingSignalCount += 1;\n this.schedule(agentName, delayMs);\n }\n\n schedule(agentName: string, delayMs: number): void {\n if (this.isStopped) return;\n const state = this.state(agentName);\n const adaptiveDelayMs = Math.min(\n state.lastRefreshDurationMs * ADAPTIVE_REFRESH_DELAY_MULTIPLIER,\n MAX_ADAPTIVE_REFRESH_DELAY_MS,\n );\n const effectiveDelayMs = Math.max(delayMs, adaptiveDelayMs);\n const deadline = Date.now() + effectiveDelayMs;\n if (state.timer) {\n if (deadline >= state.timerDeadline) return;\n clearTimeout(state.timer);\n }\n\n appLogger.debug(\"scan.refresh.schedule\", { agent: agentName, delay_ms: effectiveDelayMs });\n state.timerDeadline = deadline;\n state.timer = setTimeout(() => {\n state.timer = null;\n state.timerDeadline = 0;\n void this.refresh(agentName);\n }, effectiveDelayMs);\n }\n\n async refresh(agentName: string): Promise<void> {\n if (this.isStopped) return;\n const state = this.state(agentName);\n if (state.isRefreshRunning) {\n appLogger.debug(\"scan.refresh.pending\", { agent: agentName });\n state.hasPendingRefresh = true;\n return;\n }\n\n state.isRefreshRunning = true;\n try {\n await this.run(agentName, \"refresh\", () => this.runRefresh(agentName));\n } finally {\n state.isRefreshRunning = false;\n if (state.hasPendingRefresh && !this.isStopped) {\n state.hasPendingRefresh = false;\n this.schedule(agentName, PENDING_REFRESH_DELAY_MS);\n }\n }\n }\n\n run(\n agentName: string,\n kind: AgentOperationKind,\n operation: () => Promise<AgentOperationResult>,\n ): Promise<AgentOperationResult> {\n const previous = this.operationTails.get(agentName) ?? Promise.resolve();\n const run = previous.then(async () => {\n if (this.isStopped) return \"skipped\";\n const lifecycle = this.beginOperation(agentName, kind);\n try {\n const result = await operation();\n this.completeOperation(lifecycle, result);\n return result;\n } catch (error) {\n this.completeOperation(lifecycle, \"failed\");\n throw error;\n }\n });\n const tail = run.then(\n () => undefined,\n () => undefined,\n );\n this.operationTails.set(agentName, tail);\n void tail.finally(() => {\n if (this.operationTails.get(agentName) === tail) this.operationTails.delete(agentName);\n });\n return run;\n }\n\n takePendingSignalCount(agentName: string): number {\n const state = this.state(agentName);\n const count = state.pendingSignalCount;\n state.pendingSignalCount = 0;\n return count;\n }\n\n recordRefreshDuration(agentName: string, durationMs: number): void {\n this.state(agentName).lastRefreshDurationMs = durationMs;\n }\n\n snapshot(): AgentOperationSchedulerSnapshot {\n return {\n activeOperations: this.operationTails.size,\n activeRefreshes: [...this.states.values()].filter((state) => state.isRefreshRunning).length,\n };\n }\n\n stop(): void {\n this.isStopped = true;\n for (const state of this.states.values()) {\n if (state.timer) clearTimeout(state.timer);\n state.timer = null;\n state.timerDeadline = 0;\n state.hasPendingRefresh = false;\n state.pendingSignalCount = 0;\n }\n }\n\n async waitForIdle(): Promise<void> {\n await Promise.allSettled(this.operationTails.values());\n }\n\n private state(agentName: string): AgentScheduleState {\n const existing = this.states.get(agentName);\n if (existing) return existing;\n const state: AgentScheduleState = {\n timer: null,\n timerDeadline: 0,\n isRefreshRunning: false,\n hasPendingRefresh: false,\n lastRefreshDurationMs: 0,\n pendingSignalCount: 0,\n };\n this.states.set(agentName, state);\n return state;\n }\n\n private beginOperation(agentName: string, kind: AgentOperationKind): AgentOperationLifecycle {\n const generation = (this.operationGenerations.get(agentName) ?? 0) + 1;\n const startedAt = Date.now();\n this.operationGenerations.set(agentName, generation);\n appLogger.info(\"scan.agent_operation.started\", {\n agent: agentName,\n operation: kind,\n generation,\n started_at: startedAt,\n });\n return { agentName, kind, generation, startedAt };\n }\n\n private completeOperation(\n lifecycle: AgentOperationLifecycle,\n result: AgentOperationResult,\n ): void {\n const completedAt = Date.now();\n appLogger.info(\"scan.agent_operation.completed\", {\n agent: lifecycle.agentName,\n operation: lifecycle.kind,\n generation: lifecycle.generation,\n started_at: lifecycle.startedAt,\n completed_at: completedAt,\n duration_ms: completedAt - lifecycle.startedAt,\n result,\n });\n }\n}\n","import {\n computeSessionDiff,\n mergeSortedSessions,\n sessionSignature,\n sortSessions,\n type BaseAgent,\n type LiveSnapshot,\n type SessionHead,\n} from \"@codesesh/core\";\nimport type { SessionsUpdatedEvent } from \"@codesesh/core/contract\";\n\nexport interface LiveSessionIndexOptions {\n registeredAgents?: BaseAgent[];\n allowedAgents?: ReadonlySet<string> | null;\n}\n\nexport class LiveSessionIndex {\n private agents: BaseAgent[] = [];\n private agentsByName = new Map<string, BaseAgent>();\n private byAgent: Record<string, SessionHead[]> = {};\n private sessions: SessionHead[] = [];\n private signatureCaches = new Map<string, Map<string, string>>();\n\n initialize(snapshot: LiveSnapshot, options: LiveSessionIndexOptions = {}): void {\n const agentMap = new Map<string, BaseAgent>();\n for (const agent of snapshot.agents) agentMap.set(agent.name, agent);\n for (const agent of options.registeredAgents ?? []) {\n if (!agentMap.has(agent.name)) agentMap.set(agent.name, agent);\n }\n\n this.agents = [...agentMap.values()].filter(\n (agent) => !options.allowedAgents || options.allowedAgents.has(agent.name.toLowerCase()),\n );\n this.agentsByName = new Map(this.agents.map((agent) => [agent.name, agent]));\n this.byAgent = Object.fromEntries(\n this.agents.map((agent) => [agent.name, sortSessions(snapshot.byAgent[agent.name] ?? [])]),\n );\n this.sessions = mergeSortedSessions(Object.values(this.byAgent));\n this.signatureCaches.clear();\n }\n\n snapshot(): LiveSnapshot {\n return {\n agents: this.agents,\n byAgent: this.byAgent,\n sessions: this.sessions,\n };\n }\n\n findAgent(agentName: string): BaseAgent | undefined {\n return this.agentsByName.get(agentName);\n }\n\n commitAgentSessions(\n agentName: string,\n nextSessions: SessionHead[],\n candidateChangedIds: string[] = [],\n ): SessionsUpdatedEvent | null {\n const previousSessions = this.byAgent[agentName] ?? [];\n const signatureCache = this.signatureCache(agentName);\n const { changes, removedSessionIds, counts } = computeSessionDiff(\n previousSessions,\n nextSessions,\n candidateChangedIds,\n sessionSignature,\n signatureCache,\n );\n for (const removedId of removedSessionIds) signatureCache.delete(removedId);\n\n this.byAgent[agentName] = sortSessions(nextSessions);\n this.sessions = mergeSortedSessions(Object.values(this.byAgent));\n if (counts.new === 0 && counts.updated === 0 && counts.removed === 0) return null;\n\n return {\n type: \"sessions-updated\",\n changedAgents: [agentName],\n newSessions: counts.new,\n updatedSessions: counts.updated,\n removedSessions: counts.removed,\n totalSessions: this.sessions.length,\n timestamp: Date.now(),\n changedSessionHeads: changes.map(({ session }) => ({\n reference: { agentName, sessionId: session.id },\n session,\n })),\n removedSessionRefs: removedSessionIds.map((sessionId) => ({ agentName, sessionId })),\n };\n }\n\n private signatureCache(agentName: string): Map<string, string> {\n const existing = this.signatureCaches.get(agentName);\n if (existing) return existing;\n const cache = new Map<string, string>();\n this.signatureCaches.set(agentName, cache);\n return cache;\n }\n}\n","import { existsSync } from \"node:fs\";\nimport { fileURLToPath } from \"node:url\";\nimport { Worker } from \"node:worker_threads\";\nimport { toError } from \"./errors.js\";\nimport { appLogger, logSearchIndexSync } from \"./logging.js\";\nimport { PendingSearchIndexJobs, type SearchIndexJobBatch } from \"./pending-search-index-jobs.js\";\nimport type { SearchIndexWorkerJob, SearchIndexWorkerMessage } from \"./search-index-worker.js\";\n\nconst SHUTDOWN_ERROR_MESSAGE = \"Live scan store shut down\";\n\nexport interface SearchIndexJobRunnerSnapshot {\n activeBatchId?: number;\n pendingBatches: number;\n pendingJobs: number;\n pendingChanges: number;\n}\n\nexport class SearchIndexJobRunner {\n private worker: Worker | null = null;\n private activeBatch: SearchIndexJobBatch | null = null;\n private nextBatchId = 1;\n private pendingJobs = new PendingSearchIndexJobs();\n private isShuttingDown = false;\n\n enqueue(context: string, jobs: SearchIndexWorkerJob[]): Promise<void> {\n if (jobs.length === 0) return Promise.resolve();\n if (this.isShuttingDown) return Promise.reject(new Error(SHUTDOWN_ERROR_MESSAGE));\n\n const batchId = this.nextBatchId++;\n const completion = this.pendingJobs.enqueue(batchId, context, jobs);\n if (this.worker) {\n const snapshot = this.snapshot();\n appLogger.debug(\"search_index.worker_queued\", {\n batch_id: batchId,\n context,\n jobs: jobs.length,\n pending_batches: snapshot.pendingBatches,\n pending_jobs: snapshot.pendingJobs,\n pending_changes: snapshot.pendingChanges,\n });\n } else {\n this.startNextBatch();\n }\n return completion;\n }\n\n snapshot(): SearchIndexJobRunnerSnapshot {\n return {\n activeBatchId: this.activeBatch?.id,\n pendingBatches: this.pendingJobs.batchCount,\n pendingJobs: this.pendingJobs.jobCount,\n pendingChanges: this.pendingJobs.changeCount,\n };\n }\n\n async shutdown(): Promise<void> {\n this.isShuttingDown = true;\n const activeBatch = this.activeBatch;\n const worker = this.worker;\n this.activeBatch = null;\n this.worker = null;\n\n const shutdownError = new Error(SHUTDOWN_ERROR_MESSAGE);\n if (activeBatch) this.settle(activeBatch, shutdownError);\n this.pendingJobs.rejectAll(shutdownError);\n if (worker) await worker.terminate();\n }\n\n private startNextBatch(): void {\n if (this.isShuttingDown || this.worker) return;\n const batch = this.pendingJobs.take();\n if (!batch) return;\n\n appLogger.info(\"search_index.worker_dequeued\", {\n batch_id: batch.id,\n context: batch.context,\n pending_batches: this.pendingJobs.batchCount,\n });\n this.startBatch(batch);\n }\n\n private startBatch(batch: SearchIndexJobBatch): void {\n if (this.isShuttingDown) {\n this.settle(batch, new Error(SHUTDOWN_ERROR_MESSAGE));\n return;\n }\n\n const workerUrl = this.workerUrl();\n if (!workerUrl) {\n appLogger.warn(\"search_index.worker_missing\", { context: batch.context });\n this.settle(batch);\n return;\n }\n appLogger.info(\"search_index.worker_started\", {\n batch_id: batch.id,\n context: batch.context,\n jobs: batch.jobs.length,\n });\n\n const worker = new Worker(workerUrl, {\n workerData: {\n context: batch.context,\n jobs: batch.jobs,\n agentNames: [],\n sessionsByAgent: {},\n metaByAgent: {},\n },\n });\n worker.unref();\n this.worker = worker;\n this.activeBatch = batch;\n\n worker.on(\"message\", (message: SearchIndexWorkerMessage) => {\n if (message.type === \"sync-result\") {\n logSearchIndexSync(message.context, message.result);\n return;\n }\n if (message.type === \"persist-failed\") {\n appLogger.error(\"search_index.persist_failed\", {\n batch_id: batch.id,\n context: message.context,\n stage: message.stage,\n agent: message.agentName,\n sessions: message.sessions,\n });\n this.settle(\n batch,\n new Error(\n `Search index worker failed to persist ${message.stage} for ${message.agentName}`,\n ),\n );\n return;\n }\n if (message.type !== \"done\") return;\n\n appLogger.info(`${message.context}.done`, {\n duration_ms: Math.round(message.durationMs),\n sessions: message.sessions,\n });\n this.settle(batch);\n });\n worker.on(\"error\", (error) => {\n appLogger.error(\"search_index.worker_error\", { context: batch.context, error });\n this.settle(batch, toError(error));\n });\n worker.on(\"exit\", (code) => this.finishWorker(worker, batch, code));\n }\n\n private finishWorker(worker: Worker, batch: SearchIndexJobBatch, code: number): void {\n appLogger.info(\"search_index.worker_exited\", {\n batch_id: batch.id,\n context: batch.context,\n code,\n shutting_down: this.isShuttingDown || undefined,\n });\n if (this.worker === worker) this.worker = null;\n if (this.activeBatch === batch) this.activeBatch = null;\n\n const error =\n code === 0\n ? new Error(\"Search index worker exited before completing its batch\")\n : new Error(`Search index worker exited with code ${code}`);\n if (code !== 0) appLogger.warn(\"search_index.worker_exit\", { context: batch.context, code });\n this.settle(batch, error);\n this.startNextBatch();\n }\n\n private settle(batch: SearchIndexJobBatch, error?: Error): void {\n if (!this.pendingJobs.settle(batch, error)) return;\n appLogger.info(\"search_index.worker_settled\", {\n batch_id: batch.id,\n context: batch.context,\n result: error ? \"rejected\" : \"resolved\",\n });\n }\n\n private workerUrl(): URL | null {\n const workerUrl = new URL(\"./search-index-worker.js\", import.meta.url);\n if (workerUrl.protocol === \"file:\" && !existsSync(fileURLToPath(workerUrl))) return null;\n return workerUrl;\n }\n}\n","export function toError(value: unknown): Error {\n return value instanceof Error ? value : new Error(String(value));\n}\n","import type { SearchIndexSyncOptions, SessionCacheMeta, SessionHeadChange } from \"@codesesh/core\";\nimport type { SearchIndexWorkerJob } from \"./search-index-worker.js\";\n\ntype FullSearchIndexJob = Extract<SearchIndexWorkerJob, { kind: \"full\" }>;\ntype ChangesSearchIndexJob = Extract<SearchIndexWorkerJob, { kind: \"changes\" }>;\n\ninterface JobWaiter {\n resolve: () => void;\n reject: (error: Error) => void;\n}\n\ninterface PendingChanges {\n context: string;\n agentName: string;\n changesBySessionId: Map<string, SessionHeadChange>;\n removedSessionIds: Set<string>;\n meta: Record<string, SessionCacheMeta>;\n searchIndexOptions?: SearchIndexSyncOptions;\n}\n\ninterface PendingAgentJobs {\n full?: FullSearchIndexJob;\n changes?: PendingChanges;\n}\n\nexport interface SearchIndexJobBatch {\n readonly id: number;\n readonly context: string;\n readonly jobs: SearchIndexWorkerJob[];\n}\n\nclass PendingSearchIndexJobBatch implements SearchIndexJobBatch {\n context: string;\n private readonly jobsByAgent = new Map<string, PendingAgentJobs>();\n private readonly waiters: JobWaiter[] = [];\n private settled = false;\n\n constructor(\n readonly id: number,\n context: string,\n jobs: SearchIndexWorkerJob[],\n waiter: JobWaiter,\n ) {\n this.context = context;\n this.merge(context, jobs, waiter);\n }\n\n get jobs(): SearchIndexWorkerJob[] {\n const jobs: SearchIndexWorkerJob[] = [];\n for (const pending of this.jobsByAgent.values()) {\n if (pending.full) jobs.push(pending.full);\n if (pending.changes) jobs.push(changesJobFromPending(pending.changes));\n }\n return jobs;\n }\n\n get changeCount(): number {\n let count = 0;\n for (const pending of this.jobsByAgent.values()) {\n if (!pending.changes) continue;\n count += pending.changes.changesBySessionId.size + pending.changes.removedSessionIds.size;\n }\n return count;\n }\n\n merge(context: string, jobs: SearchIndexWorkerJob[], waiter: JobWaiter): void {\n this.context = context;\n this.waiters.push(waiter);\n for (const job of jobs) this.mergeJob(job);\n }\n\n settle(error?: Error): boolean {\n if (this.settled) return false;\n this.settled = true;\n for (const waiter of this.waiters) {\n if (error) waiter.reject(error);\n else waiter.resolve();\n }\n this.waiters.length = 0;\n return true;\n }\n\n private mergeJob(job: SearchIndexWorkerJob): void {\n const pending = this.jobsByAgent.get(job.agentName) ?? {};\n this.jobsByAgent.set(job.agentName, pending);\n\n if (job.kind === \"full\") {\n pending.full = job;\n pending.changes = undefined;\n return;\n }\n\n pending.changes ??= createPendingChanges(job);\n mergeChanges(pending.changes, job);\n }\n}\n\nexport class PendingSearchIndexJobs {\n private pendingBatch: PendingSearchIndexJobBatch | null = null;\n\n get batchCount(): number {\n return this.pendingBatch ? 1 : 0;\n }\n\n get jobCount(): number {\n return this.pendingBatch?.jobs.length ?? 0;\n }\n\n get changeCount(): number {\n return this.pendingBatch?.changeCount ?? 0;\n }\n\n enqueue(id: number, context: string, jobs: SearchIndexWorkerJob[]): Promise<void> {\n if (jobs.length === 0) return Promise.resolve();\n\n return new Promise((resolve, reject) => {\n const waiter = { resolve, reject };\n if (this.pendingBatch) {\n this.pendingBatch.merge(context, jobs, waiter);\n } else {\n this.pendingBatch = new PendingSearchIndexJobBatch(id, context, jobs, waiter);\n }\n });\n }\n\n take(): SearchIndexJobBatch | null {\n const batch = this.pendingBatch;\n this.pendingBatch = null;\n return batch;\n }\n\n settle(batch: SearchIndexJobBatch, error?: Error): boolean {\n return batch instanceof PendingSearchIndexJobBatch && batch.settle(error);\n }\n\n rejectAll(error: Error): void {\n const batch = this.take();\n if (batch) this.settle(batch, error);\n }\n}\n\nfunction createPendingChanges(job: ChangesSearchIndexJob): PendingChanges {\n return {\n context: job.context,\n agentName: job.agentName,\n changesBySessionId: new Map(),\n removedSessionIds: new Set(),\n meta: {},\n searchIndexOptions: job.searchIndexOptions,\n };\n}\n\nfunction mergeChanges(pending: PendingChanges, job: ChangesSearchIndexJob): void {\n pending.context = job.context;\n pending.searchIndexOptions = mergeSearchIndexOptions(\n pending.searchIndexOptions,\n job.searchIndexOptions,\n );\n\n for (const sessionId of job.removedSessionIds) {\n pending.changesBySessionId.delete(sessionId);\n pending.removedSessionIds.add(sessionId);\n delete pending.meta[sessionId];\n }\n\n for (const change of job.changes) {\n const sessionId = change.session.id;\n pending.removedSessionIds.delete(sessionId);\n pending.changesBySessionId.set(sessionId, change);\n if (Object.hasOwn(job.meta, sessionId)) pending.meta[sessionId] = job.meta[sessionId]!;\n else delete pending.meta[sessionId];\n }\n\n for (const [sessionId, meta] of Object.entries(job.meta)) {\n if (!pending.removedSessionIds.has(sessionId)) pending.meta[sessionId] = meta;\n }\n}\n\nfunction mergeSearchIndexOptions(\n current: SearchIndexSyncOptions | undefined,\n incoming: SearchIndexSyncOptions | undefined,\n): SearchIndexSyncOptions | undefined {\n if (!current) return incoming;\n if (!incoming) return current;\n return { ...current, ...incoming };\n}\n\nfunction changesJobFromPending(pending: PendingChanges): ChangesSearchIndexJob {\n return {\n kind: \"changes\",\n context: pending.context,\n agentName: pending.agentName,\n changes: [...pending.changesBySessionId.values()],\n removedSessionIds: [...pending.removedSessionIds],\n meta: pending.meta,\n ...(pending.searchIndexOptions ? { searchIndexOptions: pending.searchIndexOptions } : {}),\n };\n}\n","import type { AgentScanProgress } from \"@codesesh/core\";\nimport type { BackfillStatus, ScanStatusEvent } from \"@codesesh/core/contract\";\n\ntype ScanStatus = Omit<ScanStatusEvent, \"type\">;\n\nexport class ScanStatusModel {\n private status: ScanStatus = {\n active: false,\n phase: \"idle\",\n pendingAgents: [],\n scanningAgents: [],\n completedAgents: [],\n agentStatuses: {},\n totalAgents: 0,\n updatedAt: Date.now(),\n backfill: { active: false, pendingAgents: [], completedAgents: [], failedAgents: [] },\n };\n\n snapshot(): ScanStatusEvent {\n const backfill = {\n ...this.status.backfill,\n pendingAgents: [...this.status.backfill.pendingAgents],\n completedAgents: [...this.status.backfill.completedAgents],\n failedAgents: [...this.status.backfill.failedAgents],\n };\n if (this.status.backfill.progress) {\n backfill.progress = { ...this.status.backfill.progress };\n } else {\n delete backfill.progress;\n }\n return {\n type: \"scan-status\",\n ...this.status,\n pendingAgents: [...this.status.pendingAgents],\n scanningAgents: [...this.status.scanningAgents],\n completedAgents: [...this.status.completedAgents],\n agentStatuses: Object.fromEntries(\n Object.entries(this.status.agentStatuses).map(([agentName, status]) => [\n agentName,\n { ...status },\n ]),\n ),\n backfill,\n };\n }\n\n startBatch(\n agentNames: string[],\n phase: ScanStatusEvent[\"phase\"],\n sessionCounts: Record<string, number>,\n ): ScanStatusEvent {\n const uniqueAgentNames = [...new Set(agentNames)];\n const now = Date.now();\n const agentStatuses = Object.fromEntries(\n uniqueAgentNames.map((agentName) => [\n agentName,\n {\n agentName,\n status: \"pending\" as const,\n processed: 0,\n sessions: sessionCounts[agentName] ?? 0,\n updatedAt: now,\n },\n ]),\n );\n return this.set({\n ...this.status,\n active: uniqueAgentNames.length > 0,\n phase: uniqueAgentNames.length > 0 ? phase : \"idle\",\n pendingAgents: uniqueAgentNames,\n scanningAgents: [],\n completedAgents: [],\n agentStatuses,\n totalAgents: uniqueAgentNames.length,\n startedAt: uniqueAgentNames.length > 0 ? now : undefined,\n updatedAt: now,\n completedAt: uniqueAgentNames.length > 0 ? undefined : now,\n });\n }\n\n setPhase(phase: ScanStatusEvent[\"phase\"]): ScanStatusEvent | null {\n if (!this.status.active) return null;\n return this.set({ ...this.status, phase, updatedAt: Date.now() });\n }\n\n beginAgent(agentName: string, sessionCount: number): ScanStatusEvent {\n if (!this.status.active)\n this.startBatch([agentName], \"scanning\", { [agentName]: sessionCount });\n\n const pendingAgents = this.status.pendingAgents.filter((agent) => agent !== agentName);\n const scanningAgents = [...new Set([...this.status.scanningAgents, agentName])];\n const completedAgents = this.status.completedAgents.filter((agent) => agent !== agentName);\n const existingStatus = this.status.agentStatuses[agentName];\n const now = Date.now();\n return this.set({\n ...this.status,\n active: true,\n phase: this.status.phase === \"initializing\" ? \"initializing\" : \"scanning\",\n pendingAgents,\n scanningAgents,\n completedAgents,\n agentStatuses: {\n ...this.status.agentStatuses,\n [agentName]: {\n agentName,\n status: \"scanning\",\n total: existingStatus?.total,\n processed: existingStatus?.processed ?? 0,\n sessions: existingStatus?.sessions ?? sessionCount,\n startedAt: existingStatus?.startedAt ?? now,\n updatedAt: now,\n },\n },\n totalAgents: Math.max(this.status.totalAgents, pendingAgents.length + scanningAgents.length),\n updatedAt: now,\n completedAt: undefined,\n });\n }\n\n updateAgent(agentName: string, progress: AgentScanProgress): ScanStatusEvent | null {\n const status = this.status.agentStatuses[agentName];\n if (\n !status ||\n status.status === \"pending\" ||\n status.status === \"complete\" ||\n (status.status === \"indexing\" && progress.phase !== \"finalizing\")\n ) {\n return null;\n }\n const now = Date.now();\n const nextStatus: \"finalizing\" | \"scanning\" =\n progress.phase === \"finalizing\" ? \"finalizing\" : \"scanning\";\n const agentStatuses = {\n ...this.status.agentStatuses,\n [agentName]: {\n ...status,\n status: nextStatus,\n total: progress.total ?? status.total,\n processed: progress.processed ?? status.processed,\n sessions: progress.sessions ?? status.sessions,\n updatedAt: now,\n },\n };\n return this.set({\n ...this.status,\n phase: this.activePhase(this.status.pendingAgents, this.status.scanningAgents, agentStatuses),\n agentStatuses,\n updatedAt: now,\n });\n }\n\n indexAgent(agentName: string): ScanStatusEvent | null {\n const status = this.status.agentStatuses[agentName];\n if (\n !this.status.active ||\n !status ||\n (status.status !== \"scanning\" && status.status !== \"finalizing\")\n ) {\n return null;\n }\n\n const now = Date.now();\n const agentStatuses = {\n ...this.status.agentStatuses,\n [agentName]: { ...status, status: \"indexing\" as const, updatedAt: now },\n };\n return this.set({\n ...this.status,\n phase: this.activePhase(this.status.pendingAgents, this.status.scanningAgents, agentStatuses),\n agentStatuses,\n updatedAt: now,\n });\n }\n\n finishAgent(agentName: string, sessionCount?: number): ScanStatusEvent {\n const pendingAgents = this.status.pendingAgents.filter((agent) => agent !== agentName);\n const scanningAgents = this.status.scanningAgents.filter((agent) => agent !== agentName);\n const completedAgents = [...new Set([...this.status.completedAgents, agentName])];\n const isActive = pendingAgents.length > 0 || scanningAgents.length > 0;\n const now = Date.now();\n const previousStatus = this.status.agentStatuses[agentName];\n const total = previousStatus?.total ?? previousStatus?.processed;\n const agentStatuses = {\n ...this.status.agentStatuses,\n [agentName]: {\n agentName,\n status: \"complete\" as const,\n total,\n processed: total,\n sessions: sessionCount ?? previousStatus?.sessions ?? 0,\n startedAt: previousStatus?.startedAt,\n updatedAt: now,\n completedAt: now,\n },\n };\n\n return this.set({\n ...this.status,\n active: isActive,\n phase: isActive ? this.activePhase(pendingAgents, scanningAgents, agentStatuses) : \"idle\",\n pendingAgents,\n scanningAgents,\n completedAgents,\n agentStatuses,\n updatedAt: now,\n completedAt: isActive ? undefined : now,\n });\n }\n\n finishBatch(): ScanStatusEvent {\n const now = Date.now();\n return this.set({\n ...this.status,\n active: false,\n phase: \"idle\",\n pendingAgents: [],\n scanningAgents: [],\n agentStatuses: Object.fromEntries(\n Object.entries(this.status.agentStatuses).map(([agentName, status]) => [\n agentName,\n { ...status, status: \"complete\", completedAt: status.completedAt ?? now, updatedAt: now },\n ]),\n ),\n updatedAt: now,\n completedAt: now,\n });\n }\n\n updateBackfill(patch: Partial<BackfillStatus>): ScanStatusEvent {\n return this.set({\n ...this.status,\n backfill: { ...this.status.backfill, ...patch },\n updatedAt: Date.now(),\n });\n }\n\n private activePhase(\n pendingAgents: string[],\n scanningAgents: string[],\n agentStatuses: ScanStatus[\"agentStatuses\"],\n ): ScanStatusEvent[\"phase\"] {\n if (\n pendingAgents.length === 0 &&\n scanningAgents.length > 0 &&\n scanningAgents.every((agentName) => {\n const status = agentStatuses[agentName]?.status;\n return status === \"finalizing\" || status === \"indexing\";\n })\n ) {\n return \"indexing\";\n }\n return this.status.phase === \"initializing\" ? \"initializing\" : \"scanning\";\n }\n\n private set(status: ScanStatus): ScanStatusEvent {\n this.status = status;\n return this.snapshot();\n }\n}\n","import {\n FileSystemSessionSource,\n attachMissingProjectIdentities,\n buildAgentCacheMeta,\n getAgentFullSyncCursor,\n computeSessionDiff,\n getAgentLastFullSyncAt,\n isAgentCacheInitialized,\n loadCachedSessions,\n markAgentCacheInitialized,\n markAgentFullSyncProgress,\n markAgentFullSyncStarted,\n markAgentFullSyncCompleted,\n saveCachedSessionChanges,\n saveCachedSessions,\n sessionSignature,\n type AgentScanProgress,\n type BaseAgent,\n type ScanOptions,\n type LiveSnapshot,\n type SessionHead,\n type SessionHeadChange,\n} from \"@codesesh/core\";\nimport type {\n BackfillProgress,\n BackfillStatus,\n ScanStatusEvent,\n SessionsUpdatedEvent,\n} from \"@codesesh/core/contract\";\nimport { AgentOperationScheduler, type AgentOperationResult } from \"./agent-operation-scheduler.js\";\nimport { LiveSessionIndex, type LiveSessionIndexOptions } from \"./live-session-index.js\";\nimport { appLogger, logSearchIndexSync } from \"./logging.js\";\nimport { SearchIndexJobRunner } from \"./search-index-job-runner.js\";\nimport type { SearchIndexWorkerJob } from \"./search-index-worker.js\";\nimport { ScanStatusModel } from \"./scan-status-model.js\";\nimport type { ScanRefreshWorkerCheckpoint } from \"./scan-refresh-worker.js\";\nimport type { WorkerRunner } from \"./worker-runner.js\";\n\nexport type { AgentOperationResult } from \"./agent-operation-scheduler.js\";\n\nexport interface AgentSessionsChanged {\n agentName: string;\n sessions: SessionHead[];\n event: SessionsUpdatedEvent | null;\n}\n\nexport interface AgentSyncEngineOptions {\n startupScanOptions?: Pick<ScanOptions, \"from\" | \"to\">;\n workerRunner: WorkerRunner;\n}\n\nexport interface AgentSyncEngineInitializationOptions extends LiveSessionIndexOptions {\n cacheTimestamps?: Record<string, number>;\n}\n\ntype SessionsChangedListener = (change: AgentSessionsChanged) => void;\ntype StatusChangedListener = (event: ScanStatusEvent) => void;\ntype CachedSessions = NonNullable<ReturnType<typeof loadCachedSessions>>;\n\ninterface SessionPersistenceDiff {\n changedSessions: SessionHeadChange[];\n removedSessionIds: string[];\n}\n\ninterface SessionPublication {\n context: \"scan.refresh\" | \"scan.backfill\";\n agentName: string;\n sessions: SessionHead[];\n candidateChangedIds: string[];\n indexJob: SearchIndexWorkerJob;\n}\n\ninterface SessionPublicationResult {\n event: SessionsUpdatedEvent | null;\n diffDuration: number;\n}\n\ninterface RefreshStrategyResult {\n status: \"continue\" | \"unchanged\";\n nextSessions: SessionHead[];\n fullScanSessions: SessionHead[] | null;\n preciseChangedIds: string[] | null;\n persistenceDiff: SessionPersistenceDiff | null;\n checkDuration: number;\n scanDuration: number;\n}\n\nconst REFRESH_DEBOUNCE_MS = 200;\nconst EMPTY_AGENT_REFRESH_DEBOUNCE_MS = 30_000;\nconst SEARCH_INDEX_BULK_PENDING_PATH_THRESHOLD = 100;\nconst BACKFILL_INTERVAL_MS = 24 * 60 * 60 * 1000;\nconst CACHE_TRUNCATION_COVERAGE = 0.5;\n\nfunction buildPersistenceDiff(\n previousSessions: SessionHead[],\n nextSessions: SessionHead[],\n candidateChangedIds: string[] = [],\n): SessionPersistenceDiff {\n const { changes, removedSessionIds } = computeSessionDiff(\n previousSessions,\n nextSessions,\n candidateChangedIds,\n sessionSignature,\n );\n return { changedSessions: changes, removedSessionIds };\n}\n\nfunction restoreAgentCacheMeta(agent: BaseAgent, cached: CachedSessions): void {\n agent.setSessionMetaMap(new Map(Object.entries(cached.meta)));\n}\n\nexport class AgentSyncEngine {\n private lastRefreshAtByAgent = new Map<string, number>();\n private readonly scheduler: AgentOperationScheduler;\n private readonly sessionIndex = new LiveSessionIndex();\n private backfillQueue: string[] = [];\n private currentBackfillAgent: string | undefined;\n private currentBackfillProgress: BackfillProgress | undefined;\n private cacheIntegrityCheckedAgents = new Set<string>();\n private completedBackfillAgents: string[] = [];\n private failedBackfillAgents: string[] = [];\n private sessionsChangedListeners = new Set<SessionsChangedListener>();\n private statusChangedListeners = new Set<StatusChangedListener>();\n private scanStatus = new ScanStatusModel();\n private searchIndexJobs = new SearchIndexJobRunner();\n private nextPublicationId = 1;\n private backgroundRefreshTimer: NodeJS.Timeout | null = null;\n private isShuttingDown = false;\n\n constructor(private readonly options: AgentSyncEngineOptions) {\n this.scheduler = new AgentOperationScheduler((agentName) => this.performRefresh(agentName));\n }\n\n initialize(snapshot: LiveSnapshot, options: AgentSyncEngineInitializationOptions = {}): void {\n this.sessionIndex.initialize(snapshot, options);\n this.lastRefreshAtByAgent.clear();\n for (const agent of this.sessionIndex.snapshot().agents) {\n this.lastRefreshAtByAgent.set(\n agent.name,\n options.cacheTimestamps?.[agent.name] ?? Date.now(),\n );\n }\n }\n\n snapshot(): LiveSnapshot {\n return this.sessionIndex.snapshot();\n }\n\n status(): ScanStatusEvent {\n return this.scanStatus.snapshot();\n }\n\n subscribeSessionsChanged(listener: SessionsChangedListener): () => void {\n this.sessionsChangedListeners.add(listener);\n return () => this.sessionsChangedListeners.delete(listener);\n }\n\n subscribeStatusChanged(listener: StatusChangedListener): () => void {\n this.statusChangedListeners.add(listener);\n return () => this.statusChangedListeners.delete(listener);\n }\n\n async syncInitialIndex(): Promise<void> {\n const jobs = this.buildFullSearchIndexJobs(\"scan.initial\");\n await this.commitSearchIndex(\"scan.initial\", jobs, {\n publicationId: this.publicationId(\"scan.initial\"),\n agents: jobs.map((job) => job.agentName),\n });\n }\n\n handleAgentsChanged(agentNames: Iterable<string>): void {\n const snapshot = this.sessionIndex.snapshot();\n for (const agentName of agentNames) {\n const delayMs =\n (snapshot.byAgent[agentName]?.length ?? 0) === 0\n ? EMPTY_AGENT_REFRESH_DEBOUNCE_MS\n : REFRESH_DEBOUNCE_MS;\n this.scheduler.notify(agentName, delayMs);\n }\n }\n\n startBackgroundRefresh(): void {\n if (this.backgroundRefreshTimer) return;\n const agentNames = this.sessionIndex.snapshot().agents.map((agent) => agent.name);\n this.startScanBatch(agentNames, \"scanning\");\n this.backgroundRefreshTimer = setTimeout(() => {\n this.backgroundRefreshTimer = null;\n for (const agentName of agentNames) this.scheduler.schedule(agentName, 0);\n if (agentNames.length === 0) this.finishScanBatch();\n }, 0);\n }\n\n async refresh(agentName: string): Promise<void> {\n await this.scheduler.refresh(agentName);\n }\n\n async shutdown(): Promise<void> {\n this.isShuttingDown = true;\n const schedulerSnapshot = this.scheduler.snapshot();\n const activeOperations = {\n agent_operations: schedulerSnapshot.activeOperations,\n refreshes: schedulerSnapshot.activeRefreshes,\n backfill_running: this.currentBackfillAgent != null || undefined,\n scan_workers: this.options.workerRunner.activeCount,\n };\n if (activeOperations.agent_operations > 0 || activeOperations.scan_workers > 0) {\n appLogger.warn(\"scan.shutdown.active_operations\", activeOperations);\n }\n this.scheduler.stop();\n if (this.backgroundRefreshTimer) {\n clearTimeout(this.backgroundRefreshTimer);\n this.backgroundRefreshTimer = null;\n }\n this.backfillQueue.length = 0;\n this.currentBackfillAgent = undefined;\n this.currentBackfillProgress = undefined;\n this.cacheIntegrityCheckedAgents.clear();\n const searchIndexSnapshot = this.searchIndexJobs.snapshot();\n appLogger.info(\"search_index.shutdown.started\", {\n active_batch_id: searchIndexSnapshot.activeBatchId,\n pending_batches: searchIndexSnapshot.pendingBatches,\n });\n await this.searchIndexJobs.shutdown();\n await this.options.workerRunner.shutdown();\n await this.scheduler.waitForIdle();\n const stoppedSearchIndexSnapshot = this.searchIndexJobs.snapshot();\n appLogger.info(\"search_index.shutdown.completed\", {\n active_batch_id: searchIndexSnapshot.activeBatchId,\n pending_batches: stoppedSearchIndexSnapshot.pendingBatches,\n });\n }\n\n private startScanBatch(agentNames: string[], phase: ScanStatusEvent[\"phase\"]): void {\n const snapshot = this.sessionIndex.snapshot();\n const sessionCounts = Object.fromEntries(\n agentNames.map((agentName) => [agentName, snapshot.byAgent[agentName]?.length ?? 0]),\n );\n this.publishStatus(this.scanStatus.startBatch(agentNames, phase, sessionCounts));\n }\n\n private setScanPhase(phase: ScanStatusEvent[\"phase\"]): void {\n this.publishStatus(this.scanStatus.setPhase(phase));\n }\n\n private beginAgentScan(agentName: string): void {\n const snapshot = this.sessionIndex.snapshot();\n if (!this.scanStatus.snapshot().active) this.startScanBatch([agentName], \"scanning\");\n this.publishStatus(\n this.scanStatus.beginAgent(agentName, snapshot.byAgent[agentName]?.length ?? 0),\n );\n }\n\n private updateAgentScanProgress(agentName: string, progress: AgentScanProgress): void {\n if (this.currentBackfillAgent === agentName) {\n this.currentBackfillProgress = {\n phase: progress.phase,\n total: progress.total,\n processed: progress.processed,\n sessions: progress.sessions,\n };\n this.publishBackfillStatus();\n return;\n }\n this.publishStatus(this.scanStatus.updateAgent(agentName, progress));\n }\n\n private beginAgentIndexing(agentName: string): void {\n this.publishStatus(this.scanStatus.indexAgent(agentName));\n }\n\n private finishAgentScan(agentName: string): void {\n const count = this.sessionIndex.snapshot().byAgent[agentName]?.length;\n this.publishStatus(this.scanStatus.finishAgent(agentName, count));\n }\n\n private finishScanBatch(): void {\n this.publishStatus(this.scanStatus.finishBatch());\n }\n\n private publishBackfillStatus(): void {\n this.publishStatus(this.scanStatus.updateBackfill(this.backfillStatus()));\n }\n\n private publishStatus(event: ScanStatusEvent | null): void {\n if (!event || this.isShuttingDown) return;\n for (const listener of this.statusChangedListeners) listener(event);\n }\n\n private emitSessionsChanged(change: AgentSessionsChanged): void {\n if (this.isShuttingDown) return;\n for (const listener of this.sessionsChangedListeners) listener(change);\n }\n\n private async performRefresh(agentName: string): Promise<AgentOperationResult> {\n this.beginAgentScan(agentName);\n try {\n return await this.runRefresh(agentName);\n } catch (error) {\n appLogger.error(\"scan.refresh.error\", { agent: agentName, error });\n console.error(`[${agentName}] Session refresh failed:`, error);\n return \"failed\";\n } finally {\n this.finishAgentScan(agentName);\n const agent = this.findAgent(agentName);\n if (agent && this.needsBackfill(agent)) this.enqueueBackfill(agentName);\n }\n }\n\n private async runRefresh(agentName: string): Promise<Exclude<AgentOperationResult, \"failed\">> {\n const startedAt = performance.now();\n const pendingPathCount = this.scheduler.takePendingSignalCount(agentName);\n const agent = this.findAgent(agentName);\n if (!agent) {\n appLogger.warn(\"scan.refresh.missing_agent\", { agent: agentName });\n return \"skipped\";\n }\n const previousSessions = this.sessionIndex.snapshot().byAgent[agentName] ?? [];\n const cached = loadCachedSessions(agentName);\n const refreshBaseline = cached?.sessions ?? previousSessions;\n const cacheTimestamp = cached?.timestamp ?? this.lastRefreshAtByAgent.get(agentName) ?? 0;\n if (cached) restoreAgentCacheMeta(agent, cached);\n const isInitialized = isAgentCacheInitialized(agentName);\n const availabilityStartedAt = performance.now();\n const isAvailable = agent.isAvailable();\n const availabilityDuration = performance.now() - availabilityStartedAt;\n let strategyResult: RefreshStrategyResult;\n if (!isAvailable) {\n strategyResult = this.refreshUnavailableAgent(agentName);\n } else if (!isInitialized) {\n strategyResult = await this.initializeAgent(agent, previousSessions);\n } else if (cached && agent instanceof FileSystemSessionSource) {\n strategyResult = await this.syncAgentSources(agent, cached, startedAt);\n } else if (refreshBaseline.length > 0) {\n strategyResult = await this.refreshChangedAgent(\n agent,\n refreshBaseline,\n cacheTimestamp,\n startedAt,\n );\n } else {\n strategyResult = await this.scanAgentFully(agent, previousSessions);\n }\n if (strategyResult.status === \"unchanged\") return \"unchanged\";\n\n const nextSessions = attachMissingProjectIdentities(strategyResult.nextSessions);\n const searchIndexOptions =\n pendingPathCount >= SEARCH_INDEX_BULK_PENDING_PATH_THRESHOLD ? { isBulk: true } : undefined;\n const persistenceDiff = strategyResult.persistenceDiff;\n const changedSessionIds = persistenceDiff\n ? new Set(persistenceDiff.changedSessions.map(({ session }) => session.id))\n : undefined;\n const persistStartedAt = performance.now();\n const persistentJob: SearchIndexWorkerJob = persistenceDiff\n ? {\n kind: \"changes\",\n context: \"scan.refresh\",\n agentName,\n changes: persistenceDiff.changedSessions,\n removedSessionIds: persistenceDiff.removedSessionIds,\n meta: buildAgentCacheMeta(agent, changedSessionIds),\n ...(searchIndexOptions ? { searchIndexOptions } : {}),\n }\n : {\n kind: \"full\",\n context: \"scan.refresh\",\n agentName,\n sessions: strategyResult.fullScanSessions ?? nextSessions,\n meta: buildAgentCacheMeta(agent),\n saveCache: true,\n ...(searchIndexOptions ? { searchIndexOptions } : {}),\n };\n this.beginAgentIndexing(agentName);\n const publication = await this.commitSessionPublication({\n context: \"scan.refresh\",\n agentName,\n sessions: nextSessions,\n candidateChangedIds: strategyResult.preciseChangedIds ?? [],\n indexJob: persistentJob,\n });\n const persistDuration = performance.now() - persistStartedAt;\n logSearchIndexSync(\"scan.refresh\", null, { pending_paths: pendingPathCount });\n\n const totalDurationMs = performance.now() - startedAt;\n this.scheduler.recordRefreshDuration(agentName, totalDurationMs);\n appLogger.info(\"scan.refresh.done\", {\n agent: agentName,\n duration_ms: Math.round(totalDurationMs),\n sessions: nextSessions.length,\n new_sessions: publication.event?.newSessions ?? 0,\n updated_sessions: publication.event?.updatedSessions ?? 0,\n removed_sessions: publication.event?.removedSessions ?? 0,\n pending_paths: pendingPathCount,\n availability_ms: Math.round(availabilityDuration),\n check_ms: Math.round(strategyResult.checkDuration),\n scan_ms: Math.round(strategyResult.scanDuration),\n diff_ms: Math.round(publication.diffDuration),\n persist_ms: Math.round(persistDuration),\n search_index_ms: Math.round(persistDuration),\n persistent_index_worker_job: persistentJob.kind,\n });\n return \"committed\";\n }\n\n /**\n * An agent that cannot be reached was never scanned, so there is nothing to\n * compare against. Publishing an empty result here would diff every known\n * session into a removal — the same mistake as reading a failed query as an\n * empty database.\n */\n private refreshUnavailableAgent(agentName: string): RefreshStrategyResult {\n this.lastRefreshAtByAgent.set(agentName, Date.now());\n const previousSessions = this.sessionIndex.snapshot().byAgent[agentName] ?? [];\n if (previousSessions.length > 0) {\n appLogger.warn(\"scan.refresh.agent_unavailable\", {\n agent: agentName,\n retained_sessions: previousSessions.length,\n });\n return this.refreshStrategyResult(previousSessions, { status: \"unchanged\" });\n }\n return this.refreshStrategyResult([]);\n }\n\n private async initializeAgent(\n agent: BaseAgent,\n previousSessions: SessionHead[],\n ): Promise<RefreshStrategyResult> {\n this.setScanPhase(\"initializing\");\n const scanStartedAt = performance.now();\n const result = await this.runWorker(agent, previousSessions, null, this.startupScanOptions(), {\n checkpoint: true,\n });\n agent.setSessionMetaMap(new Map(Object.entries(result.meta)));\n const sessions = attachMissingProjectIdentities(result.sessions);\n this.lastRefreshAtByAgent.set(agent.name, Date.now());\n return this.refreshStrategyResult(sessions, {\n fullScanSessions: sessions,\n scanDuration: performance.now() - scanStartedAt,\n });\n }\n\n private async syncAgentSources(\n agent: FileSystemSessionSource,\n cached: CachedSessions,\n refreshStartedAt: number,\n ): Promise<RefreshStrategyResult> {\n const scanStartedAt = performance.now();\n const result = await this.runWorker(agent, cached.sessions, null, this.startupScanOptions(), {\n sourceSync: true,\n meta: cached.meta,\n });\n agent.setSessionMetaMap(new Map(Object.entries(result.meta)));\n const sessions = attachMissingProjectIdentities(result.sessions);\n const preciseChangedIds = result.changedIds ?? [];\n const persistenceDiff = buildPersistenceDiff(cached.sessions, sessions, preciseChangedIds);\n this.lastRefreshAtByAgent.set(agent.name, Date.now());\n if (\n persistenceDiff.changedSessions.length === 0 &&\n persistenceDiff.removedSessionIds.length === 0\n ) {\n this.logUnchangedRefresh(agent.name, refreshStartedAt);\n return this.refreshStrategyResult(sessions, {\n status: \"unchanged\",\n scanDuration: performance.now() - scanStartedAt,\n });\n }\n return this.refreshStrategyResult(sessions, {\n preciseChangedIds,\n persistenceDiff,\n scanDuration: performance.now() - scanStartedAt,\n });\n }\n\n private async refreshChangedAgent(\n agent: BaseAgent,\n baseline: SessionHead[],\n cacheTimestamp: number,\n refreshStartedAt: number,\n ): Promise<RefreshStrategyResult> {\n const checkStartedAt = performance.now();\n const checkResult = await Promise.resolve(agent.checkForChanges(cacheTimestamp, baseline));\n const checkDuration = performance.now() - checkStartedAt;\n this.lastRefreshAtByAgent.set(agent.name, checkResult.timestamp);\n if (!checkResult.hasChanges) {\n this.logUnchangedRefresh(agent.name, refreshStartedAt);\n return this.refreshStrategyResult(baseline, { status: \"unchanged\", checkDuration });\n }\n const preciseChangedIds = checkResult.changedIds ?? null;\n const scanStartedAt = performance.now();\n if (preciseChangedIds === null) {\n const result = await this.runWorker(agent, baseline, null, {}, { checkpoint: true });\n agent.setSessionMetaMap(new Map(Object.entries(result.meta)));\n const sessions = attachMissingProjectIdentities(result.sessions);\n return this.refreshStrategyResult(sessions, {\n persistenceDiff: buildPersistenceDiff(baseline, sessions),\n checkDuration,\n scanDuration: performance.now() - scanStartedAt,\n });\n }\n const sessions = attachMissingProjectIdentities(\n await Promise.resolve(agent.incrementalScan(baseline, preciseChangedIds, checkResult.refs)),\n );\n return this.refreshStrategyResult(sessions, {\n preciseChangedIds,\n persistenceDiff: buildPersistenceDiff(baseline, sessions, preciseChangedIds),\n checkDuration,\n scanDuration: performance.now() - scanStartedAt,\n });\n }\n\n private async scanAgentFully(\n agent: BaseAgent,\n previousSessions: SessionHead[],\n ): Promise<RefreshStrategyResult> {\n const scanStartedAt = performance.now();\n const result = await this.runWorker(agent, previousSessions, null, {}, { checkpoint: true });\n agent.setSessionMetaMap(new Map(Object.entries(result.meta)));\n const sessions = attachMissingProjectIdentities(result.sessions);\n this.lastRefreshAtByAgent.set(agent.name, Date.now());\n return this.refreshStrategyResult(sessions, {\n fullScanSessions: sessions,\n scanDuration: performance.now() - scanStartedAt,\n });\n }\n\n private refreshStrategyResult(\n nextSessions: SessionHead[],\n overrides: Partial<Omit<RefreshStrategyResult, \"nextSessions\">> = {},\n ): RefreshStrategyResult {\n return {\n status: \"continue\",\n nextSessions,\n fullScanSessions: null,\n preciseChangedIds: null,\n persistenceDiff: null,\n checkDuration: 0,\n scanDuration: 0,\n ...overrides,\n };\n }\n\n private runWorker(\n agent: BaseAgent,\n previousSessions: SessionHead[],\n changedIds: string[] | null,\n scanOptions: Pick<ScanOptions, \"from\" | \"to\" | \"fast\">,\n workerOptions: {\n sourceSync?: boolean;\n backfill?: boolean;\n backfillCursor?: string | null;\n checkpoint?: boolean;\n meta?: CachedSessions[\"meta\"];\n } = {},\n ) {\n return this.options.workerRunner.run(agent.name, {\n previousSessions,\n changedIds,\n scanOptions,\n sourceSync: workerOptions.sourceSync,\n backfill: workerOptions.backfill,\n backfillCursor: workerOptions.backfillCursor,\n checkpoint: workerOptions.checkpoint,\n meta: workerOptions.meta ?? buildAgentCacheMeta(agent),\n onProgress: (progress) => this.updateAgentScanProgress(agent.name, progress),\n onCheckpoint: (checkpoint) => this.handleWorkerCheckpoint(agent, checkpoint),\n });\n }\n\n private handleWorkerCheckpoint(agent: BaseAgent, checkpoint: ScanRefreshWorkerCheckpoint): void {\n if (this.isShuttingDown) return;\n\n if (checkpoint.stage === \"scanned\") {\n let persisted = false;\n try {\n persisted = saveCachedSessions(agent.name, checkpoint.sessions, checkpoint.meta);\n if (persisted) markAgentCacheInitialized(agent.name);\n } catch (error) {\n appLogger.error(\"scan.checkpoint.failed\", {\n agent: agent.name,\n stage: checkpoint.stage,\n error,\n });\n }\n agent.setSessionMetaMap(new Map(Object.entries(checkpoint.meta)));\n\n const event = this.sessionIndex.commitAgentSessions(agent.name, checkpoint.sessions);\n this.emitSessionsChanged({\n agentName: agent.name,\n sessions: this.sessionIndex.snapshot().byAgent[agent.name] ?? [],\n event,\n });\n appLogger.info(\"scan.checkpoint.persisted\", {\n agent: agent.name,\n stage: checkpoint.stage,\n sessions: checkpoint.sessions.length,\n persisted,\n });\n return;\n }\n\n let persisted = false;\n try {\n persisted = saveCachedSessionChanges(agent.name, checkpoint.changes, [], checkpoint.meta);\n } catch (error) {\n appLogger.error(\"scan.checkpoint.failed\", {\n agent: agent.name,\n stage: checkpoint.stage,\n sessions: checkpoint.changes.length,\n error,\n });\n }\n if (persisted && checkpoint.backfillCursor) {\n markAgentFullSyncProgress(agent.name, checkpoint.backfillCursor);\n }\n appLogger.debug(\"scan.checkpoint.persisted\", {\n agent: agent.name,\n stage: checkpoint.stage,\n sessions: checkpoint.changes.length,\n backfill_cursor: checkpoint.backfillCursor,\n persisted,\n });\n }\n\n private needsBackfill(agent: BaseAgent): boolean {\n const startupScanOptions = this.startupScanOptions();\n if (startupScanOptions.from == null && startupScanOptions.to == null) return false;\n if (!agent.isAvailable()) return false;\n const lastSyncAt = getAgentLastFullSyncAt(agent.name);\n if (lastSyncAt == null || Date.now() - lastSyncAt > BACKFILL_INTERVAL_MS) return true;\n if (!(agent instanceof FileSystemSessionSource)) return false;\n if (this.cacheIntegrityCheckedAgents.has(agent.name)) return false;\n\n const cached = loadCachedSessions(agent.name);\n const sourceCount = agent.listSessionSources().length;\n const cachedCount = cached?.sessions.length ?? 0;\n this.cacheIntegrityCheckedAgents.add(agent.name);\n if (sourceCount > 0 && cachedCount / sourceCount < CACHE_TRUNCATION_COVERAGE) {\n appLogger.warn(\"scan.backfill.cache_truncated\", {\n agent: agent.name,\n cached_sessions: cachedCount,\n source_files: sourceCount,\n last_sync_at: lastSyncAt,\n });\n return true;\n }\n return false;\n }\n\n private enqueueBackfill(agentName: string): void {\n if (\n this.isShuttingDown ||\n this.currentBackfillAgent === agentName ||\n this.backfillQueue.includes(agentName)\n ) {\n return;\n }\n this.backfillQueue.push(agentName);\n this.publishBackfillStatus();\n this.pumpBackfillQueue();\n }\n\n private pumpBackfillQueue(): void {\n if (this.isShuttingDown || this.currentBackfillAgent) return;\n const agentName = this.backfillQueue.shift();\n if (!agentName) return;\n this.currentBackfillAgent = agentName;\n this.currentBackfillProgress = undefined;\n this.publishBackfillStatus();\n void this.runBackfill(agentName).then((result) => {\n if (this.isShuttingDown) return;\n this.currentBackfillAgent = undefined;\n this.currentBackfillProgress = undefined;\n if (result === \"committed\") {\n if (!this.completedBackfillAgents.includes(agentName)) {\n this.completedBackfillAgents.push(agentName);\n }\n this.failedBackfillAgents = this.failedBackfillAgents.filter(\n (failedAgent) => failedAgent !== agentName,\n );\n } else if (!this.failedBackfillAgents.includes(agentName)) {\n this.failedBackfillAgents.push(agentName);\n this.cacheIntegrityCheckedAgents.delete(agentName);\n }\n this.publishBackfillStatus();\n this.pumpBackfillQueue();\n });\n }\n\n private runBackfill(agentName: string): Promise<AgentOperationResult> {\n return this.scheduler.run(agentName, \"backfill\", () => this.performBackfill(agentName));\n }\n\n private async performBackfill(agentName: string): Promise<AgentOperationResult> {\n const startedAt = performance.now();\n const agent = this.findAgent(agentName);\n if (!agent || !agent.isAvailable()) return \"skipped\";\n const snapshot = this.sessionIndex.snapshot();\n const cached = loadCachedSessions(agentName);\n const baseline = cached?.sessions ?? snapshot.byAgent[agentName] ?? [];\n const meta = cached?.meta ?? buildAgentCacheMeta(agent);\n const backfillCursor = getAgentFullSyncCursor(agentName);\n if (cached) restoreAgentCacheMeta(agent, cached);\n try {\n markAgentFullSyncStarted(agentName);\n const result = await this.runWorker(\n agent,\n baseline,\n null,\n {},\n {\n sourceSync: agent instanceof FileSystemSessionSource,\n backfill: true,\n backfillCursor,\n meta,\n checkpoint: true,\n },\n );\n agent.setSessionMetaMap(new Map(Object.entries(result.meta)));\n const fullSessions = attachMissingProjectIdentities(result.sessions);\n this.currentBackfillProgress = { phase: \"indexing\", sessions: fullSessions.length };\n this.publishBackfillStatus();\n await this.commitSessionPublication({\n context: \"scan.backfill\",\n agentName,\n sessions: fullSessions,\n candidateChangedIds: result.changedIds ?? [],\n indexJob: {\n kind: \"full\",\n context: \"scan.backfill\",\n agentName,\n sessions: fullSessions,\n meta: buildAgentCacheMeta(agent),\n saveCache: true,\n },\n });\n markAgentFullSyncCompleted(agentName);\n appLogger.info(\"scan.backfill.done\", {\n agent: agentName,\n duration_ms: Math.round(performance.now() - startedAt),\n sessions: fullSessions.length,\n changed: result.changedIds?.length ?? 0,\n });\n return \"committed\";\n } catch (error) {\n appLogger.error(\"scan.backfill.error\", { agent: agentName, error });\n console.error(`[${agentName}] Backfill failed:`, error);\n return \"failed\";\n }\n }\n\n private backfillStatus(): BackfillStatus {\n return {\n active: this.currentBackfillAgent != null || this.backfillQueue.length > 0,\n pendingAgents: [...this.backfillQueue],\n currentAgent: this.currentBackfillAgent,\n progress: this.currentBackfillProgress,\n completedAgents: [...this.completedBackfillAgents],\n failedAgents: [...this.failedBackfillAgents],\n };\n }\n\n private buildFullSearchIndexJobs(context: string): SearchIndexWorkerJob[] {\n const snapshot = this.sessionIndex.snapshot();\n return snapshot.agents.map((agent) => {\n const cached = loadCachedSessions(agent.name);\n return cached\n ? {\n kind: \"full\",\n context,\n agentName: agent.name,\n sessions: cached.sessions,\n meta: cached.meta,\n }\n : {\n kind: \"full\",\n context,\n agentName: agent.name,\n sessions: snapshot.byAgent[agent.name] ?? [],\n meta: buildAgentCacheMeta(agent),\n };\n });\n }\n\n private publicationId(context: string, agentName?: string): string {\n const id = this.nextPublicationId++;\n return agentName ? `${context}:${agentName}:${id}` : `${context}:${id}`;\n }\n\n private async commitSearchIndex(\n context: string,\n jobs: SearchIndexWorkerJob[],\n details: { publicationId: string; agent?: string; agents?: string[] },\n ): Promise<void> {\n appLogger.info(\"session.publication.prepared\", {\n publication_id: details.publicationId,\n context,\n agent: details.agent,\n agents: details.agents,\n jobs: jobs.length,\n });\n try {\n await this.searchIndexJobs.enqueue(context, jobs);\n } catch (error) {\n appLogger.error(\"session.publication.failed\", {\n publication_id: details.publicationId,\n context,\n agent: details.agent,\n stage: \"search_index\",\n error,\n });\n throw error;\n }\n appLogger.info(\"session.publication.index_committed\", {\n publication_id: details.publicationId,\n context,\n agent: details.agent,\n });\n }\n\n private async commitSessionPublication(\n publication: SessionPublication,\n ): Promise<SessionPublicationResult> {\n const publicationId = this.publicationId(publication.context, publication.agentName);\n await this.commitSearchIndex(publication.context, [publication.indexJob], {\n publicationId,\n agent: publication.agentName,\n });\n const diffStartedAt = performance.now();\n const event = this.sessionIndex.commitAgentSessions(\n publication.agentName,\n publication.sessions,\n publication.candidateChangedIds,\n );\n const diffDuration = performance.now() - diffStartedAt;\n this.emitSessionsChanged({\n agentName: publication.agentName,\n sessions: this.sessionIndex.snapshot().byAgent[publication.agentName] ?? [],\n event,\n });\n appLogger.info(\"session.publication.published\", {\n publication_id: publicationId,\n context: publication.context,\n agent: publication.agentName,\n sessions: publication.sessions.length,\n has_event: event != null,\n });\n return { event, diffDuration };\n }\n\n private findAgent(agentName: string): BaseAgent | undefined {\n return this.sessionIndex.findAgent(agentName);\n }\n\n private startupScanOptions(): Pick<ScanOptions, \"from\" | \"to\"> {\n return this.options.startupScanOptions ?? {};\n }\n\n private logUnchangedRefresh(agentName: string, startedAt: number): void {\n appLogger.debug(\"scan.refresh.unchanged\", {\n agent: agentName,\n duration_ms: Math.round(performance.now() - startedAt),\n });\n }\n}\n","/**\n * SessionWatcher — a deep module that hides platform-specific file watching\n * (recursive watch availability, non-recursive fallback trees, write-stability\n * polling, debounce) behind a tiny interface.\n *\n * Consumers only need to know: start watching these agent sources, stop, and get\n * notified (post write-stability + debounce) which agents' data changed. The\n * recursive-vs-fallback strategy, APFS mtime quirks, and path-stability polling\n * are all internal details.\n */\nimport { existsSync, readdirSync, statSync, watch, type FSWatcher } from \"node:fs\";\nimport { dirname, isAbsolute, join, relative, resolve } from \"node:path\";\nimport type { SessionWatchPlan } from \"@codesesh/core\";\nimport { appLogger } from \"./logging.js\";\n\nconst WRITE_STABILITY_THRESHOLD_MS = 250;\nconst WRITE_STABILITY_POLL_MS = 100;\n\nexport interface SessionWatchSource {\n readonly name: string;\n getSessionWatchPlan(): SessionWatchPlan;\n}\n\ninterface WatchScope {\n agentName: string;\n targetPath: string;\n}\n\ninterface StablePathState {\n path: string;\n agentNames: Set<string>;\n lastMtimeMs: number | null;\n lastSize: number | null;\n stableSince: number;\n timer: NodeJS.Timeout | null;\n}\n\nexport type AgentsChangedListener = (agentNames: Set<string>) => void;\n\nexport function toAbsolutePath(path: string): string {\n return isAbsolute(path) ? path : resolve(path);\n}\n\nfunction closestWatchablePath(targetPath: string): string | null {\n if (!isAbsolute(targetPath) && !existsSync(targetPath)) {\n return null;\n }\n\n let current = toAbsolutePath(targetPath);\n\n while (!existsSync(current)) {\n const parent = dirname(current);\n if (parent === current) {\n return null;\n }\n current = parent;\n }\n\n return current;\n}\n\nfunction getWatchRoot(path: string): string {\n const stat = statSync(path);\n return stat.isDirectory() ? path : dirname(path);\n}\n\nexport function isRecursiveWatchSupported(\n // \"ibmi\" is a real process.platform value on IBM i (PASE) but is not yet\n // declared in @types/node's Platform union.\n platform: NodeJS.Platform | \"ibmi\" = process.platform,\n nodeVersion = process.versions.node,\n): boolean {\n if (platform === \"darwin\" || platform === \"win32\") {\n return true;\n }\n if (platform !== \"linux\" && platform !== \"aix\" && platform !== \"ibmi\") {\n return false;\n }\n\n const [major = 0, minor = 0] = nodeVersion.split(\".\").map((part) => Number(part));\n return major > 19 || (major === 19 && minor >= 1);\n}\n\nfunction isRecursiveWatchUnavailable(error: unknown): boolean {\n return (\n typeof error === \"object\" &&\n error !== null &&\n \"code\" in error &&\n error.code === \"ERR_FEATURE_UNAVAILABLE_ON_PLATFORM\"\n );\n}\n\nfunction isSameOrChildPath(parentPath: string, childPath: string): boolean {\n const path = relative(parentPath, childPath);\n return path === \"\" || (!path.startsWith(\"..\") && !isAbsolute(path));\n}\n\n/**\n * Sidecars a SQLite commit writes. `-shm` is excluded because a read-only open\n * rewrites it, which would make every scan look like a new change.\n */\nconst SQLITE_SIDECAR_SUFFIXES = [\"-wal\", \"-journal\"];\n\n/** True for `foo.db-wal` against `foo.db`, but not for `foo.db.bak`. */\nfunction isSqliteSidecarOf(changedPath: string, targetPath: string): boolean {\n return SQLITE_SIDECAR_SUFFIXES.some((suffix) => changedPath === `${targetPath}${suffix}`);\n}\n\nfunction isRelatedPath(changedPath: string, targetPath: string): boolean {\n return (\n isSameOrChildPath(targetPath, changedPath) ||\n isSameOrChildPath(changedPath, targetPath) ||\n isSqliteSidecarOf(changedPath, targetPath)\n );\n}\n\nfunction mergeScopes(target: WatchScope[], scopes: WatchScope[]): void {\n for (const scope of scopes) {\n if (\n !target.some(\n (item) => item.agentName === scope.agentName && item.targetPath === scope.targetPath,\n )\n ) {\n target.push(scope);\n }\n }\n}\n\nfunction resolveWatchEventPath(watchPath: string, filename: string | Buffer | null): string {\n const filenameText = filename?.toString();\n if (!filenameText) {\n return watchPath;\n }\n return isAbsolute(filenameText) ? filenameText : join(watchPath, filenameText);\n}\n\nexport class SessionWatcher {\n private watchers: FSWatcher[] = [];\n private fallbackWatchScopes = new Map<string, WatchScope[]>();\n private stablePaths = new Map<string, StablePathState>();\n private listeners = new Set<AgentsChangedListener>();\n\n /** Register a listener fired (after write-stability polling) with the changed agent set. */\n onAgentsChanged(cb: AgentsChangedListener): () => void {\n this.listeners.add(cb);\n return () => {\n this.listeners.delete(cb);\n };\n }\n\n /** Begin watching the session sources declared by each agent adapter. */\n start(agents: SessionWatchSource[]): void {\n const scopesByRoot = new Map<string, WatchScope[]>();\n\n for (const agent of agents) {\n const plan = agent.getSessionWatchPlan();\n if (plan.status !== \"supported\") {\n appLogger.debug(\"watch.skip\", {\n agent: agent.name,\n status: plan.status,\n reason: plan.reason,\n });\n continue;\n }\n if (plan.targets.length === 0) {\n appLogger.debug(\"watch.skip\", { agent: agent.name, status: plan.status });\n continue;\n }\n\n for (const target of plan.targets) {\n const watchRootPath = closestWatchablePath(target.root ?? target.path);\n if (!watchRootPath) continue;\n\n let rootPath: string;\n try {\n rootPath = getWatchRoot(watchRootPath);\n } catch (error) {\n this.reportWatchError(\"watch.resolve.error\", { path: watchRootPath, error });\n continue;\n }\n const targetPath = toAbsolutePath(target.path);\n const scopes = scopesByRoot.get(rootPath) ?? [];\n if (\n !scopes.some((scope) => scope.agentName === agent.name && scope.targetPath === targetPath)\n ) {\n scopes.push({ agentName: agent.name, targetPath });\n }\n scopesByRoot.set(rootPath, scopes);\n }\n }\n\n for (const [rootPath, scopes] of scopesByRoot.entries()) {\n const agents = Array.from(new Set(scopes.map((scope) => scope.agentName)));\n appLogger.info(\"watch.start\", {\n root: rootPath,\n agents,\n targets: scopes.map((scope) => ({\n agent: scope.agentName,\n path: scope.targetPath,\n })),\n });\n\n if (isRecursiveWatchSupported()) {\n const started = this.watchDirectory(rootPath, scopes, true);\n if (started) {\n continue;\n }\n }\n\n this.watchDirectoryTree(rootPath, scopes);\n }\n }\n\n /** Stop all watchers and clear pending stability polls. */\n async dispose(): Promise<void> {\n for (const state of this.stablePaths.values()) {\n if (state.timer) {\n clearTimeout(state.timer);\n }\n }\n this.stablePaths.clear();\n\n await Promise.all(this.watchers.map((watcher) => watcher.close()));\n this.watchers = [];\n this.fallbackWatchScopes.clear();\n this.listeners.clear();\n }\n\n private watchDirectory(path: string, scopes: WatchScope[], recursive: boolean): boolean {\n try {\n const watcher = watch(path, { recursive }, (eventType, filename) => {\n queueMicrotask(() => {\n try {\n const activeScopes = recursive\n ? scopes\n : (this.fallbackWatchScopes.get(path) ?? scopes);\n this.handleWatchEvent(path, activeScopes, eventType, filename);\n if (!recursive) {\n this.watchNewDirectories(path, filename, activeScopes);\n }\n } catch (error) {\n this.reportWatchError(\"watch.event.error\", { path, recursive, error });\n }\n });\n });\n\n watcher.on(\"error\", (error) => {\n this.reportWatchError(\"watch.error\", { path, recursive, error });\n });\n\n this.watchers.push(watcher);\n return true;\n } catch (error) {\n if (recursive && isRecursiveWatchUnavailable(error)) {\n appLogger.warn(\"watch.recursive_unavailable\", { path, error });\n return false;\n }\n\n this.reportWatchError(\"watch.start.error\", { path, recursive, error });\n return false;\n }\n }\n\n private watchDirectoryTree(rootPath: string, scopes: WatchScope[]): void {\n const pending = [rootPath];\n\n while (pending.length > 0) {\n const dirPath = pending.pop()!;\n this.watchFallbackDirectory(dirPath, scopes);\n\n try {\n for (const entry of readdirSync(dirPath, { withFileTypes: true })) {\n if (entry.isDirectory()) {\n pending.push(join(dirPath, entry.name));\n }\n }\n } catch (error) {\n this.reportWatchError(\"watch.scan.error\", { path: dirPath, error });\n }\n }\n }\n\n private watchFallbackDirectory(path: string, scopes: WatchScope[]): void {\n const existingScopes = this.fallbackWatchScopes.get(path);\n if (existingScopes) {\n mergeScopes(existingScopes, scopes);\n return;\n }\n\n const storedScopes = [...scopes];\n this.fallbackWatchScopes.set(path, storedScopes);\n if (!this.watchDirectory(path, storedScopes, false)) {\n this.fallbackWatchScopes.delete(path);\n }\n }\n\n private watchNewDirectories(\n watchPath: string,\n filename: string | Buffer | null,\n scopes: WatchScope[],\n ): void {\n const path = resolveWatchEventPath(watchPath, filename);\n try {\n if (statSync(path).isDirectory()) {\n this.watchDirectoryTree(path, scopes);\n }\n } catch {}\n }\n\n private handleWatchEvent(\n watchPath: string,\n scopes: WatchScope[],\n eventType: string,\n filename: string | Buffer | null,\n ): void {\n const changedPath = resolveWatchEventPath(watchPath, filename);\n const agentNames = new Set(\n scopes\n .filter((scope) => isRelatedPath(changedPath, scope.targetPath))\n .map((scope) => scope.agentName),\n );\n\n if (agentNames.size === 0) {\n return;\n }\n\n appLogger.debug(\"watch.event\", {\n event: eventType,\n path: changedPath,\n agents: Array.from(agentNames),\n });\n this.waitForStablePath(changedPath, agentNames);\n }\n\n private waitForStablePath(path: string, agentNames: Set<string>): void {\n const existing = this.stablePaths.get(path);\n if (existing) {\n for (const agentName of agentNames) {\n existing.agentNames.add(agentName);\n }\n return;\n }\n\n const state: StablePathState = {\n path,\n agentNames: new Set(agentNames),\n lastMtimeMs: null,\n lastSize: null,\n stableSince: Date.now(),\n timer: null,\n };\n this.stablePaths.set(path, state);\n this.pollStablePath(path);\n }\n\n private pollStablePath(path: string): void {\n const state = this.stablePaths.get(path);\n if (!state) {\n return;\n }\n\n let size: number;\n let mtimeMs: number;\n try {\n const stat = statSync(path);\n size = stat.size;\n mtimeMs = stat.mtimeMs;\n } catch {\n this.stablePaths.delete(path);\n this.emitAgentsChanged(state.agentNames);\n return;\n }\n\n const now = Date.now();\n const unchanged = state.lastSize === size && state.lastMtimeMs === mtimeMs;\n if (!unchanged) {\n state.lastSize = size;\n state.lastMtimeMs = mtimeMs;\n state.stableSince = now;\n }\n\n if (unchanged && now - state.stableSince >= WRITE_STABILITY_THRESHOLD_MS) {\n this.stablePaths.delete(path);\n this.emitAgentsChanged(state.agentNames);\n return;\n }\n\n state.timer = setTimeout(() => this.pollStablePath(path), WRITE_STABILITY_POLL_MS);\n }\n\n private emitAgentsChanged(agentNames: Set<string>): void {\n if (agentNames.size === 0) return;\n for (const listener of this.listeners) {\n listener(new Set(agentNames));\n }\n }\n\n private reportWatchError(event: string, data: Record<string, unknown>): void {\n appLogger.error(event, data);\n console.error(\"[watch] File watcher failed:\", data.error);\n }\n}\n","import { Worker } from \"node:worker_threads\";\nimport type {\n AgentScanProgress,\n ScanOptions,\n SessionCacheMeta,\n SessionHead,\n SessionHeadChange,\n} from \"@codesesh/core\";\nimport { appLogger } from \"./logging.js\";\nimport type {\n ScanRefreshWorkerCheckpoint,\n ScanRefreshWorkerMessage,\n ScanRefreshWorkerRequest,\n} from \"./scan-refresh-worker.js\";\nimport { toError } from \"./errors.js\";\n\nexport interface WorkerPayload {\n previousSessions: SessionHead[];\n changedIds: string[] | null;\n sourceSync?: boolean;\n backfill?: boolean;\n backfillCursor?: string | null;\n checkpoint?: boolean;\n scanOptions: Pick<ScanOptions, \"from\" | \"to\" | \"fast\">;\n meta: Record<string, SessionCacheMeta>;\n onProgress?: (progress: AgentScanProgress) => void;\n onCheckpoint?: (checkpoint: ScanRefreshWorkerCheckpoint) => void;\n}\n\nexport interface WorkerResult {\n sessions: SessionHead[];\n meta: Record<string, SessionCacheMeta>;\n changedIds?: string[];\n}\n\nexport interface WorkerRunner {\n readonly activeCount: number;\n run(agentName: string, payload: WorkerPayload): Promise<WorkerResult>;\n shutdown(): Promise<void>;\n}\n\ninterface PendingRequest {\n resolve: (result: WorkerResult) => void;\n reject: (error: Error) => void;\n payload: WorkerPayload;\n onProgress?: (progress: AgentScanProgress) => void;\n onCheckpoint?: (checkpoint: ScanRefreshWorkerCheckpoint) => void;\n}\n\ninterface WorkerSlot {\n worker: Worker;\n pending: Map<number, PendingRequest>;\n closed: boolean;\n}\n\nconst SHUTDOWN_ERROR_MESSAGE = \"Scan refresh worker shut down\";\n\nfunction applySessionChanges(\n previousSessions: SessionHead[],\n changes: SessionHeadChange[],\n removedSessionIds: string[],\n): SessionHead[] {\n const replacedIds = new Set(removedSessionIds);\n for (const { session } of changes) replacedIds.add(session.id);\n const retained = previousSessions.filter((session) => !replacedIds.has(session.id));\n const next: Array<SessionHead | undefined> = Array.from({\n length: retained.length + changes.length,\n });\n\n for (const { session, sortIndex } of changes) {\n if (sortIndex < 0 || sortIndex >= next.length || next[sortIndex]) {\n throw new Error(`Invalid scan refresh sort index: ${sortIndex}`);\n }\n next[sortIndex] = session;\n }\n\n let retainedIndex = 0;\n for (let index = 0; index < next.length; index += 1) {\n if (!next[index]) next[index] = retained[retainedIndex++];\n }\n if (retainedIndex !== retained.length || next.some((session) => !session)) {\n throw new Error(\"Invalid scan refresh delta\");\n }\n return next as SessionHead[];\n}\n\nfunction applyMetaChanges(\n previous: Record<string, SessionCacheMeta>,\n changed: Record<string, SessionCacheMeta>,\n replacedSessionIds: Iterable<string>,\n): Record<string, SessionCacheMeta> {\n const next = { ...previous };\n for (const id of replacedSessionIds) delete next[id];\n return Object.assign(next, changed);\n}\n\nexport class ThreadWorkerRunner implements WorkerRunner {\n private workers = new Map<string, WorkerSlot>();\n private nextRequestId = 1;\n private isShuttingDown = false;\n\n constructor(private readonly workerUrl: URL) {}\n\n get activeCount(): number {\n let count = 0;\n for (const slot of this.workers.values()) count += slot.pending.size;\n return count;\n }\n\n run(agentName: string, payload: WorkerPayload): Promise<WorkerResult> {\n if (this.isShuttingDown) return Promise.reject(new Error(SHUTDOWN_ERROR_MESSAGE));\n\n const request: ScanRefreshWorkerRequest = {\n type: \"run\",\n requestId: this.nextRequestId++,\n agentName,\n previousSessions: payload.previousSessions,\n changedIds: payload.changedIds,\n sourceSync: payload.sourceSync,\n backfill: payload.backfill,\n backfillCursor: payload.backfillCursor,\n checkpoint: payload.checkpoint,\n scanOptions: payload.scanOptions,\n meta: payload.meta,\n };\n\n return new Promise((resolve, reject) => {\n let slot = this.workers.get(agentName);\n const isNewWorker = !slot;\n if (!slot) {\n try {\n slot = this.createWorker(agentName, request);\n } catch (error) {\n reject(toError(error));\n return;\n }\n }\n\n slot.pending.set(request.requestId, {\n resolve,\n reject,\n payload,\n onProgress: payload.onProgress,\n onCheckpoint: payload.onCheckpoint,\n });\n\n if (!isNewWorker) {\n try {\n slot.worker.postMessage(request);\n } catch (error) {\n slot.pending.delete(request.requestId);\n reject(toError(error));\n }\n }\n });\n }\n\n async shutdown(): Promise<void> {\n this.isShuttingDown = true;\n const slots = [...this.workers.values()];\n this.workers.clear();\n const shutdownError = new Error(SHUTDOWN_ERROR_MESSAGE);\n for (const slot of slots) {\n slot.closed = true;\n for (const pending of slot.pending.values()) pending.reject(shutdownError);\n slot.pending.clear();\n }\n await Promise.allSettled(slots.map((slot) => slot.worker.terminate()));\n }\n\n private createWorker(agentName: string, request: ScanRefreshWorkerRequest): WorkerSlot {\n const worker = new Worker(this.workerUrl, { workerData: request });\n const slot: WorkerSlot = { worker, pending: new Map(), closed: false };\n worker.unref();\n this.workers.set(agentName, slot);\n worker.on(\"message\", (message: ScanRefreshWorkerMessage) => {\n this.handleMessage(slot, message);\n });\n worker.on(\"error\", (error) => {\n this.closeWorker(agentName, slot, toError(error));\n });\n worker.on(\"exit\", (code) => {\n if (slot.closed) return;\n const error = new Error(`Scan refresh worker exited before completing (code ${code})`);\n if (slot.pending.size > 0) {\n appLogger.warn(\"scan.refresh_worker.exit_before_done\", { agent: agentName, code });\n }\n this.closeWorker(agentName, slot, error);\n });\n return slot;\n }\n\n private handleMessage(slot: WorkerSlot, message: ScanRefreshWorkerMessage): void {\n const pending = slot.pending.get(message.requestId);\n if (!pending) return;\n if (message.type === \"progress\") {\n pending.onProgress?.(message.progress);\n return;\n }\n if (message.type === \"checkpoint\") {\n pending.onCheckpoint?.(message.checkpoint);\n return;\n }\n\n slot.pending.delete(message.requestId);\n if (message.type === \"error\") {\n pending.reject(new Error(message.error));\n return;\n }\n const changedIds = message.changes.map(({ session }) => session.id);\n const replacedSessionIds = [...changedIds, ...message.removedSessionIds];\n const removedMetaIds = [...message.removedSessionIds, ...message.removedMetaIds];\n try {\n pending.resolve({\n sessions: applySessionChanges(\n pending.payload.previousSessions,\n message.changes,\n message.removedSessionIds,\n ),\n meta: applyMetaChanges(pending.payload.meta, message.meta, removedMetaIds),\n changedIds: pending.payload.sourceSync ? replacedSessionIds : undefined,\n });\n } catch (error) {\n pending.reject(toError(error));\n }\n }\n\n private closeWorker(agentName: string, slot: WorkerSlot, error: Error): void {\n if (slot.closed) return;\n slot.closed = true;\n if (this.workers.get(agentName) === slot) this.workers.delete(agentName);\n for (const pending of slot.pending.values()) pending.reject(error);\n slot.pending.clear();\n }\n}\n","import { consola } from \"consola\";\nimport type { BaseAgent } from \"@codesesh/core\";\nimport { VERSION } from \"./version.js\";\n\nexport function printScanResults(agents: BaseAgent[]): void {\n consola.log(\"\");\n consola.box({\n title: \"CodeSesh\",\n message: `v${VERSION} • local session browser`,\n style: {\n padding: 1,\n borderColor: \"cyan\",\n },\n });\n consola.log(\"\");\n consola.info(\n `Indexing ${agents.map((agent) => agent.displayName).join(\", \")} sessions in the background.`,\n );\n consola.info(\"The Web UI will update automatically as sessions are discovered.\");\n consola.log(\"\");\n}\n","import { readFileSync } from \"node:fs\";\nimport { resolve, dirname } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\nconst pkg = JSON.parse(readFileSync(resolve(__dirname, \"../package.json\"), \"utf-8\"));\n\nexport const VERSION = pkg.version;\n","/**\n * Shape of `--json`: an index of what exists, not an archive of what was said.\n *\n * Sessions are reported as heads — metadata only. Messages, tool calls,\n * reasoning and file activity stay in each agent's own data directory, so this\n * output is deliberately not a backup, and must not quietly grow into one.\n */\nimport {\n filterSessionTreeByActivityWindow,\n getAgentInfoMap,\n type LiveSnapshot,\n type SessionHead,\n} from \"@codesesh/core\";\n\nexport interface SessionIndexAgent {\n name: string;\n displayName: string;\n count: number;\n available: boolean;\n}\n\nexport interface SessionIndexOutput {\n agents: SessionIndexAgent[];\n sessions: SessionHead[];\n}\n\nexport interface SessionIndexWindow {\n from?: number;\n to?: number;\n}\n\nexport function buildSessionIndexOutput(\n snapshot: Pick<LiveSnapshot, \"sessions\" | \"byAgent\">,\n window: SessionIndexWindow = {},\n): SessionIndexOutput {\n // Keep --days/--from/--to meaningful for the JSON output too.\n const sessions = filterSessionTreeByActivityWindow(snapshot.sessions, window.from, window.to);\n\n const agents = getAgentInfoMap(\n Object.fromEntries(\n Object.entries(snapshot.byAgent).map(([name, list]) => [\n name,\n filterSessionTreeByActivityWindow(list, window.from, window.to).length,\n ]),\n ),\n ).map(({ name, displayName, count }) => ({\n name,\n displayName,\n count,\n available: count > 0,\n }));\n\n return { agents, sessions };\n}\n","import type { ScanOptions } from \"@codesesh/core\";\nimport { sessionRoutePath } from \"@codesesh/core/contract\";\nimport { resolveTimeWindow, type TimeWindow } from \"./time-window-resolution.js\";\n\nexport interface TargetSession {\n agent: string;\n sessionId: string;\n}\n\ninterface CliRuntimePlanInput {\n agent?: string;\n cwd?: string;\n from?: string;\n to?: string;\n days?: string;\n jsonOnly: boolean;\n useCache: boolean;\n targetSession: TargetSession | null;\n}\n\ninterface CliRuntimeEnvironment {\n currentWorkingDirectory: string;\n now?: number;\n}\n\nexport interface CliRuntimePlan {\n listWindow: TimeWindow;\n scanOptions: ScanOptions;\n startupScanOptions: Pick<ScanOptions, \"from\" | \"to\">;\n}\n\nexport function parseSessionUri(uri: string): TargetSession | null {\n const match = uri.match(/^([a-z]+):\\/\\/(.+)$/i);\n if (!match) return null;\n return { agent: match[1]!, sessionId: match[2]! };\n}\n\nexport function buildCliRuntimePlan(\n input: CliRuntimePlanInput,\n environment: CliRuntimeEnvironment,\n): CliRuntimePlan {\n const listWindow = resolveTimeWindow({\n mode: \"cli\",\n from: input.from,\n to: input.to,\n days: input.days,\n now: environment.now,\n });\n const cwd = input.cwd === \".\" ? environment.currentWorkingDirectory : input.cwd;\n const agents = input.targetSession\n ? [input.targetSession.agent]\n : input.agent\n ? input.agent.split(\",\").map((agent) => agent.trim())\n : undefined;\n\n return {\n listWindow,\n scanOptions: { agents, cwd, useCache: input.useCache },\n startupScanOptions:\n input.targetSession || input.jsonOnly ? {} : { from: listWindow.from, to: listWindow.to },\n };\n}\n\nexport function resolveStartupUrl(startupUrl: string, targetSession: TargetSession | null): string {\n if (!targetSession) return startupUrl;\n const url = new URL(startupUrl);\n url.pathname = sessionRoutePath({\n agentName: targetSession.agent,\n sessionId: targetSession.sessionId,\n });\n return url.toString();\n}\n\nexport function redactStartupUrl(startupUrl: string): string {\n const url = new URL(startupUrl);\n for (const key of url.searchParams.keys()) {\n url.searchParams.set(key, \"[redacted]\");\n }\n return url.toString();\n}\n","export const DEFAULT_PORT = 4521;\nexport const DEFAULT_PORT_FALLBACK_ATTEMPTS = 20;\n\nexport function parsePort(value: string | undefined): number {\n const port = parseInt(value ?? \"\", 10);\n return Number.isNaN(port) ? DEFAULT_PORT : port;\n}\n\nexport function hasExplicitPortArg(argv: string[]): boolean {\n return argv.some((arg, index) => {\n if (arg === \"--port\" || arg === \"-p\") return index < argv.length - 1;\n return arg.startsWith(\"--port=\") || /^-p\\d+$/.test(arg);\n });\n}\n","/**\n * Lifecycle owner for the background price refresh.\n *\n * The refresh used to be fired and forgotten: no timeout, no cancellation, and\n * it replaced the live prices the moment it returned — so one scan could price\n * its first sessions differently from its last. Here it is bounded, cancellable\n * on shutdown, and published only at a point where no scan is running.\n */\nimport { publishPendingPricing, refreshPricingCache } from \"@codesesh/core\";\nimport { appLogger } from \"./logging.js\";\n\n/** Long enough for a cold network, short enough not to outlive a --json run. */\nconst REFRESH_TIMEOUT_MS = 10_000;\n\nexport interface PricingRefresh {\n /** Makes a completed refresh current. Safe to call more than once. */\n publish(): void;\n /** Cancels an in-flight refresh and waits for it to settle. */\n cancel(): Promise<void>;\n}\n\nexport function startPricingRefresh(timeoutMs = REFRESH_TIMEOUT_MS): PricingRefresh {\n const controller = new AbortController();\n const completion = refreshPricingCache({ signal: controller.signal, timeoutMs }).catch(\n (error: unknown) => {\n appLogger.warn(\"pricing.refresh.error\", { error });\n return false;\n },\n );\n\n return {\n publish() {\n if (publishPendingPricing()) appLogger.info(\"pricing.refresh.published\", {});\n },\n async cancel() {\n controller.abort();\n await completion;\n },\n };\n}\n"],"mappings":"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","names":["Hono","session","__dirname","resolve","Hono","url","existsSync","fileURLToPath","existsSync","fileURLToPath","resolve","existsSync","fileURLToPath","sessions","persisted","existsSync","dirname","resolve","resolve","existsSync","dirname","agents","Worker","SHUTDOWN_ERROR_MESSAGE","applySessionChanges","resolve","Worker","existsSync","fileURLToPath","readFileSync","resolve","dirname","fileURLToPath"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/server.ts","../src/api/routes.ts","../src/time-window-resolution.ts","../src/api/query-params.ts","../src/api/session-pagination.ts","../src/api/session-aliases-view.ts","../src/api/handlers.ts","../src/api/sse-event-buffer.ts","../src/loopback-authority.ts","../src/loopback-write-guard.ts","../src/remote-access.ts","../src/live-scan.ts","../src/agent-operation-scheduler.ts","../src/backfill-lifecycle.ts","../src/live-session-index.ts","../src/latest-value-throttle.ts","../src/search-index-job-runner.ts","../src/errors.ts","../src/pending-search-index-jobs.ts","../src/search-index-maintenance-scheduler.ts","../src/scan-status-model.ts","../src/agent-sync-engine.ts","../src/session-watcher.ts","../src/worker-runner.ts","../src/output.ts","../src/version.ts","../src/session-index-output.ts","../src/runtime-plan.ts","../src/ports.ts","../src/pricing-refresh.ts"],"sourcesContent":["import \"./diagnostics-bridge.js\";\nimport { defineCommand, runMain } from \"citty\";\nimport { createServer, getServerStartupErrorMessage } from \"./server.js\";\nimport { LiveScanStore } from \"./live-scan.js\";\nimport { printScanResults } from \"./output.js\";\nimport { VERSION } from \"./version.js\";\nimport { appLogger } from \"./logging.js\";\nimport { buildSessionIndexOutput, formatScanFailureDiagnostics } from \"./session-index-output.js\";\nimport {\n resolveRemoteAccessPolicy,\n resolveRemoteTransport,\n type RemoteTransport,\n} from \"./remote-access.js\";\nimport {\n buildCliRuntimePlan,\n parseSessionUri,\n redactStartupUrl,\n resolveStartupUrl,\n} from \"./runtime-plan.js\";\nimport {\n DEFAULT_PORT,\n DEFAULT_PORT_FALLBACK_ATTEMPTS,\n hasExplicitPortArg,\n parsePort,\n} from \"./ports.js\";\nimport { createRegisteredAgents, perf } from \"@codesesh/core\";\nimport { startPricingRefresh } from \"./pricing-refresh.js\";\n\nconst main = defineCommand({\n meta: {\n name: \"codesesh\",\n description: \"Discover, aggregate, and visualize AI coding agent sessions\",\n version: VERSION,\n },\n args: {\n port: {\n type: \"string\",\n alias: \"p\",\n description: \"HTTP server port\",\n default: String(DEFAULT_PORT),\n },\n host: {\n type: \"string\",\n description: \"HTTP server bind address (default 127.0.0.1, local access only)\",\n default: \"127.0.0.1\",\n },\n \"remote-access\": {\n type: \"boolean\",\n description: \"Allow authenticated access when binding to a non-loopback address\",\n default: false,\n },\n \"tls-cert\": {\n type: \"string\",\n description: \"Path to a TLS certificate; serve remote access over HTTPS\",\n },\n \"tls-key\": {\n type: \"string\",\n description: \"Path to the TLS private key matching --tls-cert\",\n },\n \"trust-proxy\": {\n type: \"boolean\",\n description: \"A reverse proxy in front of CodeSesh terminates TLS\",\n default: false,\n },\n agent: {\n type: \"string\",\n alias: \"a\",\n description: \"Filter to specific agent(s), comma-separated\",\n },\n days: {\n type: \"string\",\n alias: \"d\",\n description: \"Only include sessions active in the last N days (0 = all time)\",\n default: \"7\",\n },\n cwd: {\n type: \"string\",\n description: \"Filter to sessions from a specific project directory (use '.' for current dir)\",\n },\n from: {\n type: \"string\",\n description: \"Sessions active after this date, YYYY-MM-DD (overrides --days)\",\n },\n to: {\n type: \"string\",\n description: \"Sessions active before this date (YYYY-MM-DD)\",\n },\n session: {\n type: \"string\",\n alias: \"s\",\n description: \"Directly open a specific session (agent://session-id)\",\n },\n json: {\n type: \"boolean\",\n alias: \"j\",\n description: \"Output session index as JSON to stdout (no server)\",\n default: false,\n },\n noOpen: {\n type: \"boolean\",\n description: \"Don't auto-open browser\",\n default: false,\n },\n trace: {\n type: \"boolean\",\n description: \"Show performance trace logs\",\n default: false,\n },\n cache: {\n type: \"boolean\",\n description: \"Use cached scan results if available\",\n default: true,\n },\n \"clear-cache\": {\n type: \"boolean\",\n description: \"Clear scan cache before starting\",\n default: false,\n },\n },\n async run({ args }) {\n const startedAt = performance.now();\n const port = parsePort(args.port as string | undefined);\n const explicitPort = hasExplicitPortArg(process.argv.slice(2));\n const noOpen = args.noOpen as boolean;\n const jsonOnly = args.json as boolean;\n const trace = args.trace as boolean;\n const useCache = args.cache as boolean;\n const clearCache = args[\"clear-cache\"] as boolean;\n const hostname = args.host as string;\n const remoteAccess = args[\"remote-access\"] as boolean;\n\n let transport: RemoteTransport;\n try {\n transport = resolveRemoteTransport({\n hostname,\n tlsCertPath: args[\"tls-cert\"] as string | undefined,\n tlsKeyPath: args[\"tls-key\"] as string | undefined,\n trustProxy: args[\"trust-proxy\"] as boolean,\n });\n } catch (error) {\n console.error(error instanceof Error ? error.message : String(error));\n process.exit(1);\n }\n\n if (resolveRemoteAccessPolicy(hostname, transport).authenticationRequired && !remoteAccess) {\n console.error(\n `Refusing to expose CodeSesh on ${hostname} without authentication. Add --remote-access to continue.`,\n );\n process.exit(1);\n }\n\n if (trace) {\n perf.enable();\n }\n\n appLogger.info(\"cli.start\", {\n version: VERSION,\n argv: process.argv.slice(2),\n port,\n json: jsonOnly,\n no_open: noOpen,\n cache: useCache,\n log_path: appLogger.getLogPath(),\n });\n\n if (clearCache) {\n const { clearCache: clear } = await import(\"@codesesh/core\");\n clear();\n appLogger.info(\"cache.clear\");\n console.log(\"Cache cleared.\");\n }\n\n // Owns the refresh: bounded, cancellable, and published only between scans\n // so a scan never spans two price generations.\n const pricingRefresh = startPricingRefresh();\n\n // Parse session URI if provided\n let targetSession: { agent: string; sessionId: string } | null = null;\n if (args.session) {\n targetSession = parseSessionUri(args.session as string);\n if (!targetSession) {\n console.error(`Invalid session format: ${args.session}. Expected: agent://session-id`);\n process.exit(1);\n }\n }\n\n const { listWindow, scanOptions, startupScanOptions } = buildCliRuntimePlan(\n {\n agent: args.agent as string | undefined,\n cwd: args.cwd as string | undefined,\n from: args.from as string | undefined,\n to: args.to as string | undefined,\n days: args.days as string | undefined,\n jsonOnly,\n targetSession,\n useCache,\n },\n { currentWorkingDirectory: process.cwd() },\n );\n const { from: listDefaultFrom, to: listDefaultTo, days: listDefaultDays } = listWindow;\n\n const store = new LiveScanStore({\n watchEnabled: !jsonOnly,\n scanOptions,\n startupScanOptions,\n deferInitialRefresh: !jsonOnly,\n });\n await store.initialize();\n const result = store.getSnapshot();\n appLogger.info(\"cli.scan_ready\", {\n duration_ms: Math.round(performance.now() - startedAt),\n sessions: result.sessions.length,\n agents: Object.fromEntries(\n Object.entries(result.byAgent).map(([key, value]) => [key, value.length]),\n ),\n startup_from: startupScanOptions.from,\n startup_to: startupScanOptions.to,\n });\n\n if (trace) {\n console.log(perf.getReport());\n }\n\n if (jsonOnly) {\n // Nothing will consume a later generation, so stop waiting for it.\n await pricingRefresh.cancel();\n const scanFailureDiagnostics = formatScanFailureDiagnostics(result);\n if (scanFailureDiagnostics.length > 0) {\n await store.shutdown();\n for (const diagnostic of scanFailureDiagnostics) console.error(diagnostic);\n process.exitCode = 1;\n return;\n }\n const output = buildSessionIndexOutput(result, { from: listDefaultFrom, to: listDefaultTo });\n appLogger.info(\"cli.json_output\", {\n sessions: output.sessions.length,\n duration_ms: Math.round(performance.now() - startedAt),\n });\n console.log(JSON.stringify(output, null, 2));\n return;\n }\n\n // Print console output\n const agents = createRegisteredAgents();\n printScanResults(agents);\n\n // Start server\n let app: Awaited<ReturnType<typeof createServer>>;\n try {\n app = await createServer(port, store, {\n defaultSessionFrom: listDefaultFrom,\n defaultSessionTo: listDefaultTo,\n defaultSessionDays: listDefaultDays,\n portFallbackAttempts: explicitPort ? 1 : DEFAULT_PORT_FALLBACK_ATTEMPTS,\n hostname,\n remoteAccess,\n transport,\n });\n } catch (error) {\n console.error(getServerStartupErrorMessage(error, port));\n process.exit(1);\n }\n\n const { url } = app;\n if (!jsonOnly) {\n // The startup scan has finished and background scans have not begun.\n pricingRefresh.publish();\n store.startBackgroundRefresh();\n }\n let shuttingDown = false;\n const shutdown = async (signal: NodeJS.Signals) => {\n if (shuttingDown) return;\n shuttingDown = true;\n appLogger.info(\"cli.shutdown\", { signal });\n await pricingRefresh.cancel();\n await app.shutdown();\n process.exit(0);\n };\n process.once(\"SIGINT\", (signal) => {\n void shutdown(signal);\n });\n process.once(\"SIGTERM\", (signal) => {\n void shutdown(signal);\n });\n\n console.log(` ${url}`);\n console.log(\"\");\n appLogger.info(\"cli.ready\", {\n url: redactStartupUrl(url),\n duration_ms: Math.round(performance.now() - startedAt),\n log_path: appLogger.getLogPath(),\n });\n\n if (!noOpen) {\n const open = (await import(\"open\")).default;\n const targetUrl = resolveStartupUrl(url, targetSession);\n appLogger.info(\"browser.open\", { url: redactStartupUrl(targetUrl) });\n await open(targetUrl);\n }\n },\n});\n\nif (process.argv.slice(2).includes(\"-v\")) {\n console.log(VERSION);\n process.exit(0);\n}\n\nrunMain(main);\n","import { Hono } from \"hono\";\nimport { bodyLimit } from \"hono/body-limit\";\nimport { compress } from \"hono/compress\";\nimport { secureHeaders } from \"hono/secure-headers\";\nimport { serve } from \"@hono/node-server\";\nimport type { HttpBindings, ServerType } from \"@hono/node-server\";\nimport { serveStatic } from \"@hono/node-server/serve-static\";\nimport { existsSync } from \"node:fs\";\nimport { createServer as createHttpsServer } from \"node:https\";\nimport type { AddressInfo } from \"node:net\";\nimport { resolve, dirname } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport type { ScanResultSource } from \"./api/handlers.js\";\nimport { createApiRoutes, type ApiRouteOptions } from \"./api/routes.js\";\nimport { appLogger } from \"./logging.js\";\nimport { validateLoopbackAuthority } from \"./loopback-authority.js\";\nimport { loopbackWriteGuard } from \"./loopback-write-guard.js\";\nimport {\n createRemoteAccessToken,\n REMOTE_ACCESS_QUERY_PARAM,\n remoteAccessAuth,\n requireProxyTls,\n resolveRemoteAccessPolicy,\n resolveRemoteTransport,\n type RemoteTransport,\n} from \"./remote-access.js\";\nimport type { ScanEventSource } from \"./scan-source.js\";\n\nconst MAX_API_REQUEST_BYTES = 1024 * 1024;\nconst SERVER_CLOSE_GRACE_MS = 1_000;\n\nexport interface CreateServerOptions {\n defaultSessionFrom?: number;\n defaultSessionTo?: number;\n defaultSessionDays?: number;\n portFallbackAttempts?: number;\n hostname?: string;\n remoteAccess?: boolean;\n remoteAccessToken?: string;\n /** How the listener is protected; defaults to plaintext for a non-loopback host. */\n transport?: RemoteTransport;\n /** Overrides the auto-detected web build directory; used to pin the static root in tests. */\n webDistPath?: string;\n}\n\nfunction findWebDistPath(): string | null {\n const __dirname = dirname(fileURLToPath(import.meta.url));\n\n // Priority 1: Packaged web dist (copied during build)\n const packagedPath = resolve(__dirname, \"web\");\n if (existsSync(packagedPath)) {\n return packagedPath;\n }\n\n // Priority 2: Development path (monorepo)\n const devPath = resolve(__dirname, \"../../../apps/web/dist\");\n if (existsSync(devPath)) {\n return devPath;\n }\n\n return null;\n}\n\nfunction waitForListening(server: ServerType): Promise<void> {\n return new Promise((resolve, reject) => {\n const handleListening = () => {\n server.off(\"error\", handleError);\n resolve();\n };\n const handleError = (error: Error) => {\n server.off(\"listening\", handleListening);\n reject(error);\n };\n\n server.once(\"listening\", handleListening);\n server.once(\"error\", handleError);\n });\n}\n\nexport function getServerStartupErrorMessage(error: unknown, port: number): string {\n if (\n typeof error === \"object\" &&\n error !== null &&\n \"code\" in error &&\n error.code === \"EADDRINUSE\"\n ) {\n return `Port ${port} 已被占用,请关闭现有 CodeSesh 进程或改用 --port 指定其他端口。`;\n }\n\n return error instanceof Error ? error.message : `启动服务器失败: ${String(error)}`;\n}\n\nfunction isAddressInUse(error: unknown): boolean {\n return (\n typeof error === \"object\" && error !== null && \"code\" in error && error.code === \"EADDRINUSE\"\n );\n}\n\nfunction getListeningPort(server: ServerType, fallback: number): number {\n const address = server.address();\n return typeof address === \"object\" && address !== null ? (address as AddressInfo).port : fallback;\n}\n\nasync function closeHttpServer(server: ServerType | null, port: number | null): Promise<void> {\n if (!server) return;\n\n let forceCloseTimer: ReturnType<typeof setTimeout> | undefined;\n const gracefulClose = new Promise<void>((resolve) => server.close(() => resolve()));\n const forceClose = new Promise<void>((resolve) => {\n forceCloseTimer = setTimeout(() => {\n appLogger.warn(\"server.shutdown.force_close\", {\n port,\n grace_ms: SERVER_CLOSE_GRACE_MS,\n });\n if (\"closeAllConnections\" in server) server.closeAllConnections();\n resolve();\n }, SERVER_CLOSE_GRACE_MS);\n forceCloseTimer.unref();\n });\n\n try {\n await Promise.race([gracefulClose, forceClose]);\n } finally {\n if (forceCloseTimer) clearTimeout(forceCloseTimer);\n }\n}\n\nexport async function createServer(\n port: number,\n store: ScanResultSource & ScanEventSource & { shutdown(): Promise<void> },\n options: CreateServerOptions = {},\n): Promise<{ url: string; shutdown: () => Promise<void> }> {\n const app = new Hono<{ Bindings: HttpBindings }>();\n const hostname = options.hostname ?? \"127.0.0.1\";\n const transport: RemoteTransport = options.transport ?? resolveRemoteTransport({ hostname });\n const accessPolicy = resolveRemoteAccessPolicy(hostname, transport);\n const remoteAccessToken = accessPolicy.authenticationRequired\n ? (options.remoteAccessToken ?? (options.remoteAccess ? createRemoteAccessToken() : null))\n : null;\n const loopbackAuthorityEnabled = !accessPolicy.authenticationRequired;\n const shutdownController = new AbortController();\n let actualPort: number | null = null;\n\n appLogger.info(\"server.access_policy\", {\n bind_category: accessPolicy.bindCategory,\n transport: transport.kind,\n authentication: remoteAccessToken ? \"token\" : \"none\",\n loopback_authority: loopbackAuthorityEnabled ? \"enabled\" : \"disabled\",\n });\n\n if (accessPolicy.authenticationRequired && !remoteAccessToken) {\n throw new Error(\n `Refusing to expose CodeSesh on ${hostname} without authentication. Add --remote-access to continue.`,\n );\n }\n\n app.use(\n \"*\",\n secureHeaders({\n contentSecurityPolicy: {\n defaultSrc: [\"'self'\"],\n baseUri: [\"'none'\"],\n connectSrc: [\"'self'\"],\n fontSrc: [\"'self'\", \"data:\"],\n formAction: [\"'self'\"],\n frameAncestors: [\"'none'\"],\n imgSrc: [\"'self'\", \"data:\"],\n objectSrc: [\"'none'\"],\n scriptSrc: [\"'self'\"],\n scriptSrcAttr: [\"'none'\"],\n styleSrc: [\"'self'\", \"'unsafe-inline'\"],\n },\n crossOriginOpenerPolicy: false,\n crossOriginResourcePolicy: false,\n originAgentCluster: false,\n referrerPolicy: \"no-referrer\",\n strictTransportSecurity: false,\n xContentTypeOptions: \"nosniff\",\n xDnsPrefetchControl: false,\n xDownloadOptions: false,\n xFrameOptions: \"DENY\",\n xPermittedCrossDomainPolicies: false,\n xXssProtection: false,\n }),\n );\n\n if (loopbackAuthorityEnabled) {\n app.use(\"*\", async (c, next) => {\n const decision = validateLoopbackAuthority(c.env.incoming.rawHeaders, hostname, actualPort);\n if (!decision.allowed) {\n appLogger.warn(\"http.loopback_authority.rejected\", {\n method: c.req.method,\n path: new URL(c.req.url).pathname,\n reason: decision.reason,\n authority: decision.authority,\n });\n return c.json({ error: \"Loopback request authority rejected\" }, 403);\n }\n await next();\n });\n }\n\n app.use(\"*\", async (c, next) => {\n const startedAt = performance.now();\n let thrown: unknown;\n\n try {\n await next();\n } catch (error) {\n thrown = error;\n throw error;\n } finally {\n const url = new URL(c.req.url);\n appLogger.info(\"http.request\", {\n method: c.req.method,\n path: url.pathname,\n query_keys: [...url.searchParams.keys()].toSorted(),\n status: c.res.status,\n duration_ms: Math.round(performance.now() - startedAt),\n error: thrown instanceof Error ? thrown.message : undefined,\n });\n }\n });\n\n // Ordered before authentication: a request that bypassed the proxy must be\n // refused outright, not given a chance to present a token in the clear.\n if (transport.kind === \"trusted-proxy\") {\n app.use(\"/api/*\", requireProxyTls());\n }\n if (remoteAccessToken) {\n app.use(\"/api/*\", remoteAccessAuth(remoteAccessToken));\n }\n app.use(\"/api/*\", loopbackWriteGuard());\n app.use(\n \"/api/*\",\n bodyLimit({\n maxSize: MAX_API_REQUEST_BYTES,\n onError: (c) => c.json({ error: \"Request body too large\" }, 413),\n }),\n );\n // Hono's default filter already excludes text/event-stream, so this does not\n // interfere with the /api/events SSE stream.\n app.use(\"/api/*\", compress());\n\n // API routes\n const routeOptions: ApiRouteOptions = {\n defaultSessionFrom: options.defaultSessionFrom,\n defaultSessionTo: options.defaultSessionTo,\n defaultSessionDays: options.defaultSessionDays,\n shutdownSignal: shutdownController.signal,\n };\n app.route(\"/api\", createApiRoutes(store, store, routeOptions));\n\n // Serve static files from web dist (if available)\n const webDistPath = options.webDistPath ?? findWebDistPath();\n\n if (webDistPath) {\n app.use(\"/*\", serveStatic({ root: webDistPath }));\n app.get(\"/*\", serveStatic({ root: webDistPath, path: \"index.html\" }));\n }\n\n const attempts = Math.max(1, options.portFallbackAttempts ?? 1);\n let server: ServerType | null = null;\n\n for (let offset = 0; offset < attempts; offset += 1) {\n const candidatePort = port + offset;\n server = serve({\n fetch: app.fetch,\n port: candidatePort,\n hostname,\n ...(transport.kind === \"tls\"\n ? {\n createServer: createHttpsServer,\n serverOptions: { cert: transport.cert, key: transport.key },\n }\n : {}),\n });\n\n try {\n await waitForListening(server);\n actualPort = getListeningPort(server, candidatePort);\n break;\n } catch (error) {\n appLogger.error(\"server.listen.error\", { port: candidatePort, error });\n server.close();\n\n if (isAddressInUse(error) && offset < attempts - 1) {\n continue;\n }\n\n await store.shutdown();\n\n if (isAddressInUse(error) && attempts > 1) {\n throw new Error(\n `端口 ${port}-${port + attempts - 1} 均已被占用,请关闭现有进程或改用 --port 指定其他端口。`,\n );\n }\n\n throw new Error(getServerStartupErrorMessage(error, candidatePort));\n }\n }\n\n // A trusted proxy publishes its own https origin, so only direct TLS changes\n // the scheme CodeSesh prints for itself.\n const scheme = transport.kind === \"tls\" ? \"https\" : \"http\";\n const baseUrl =\n accessPolicy.bindCategory === \"loopback\"\n ? `${scheme}://localhost:${actualPort}`\n : `${scheme}://${hostname}:${actualPort}`;\n const url = remoteAccessToken\n ? `${baseUrl}/?${REMOTE_ACCESS_QUERY_PARAM}=${encodeURIComponent(remoteAccessToken)}`\n : baseUrl;\n appLogger.info(\"server.listen\", {\n port: actualPort,\n requested_port: port,\n hostname,\n remote_access: Boolean(remoteAccessToken),\n transport: transport.kind,\n });\n\n if (accessPolicy.authenticationRequired) {\n appLogger.warn(\"server.listen.remote_access\", {\n hostname,\n port: actualPort,\n transport: transport.kind,\n });\n console.warn(`\\n⚠ 远程访问已启用。任何持有启动 URL 的人都可以读取你的 AI 会话记录。\\n`);\n if (transport.kind === \"plaintext\") {\n appLogger.warn(\"server.listen.plaintext\", { hostname, port: actualPort });\n console.warn(\n `⚠ 传输未加密。访问令牌与完整会话内容以明文经过网络,URL 中的令牌还可能写入代理访问日志。\\n` +\n ` 使用 --tls-cert/--tls-key 直接启用 TLS,或在受信反向代理后使用 --trust-proxy。\\n`,\n );\n }\n if (transport.kind === \"trusted-proxy\") {\n appLogger.warn(\"server.listen.proxy_logging\", { hostname, port: actualPort });\n console.warn(\n `⚠ URL 中的访问令牌会用于 SSE 重连,并可能写入受信反向代理的访问日志。\\n` +\n ` 请在代理配置中关闭查询参数日志,或对 access_token 参数脱敏。\\n`,\n );\n }\n }\n\n return {\n url,\n shutdown: async () => {\n appLogger.info(\"server.shutdown\", { port: actualPort });\n shutdownController.abort();\n try {\n appLogger.info(\"server.shutdown.phase\", { phase: \"http-closing\", port: actualPort });\n await closeHttpServer(server, actualPort);\n } finally {\n appLogger.info(\"server.shutdown.phase\", { phase: \"store-closing\", port: actualPort });\n await store.shutdown();\n }\n appLogger.info(\"server.shutdown.phase\", { phase: \"complete\", port: actualPort });\n },\n };\n}\n","import { Hono } from \"hono\";\nimport {\n handleGetAgents,\n handleGetBookmarks,\n handleGetConfig,\n handleGetDashboard,\n handleGetFileActivity,\n handleGetProjects,\n handleGetScanStatus,\n handleDeleteBookmark,\n handleDeleteSessionAlias,\n handleImportBookmarks,\n handlePostClientLog,\n handleSearchSessions,\n handleGetSessions,\n handleGetSessionData,\n handlePutBookmark,\n handlePutSessionAlias,\n type ScanResultSource,\n type SessionListDefaults,\n} from \"./handlers.js\";\nimport type { ScanEventSource } from \"../scan-source.js\";\nimport { SseEventBuffer } from \"./sse-event-buffer.js\";\n\nexport interface ApiRouteOptions {\n defaultSessionFrom?: number;\n defaultSessionTo?: number;\n defaultSessionDays?: number;\n shutdownSignal?: AbortSignal;\n}\n\nfunction createSseResponse(eventSource: ScanEventSource, signal: AbortSignal): Response {\n let cancelStream = () => {};\n let drainStream = () => {};\n\n return new Response(\n new ReadableStream({\n start(controller) {\n let isClosed = false;\n let unsubscribeSessions = () => {};\n let unsubscribeScanStatus = () => {};\n let abortStream = () => {};\n let heartbeat: ReturnType<typeof setInterval> | undefined;\n let buffer: SseEventBuffer;\n\n const cleanup = () => {\n if (isClosed) return false;\n isClosed = true;\n buffer.close();\n if (heartbeat) clearInterval(heartbeat);\n unsubscribeSessions();\n unsubscribeScanStatus();\n signal.removeEventListener(\"abort\", abortStream);\n return true;\n };\n abortStream = () => {\n if (cleanup()) controller.close();\n };\n buffer = new SseEventBuffer(controller, () => {\n if (cleanup()) controller.error(new Error(\"SSE client fell behind\"));\n });\n drainStream = () => buffer.drain();\n\n buffer.enqueue(\"connected\", { timestamp: Date.now() });\n buffer.enqueueScanStatus(eventSource.getScanStatus());\n\n unsubscribeSessions = eventSource.subscribe((event) => {\n buffer.enqueue(event.type, event);\n });\n unsubscribeScanStatus = eventSource.subscribeScanStatus((event) => {\n buffer.enqueueScanStatus(event);\n });\n\n heartbeat = setInterval(() => buffer.enqueueHeartbeat(), 15000);\n cancelStream = () => {\n cleanup();\n };\n\n if (signal.aborted) abortStream();\n else signal.addEventListener(\"abort\", abortStream, { once: true });\n },\n pull() {\n drainStream();\n },\n cancel() {\n cancelStream();\n },\n }),\n {\n headers: {\n \"Cache-Control\": \"no-cache\",\n Connection: \"keep-alive\",\n \"Content-Type\": \"text/event-stream\",\n },\n },\n );\n}\n\nexport function createApiRoutes(\n scanSource: ScanResultSource,\n eventSource?: ScanEventSource,\n options: ApiRouteOptions = {},\n): Hono {\n const api = new Hono();\n const listDefaults: SessionListDefaults = {\n from: options.defaultSessionFrom,\n to: options.defaultSessionTo,\n days: options.defaultSessionDays,\n };\n\n api.get(\"/config\", (c) => handleGetConfig(c, listDefaults));\n if (eventSource) {\n api.get(\"/status\", (c) => handleGetScanStatus(c, eventSource));\n }\n api.get(\"/agents\", (c) => handleGetAgents(c, scanSource, listDefaults));\n api.get(\"/projects\", (c) => handleGetProjects(c, scanSource, listDefaults));\n api.get(\"/sessions\", (c) => handleGetSessions(c, scanSource, listDefaults));\n api.get(\"/search\", (c) => handleSearchSessions(c, scanSource, listDefaults));\n api.get(\"/file-activity\", (c) => handleGetFileActivity(c, listDefaults));\n api.get(\"/sessions/:agent/:id\", (c) => handleGetSessionData(c, scanSource));\n api.get(\"/dashboard\", (c) => handleGetDashboard(c, scanSource, listDefaults));\n api.get(\"/bookmarks\", (c) => handleGetBookmarks(c, scanSource));\n api.put(\"/bookmarks\", (c) => handlePutBookmark(c));\n api.post(\"/bookmarks/import\", (c) => handleImportBookmarks(c, scanSource));\n api.delete(\"/bookmarks/:agent/:id\", (c) => handleDeleteBookmark(c));\n api.put(\"/session-aliases/:agent/:id\", (c) => handlePutSessionAlias(c));\n api.delete(\"/session-aliases/:agent/:id\", (c) => handleDeleteSessionAlias(c));\n api.post(\"/logs\", (c) => handlePostClientLog(c));\n if (eventSource) {\n api.get(\"/events\", (c) => {\n const signal = options.shutdownSignal\n ? AbortSignal.any([c.req.raw.signal, options.shutdownSignal])\n : c.req.raw.signal;\n return createSseResponse(eventSource, signal);\n });\n }\n\n return api;\n}\n","import { addCalendarDays, countCalendarDays, startOfCalendarDay } from \"@codesesh/core/contract\";\n\n/** Rolling duration for CLI --days, which is a span of hours, not a calendar range. */\nconst ROLLING_DAY_MS = 24 * 60 * 60 * 1000;\nconst DEFAULT_DASHBOARD_DAYS = 30;\n\nexport interface TimeWindow {\n from?: number;\n to?: number;\n /** Original relative window value used by the UI label. */\n days?: number;\n}\n\ninterface RawTimeWindow {\n from?: string;\n to?: string;\n days?: string;\n}\n\ninterface CliTimeWindowRequest extends RawTimeWindow {\n mode: \"cli\";\n now?: number;\n}\n\ninterface DashboardTimeWindowRequest {\n mode: \"dashboard\";\n query: RawTimeWindow;\n defaults?: TimeWindow;\n now?: number;\n}\n\ninterface DashboardTimeWindow extends TimeWindow {\n to: number;\n}\n\ntype TimeWindowRequest = CliTimeWindowRequest | DashboardTimeWindowRequest;\n\nexport function resolveTimeWindow(request: CliTimeWindowRequest): TimeWindow;\nexport function resolveTimeWindow(request: DashboardTimeWindowRequest): DashboardTimeWindow;\nexport function resolveTimeWindow(request: TimeWindowRequest): TimeWindow {\n return request.mode === \"cli\" ? resolveCliWindow(request) : resolveDashboardWindow(request);\n}\n\nfunction resolveCliWindow(request: CliTimeWindowRequest): TimeWindow {\n const now = request.now ?? Date.now();\n const from = parseRequiredDate(request.from);\n const to = parseRequiredDate(request.to);\n if (from != null) return { from, to };\n\n const days = parseDays(request.days);\n if (days === 0) return { to, days };\n if (days == null || days < 0) return { to };\n\n const rollingFrom = now - days * ROLLING_DAY_MS;\n return Number.isFinite(rollingFrom) ? { from: rollingFrom, to, days } : { to };\n}\n\nfunction resolveDashboardWindow(request: DashboardTimeWindowRequest): DashboardTimeWindow {\n const now = request.now ?? Date.now();\n const defaults = request.defaults ?? {};\n const to = parseOptionalDate(request.query.to) ?? defaults.to ?? now;\n const hasQueryDays = Boolean(request.query.days?.trim());\n const parsedDays = hasQueryDays ? parseDays(request.query.days) : undefined;\n let days = parsedDays != null && parsedDays > 0 ? parsedDays : defaults.days;\n\n const queryFrom = parseOptionalDate(request.query.from);\n if (queryFrom != null) {\n days ??= countCalendarDays(queryFrom, to);\n return { from: queryFrom, to, days };\n }\n\n if (parsedDays === 0 || (!hasQueryDays && defaults.days === 0)) {\n return { to, days: 0 };\n }\n\n if (defaults.from != null) {\n days ??= countCalendarDays(defaults.from, to);\n return { from: defaults.from, to, days };\n }\n\n const resolvedDays = days != null && days > 0 ? days : DEFAULT_DASHBOARD_DAYS;\n return {\n from: addCalendarDays(startOfCalendarDay(to), -(resolvedDays - 1)),\n to,\n days: resolvedDays,\n };\n}\n\nfunction parseRequiredDate(value: string | undefined): number | undefined {\n if (!value) return undefined;\n const timestamp = new Date(value).getTime();\n if (Number.isNaN(timestamp)) throw new Error(`Invalid date: ${value}`);\n return timestamp;\n}\n\nfunction parseOptionalDate(value: string | undefined): number | undefined {\n if (value == null) return undefined;\n const timestamp = new Date(value).getTime();\n return Number.isNaN(timestamp) ? undefined : timestamp;\n}\n\nfunction parseDays(value: string | undefined): number | undefined {\n if (value == null) return undefined;\n const days = Number.parseInt(value, 10);\n return Number.isSafeInteger(days) && Number.isSafeInteger(days * ROLLING_DAY_MS)\n ? days\n : undefined;\n}\n","/**\n * Request-parameter parsing for the HTTP API. Everything here turns raw query\n * strings into the option objects the domain layer expects; no domain logic,\n * no storage access.\n */\nimport type { Context } from \"hono\";\nimport type { SessionHead, SmartTag } from \"@codesesh/core\";\nimport {\n filterSessionTreeByActivityWindow,\n isProjectIdentityKind,\n type FileActivityKind,\n type ProjectIdentityRef,\n type SearchOptions,\n} from \"@codesesh/core\";\nimport type { TimeWindow } from \"../time-window-resolution.js\";\n\nexport type SessionListDefaults = TimeWindow;\n\nconst SMART_TAGS: readonly string[] = [\n \"bugfix\",\n \"refactoring\",\n \"feature-dev\",\n \"testing\",\n \"docs\",\n \"git-ops\",\n \"build-deploy\",\n \"exploration\",\n \"planning\",\n];\n\nexport interface LimitPolicy {\n defaultValue: number;\n maxValue: number;\n}\n\nexport const SEARCH_LIMIT_POLICY: LimitPolicy = { defaultValue: 50, maxValue: 100 };\nexport const FILE_ACTIVITY_LIMIT_POLICY: LimitPolicy = { defaultValue: 50, maxValue: 200 };\nexport const SESSION_PAGE_LIMIT_POLICY: LimitPolicy = { defaultValue: 250, maxValue: 500 };\n\nexport type AgentFilterOutcome =\n | { kind: \"all\" }\n | { kind: \"known\"; agentName: string }\n | { kind: \"unknown\" };\n\nexport type LimitOutcome =\n | { kind: \"default\"; value: number }\n | { kind: \"valid\"; value: number }\n | { kind: \"invalid\"; error: string };\n\nexport type DateParamOutcome =\n | { kind: \"default\"; value: number | undefined }\n | { kind: \"valid\"; value: number }\n | { kind: \"invalid\"; error: string };\n\nexport type DateWindowOutcome =\n | { kind: \"valid\"; from: number | undefined; to: number | undefined }\n | { kind: \"invalid\"; parameter: \"from\" | \"to\"; error: string };\n\nexport interface SessionQuery {\n agent: AgentFilterOutcome;\n}\n\nexport interface LimitedSessionQuery extends SessionQuery {\n limit: LimitOutcome;\n}\n\nexport function searchParams(c: Context): URLSearchParams {\n return new URL(c.req.url ?? \"http://localhost/\", \"http://localhost/\").searchParams;\n}\n\n/** Collects repeated and comma-separated values across several parameter names. */\nexport function queryValues(params: URLSearchParams, ...names: string[]): string[] {\n return names.flatMap((name) =>\n params\n .getAll(name)\n .flatMap((value) => value.split(\",\"))\n .map((value) => value.trim())\n .filter(Boolean),\n );\n}\n\nexport function optionalQueryValue(value: string | undefined): string | undefined {\n const normalized = value?.trim();\n return normalized ? normalized : undefined;\n}\n\nexport function parseDateParam(\n value: string | undefined,\n fallback: number | undefined,\n): DateParamOutcome {\n const normalized = optionalQueryValue(value);\n if (normalized == null) return { kind: \"default\", value: fallback };\n const timestamp = new Date(normalized).getTime();\n return Number.isNaN(timestamp)\n ? { kind: \"invalid\", error: \"must be a valid date\" }\n : { kind: \"valid\", value: timestamp };\n}\n\nexport function parseDateWindow(\n params: URLSearchParams,\n defaults: SessionListDefaults,\n): DateWindowOutcome {\n const from = parseDateParam(params.get(\"from\") ?? undefined, defaults.from);\n if (from.kind === \"invalid\") return { ...from, parameter: \"from\" };\n\n const to = parseDateParam(params.get(\"to\") ?? undefined, defaults.to);\n if (to.kind === \"invalid\") return { ...to, parameter: \"to\" };\n\n if (from.value != null && to.value != null && from.value > to.value) {\n return { kind: \"invalid\", parameter: \"from\", error: \"must not be after to\" };\n }\n\n return { kind: \"valid\", from: from.value, to: to.value };\n}\n\nexport function parseNumberParam(value: string | undefined): number | undefined {\n if (value == null || !value.trim()) return undefined;\n const number = Number(value);\n return Number.isFinite(number) ? number : undefined;\n}\n\nfunction parseAgentFilter(\n value: string | null,\n knownAgentNames: Iterable<string>,\n): AgentFilterOutcome {\n if (value === null) return { kind: \"all\" };\n const normalized = value.trim().toLowerCase();\n if (!normalized) return { kind: \"unknown\" };\n\n for (const agentName of knownAgentNames) {\n if (agentName.toLowerCase() === normalized) return { kind: \"known\", agentName };\n }\n return { kind: \"unknown\" };\n}\n\nfunction parseLimit(value: string | null, policy: LimitPolicy): LimitOutcome {\n if (value === null) return { kind: \"default\", value: policy.defaultValue };\n const normalized = value.trim();\n if (!/^\\d+$/.test(normalized)) {\n return { kind: \"invalid\", error: \"limit must be a positive integer\" };\n }\n\n const digits = normalized.replace(/^0+/, \"\");\n if (!digits) return { kind: \"invalid\", error: \"limit must be a positive integer\" };\n const maxDigits = String(policy.maxValue);\n const exceedsMaximum =\n digits.length > maxDigits.length || (digits.length === maxDigits.length && digits > maxDigits);\n return { kind: \"valid\", value: exceedsMaximum ? policy.maxValue : Number(digits) };\n}\n\nexport function parseSessionQuery(\n params: URLSearchParams,\n knownAgentNames: Iterable<string>,\n): SessionQuery;\nexport function parseSessionQuery(\n params: URLSearchParams,\n knownAgentNames: Iterable<string>,\n limitPolicy: LimitPolicy,\n): LimitedSessionQuery;\nexport function parseSessionQuery(\n params: URLSearchParams,\n knownAgentNames: Iterable<string>,\n limitPolicy?: LimitPolicy,\n): SessionQuery | LimitedSessionQuery {\n const agent = parseAgentFilter(params.get(\"agent\"), knownAgentNames);\n return limitPolicy ? { agent, limit: parseLimit(params.get(\"limit\"), limitPolicy) } : { agent };\n}\n\nexport function parseSmartTags(values: string[]): SmartTag[] | undefined {\n const tags = values\n .map((value) => value.toLowerCase())\n .filter((value): value is SmartTag => SMART_TAGS.includes(value));\n return tags.length > 0 ? [...new Set(tags)] : undefined;\n}\n\nexport function parseFileActivityKind(value: string | undefined): FileActivityKind | undefined {\n if (value === \"read\" || value === \"edit\" || value === \"write\" || value === \"delete\") {\n return value;\n }\n return undefined;\n}\n\n/**\n * Returns the identity when both halves are present and valid, `undefined` when\n * neither is supplied, and `null` when the pair is incomplete or malformed —\n * callers turn that `null` into a 400.\n */\nexport function parseProjectIdentityFilter(\n kindValue: string | undefined,\n keyValue: string | undefined,\n): ProjectIdentityRef | null | undefined {\n const kind = optionalQueryValue(kindValue);\n const key = optionalQueryValue(keyValue);\n if (!kind && !key) return undefined;\n if (!kind || !key || !isProjectIdentityKind(kind)) return null;\n return { kind, key };\n}\n\nexport function parseSearchOptions(\n c: Context,\n window: SessionListDefaults,\n request: { agent?: string; limit: number },\n projectIdentity?: ProjectIdentityRef,\n): SearchOptions {\n const params = searchParams(c);\n return {\n agent: request.agent,\n project: optionalQueryValue(params.get(\"project\") ?? undefined),\n projectKind: projectIdentity?.kind,\n projectKey: projectIdentity?.key,\n cwd: optionalQueryValue(params.get(\"cwd\") ?? undefined),\n tags: parseSmartTags(queryValues(params, \"tag\", \"tags\", \"signal\")),\n tools: queryValues(params, \"tool\", \"tools\").map((tool) => tool.toLowerCase()),\n file: optionalQueryValue(params.get(\"file\") ?? params.get(\"path\") ?? undefined),\n fileKind: parseFileActivityKind(\n optionalQueryValue(params.get(\"fileKind\") ?? params.get(\"fileActivity\") ?? undefined),\n ),\n costMin: parseNumberParam(params.get(\"costMin\") ?? undefined),\n costMax: parseNumberParam(params.get(\"costMax\") ?? undefined),\n from: window.from,\n to: window.to,\n limit: request.limit,\n };\n}\n\nexport function filterSessionsByActivityWindow(\n sessions: SessionHead[],\n from: number | undefined,\n to: number | undefined,\n): SessionHead[] {\n return filterSessionTreeByActivityWindow(sessions, from, to);\n}\n","import { createHash, randomUUID } from \"node:crypto\";\n\ninterface CursorPayload {\n version: 1;\n snapshot: string;\n view: string;\n query: string;\n offset: number;\n}\n\ninterface PaginationRequest {\n cursor?: string;\n limit: number;\n query: URLSearchParams;\n snapshotIdentity: object;\n viewIdentity: object;\n}\n\nexport type PaginationResult<T> =\n | { kind: \"page\"; items: T[]; nextCursor?: string }\n | { kind: \"invalid_cursor\" }\n | { kind: \"stale_snapshot\" };\n\nconst identityVersions = new WeakMap<object, string>();\n\nfunction identityVersion(identity: object): string {\n const existing = identityVersions.get(identity);\n if (existing) return existing;\n const version = randomUUID();\n identityVersions.set(identity, version);\n return version;\n}\n\nfunction queryFingerprint(params: URLSearchParams): string {\n const canonical = new URLSearchParams(params);\n canonical.delete(\"cursor\");\n canonical.delete(\"limit\");\n canonical.sort();\n return createHash(\"sha256\").update(canonical.toString()).digest(\"base64url\");\n}\n\nfunction encodeCursor(payload: CursorPayload): string {\n return Buffer.from(JSON.stringify(payload)).toString(\"base64url\");\n}\n\nfunction decodeCursor(cursor: string): CursorPayload | null {\n if (!cursor || cursor.length > 512 || !/^[A-Za-z0-9_-]+$/.test(cursor)) return null;\n\n try {\n const value = JSON.parse(\n Buffer.from(cursor, \"base64url\").toString(\"utf8\"),\n ) as Partial<CursorPayload>;\n if (\n value.version !== 1 ||\n typeof value.snapshot !== \"string\" ||\n typeof value.view !== \"string\" ||\n typeof value.query !== \"string\" ||\n !Number.isSafeInteger(value.offset) ||\n value.offset! <= 0\n ) {\n return null;\n }\n return value as CursorPayload;\n } catch {\n return null;\n }\n}\n\n/** Keeps every page on the same immutable scan and alias read-model versions. */\nexport function paginateSessionSnapshot<T>(\n items: T[],\n request: PaginationRequest,\n): PaginationResult<T> {\n const snapshot = identityVersion(request.snapshotIdentity);\n const view = identityVersion(request.viewIdentity);\n const query = queryFingerprint(request.query);\n let offset = 0;\n\n if (request.cursor) {\n const cursor = decodeCursor(request.cursor);\n if (!cursor || cursor.query !== query) return { kind: \"invalid_cursor\" };\n if (cursor.snapshot !== snapshot || cursor.view !== view) {\n return { kind: \"stale_snapshot\" };\n }\n if (cursor.offset >= items.length) return { kind: \"invalid_cursor\" };\n offset = cursor.offset;\n }\n\n const end = Math.min(offset + request.limit, items.length);\n const nextCursor =\n end < items.length\n ? encodeCursor({ version: 1, snapshot, view, query, offset: end })\n : undefined;\n return {\n kind: \"page\",\n items: items.slice(offset, end),\n ...(nextCursor ? { nextCursor } : {}),\n };\n}\n","/**\n * Session aliases as a read model for the HTTP layer: load the user's local\n * renames once, then decorate outgoing records with `display_title`.\n */\nimport type { BookmarkView, SessionAlias, SessionHead } from \"@codesesh/core\";\nimport type { SearchResult, SessionReference } from \"@codesesh/core/contract\";\nimport {\n filterSessionSearchCandidates,\n getSessionActivityTime,\n listSessionAliases,\n mergeSearchQueryOptions,\n StateStorageUnavailableError,\n type FileActivityResult,\n type LiveSnapshot,\n type SearchOptions,\n} from \"@codesesh/core\";\nimport { appLogger } from \"../logging.js\";\n\n/** Anything the API returns that can carry a locally-renamed title. */\ntype Titled = { id: string; title: string; display_title?: string };\n\nexport interface AliasView {\n readonly size: number;\n get(reference: SessionReference): string | undefined;\n /** Returns the record unchanged when no alias applies, so callers can pass through freely. */\n decorate<T extends Titled>(record: T, reference: SessionReference): T;\n entries(): IterableIterator<SessionAlias>;\n}\n\nfunction aliasKey(reference: SessionReference): string {\n return `${reference.agentName.toLowerCase()}\\0${reference.sessionId}`;\n}\n\nfunction loadAliasMap(): Map<string, SessionAlias> {\n try {\n return new Map(listSessionAliases().map((alias) => [aliasKey(alias.reference), alias]));\n } catch (error) {\n if (!(error instanceof StateStorageUnavailableError)) {\n appLogger.warn(\"api.session_aliases.load_failed\", {\n error: error instanceof Error ? error.message : String(error),\n });\n }\n return new Map();\n }\n}\n\nfunction buildAliasView(): AliasView {\n const aliases = loadAliasMap();\n return {\n size: aliases.size,\n get: (reference) => aliases.get(aliasKey(reference))?.alias,\n decorate(record, reference) {\n const alias = aliases.get(aliasKey(reference))?.alias;\n return alias ? { ...record, display_title: alias } : record;\n },\n entries: () => aliases.values(),\n };\n}\n\n/**\n * Aliases change only through this process's own PUT/DELETE handlers, so the\n * read model is built once and reused until one of them invalidates it. Six read\n * handlers call this per request; without the cache each one re-queries the whole\n * table. A storage failure is cached too — it does not heal between requests, and\n * invalidateAliasView() is what lets a recovered store be retried.\n */\nlet cachedView: AliasView | null = null;\n\nexport function loadAliasView(): AliasView {\n return (cachedView ??= buildAliasView());\n}\n\nexport function invalidateAliasView(): void {\n cachedView = null;\n}\n\nexport function decorateBookmark(bookmark: BookmarkView, aliases: AliasView): BookmarkView {\n if (bookmark.availability === \"available\") {\n return {\n ...bookmark,\n session: aliases.decorate(bookmark.session, bookmark.reference),\n };\n }\n\n const displayTitle = aliases.get(bookmark.reference);\n return displayTitle ? { ...bookmark, display_title: displayTitle } : bookmark;\n}\n\nexport function decorateFileActivity(\n activity: FileActivityResult,\n aliases: AliasView,\n): FileActivityResult {\n return {\n ...activity,\n session: aliases.decorate(activity.session, activity.reference),\n };\n}\n\n/**\n * Aliases are stored outside the search index, so a query matching only a local\n * rename has to be resolved here. Hits still have to satisfy the same\n * time-window / project / agent filters as the main search, otherwise an aliased\n * session could surface outside its search scope.\n */\nexport function findAliasSearchResults(\n query: string,\n options: SearchOptions,\n scanResult: LiveSnapshot,\n aliases: AliasView,\n): SearchResult[] {\n const search = mergeSearchQueryOptions(query, options);\n const needle = search.text.trim().toLowerCase();\n if (!needle || aliases.size === 0) return [];\n\n const sessionsByAgent = new Map<string, Map<string, SessionHead>>();\n const lookupSession = (agentName: string, sessionId: string): SessionHead | undefined => {\n let byId = sessionsByAgent.get(agentName);\n if (!byId) {\n byId = new Map((scanResult.byAgent[agentName] ?? []).map((item) => [item.id, item]));\n sessionsByAgent.set(agentName, byId);\n }\n return byId.get(sessionId);\n };\n\n const results: SearchResult[] = [];\n for (const alias of aliases.entries()) {\n if (!alias.alias.toLowerCase().includes(needle)) continue;\n const { agentName, sessionId } = alias.reference;\n const session = lookupSession(agentName, sessionId);\n if (!session) continue;\n results.push({\n reference: alias.reference,\n session: aliases.decorate(session, alias.reference),\n snippet: `Alias · ${session.directory}`,\n snippetHighlights: [],\n matchType: \"title\",\n });\n }\n\n return filterSessionSearchCandidates(results, search.options, scanResult.sessions).sort(\n (a, b) => getSessionActivityTime(b.session) - getSessionActivityTime(a.session),\n );\n}\n","import type { Context } from \"hono\";\nimport type {\n BookmarkRecord,\n BookmarkView,\n LiveSnapshot,\n SessionDetail,\n SessionHead,\n SmartTag,\n} from \"@codesesh/core\";\nimport {\n addCalendarDays,\n countCalendarDays,\n createSessionIndex,\n buildSessionTree,\n filterSessionTreeByActivityWindow,\n formatSessionReference,\n getSessionAgentKey,\n getSessionRouteKey,\n normalizeSessionReference,\n type AppConfig,\n type ScanStatusEvent,\n type SearchResult,\n type SessionReference,\n startOfCalendarDay,\n} from \"@codesesh/core/contract\";\nimport {\n SessionAliasValidationError,\n StateStorageUnavailableError,\n attachProjectMetricsFromTree,\n createProjectScopeMatcher,\n deleteBookmark,\n getAgentInfoMap,\n executeSessionSearch,\n importBookmarks,\n listFileActivity,\n listCachedProjectGroups,\n loadCachedSessionHeads,\n listBookmarks,\n listModelCostDistribution,\n deleteSessionAlias,\n materializeSessionDetailResponse,\n materializeBookmarkViews,\n upsertSessionAlias,\n upsertBookmark,\n matchesProjectScope as sessionMatchesProjectScope,\n matchesProjectIdentity,\n buildDashboard,\n type DashboardData,\n type DashboardScope,\n} from \"@codesesh/core\";\nimport { appLogger } from \"../logging.js\";\nimport { resolveTimeWindow } from \"../time-window-resolution.js\";\nimport {\n filterSessionsByActivityWindow,\n FILE_ACTIVITY_LIMIT_POLICY,\n parseDateWindow,\n parseFileActivityKind,\n parseProjectIdentityFilter,\n parseSessionQuery,\n parseSearchOptions,\n optionalQueryValue,\n searchParams,\n SEARCH_LIMIT_POLICY,\n SESSION_PAGE_LIMIT_POLICY,\n type SessionListDefaults,\n} from \"./query-params.js\";\nimport { paginateSessionSnapshot } from \"./session-pagination.js\";\nimport {\n decorateBookmark,\n decorateFileActivity,\n findAliasSearchResults,\n invalidateAliasView,\n loadAliasView,\n type AliasView,\n} from \"./session-aliases-view.js\";\n\nexport type { SessionListDefaults };\n\nexport interface ScanResultSource {\n getSnapshot(): LiveSnapshot;\n}\n\nexport interface ScanStatusSource {\n getScanStatus(): ScanStatusEvent;\n}\n\nconst KNOWN_AGENT_NAMES = getAgentInfoMap({}).map((agent) => agent.name);\nconst KNOWN_AGENT_NAME_SET = new Set(KNOWN_AGENT_NAMES);\n\nfunction reportInvalidQueryParameter(\n endpoint: string,\n parameter: \"agent\" | \"cursor\" | \"limit\" | \"from\" | \"to\",\n validationOutcome: \"empty_result\" | \"rejected\",\n): void {\n appLogger.warn(\"api.query_parameter.invalid\", {\n endpoint,\n parameter,\n validation_outcome: validationOutcome,\n });\n}\n\nfunction parseDateWindowRequest(c: Context, endpoint: string, defaults: SessionListDefaults) {\n const outcome = parseDateWindow(searchParams(c), defaults);\n if (outcome.kind === \"valid\") return outcome;\n\n reportInvalidQueryParameter(endpoint, outcome.parameter, \"rejected\");\n return {\n kind: \"rejected\" as const,\n response: c.json({ error: `${outcome.parameter} ${outcome.error}` }, 400),\n };\n}\n\ninterface SnapshotAggregationCache {\n sessions: SessionHead[];\n values: Map<string, unknown>;\n}\n\nconst SNAPSHOT_AGGREGATION_CACHE_LIMIT = 64;\nconst snapshotAggregationCaches = new WeakMap<ScanResultSource, SnapshotAggregationCache>();\n\n/**\n * LiveScanStore replaces its canonical sessions array whenever the snapshot\n * changes, so that existing reference is the snapshot version.\n */\nfunction getSnapshotAggregation<T>(\n source: ScanResultSource,\n sessions: SessionHead[],\n key: readonly unknown[],\n build: () => T,\n): T {\n let cache = snapshotAggregationCaches.get(source);\n if (!cache || cache.sessions !== sessions) {\n cache = { sessions, values: new Map() };\n snapshotAggregationCaches.set(source, cache);\n }\n\n const cacheKey = JSON.stringify(key);\n if (cache.values.has(cacheKey)) return cache.values.get(cacheKey) as T;\n\n const value = build();\n if (cache.values.size >= SNAPSHOT_AGGREGATION_CACHE_LIMIT) {\n const oldestKey = cache.values.keys().next().value;\n if (oldestKey != null) cache.values.delete(oldestKey);\n }\n cache.values.set(cacheKey, value);\n return value;\n}\n\ninterface ClientLogPayload {\n event?: unknown;\n data?: unknown;\n}\n\ninterface SessionAliasPayload {\n alias?: unknown;\n}\n\nfunction withStorageErrors<TResult, TFallback>(\n handler: () => TResult,\n onUnavailable: () => TFallback,\n): TResult | TFallback {\n try {\n return handler();\n } catch (error) {\n if (error instanceof StateStorageUnavailableError) {\n return onUnavailable();\n }\n throw error;\n }\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null;\n}\n\nfunction parseSessionReferencePayload(value: unknown): SessionReference | null {\n if (\n !isRecord(value) ||\n typeof value.agentName !== \"string\" ||\n typeof value.sessionId !== \"string\" ||\n !value.agentName.trim() ||\n !value.sessionId\n ) {\n return null;\n }\n return normalizeSessionReference({\n agentName: value.agentName.trim().toLowerCase(),\n sessionId: value.sessionId,\n });\n}\n\nfunction parseBookmarkReference(value: unknown): SessionReference | null {\n if (!isRecord(value)) return null;\n\n const reference = parseSessionReferencePayload(value.reference);\n if (reference) return reference;\n\n if (\n typeof value.agentKey !== \"string\" ||\n typeof value.sessionId !== \"string\" ||\n !value.agentKey.trim() ||\n !value.sessionId\n ) {\n return null;\n }\n return normalizeSessionReference({\n agentName: value.agentKey.trim().toLowerCase(),\n sessionId: value.sessionId,\n });\n}\n\nfunction parseBookmarkImport(value: unknown): BookmarkRecord | null {\n if (!isRecord(value)) return null;\n const reference = parseBookmarkReference(value);\n if (!reference) return null;\n\n const timestamp = value.bookmarkedAt ?? value.bookmarked_at;\n if (timestamp != null && (typeof timestamp !== \"number\" || !Number.isFinite(timestamp))) {\n return null;\n }\n return {\n reference,\n bookmarkedAt: typeof timestamp === \"number\" ? timestamp : Date.now(),\n };\n}\n\nfunction sanitizeClientLogData(value: unknown): Record<string, unknown> {\n if (!isRecord(value)) return {};\n\n return Object.fromEntries(\n Object.entries(value)\n .slice(0, 30)\n .map(([key, item]) => {\n if (typeof item === \"string\") return [key, item.slice(0, 300)];\n if (typeof item === \"number\" || typeof item === \"boolean\" || item == null) {\n return [key, item];\n }\n return [key, String(item).slice(0, 300)];\n }),\n );\n}\n\nfunction toSessionListItem(session: SessionHead): SessionHead {\n const {\n model_usage: _modelUsage,\n project_identity_resolver_revision: _resolverRevision,\n project_identity_input_signature: _identityInputSignature,\n smart_tags_source_updated_at: _smartTagsSourceUpdatedAt,\n smart_tags_classifier_revision: _smartTagsClassifierRevision,\n ...item\n } = session;\n return item;\n}\n\nfunction getSessionHeadReference(session: SessionHead): SessionReference {\n return {\n agentName: getSessionAgentKey(session),\n sessionId: session.id,\n };\n}\n\nconst SESSION_DETAIL_STREAM_BATCH_CHARS = 64 * 1024;\n\nfunction createSessionDetailJsonResponse(\n data: Omit<SessionDetail, \"messages\">,\n messages: Iterable<string>,\n): Response {\n const encoder = new TextEncoder();\n const headerJson = JSON.stringify(data);\n const headerPrefix =\n headerJson === \"{}\" ? '{\"messages\":[' : `${headerJson.slice(0, -1)},\"messages\":[`;\n const iterator = messages[Symbol.iterator]();\n let wroteHeader = false;\n let wroteMessage = false;\n\n return new Response(\n new ReadableStream<Uint8Array>({\n pull(controller) {\n if (!wroteHeader) {\n controller.enqueue(encoder.encode(headerPrefix));\n wroteHeader = true;\n return;\n }\n\n const batch: string[] = [];\n let batchLength = 0;\n let next: IteratorResult<string>;\n try {\n next = iterator.next();\n while (!next.done) {\n const prefix = wroteMessage ? \",\" : \"\";\n batch.push(prefix, next.value);\n batchLength += prefix.length + next.value.length;\n wroteMessage = true;\n if (batchLength >= SESSION_DETAIL_STREAM_BATCH_CHARS) break;\n next = iterator.next();\n }\n } catch (error) {\n try {\n iterator.return?.();\n } catch {}\n controller.error(error);\n return;\n }\n\n if (next.done) {\n batch.push(\"]}\");\n controller.enqueue(encoder.encode(batch.join(\"\")));\n controller.close();\n return;\n }\n\n controller.enqueue(encoder.encode(batch.join(\"\")));\n },\n cancel() {\n iterator.return?.();\n },\n }),\n { headers: { \"Content-Type\": \"application/json; charset=UTF-8\" } },\n );\n}\n\nexport function handleGetConfig(c: Context, defaults: SessionListDefaults) {\n const payload: AppConfig = {\n window: {\n from: defaults.from,\n to: defaults.to,\n days: defaults.days,\n },\n };\n return c.json(payload);\n}\n\nexport function handleGetScanStatus(c: Context, scanSource: ScanStatusSource) {\n return c.json(scanSource.getScanStatus());\n}\n\nexport function handleGetAgents(\n c: Context,\n scanSource: ScanResultSource,\n defaults: SessionListDefaults = {},\n) {\n const scanResult = scanSource.getSnapshot();\n const window = parseDateWindowRequest(c, \"agents\", defaults);\n if (window.kind === \"rejected\") return window.response;\n const { from, to } = window;\n const agents = getSnapshotAggregation(\n scanSource,\n scanResult.sessions,\n [\"agents\", from, to],\n () => {\n const counts = Object.fromEntries(\n Object.entries(scanResult.byAgent).map(([agentName, sessions]) => [\n agentName,\n filterSessionsByActivityWindow(sessions, from, to).length,\n ]),\n );\n return getAgentInfoMap(counts);\n },\n );\n return c.json(agents);\n}\n\nexport function handleGetProjects(\n c: Context,\n scanSource: ScanResultSource,\n defaults: SessionListDefaults = {},\n) {\n const scanResult = scanSource.getSnapshot();\n const window = parseDateWindowRequest(c, \"projects\", defaults);\n if (window.kind === \"rejected\") return window.response;\n const { from, to } = window;\n const projects = getSnapshotAggregation(\n scanSource,\n scanResult.sessions,\n [\"projects\", from, to],\n () => {\n const tree = buildSessionTree(scanResult.sessions);\n const sessions = filterSessionTreeByActivityWindow(scanResult.sessions, from, to, tree);\n return {\n projects: attachProjectMetricsFromTree(listCachedProjectGroups(sessions), tree, from, to),\n };\n },\n );\n return c.json(projects);\n}\n\nexport function handleGetSessions(\n c: Context,\n scanSource: ScanResultSource,\n defaults: SessionListDefaults = {},\n) {\n const scanResult = scanSource.getSnapshot();\n const params = searchParams(c);\n const paginationRequested = params.has(\"limit\") || params.has(\"cursor\");\n const sessionQuery = parseSessionQuery(params, KNOWN_AGENT_NAMES, SESSION_PAGE_LIMIT_POLICY);\n if (sessionQuery.limit.kind === \"invalid\") {\n reportInvalidQueryParameter(\"sessions\", \"limit\", \"rejected\");\n return c.json({ error: sessionQuery.limit.error }, 400);\n }\n const q = c.req.query(\"q\")?.toLowerCase();\n const cwd = c.req.query(\"cwd\");\n const projectIdentity = parseProjectIdentityFilter(\n c.req.query(\"projectKind\"),\n c.req.query(\"projectKey\"),\n );\n if (projectIdentity === null) {\n return c.json({ error: \"projectKind and projectKey must form a valid project identity\" }, 400);\n }\n const tag = c.req.query(\"tag\")?.toLowerCase();\n const window = parseDateWindowRequest(c, \"sessions\", defaults);\n if (window.kind === \"rejected\") return window.response;\n const { from, to } = window;\n\n if (sessionQuery.agent.kind === \"unknown\") {\n reportInvalidQueryParameter(\"sessions\", \"agent\", \"empty_result\");\n }\n\n const agentFilter =\n sessionQuery.agent.kind === \"known\" ? sessionQuery.agent.agentName : sessionQuery.agent.kind;\n let sessions = getSnapshotAggregation(\n scanSource,\n scanResult.sessions,\n [\"sessions\", agentFilter, projectIdentity?.kind, projectIdentity?.key, cwd, tag, from, to],\n () => {\n let filtered =\n sessionQuery.agent.kind === \"all\"\n ? scanResult.sessions\n : sessionQuery.agent.kind === \"known\"\n ? (scanResult.byAgent[sessionQuery.agent.agentName] ?? [])\n : [];\n\n if (projectIdentity) {\n filtered = filtered.filter((session) =>\n matchesProjectIdentity(session.project_identity, projectIdentity),\n );\n } else if (cwd) {\n const projectScope = createProjectScopeMatcher(cwd);\n filtered = filtered.filter((session) => sessionMatchesProjectScope(session, projectScope));\n }\n filtered = filterSessionsByActivityWindow(filtered, from, to);\n return tag\n ? filtered.filter((session) => session.smart_tags?.includes(tag as SmartTag))\n : filtered;\n },\n );\n\n const aliases = loadAliasView();\n if (q) {\n sessions = sessions.filter((session) => {\n const alias = aliases.get(getSessionHeadReference(session));\n return session.title.toLowerCase().includes(q) || alias?.toLowerCase().includes(q);\n });\n }\n\n if (paginationRequested) {\n const page = paginateSessionSnapshot(sessions, {\n cursor: params.get(\"cursor\") ?? undefined,\n limit: sessionQuery.limit.value,\n query: params,\n snapshotIdentity: scanResult.sessions,\n viewIdentity: aliases,\n });\n if (page.kind === \"invalid_cursor\") {\n reportInvalidQueryParameter(\"sessions\", \"cursor\", \"rejected\");\n return c.json({ error: \"cursor is invalid for this request\" }, 400);\n }\n if (page.kind === \"stale_snapshot\") {\n return c.json({ error: \"session snapshot changed; restart pagination\" }, 409);\n }\n return c.json({\n sessions: page.items.map((session) =>\n toSessionListItem(aliases.decorate(session, getSessionHeadReference(session))),\n ),\n ...(page.nextCursor ? { nextCursor: page.nextCursor } : {}),\n });\n }\n\n return c.json({\n sessions: sessions.map((session) =>\n toSessionListItem(aliases.decorate(session, getSessionHeadReference(session))),\n ),\n });\n}\n\n/**\n * Sub-session hits render as 父 › 子, so each one needs its parent's title. The\n * index is built only when some hit actually has a parent — the common query\n * touches no sub-session at all.\n */\nfunction withParentContext(\n results: SearchResult[],\n sessions: SessionHead[],\n aliases: AliasView,\n): SearchResult[] {\n if (!results.some((result) => result.session.parent_reference)) return results;\n\n const byRouteKey = new Map(\n sessions.map((session) => [\n getSessionRouteKey(getSessionAgentKey(session), session.id),\n session,\n ]),\n );\n\n return results.map((result) => {\n const parentReference = result.session.parent_reference;\n if (!parentReference) return result;\n const parent = byRouteKey.get(formatSessionReference(parentReference));\n if (!parent) return result;\n const reference = normalizeSessionReference(parentReference);\n return { ...result, parent: { reference, title: aliases.get(reference) ?? parent.title } };\n });\n}\n\nconst ALIAS_SEARCH_RESULT_SHARE = 0.25;\n\nfunction searchResultKey(result: SearchResult): string {\n return `${result.reference.agentName}\\0${result.reference.sessionId}`;\n}\n\nfunction uniqueSearchResults(results: SearchResult[]): SearchResult[] {\n const seen = new Set<string>();\n return results.filter((result) => {\n const key = searchResultKey(result);\n if (seen.has(key)) return false;\n seen.add(key);\n return true;\n });\n}\n\nfunction mergeAliasSearchResults(\n rankedResults: SearchResult[],\n aliasResults: SearchResult[],\n limit: number,\n): SearchResult[] {\n if (limit <= 0) return [];\n\n const ranked = uniqueSearchResults(rankedResults);\n const rankedKeys = new Set(ranked.map(searchResultKey));\n const aliases = uniqueSearchResults(aliasResults).filter(\n (result) => !rankedKeys.has(searchResultKey(result)),\n );\n if (ranked.length === 0) return aliases.slice(0, limit);\n if (aliases.length === 0) return ranked.slice(0, limit);\n\n // Alias hits have no BM25 score. Keep ranked search dominant while reserving\n // a bounded share so local renames remain discoverable.\n const aliasQuota = Math.min(\n limit - 1,\n Math.max(1, Math.floor(limit * ALIAS_SEARCH_RESULT_SHARE)),\n );\n const rankedQuota = limit - aliasQuota;\n return [\n ...ranked.slice(0, rankedQuota),\n ...aliases.slice(0, aliasQuota),\n ...ranked.slice(rankedQuota),\n ...aliases.slice(aliasQuota),\n ].slice(0, limit);\n}\n\nexport function handleSearchSessions(\n c: Context,\n scanSource: ScanResultSource,\n defaults: SessionListDefaults = {},\n) {\n const query = c.req.query(\"q\")?.trim() ?? \"\";\n const scanResult = scanSource.getSnapshot();\n const sessionQuery = parseSessionQuery(searchParams(c), KNOWN_AGENT_NAMES, SEARCH_LIMIT_POLICY);\n if (sessionQuery.limit.kind === \"invalid\") {\n reportInvalidQueryParameter(\"search\", \"limit\", \"rejected\");\n return c.json({ error: sessionQuery.limit.error }, 400);\n }\n const projectIdentity = parseProjectIdentityFilter(\n c.req.query(\"projectKind\"),\n c.req.query(\"projectKey\"),\n );\n if (projectIdentity === null) {\n return c.json({ error: \"projectKind and projectKey must form a valid project identity\" }, 400);\n }\n const window = parseDateWindowRequest(c, \"search\", defaults);\n if (window.kind === \"rejected\") return window.response;\n if (sessionQuery.agent.kind === \"unknown\") {\n reportInvalidQueryParameter(\"search\", \"agent\", \"empty_result\");\n return c.json({ results: [] });\n }\n const searchOptions = parseSearchOptions(\n c,\n window,\n {\n agent: sessionQuery.agent.kind === \"known\" ? sessionQuery.agent.agentName : undefined,\n limit: sessionQuery.limit.value,\n },\n projectIdentity,\n );\n const aliases = loadAliasView();\n const results = executeSessionSearch(query, searchOptions, scanResult).map((result) => ({\n ...result,\n session: aliases.decorate(result.session, result.reference),\n }));\n const aliasResults = findAliasSearchResults(query, searchOptions, scanResult, aliases);\n const mergedResults = mergeAliasSearchResults(results, aliasResults, searchOptions.limit ?? 50);\n return c.json({\n results: withParentContext(mergedResults, scanResult.sessions, aliases),\n });\n}\n\nexport function handleGetFileActivity(c: Context, defaults: SessionListDefaults = {}) {\n const sessionQuery = parseSessionQuery(\n searchParams(c),\n KNOWN_AGENT_NAMES,\n FILE_ACTIVITY_LIMIT_POLICY,\n );\n if (sessionQuery.limit.kind === \"invalid\") {\n reportInvalidQueryParameter(\"file-activity\", \"limit\", \"rejected\");\n return c.json({ error: sessionQuery.limit.error }, 400);\n }\n const projectIdentity = parseProjectIdentityFilter(\n c.req.query(\"projectKind\"),\n c.req.query(\"projectKey\"),\n );\n if (projectIdentity === null) {\n return c.json({ error: \"projectKind and projectKey must form a valid project identity\" }, 400);\n }\n const window = parseDateWindowRequest(c, \"file-activity\", defaults);\n if (window.kind === \"rejected\") return window.response;\n if (sessionQuery.agent.kind === \"unknown\") {\n reportInvalidQueryParameter(\"file-activity\", \"agent\", \"empty_result\");\n return c.json({ activity: [] });\n }\n\n const aliases = loadAliasView();\n return c.json({\n activity: listFileActivity({\n agent: sessionQuery.agent.kind === \"known\" ? sessionQuery.agent.agentName : undefined,\n sessionId: optionalQueryValue(c.req.query(\"sessionId\")),\n projectKind: projectIdentity?.kind,\n projectKey: projectIdentity?.key,\n project: optionalQueryValue(c.req.query(\"project\")),\n cwd: optionalQueryValue(c.req.query(\"cwd\")),\n path: optionalQueryValue(c.req.query(\"path\")),\n kind: parseFileActivityKind(optionalQueryValue(c.req.query(\"kind\"))),\n from: window.from,\n to: window.to,\n limit: sessionQuery.limit.value,\n }).map((activity) => decorateFileActivity(activity, aliases)),\n });\n}\n\nexport async function handleGetSessionData(c: Context, scanSource: ScanResultSource) {\n const startedAt = performance.now();\n const agentName = c.req.param(\"agent\");\n const sessionId = c.req.param(\"id\");\n\n if (!agentName) {\n return c.json({ error: \"Missing agent name\" }, 400);\n }\n\n if (!sessionId) {\n return c.json({ error: \"Missing session ID\" }, 400);\n }\n\n try {\n const reference = {\n agentName,\n sessionId,\n };\n const messageCursor = optionalQueryValue(c.req.query(\"messageCursor\"));\n const result = messageCursor\n ? materializeSessionDetailResponse(scanSource.getSnapshot(), reference, { messageCursor })\n : materializeSessionDetailResponse(scanSource.getSnapshot(), reference);\n if (result.status === \"unknown-agent\") {\n return c.json({ error: `Unknown agent: ${agentName}` }, 404);\n }\n if (result.status === \"not-ready\") {\n appLogger.warn(\"api.session_data.cache_miss\", {\n agent: agentName,\n session_id: sessionId,\n duration_ms: Math.round(performance.now() - startedAt),\n });\n return c.json({ error: \"Session cache not ready\" }, 404);\n }\n\n appLogger.info(\"api.session_data\", {\n agent: agentName,\n session_id: sessionId,\n messages: result.status === \"found-json\" ? result.messageCount : result.data.messages.length,\n sent_messages:\n result.status === \"found-json\" ? result.sentMessageCount : result.data.messages.length,\n message_update: result.data.message_update ?? \"reset\",\n duration_ms: Math.round(performance.now() - startedAt),\n });\n const aliases = loadAliasView();\n if (result.status === \"found-json\") {\n return createSessionDetailJsonResponse(\n aliases.decorate(result.data, result.data.reference),\n result.messages,\n );\n }\n return c.json(aliases.decorate(result.data, result.data.reference));\n } catch (err) {\n const message = err instanceof Error ? err.message : \"Failed to load session\";\n appLogger.error(\"api.session_data.error\", {\n agent: agentName,\n session_id: sessionId,\n duration_ms: Math.round(performance.now() - startedAt),\n error: message,\n });\n return c.json({ error: \"Failed to load session\" }, 500);\n }\n}\n\nexport async function handlePostClientLog(c: Context) {\n const payload = (await c.req.json().catch(() => null)) as ClientLogPayload | null;\n const rawEvent = payload?.event;\n\n if (typeof rawEvent !== \"string\" || !rawEvent.trim()) {\n return c.json({ ok: false }, 400);\n }\n\n const event = rawEvent\n .trim()\n .replace(/[^a-zA-Z0-9_.:-]/g, \"_\")\n .slice(0, 120);\n appLogger.info(`client.${event}`, sanitizeClientLogData(payload?.data));\n return c.json({ ok: true });\n}\n\nfunction materializeStoredBookmarks(\n scanSource: ScanResultSource,\n bookmarks: readonly BookmarkRecord[],\n aliases: AliasView,\n): BookmarkView[] {\n const snapshot = scanSource.getSnapshot();\n const sessionIndex = getSnapshotAggregation(\n scanSource,\n snapshot.sessions,\n [\"bookmark-session-index\"],\n () => createSessionIndex(snapshot.sessions),\n );\n return materializeBookmarkViews(bookmarks, {\n liveSessionsByReference: sessionIndex.byRouteKey,\n knownAgentNames: KNOWN_AGENT_NAME_SET,\n resolveCachedSessions: loadCachedSessionHeads,\n }).map((bookmark) => decorateBookmark(bookmark, aliases));\n}\n\nexport function handleGetBookmarks(c: Context, scanSource: ScanResultSource) {\n return withStorageErrors(\n () => {\n const aliases = loadAliasView();\n const bookmarks = materializeStoredBookmarks(scanSource, listBookmarks(), aliases);\n return c.json({\n bookmarks,\n storageAvailable: true,\n });\n },\n () => c.json({ bookmarks: [], storageAvailable: false }),\n );\n}\n\nexport async function handlePutBookmark(c: Context) {\n const payload = parseBookmarkReference(await c.req.json().catch(() => null));\n if (!payload) {\n return c.json({ error: \"Invalid bookmark payload\" }, 400);\n }\n\n return withStorageErrors(\n () => c.json({ bookmark: upsertBookmark(payload), storageAvailable: true }),\n () => c.json({ error: \"Bookmark storage is unavailable\" }, 503),\n );\n}\n\nexport async function handleImportBookmarks(c: Context, scanSource: ScanResultSource) {\n const payload = await c.req.json().catch(() => null);\n if (!Array.isArray(payload)) {\n return c.json({ error: \"Invalid bookmark payload\" }, 400);\n }\n\n const bookmarks = payload\n .map((entry) => parseBookmarkImport(entry))\n .filter((entry): entry is NonNullable<typeof entry> => entry !== null);\n\n if (bookmarks.length !== payload.length) {\n return c.json({ error: \"Invalid bookmark payload\" }, 400);\n }\n\n return withStorageErrors(\n () => {\n const imported = importBookmarks(bookmarks);\n const views = materializeStoredBookmarks(scanSource, imported, loadAliasView());\n return c.json({ bookmarks: views, storageAvailable: true });\n },\n () => c.json({ error: \"Bookmark storage is unavailable\" }, 503),\n );\n}\n\nexport function handleDeleteBookmark(c: Context) {\n const agentKey = c.req.param(\"agent\");\n const sessionId = c.req.param(\"id\");\n if (!agentKey || !sessionId) {\n return c.json({ error: \"Missing bookmark identifier\" }, 400);\n }\n\n return withStorageErrors(\n () => {\n deleteBookmark({ agentName: agentKey, sessionId });\n return c.json({ ok: true, storageAvailable: true });\n },\n () => c.json({ error: \"Bookmark storage is unavailable\" }, 503),\n );\n}\n\nexport async function handlePutSessionAlias(c: Context) {\n const agentKey = c.req.param(\"agent\");\n const sessionId = c.req.param(\"id\");\n const payload = (await c.req.json().catch(() => null)) as SessionAliasPayload | null;\n const aliasValue = payload?.alias;\n if (!agentKey || !sessionId || typeof aliasValue !== \"string\") {\n return c.json({ error: \"Invalid session alias payload\" }, 400);\n }\n\n try {\n return withStorageErrors(\n () => {\n const alias = upsertSessionAlias({ agentName: agentKey, sessionId }, aliasValue);\n invalidateAliasView();\n return c.json({ alias });\n },\n () => c.json({ error: \"Session alias storage is unavailable\" }, 503),\n );\n } catch (error) {\n if (error instanceof SessionAliasValidationError) {\n return c.json({ error: \"Session alias must be non-empty and at most 160 characters\" }, 400);\n }\n throw error;\n }\n}\n\nexport function handleDeleteSessionAlias(c: Context) {\n const agentKey = c.req.param(\"agent\");\n const sessionId = c.req.param(\"id\");\n if (!agentKey || !sessionId) {\n return c.json({ error: \"Missing session alias identifier\" }, 400);\n }\n\n return withStorageErrors(\n () => {\n deleteSessionAlias({ agentName: agentKey, sessionId });\n invalidateAliasView();\n return c.json({ ok: true });\n },\n () => c.json({ error: \"Session alias storage is unavailable\" }, 503),\n );\n}\n\nexport function handleGetDashboard(\n c: Context,\n scanSource: ScanResultSource,\n defaults: SessionListDefaults = {},\n) {\n const scanResult = scanSource.getSnapshot();\n const projectIdentity = parseProjectIdentityFilter(\n c.req.query(\"projectKind\"),\n c.req.query(\"projectKey\"),\n );\n if (projectIdentity === null) {\n return c.json({ error: \"projectKind and projectKey must form a valid project identity\" }, 400);\n }\n const dateWindow = parseDateWindowRequest(c, \"dashboard\", defaults);\n if (dateWindow.kind === \"rejected\") return dateWindow.response;\n const { from, to, days } = resolveTimeWindow({\n mode: \"dashboard\",\n query: {\n days: c.req.query(\"days\"),\n from: c.req.query(\"from\"),\n to: c.req.query(\"to\"),\n },\n defaults,\n });\n const scope: DashboardScope = {\n agent: optionalQueryValue(c.req.query(\"agent\"))?.toLowerCase(),\n projectKind: projectIdentity?.kind,\n projectKey: projectIdentity?.key,\n };\n\n const compare =\n from == null\n ? undefined\n : { from: addCalendarDays(from, -(days ?? countCalendarDays(from, to))), to: from - 1 };\n\n const fixedTo = dateWindow.to;\n const aggregate = getSnapshotAggregation(\n scanSource,\n scanResult.sessions,\n [\n \"dashboard\",\n scope.agent,\n scope.projectKind,\n scope.projectKey,\n from,\n fixedTo ?? startOfCalendarDay(to),\n compare?.from,\n compare?.to,\n ],\n () => {\n const agentInfo = getAgentInfoMap({});\n const agentInfoMap = new Map(agentInfo.map((agent) => [agent.name, agent]));\n return buildDashboard(scanResult.sessions, {\n byAgentNames: Object.keys(scanResult.byAgent),\n scope,\n from,\n to,\n agentInfoMap,\n compare,\n });\n },\n );\n\n const data: DashboardData = {\n ...aggregate,\n recentFileActivities: listFileActivity({\n agent: scope.agent,\n projectKind: scope.projectKind,\n projectKey: scope.projectKey,\n from,\n to,\n limit: 12,\n }),\n modelCost: listModelCostDistribution({\n agent: scope.agent,\n projectKind: scope.projectKind,\n projectKey: scope.projectKey,\n from,\n to,\n }),\n window: { from, to, days, compareFrom: compare?.from, compareTo: compare?.to },\n };\n\n const aliases = loadAliasView();\n return c.json({\n ...data,\n recentSessions: data.recentSessions.map((item) => ({\n ...item,\n session: aliases.decorate(item.session, item.reference),\n })),\n recentFileActivities: data.recentFileActivities.map((activity) =>\n decorateFileActivity(activity, aliases),\n ),\n });\n}\n","import type { ScanStatusEvent } from \"@codesesh/core/contract\";\n\ninterface PendingFrame {\n bytes: Uint8Array;\n critical: boolean;\n}\n\nexport const MAX_PENDING_CRITICAL_SSE_FRAMES = 64;\n\nfunction scanStatusMilestone(status: ScanStatusEvent): string {\n const agentStates = Object.entries(status.agentStatuses)\n .sort(([left], [right]) => left.localeCompare(right))\n .map(([agentName, agentStatus]) => [agentName, agentStatus.status, agentStatus.error ?? null]);\n return JSON.stringify([\n status.active,\n status.phase,\n status.totalAgents,\n status.pendingAgents,\n status.scanningAgents,\n status.completedAgents,\n agentStates,\n status.backfill.active,\n status.backfill.currentAgent ?? null,\n status.backfill.pendingAgents,\n status.backfill.completedAgents,\n status.backfill.failedAgents,\n status.backfill.progress?.phase ?? null,\n status.searchIndexMaintenance?.active ?? false,\n status.searchIndexMaintenance?.currentAgent ?? null,\n status.searchIndexMaintenance?.pendingAgents ?? [],\n status.searchIndexMaintenance?.completedAgents ?? [],\n status.searchIndexMaintenance?.failedAgents ?? [],\n ]);\n}\n\nexport class SseEventBuffer {\n private readonly encoder = new TextEncoder();\n private readonly frames: PendingFrame[] = [];\n private replaceableStatus: PendingFrame | null = null;\n private lastStatusMilestone: string | null = null;\n private criticalFrameCount = 0;\n private isClosed = false;\n\n constructor(\n private readonly controller: ReadableStreamDefaultController<Uint8Array>,\n private readonly onOverflow: () => void,\n ) {}\n\n enqueue(event: string, data: unknown): void {\n if (!this.freezeReplaceableStatus()) return;\n this.appendCritical(this.frame(event, data));\n }\n\n enqueueScanStatus(status: ScanStatusEvent): void {\n if (this.isClosed) return;\n const milestone = scanStatusMilestone(status);\n const bytes = this.frame(status.type, status);\n\n if (this.lastStatusMilestone !== milestone) {\n if (!this.freezeReplaceableStatus()) return;\n this.lastStatusMilestone = milestone;\n this.appendCritical(bytes);\n return;\n }\n\n if (this.replaceableStatus) {\n this.replaceableStatus.bytes = bytes;\n return;\n }\n\n const frame = { bytes, critical: false };\n this.frames.push(frame);\n this.replaceableStatus = frame;\n this.drain();\n }\n\n enqueueHeartbeat(): void {\n if (\n this.isClosed ||\n this.frames.length > 0 ||\n this.controller.desiredSize == null ||\n this.controller.desiredSize <= 0\n ) {\n return;\n }\n this.controller.enqueue(this.encoder.encode(\": keepalive\\n\\n\"));\n }\n\n drain(): void {\n while (\n !this.isClosed &&\n this.frames.length > 0 &&\n this.controller.desiredSize != null &&\n this.controller.desiredSize > 0\n ) {\n const frame = this.frames.shift()!;\n if (frame === this.replaceableStatus) this.replaceableStatus = null;\n if (frame.critical) this.criticalFrameCount -= 1;\n this.controller.enqueue(frame.bytes);\n }\n }\n\n close(): void {\n this.isClosed = true;\n this.frames.length = 0;\n this.replaceableStatus = null;\n this.criticalFrameCount = 0;\n }\n\n private freezeReplaceableStatus(): boolean {\n if (!this.replaceableStatus) return !this.isClosed;\n if (this.criticalFrameCount >= MAX_PENDING_CRITICAL_SSE_FRAMES) {\n this.overflow();\n return false;\n }\n this.replaceableStatus.critical = true;\n this.replaceableStatus = null;\n this.criticalFrameCount += 1;\n return true;\n }\n\n private appendCritical(bytes: Uint8Array): void {\n if (this.isClosed) return;\n if (this.criticalFrameCount >= MAX_PENDING_CRITICAL_SSE_FRAMES) {\n this.overflow();\n return;\n }\n this.frames.push({ bytes, critical: true });\n this.criticalFrameCount += 1;\n this.drain();\n }\n\n private overflow(): void {\n if (this.isClosed) return;\n this.close();\n this.onOverflow();\n }\n\n private frame(event: string, data: unknown): Uint8Array {\n return this.encoder.encode(`event: ${event}\\ndata: ${JSON.stringify(data)}\\n\\n`);\n }\n}\n","import { isIP } from \"node:net\";\n\nexport type LoopbackAuthorityRejection =\n | \"listener-not-ready\"\n | \"missing-host\"\n | \"multiple-hosts\"\n | \"invalid-host\"\n | \"hostname-not-allowed\"\n | \"port-mismatch\";\n\nexport type LoopbackAuthorityDecision =\n | { allowed: true; authority: string }\n | { allowed: false; reason: LoopbackAuthorityRejection; authority?: string };\n\ninterface ParsedAuthority {\n hostname: string;\n port: number;\n normalized: string;\n}\n\nconst LOOPBACK_AUTHORITY_HOSTS = new Set([\"localhost\", \"127.0.0.1\", \"::1\"]);\n\nfunction canonicalizeHostname(hostname: string): string | null {\n const unwrapped = hostname.toLowerCase().replace(/^\\[(.*)\\]$/, \"$1\");\n const authorityHost = isIP(unwrapped) === 6 ? `[${unwrapped}]` : unwrapped;\n try {\n return new URL(`http://${authorityHost}`).hostname.toLowerCase().replace(/^\\[(.*)\\]$/, \"$1\");\n } catch {\n return null;\n }\n}\n\nfunction parseAuthority(value: string): ParsedAuthority | null {\n if (!value || value !== value.trim()) return null;\n const bracketed = /^\\[([^\\]]+)\\]:(\\d{1,5})$/.exec(value);\n const plain = /^([^:[\\]]+):(\\d{1,5})$/.exec(value);\n const match = bracketed ?? plain;\n if (!match) return null;\n\n const port = Number(match[2]);\n if (!Number.isInteger(port) || port < 1 || port > 65_535) return null;\n\n const rawHostname = match[1]!;\n const authorityHost = bracketed ? `[${rawHostname}]` : rawHostname;\n try {\n const parsed = new URL(`http://${authorityHost}:${port}`);\n if (parsed.username || parsed.password) return null;\n const hostname = parsed.hostname.toLowerCase().replace(/^\\[(.*)\\]$/, \"$1\");\n return {\n hostname,\n port,\n normalized: isIP(hostname) === 6 ? `[${hostname}]:${port}` : `${hostname}:${port}`,\n };\n } catch {\n return null;\n }\n}\n\nfunction hostHeaders(rawHeaders: readonly string[]): string[] {\n const values: string[] = [];\n for (let index = 0; index < rawHeaders.length; index += 2) {\n if (rawHeaders[index]?.toLowerCase() === \"host\") values.push(rawHeaders[index + 1] ?? \"\");\n }\n return values;\n}\n\nexport function validateLoopbackAuthority(\n rawHeaders: readonly string[],\n listenerHostname: string,\n listenerPort: number | null,\n): LoopbackAuthorityDecision {\n if (listenerPort === null) return { allowed: false, reason: \"listener-not-ready\" };\n\n const hosts = hostHeaders(rawHeaders);\n if (hosts.length === 0) return { allowed: false, reason: \"missing-host\" };\n if (hosts.length !== 1) return { allowed: false, reason: \"multiple-hosts\" };\n\n const authority = parseAuthority(hosts[0]!);\n if (!authority) return { allowed: false, reason: \"invalid-host\" };\n if (authority.port !== listenerPort) {\n return { allowed: false, reason: \"port-mismatch\", authority: authority.normalized };\n }\n\n const listener = canonicalizeHostname(listenerHostname);\n if (!LOOPBACK_AUTHORITY_HOSTS.has(authority.hostname) && authority.hostname !== listener) {\n return {\n allowed: false,\n reason: \"hostname-not-allowed\",\n authority: authority.normalized,\n };\n }\n\n return { allowed: true, authority: authority.normalized };\n}\n","import type { MiddlewareHandler } from \"hono\";\nimport { appLogger } from \"./logging.js\";\n\nconst SAFE_METHODS = new Set([\"GET\", \"HEAD\", \"OPTIONS\"]);\nconst JSON_BODY_METHODS = new Set([\"POST\", \"PUT\", \"PATCH\"]);\nconst ALLOWED_FETCH_SITES = new Set([\"same-origin\", \"none\"]);\n\nexport type LoopbackWriteRejection = \"content-type\" | \"fetch-site\" | \"origin\";\n\nexport type LoopbackWriteDecision =\n | { allowed: true }\n | { allowed: false; reason: LoopbackWriteRejection; status: 403 | 415 };\n\ninterface LoopbackWriteRequest {\n method: string;\n contentType?: string;\n fetchSite?: string;\n origin?: string;\n requestOrigin: string;\n}\n\nfunction mediaType(contentType: string | undefined): string | null {\n return contentType?.split(\";\", 1)[0]?.trim().toLowerCase() || null;\n}\n\nfunction isSameOrigin(origin: string, requestOrigin: string): boolean {\n try {\n return new URL(origin).origin === requestOrigin;\n } catch {\n return false;\n }\n}\n\nexport function evaluateLoopbackWriteRequest(request: LoopbackWriteRequest): LoopbackWriteDecision {\n const method = request.method.toUpperCase();\n if (SAFE_METHODS.has(method)) return { allowed: true };\n\n if (JSON_BODY_METHODS.has(method) && mediaType(request.contentType) !== \"application/json\") {\n return { allowed: false, reason: \"content-type\", status: 415 };\n }\n if (request.fetchSite && !ALLOWED_FETCH_SITES.has(request.fetchSite)) {\n return { allowed: false, reason: \"fetch-site\", status: 403 };\n }\n if (request.origin && !isSameOrigin(request.origin, request.requestOrigin)) {\n return { allowed: false, reason: \"origin\", status: 403 };\n }\n return { allowed: true };\n}\n\nexport function loopbackWriteGuard(): MiddlewareHandler {\n return async (c, next) => {\n const url = new URL(c.req.url);\n const decision = evaluateLoopbackWriteRequest({\n method: c.req.method,\n contentType: c.req.header(\"Content-Type\"),\n fetchSite: c.req.header(\"Sec-Fetch-Site\"),\n origin: c.req.header(\"Origin\"),\n requestOrigin: url.origin,\n });\n if (!decision.allowed) {\n appLogger.warn(\"http.loopback_write.rejected\", {\n method: c.req.method,\n path: url.pathname,\n reason: decision.reason,\n });\n const error =\n decision.reason === \"content-type\"\n ? \"Write requests require application/json\"\n : \"Cross-origin write request rejected\";\n return c.json({ error }, decision.status);\n }\n await next();\n };\n}\n","import { randomBytes, timingSafeEqual } from \"node:crypto\";\nimport { readFileSync } from \"node:fs\";\nimport { isIP } from \"node:net\";\nimport type { Context, MiddlewareHandler } from \"hono\";\n\nexport const REMOTE_ACCESS_QUERY_PARAM = \"access_token\";\n\n/**\n * How a remote listener's traffic is protected. A token proves who is asking;\n * it says nothing about who else can read the answer, so confidentiality is\n * modelled separately from authentication.\n */\nexport type RemoteTransport =\n | { kind: \"loopback\" }\n /** CodeSesh terminates TLS itself. */\n | { kind: \"tls\"; cert: Buffer; key: Buffer }\n /** A reverse proxy in front of CodeSesh terminates TLS. */\n | { kind: \"trusted-proxy\" }\n /** The operator accepted plaintext on an untrusted network. */\n | { kind: \"plaintext\" };\n\nexport interface RemoteAccessPolicy {\n bindCategory: \"loopback\" | \"network\";\n authenticationRequired: boolean;\n}\n\nexport interface RemoteTransportRequest {\n hostname: string;\n tlsCertPath?: string;\n tlsKeyPath?: string;\n trustProxy?: boolean;\n}\n\nexport class RemoteTransportError extends Error {}\n\n/**\n * Resolves the transport from the CLI flags. Loopback stays plaintext without\n * ceremony: nothing leaves the machine.\n */\nexport function resolveRemoteTransport(request: RemoteTransportRequest): RemoteTransport {\n const hasCert = Boolean(request.tlsCertPath);\n const hasKey = Boolean(request.tlsKeyPath);\n if (hasCert !== hasKey) {\n throw new RemoteTransportError(\"TLS requires both --tls-cert and --tls-key.\");\n }\n if (hasCert && request.trustProxy) {\n throw new RemoteTransportError(\n \"Use either --tls-cert/--tls-key or --trust-proxy, not both: only one of them terminates TLS.\",\n );\n }\n\n if (hasCert) {\n try {\n return {\n kind: \"tls\",\n cert: readFileSync(request.tlsCertPath!),\n key: readFileSync(request.tlsKeyPath!),\n };\n } catch (error) {\n throw new RemoteTransportError(\n `Unable to read the TLS certificate or key: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n\n if (request.trustProxy) return { kind: \"trusted-proxy\" };\n return isLoopbackHostname(request.hostname) ? { kind: \"loopback\" } : { kind: \"plaintext\" };\n}\n\n/** Whether the transport keeps request and response bodies off the wire in the clear. */\nexport function isConfidentialTransport(transport: RemoteTransport): boolean {\n return transport.kind !== \"plaintext\";\n}\n\nexport function resolveRemoteAccessPolicy(\n hostname: string,\n transport: RemoteTransport,\n): RemoteAccessPolicy {\n const bindCategory = isLoopbackHostname(hostname) ? \"loopback\" : \"network\";\n return {\n bindCategory,\n authenticationRequired: bindCategory === \"network\" || transport.kind !== \"loopback\",\n };\n}\n\nconst FORWARDED_PROTO_HEADER = \"X-Forwarded-Proto\";\n\n/**\n * Behind a trusted proxy, a request arriving without the proxy's own\n * `X-Forwarded-Proto: https` did not come through it. Trusting the header is\n * only sound because the deployment is expected to make CodeSesh unreachable\n * except via that proxy — which is what --trust-proxy asserts.\n */\nexport function requireProxyTls(): MiddlewareHandler {\n return async (c, next) => {\n const proto = c.req.header(FORWARDED_PROTO_HEADER)?.split(\",\")[0]?.trim().toLowerCase();\n if (proto !== \"https\") {\n return c.json({ error: \"Requests must arrive over TLS through the trusted proxy\" }, 403);\n }\n await next();\n };\n}\n\nexport function createRemoteAccessToken(): string {\n return randomBytes(32).toString(\"base64url\");\n}\n\nexport function isLoopbackHostname(hostname: string): boolean {\n const normalized = hostname.toLowerCase().replace(/^\\[(.*)\\]$/, \"$1\");\n if (normalized === \"localhost\" || normalized === \"::1\") return true;\n return isIP(normalized) === 4 && normalized.startsWith(\"127.\");\n}\n\nfunction tokenMatches(actual: string | undefined, expected: string): boolean {\n if (!actual) return false;\n const actualBuffer = Buffer.from(actual);\n const expectedBuffer = Buffer.from(expected);\n return (\n actualBuffer.length === expectedBuffer.length && timingSafeEqual(actualBuffer, expectedBuffer)\n );\n}\n\nfunction bearerToken(c: Context): string | undefined {\n const authorization = c.req.header(\"Authorization\");\n if (!authorization?.startsWith(\"Bearer \")) return undefined;\n return authorization.slice(\"Bearer \".length);\n}\n\nfunction requestToken(c: Context): string | undefined {\n const bearer = bearerToken(c);\n if (bearer) return bearer;\n if (c.req.method !== \"GET\") return undefined;\n return c.req.query(REMOTE_ACCESS_QUERY_PARAM);\n}\n\nexport function remoteAccessAuth(expectedToken: string): MiddlewareHandler {\n return async (c, next) => {\n if (!tokenMatches(requestToken(c), expectedToken)) {\n return c.json({ error: \"Remote access authentication required\" }, 401);\n }\n await next();\n };\n}\n","import { existsSync } from \"node:fs\";\nimport { fileURLToPath } from \"node:url\";\nimport {\n closeCacheStorage,\n createRegisteredAgents,\n scanSessions,\n type LiveSnapshot,\n type ScanOptions,\n} from \"@codesesh/core\";\nimport type {\n AgentScanStatus,\n BackfillStatus,\n SearchIndexMaintenanceStatus,\n ScanStatusEvent,\n SessionsUpdatedEvent,\n} from \"@codesesh/core/contract\";\nimport { mergeSessionsUpdatedEvents } from \"@codesesh/core/contract\";\nimport { AgentSyncEngine } from \"./agent-sync-engine.js\";\nimport { appLogger } from \"./logging.js\";\nimport { SessionWatcher } from \"./session-watcher.js\";\nimport { ThreadWorkerRunner, type WorkerRunner } from \"./worker-runner.js\";\n\nexport type {\n AgentScanStatus,\n BackfillStatus,\n SearchIndexMaintenanceStatus,\n ScanStatusEvent,\n SessionsUpdatedEvent,\n};\n\ntype StoreListener = (event: SessionsUpdatedEvent) => void;\ntype ScanStatusListener = (event: ScanStatusEvent) => void;\n\nexport interface LiveScanStoreOptions {\n watchEnabled?: boolean;\n scanOptions?: ScanOptions;\n startupScanOptions?: Pick<ScanOptions, \"from\" | \"to\">;\n deferInitialRefresh?: boolean;\n workerRunner?: WorkerRunner;\n}\n\nconst NEW_SESSION_EVENT_WINDOW_MS = 250;\n\nexport class LiveScanStore {\n private readonly watchEnabled: boolean;\n private readonly scanOptions: ScanOptions;\n private readonly startupScanOptions: Pick<ScanOptions, \"from\" | \"to\">;\n private readonly deferInitialRefresh: boolean;\n private readonly syncEngine: AgentSyncEngine;\n private listeners = new Set<StoreListener>();\n private watcher: SessionWatcher | null = null;\n private pendingEvent: SessionsUpdatedEvent | null = null;\n private pendingEventTimer: NodeJS.Timeout | null = null;\n private shutdownPromise: Promise<void> | null = null;\n private shuttingDown = false;\n\n constructor(options: LiveScanStoreOptions = {}) {\n this.watchEnabled = options.watchEnabled ?? true;\n this.scanOptions = options.scanOptions ?? {};\n this.startupScanOptions = options.startupScanOptions ?? {};\n this.deferInitialRefresh = options.deferInitialRefresh === true;\n const workerRunner =\n options.workerRunner ??\n new ThreadWorkerRunner(new URL(\"./scan-refresh-worker.js\", import.meta.url));\n this.syncEngine = new AgentSyncEngine({\n startupScanOptions: this.startupScanOptions,\n workerRunner,\n });\n this.syncEngine.subscribeSessionsChanged((change) => {\n if (change.event) this.emit(change.event);\n });\n }\n\n async initialize(): Promise<void> {\n const startedAt = performance.now();\n appLogger.info(\"scan.initial.start\", {\n watch_enabled: this.watchEnabled,\n agents: this.scanOptions.agents,\n use_cache: this.scanOptions.useCache ?? true,\n startup_from: this.startupScanOptions.from,\n startup_to: this.startupScanOptions.to,\n deferred: this.deferInitialRefresh || undefined,\n });\n const initialResult = await scanSessions({\n ...this.scanOptions,\n useCache: this.scanOptions.useCache ?? true,\n smartRefresh: false,\n cacheOnly: this.deferInitialRefresh,\n writeCache: this.deferInitialRefresh ? false : this.scanOptions.writeCache,\n smartTagWorkerUrl: this.getSmartTagWorkerUrl() ?? undefined,\n includeSmartTags: this.deferInitialRefresh ? false : undefined,\n });\n this.syncEngine.initialize(initialResult, {\n cacheTimestamps: initialResult.cacheTimestamps,\n registeredAgents: createRegisteredAgents(),\n allowedAgents: this.getAllowedAgents(),\n });\n const snapshot = this.getSnapshot();\n const indexStartedAt = performance.now();\n if (!this.deferInitialRefresh) {\n // The snapshot is already served from memory, so an index-write failure\n // degrades search freshness rather than startup.\n await this.syncEngine.syncInitialIndex().catch((error: unknown) => {\n appLogger.error(\"scan.initial.index_failed\", { error });\n });\n }\n const indexDuration = performance.now() - indexStartedAt;\n appLogger.info(\"scan.initial.done\", {\n duration_ms: Math.round(performance.now() - startedAt),\n index_ms: this.deferInitialRefresh ? undefined : Math.round(indexDuration),\n deferred: this.deferInitialRefresh || undefined,\n sessions: snapshot.sessions.length,\n agents: Object.fromEntries(\n Object.entries(snapshot.byAgent).map(([key, value]) => [key, value.length]),\n ),\n agent_timings: initialResult.timings\n ? Object.fromEntries(\n Object.entries(initialResult.timings).map(([name, timing]) => [\n name,\n {\n total_ms: Math.round(timing.total),\n cache_load_ms: timing.cacheLoad != null ? Math.round(timing.cacheLoad) : undefined,\n check_changes_ms:\n timing.checkChanges != null ? Math.round(timing.checkChanges) : undefined,\n scan_ms: timing.scan != null ? Math.round(timing.scan) : undefined,\n identity_ms: timing.identity != null ? Math.round(timing.identity) : undefined,\n tags_ms: timing.tags != null ? Math.round(timing.tags) : undefined,\n },\n ]),\n )\n : undefined,\n });\n if (!this.watchEnabled) return;\n this.watcher = new SessionWatcher();\n this.watcher.onAgentsChanged((agentNames) => this.syncEngine.handleAgentsChanged(agentNames));\n this.watcher.start(snapshot.agents);\n }\n\n startBackgroundRefresh(): void {\n this.syncEngine.startBackgroundRefresh();\n }\n\n getSnapshot(): LiveSnapshot {\n return this.syncEngine.snapshot();\n }\n\n getScanStatus(): ScanStatusEvent {\n return this.syncEngine.status();\n }\n\n subscribe(listener: StoreListener): () => void {\n this.listeners.add(listener);\n return () => this.listeners.delete(listener);\n }\n\n subscribeScanStatus(listener: ScanStatusListener): () => void {\n return this.syncEngine.subscribeStatusChanged(listener);\n }\n\n shutdown(): Promise<void> {\n this.shutdownPromise ??= this.performShutdown();\n return this.shutdownPromise;\n }\n\n private async performShutdown(): Promise<void> {\n this.shuttingDown = true;\n if (this.pendingEventTimer) {\n clearTimeout(this.pendingEventTimer);\n this.pendingEventTimer = null;\n }\n await this.syncEngine.shutdown();\n this.pendingEvent = null;\n if (this.watcher) {\n await this.watcher.dispose();\n this.watcher = null;\n }\n closeCacheStorage();\n }\n\n private emit(event: SessionsUpdatedEvent): void {\n if (this.shuttingDown) return;\n if (this.pendingEvent || event.newSessions > 0) {\n this.queueEvent(event);\n return;\n }\n this.emitNow(event);\n }\n\n private emitNow(event: SessionsUpdatedEvent): void {\n for (const listener of this.listeners) listener(event);\n }\n\n private queueEvent(event: SessionsUpdatedEvent): void {\n this.pendingEvent = this.pendingEvent\n ? mergeSessionsUpdatedEvents(this.pendingEvent, event)\n : event;\n if (this.pendingEventTimer) return;\n this.pendingEventTimer = setTimeout(() => {\n const pending = this.pendingEvent;\n this.pendingEvent = null;\n this.pendingEventTimer = null;\n if (pending) this.emitNow(pending);\n }, NEW_SESSION_EVENT_WINDOW_MS);\n }\n\n private getSmartTagWorkerUrl(): URL | null {\n const workerUrl = new URL(\"./smart-tag-worker.js\", import.meta.url);\n if (workerUrl.protocol === \"file:\" && !existsSync(fileURLToPath(workerUrl))) return null;\n return workerUrl;\n }\n\n private getAllowedAgents(): Set<string> | null {\n if (!this.scanOptions.agents?.length) return null;\n return new Set(this.scanOptions.agents.map((agent) => agent.toLowerCase()));\n }\n}\n","import { appLogger } from \"./logging.js\";\n\nexport type AgentOperationKind = \"backfill\" | \"refresh\";\nexport type AgentOperationResult = \"committed\" | \"failed\" | \"skipped\" | \"unchanged\";\n\ninterface AgentScheduleState {\n timer: NodeJS.Timeout | null;\n timerDeadline: number;\n isRefreshRunning: boolean;\n hasPendingRefresh: boolean;\n lastRefreshDurationMs: number;\n pendingSignalCount: number;\n}\n\ninterface AgentOperationLifecycle {\n agentName: string;\n kind: AgentOperationKind;\n generation: number;\n startedAt: number;\n}\n\nexport interface AgentOperationSchedulerSnapshot {\n activeOperations: number;\n activeRefreshes: number;\n}\n\nconst PENDING_REFRESH_DELAY_MS = 100;\nconst MAX_ADAPTIVE_REFRESH_DELAY_MS = 30_000;\nconst ADAPTIVE_REFRESH_DELAY_MULTIPLIER = 4;\n\nexport class AgentOperationScheduler {\n private readonly states = new Map<string, AgentScheduleState>();\n private readonly operationGenerations = new Map<string, number>();\n private readonly operationTails = new Map<string, Promise<void>>();\n private isStopped = false;\n\n constructor(private readonly runRefresh: (agentName: string) => Promise<AgentOperationResult>) {}\n\n notify(agentName: string, delayMs: number): void {\n if (this.isStopped) return;\n this.state(agentName).pendingSignalCount += 1;\n this.schedule(agentName, delayMs);\n }\n\n schedule(agentName: string, delayMs: number): void {\n if (this.isStopped) return;\n const state = this.state(agentName);\n const adaptiveDelayMs = Math.min(\n state.lastRefreshDurationMs * ADAPTIVE_REFRESH_DELAY_MULTIPLIER,\n MAX_ADAPTIVE_REFRESH_DELAY_MS,\n );\n const effectiveDelayMs = Math.max(delayMs, adaptiveDelayMs);\n const deadline = Date.now() + effectiveDelayMs;\n if (state.timer) {\n if (deadline >= state.timerDeadline) return;\n clearTimeout(state.timer);\n }\n\n appLogger.debug(\"scan.refresh.schedule\", { agent: agentName, delay_ms: effectiveDelayMs });\n state.timerDeadline = deadline;\n state.timer = setTimeout(() => {\n state.timer = null;\n state.timerDeadline = 0;\n void this.refresh(agentName);\n }, effectiveDelayMs);\n }\n\n async refresh(agentName: string): Promise<void> {\n if (this.isStopped) return;\n const state = this.state(agentName);\n if (state.isRefreshRunning) {\n appLogger.debug(\"scan.refresh.pending\", { agent: agentName });\n state.hasPendingRefresh = true;\n return;\n }\n\n state.isRefreshRunning = true;\n try {\n await this.run(agentName, \"refresh\", () => this.runRefresh(agentName));\n } finally {\n state.isRefreshRunning = false;\n if (state.hasPendingRefresh && !this.isStopped) {\n state.hasPendingRefresh = false;\n this.schedule(agentName, PENDING_REFRESH_DELAY_MS);\n }\n }\n }\n\n run<Result extends AgentOperationResult>(\n agentName: string,\n kind: AgentOperationKind,\n operation: () => Promise<Result>,\n ): Promise<Result | \"skipped\"> {\n const previous = this.operationTails.get(agentName) ?? Promise.resolve();\n const run = previous.then(async () => {\n if (this.isStopped) return \"skipped\";\n const lifecycle = this.beginOperation(agentName, kind);\n try {\n const result = await operation();\n this.completeOperation(lifecycle, result);\n return result;\n } catch (error) {\n this.completeOperation(lifecycle, \"failed\");\n throw error;\n }\n });\n const tail = run.then(\n () => undefined,\n () => undefined,\n );\n this.operationTails.set(agentName, tail);\n void tail.finally(() => {\n if (this.operationTails.get(agentName) === tail) this.operationTails.delete(agentName);\n });\n return run;\n }\n\n takePendingSignalCount(agentName: string): number {\n const state = this.state(agentName);\n const count = state.pendingSignalCount;\n state.pendingSignalCount = 0;\n return count;\n }\n\n recordRefreshDuration(agentName: string, durationMs: number): void {\n this.state(agentName).lastRefreshDurationMs = durationMs;\n }\n\n snapshot(): AgentOperationSchedulerSnapshot {\n return {\n activeOperations: this.operationTails.size,\n activeRefreshes: [...this.states.values()].filter((state) => state.isRefreshRunning).length,\n };\n }\n\n stop(): void {\n this.isStopped = true;\n for (const state of this.states.values()) {\n if (state.timer) clearTimeout(state.timer);\n state.timer = null;\n state.timerDeadline = 0;\n state.hasPendingRefresh = false;\n state.pendingSignalCount = 0;\n }\n }\n\n async waitForIdle(): Promise<void> {\n await Promise.allSettled(this.operationTails.values());\n }\n\n private state(agentName: string): AgentScheduleState {\n const existing = this.states.get(agentName);\n if (existing) return existing;\n const state: AgentScheduleState = {\n timer: null,\n timerDeadline: 0,\n isRefreshRunning: false,\n hasPendingRefresh: false,\n lastRefreshDurationMs: 0,\n pendingSignalCount: 0,\n };\n this.states.set(agentName, state);\n return state;\n }\n\n private beginOperation(agentName: string, kind: AgentOperationKind): AgentOperationLifecycle {\n const generation = (this.operationGenerations.get(agentName) ?? 0) + 1;\n const startedAt = Date.now();\n this.operationGenerations.set(agentName, generation);\n appLogger.info(\"scan.agent_operation.started\", {\n agent: agentName,\n operation: kind,\n generation,\n started_at: startedAt,\n });\n return { agentName, kind, generation, startedAt };\n }\n\n private completeOperation(\n lifecycle: AgentOperationLifecycle,\n result: AgentOperationResult,\n ): void {\n const completedAt = Date.now();\n appLogger.info(\"scan.agent_operation.completed\", {\n agent: lifecycle.agentName,\n operation: lifecycle.kind,\n generation: lifecycle.generation,\n started_at: lifecycle.startedAt,\n completed_at: completedAt,\n duration_ms: completedAt - lifecycle.startedAt,\n result,\n });\n }\n}\n","import type { BackfillProgress, BackfillStatus } from \"@codesesh/core/contract\";\n\nexport type BackfillTerminalStatus = \"committed\" | \"failed\" | \"skipped\";\n\nexport interface BackfillAttemptRef {\n agentName: string;\n attemptId: number;\n}\n\nexport type BackfillAttemptState =\n | (BackfillAttemptRef & { status: \"queued\" })\n | (BackfillAttemptRef & { status: \"running\"; progress?: BackfillProgress })\n | (BackfillAttemptRef & { status: BackfillTerminalStatus | \"cancelled\" });\n\nexport class BackfillLifecycle {\n private readonly attempts = new Map<string, BackfillAttemptState>();\n private nextAttemptId = 1;\n\n enqueue(agentName: string): BackfillAttemptRef | null {\n const current = this.attempts.get(agentName);\n if (current?.status === \"queued\" || current?.status === \"running\") return null;\n\n const attempt: BackfillAttemptState = {\n agentName,\n attemptId: this.nextAttemptId++,\n status: \"queued\",\n };\n this.attempts.set(agentName, attempt);\n return attempt;\n }\n\n startNext(): BackfillAttemptRef | null {\n if ([...this.attempts.values()].some((attempt) => attempt.status === \"running\")) return null;\n\n const queued = [...this.attempts.values()]\n .filter((attempt) => attempt.status === \"queued\")\n .sort((left, right) => left.attemptId - right.attemptId)[0];\n if (!queued) return null;\n\n const running: BackfillAttemptState = { ...queued, status: \"running\" };\n this.attempts.set(running.agentName, running);\n return running;\n }\n\n updateProgress(attempt: BackfillAttemptRef, progress: BackfillProgress): boolean {\n const current = this.matchingRunningAttempt(attempt);\n if (!current) return false;\n this.attempts.set(attempt.agentName, {\n ...current,\n progress: { ...current.progress, ...progress },\n });\n return true;\n }\n\n complete(attempt: BackfillAttemptRef, status: BackfillTerminalStatus): boolean {\n if (!this.matchingRunningAttempt(attempt)) return false;\n this.attempts.set(attempt.agentName, { ...attempt, status });\n return true;\n }\n\n cancelAll(): void {\n for (const [agentName, attempt] of this.attempts) {\n if (attempt.status === \"queued\" || attempt.status === \"running\") {\n this.attempts.set(agentName, { ...attempt, status: \"cancelled\" });\n }\n }\n }\n\n runningAttempt(): BackfillAttemptRef | null {\n const running = [...this.attempts.values()].find((attempt) => attempt.status === \"running\");\n return running ?? null;\n }\n\n stateFor(agentName: string): BackfillAttemptState | undefined {\n const state = this.attempts.get(agentName);\n if (!state) return undefined;\n return state.status === \"running\" && state.progress\n ? { ...state, progress: { ...state.progress } }\n : { ...state };\n }\n\n status(): BackfillStatus {\n const states = [...this.attempts.values()];\n const queued = states\n .filter((attempt) => attempt.status === \"queued\")\n .sort((left, right) => left.attemptId - right.attemptId);\n const running = states.find((attempt) => attempt.status === \"running\");\n const status: BackfillStatus = {\n active: running != null || queued.length > 0,\n pendingAgents: queued.map((attempt) => attempt.agentName),\n completedAgents: states\n .filter((attempt) => attempt.status === \"committed\")\n .map((attempt) => attempt.agentName),\n failedAgents: states\n .filter((attempt) => attempt.status === \"failed\")\n .map((attempt) => attempt.agentName),\n };\n if (running) {\n status.currentAgent = running.agentName;\n if (running.progress) status.progress = { ...running.progress };\n }\n return status;\n }\n\n private matchingRunningAttempt(\n attempt: BackfillAttemptRef,\n ): Extract<BackfillAttemptState, { status: \"running\" }> | null {\n const current = this.attempts.get(attempt.agentName);\n return current?.status === \"running\" && current.attemptId === attempt.attemptId\n ? current\n : null;\n }\n}\n","import {\n computeSessionDiff,\n mergeSortedSessions,\n sessionSignature,\n sortSessions,\n type AgentScanFailure,\n type BaseAgent,\n type LiveSnapshot,\n type SessionHead,\n} from \"@codesesh/core\";\nimport { createSessionProjectionContext, type SessionsUpdatedEvent } from \"@codesesh/core/contract\";\n\nexport interface LiveSessionIndexOptions {\n registeredAgents?: BaseAgent[];\n allowedAgents?: ReadonlySet<string> | null;\n}\n\nexport class LiveSessionIndex {\n private agents: BaseAgent[] = [];\n private agentsByName = new Map<string, BaseAgent>();\n private byAgent: Record<string, SessionHead[]> = {};\n private sessions: SessionHead[] = [];\n private scanFailures: Record<string, AgentScanFailure> = {};\n private signatureCaches = new Map<string, Map<string, string>>();\n\n initialize(snapshot: LiveSnapshot, options: LiveSessionIndexOptions = {}): void {\n const agentMap = new Map<string, BaseAgent>();\n for (const agent of snapshot.agents) agentMap.set(agent.name, agent);\n for (const agent of options.registeredAgents ?? []) {\n if (!agentMap.has(agent.name)) agentMap.set(agent.name, agent);\n }\n\n this.agents = [...agentMap.values()].filter(\n (agent) => !options.allowedAgents || options.allowedAgents.has(agent.name.toLowerCase()),\n );\n this.agentsByName = new Map(this.agents.map((agent) => [agent.name, agent]));\n this.scanFailures = { ...snapshot.scanFailures };\n this.byAgent = Object.fromEntries(\n this.agents.flatMap((agent) => {\n if (this.scanFailures[agent.name] && !(agent.name in snapshot.byAgent)) return [];\n return [[agent.name, sortSessions(snapshot.byAgent[agent.name] ?? [])]];\n }),\n );\n this.sessions = mergeSortedSessions(Object.values(this.byAgent));\n this.signatureCaches.clear();\n }\n\n snapshot(): LiveSnapshot {\n return {\n agents: this.agents,\n byAgent: this.byAgent,\n sessions: this.sessions,\n ...(Object.keys(this.scanFailures).length > 0 ? { scanFailures: this.scanFailures } : {}),\n };\n }\n\n findAgent(agentName: string): BaseAgent | undefined {\n return this.agentsByName.get(agentName);\n }\n\n commitAgentSessions(\n agentName: string,\n nextSessions: SessionHead[],\n candidateChangedIds: string[] = [],\n ): SessionsUpdatedEvent | null {\n delete this.scanFailures[agentName];\n const previousSessions = this.byAgent[agentName] ?? [];\n const previousGlobalSessions = this.sessions;\n const signatureCache = this.signatureCache(agentName);\n const { changes, removedSessionIds, counts } = computeSessionDiff(\n previousSessions,\n nextSessions,\n candidateChangedIds,\n sessionSignature,\n signatureCache,\n );\n for (const removedId of removedSessionIds) signatureCache.delete(removedId);\n\n this.byAgent[agentName] = sortSessions(nextSessions);\n this.sessions = mergeSortedSessions(Object.values(this.byAgent));\n if (counts.new === 0 && counts.updated === 0 && counts.removed === 0) return null;\n\n const changedSessionHeads = changes.map(({ session }) => ({\n reference: { agentName, sessionId: session.id },\n session,\n }));\n const previousSessionIds = new Set(previousSessions.map((session) => session.id));\n const newSessionRefs = changedSessionHeads.flatMap(({ reference }) =>\n previousSessionIds.has(reference.sessionId) ? [] : [reference],\n );\n const removedSessionRefs = removedSessionIds.map((sessionId) => ({ agentName, sessionId }));\n const projectionContext = createSessionProjectionContext(\n previousGlobalSessions,\n this.sessions,\n changedSessionHeads,\n removedSessionRefs,\n );\n return {\n type: \"sessions-updated\",\n changedAgents: [agentName],\n newSessions: counts.new,\n newSessionRefs,\n updatedSessions: counts.updated,\n removedSessions: counts.removed,\n totalSessions: this.sessions.length,\n timestamp: Date.now(),\n changedSessionHeads,\n projectionRelatedSessionHeads: projectionContext.relatedSessionHeads,\n projectionSessionOrder: projectionContext.sessionOrder,\n removedSessionRefs,\n };\n }\n\n private signatureCache(agentName: string): Map<string, string> {\n const existing = this.signatureCaches.get(agentName);\n if (existing) return existing;\n const cache = new Map<string, string>();\n this.signatureCaches.set(agentName, cache);\n return cache;\n }\n}\n","export class LatestValueThrottle<Value> {\n private timer: ReturnType<typeof setTimeout> | null = null;\n private phase: string | null = null;\n private pending: Value | undefined;\n private hasPending = false;\n\n constructor(\n private readonly intervalMs: number,\n private readonly emit: (value: Value) => void,\n ) {}\n\n push(value: Value, phase: string): void {\n if (this.phase !== phase) {\n this.flush();\n this.phase = phase;\n this.emit(value);\n this.schedule();\n return;\n }\n\n if (this.timer) {\n this.pending = value;\n this.hasPending = true;\n return;\n }\n\n this.emit(value);\n this.schedule();\n }\n\n flush(): void {\n this.clearTimer();\n if (!this.hasPending) return;\n const pending = this.pending as Value;\n this.pending = undefined;\n this.hasPending = false;\n this.emit(pending);\n }\n\n cancel(): void {\n this.dropPending();\n this.phase = null;\n }\n\n private schedule(): void {\n this.timer = setTimeout(() => {\n this.timer = null;\n if (!this.hasPending) return;\n const pending = this.pending as Value;\n this.pending = undefined;\n this.hasPending = false;\n this.emit(pending);\n this.schedule();\n }, this.intervalMs);\n }\n\n private clearTimer(): void {\n if (!this.timer) return;\n clearTimeout(this.timer);\n this.timer = null;\n }\n\n private dropPending(): void {\n this.clearTimer();\n this.pending = undefined;\n this.hasPending = false;\n }\n}\n","import { existsSync } from \"node:fs\";\nimport { fileURLToPath } from \"node:url\";\nimport { Worker } from \"node:worker_threads\";\nimport { getPricingGeneration } from \"@codesesh/core\";\nimport { toError } from \"./errors.js\";\nimport { appLogger, logSearchIndexSync } from \"./logging.js\";\nimport { PendingSearchIndexJobs, type SearchIndexJobBatch } from \"./pending-search-index-jobs.js\";\nimport type {\n SearchIndexWorkerJob,\n SearchIndexWorkerMessage,\n SearchIndexWorkerRunRequest,\n} from \"./search-index-worker.js\";\n\nconst SHUTDOWN_ERROR_MESSAGE = \"Live scan store shut down\";\n\nexport interface SearchIndexJobRunnerSnapshot {\n activeBatchId?: number;\n pendingBatches: number;\n pendingJobs: number;\n pendingChanges: number;\n pendingMaintenanceBatches: number;\n pendingMaintenanceJobs: number;\n}\n\nexport class SearchIndexJobRunner {\n private worker: Worker | null = null;\n private activeBatch: SearchIndexJobBatch | null = null;\n private nextBatchId = 1;\n private pendingJobs = new PendingSearchIndexJobs();\n private pendingMaintenanceJobs = new PendingSearchIndexJobs();\n private isShuttingDown = false;\n\n enqueue(context: string, jobs: SearchIndexWorkerJob[], onStarted?: () => void): Promise<void> {\n return this.enqueueIn(this.pendingJobs, context, jobs, onStarted);\n }\n\n enqueueMaintenance(context: string, jobs: SearchIndexWorkerJob[]): Promise<void> {\n return this.enqueueIn(this.pendingMaintenanceJobs, context, jobs);\n }\n\n private enqueueIn(\n queue: PendingSearchIndexJobs,\n context: string,\n jobs: SearchIndexWorkerJob[],\n onStarted?: () => void,\n ): Promise<void> {\n if (jobs.length === 0) return Promise.resolve();\n if (this.isShuttingDown) return Promise.reject(new Error(SHUTDOWN_ERROR_MESSAGE));\n\n const batchId = this.nextBatchId++;\n const completion = queue.enqueue(batchId, context, jobs, onStarted);\n if (this.activeBatch) {\n const snapshot = this.snapshot();\n appLogger.debug(\"search_index.worker_queued\", {\n batch_id: batchId,\n context,\n jobs: jobs.length,\n pending_batches: snapshot.pendingBatches,\n pending_jobs: snapshot.pendingJobs,\n pending_changes: snapshot.pendingChanges,\n });\n } else {\n this.startNextBatch();\n }\n return completion;\n }\n\n snapshot(): SearchIndexJobRunnerSnapshot {\n return {\n activeBatchId: this.activeBatch?.id,\n pendingBatches: this.pendingJobs.batchCount,\n pendingJobs: this.pendingJobs.jobCount,\n pendingChanges: this.pendingJobs.changeCount,\n pendingMaintenanceBatches: this.pendingMaintenanceJobs.batchCount,\n pendingMaintenanceJobs: this.pendingMaintenanceJobs.jobCount,\n };\n }\n\n async shutdown(): Promise<void> {\n this.isShuttingDown = true;\n const activeBatch = this.activeBatch;\n const worker = this.worker;\n this.activeBatch = null;\n this.worker = null;\n\n const shutdownError = new Error(SHUTDOWN_ERROR_MESSAGE);\n if (activeBatch) this.settle(activeBatch, shutdownError);\n this.pendingJobs.rejectAll(shutdownError);\n this.pendingMaintenanceJobs.rejectAll(shutdownError);\n if (worker) await worker.terminate();\n }\n\n private startNextBatch(): void {\n if (this.isShuttingDown || this.activeBatch) return;\n const batch = this.pendingJobs.take() ?? this.pendingMaintenanceJobs.take();\n if (!batch) return;\n\n appLogger.info(\"search_index.worker_dequeued\", {\n batch_id: batch.id,\n context: batch.context,\n pending_batches: this.pendingJobs.batchCount,\n });\n batch.start((error) => {\n appLogger.error(\"search_index.worker_start_listener_failed\", {\n batch_id: batch.id,\n context: batch.context,\n error: toError(error),\n });\n });\n this.startBatch(batch);\n }\n\n private startBatch(batch: SearchIndexJobBatch): void {\n if (this.isShuttingDown) {\n this.settle(batch, new Error(SHUTDOWN_ERROR_MESSAGE));\n return;\n }\n\n const request: SearchIndexWorkerRunRequest = {\n type: \"run\",\n pricingGenerationId: getPricingGeneration().id,\n context: batch.context,\n jobs: batch.jobs,\n };\n const existingWorker = this.worker;\n if (existingWorker) {\n this.activeBatch = batch;\n try {\n existingWorker.postMessage(request);\n } catch (error) {\n this.invalidateWorker(existingWorker, toError(error));\n }\n return;\n }\n\n const workerUrl = this.workerUrl();\n if (!workerUrl) {\n appLogger.warn(\"search_index.worker_missing\", { context: batch.context });\n this.settle(batch, new Error(\"Search index worker is unavailable\"));\n this.startNextBatch();\n return;\n }\n appLogger.info(\"search_index.worker_started\", {\n batch_id: batch.id,\n context: batch.context,\n jobs: batch.jobs.length,\n });\n\n let worker: Worker;\n try {\n worker = new Worker(workerUrl, { workerData: request });\n } catch (error) {\n this.settle(batch, toError(error));\n this.startNextBatch();\n return;\n }\n worker.unref();\n this.worker = worker;\n this.activeBatch = batch;\n\n worker.on(\"message\", (message: SearchIndexWorkerMessage) => {\n if (appLogger.consumeWorkerMessage(message)) return;\n if (this.worker !== worker) return;\n const activeBatch = this.activeBatch;\n if (!activeBatch) return;\n if (message.type === \"sync-result\") {\n logSearchIndexSync(message.context, message.result);\n return;\n }\n if (message.type === \"persist-failed\") {\n appLogger.error(\"search_index.persist_failed\", {\n batch_id: activeBatch.id,\n context: message.context,\n stage: message.stage,\n publication_id: message.publicationId,\n agent: message.agentName,\n sessions: message.sessions,\n });\n this.finishBatch(\n activeBatch,\n new Error(\n `Search index worker failed to persist ${message.stage} for ${message.agentName}`,\n ),\n );\n return;\n }\n if (message.type !== \"done\") return;\n\n appLogger.info(`${message.context}.done`, {\n duration_ms: Math.round(message.durationMs),\n sessions: message.sessions,\n });\n this.finishBatch(activeBatch);\n });\n worker.on(\"error\", (error) => {\n appLogger.error(\"search_index.worker_error\", {\n context: this.activeBatch?.context ?? batch.context,\n error,\n });\n this.invalidateWorker(worker, toError(error));\n });\n worker.on(\"exit\", (code) => this.finishWorker(worker, code));\n }\n\n private finishBatch(batch: SearchIndexJobBatch, error?: Error): void {\n if (this.activeBatch !== batch) return;\n this.activeBatch = null;\n this.settle(batch, error);\n this.startNextBatch();\n }\n\n private invalidateWorker(worker: Worker, error: Error): void {\n if (this.worker !== worker) return;\n this.worker = null;\n const batch = this.activeBatch;\n this.activeBatch = null;\n if (batch) this.settle(batch, error);\n void worker.terminate();\n this.startNextBatch();\n }\n\n private finishWorker(worker: Worker, code: number): void {\n const batch = this.worker === worker ? this.activeBatch : null;\n appLogger.info(\"search_index.worker_exited\", {\n batch_id: batch?.id,\n context: batch?.context,\n code,\n shutting_down: this.isShuttingDown || undefined,\n });\n if (this.worker !== worker) return;\n this.worker = null;\n this.activeBatch = null;\n\n if (batch) {\n const error =\n code === 0\n ? new Error(\"Search index worker exited before completing its batch\")\n : new Error(`Search index worker exited with code ${code}`);\n if (code !== 0) {\n appLogger.warn(\"search_index.worker_exit\", { context: batch.context, code });\n }\n this.settle(batch, error);\n }\n this.startNextBatch();\n }\n\n private settle(batch: SearchIndexJobBatch, error?: Error): void {\n if (\n !this.pendingJobs.settle(batch, error) &&\n !this.pendingMaintenanceJobs.settle(batch, error)\n ) {\n return;\n }\n appLogger.info(\"search_index.worker_settled\", {\n batch_id: batch.id,\n context: batch.context,\n result: error ? \"rejected\" : \"resolved\",\n });\n }\n\n private workerUrl(): URL | null {\n const workerUrl = new URL(\"./search-index-worker.js\", import.meta.url);\n if (workerUrl.protocol === \"file:\" && !existsSync(fileURLToPath(workerUrl))) return null;\n return workerUrl;\n }\n}\n","export function toError(value: unknown): Error {\n return value instanceof Error ? value : new Error(String(value));\n}\n","import type { SearchIndexSyncOptions, SessionCacheMeta, SessionHeadChange } from \"@codesesh/core\";\nimport type { SearchIndexWorkerJob } from \"./search-index-worker.js\";\n\ntype FullSearchIndexJob = Extract<SearchIndexWorkerJob, { kind: \"full\" }>;\ntype ChangesSearchIndexJob = Extract<SearchIndexWorkerJob, { kind: \"changes\" }>;\ntype MaintenanceSearchIndexJob = Extract<SearchIndexWorkerJob, { kind: \"maintenance\" }>;\ntype IncrementalSearchIndexJob = ChangesSearchIndexJob | MaintenanceSearchIndexJob;\n\ninterface JobWaiter {\n resolve: () => void;\n reject: (error: Error) => void;\n onStarted?: () => void;\n}\n\ninterface PendingChanges {\n kind: IncrementalSearchIndexJob[\"kind\"];\n context: string;\n agentName: string;\n publicationId?: string;\n changesBySessionId: Map<string, SessionHeadChange>;\n removedSessionIds: Set<string>;\n meta: Record<string, SessionCacheMeta>;\n searchIndexOptions?: SearchIndexSyncOptions;\n}\n\ninterface PendingAgentJobs {\n full?: FullSearchIndexJob;\n changes?: PendingChanges;\n}\n\nexport interface SearchIndexJobBatch {\n readonly id: number;\n readonly context: string;\n readonly jobs: SearchIndexWorkerJob[];\n start(onError: (error: unknown) => void): void;\n}\n\nclass PendingSearchIndexJobBatch implements SearchIndexJobBatch {\n context: string;\n private readonly jobsByAgent = new Map<string, PendingAgentJobs>();\n private readonly waiters: JobWaiter[] = [];\n private settled = false;\n private started = false;\n\n constructor(\n readonly id: number,\n context: string,\n jobs: SearchIndexWorkerJob[],\n waiter: JobWaiter,\n ) {\n this.context = context;\n this.merge(context, jobs, waiter);\n }\n\n get jobs(): SearchIndexWorkerJob[] {\n const jobs: SearchIndexWorkerJob[] = [];\n for (const pending of this.jobsByAgent.values()) {\n if (pending.full) jobs.push(pending.full);\n if (pending.changes) jobs.push(changesJobFromPending(pending.changes));\n }\n return jobs;\n }\n\n get changeCount(): number {\n let count = 0;\n for (const pending of this.jobsByAgent.values()) {\n if (!pending.changes) continue;\n count += pending.changes.changesBySessionId.size + pending.changes.removedSessionIds.size;\n }\n return count;\n }\n\n start(onError: (error: unknown) => void): void {\n if (this.started) return;\n this.started = true;\n for (const waiter of this.waiters) {\n try {\n waiter.onStarted?.();\n } catch (error) {\n onError(error);\n }\n }\n }\n\n merge(context: string, jobs: SearchIndexWorkerJob[], waiter: JobWaiter): void {\n this.context = context;\n this.waiters.push(waiter);\n for (const job of jobs) this.mergeJob(job);\n }\n\n settle(error?: Error): boolean {\n if (this.settled) return false;\n this.settled = true;\n for (const waiter of this.waiters) {\n if (error) waiter.reject(error);\n else waiter.resolve();\n }\n this.waiters.length = 0;\n return true;\n }\n\n private mergeJob(job: SearchIndexWorkerJob): void {\n const pending = this.jobsByAgent.get(job.agentName) ?? {};\n this.jobsByAgent.set(job.agentName, pending);\n\n if (job.kind === \"full\") {\n pending.full = job;\n pending.changes = undefined;\n return;\n }\n\n pending.changes ??= createPendingChanges(job);\n mergeChanges(pending.changes, job);\n }\n}\n\nexport class PendingSearchIndexJobs {\n private pendingBatch: PendingSearchIndexJobBatch | null = null;\n private readonly batches = new WeakSet<PendingSearchIndexJobBatch>();\n\n get batchCount(): number {\n return this.pendingBatch ? 1 : 0;\n }\n\n get jobCount(): number {\n return this.pendingBatch?.jobs.length ?? 0;\n }\n\n get changeCount(): number {\n return this.pendingBatch?.changeCount ?? 0;\n }\n\n enqueue(\n id: number,\n context: string,\n jobs: SearchIndexWorkerJob[],\n onStarted?: () => void,\n ): Promise<void> {\n if (jobs.length === 0) return Promise.resolve();\n\n return new Promise((resolve, reject) => {\n const waiter = { resolve, reject, onStarted };\n if (this.pendingBatch) {\n this.pendingBatch.merge(context, jobs, waiter);\n } else {\n this.pendingBatch = new PendingSearchIndexJobBatch(id, context, jobs, waiter);\n this.batches.add(this.pendingBatch);\n }\n });\n }\n\n take(): SearchIndexJobBatch | null {\n const batch = this.pendingBatch;\n this.pendingBatch = null;\n return batch;\n }\n\n settle(batch: SearchIndexJobBatch, error?: Error): boolean {\n if (!(batch instanceof PendingSearchIndexJobBatch) || !this.batches.has(batch)) return false;\n this.batches.delete(batch);\n return batch.settle(error);\n }\n\n rejectAll(error: Error): void {\n const batch = this.take();\n if (batch) this.settle(batch, error);\n }\n}\n\nfunction createPendingChanges(job: IncrementalSearchIndexJob): PendingChanges {\n return {\n kind: job.kind,\n context: job.context,\n agentName: job.agentName,\n ...(job.kind === \"changes\" && job.publicationId ? { publicationId: job.publicationId } : {}),\n changesBySessionId: new Map(),\n removedSessionIds: new Set(),\n meta: {},\n searchIndexOptions: job.searchIndexOptions,\n };\n}\n\nfunction mergeChanges(pending: PendingChanges, job: IncrementalSearchIndexJob): void {\n pending.kind = job.kind;\n pending.context = job.context;\n if (job.kind === \"changes\" && job.publicationId) {\n pending.publicationId = job.publicationId;\n }\n pending.searchIndexOptions = mergeSearchIndexOptions(\n pending.searchIndexOptions,\n job.searchIndexOptions,\n );\n\n for (const sessionId of job.removedSessionIds) {\n pending.changesBySessionId.delete(sessionId);\n pending.removedSessionIds.add(sessionId);\n delete pending.meta[sessionId];\n }\n\n for (const change of job.changes) {\n const sessionId = change.session.id;\n pending.removedSessionIds.delete(sessionId);\n pending.changesBySessionId.set(sessionId, change);\n if (Object.hasOwn(job.meta, sessionId)) pending.meta[sessionId] = job.meta[sessionId]!;\n else delete pending.meta[sessionId];\n }\n\n for (const [sessionId, meta] of Object.entries(job.meta)) {\n if (!pending.removedSessionIds.has(sessionId)) pending.meta[sessionId] = meta;\n }\n}\n\nfunction mergeSearchIndexOptions(\n current: SearchIndexSyncOptions | undefined,\n incoming: SearchIndexSyncOptions | undefined,\n): SearchIndexSyncOptions | undefined {\n if (!current) return incoming;\n if (!incoming) return current;\n return { ...current, ...incoming };\n}\n\nfunction changesJobFromPending(pending: PendingChanges): IncrementalSearchIndexJob {\n const common = {\n context: pending.context,\n agentName: pending.agentName,\n changes: [...pending.changesBySessionId.values()],\n removedSessionIds: [...pending.removedSessionIds],\n meta: pending.meta,\n ...(pending.searchIndexOptions ? { searchIndexOptions: pending.searchIndexOptions } : {}),\n };\n return pending.kind === \"changes\"\n ? {\n kind: \"changes\",\n ...common,\n ...(pending.publicationId ? { publicationId: pending.publicationId } : {}),\n }\n : { kind: \"maintenance\", ...common };\n}\n","import {\n loadCachedSessions,\n readPendingSearchIndexMaintenance,\n type SessionHeadChange,\n} from \"@codesesh/core\";\nimport type { SearchIndexMaintenanceStatus } from \"@codesesh/core/contract\";\nimport { toError } from \"./errors.js\";\nimport { appLogger } from \"./logging.js\";\nimport type { SearchIndexJobRunner } from \"./search-index-job-runner.js\";\nimport type { SearchIndexWorkerJob } from \"./search-index-worker.js\";\n\nconst MAINTENANCE_BATCH_SIZE = 4;\n\ntype StatusListener = (status: SearchIndexMaintenanceStatus) => void;\n\nexport class SearchIndexMaintenanceScheduler {\n private readonly pendingAgents = new Set<string>();\n private readonly completedAgents = new Set<string>();\n private readonly failedAgents = new Set<string>();\n private readonly cachedSessionsByAgent = new Map<\n string,\n NonNullable<ReturnType<typeof loadCachedSessions>>\n >();\n private currentAgent: string | undefined;\n private remaining: number | undefined;\n private pumpPromise: Promise<void> | null = null;\n private stopped = false;\n\n constructor(\n private readonly runner: SearchIndexJobRunner,\n private readonly onStatus: StatusListener,\n ) {}\n\n enqueue(agentName: string): void {\n if (this.stopped) return;\n this.pendingAgents.add(agentName);\n this.completedAgents.delete(agentName);\n this.failedAgents.delete(agentName);\n this.cachedSessionsByAgent.delete(agentName);\n this.startPump();\n }\n\n stop(): void {\n this.stopped = true;\n this.pendingAgents.clear();\n this.cachedSessionsByAgent.clear();\n this.publishStatus();\n }\n\n async waitForIdle(): Promise<void> {\n while (this.pumpPromise) await this.pumpPromise;\n }\n\n private startPump(): void {\n if (this.pumpPromise || this.stopped) return;\n this.pumpPromise = this.pump().finally(() => {\n this.pumpPromise = null;\n if (this.pendingAgents.size > 0 && !this.stopped) this.startPump();\n });\n }\n\n private async pump(): Promise<void> {\n while (!this.stopped && this.pendingAgents.size > 0) {\n const agentName = this.pendingAgents.values().next().value as string;\n this.pendingAgents.delete(agentName);\n this.currentAgent = agentName;\n try {\n await this.runBatch(agentName);\n } catch (error) {\n this.cachedSessionsByAgent.delete(agentName);\n if (!this.stopped) {\n this.failedAgents.add(agentName);\n appLogger.error(\"search_index.maintenance_failed\", {\n agent: agentName,\n error: toError(error),\n });\n }\n } finally {\n this.currentAgent = undefined;\n this.remaining = undefined;\n this.publishStatus();\n }\n }\n }\n\n private async runBatch(agentName: string): Promise<void> {\n const pending = readPendingSearchIndexMaintenance(agentName, MAINTENANCE_BATCH_SIZE);\n if (!pending) throw new Error(\"Search index storage is unavailable\");\n if (pending.total === 0) {\n this.completedAgents.add(agentName);\n return;\n }\n this.remaining = pending.total;\n this.publishStatus();\n\n const cached = this.cachedSessionsByAgent.get(agentName) ?? loadCachedSessions(agentName);\n if (!cached) throw new Error(`Session cache is unavailable for ${agentName}`);\n this.cachedSessionsByAgent.set(agentName, cached);\n const sessionsById = new Map(\n cached.sessions.map((session, sortIndex) => [session.id, { session, sortIndex }]),\n );\n const changes = pending.sessionIds.flatMap((sessionId): SessionHeadChange[] => {\n const change = sessionsById.get(sessionId);\n return change ? [change] : [];\n });\n if (changes.length === 0) {\n throw new Error(`No cached sessions matched pending maintenance for ${agentName}`);\n }\n\n const meta = Object.fromEntries(\n changes.flatMap(({ session }) => {\n const sessionMeta = cached.meta[session.id];\n return sessionMeta ? [[session.id, sessionMeta]] : [];\n }),\n );\n const job: SearchIndexWorkerJob = {\n kind: \"maintenance\",\n context: \"search.maintenance\",\n agentName,\n changes,\n removedSessionIds: [],\n meta,\n searchIndexOptions: { isBulk: false },\n };\n appLogger.info(\"search_index.maintenance_batch_started\", {\n agent: agentName,\n batch_sessions: changes.length,\n remaining: pending.total,\n });\n await this.runner.enqueueMaintenance(\"search.maintenance\", [job]);\n\n const next = readPendingSearchIndexMaintenance(agentName, MAINTENANCE_BATCH_SIZE);\n if (!next) throw new Error(\"Search index storage became unavailable\");\n if (next.total >= pending.total) {\n throw new Error(`Search index maintenance made no progress for ${agentName}`);\n }\n appLogger.info(\"search_index.maintenance_batch_completed\", {\n agent: agentName,\n indexed: pending.total - next.total,\n remaining: next.total,\n });\n if (next.total > 0) {\n this.pendingAgents.add(agentName);\n this.remaining = next.total;\n return;\n }\n this.cachedSessionsByAgent.delete(agentName);\n this.completedAgents.add(agentName);\n }\n\n private publishStatus(): void {\n this.onStatus({\n active: this.currentAgent != null || this.pendingAgents.size > 0,\n pendingAgents: [...this.pendingAgents],\n ...(this.currentAgent ? { currentAgent: this.currentAgent } : {}),\n ...(this.remaining != null ? { remaining: this.remaining } : {}),\n completedAgents: [...this.completedAgents],\n failedAgents: [...this.failedAgents],\n });\n }\n}\n","import type { AgentScanProgress } from \"@codesesh/core\";\nimport type {\n BackfillStatus,\n ScanStatusEvent,\n SearchIndexMaintenanceStatus,\n} from \"@codesesh/core/contract\";\n\ntype ScanStatus = Omit<ScanStatusEvent, \"type\" | \"searchIndexMaintenance\"> & {\n searchIndexMaintenance: SearchIndexMaintenanceStatus;\n};\n\nexport class ScanStatusModel {\n private status: ScanStatus = {\n active: false,\n phase: \"idle\",\n pendingAgents: [],\n scanningAgents: [],\n completedAgents: [],\n agentStatuses: {},\n totalAgents: 0,\n updatedAt: Date.now(),\n backfill: { active: false, pendingAgents: [], completedAgents: [], failedAgents: [] },\n searchIndexMaintenance: {\n active: false,\n pendingAgents: [],\n completedAgents: [],\n failedAgents: [],\n },\n };\n\n snapshot(): ScanStatusEvent {\n const backfill = {\n ...this.status.backfill,\n pendingAgents: [...this.status.backfill.pendingAgents],\n completedAgents: [...this.status.backfill.completedAgents],\n failedAgents: [...this.status.backfill.failedAgents],\n };\n if (this.status.backfill.progress) {\n backfill.progress = { ...this.status.backfill.progress };\n } else {\n delete backfill.progress;\n }\n return {\n type: \"scan-status\",\n ...this.status,\n pendingAgents: [...this.status.pendingAgents],\n scanningAgents: [...this.status.scanningAgents],\n completedAgents: [...this.status.completedAgents],\n agentStatuses: Object.fromEntries(\n Object.entries(this.status.agentStatuses).map(([agentName, status]) => [\n agentName,\n { ...status },\n ]),\n ),\n backfill,\n searchIndexMaintenance: {\n ...this.status.searchIndexMaintenance,\n pendingAgents: [...this.status.searchIndexMaintenance.pendingAgents],\n completedAgents: [...this.status.searchIndexMaintenance.completedAgents],\n failedAgents: [...this.status.searchIndexMaintenance.failedAgents],\n },\n };\n }\n\n startBatch(\n agentNames: string[],\n phase: ScanStatusEvent[\"phase\"],\n sessionCounts: Record<string, number>,\n ): ScanStatusEvent {\n const uniqueAgentNames = [...new Set(agentNames)];\n const now = Date.now();\n const agentStatuses = Object.fromEntries(\n uniqueAgentNames.map((agentName) => [\n agentName,\n {\n agentName,\n status: \"pending\" as const,\n processed: 0,\n sessions: sessionCounts[agentName] ?? 0,\n updatedAt: now,\n },\n ]),\n );\n return this.set({\n ...this.status,\n active: uniqueAgentNames.length > 0,\n phase: uniqueAgentNames.length > 0 ? phase : \"idle\",\n pendingAgents: uniqueAgentNames,\n scanningAgents: [],\n completedAgents: [],\n agentStatuses,\n totalAgents: uniqueAgentNames.length,\n startedAt: uniqueAgentNames.length > 0 ? now : undefined,\n updatedAt: now,\n completedAt: uniqueAgentNames.length > 0 ? undefined : now,\n });\n }\n\n setPhase(phase: ScanStatusEvent[\"phase\"]): ScanStatusEvent | null {\n if (!this.status.active) return null;\n return this.set({ ...this.status, phase, updatedAt: Date.now() });\n }\n\n beginAgent(agentName: string, sessionCount: number): ScanStatusEvent {\n if (!this.status.active)\n this.startBatch([agentName], \"scanning\", { [agentName]: sessionCount });\n\n const pendingAgents = this.status.pendingAgents.filter((agent) => agent !== agentName);\n const scanningAgents = [...new Set([...this.status.scanningAgents, agentName])];\n const completedAgents = this.status.completedAgents.filter((agent) => agent !== agentName);\n const existingStatus = this.status.agentStatuses[agentName];\n const now = Date.now();\n return this.set({\n ...this.status,\n active: true,\n phase: this.status.phase === \"initializing\" ? \"initializing\" : \"scanning\",\n pendingAgents,\n scanningAgents,\n completedAgents,\n agentStatuses: {\n ...this.status.agentStatuses,\n [agentName]: {\n agentName,\n status: \"scanning\",\n total: existingStatus?.total,\n processed: existingStatus?.processed ?? 0,\n sessions: existingStatus?.sessions ?? sessionCount,\n startedAt: existingStatus?.startedAt ?? now,\n updatedAt: now,\n },\n },\n totalAgents: Math.max(this.status.totalAgents, pendingAgents.length + scanningAgents.length),\n updatedAt: now,\n completedAt: undefined,\n });\n }\n\n updateAgent(agentName: string, progress: AgentScanProgress): ScanStatusEvent | null {\n const status = this.status.agentStatuses[agentName];\n if (\n !status ||\n status.status === \"pending\" ||\n status.status === \"complete\" ||\n ((status.status === \"publish-queued\" || status.status === \"publishing\") &&\n progress.phase !== \"finalizing\")\n ) {\n return null;\n }\n const now = Date.now();\n const nextStatus: \"finalizing\" | \"scanning\" =\n progress.phase === \"finalizing\" ? \"finalizing\" : \"scanning\";\n const agentStatuses = {\n ...this.status.agentStatuses,\n [agentName]: {\n ...status,\n status: nextStatus,\n total: progress.total ?? status.total,\n processed: progress.processed ?? status.processed,\n sessions: progress.sessions ?? status.sessions,\n updatedAt: now,\n },\n };\n return this.set({\n ...this.status,\n phase: this.activePhase(this.status.pendingAgents, this.status.scanningAgents, agentStatuses),\n agentStatuses,\n updatedAt: now,\n });\n }\n\n queueAgentPublication(agentName: string): ScanStatusEvent | null {\n const status = this.status.agentStatuses[agentName];\n if (\n !this.status.active ||\n !status ||\n (status.status !== \"scanning\" && status.status !== \"finalizing\")\n ) {\n return null;\n }\n\n const now = Date.now();\n const agentStatuses = {\n ...this.status.agentStatuses,\n [agentName]: { ...status, status: \"publish-queued\" as const, updatedAt: now },\n };\n return this.set({\n ...this.status,\n phase: this.activePhase(this.status.pendingAgents, this.status.scanningAgents, agentStatuses),\n agentStatuses,\n updatedAt: now,\n });\n }\n\n publishAgent(agentName: string): ScanStatusEvent | null {\n const status = this.status.agentStatuses[agentName];\n if (\n !this.status.active ||\n !status ||\n (status.status !== \"scanning\" &&\n status.status !== \"finalizing\" &&\n status.status !== \"publish-queued\")\n ) {\n return null;\n }\n\n const now = Date.now();\n const agentStatuses = {\n ...this.status.agentStatuses,\n [agentName]: { ...status, status: \"publishing\" as const, updatedAt: now },\n };\n return this.set({\n ...this.status,\n phase: this.activePhase(this.status.pendingAgents, this.status.scanningAgents, agentStatuses),\n agentStatuses,\n updatedAt: now,\n });\n }\n\n finishAgent(agentName: string, sessionCount?: number): ScanStatusEvent {\n const pendingAgents = this.status.pendingAgents.filter((agent) => agent !== agentName);\n const scanningAgents = this.status.scanningAgents.filter((agent) => agent !== agentName);\n const completedAgents = [...new Set([...this.status.completedAgents, agentName])];\n const isActive = pendingAgents.length > 0 || scanningAgents.length > 0;\n const now = Date.now();\n const previousStatus = this.status.agentStatuses[agentName];\n const total = previousStatus?.total ?? previousStatus?.processed;\n const agentStatuses = {\n ...this.status.agentStatuses,\n [agentName]: {\n agentName,\n status: \"complete\" as const,\n total,\n processed: total,\n sessions: sessionCount ?? previousStatus?.sessions ?? 0,\n startedAt: previousStatus?.startedAt,\n updatedAt: now,\n completedAt: now,\n },\n };\n\n return this.set({\n ...this.status,\n active: isActive,\n phase: isActive ? this.activePhase(pendingAgents, scanningAgents, agentStatuses) : \"idle\",\n pendingAgents,\n scanningAgents,\n completedAgents,\n agentStatuses,\n updatedAt: now,\n completedAt: isActive ? undefined : now,\n });\n }\n\n failAgent(agentName: string, error: string, sessionCount?: number): ScanStatusEvent {\n const pendingAgents = this.status.pendingAgents.filter((agent) => agent !== agentName);\n const scanningAgents = this.status.scanningAgents.filter((agent) => agent !== agentName);\n const completedAgents = this.status.completedAgents.filter((agent) => agent !== agentName);\n const isActive = pendingAgents.length > 0 || scanningAgents.length > 0;\n const now = Date.now();\n const previousStatus = this.status.agentStatuses[agentName];\n return this.set({\n ...this.status,\n active: isActive,\n phase: isActive\n ? this.activePhase(pendingAgents, scanningAgents, this.status.agentStatuses)\n : \"idle\",\n pendingAgents,\n scanningAgents,\n completedAgents,\n agentStatuses: {\n ...this.status.agentStatuses,\n [agentName]: {\n agentName,\n status: \"failed\",\n error,\n total: previousStatus?.total,\n processed: previousStatus?.processed,\n sessions: sessionCount ?? previousStatus?.sessions ?? 0,\n startedAt: previousStatus?.startedAt,\n updatedAt: now,\n completedAt: now,\n },\n },\n updatedAt: now,\n completedAt: isActive ? undefined : now,\n });\n }\n\n finishBatch(): ScanStatusEvent {\n const now = Date.now();\n return this.set({\n ...this.status,\n active: false,\n phase: \"idle\",\n pendingAgents: [],\n scanningAgents: [],\n agentStatuses: Object.fromEntries(\n Object.entries(this.status.agentStatuses).map(([agentName, status]) => [\n agentName,\n status.status === \"failed\"\n ? { ...status, completedAt: status.completedAt ?? now, updatedAt: now }\n : {\n ...status,\n status: \"complete\",\n completedAt: status.completedAt ?? now,\n updatedAt: now,\n },\n ]),\n ),\n updatedAt: now,\n completedAt: now,\n });\n }\n\n updateBackfill(backfill: BackfillStatus): ScanStatusEvent {\n return this.set({\n ...this.status,\n backfill: {\n ...backfill,\n pendingAgents: [...backfill.pendingAgents],\n completedAgents: [...backfill.completedAgents],\n failedAgents: [...backfill.failedAgents],\n progress: backfill.progress ? { ...backfill.progress } : undefined,\n },\n updatedAt: Date.now(),\n });\n }\n\n updateSearchIndexMaintenance(\n searchIndexMaintenance: SearchIndexMaintenanceStatus,\n ): ScanStatusEvent {\n return this.set({\n ...this.status,\n searchIndexMaintenance: {\n ...searchIndexMaintenance,\n pendingAgents: [...searchIndexMaintenance.pendingAgents],\n completedAgents: [...searchIndexMaintenance.completedAgents],\n failedAgents: [...searchIndexMaintenance.failedAgents],\n },\n updatedAt: Date.now(),\n });\n }\n\n private activePhase(\n pendingAgents: string[],\n scanningAgents: string[],\n agentStatuses: ScanStatus[\"agentStatuses\"],\n ): ScanStatusEvent[\"phase\"] {\n if (\n pendingAgents.length === 0 &&\n scanningAgents.length > 0 &&\n scanningAgents.every((agentName) => {\n const status = agentStatuses[agentName]?.status;\n return status === \"finalizing\" || status === \"publish-queued\" || status === \"publishing\";\n })\n ) {\n return \"publishing\";\n }\n return this.status.phase === \"initializing\" ? \"initializing\" : \"scanning\";\n }\n\n private set(status: ScanStatus): ScanStatusEvent {\n this.status = status;\n return this.snapshot();\n }\n}\n","import {\n FileSystemSessionSource,\n attachMissingProjectIdentities,\n buildAgentCacheMeta,\n getAgentFullSyncCursor,\n computeSessionDiff,\n loadCachedSessions,\n markAgentFullSyncProgress,\n markAgentFullSyncStarted,\n markAgentFullSyncCompleted,\n readAgentCacheInitialization,\n readAgentLastFullSyncAt,\n sessionSignature,\n type AgentScanProgress,\n type BaseAgent,\n type ScanOptions,\n type LiveSnapshot,\n type SessionHead,\n type SessionHeadChange,\n type SessionSourceFailure,\n type SessionSnapshotCompleteness,\n} from \"@codesesh/core\";\nimport type { ScanStatusEvent, SessionsUpdatedEvent } from \"@codesesh/core/contract\";\nimport { AgentOperationScheduler, type AgentOperationResult } from \"./agent-operation-scheduler.js\";\nimport {\n BackfillLifecycle,\n type BackfillAttemptRef,\n type BackfillTerminalStatus,\n} from \"./backfill-lifecycle.js\";\nimport { LiveSessionIndex, type LiveSessionIndexOptions } from \"./live-session-index.js\";\nimport { LatestValueThrottle } from \"./latest-value-throttle.js\";\nimport { appLogger, logSearchIndexSync } from \"./logging.js\";\nimport { SearchIndexJobRunner } from \"./search-index-job-runner.js\";\nimport { SearchIndexMaintenanceScheduler } from \"./search-index-maintenance-scheduler.js\";\nimport type { SearchIndexWorkerJob } from \"./search-index-worker.js\";\nimport { ScanStatusModel } from \"./scan-status-model.js\";\nimport type {\n BackfillScanRefreshOperation,\n ScanRefreshOperation,\n} from \"./scan-refresh-operation.js\";\nimport type { ScanRefreshWorkerCheckpoint } from \"./scan-refresh-worker.js\";\nimport type { WorkerRunner } from \"./worker-runner.js\";\nimport { toError } from \"./errors.js\";\n\nexport type { AgentOperationResult } from \"./agent-operation-scheduler.js\";\n\nexport interface AgentSessionsChanged {\n agentName: string;\n sessions: SessionHead[];\n event: SessionsUpdatedEvent | null;\n}\n\nexport interface AgentSyncEngineOptions {\n startupScanOptions?: Pick<ScanOptions, \"from\" | \"to\">;\n workerRunner: WorkerRunner;\n}\n\nexport interface AgentSyncEngineInitializationOptions extends LiveSessionIndexOptions {\n cacheTimestamps?: Record<string, number>;\n}\n\ntype SessionsChangedListener = (change: AgentSessionsChanged) => void;\ntype StatusChangedListener = (event: ScanStatusEvent) => void;\ntype CachedSessions = NonNullable<ReturnType<typeof loadCachedSessions>>;\n\ninterface SessionPersistenceDiff {\n changedSessions: SessionHeadChange[];\n removedSessionIds: string[];\n}\n\ninterface SessionPublication {\n context: \"scan.refresh\" | \"scan.backfill\";\n agentName: string;\n sessions: SessionHead[];\n candidateChangedIds: string[];\n indexJob: SearchIndexWorkerJob;\n onPublishing?: () => void;\n}\n\ninterface SessionPublicationResult {\n event: SessionsUpdatedEvent | null;\n diffDuration: number;\n}\n\ninterface RefreshStrategyResult {\n status: \"continue\" | \"unchanged\";\n nextSessions: SessionHead[];\n fullScanSessions: SessionHead[] | null;\n preciseChangedIds: string[] | null;\n persistenceDiff: SessionPersistenceDiff | null;\n checkDuration: number;\n scanDuration: number;\n sourceFailures: SessionSourceFailure[];\n completeness: SessionSnapshotCompleteness;\n scope: Pick<ScanOptions, \"from\" | \"to\">;\n explicitRemovedSessionIds: string[];\n}\n\nconst REFRESH_DEBOUNCE_MS = 200;\nconst EMPTY_AGENT_REFRESH_DEBOUNCE_MS = 30_000;\nconst SEARCH_INDEX_BULK_PENDING_PATH_THRESHOLD = 100;\nconst BACKFILL_INTERVAL_MS = 24 * 60 * 60 * 1000;\nconst CACHE_TRUNCATION_COVERAGE = 0.5;\nconst STATUS_PROGRESS_INTERVAL_MS = 100;\n\nfunction buildPersistenceDiff(\n previousSessions: SessionHead[],\n nextSessions: SessionHead[],\n candidateChangedIds: string[] = [],\n completeness: SessionSnapshotCompleteness = \"complete\",\n explicitRemovedSessionIds: readonly string[] = [],\n): SessionPersistenceDiff {\n const { changes, removedSessionIds } = computeSessionDiff(\n previousSessions,\n nextSessions,\n candidateChangedIds,\n sessionSignature,\n );\n if (completeness === \"complete\") {\n return { changedSessions: changes, removedSessionIds };\n }\n // A bounded or failed scan cannot prove that an omitted session disappeared.\n const explicitRemovals = new Set(explicitRemovedSessionIds);\n return {\n changedSessions: changes,\n removedSessionIds: removedSessionIds.filter((sessionId) => explicitRemovals.has(sessionId)),\n };\n}\n\nfunction sourceFailureError(failures: SessionSourceFailure[]): Error {\n const noun = failures.length === 1 ? \"source\" : \"sources\";\n return new Error(`${failures.length} session ${noun} failed; last-known-good data retained`);\n}\n\nfunction restoreAgentCacheMeta(agent: BaseAgent, cached: CachedSessions): void {\n agent.setSessionMetaMap(new Map(Object.entries(cached.meta)));\n}\n\nexport class AgentSyncEngine {\n private lastRefreshAtByAgent = new Map<string, number>();\n private readonly scheduler: AgentOperationScheduler;\n private readonly sessionIndex = new LiveSessionIndex();\n private readonly backfills = new BackfillLifecycle();\n private cacheIntegrityValidUntilByAgent = new Map<string, number>();\n private sessionsChangedListeners = new Set<SessionsChangedListener>();\n private statusChangedListeners = new Set<StatusChangedListener>();\n private statusProgressThrottles = new Map<string, LatestValueThrottle<void>>();\n private scanStatus = new ScanStatusModel();\n private readonly searchIndexJobs: SearchIndexJobRunner;\n private readonly searchIndexMaintenance: SearchIndexMaintenanceScheduler;\n private nextPublicationId = 1;\n private backgroundRefreshTimer: NodeJS.Timeout | null = null;\n private isShuttingDown = false;\n\n constructor(private readonly options: AgentSyncEngineOptions) {\n this.scheduler = new AgentOperationScheduler((agentName) => this.performRefresh(agentName));\n this.searchIndexJobs = new SearchIndexJobRunner();\n this.searchIndexMaintenance = new SearchIndexMaintenanceScheduler(\n this.searchIndexJobs,\n (status) => this.publishStatus(this.scanStatus.updateSearchIndexMaintenance(status)),\n );\n }\n\n initialize(snapshot: LiveSnapshot, options: AgentSyncEngineInitializationOptions = {}): void {\n this.sessionIndex.initialize(snapshot, options);\n this.lastRefreshAtByAgent.clear();\n for (const agent of this.sessionIndex.snapshot().agents) {\n this.lastRefreshAtByAgent.set(\n agent.name,\n options.cacheTimestamps?.[agent.name] ?? Date.now(),\n );\n }\n for (const [agentName, failure] of Object.entries(snapshot.scanFailures ?? {})) {\n this.scanStatus.failAgent(\n agentName,\n `${failure.stage}: ${failure.message}`,\n snapshot.byAgent[agentName]?.length ?? 0,\n );\n }\n }\n\n snapshot(): LiveSnapshot {\n return this.sessionIndex.snapshot();\n }\n\n status(): ScanStatusEvent {\n return this.scanStatus.snapshot();\n }\n\n subscribeSessionsChanged(listener: SessionsChangedListener): () => void {\n this.sessionsChangedListeners.add(listener);\n return () => this.sessionsChangedListeners.delete(listener);\n }\n\n subscribeStatusChanged(listener: StatusChangedListener): () => void {\n this.statusChangedListeners.add(listener);\n return () => this.statusChangedListeners.delete(listener);\n }\n\n async syncInitialIndex(): Promise<void> {\n const jobs = this.buildFullSearchIndexJobs(\"scan.initial\");\n await this.commitSearchIndex(\"scan.initial\", jobs, {\n publicationId: this.publicationId(\"scan.initial\"),\n agents: jobs.map((job) => job.agentName),\n });\n for (const job of jobs) this.searchIndexMaintenance.enqueue(job.agentName);\n }\n\n handleAgentsChanged(agentNames: Iterable<string>): void {\n const snapshot = this.sessionIndex.snapshot();\n for (const agentName of agentNames) {\n const delayMs =\n (snapshot.byAgent[agentName]?.length ?? 0) === 0\n ? EMPTY_AGENT_REFRESH_DEBOUNCE_MS\n : REFRESH_DEBOUNCE_MS;\n this.scheduler.notify(agentName, delayMs);\n }\n }\n\n startBackgroundRefresh(): void {\n if (this.backgroundRefreshTimer) return;\n const agentNames = this.sessionIndex.snapshot().agents.map((agent) => agent.name);\n this.startScanBatch(agentNames, \"scanning\");\n this.backgroundRefreshTimer = setTimeout(() => {\n this.backgroundRefreshTimer = null;\n for (const agentName of agentNames) this.scheduler.schedule(agentName, 0);\n if (agentNames.length === 0) this.finishScanBatch();\n }, 0);\n }\n\n async refresh(agentName: string): Promise<void> {\n await this.scheduler.refresh(agentName);\n }\n\n async shutdown(): Promise<void> {\n this.isShuttingDown = true;\n const schedulerSnapshot = this.scheduler.snapshot();\n const activeOperations = {\n agent_operations: schedulerSnapshot.activeOperations,\n refreshes: schedulerSnapshot.activeRefreshes,\n backfill_running: this.backfills.runningAttempt()?.agentName || undefined,\n scan_workers: this.options.workerRunner.activeCount,\n };\n if (activeOperations.agent_operations > 0 || activeOperations.scan_workers > 0) {\n appLogger.warn(\"scan.shutdown.active_operations\", activeOperations);\n }\n this.scheduler.stop();\n if (this.backgroundRefreshTimer) {\n clearTimeout(this.backgroundRefreshTimer);\n this.backgroundRefreshTimer = null;\n }\n this.backfills.cancelAll();\n this.searchIndexMaintenance.stop();\n this.cancelProgressStatuses();\n this.cacheIntegrityValidUntilByAgent.clear();\n const searchIndexSnapshot = this.searchIndexJobs.snapshot();\n appLogger.info(\"search_index.shutdown.started\", {\n active_batch_id: searchIndexSnapshot.activeBatchId,\n pending_batches: searchIndexSnapshot.pendingBatches,\n });\n await this.searchIndexJobs.shutdown();\n await this.searchIndexMaintenance.waitForIdle();\n await this.options.workerRunner.shutdown();\n await this.scheduler.waitForIdle();\n const stoppedSearchIndexSnapshot = this.searchIndexJobs.snapshot();\n appLogger.info(\"search_index.shutdown.completed\", {\n active_batch_id: searchIndexSnapshot.activeBatchId,\n pending_batches: stoppedSearchIndexSnapshot.pendingBatches,\n });\n }\n\n private startScanBatch(agentNames: string[], phase: ScanStatusEvent[\"phase\"]): void {\n const snapshot = this.sessionIndex.snapshot();\n const sessionCounts = Object.fromEntries(\n agentNames.map((agentName) => [agentName, snapshot.byAgent[agentName]?.length ?? 0]),\n );\n this.publishStatus(this.scanStatus.startBatch(agentNames, phase, sessionCounts));\n }\n\n private setScanPhase(phase: ScanStatusEvent[\"phase\"]): void {\n this.publishStatus(this.scanStatus.setPhase(phase));\n }\n\n private beginAgentScan(agentName: string): void {\n this.cancelProgressStatus(`scan:${agentName}`);\n const snapshot = this.sessionIndex.snapshot();\n if (!this.scanStatus.snapshot().active) this.startScanBatch([agentName], \"scanning\");\n this.publishStatus(\n this.scanStatus.beginAgent(agentName, snapshot.byAgent[agentName]?.length ?? 0),\n );\n }\n\n private updateAgentScanProgress(\n agentName: string,\n progress: AgentScanProgress,\n backfillAttempt?: BackfillAttemptRef,\n ): void {\n if (backfillAttempt) {\n const key = `backfill:${agentName}`;\n const current = this.backfills.stateFor(agentName);\n if (current?.status !== \"running\" || current.attemptId !== backfillAttempt.attemptId) {\n return;\n }\n const currentPhase = current.progress?.phase ?? \"scanning\";\n const nextPhase = progress.phase ?? \"scanning\";\n if (currentPhase && currentPhase !== nextPhase) this.flushProgressStatus(key);\n if (\n this.backfills.updateProgress(backfillAttempt, {\n phase: progress.phase,\n total: progress.total,\n processed: progress.processed,\n sessions: progress.sessions,\n })\n ) {\n this.publishProgressStatus(\n key,\n nextPhase,\n this.scanStatus.updateBackfill(this.backfills.status()),\n );\n }\n return;\n }\n const key = `scan:${agentName}`;\n const currentPhase = this.scanStatus.snapshot().agentStatuses[agentName]?.status;\n const nextPhase = progress.phase === \"finalizing\" ? \"finalizing\" : \"scanning\";\n if (currentPhase && currentPhase !== nextPhase) this.flushProgressStatus(key);\n const status = this.scanStatus.updateAgent(agentName, progress);\n this.publishProgressStatus(key, status?.agentStatuses[agentName]?.status ?? nextPhase, status);\n }\n\n private beginAgentPublishing(agentName: string): void {\n this.flushProgressStatus(`scan:${agentName}`);\n this.publishStatus(this.scanStatus.publishAgent(agentName));\n }\n\n private queueAgentPublication(agentName: string): void {\n this.flushProgressStatus(`scan:${agentName}`);\n this.publishStatus(this.scanStatus.queueAgentPublication(agentName));\n }\n\n private finishAgentScan(agentName: string): void {\n this.flushProgressStatus(`scan:${agentName}`);\n const count = this.sessionIndex.snapshot().byAgent[agentName]?.length;\n this.publishStatus(this.scanStatus.finishAgent(agentName, count));\n }\n\n private finishScanBatch(): void {\n this.flushProgressStatuses(\"scan:\");\n this.publishStatus(this.scanStatus.finishBatch());\n }\n\n private publishBackfillStatus(): void {\n this.publishStatus(this.scanStatus.updateBackfill(this.backfills.status()));\n }\n\n private publishStatus(event: ScanStatusEvent | null): void {\n if (!event || this.isShuttingDown) return;\n for (const listener of this.statusChangedListeners) {\n try {\n listener(event);\n } catch (error) {\n appLogger.error(\"scan.status_listener.error\", { error });\n }\n }\n }\n\n private publishProgressStatus(key: string, phase: string, event: ScanStatusEvent | null): void {\n if (!event) return;\n let throttle = this.statusProgressThrottles.get(key);\n if (!throttle) {\n throttle = new LatestValueThrottle<void>(STATUS_PROGRESS_INTERVAL_MS, () => {\n this.publishStatus(this.scanStatus.snapshot());\n });\n this.statusProgressThrottles.set(key, throttle);\n }\n throttle.push(undefined, phase);\n }\n\n private flushProgressStatus(key: string): void {\n const throttle = this.statusProgressThrottles.get(key);\n if (!throttle) return;\n throttle.flush();\n throttle.cancel();\n this.statusProgressThrottles.delete(key);\n }\n\n private cancelProgressStatus(key: string): void {\n const throttle = this.statusProgressThrottles.get(key);\n if (!throttle) return;\n throttle.cancel();\n this.statusProgressThrottles.delete(key);\n }\n\n private flushProgressStatuses(prefix: string): void {\n for (const key of this.statusProgressThrottles.keys()) {\n if (key.startsWith(prefix)) this.flushProgressStatus(key);\n }\n }\n\n private cancelProgressStatuses(): void {\n for (const throttle of this.statusProgressThrottles.values()) throttle.cancel();\n this.statusProgressThrottles.clear();\n }\n\n private emitSessionsChanged(change: AgentSessionsChanged): void {\n if (this.isShuttingDown) return;\n for (const listener of this.sessionsChangedListeners) listener(change);\n }\n\n private async performRefresh(agentName: string): Promise<AgentOperationResult> {\n this.beginAgentScan(agentName);\n const startedAt = performance.now();\n let failed = false;\n let cached: CachedSessions | null = null;\n let result: Exclude<AgentOperationResult, \"failed\"> | null = null;\n try {\n if (this.findAgent(agentName)) cached = loadCachedSessions(agentName);\n result = await this.runRefresh(agentName, cached, startedAt);\n return result;\n } catch (error) {\n this.options.workerRunner.discard?.(agentName);\n failed = true;\n const failure = toError(error);\n appLogger.error(\"scan.refresh.error\", { agent: agentName, error });\n console.error(`[${agentName}] Session refresh failed:`, error);\n this.flushProgressStatus(`scan:${agentName}`);\n this.publishStatus(this.scanStatus.failAgent(agentName, failure.message));\n return \"failed\";\n } finally {\n if (!failed) this.finishAgentScan(agentName);\n const agent = this.findAgent(agentName);\n if (agent && this.needsBackfill(agent, cached, failed || result === \"committed\")) {\n this.enqueueBackfill(agentName);\n }\n if (agent) this.searchIndexMaintenance.enqueue(agentName);\n }\n }\n\n private async runRefresh(\n agentName: string,\n cached: CachedSessions | null,\n startedAt: number,\n ): Promise<Exclude<AgentOperationResult, \"failed\">> {\n const pendingPathCount = this.scheduler.takePendingSignalCount(agentName);\n const agent = this.findAgent(agentName);\n if (!agent) {\n appLogger.warn(\"scan.refresh.missing_agent\", { agent: agentName });\n return \"skipped\";\n }\n const previousSessions = this.sessionIndex.snapshot().byAgent[agentName] ?? [];\n const refreshBaseline = cached?.sessions ?? previousSessions;\n const cacheTimestamp = cached?.timestamp ?? this.lastRefreshAtByAgent.get(agentName) ?? 0;\n if (cached) restoreAgentCacheMeta(agent, cached);\n const durableMeta = new Map(agent.getSessionMetaMap());\n const durableLastRefreshAt = this.lastRefreshAtByAgent.get(agentName);\n const initialization = readAgentCacheInitialization(agentName);\n if (initialization.status === \"failed\") {\n appLogger.warn(\"scan.refresh.cache_state_unavailable\", {\n agent: agentName,\n state: \"initialization\",\n });\n return \"unchanged\";\n }\n const isInitialized = initialization.value;\n const availabilityStartedAt = performance.now();\n const isAvailable = agent.isAvailable();\n const availabilityDuration = performance.now() - availabilityStartedAt;\n let strategyResult: RefreshStrategyResult;\n if (!isAvailable) {\n strategyResult = this.refreshUnavailableAgent(agentName);\n } else if (!isInitialized) {\n strategyResult = await this.initializeAgent(agent, previousSessions);\n } else if (cached && agent instanceof FileSystemSessionSource) {\n strategyResult = await this.syncAgentSources(agent, cached, startedAt);\n } else if (refreshBaseline.length > 0) {\n strategyResult = await this.refreshChangedAgent(\n agent,\n refreshBaseline,\n cacheTimestamp,\n startedAt,\n );\n } else {\n strategyResult = await this.scanAgentFully(agent, previousSessions);\n }\n if (strategyResult.status === \"unchanged\") {\n this.options.workerRunner.commit?.(agentName);\n return \"unchanged\";\n }\n\n const nextSessions = attachMissingProjectIdentities(strategyResult.nextSessions);\n const searchIndexOptions =\n pendingPathCount >= SEARCH_INDEX_BULK_PENDING_PATH_THRESHOLD ? { isBulk: true } : undefined;\n const persistenceDiff = strategyResult.persistenceDiff;\n const publicationSessions = strategyResult.fullScanSessions ?? nextSessions;\n const publicationSessionIds = new Set(publicationSessions.map((session) => session.id));\n const missingBaselineSessions = refreshBaseline.reduce(\n (count, session) => count + Number(!publicationSessionIds.has(session.id)),\n 0,\n );\n const replacementDeleteCandidates = persistenceDiff\n ? persistenceDiff.removedSessionIds.length\n : strategyResult.completeness === \"complete\"\n ? missingBaselineSessions\n : strategyResult.explicitRemovedSessionIds.length;\n appLogger.info(\"scan.refresh.persistence_candidate\", {\n agent: agentName,\n scope_from: strategyResult.scope.from,\n scope_to: strategyResult.scope.to,\n publication_completeness: strategyResult.completeness,\n durable_baseline_sessions: refreshBaseline.length,\n payload_sessions: publicationSessions.length,\n delete_candidates: replacementDeleteCandidates,\n });\n const changedSessionIds = persistenceDiff\n ? new Set(persistenceDiff.changedSessions.map(({ session }) => session.id))\n : undefined;\n const persistStartedAt = performance.now();\n const persistentJob: SearchIndexWorkerJob = persistenceDiff\n ? {\n kind: \"changes\",\n context: \"scan.refresh\",\n agentName,\n changes: persistenceDiff.changedSessions,\n removedSessionIds: persistenceDiff.removedSessionIds,\n meta: buildAgentCacheMeta(agent, changedSessionIds),\n ...(searchIndexOptions ? { searchIndexOptions } : {}),\n }\n : {\n kind: \"full\",\n context: \"scan.refresh\",\n agentName,\n sessions: publicationSessions,\n meta: buildAgentCacheMeta(agent),\n completeness: strategyResult.completeness,\n removedSessionIds: strategyResult.explicitRemovedSessionIds,\n saveCache: true,\n ...(searchIndexOptions ? { searchIndexOptions } : {}),\n };\n this.queueAgentPublication(agentName);\n let publication: SessionPublicationResult;\n try {\n publication = await this.commitSessionPublication({\n context: \"scan.refresh\",\n agentName,\n sessions: nextSessions,\n candidateChangedIds: strategyResult.preciseChangedIds ?? [],\n indexJob: persistentJob,\n onPublishing: () => this.beginAgentPublishing(agentName),\n });\n } catch (error) {\n agent.setSessionMetaMap(durableMeta);\n if (durableLastRefreshAt == null) this.lastRefreshAtByAgent.delete(agentName);\n else this.lastRefreshAtByAgent.set(agentName, durableLastRefreshAt);\n throw error;\n }\n this.options.workerRunner.commit?.(agentName);\n const persistDuration = performance.now() - persistStartedAt;\n logSearchIndexSync(\"scan.refresh\", null, { pending_paths: pendingPathCount });\n\n const totalDurationMs = performance.now() - startedAt;\n this.scheduler.recordRefreshDuration(agentName, totalDurationMs);\n appLogger.info(\n strategyResult.sourceFailures.length > 0 ? \"scan.refresh.partial\" : \"scan.refresh.done\",\n {\n agent: agentName,\n duration_ms: Math.round(totalDurationMs),\n sessions: nextSessions.length,\n new_sessions: publication.event?.newSessions ?? 0,\n updated_sessions: publication.event?.updatedSessions ?? 0,\n removed_sessions: publication.event?.removedSessions ?? 0,\n pending_paths: pendingPathCount,\n availability_ms: Math.round(availabilityDuration),\n check_ms: Math.round(strategyResult.checkDuration),\n scan_ms: Math.round(strategyResult.scanDuration),\n diff_ms: Math.round(publication.diffDuration),\n persist_ms: Math.round(persistDuration),\n search_index_ms: Math.round(persistDuration),\n persistent_index_worker_job: persistentJob.kind,\n failed_sources: strategyResult.sourceFailures.length,\n },\n );\n if (strategyResult.sourceFailures.length > 0) {\n appLogger.warn(\"scan.refresh.source_failures\", {\n agent: agentName,\n failures: strategyResult.sourceFailures,\n });\n throw sourceFailureError(strategyResult.sourceFailures);\n }\n return \"committed\";\n }\n\n /**\n * An agent that cannot be reached was never scanned, so there is nothing to\n * compare against. Publishing an empty result here would diff every known\n * session into a removal — the same mistake as reading a failed query as an\n * empty database.\n */\n private refreshUnavailableAgent(agentName: string): RefreshStrategyResult {\n this.lastRefreshAtByAgent.set(agentName, Date.now());\n const previousSessions = this.sessionIndex.snapshot().byAgent[agentName] ?? [];\n if (previousSessions.length > 0) {\n appLogger.warn(\"scan.refresh.agent_unavailable\", {\n agent: agentName,\n retained_sessions: previousSessions.length,\n });\n return this.refreshStrategyResult(previousSessions, \"partial\", {}, { status: \"unchanged\" });\n }\n return this.refreshStrategyResult([], \"partial\", {});\n }\n\n private async initializeAgent(\n agent: BaseAgent,\n previousSessions: SessionHead[],\n ): Promise<RefreshStrategyResult> {\n this.setScanPhase(\"initializing\");\n const scanStartedAt = performance.now();\n const scope = this.startupScanOptions();\n const result = await this.runWorker(agent, previousSessions, { kind: \"full-scan\" }, scope);\n agent.setSessionMetaMap(new Map(Object.entries(result.meta)));\n const sessions = attachMissingProjectIdentities(result.sessions);\n this.lastRefreshAtByAgent.set(agent.name, Date.now());\n return this.refreshStrategyResult(sessions, result.completeness, scope, {\n fullScanSessions: sessions,\n explicitRemovedSessionIds: result.explicitRemovedSessionIds,\n scanDuration: performance.now() - scanStartedAt,\n sourceFailures: result.sourceFailures ?? [],\n });\n }\n\n private async syncAgentSources(\n agent: FileSystemSessionSource,\n cached: CachedSessions,\n refreshStartedAt: number,\n ): Promise<RefreshStrategyResult> {\n const scanStartedAt = performance.now();\n const scope = this.startupScanOptions();\n const result = await this.runWorker(agent, cached.sessions, { kind: \"source-refresh\" }, scope, {\n meta: cached.meta,\n });\n agent.setSessionMetaMap(new Map(Object.entries(result.meta)));\n const sessions = attachMissingProjectIdentities(result.sessions);\n const preciseChangedIds = result.changedIds ?? [];\n const persistenceDiff = buildPersistenceDiff(cached.sessions, sessions, preciseChangedIds);\n this.lastRefreshAtByAgent.set(agent.name, Date.now());\n if (\n persistenceDiff.changedSessions.length === 0 &&\n persistenceDiff.removedSessionIds.length === 0 &&\n (result.sourceFailures?.length ?? 0) === 0\n ) {\n this.logUnchangedRefresh(agent.name, refreshStartedAt);\n return this.refreshStrategyResult(sessions, result.completeness, scope, {\n status: \"unchanged\",\n scanDuration: performance.now() - scanStartedAt,\n });\n }\n return this.refreshStrategyResult(sessions, result.completeness, scope, {\n preciseChangedIds,\n persistenceDiff,\n scanDuration: performance.now() - scanStartedAt,\n sourceFailures: result.sourceFailures ?? [],\n });\n }\n\n private async refreshChangedAgent(\n agent: BaseAgent,\n baseline: SessionHead[],\n cacheTimestamp: number,\n refreshStartedAt: number,\n ): Promise<RefreshStrategyResult> {\n const scope = this.startupScanOptions();\n const checkStartedAt = performance.now();\n const checkResult = await Promise.resolve(agent.checkForChanges(cacheTimestamp, baseline));\n const checkDuration = performance.now() - checkStartedAt;\n if (checkResult.status === \"failed\") {\n appLogger.warn(\"scan.refresh.change_check_failed\", {\n agent: agent.name,\n source_path: checkResult.failure.sourcePath,\n error_class: checkResult.failure.errorClass,\n message: checkResult.failure.message,\n });\n return this.refreshStrategyResult(\n baseline,\n \"partial\",\n {},\n { status: \"unchanged\", checkDuration },\n );\n }\n this.lastRefreshAtByAgent.set(agent.name, checkResult.timestamp);\n if (!checkResult.hasChanges) {\n const scanStartedAt = performance.now();\n const result = await this.runWorker(agent, baseline, { kind: \"recompute-derived\" }, {});\n agent.setSessionMetaMap(new Map(Object.entries(result.meta)));\n const sessions = attachMissingProjectIdentities(result.sessions);\n const persistenceDiff = buildPersistenceDiff(baseline, sessions);\n if (\n persistenceDiff.changedSessions.length === 0 &&\n persistenceDiff.removedSessionIds.length === 0\n ) {\n this.logUnchangedRefresh(agent.name, refreshStartedAt);\n return this.refreshStrategyResult(\n sessions,\n result.completeness,\n {},\n {\n status: \"unchanged\",\n checkDuration,\n scanDuration: performance.now() - scanStartedAt,\n },\n );\n }\n return this.refreshStrategyResult(\n sessions,\n result.completeness,\n {},\n {\n persistenceDiff,\n checkDuration,\n scanDuration: performance.now() - scanStartedAt,\n sourceFailures: result.sourceFailures ?? [],\n },\n );\n }\n const preciseChangedIds = checkResult.changedIds ?? null;\n const scanStartedAt = performance.now();\n if (preciseChangedIds === null) {\n const result = await this.runWorker(agent, baseline, { kind: \"full-scan\" }, scope);\n agent.setSessionMetaMap(new Map(Object.entries(result.meta)));\n const sessions = attachMissingProjectIdentities(result.sessions);\n return this.refreshStrategyResult(sessions, result.completeness, scope, {\n // Meta-only changes (e.g. a pricing capture epoch bump) leave the head\n // signature intact; without the worker-reported ids they would never\n // persist and checkForChanges would rescan on every startup.\n persistenceDiff: buildPersistenceDiff(\n baseline,\n sessions,\n result.changedIds ?? [],\n result.completeness,\n result.explicitRemovedSessionIds,\n ),\n checkDuration,\n scanDuration: performance.now() - scanStartedAt,\n sourceFailures: result.sourceFailures ?? [],\n });\n }\n this.options.workerRunner.discard?.(agent.name);\n const sessions = attachMissingProjectIdentities(\n await Promise.resolve(\n agent.incrementalScan(baseline, preciseChangedIds, checkResult.refs, scope),\n ),\n );\n const sourceFailures = checkResult.sourceFailures ?? [];\n const completeness =\n scope.from == null && scope.to == null && sourceFailures.length === 0\n ? \"complete\"\n : \"partial\";\n return this.refreshStrategyResult(sessions, completeness, scope, {\n preciseChangedIds,\n persistenceDiff: buildPersistenceDiff(\n baseline,\n sessions,\n preciseChangedIds,\n completeness,\n preciseChangedIds,\n ),\n checkDuration,\n scanDuration: performance.now() - scanStartedAt,\n sourceFailures,\n });\n }\n\n private async scanAgentFully(\n agent: BaseAgent,\n previousSessions: SessionHead[],\n ): Promise<RefreshStrategyResult> {\n const scanStartedAt = performance.now();\n const scope = this.startupScanOptions();\n const result = await this.runWorker(agent, previousSessions, { kind: \"full-scan\" }, scope);\n agent.setSessionMetaMap(new Map(Object.entries(result.meta)));\n const sessions = attachMissingProjectIdentities(result.sessions);\n this.lastRefreshAtByAgent.set(agent.name, Date.now());\n return this.refreshStrategyResult(sessions, result.completeness, scope, {\n fullScanSessions: sessions,\n explicitRemovedSessionIds: result.explicitRemovedSessionIds,\n scanDuration: performance.now() - scanStartedAt,\n sourceFailures: result.sourceFailures ?? [],\n });\n }\n\n private refreshStrategyResult(\n nextSessions: SessionHead[],\n completeness: SessionSnapshotCompleteness,\n scope: Pick<ScanOptions, \"from\" | \"to\">,\n overrides: Partial<Omit<RefreshStrategyResult, \"nextSessions\" | \"completeness\" | \"scope\">> = {},\n ): RefreshStrategyResult {\n return {\n status: \"continue\",\n nextSessions,\n fullScanSessions: null,\n preciseChangedIds: null,\n persistenceDiff: null,\n checkDuration: 0,\n scanDuration: 0,\n sourceFailures: [],\n completeness,\n scope,\n explicitRemovedSessionIds: [],\n ...overrides,\n };\n }\n\n private runWorker(\n agent: BaseAgent,\n previousSessions: SessionHead[],\n operation: ScanRefreshOperation,\n scanOptions: Pick<ScanOptions, \"from\" | \"to\" | \"fast\">,\n runOptions: {\n backfillAttempt?: BackfillAttemptRef;\n meta?: CachedSessions[\"meta\"];\n onCheckpoint?: (checkpoint: ScanRefreshWorkerCheckpoint) => void;\n } = {},\n ) {\n return this.options.workerRunner.run(agent.name, {\n previousSessions,\n operation,\n scanOptions,\n meta: runOptions.meta ?? buildAgentCacheMeta(agent),\n onProgress: (progress) =>\n this.updateAgentScanProgress(agent.name, progress, runOptions.backfillAttempt),\n onCheckpoint: runOptions.onCheckpoint,\n });\n }\n\n private handleBackfillCheckpoint(\n agentName: string,\n checkpoint: ScanRefreshWorkerCheckpoint,\n ): void {\n if (checkpoint.stage !== \"finalizing\" || !checkpoint.backfillCursor) return;\n markAgentFullSyncProgress(agentName, checkpoint.backfillCursor);\n appLogger.debug(\"scan.backfill.checkpoint\", {\n agent: agentName,\n cursor: checkpoint.backfillCursor,\n sessions: checkpoint.changes.length,\n });\n }\n\n private needsBackfill(\n agent: BaseAgent,\n cached?: CachedSessions | null,\n reloadCached = false,\n ): boolean {\n const startupScanOptions = this.startupScanOptions();\n if (startupScanOptions.from == null && startupScanOptions.to == null) return false;\n const now = Date.now();\n if ((this.cacheIntegrityValidUntilByAgent.get(agent.name) ?? 0) >= now) return false;\n const lastSync = readAgentLastFullSyncAt(agent.name);\n if (lastSync.status === \"failed\") {\n appLogger.warn(\"scan.backfill.cache_state_unavailable\", {\n agent: agent.name,\n state: \"last_full_sync\",\n });\n return false;\n }\n const lastSyncAt = lastSync.value;\n if (lastSyncAt == null || now - lastSyncAt > BACKFILL_INTERVAL_MS) {\n return agent.isAvailable();\n }\n if (!(agent instanceof FileSystemSessionSource)) return false;\n if (!agent.isAvailable()) return false;\n\n const cachedSessions =\n reloadCached || cached === undefined ? loadCachedSessions(agent.name) : cached;\n const sourceCount = agent.listSessionSources().length;\n const cachedCount = cachedSessions?.sessions.length ?? 0;\n this.cacheIntegrityValidUntilByAgent.set(agent.name, lastSyncAt + BACKFILL_INTERVAL_MS);\n if (sourceCount > 0 && cachedCount / sourceCount < CACHE_TRUNCATION_COVERAGE) {\n appLogger.warn(\"scan.backfill.cache_truncated\", {\n agent: agent.name,\n cached_sessions: cachedCount,\n source_files: sourceCount,\n last_sync_at: lastSyncAt,\n });\n return true;\n }\n return false;\n }\n\n private enqueueBackfill(agentName: string): void {\n if (this.isShuttingDown || !this.backfills.enqueue(agentName)) return;\n this.publishBackfillStatus();\n this.pumpBackfillQueue();\n }\n\n private pumpBackfillQueue(): void {\n if (this.isShuttingDown) return;\n const attempt = this.backfills.startNext();\n if (!attempt) return;\n this.publishBackfillStatus();\n void this.runBackfill(attempt)\n .then((result) => this.completeBackfillAttempt(attempt, result))\n .catch((error) => this.rejectBackfillAttempt(attempt, error));\n }\n\n private completeBackfillAttempt(\n attempt: BackfillAttemptRef,\n result: BackfillTerminalStatus,\n ): void {\n if (this.isShuttingDown) return;\n const current = this.backfills.stateFor(attempt.agentName);\n if (current?.status === \"running\" && current.attemptId === attempt.attemptId) {\n this.flushProgressStatus(`backfill:${attempt.agentName}`);\n if (this.backfills.complete(attempt, result)) {\n if (result === \"failed\") {\n this.cacheIntegrityValidUntilByAgent.delete(attempt.agentName);\n } else if (result === \"committed\") {\n this.cacheIntegrityValidUntilByAgent.set(\n attempt.agentName,\n Date.now() + BACKFILL_INTERVAL_MS,\n );\n }\n this.publishBackfillStatus();\n }\n }\n this.pumpBackfillQueue();\n }\n\n private rejectBackfillAttempt(attempt: BackfillAttemptRef, error: unknown): void {\n appLogger.error(\"scan.backfill.queue_error\", { agent: attempt.agentName, error });\n this.completeBackfillAttempt(attempt, \"failed\");\n }\n\n private runBackfill(attempt: BackfillAttemptRef): Promise<BackfillTerminalStatus> {\n return this.scheduler.run(attempt.agentName, \"backfill\", () => this.performBackfill(attempt));\n }\n\n private async performBackfill(attempt: BackfillAttemptRef): Promise<BackfillTerminalStatus> {\n const { agentName } = attempt;\n const startedAt = performance.now();\n const agent = this.findAgent(agentName);\n if (!agent || !agent.isAvailable()) return \"skipped\";\n const snapshot = this.sessionIndex.snapshot();\n const cached = loadCachedSessions(agentName);\n const baseline = cached?.sessions ?? snapshot.byAgent[agentName] ?? [];\n const meta = cached?.meta ?? buildAgentCacheMeta(agent);\n const backfillCursor = getAgentFullSyncCursor(agentName);\n if (cached) restoreAgentCacheMeta(agent, cached);\n let durableCommitted = false;\n try {\n markAgentFullSyncStarted(agentName);\n const operation: BackfillScanRefreshOperation =\n agent instanceof FileSystemSessionSource\n ? { kind: \"source-backfill\", cursor: backfillCursor, checkpoint: \"durable\" }\n : { kind: \"full-backfill\", cursor: backfillCursor, checkpoint: \"durable\" };\n appLogger.info(\"scan.backfill.started\", {\n agent: agentName,\n cursor: backfillCursor ?? undefined,\n durable_checkpoints: operation.checkpoint === \"durable\",\n });\n const result = await this.runWorker(\n agent,\n baseline,\n operation,\n {},\n {\n backfillAttempt: attempt,\n meta,\n onCheckpoint: (checkpoint) => this.handleBackfillCheckpoint(agentName, checkpoint),\n },\n );\n agent.setSessionMetaMap(new Map(Object.entries(result.meta)));\n const fullSessions = attachMissingProjectIdentities(result.sessions);\n this.flushProgressStatus(`backfill:${agentName}`);\n const updatePublicationPhase = (phase: \"publish-queued\" | \"publishing\") => {\n if (\n this.backfills.updateProgress(attempt, {\n phase,\n sessions: fullSessions.length,\n })\n ) {\n this.publishProgressStatus(\n `backfill:${agentName}`,\n phase,\n this.scanStatus.updateBackfill(this.backfills.status()),\n );\n }\n };\n updatePublicationPhase(\"publish-queued\");\n await this.commitSessionPublication({\n context: \"scan.backfill\",\n agentName,\n sessions: fullSessions,\n candidateChangedIds: result.changedIds ?? [],\n indexJob: {\n kind: \"full\",\n context: \"scan.backfill\",\n agentName,\n sessions: fullSessions,\n meta: buildAgentCacheMeta(agent),\n completeness: result.completeness,\n removedSessionIds: result.explicitRemovedSessionIds,\n saveCache: true,\n },\n onPublishing: () => updatePublicationPhase(\"publishing\"),\n });\n durableCommitted = true;\n this.options.workerRunner.commit?.(agentName);\n if (result.sourceFailures?.length) throw sourceFailureError(result.sourceFailures);\n markAgentFullSyncCompleted(agentName);\n appLogger.info(\"scan.backfill.done\", {\n agent: agentName,\n duration_ms: Math.round(performance.now() - startedAt),\n sessions: fullSessions.length,\n changed: result.changedIds?.length ?? 0,\n });\n return \"committed\";\n } catch (error) {\n if (!durableCommitted) agent.setSessionMetaMap(new Map(Object.entries(meta)));\n this.options.workerRunner.discard?.(agentName);\n appLogger.error(\"scan.backfill.error\", { agent: agentName, error });\n console.error(`[${agentName}] Backfill failed:`, error);\n return \"failed\";\n }\n }\n\n private buildFullSearchIndexJobs(context: string): SearchIndexWorkerJob[] {\n const snapshot = this.sessionIndex.snapshot();\n return snapshot.agents.flatMap((agent) => {\n if (!(agent.name in snapshot.byAgent)) return [];\n const cached = loadCachedSessions(agent.name);\n return [\n cached\n ? {\n kind: \"full\",\n context,\n agentName: agent.name,\n sessions: cached.sessions,\n meta: cached.meta,\n completeness: \"partial\",\n removedSessionIds: [],\n searchIndexOptions: { includePendingReindex: false },\n }\n : {\n kind: \"full\",\n context,\n agentName: agent.name,\n sessions: snapshot.byAgent[agent.name] ?? [],\n meta: buildAgentCacheMeta(agent),\n completeness: \"partial\",\n removedSessionIds: [],\n searchIndexOptions: { includePendingReindex: false },\n },\n ];\n });\n }\n\n private publicationId(context: string, agentName?: string): string {\n const id = this.nextPublicationId++;\n return agentName ? `${context}:${agentName}:${id}` : `${context}:${id}`;\n }\n\n private async commitSearchIndex(\n context: string,\n jobs: SearchIndexWorkerJob[],\n details: {\n publicationId: string;\n agent?: string;\n agents?: string[];\n onStarted?: () => void;\n },\n ): Promise<void> {\n appLogger.info(\"session.publication.prepared\", {\n publication_id: details.publicationId,\n context,\n agent: details.agent,\n agents: details.agents,\n jobs: jobs.length,\n });\n try {\n const publicationJobs = jobs.map((job) => ({\n ...job,\n publicationId: details.publicationId,\n }));\n await (details.onStarted\n ? this.searchIndexJobs.enqueue(context, publicationJobs, details.onStarted)\n : this.searchIndexJobs.enqueue(context, publicationJobs));\n } catch (error) {\n appLogger.error(\"session.publication.failed\", {\n publication_id: details.publicationId,\n context,\n agent: details.agent,\n stage: \"search_index\",\n error,\n });\n throw error;\n }\n appLogger.info(\"session.publication.index_committed\", {\n publication_id: details.publicationId,\n context,\n agent: details.agent,\n });\n }\n\n private async commitSessionPublication(\n publication: SessionPublication,\n ): Promise<SessionPublicationResult> {\n const publicationId = this.publicationId(publication.context, publication.agentName);\n await this.commitSearchIndex(publication.context, [publication.indexJob], {\n publicationId,\n agent: publication.agentName,\n ...(publication.onPublishing ? { onStarted: publication.onPublishing } : {}),\n });\n const diffStartedAt = performance.now();\n const event = this.sessionIndex.commitAgentSessions(\n publication.agentName,\n publication.sessions,\n publication.candidateChangedIds,\n );\n const diffDuration = performance.now() - diffStartedAt;\n this.emitSessionsChanged({\n agentName: publication.agentName,\n sessions: this.sessionIndex.snapshot().byAgent[publication.agentName] ?? [],\n event,\n });\n appLogger.info(\"session.publication.published\", {\n publication_id: publicationId,\n context: publication.context,\n agent: publication.agentName,\n sessions: publication.sessions.length,\n has_event: event != null,\n });\n return { event, diffDuration };\n }\n\n private findAgent(agentName: string): BaseAgent | undefined {\n return this.sessionIndex.findAgent(agentName);\n }\n\n private startupScanOptions(): Pick<ScanOptions, \"from\" | \"to\"> {\n return this.options.startupScanOptions ?? {};\n }\n\n private logUnchangedRefresh(agentName: string, startedAt: number): void {\n appLogger.debug(\"scan.refresh.unchanged\", {\n agent: agentName,\n duration_ms: Math.round(performance.now() - startedAt),\n });\n }\n}\n","/**\n * SessionWatcher — a deep module that hides platform-specific file watching\n * (recursive watch availability, non-recursive fallback trees, write-stability\n * polling, debounce) behind a tiny interface.\n *\n * Consumers only need to know: start watching these agent sources, stop, and get\n * notified (post write-stability + debounce) which agents' data changed. The\n * recursive-vs-fallback strategy, APFS mtime quirks, and path-stability polling\n * are all internal details.\n */\nimport { existsSync, readdirSync, statSync, watch, type FSWatcher } from \"node:fs\";\nimport { dirname, isAbsolute, join, relative, resolve } from \"node:path\";\nimport type { SessionWatchPlan } from \"@codesesh/core\";\nimport { appLogger } from \"./logging.js\";\n\nconst WRITE_STABILITY_THRESHOLD_MS = 250;\nconst WRITE_STABILITY_POLL_MS = 100;\n\nexport interface SessionWatchSource {\n readonly name: string;\n getSessionWatchPlan(): SessionWatchPlan;\n}\n\ninterface WatchScope {\n agentName: string;\n targetPath: string;\n}\n\ninterface WatchRegistration {\n path: string;\n recursive: boolean;\n watcher: FSWatcher;\n}\n\ninterface StablePathState {\n path: string;\n agentNames: Set<string>;\n lastMtimeMs: number | null;\n lastSize: number | null;\n stableSince: number;\n timer: NodeJS.Timeout | null;\n}\n\nexport type AgentsChangedListener = (agentNames: Set<string>) => void;\n\nexport function toAbsolutePath(path: string): string {\n return isAbsolute(path) ? path : resolve(path);\n}\n\nfunction closestWatchablePath(targetPath: string): string | null {\n if (!isAbsolute(targetPath) && !existsSync(targetPath)) {\n return null;\n }\n\n let current = toAbsolutePath(targetPath);\n\n while (!existsSync(current)) {\n const parent = dirname(current);\n if (parent === current) {\n return null;\n }\n current = parent;\n }\n\n return current;\n}\n\nfunction getWatchRoot(path: string): string {\n const stat = statSync(path);\n return stat.isDirectory() ? path : dirname(path);\n}\n\nexport function isRecursiveWatchSupported(\n // \"ibmi\" is a real process.platform value on IBM i (PASE) but is not yet\n // declared in @types/node's Platform union.\n platform: NodeJS.Platform | \"ibmi\" = process.platform,\n nodeVersion = process.versions.node,\n): boolean {\n if (platform === \"darwin\" || platform === \"win32\") {\n return true;\n }\n if (platform !== \"linux\" && platform !== \"aix\" && platform !== \"ibmi\") {\n return false;\n }\n\n const [major = 0, minor = 0] = nodeVersion.split(\".\").map((part) => Number(part));\n return major > 19 || (major === 19 && minor >= 1);\n}\n\nfunction isRecursiveWatchUnavailable(error: unknown): boolean {\n return (\n typeof error === \"object\" &&\n error !== null &&\n \"code\" in error &&\n error.code === \"ERR_FEATURE_UNAVAILABLE_ON_PLATFORM\"\n );\n}\n\nfunction isSameOrChildPath(parentPath: string, childPath: string): boolean {\n const path = relative(parentPath, childPath);\n return path === \"\" || (!path.startsWith(\"..\") && !isAbsolute(path));\n}\n\n/**\n * Sidecars a SQLite commit writes. `-shm` is excluded because a read-only open\n * rewrites it, which would make every scan look like a new change.\n */\nconst SQLITE_SIDECAR_SUFFIXES = [\"-wal\", \"-journal\"];\n\n/** True for `foo.db-wal` against `foo.db`, but not for `foo.db.bak`. */\nfunction isSqliteSidecarOf(changedPath: string, targetPath: string): boolean {\n return SQLITE_SIDECAR_SUFFIXES.some((suffix) => changedPath === `${targetPath}${suffix}`);\n}\n\nfunction isRelatedPath(changedPath: string, targetPath: string): boolean {\n return (\n isSameOrChildPath(targetPath, changedPath) ||\n isSameOrChildPath(changedPath, targetPath) ||\n isSqliteSidecarOf(changedPath, targetPath)\n );\n}\n\nfunction mergeScopes(target: WatchScope[], scopes: WatchScope[]): void {\n for (const scope of scopes) {\n if (\n !target.some(\n (item) => item.agentName === scope.agentName && item.targetPath === scope.targetPath,\n )\n ) {\n target.push(scope);\n }\n }\n}\n\nfunction resolveWatchEventPath(watchPath: string, filename: string | Buffer | null): string {\n const filenameText = filename?.toString();\n if (!filenameText) {\n return watchPath;\n }\n return isAbsolute(filenameText) ? filenameText : join(watchPath, filenameText);\n}\n\nexport class SessionWatcher {\n private watchers: WatchRegistration[] = [];\n private fallbackWatchScopes = new Map<string, WatchScope[]>();\n private stablePaths = new Map<string, StablePathState>();\n private listeners = new Set<AgentsChangedListener>();\n\n /** Register a listener fired (after write-stability polling) with the changed agent set. */\n onAgentsChanged(cb: AgentsChangedListener): () => void {\n this.listeners.add(cb);\n return () => {\n this.listeners.delete(cb);\n };\n }\n\n /** Begin watching the session sources declared by each agent adapter. */\n start(agents: SessionWatchSource[]): void {\n const scopesByRoot = new Map<string, WatchScope[]>();\n\n for (const agent of agents) {\n const plan = agent.getSessionWatchPlan();\n if (plan.status !== \"supported\") {\n appLogger.debug(\"watch.skip\", {\n agent: agent.name,\n status: plan.status,\n reason: plan.reason,\n });\n continue;\n }\n if (plan.targets.length === 0) {\n appLogger.debug(\"watch.skip\", { agent: agent.name, status: plan.status });\n continue;\n }\n\n for (const target of plan.targets) {\n const watchRootPath = closestWatchablePath(target.root ?? target.path);\n if (!watchRootPath) continue;\n\n let rootPath: string;\n try {\n rootPath = getWatchRoot(watchRootPath);\n } catch (error) {\n this.reportWatchError(\"watch.resolve.error\", { path: watchRootPath, error });\n continue;\n }\n const targetPath = toAbsolutePath(target.path);\n const scopes = scopesByRoot.get(rootPath) ?? [];\n if (\n !scopes.some((scope) => scope.agentName === agent.name && scope.targetPath === targetPath)\n ) {\n scopes.push({ agentName: agent.name, targetPath });\n }\n scopesByRoot.set(rootPath, scopes);\n }\n }\n\n for (const [rootPath, scopes] of scopesByRoot.entries()) {\n const agents = Array.from(new Set(scopes.map((scope) => scope.agentName)));\n appLogger.info(\"watch.start\", {\n root: rootPath,\n agents,\n targets: scopes.map((scope) => ({\n agent: scope.agentName,\n path: scope.targetPath,\n })),\n });\n\n if (isRecursiveWatchSupported()) {\n const started = this.watchDirectory(rootPath, scopes, true);\n if (started) {\n continue;\n }\n }\n\n this.watchDirectoryTree(rootPath, scopes);\n }\n }\n\n /** Stop all watchers and clear pending stability polls. */\n async dispose(): Promise<void> {\n for (const state of this.stablePaths.values()) {\n if (state.timer) {\n clearTimeout(state.timer);\n }\n }\n this.stablePaths.clear();\n\n await Promise.all(this.watchers.map(({ watcher }) => watcher.close()));\n this.watchers = [];\n this.fallbackWatchScopes.clear();\n this.listeners.clear();\n }\n\n private watchDirectory(path: string, scopes: WatchScope[], recursive: boolean): boolean {\n try {\n const watcher = watch(path, { recursive }, (eventType, filename) => {\n queueMicrotask(() => {\n try {\n const activeScopes = recursive\n ? scopes\n : (this.fallbackWatchScopes.get(path) ?? scopes);\n this.handleWatchEvent(path, activeScopes, eventType, filename);\n if (!recursive) {\n this.watchNewDirectories(path, filename, activeScopes);\n }\n } catch (error) {\n this.reportWatchError(\"watch.event.error\", { path, recursive, error });\n }\n });\n });\n\n watcher.on(\"error\", (error) => {\n this.reportWatchError(\"watch.error\", { path, recursive, error });\n });\n\n this.watchers.push({ path, recursive, watcher });\n return true;\n } catch (error) {\n if (recursive && isRecursiveWatchUnavailable(error)) {\n appLogger.warn(\"watch.recursive_unavailable\", { path, error });\n return false;\n }\n\n this.reportWatchError(\"watch.start.error\", { path, recursive, error });\n return false;\n }\n }\n\n private watchDirectoryTree(rootPath: string, scopes: WatchScope[]): void {\n const pending = [rootPath];\n\n while (pending.length > 0) {\n const dirPath = pending.pop()!;\n this.watchFallbackDirectory(dirPath, scopes);\n\n try {\n for (const entry of readdirSync(dirPath, { withFileTypes: true })) {\n if (entry.isDirectory()) {\n pending.push(join(dirPath, entry.name));\n }\n }\n } catch (error) {\n this.reportWatchError(\"watch.scan.error\", { path: dirPath, error });\n }\n }\n }\n\n private watchFallbackDirectory(path: string, scopes: WatchScope[]): void {\n const existingScopes = this.fallbackWatchScopes.get(path);\n if (existingScopes) {\n mergeScopes(existingScopes, scopes);\n return;\n }\n\n const storedScopes = [...scopes];\n this.fallbackWatchScopes.set(path, storedScopes);\n if (!this.watchDirectory(path, storedScopes, false)) {\n this.fallbackWatchScopes.delete(path);\n }\n }\n\n private watchNewDirectories(\n watchPath: string,\n filename: string | Buffer | null,\n scopes: WatchScope[],\n ): void {\n const path = resolveWatchEventPath(watchPath, filename);\n try {\n if (statSync(path).isDirectory()) {\n this.watchDirectoryTree(path, scopes);\n }\n } catch {\n this.unwatchFallbackTree(path);\n }\n }\n\n private unwatchFallbackTree(path: string): void {\n const active: WatchRegistration[] = [];\n for (const registration of this.watchers) {\n if (registration.recursive || !isSameOrChildPath(path, registration.path)) {\n active.push(registration);\n continue;\n }\n registration.watcher.close();\n this.fallbackWatchScopes.delete(registration.path);\n }\n this.watchers = active;\n }\n\n private handleWatchEvent(\n watchPath: string,\n scopes: WatchScope[],\n eventType: string,\n filename: string | Buffer | null,\n ): void {\n const changedPath = resolveWatchEventPath(watchPath, filename);\n const agentNames = new Set(\n scopes\n .filter((scope) => isRelatedPath(changedPath, scope.targetPath))\n .map((scope) => scope.agentName),\n );\n\n if (agentNames.size === 0) {\n return;\n }\n\n appLogger.debug(\"watch.event\", {\n event: eventType,\n path: changedPath,\n agents: Array.from(agentNames),\n });\n this.waitForStablePath(changedPath, agentNames);\n }\n\n private waitForStablePath(path: string, agentNames: Set<string>): void {\n const existing = this.stablePaths.get(path);\n if (existing) {\n for (const agentName of agentNames) {\n existing.agentNames.add(agentName);\n }\n return;\n }\n\n const state: StablePathState = {\n path,\n agentNames: new Set(agentNames),\n lastMtimeMs: null,\n lastSize: null,\n stableSince: Date.now(),\n timer: null,\n };\n this.stablePaths.set(path, state);\n this.pollStablePath(path);\n }\n\n private pollStablePath(path: string): void {\n const state = this.stablePaths.get(path);\n if (!state) {\n return;\n }\n\n let size: number;\n let mtimeMs: number;\n try {\n const stat = statSync(path);\n size = stat.size;\n mtimeMs = stat.mtimeMs;\n } catch {\n this.stablePaths.delete(path);\n this.emitAgentsChanged(state.agentNames);\n return;\n }\n\n const now = Date.now();\n const unchanged = state.lastSize === size && state.lastMtimeMs === mtimeMs;\n if (!unchanged) {\n state.lastSize = size;\n state.lastMtimeMs = mtimeMs;\n state.stableSince = now;\n }\n\n if (unchanged && now - state.stableSince >= WRITE_STABILITY_THRESHOLD_MS) {\n this.stablePaths.delete(path);\n this.emitAgentsChanged(state.agentNames);\n return;\n }\n\n state.timer = setTimeout(() => this.pollStablePath(path), WRITE_STABILITY_POLL_MS);\n }\n\n private emitAgentsChanged(agentNames: Set<string>): void {\n if (agentNames.size === 0) return;\n for (const listener of this.listeners) {\n listener(new Set(agentNames));\n }\n }\n\n private reportWatchError(event: string, data: Record<string, unknown>): void {\n appLogger.error(event, data);\n console.error(\"[watch] File watcher failed:\", data.error);\n }\n}\n","import { Worker } from \"node:worker_threads\";\nimport {\n getPricingGeneration,\n type AgentScanProgress,\n type ScanOptions,\n type SessionCacheMeta,\n type SessionHead,\n type SessionHeadChange,\n type SessionSourceFailure,\n type SessionSnapshotCompleteness,\n} from \"@codesesh/core\";\nimport { appLogger } from \"./logging.js\";\nimport type {\n ScanRefreshWorkerCommitRequest,\n ScanRefreshWorkerCheckpoint,\n ScanRefreshWorkerMessage,\n ScanRefreshWorkerRunRequest,\n} from \"./scan-refresh-worker.js\";\nimport type { ScanRefreshOperation } from \"./scan-refresh-operation.js\";\nimport { toError } from \"./errors.js\";\n\nexport interface WorkerPayload {\n previousSessions: SessionHead[];\n operation: ScanRefreshOperation;\n scanOptions: Pick<ScanOptions, \"from\" | \"to\" | \"fast\">;\n meta: Record<string, SessionCacheMeta>;\n onProgress?: (progress: AgentScanProgress) => void;\n onCheckpoint?: (checkpoint: ScanRefreshWorkerCheckpoint) => void;\n}\n\nexport interface WorkerResult {\n sessions: SessionHead[];\n meta: Record<string, SessionCacheMeta>;\n changedIds?: string[];\n sourceFailures?: SessionSourceFailure[];\n completeness: SessionSnapshotCompleteness;\n explicitRemovedSessionIds: string[];\n}\n\nexport interface WorkerRunner {\n readonly activeCount: number;\n run(agentName: string, payload: WorkerPayload): Promise<WorkerResult>;\n commit?(agentName: string): void;\n discard?(agentName: string): void;\n shutdown(): Promise<void>;\n}\n\ninterface PendingRequest {\n resolve: (result: WorkerResult) => void;\n reject: (error: Error) => void;\n payload: WorkerPayload;\n generation: number;\n onProgress?: (progress: AgentScanProgress) => void;\n onCheckpoint?: (checkpoint: ScanRefreshWorkerCheckpoint) => void;\n}\n\ninterface WorkerSlot {\n agentName: string;\n worker: Worker;\n pending: Map<number, PendingRequest>;\n generation: number;\n awaitingCommit: { requestId: number; generation: number } | null;\n closed: boolean;\n}\n\nconst SHUTDOWN_ERROR_MESSAGE = \"Scan refresh worker shut down\";\n\nfunction applySessionChanges(\n previousSessions: SessionHead[],\n changes: SessionHeadChange[],\n removedSessionIds: string[],\n): SessionHead[] {\n if (changes.length === 0 && removedSessionIds.length === 0) return previousSessions;\n const replacedIds = new Set(removedSessionIds);\n for (const { session } of changes) replacedIds.add(session.id);\n const retained = previousSessions.filter((session) => !replacedIds.has(session.id));\n const next: Array<SessionHead | undefined> = Array.from({\n length: retained.length + changes.length,\n });\n\n for (const { session, sortIndex } of changes) {\n if (sortIndex < 0 || sortIndex >= next.length || next[sortIndex]) {\n throw new Error(`Invalid scan refresh sort index: ${sortIndex}`);\n }\n next[sortIndex] = session;\n }\n\n let retainedIndex = 0;\n for (let index = 0; index < next.length; index += 1) {\n if (!next[index]) next[index] = retained[retainedIndex++];\n }\n if (retainedIndex !== retained.length || next.some((session) => !session)) {\n throw new Error(\"Invalid scan refresh delta\");\n }\n return next as SessionHead[];\n}\n\nfunction applyMetaChanges(\n previous: Record<string, SessionCacheMeta>,\n changed: Record<string, SessionCacheMeta>,\n replacedSessionIds: Iterable<string>,\n): Record<string, SessionCacheMeta> {\n const replacedIds = [...replacedSessionIds];\n if (Object.keys(changed).length === 0 && replacedIds.length === 0) return previous;\n const next = { ...previous };\n for (const id of replacedIds) delete next[id];\n return Object.assign(next, changed);\n}\n\nexport class ThreadWorkerRunner implements WorkerRunner {\n private workers = new Map<string, WorkerSlot>();\n private nextRequestId = 1;\n private isShuttingDown = false;\n\n constructor(private readonly workerUrl: URL) {}\n\n get activeCount(): number {\n let count = 0;\n for (const slot of this.workers.values()) {\n count += slot.pending.size + Number(slot.awaitingCommit != null);\n }\n return count;\n }\n\n run(agentName: string, payload: WorkerPayload): Promise<WorkerResult> {\n if (this.isShuttingDown) return Promise.reject(new Error(SHUTDOWN_ERROR_MESSAGE));\n\n const existingSlot = this.workers.get(agentName);\n if (existingSlot && (existingSlot.pending.size > 0 || existingSlot.awaitingCommit)) {\n return Promise.reject(new Error(`Scan refresh worker for ${agentName} is busy`));\n }\n const generation = existingSlot?.generation ?? 0;\n const request: ScanRefreshWorkerRunRequest = {\n type: \"run\",\n requestId: this.nextRequestId++,\n agentName,\n generation,\n pricingGenerationId: getPricingGeneration().id,\n operation: payload.operation,\n scanOptions: payload.scanOptions,\n ...(existingSlot ? {} : { previousSessions: payload.previousSessions, meta: payload.meta }),\n };\n\n return new Promise((resolve, reject) => {\n let slot = this.workers.get(agentName);\n const isNewWorker = !slot;\n if (!slot) {\n try {\n slot = this.createWorker(agentName, request);\n } catch (error) {\n reject(toError(error));\n return;\n }\n }\n\n slot.pending.set(request.requestId, {\n resolve,\n reject,\n payload,\n generation,\n onProgress: payload.onProgress,\n onCheckpoint: payload.onCheckpoint,\n });\n\n if (!isNewWorker) {\n try {\n slot.worker.postMessage(request);\n } catch (error) {\n slot.pending.delete(request.requestId);\n reject(toError(error));\n this.invalidateWorker(agentName, slot);\n }\n }\n });\n }\n\n commit(agentName: string): void {\n const slot = this.workers.get(agentName);\n const awaiting = slot?.awaitingCommit;\n if (!slot || !awaiting) return;\n const request: ScanRefreshWorkerCommitRequest = {\n type: \"commit\",\n requestId: awaiting.requestId,\n generation: awaiting.generation,\n };\n try {\n slot.worker.postMessage(request);\n slot.awaitingCommit = null;\n slot.generation += 1;\n } catch {\n this.invalidateWorker(agentName, slot);\n }\n }\n\n discard(agentName: string): void {\n const slot = this.workers.get(agentName);\n if (slot) this.invalidateWorker(agentName, slot);\n }\n\n async shutdown(): Promise<void> {\n this.isShuttingDown = true;\n const slots = [...this.workers.values()];\n this.workers.clear();\n const shutdownError = new Error(SHUTDOWN_ERROR_MESSAGE);\n for (const slot of slots) {\n slot.closed = true;\n for (const pending of slot.pending.values()) pending.reject(shutdownError);\n slot.pending.clear();\n }\n await Promise.allSettled(slots.map((slot) => slot.worker.terminate()));\n }\n\n private createWorker(agentName: string, request: ScanRefreshWorkerRunRequest): WorkerSlot {\n const worker = new Worker(this.workerUrl, { workerData: request });\n const slot: WorkerSlot = {\n agentName,\n worker,\n pending: new Map(),\n generation: request.generation,\n awaitingCommit: null,\n closed: false,\n };\n worker.unref();\n this.workers.set(agentName, slot);\n worker.on(\"message\", (message: unknown) => {\n if (appLogger.consumeWorkerMessage(message)) return;\n this.handleMessage(slot, message as ScanRefreshWorkerMessage);\n });\n worker.on(\"error\", (error) => {\n this.closeWorker(agentName, slot, toError(error));\n });\n worker.on(\"exit\", (code) => {\n if (slot.closed) return;\n const error = new Error(`Scan refresh worker exited before completing (code ${code})`);\n if (slot.pending.size > 0) {\n appLogger.warn(\"scan.refresh_worker.exit_before_done\", { agent: agentName, code });\n }\n this.closeWorker(agentName, slot, error);\n });\n return slot;\n }\n\n private handleMessage(slot: WorkerSlot, message: ScanRefreshWorkerMessage): void {\n const pending = slot.pending.get(message.requestId);\n if (!pending) return;\n if (message.generation !== pending.generation) {\n const error = new Error(\n `Scan refresh generation mismatch: expected ${pending.generation}, received ${message.generation}`,\n );\n slot.pending.delete(message.requestId);\n pending.reject(error);\n this.invalidateWorker(slot.agentName, slot);\n return;\n }\n if (message.type === \"progress\") {\n pending.onProgress?.(message.progress);\n return;\n }\n if (message.type === \"checkpoint\") {\n try {\n pending.onCheckpoint?.(message.checkpoint);\n } catch (error) {\n slot.pending.delete(message.requestId);\n pending.reject(toError(error));\n this.invalidateWorker(slot.agentName, slot);\n }\n return;\n }\n\n slot.pending.delete(message.requestId);\n if (message.type === \"error\") {\n pending.reject(new Error(message.error));\n this.invalidateWorker(slot.agentName, slot);\n return;\n }\n const changedIds = message.changes.map(({ session }) => session.id);\n const replacedSessionIds = [...changedIds, ...message.removedSessionIds];\n const removedMetaIds = [...message.removedSessionIds, ...message.removedMetaIds];\n try {\n const result = {\n sessions: applySessionChanges(\n pending.payload.previousSessions,\n message.changes,\n message.removedSessionIds,\n ),\n meta: applyMetaChanges(pending.payload.meta, message.meta, removedMetaIds),\n changedIds: replacedSessionIds,\n sourceFailures: message.sourceFailures,\n completeness: message.completeness,\n explicitRemovedSessionIds: message.explicitRemovedSessionIds,\n };\n slot.awaitingCommit = {\n requestId: message.requestId,\n generation: message.generation,\n };\n pending.resolve(result);\n } catch (error) {\n pending.reject(toError(error));\n this.invalidateWorker(slot.agentName, slot);\n }\n }\n\n private closeWorker(agentName: string, slot: WorkerSlot, error: Error): void {\n if (slot.closed) return;\n slot.closed = true;\n if (this.workers.get(agentName) === slot) this.workers.delete(agentName);\n for (const pending of slot.pending.values()) pending.reject(error);\n slot.pending.clear();\n slot.awaitingCommit = null;\n }\n\n private invalidateWorker(agentName: string, slot: WorkerSlot): void {\n this.closeWorker(\n agentName,\n slot,\n new Error(`Scan refresh worker state discarded for ${agentName}`),\n );\n void slot.worker.terminate().catch(() => undefined);\n }\n}\n","import { consola } from \"consola\";\nimport type { BaseAgent } from \"@codesesh/core\";\nimport { VERSION } from \"./version.js\";\n\nexport function printScanResults(agents: BaseAgent[]): void {\n consola.log(\"\");\n consola.box({\n title: \"CodeSesh\",\n message: `v${VERSION} • local session browser`,\n style: {\n padding: 1,\n borderColor: \"cyan\",\n },\n });\n consola.log(\"\");\n consola.info(\n `Indexing ${agents.map((agent) => agent.displayName).join(\", \")} sessions in the background.`,\n );\n consola.info(\"The Web UI will update automatically as sessions are discovered.\");\n consola.log(\"\");\n}\n","import { readFileSync } from \"node:fs\";\nimport { resolve, dirname } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\nconst pkg = JSON.parse(readFileSync(resolve(__dirname, \"../package.json\"), \"utf-8\"));\n\nexport const VERSION = pkg.version;\n","/**\n * Shape of `--json`: an index of what exists, not an archive of what was said.\n *\n * Sessions are reported as heads — metadata only. Messages, tool calls,\n * reasoning and file activity stay in each agent's own data directory, so this\n * output is deliberately not a backup, and must not quietly grow into one.\n */\nimport {\n filterSessionTreeByActivityWindow,\n getAgentInfoMap,\n type LiveSnapshot,\n type SessionHead,\n} from \"@codesesh/core\";\n\nexport interface SessionIndexAgent {\n name: string;\n displayName: string;\n count: number;\n available: boolean;\n}\n\nexport interface SessionIndexOutput {\n agents: SessionIndexAgent[];\n sessions: SessionHead[];\n}\n\nexport interface SessionIndexWindow {\n from?: number;\n to?: number;\n}\n\nexport function formatScanFailureDiagnostics(\n snapshot: Pick<LiveSnapshot, \"scanFailures\">,\n): string[] {\n return Object.values(snapshot.scanFailures ?? {}).map((failure) => {\n const source = failure.sourcePath ? ` at ${failure.sourcePath}` : \"\";\n return `[${failure.agentName}] Scan failed during ${failure.stage}${source} (${failure.errorClass}): ${failure.message}`;\n });\n}\n\nexport function buildSessionIndexOutput(\n snapshot: Pick<LiveSnapshot, \"sessions\" | \"byAgent\">,\n window: SessionIndexWindow = {},\n): SessionIndexOutput {\n // Keep --days/--from/--to meaningful for the JSON output too.\n const sessions = filterSessionTreeByActivityWindow(snapshot.sessions, window.from, window.to);\n\n const agents = getAgentInfoMap(\n Object.fromEntries(\n Object.entries(snapshot.byAgent).map(([name, list]) => [\n name,\n filterSessionTreeByActivityWindow(list, window.from, window.to).length,\n ]),\n ),\n ).map(({ name, displayName, count }) => ({\n name,\n displayName,\n count,\n available: count > 0,\n }));\n\n return { agents, sessions };\n}\n","import type { ScanOptions } from \"@codesesh/core\";\nimport { sessionRoutePath } from \"@codesesh/core/contract\";\nimport { resolveTimeWindow, type TimeWindow } from \"./time-window-resolution.js\";\n\nexport interface TargetSession {\n agent: string;\n sessionId: string;\n}\n\ninterface CliRuntimePlanInput {\n agent?: string;\n cwd?: string;\n from?: string;\n to?: string;\n days?: string;\n jsonOnly: boolean;\n useCache: boolean;\n targetSession: TargetSession | null;\n}\n\ninterface CliRuntimeEnvironment {\n currentWorkingDirectory: string;\n now?: number;\n}\n\nexport interface CliRuntimePlan {\n listWindow: TimeWindow;\n scanOptions: ScanOptions;\n startupScanOptions: Pick<ScanOptions, \"from\" | \"to\">;\n}\n\nexport function parseSessionUri(uri: string): TargetSession | null {\n const match = uri.match(/^([a-z]+):\\/\\/(.+)$/i);\n if (!match) return null;\n return { agent: match[1]!, sessionId: match[2]! };\n}\n\nexport function buildCliRuntimePlan(\n input: CliRuntimePlanInput,\n environment: CliRuntimeEnvironment,\n): CliRuntimePlan {\n const listWindow = resolveTimeWindow({\n mode: \"cli\",\n from: input.from,\n to: input.to,\n days: input.days,\n now: environment.now,\n });\n const cwd = input.cwd === \".\" ? environment.currentWorkingDirectory : input.cwd;\n const agents = input.targetSession\n ? [input.targetSession.agent]\n : input.agent\n ? input.agent.split(\",\").map((agent) => agent.trim())\n : undefined;\n\n return {\n listWindow,\n scanOptions: { agents, cwd, useCache: input.useCache },\n startupScanOptions:\n input.targetSession || input.jsonOnly ? {} : { from: listWindow.from, to: listWindow.to },\n };\n}\n\nexport function resolveStartupUrl(startupUrl: string, targetSession: TargetSession | null): string {\n if (!targetSession) return startupUrl;\n const url = new URL(startupUrl);\n url.pathname = sessionRoutePath({\n agentName: targetSession.agent,\n sessionId: targetSession.sessionId,\n });\n return url.toString();\n}\n\nexport function redactStartupUrl(startupUrl: string): string {\n const url = new URL(startupUrl);\n for (const key of url.searchParams.keys()) {\n url.searchParams.set(key, \"[redacted]\");\n }\n return url.toString();\n}\n","export const DEFAULT_PORT = 4521;\nexport const DEFAULT_PORT_FALLBACK_ATTEMPTS = 20;\n\nexport function parsePort(value: string | undefined): number {\n const port = parseInt(value ?? \"\", 10);\n return Number.isNaN(port) ? DEFAULT_PORT : port;\n}\n\nexport function hasExplicitPortArg(argv: string[]): boolean {\n return argv.some((arg, index) => {\n if (arg === \"--port\" || arg === \"-p\") return index < argv.length - 1;\n return arg.startsWith(\"--port=\") || /^-p\\d+$/.test(arg);\n });\n}\n","/**\n * Lifecycle owner for the background price refresh.\n *\n * The refresh used to be fired and forgotten: no timeout, no cancellation, and\n * it replaced the live prices the moment it returned — so one scan could price\n * its first sessions differently from its last. Here it is bounded, cancellable\n * on shutdown, and published only at a point where no scan is running.\n */\nimport { publishPendingPricing, refreshPricingCache } from \"@codesesh/core\";\nimport { appLogger } from \"./logging.js\";\n\n/** Long enough for a cold network, short enough not to outlive a --json run. */\nconst REFRESH_TIMEOUT_MS = 10_000;\n\nexport interface PricingRefresh {\n /** Makes a completed refresh current. Safe to call more than once. */\n publish(): void;\n /** Cancels an in-flight refresh and waits for it to settle. */\n cancel(): Promise<void>;\n}\n\nexport function startPricingRefresh(timeoutMs = REFRESH_TIMEOUT_MS): PricingRefresh {\n const controller = new AbortController();\n const completion = refreshPricingCache({ signal: controller.signal, timeoutMs }).catch(\n (error: unknown) => {\n appLogger.warn(\"pricing.refresh.error\", { error });\n return false;\n },\n );\n\n return {\n publish() {\n if (publishPendingPricing()) appLogger.info(\"pricing.refresh.published\", {});\n },\n async cancel() {\n controller.abort();\n await completion;\n },\n };\n}\n"],"mappings":"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","names":["Hono","isIP","isIP","__dirname","resolve","Hono","url","existsSync","fileURLToPath","existsSync","fileURLToPath","resolve","existsSync","fileURLToPath","key","currentPhase","nextPhase","scanStartedAt","sessions","existsSync","dirname","resolve","resolve","existsSync","dirname","agents","Worker","SHUTDOWN_ERROR_MESSAGE","applySessionChanges","resolve","Worker","existsSync","fileURLToPath","readFileSync","resolve","dirname","fileURLToPath"]}
|