codesesh 1.0.2 → 1.0.3

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.
Files changed (39) hide show
  1. package/dist/{chunk-VAUC2W7I.js → chunk-PSHZZITB.js} +1919 -731
  2. package/dist/chunk-PSHZZITB.js.map +1 -0
  3. package/dist/chunk-RF3EEWPH.js +17 -0
  4. package/dist/chunk-RF3EEWPH.js.map +1 -0
  5. package/dist/{chunk-PROMURPM.js → chunk-WAKW5OPS.js} +2 -2
  6. package/dist/{dist-6QTGTYZT.js → dist-RHDY2EZX.js} +18 -20
  7. package/dist/index.js +1291 -672
  8. package/dist/index.js.map +1 -1
  9. package/dist/project-identity-worker.js +27 -0
  10. package/dist/project-identity-worker.js.map +1 -0
  11. package/dist/scan-refresh-worker.js +15 -6
  12. package/dist/scan-refresh-worker.js.map +1 -1
  13. package/dist/search-index-worker.js +16 -6
  14. package/dist/search-index-worker.js.map +1 -1
  15. package/dist/smart-tag-worker.js +2 -2
  16. package/dist/web/assets/{ErrorBoundary-D11tWzfn.js → ErrorBoundary-DIwwrdlw.js} +1 -1
  17. package/dist/web/assets/InteractiveReceipt-DmNBDVms.js +1 -0
  18. package/dist/web/assets/{OverviewScreen-DriPmCam.js → OverviewScreen-B5JekBLC.js} +1 -1
  19. package/dist/web/assets/Projects-Bj6ma2k2.js +1 -0
  20. package/dist/web/assets/{SearchFilterBar-Bx73B5e9.js → SearchFilterBar-B9VrUbym.js} +1 -1
  21. package/dist/web/assets/{SearchResultsPanel-A6_3TPhW.js → SearchResultsPanel-C1cuuOKq.js} +1 -1
  22. package/dist/web/assets/{SessionDetail-BnpvDwtH.js → SessionDetail-Dc2CQ3hH.js} +5 -5
  23. package/dist/web/assets/contract-DXvltqJG.js +1 -0
  24. package/dist/web/assets/index-3UfOiTBO.css +1 -0
  25. package/dist/web/assets/index-DBMiEd61.js +1410 -0
  26. package/dist/web/assets/panel-CLnL4kMN.js +1 -0
  27. package/dist/web/assets/{session-indexes-0oT5HSS5.js → session-indexes-BPhf1X2P.js} +2 -2
  28. package/dist/web/assets/{utils-DgUgu15E.js → utils-BKqufGdv.js} +1 -1
  29. package/dist/web/index.html +8 -8
  30. package/package.json +1 -1
  31. package/dist/chunk-VAUC2W7I.js.map +0 -1
  32. package/dist/web/assets/InteractiveReceipt-DYGyHeZd.js +0 -1
  33. package/dist/web/assets/Projects-BPDIcUBK.js +0 -1
  34. package/dist/web/assets/contract-V6QuD0UY.js +0 -1
  35. package/dist/web/assets/index-99ZxpV2y.js +0 -1410
  36. package/dist/web/assets/index-B2RqUgZ5.css +0 -1
  37. package/dist/web/assets/panel-C-gc79Gz.js +0 -1
  38. /package/dist/{chunk-PROMURPM.js.map → chunk-WAKW5OPS.js.map} +0 -0
  39. /package/dist/{dist-6QTGTYZT.js.map → dist-RHDY2EZX.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-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"]}
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/snapshot-aggregation.ts","../src/api/request-payloads.ts","../src/api/session-detail-stream.ts","../src/api/search-result-merge.ts","../src/api/session-aliases-view.ts","../src/api/handlers.ts","../src/api/bookmark-handlers.ts","../src/api/sse-event-buffer.ts","../src/project-identity-resolver.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/search-index-job-runner.ts","../src/errors.ts","../src/pending-search-index-jobs.ts","../src/search-index-maintenance-scheduler.ts","../src/latest-value-throttle.ts","../src/scan-status-model.ts","../src/scan-status-reporter.ts","../src/search-index-publisher.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 {\n buildSessionIndexOutput,\n formatCacheFailureDiagnostics,\n formatScanFailureDiagnostics,\n} 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\n// Node's default reaction to an unhandled rejection is to terminate without\n// touching the app log; record it first, then let the crash proceed.\nprocess.on(\"unhandledRejection\", (reason) => {\n appLogger.error(\"process.unhandled_rejection\", { error: reason });\n throw reason;\n});\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 // Parsed named fields only — raw argv is the one unredacted sink in the\n // logging pipeline, and would capture any future credential-bearing flag.\n appLogger.info(\"cli.start\", {\n version: VERSION,\n port,\n host: hostname,\n transport: transport.kind,\n remote_access: remoteAccess,\n json: jsonOnly,\n no_open: noOpen,\n cache: useCache,\n clear_cache: clearCache,\n trace,\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 for (const diagnostic of formatCacheFailureDiagnostics(result)) console.error(diagnostic);\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 // If shutdown rejects, process.exit(0) inside it never runs; log and\n // exit non-zero instead of leaving an unhandled rejection behind.\n const shutdownOnSignal = (signal: NodeJS.Signals) => {\n shutdown(signal).catch((error) => {\n appLogger.error(\"cli.shutdown_failed\", { signal, error });\n process.exit(1);\n });\n };\n process.once(\"SIGINT\", shutdownOnSignal);\n process.once(\"SIGTERM\", shutdownOnSignal);\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 {\n createProjectIdentityResolver,\n type ProjectIdentityResolver,\n} from \"./project-identity-resolver.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 projectIdentityResolver?: ProjectIdentityResolver;\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 const projectIdentityResolver =\n options.projectIdentityResolver ?? createProjectIdentityResolver();\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 projectIdentityResolver,\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 try {\n await projectIdentityResolver.shutdown();\n } finally {\n appLogger.info(\"server.shutdown.phase\", { phase: \"store-closing\", port: actualPort });\n await store.shutdown();\n }\n }\n appLogger.info(\"server.shutdown.phase\", { phase: \"complete\", port: actualPort });\n },\n };\n}\n","import { Hono } from \"hono\";\nimport {\n handleGetAgents,\n handleGetConfig,\n handleGetDashboard,\n handleGetFileActivity,\n handleGetProjects,\n handleGetScanStatus,\n handlePostClientLog,\n handleSearchSessions,\n handleGetSessions,\n handleGetSessionData,\n type ScanResultSource,\n type SessionListDefaults,\n} from \"./handlers.js\";\nimport {\n handleDeleteBookmark,\n handleDeleteSessionAlias,\n handleGetBookmarks,\n handleImportBookmarks,\n handlePutBookmark,\n handlePutSessionAlias,\n} from \"./bookmark-handlers.js\";\nimport type { ScanEventSource } from \"../scan-source.js\";\nimport type { ProjectIdentityResolver } from \"../project-identity-resolver.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 projectIdentityResolver?: ProjectIdentityResolver;\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) =>\n handleGetSessions(c, scanSource, listDefaults, options.projectIdentityResolver),\n );\n api.get(\"/search\", (c) =>\n handleSearchSessions(c, scanSource, listDefaults, options.projectIdentityResolver),\n );\n api.get(\"/file-activity\", (c) =>\n handleGetFileActivity(c, listDefaults, options.projectIdentityResolver),\n );\n api.get(\"/sessions/:agent/:id\", (c) =>\n handleGetSessionData(c, scanSource, options.projectIdentityResolver),\n );\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 SearchRequestOptions,\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): SearchRequestOptions {\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","import {\n listFileActivity,\n listDashboardCostFacts,\n type DashboardCostFacts,\n type DashboardData,\n type DashboardScope,\n type SessionHead,\n} from \"@codesesh/core\";\nimport { buildSessionTree, type SessionTree } from \"@codesesh/core/contract\";\nimport { appLogger } from \"../logging.js\";\nimport type { ScanResultSource } from \"./scan-sources.js\";\n\ninterface SnapshotAggregationCache {\n sessions: SessionHead[];\n sessionTree?: SessionTree;\n values: Map<string, unknown>;\n}\n\nconst SNAPSHOT_AGGREGATION_CACHE_LIMIT = 64;\nconst snapshotAggregationCaches = new WeakMap<ScanResultSource, SnapshotAggregationCache>();\ntype SnapshotAggregationCacheState = \"hit\" | \"miss\";\n\nfunction getSnapshotAggregationCache(\n source: ScanResultSource,\n sessions: SessionHead[],\n): SnapshotAggregationCache {\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 return cache;\n}\n\n/**\n * LiveScanStore replaces its canonical sessions array whenever the snapshot\n * changes, so that existing reference is the snapshot version.\n */\nexport function getSnapshotAggregation<T>(\n source: ScanResultSource,\n sessions: SessionHead[],\n key: readonly unknown[],\n build: () => T,\n onCacheState?: (state: SnapshotAggregationCacheState) => void,\n): T {\n const cache = getSnapshotAggregationCache(source, sessions);\n\n const cacheKey = JSON.stringify(key);\n if (cache.values.has(cacheKey)) {\n const cached = cache.values.get(cacheKey) as T;\n cache.values.delete(cacheKey);\n cache.values.set(cacheKey, cached);\n onCacheState?.(\"hit\");\n return cached;\n }\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 onCacheState?.(\"miss\");\n return value;\n}\n\nexport function getSnapshotSessionTree(\n source: ScanResultSource,\n sessions: SessionHead[],\n): SessionTree {\n const cache = getSnapshotAggregationCache(source, sessions);\n return (cache.sessionTree ??= buildSessionTree(sessions));\n}\n\ntype DashboardStorageAggregation = Pick<DashboardData, \"recentFileActivities\">;\n\nexport function getDashboardCostFacts(\n source: ScanResultSource,\n sessions: SessionHead[],\n from: number | undefined,\n to: number | undefined,\n cacheTo: number | undefined,\n analyticsRevision: string | null,\n): DashboardCostFacts | null {\n const build = () => listDashboardCostFacts({ from, to });\n if (analyticsRevision === null) return build();\n\n return getSnapshotAggregation(\n source,\n sessions,\n [\"dashboard-cost-facts\", from, cacheTo, analyticsRevision],\n build,\n );\n}\n\nexport function getDashboardStorageAggregation(\n source: ScanResultSource,\n sessions: SessionHead[],\n scope: DashboardScope,\n from: number | undefined,\n to: number,\n cacheTo: number,\n analyticsRevision: string | null,\n): DashboardStorageAggregation {\n const build = (): DashboardStorageAggregation => ({\n recentFileActivities: listFileActivity({\n agent: scope.agent,\n projectKind: scope.projectKind,\n projectKey: scope.projectKey,\n from,\n to,\n limit: 12,\n }),\n });\n const startedAt = performance.now();\n const log = (cache: SnapshotAggregationCacheState | \"unavailable\") => {\n appLogger.info(\"api.dashboard.storage_aggregation\", {\n cache,\n ...(analyticsRevision === null ? {} : { analytics_revision: analyticsRevision }),\n duration_ms: Math.round(performance.now() - startedAt),\n });\n };\n\n if (analyticsRevision === null) {\n const value = build();\n log(\"unavailable\");\n return value;\n }\n\n return getSnapshotAggregation(\n source,\n sessions,\n [\n \"dashboard-storage\",\n scope.agent,\n scope.projectKind,\n scope.projectKey,\n from,\n cacheTo,\n analyticsRevision,\n ],\n build,\n log,\n );\n}\n","import type { BookmarkRecord } from \"@codesesh/core\";\nimport { normalizeSessionReference, type SessionReference } from \"@codesesh/core/contract\";\n\nexport function isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null;\n}\n\nexport function 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\nexport function 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\nexport function 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\nexport function 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","import type { SessionDetail } from \"@codesesh/core\";\n\nconst SESSION_DETAIL_STREAM_BATCH_CHARS = 64 * 1024;\n\nexport function 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","import {\n formatSessionReference,\n normalizeSessionReference,\n type SearchResult,\n type SessionTree,\n} from \"@codesesh/core/contract\";\nimport type { AliasView } from \"./session-aliases-view.js\";\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 */\nexport function withParentContext(\n results: SearchResult[],\n getSessionTree: () => SessionTree,\n aliases: AliasView,\n): SearchResult[] {\n if (!results.some((result) => result.session.parent_reference)) return results;\n const byRouteKey = getSessionTree().byRouteKey;\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))?.session;\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\nexport function 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","/**\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 SessionSearchContext,\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 context: SessionSearchContext = {},\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, {\n sessionSnapshot: scanResult.sessions,\n sessionTree: context.sessionTree,\n }).sort((a, b) => getSessionActivityTime(b.session) - getSessionActivityTime(a.session));\n}\n","import type { Context } from \"hono\";\nimport type { SessionHead, SmartTag } from \"@codesesh/core\";\nimport {\n addCalendarDays,\n countCalendarDays,\n getSessionAgentKey,\n type SessionTree,\n type AppConfig,\n type SessionReference,\n startOfCalendarDay,\n} from \"@codesesh/core/contract\";\nimport {\n attachProjectMetricsFromTree,\n createProjectScopeMatcherFromIdentity,\n getAgentInfoMap,\n getAnalyticsRevision,\n mergeSearchQueryOptions,\n executeSessionSearch,\n getSearchProjectDirectory,\n listDashboardCostFacts,\n listFileActivity,\n listCachedProjectGroups,\n materializeSessionDetailResponse,\n matchesProjectScope as sessionMatchesProjectScope,\n matchesProjectIdentity,\n normalizeProjectDirectory,\n PROJECT_IDENTITY_RESOLVER_REVISION,\n buildDashboard,\n type DashboardData,\n type DashboardScope,\n type ProjectIdentityProjection,\n type ProjectScopeMatcher,\n} from \"@codesesh/core\";\nimport { appLogger } from \"../logging.js\";\nimport type { ProjectIdentityResolver } from \"../project-identity-resolver.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 type { ScanResultSource, ScanStatusSource } from \"./scan-sources.js\";\nimport {\n getDashboardCostFacts,\n getDashboardStorageAggregation,\n getSnapshotAggregation,\n getSnapshotSessionTree,\n} from \"./snapshot-aggregation.js\";\nimport { sanitizeClientLogData } from \"./request-payloads.js\";\nimport { createSessionDetailJsonResponse } from \"./session-detail-stream.js\";\nimport { mergeAliasSearchResults, withParentContext } from \"./search-result-merge.js\";\nimport {\n decorateFileActivity,\n findAliasSearchResults,\n loadAliasView,\n} from \"./session-aliases-view.js\";\n\nexport type { SessionListDefaults };\n\nexport type { ScanResultSource, ScanStatusSource } from \"./scan-sources.js\";\n\nconst KNOWN_AGENT_NAMES = getAgentInfoMap({}).map((agent) => agent.name);\nexport const KNOWN_AGENT_NAME_SET = new Set(KNOWN_AGENT_NAMES);\n\nasync function resolveProjectScope(\n cwd: string,\n sessions: readonly SessionHead[],\n resolver: ProjectIdentityResolver | undefined,\n): Promise<ProjectScopeMatcher> {\n const normalizedCwd = normalizeProjectDirectory(cwd);\n const matchingSession = sessions.find(\n (session) =>\n normalizeProjectDirectory(session.directory) === normalizedCwd &&\n session.project_identity != null &&\n session.project_identity_resolver_revision === PROJECT_IDENTITY_RESOLVER_REVISION &&\n Boolean(session.project_identity_input_signature),\n );\n if (matchingSession?.project_identity) {\n return createProjectScopeMatcherFromIdentity(cwd, matchingSession.project_identity);\n }\n if (!resolver) throw new Error(\"Project identity resolver is unavailable\");\n\n const projection = await resolver.resolve(cwd);\n return createProjectScopeMatcherFromIdentity(cwd, projection.identity);\n}\n\nfunction reportProjectScopeResolutionFailure(endpoint: string, error: unknown): void {\n appLogger.warn(\"api.project_scope.unavailable\", {\n endpoint,\n error: error instanceof Error ? error.message : String(error),\n });\n}\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 ClientLogPayload {\n event?: unknown;\n data?: unknown;\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\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 analyticsRevision = getAnalyticsRevision();\n const projects = getSnapshotAggregation(\n scanSource,\n scanResult.sessions,\n [\"projects\", from, to, analyticsRevision],\n () => {\n const tree = getSnapshotSessionTree(scanSource, scanResult.sessions);\n const costFacts = listDashboardCostFacts({ from, to, includeModelCosts: false });\n return {\n projects: attachProjectMetricsFromTree(\n listCachedProjectGroups(scanResult.sessions),\n tree,\n from,\n to,\n costFacts,\n ).filter(\n (project) =>\n project.sessionCount > 0 ||\n project.messages > 0 ||\n project.tokens > 0 ||\n project.cost > 0,\n ),\n };\n },\n );\n return c.json(projects);\n}\n\nexport async function handleGetSessions(\n c: Context,\n scanSource: ScanResultSource,\n defaults: SessionListDefaults = {},\n resolver?: ProjectIdentityResolver,\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 = optionalQueryValue(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 let projectScope: ProjectScopeMatcher | undefined;\n if (cwd && !projectIdentity) {\n try {\n projectScope = await resolveProjectScope(cwd, scanResult.sessions, resolver);\n } catch (error) {\n reportProjectScopeResolutionFailure(\"sessions\", error);\n return c.json({ error: \"Project scope unavailable\" }, 503);\n }\n }\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 [\n \"sessions\",\n agentFilter,\n projectIdentity?.kind,\n projectIdentity?.key,\n projectScope?.identity.kind,\n projectScope?.identity.key,\n projectScope?.path,\n tag,\n from,\n to,\n ],\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 (projectScope) {\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\nexport async function handleSearchSessions(\n c: Context,\n scanSource: ScanResultSource,\n defaults: SessionListDefaults = {},\n resolver?: ProjectIdentityResolver,\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 searchRequestOptions = 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 cwd = getSearchProjectDirectory(query, searchRequestOptions);\n let projectScope: ProjectScopeMatcher | undefined;\n if (cwd) {\n try {\n projectScope = await resolveProjectScope(cwd, scanResult.sessions, resolver);\n } catch (error) {\n reportProjectScopeResolutionFailure(\"search\", error);\n return c.json({ error: \"Project scope unavailable\" }, 503);\n }\n }\n const { cwd: _cwd, ...searchOptions } = searchRequestOptions;\n const resolvedSearchOptions = projectScope ? { ...searchOptions, projectScope } : searchOptions;\n const aliases = loadAliasView();\n let sessionTree: SessionTree | undefined;\n const getSessionTree = () =>\n (sessionTree ??= getSnapshotSessionTree(scanSource, scanResult.sessions));\n const effectiveSearchOptions = mergeSearchQueryOptions(query, resolvedSearchOptions).options;\n const searchContext =\n effectiveSearchOptions.costMin != null || effectiveSearchOptions.costMax != null\n ? { sessionTree: getSessionTree() }\n : undefined;\n const searchResults = searchContext\n ? executeSessionSearch(query, resolvedSearchOptions, scanResult, searchContext)\n : executeSessionSearch(query, resolvedSearchOptions, scanResult);\n const results = searchResults.map((result) => ({\n ...result,\n session: aliases.decorate(result.session, result.reference),\n }));\n const aliasResults = findAliasSearchResults(\n query,\n resolvedSearchOptions,\n scanResult,\n aliases,\n searchContext,\n );\n const mergedResults = mergeAliasSearchResults(\n results,\n aliasResults,\n resolvedSearchOptions.limit ?? 50,\n );\n return c.json({\n results: withParentContext(mergedResults, getSessionTree, aliases),\n });\n}\n\nexport async function handleGetFileActivity(\n c: Context,\n defaults: SessionListDefaults = {},\n resolver?: ProjectIdentityResolver,\n) {\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 cwd = optionalQueryValue(c.req.query(\"cwd\"));\n let projectScope: ProjectScopeMatcher | undefined;\n if (cwd) {\n try {\n projectScope = await resolveProjectScope(cwd, [], resolver);\n } catch (error) {\n reportProjectScopeResolutionFailure(\"file-activity\", error);\n return c.json({ error: \"Project scope unavailable\" }, 503);\n }\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 projectScope,\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(\n c: Context,\n scanSource: ScanResultSource,\n resolver?: ProjectIdentityResolver,\n) {\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 materialize = (fallback?: ProjectIdentityProjection[\"identity\"]) =>\n materializeSessionDetailResponse(scanSource.getSnapshot(), reference, {\n ...(messageCursor ? { messageCursor } : {}),\n ...(fallback ? { projectIdentityFallback: fallback } : {}),\n });\n let result = materialize();\n if (result.status === \"needs-identity\") {\n // Identity resolution probes the filesystem and spawns git; it must run\n // on the worker resolver, never synchronously on the request path.\n if (!resolver) throw new Error(\"Project identity resolver is unavailable\");\n result = materialize((await resolver.resolve(result.directory)).identity);\n }\n if (result.status === \"needs-identity\") {\n throw new Error(\"Project identity fallback was not applied\");\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 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\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 cacheTo = fixedTo ?? startOfCalendarDay(to);\n const analyticsRevision = getAnalyticsRevision();\n const costFacts = getDashboardCostFacts(\n scanSource,\n scanResult.sessions,\n compare?.from ?? from,\n to,\n cacheTo,\n analyticsRevision,\n );\n const aggregate = getSnapshotAggregation(\n scanSource,\n scanResult.sessions,\n [\n \"dashboard\",\n scope.agent,\n scope.projectKind,\n scope.projectKey,\n from,\n cacheTo,\n compare?.from,\n compare?.to,\n analyticsRevision,\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 costFacts,\n });\n },\n );\n\n const storageAggregation = getDashboardStorageAggregation(\n scanSource,\n scanResult.sessions,\n scope,\n from,\n to,\n cacheTo,\n analyticsRevision,\n );\n const data: DashboardData = {\n ...aggregate,\n ...storageAggregation,\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 { Context } from \"hono\";\nimport type { BookmarkRecord, BookmarkView } from \"@codesesh/core\";\nimport { createSessionIndex } from \"@codesesh/core/contract\";\nimport {\n SessionAliasValidationError,\n StateStorageUnavailableError,\n deleteBookmark,\n deleteSessionAlias,\n importBookmarks,\n listBookmarks,\n loadCachedSessionHeads,\n materializeBookmarkViews,\n upsertBookmark,\n upsertSessionAlias,\n} from \"@codesesh/core\";\nimport { KNOWN_AGENT_NAME_SET } from \"./handlers.js\";\nimport { parseBookmarkImport, parseBookmarkReference } from \"./request-payloads.js\";\nimport { getSnapshotAggregation } from \"./snapshot-aggregation.js\";\nimport type { ScanResultSource } from \"./scan-sources.js\";\nimport {\n decorateBookmark,\n invalidateAliasView,\n loadAliasView,\n type AliasView,\n} from \"./session-aliases-view.js\";\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 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\n/**\n * Write endpoints must reject unknown agents: rows for agents that do not\n * exist accumulate in state.db forever — materialization filters on the known\n * set, so they are never visible and never garbage-collected.\n */\nfunction isKnownAgentKey(agentKey: string): boolean {\n return KNOWN_AGENT_NAME_SET.has(agentKey.trim().toLowerCase());\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 if (!isKnownAgentKey(payload.agentName)) {\n return c.json({ error: `Unknown agent: ${payload.agentName}` }, 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 parsed = payload\n .map((entry) => parseBookmarkImport(entry))\n .filter((entry): entry is NonNullable<typeof entry> => entry !== null);\n\n if (parsed.length !== payload.length) {\n return c.json({ error: \"Invalid bookmark payload\" }, 400);\n }\n\n // Legacy exports may reference agents this build no longer knows; skip them\n // (reporting the count) instead of rejecting the rest of the import.\n const bookmarks = parsed.filter((entry) => isKnownAgentKey(entry.reference.agentName));\n const skippedUnknownAgents = parsed.length - bookmarks.length;\n\n return withStorageErrors(\n () => {\n const imported = importBookmarks(bookmarks);\n const views = materializeStoredBookmarks(scanSource, imported, loadAliasView());\n return c.json({\n bookmarks: views,\n storageAvailable: true,\n ...(skippedUnknownAgents > 0 ? { skippedUnknownAgents } : {}),\n });\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 if (!isKnownAgentKey(agentKey)) {\n return c.json({ error: `Unknown agent: ${agentKey}` }, 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 if (!isKnownAgentKey(agentKey)) {\n return c.json({ error: `Unknown agent: ${agentKey}` }, 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 if (!isKnownAgentKey(agentKey)) {\n return c.json({ error: `Unknown agent: ${agentKey}` }, 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","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]) => [\n agentName,\n agentStatus.status,\n agentStatus.error ?? null,\n agentStatus.completeness ?? null,\n agentStatus.sourceFailureCount ?? null,\n agentStatus.sourceFailureSummary ?? null,\n ]);\n const partialBackfills = Object.entries(status.backfill.partialAgents ?? {})\n .sort(([left], [right]) => left.localeCompare(right))\n .map(([agentName, completion]) => [\n agentName,\n completion.completeness,\n completion.sourceFailureCount ?? null,\n completion.sourceFailureSummary ?? null,\n ]);\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 partialBackfills,\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 { Worker } from \"node:worker_threads\";\nimport type { ProjectIdentityProjection } from \"@codesesh/core\";\nimport { appLogger } from \"./logging.js\";\nimport type {\n ProjectIdentityWorkerMessage,\n ProjectIdentityWorkerRequest,\n} from \"./project-identity-worker.js\";\n\nexport const PROJECT_IDENTITY_RESOLVER_MAX_WORKERS = 2;\n\nconst SHUTDOWN_ERROR_MESSAGE = \"Project identity resolver shut down\";\n\nexport interface ProjectIdentityResolver {\n resolve(cwd: string): Promise<ProjectIdentityProjection>;\n shutdown(): Promise<void>;\n}\n\ninterface PendingRequest {\n requestId: number;\n cwd: string;\n resolve: (projection: ProjectIdentityProjection) => void;\n reject: (error: Error) => void;\n}\n\ninterface WorkerSlot {\n worker: Worker;\n pending: PendingRequest | null;\n closed: boolean;\n}\n\nfunction toError(error: unknown): Error {\n return error instanceof Error ? error : new Error(String(error));\n}\n\nfunction isWorkerMessage(message: unknown): message is ProjectIdentityWorkerMessage {\n return (\n typeof message === \"object\" &&\n message !== null &&\n \"type\" in message &&\n ((message.type === \"resolved\" && \"requestId\" in message && \"projection\" in message) ||\n (message.type === \"failed\" && \"requestId\" in message && \"error\" in message))\n );\n}\n\nexport class ThreadProjectIdentityResolver implements ProjectIdentityResolver {\n private readonly workers = new Set<WorkerSlot>();\n private readonly queue: PendingRequest[] = [];\n private nextRequestId = 1;\n private isShuttingDown = false;\n\n constructor(\n private readonly workerUrl: URL,\n private readonly maxWorkers = PROJECT_IDENTITY_RESOLVER_MAX_WORKERS,\n ) {}\n\n resolve(cwd: string): Promise<ProjectIdentityProjection> {\n if (this.isShuttingDown) return Promise.reject(new Error(SHUTDOWN_ERROR_MESSAGE));\n\n return new Promise((resolve, reject) => {\n this.queue.push({ requestId: this.nextRequestId++, cwd, resolve, reject });\n this.pump();\n });\n }\n\n async shutdown(): Promise<void> {\n if (this.isShuttingDown) return;\n this.isShuttingDown = true;\n const error = new Error(SHUTDOWN_ERROR_MESSAGE);\n for (const request of this.queue.splice(0)) request.reject(error);\n\n const workers = [...this.workers];\n this.workers.clear();\n for (const slot of workers) {\n slot.closed = true;\n slot.pending?.reject(error);\n slot.pending = null;\n }\n await Promise.allSettled(workers.map(({ worker }) => worker.terminate()));\n }\n\n private pump(): void {\n while (!this.isShuttingDown && this.queue.length > 0) {\n const slot = this.idleWorker() ?? this.createWorker();\n if (!slot) return;\n const request = this.queue.shift();\n if (!request) return;\n slot.pending = request;\n try {\n slot.worker.postMessage({\n type: \"resolve\",\n requestId: request.requestId,\n cwd: request.cwd,\n } satisfies ProjectIdentityWorkerRequest);\n } catch (error) {\n this.closeWorker(slot, toError(error));\n }\n }\n }\n\n private idleWorker(): WorkerSlot | null {\n for (const slot of this.workers) {\n if (!slot.closed && slot.pending == null) return slot;\n }\n return null;\n }\n\n private createWorker(): WorkerSlot | null {\n if (this.workers.size >= this.maxWorkers) return null;\n\n let worker: Worker;\n try {\n worker = new Worker(this.workerUrl);\n } catch (error) {\n this.rejectQueued(toError(error));\n return null;\n }\n\n const slot: WorkerSlot = { worker, pending: null, closed: false };\n this.workers.add(slot);\n worker.unref();\n worker.on(\"message\", (message: unknown) => {\n if (appLogger.consumeWorkerMessage(message)) return;\n this.handleWorkerMessage(slot, message);\n });\n worker.on(\"error\", (error) => this.closeWorker(slot, toError(error)));\n worker.on(\"exit\", (code) => {\n if (!slot.closed) {\n this.closeWorker(slot, new Error(`Project identity worker exited with code ${code}`));\n }\n });\n return slot;\n }\n\n private handleWorkerMessage(slot: WorkerSlot, message: unknown): void {\n if (!isWorkerMessage(message) || slot.closed) return;\n const request = slot.pending;\n if (!request || message.requestId !== request.requestId) return;\n\n slot.pending = null;\n if (message.type === \"resolved\") request.resolve(message.projection);\n else request.reject(new Error(message.error));\n this.pump();\n }\n\n private closeWorker(slot: WorkerSlot, error: Error): void {\n if (slot.closed) return;\n slot.closed = true;\n this.workers.delete(slot);\n const request = slot.pending;\n slot.pending = null;\n request?.reject(error);\n if (!this.isShuttingDown) this.pump();\n }\n\n private rejectQueued(error: Error): void {\n for (const request of this.queue.splice(0)) request.reject(error);\n }\n}\n\nexport function createProjectIdentityResolver(): ProjectIdentityResolver {\n return new ThreadProjectIdentityResolver(\n new URL(\"./project-identity-worker.js\", import.meta.url),\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 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 (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_request.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 API 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 // Per-listener isolation: one broken SSE subscriber must not starve the\n // rest, and on the queueEvent timer path an escaped throw would be an\n // uncaught exception.\n for (const listener of this.listeners) {\n try {\n listener(event);\n } catch (error) {\n appLogger.error(\"scan.sessions_listener.error\", { error });\n }\n }\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 // A rejection here has no awaiter — without the catch it would escape\n // as an unhandled rejection and take down the process.\n this.refresh(agentName).catch((error) => {\n appLogger.error(\"scan.refresh.uncaught\", { agent: agentName, error });\n });\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, ScanCompletion } 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\"; completion?: ScanCompletion })\n | (BackfillAttemptRef & {\n status: \"running\";\n progress?: BackfillProgress;\n completion?: ScanCompletion;\n })\n | (BackfillAttemptRef & {\n status: BackfillTerminalStatus | \"cancelled\";\n completion?: ScanCompletion;\n });\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 recordCompletion(attempt: BackfillAttemptRef, completion: ScanCompletion): boolean {\n const current = this.matchingRunningAttempt(attempt);\n if (!current) return false;\n this.attempts.set(attempt.agentName, { ...current, completion: { ...completion } });\n return true;\n }\n\n complete(attempt: BackfillAttemptRef, status: BackfillTerminalStatus): boolean {\n const current = this.matchingRunningAttempt(attempt);\n if (!current) return false;\n this.attempts.set(attempt.agentName, { ...current, 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 const completion = state.completion ? { completion: { ...state.completion } } : {};\n return state.status === \"running\" && state.progress\n ? { ...state, progress: { ...state.progress }, ...completion }\n : { ...state, ...completion };\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 partialAgents: Record<string, ScanCompletion> = {};\n for (const attempt of states) {\n if (attempt.status === \"committed\" && attempt.completion?.completeness === \"partial\") {\n partialAgents[attempt.agentName] = { ...attempt.completion };\n }\n }\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 ...(Object.keys(partialAgents).length > 0 ? { partialAgents } : {}),\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 type AgentCacheFailure,\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 cacheFailures: Record<string, AgentCacheFailure> = {};\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.cacheFailures = { ...snapshot.cacheFailures };\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.cacheFailures).length > 0 ? { cacheFailures: this.cacheFailures } : {}),\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.cacheFailures[agentName];\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","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 // Non-fatal failures keep the batch running: the worker continues\n // with the remaining agents and reports them in the done message.\n if (message.fatal) {\n this.finishBatch(\n activeBatch,\n new Error(\n `Search index worker failed to persist ${message.stage} for ${message.agentName}`,\n ),\n );\n }\n return;\n }\n if (message.type !== \"done\") return;\n\n if (message.failedAgents.length > 0) {\n appLogger.warn(\"search_index.batch_partial\", {\n batch_id: activeBatch.id,\n context: message.context,\n failed_agents: message.failedAgents,\n });\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 {\n PersistedSessionHeadChange,\n SearchIndexSyncOptions,\n SessionCacheMeta,\n} 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, PersistedSessionHeadChange>;\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 PersistedSessionHeadChange,\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): PersistedSessionHeadChange[] => {\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","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 type { AgentScanProgress } from \"@codesesh/core\";\nimport type {\n BackfillStatus,\n ScanCompletion,\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 if (this.status.backfill.partialAgents) {\n backfill.partialAgents = Object.fromEntries(\n Object.entries(this.status.backfill.partialAgents).map(([agentName, completion]) => [\n agentName,\n { ...completion },\n ]),\n );\n } else {\n delete backfill.partialAgents;\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(\n agentName: string,\n sessionCount?: number,\n completion: ScanCompletion = { completeness: \"complete\" },\n ): 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 ...completion,\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 completeness: status.completeness ?? \"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 ...(backfill.partialAgents\n ? {\n partialAgents: Object.fromEntries(\n Object.entries(backfill.partialAgents).map(([agentName, completion]) => [\n agentName,\n { ...completion },\n ]),\n ),\n }\n : {}),\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 type {\n ScanCompletion,\n ScanStatusEvent,\n SearchIndexMaintenanceStatus,\n} from \"@codesesh/core/contract\";\nimport type { AgentScanProgress } from \"@codesesh/core\";\nimport type { BackfillAttemptRef, BackfillLifecycle } from \"./backfill-lifecycle.js\";\n\nimport { LatestValueThrottle } from \"./latest-value-throttle.js\";\nimport { ScanStatusModel } from \"./scan-status-model.js\";\nimport { appLogger } from \"./logging.js\";\n\nconst STATUS_PROGRESS_INTERVAL_MS = 100;\n\ntype StatusChangedListener = (event: ScanStatusEvent) => void;\n\nexport interface ScanStatusReporterOptions {\n /** Session count for an agent in the current snapshot. */\n sessionCount(agentName: string): number | undefined;\n backfills: BackfillLifecycle;\n}\n\n/**\n * Owns scan-status projection and fan-out: the ScanStatusModel, the\n * per-key progress throttles, and the status listener set. The sync engine\n * reports lifecycle transitions here and keeps only refresh orchestration.\n */\nexport class ScanStatusReporter {\n private readonly scanStatus = new ScanStatusModel();\n private readonly listeners = new Set<StatusChangedListener>();\n private readonly progressThrottles = new Map<string, LatestValueThrottle<void>>();\n private shuttingDown = false;\n\n constructor(private readonly options: ScanStatusReporterOptions) {}\n\n subscribe(listener: StatusChangedListener): () => void {\n this.listeners.add(listener);\n return () => this.listeners.delete(listener);\n }\n\n status(): ScanStatusEvent {\n return this.scanStatus.snapshot();\n }\n\n markShuttingDown(): void {\n this.shuttingDown = true;\n this.cancelProgressStatuses();\n }\n\n /** Record a failure without publishing (initialization-time bookkeeping). */\n recordAgentFailure(agentName: string, message: string, sessionCount?: number): void {\n this.scanStatus.failAgent(agentName, message, sessionCount);\n }\n\n failAgent(agentName: string, message: string): void {\n this.flushProgressStatus(`scan:${agentName}`);\n this.publishStatus(this.scanStatus.failAgent(agentName, message));\n }\n\n updateSearchIndexMaintenance(status: SearchIndexMaintenanceStatus): void {\n this.publishStatus(this.scanStatus.updateSearchIndexMaintenance(status));\n }\n\n startScanBatch(agentNames: string[], phase: ScanStatusEvent[\"phase\"]): void {\n const sessionCounts = Object.fromEntries(\n agentNames.map((agentName) => [agentName, this.options.sessionCount(agentName) ?? 0]),\n );\n this.publishStatus(this.scanStatus.startBatch(agentNames, phase, sessionCounts));\n }\n\n setScanPhase(phase: ScanStatusEvent[\"phase\"]): void {\n this.publishStatus(this.scanStatus.setPhase(phase));\n }\n\n beginAgentScan(agentName: string): void {\n this.cancelProgressStatus(`scan:${agentName}`);\n if (!this.scanStatus.snapshot().active) this.startScanBatch([agentName], \"scanning\");\n this.publishStatus(\n this.scanStatus.beginAgent(agentName, this.options.sessionCount(agentName) ?? 0),\n );\n }\n\n updateAgentScanProgress(\n agentName: string,\n progress: AgentScanProgress,\n backfillAttempt?: BackfillAttemptRef,\n ): void {\n const backfills = this.options.backfills;\n if (backfillAttempt) {\n const key = `backfill:${agentName}`;\n const current = 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 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(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 beginAgentPublishing(agentName: string): void {\n this.flushProgressStatus(`scan:${agentName}`);\n this.publishStatus(this.scanStatus.publishAgent(agentName));\n }\n\n queueAgentPublication(agentName: string): void {\n this.flushProgressStatus(`scan:${agentName}`);\n this.publishStatus(this.scanStatus.queueAgentPublication(agentName));\n }\n\n finishAgentScan(agentName: string, completion: ScanCompletion): void {\n this.flushProgressStatus(`scan:${agentName}`);\n this.publishStatus(\n this.scanStatus.finishAgent(agentName, this.options.sessionCount(agentName), completion),\n );\n }\n\n finishScanBatch(): void {\n this.flushProgressStatuses(\"scan:\");\n this.publishStatus(this.scanStatus.finishBatch());\n }\n\n publishBackfillStatus(): void {\n this.publishStatus(this.scanStatus.updateBackfill(this.options.backfills.status()));\n }\n\n publishBackfillProgress(key: string, phase: string): void {\n this.publishProgressStatus(\n key,\n phase,\n this.scanStatus.updateBackfill(this.options.backfills.status()),\n );\n }\n\n flushProgressStatus(key: string): void {\n const throttle = this.progressThrottles.get(key);\n if (!throttle) return;\n throttle.flush();\n throttle.cancel();\n this.progressThrottles.delete(key);\n }\n\n cancelProgressStatus(key: string): void {\n const throttle = this.progressThrottles.get(key);\n if (!throttle) return;\n throttle.cancel();\n this.progressThrottles.delete(key);\n }\n\n flushProgressStatuses(prefix: string): void {\n for (const key of this.progressThrottles.keys()) {\n if (key.startsWith(prefix)) this.flushProgressStatus(key);\n }\n }\n\n cancelProgressStatuses(): void {\n for (const throttle of this.progressThrottles.values()) throttle.cancel();\n this.progressThrottles.clear();\n }\n\n private publishStatus(event: ScanStatusEvent | null): void {\n if (!event || this.shuttingDown) return;\n for (const listener of this.listeners) {\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.progressThrottles.get(key);\n if (!throttle) {\n throttle = new LatestValueThrottle<void>(STATUS_PROGRESS_INTERVAL_MS, () => {\n this.publishStatus(this.scanStatus.snapshot());\n });\n this.progressThrottles.set(key, throttle);\n }\n throttle.push(undefined, phase);\n }\n}\n","import { buildAgentCacheMeta, type LiveSnapshot, type loadCachedSessions } from \"@codesesh/core\";\nimport { appLogger } from \"./logging.js\";\nimport type { SearchIndexJobRunner } from \"./search-index-job-runner.js\";\nimport type { SearchIndexWorkerJob } from \"./search-index-worker.js\";\n\ntype CachedSessions = NonNullable<ReturnType<typeof loadCachedSessions>>;\n\nexport interface SearchIndexPublisherOptions {\n jobs: SearchIndexJobRunner;\n snapshot(): LiveSnapshot;\n readCachedSessions(agentName: string): CachedSessions | null;\n}\n\n/**\n * Owns search-index publication: job construction, publication-id minting,\n * and the durable enqueue with its logging protocol.\n */\nexport class SearchIndexPublisher {\n private nextPublicationId = 1;\n\n constructor(private readonly options: SearchIndexPublisherOptions) {}\n\n buildFullSearchIndexJobs(context: string): SearchIndexWorkerJob[] {\n const snapshot = this.options.snapshot();\n return snapshot.agents.flatMap((agent) => {\n if (!(agent.name in snapshot.byAgent)) return [];\n const cached = this.options.readCachedSessions(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 publicationId(context: string, agentName?: string): string {\n const id = this.nextPublicationId++;\n return agentName ? `${context}:${agentName}:${id}` : `${context}:${id}`;\n }\n\n 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.options.jobs.enqueue(context, publicationJobs, details.onStarted)\n : this.options.jobs.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","import {\n FileSystemSessionSource,\n attachMissingProjectIdentities,\n buildAgentCacheMeta,\n getAgentFullSyncCursor,\n computeSessionDiff,\n loadCachedSessions,\n markAgentFullSyncProgress,\n markAgentFullSyncStarted,\n markAgentFullSyncCompleted,\n readCachedSessions,\n readAgentCacheInitialization,\n readAgentLastFullSyncAt,\n sessionSignature,\n type BaseAgent,\n type ScanOptions,\n type LiveSnapshot,\n type SessionHead,\n type PersistedSessionHeadChange,\n type SessionSourceFailure,\n type SessionSnapshotCompleteness,\n} from \"@codesesh/core\";\nimport type {\n ScanCompletion,\n ScanStatusEvent,\n SessionsUpdatedEvent,\n} 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 { 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 { ScanStatusReporter } from \"./scan-status-reporter.js\";\nimport { SearchIndexPublisher } from \"./search-index-publisher.js\";\nimport type {\n BackfillScanRefreshOperation,\n ScanRefreshOperation,\n} from \"./scan-refresh-operation.js\";\nimport type { ScanRefreshWorkerCheckpoint } from \"./scan-refresh-worker.js\";\nimport { AgentUnavailableDuringScanError } from \"./scan-refresh-error.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: PersistedSessionHeadChange[];\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 onCommitted?: (result: SessionPublicationResult) => void;\n}\n\ninterface SessionPublicationResult {\n durableCommitted: true;\n event: SessionsUpdatedEvent | null;\n diffDuration: number;\n}\n\ninterface RefreshResult {\n result: Exclude<AgentOperationResult, \"failed\">;\n completion: ScanCompletion;\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;\n// SSE carries one compact summary; logs retain the complete failure list.\nconst SOURCE_FAILURE_SUMMARY_MAX_LENGTH = 160;\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 buildScanCompletion(\n completeness: SessionSnapshotCompleteness,\n sourceFailures: readonly SessionSourceFailure[],\n): ScanCompletion {\n if (sourceFailures.length === 0) return { completeness };\n const firstFailure = sourceFailures[0]!;\n const summary = `${firstFailure.errorClass}: ${firstFailure.message}`;\n return {\n completeness: \"partial\",\n sourceFailureCount: sourceFailures.length,\n sourceFailureSummary:\n summary.length > SOURCE_FAILURE_SUMMARY_MAX_LENGTH\n ? `${summary.slice(0, SOURCE_FAILURE_SUMMARY_MAX_LENGTH - 1)}…`\n : summary,\n };\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 readonly statusReporter: ScanStatusReporter;\n private readonly indexPublisher: SearchIndexPublisher;\n private readonly searchIndexJobs: SearchIndexJobRunner;\n private readonly searchIndexMaintenance: SearchIndexMaintenanceScheduler;\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.statusReporter = new ScanStatusReporter({\n sessionCount: (agentName) => this.sessionIndex.snapshot().byAgent[agentName]?.length,\n backfills: this.backfills,\n });\n this.searchIndexJobs = new SearchIndexJobRunner();\n this.indexPublisher = new SearchIndexPublisher({\n jobs: this.searchIndexJobs,\n snapshot: () => this.sessionIndex.snapshot(),\n readCachedSessions: (agentName) => this.readCachedSessionsOrWarn(\"search.index\", agentName),\n });\n this.searchIndexMaintenance = new SearchIndexMaintenanceScheduler(\n this.searchIndexJobs,\n (status) => this.statusReporter.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.statusReporter.recordAgentFailure(\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.statusReporter.status();\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 return this.statusReporter.subscribe(listener);\n }\n\n async syncInitialIndex(): Promise<void> {\n const jobs = this.indexPublisher.buildFullSearchIndexJobs(\"scan.initial\");\n await this.indexPublisher.commitSearchIndex(\"scan.initial\", jobs, {\n publicationId: this.indexPublisher.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.statusReporter.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.statusReporter.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.statusReporter.markShuttingDown();\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 emitSessionsChanged(change: AgentSessionsChanged): void {\n if (this.isShuttingDown) return;\n for (const listener of this.sessionsChangedListeners) {\n try {\n listener(change);\n } catch (error) {\n this.reportPostCommitError(\"session.publication\", change.agentName, error);\n }\n }\n }\n\n private reportPostCommitError(\n operation: \"scan.refresh\" | \"scan.backfill\" | \"session.publication\",\n agentName: string,\n error: unknown,\n ): void {\n appLogger.error(`${operation}.post_commit_error`, { agent: agentName, error });\n }\n\n private finishCommittedAgentScan(agentName: string, completion: ScanCompletion): void {\n try {\n this.statusReporter.finishAgentScan(agentName, completion);\n } catch (error) {\n this.reportPostCommitError(\"scan.refresh\", agentName, error);\n // finishAgent is idempotent, so one retry restores the terminal projection.\n try {\n this.statusReporter.finishAgentScan(agentName, completion);\n } catch (recoveryError) {\n this.reportPostCommitError(\"scan.refresh\", agentName, recoveryError);\n }\n }\n }\n\n private async performRefresh(agentName: string): Promise<AgentOperationResult> {\n this.statusReporter.beginAgentScan(agentName);\n const startedAt = performance.now();\n let failed = false;\n let durableCommitted = false;\n let cached: CachedSessions | null = null;\n let result: AgentOperationResult = \"failed\";\n let completion: ScanCompletion = { completeness: \"complete\" };\n try {\n if (this.findAgent(agentName))\n cached = this.readCachedSessionsOrWarn(\"scan.refresh\", agentName);\n const refresh = await this.runRefresh(agentName, cached, startedAt, (committedCompletion) => {\n durableCommitted = true;\n completion = committedCompletion;\n result = \"committed\";\n });\n result = refresh.result;\n completion = refresh.completion;\n } catch (error) {\n if (durableCommitted) {\n this.reportPostCommitError(\"scan.refresh\", agentName, error);\n result = \"committed\";\n } else {\n this.options.workerRunner.discard?.(agentName);\n failed = true;\n const failure = toError(error);\n if (failure instanceof AgentUnavailableDuringScanError) {\n appLogger.warn(\"scan.refresh.worker_agent_unavailable\", {\n agent: agentName,\n error: failure.message,\n });\n } else {\n appLogger.error(\"scan.refresh.error\", { agent: agentName, error });\n }\n console.error(`[${agentName}] Session refresh failed:`, error);\n this.statusReporter.failAgent(agentName, failure.message);\n }\n }\n try {\n if (!failed) {\n if (durableCommitted) this.finishCommittedAgentScan(agentName, completion);\n else this.statusReporter.finishAgentScan(agentName, completion);\n }\n } catch (error) {\n if (!durableCommitted) throw error;\n this.reportPostCommitError(\"scan.refresh\", agentName, error);\n }\n // The backfill probe touches the agent's filesystem (isAvailable /\n // listSessionSources) and may throw on transient errors; that must not\n // fail — let alone reject — an otherwise finished refresh.\n try {\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 } catch (error) {\n appLogger.warn(\"scan.refresh.backfill_probe_failed\", { agent: agentName, error });\n }\n return result;\n }\n\n private async runRefresh(\n agentName: string,\n cached: CachedSessions | null,\n startedAt: number,\n onDurableCommit: (completion: ScanCompletion) => void,\n ): Promise<RefreshResult> {\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 { result: \"skipped\", completion: { completeness: \"complete\" } };\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 { result: \"unchanged\", completion: { completeness: \"complete\" } };\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 {\n result: \"unchanged\",\n completion: buildScanCompletion(strategyResult.completeness, strategyResult.sourceFailures),\n };\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 const completion = buildScanCompletion(\n strategyResult.completeness,\n strategyResult.sourceFailures,\n );\n this.statusReporter.queueAgentPublication(agentName);\n let publicationCommitted = false;\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.statusReporter.beginAgentPublishing(agentName),\n onCommitted: () => {\n publicationCommitted = true;\n onDurableCommit(completion);\n },\n });\n } catch (error) {\n if (!publicationCommitted) {\n agent.setSessionMetaMap(durableMeta);\n if (durableLastRefreshAt == null) this.lastRefreshAtByAgent.delete(agentName);\n else this.lastRefreshAtByAgent.set(agentName, durableLastRefreshAt);\n }\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 }\n return { result: \"committed\", completion };\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.statusReporter.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 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 agent.commitChangeCheck();\n this.lastRefreshAtByAgent.set(agent.name, checkResult.timestamp);\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 agent.commitChangeCheck();\n this.lastRefreshAtByAgent.set(agent.name, checkResult.timestamp);\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 agent.commitChangeCheck();\n this.lastRefreshAtByAgent.set(agent.name, checkResult.timestamp);\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.statusReporter.updateAgentScanProgress(\n agent.name,\n progress,\n runOptions.backfillAttempt,\n ),\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 if (!markAgentFullSyncProgress(agentName, checkpoint.backfillCursor)) {\n // Without a durable cursor the next restart re-walks the whole history;\n // do not log the checkpoint as if it landed.\n appLogger.warn(\"scan.backfill.checkpoint_not_durable\", {\n agent: agentName,\n cursor: checkpoint.backfillCursor,\n });\n return;\n }\n appLogger.debug(\"scan.backfill.checkpoint\", {\n agent: agentName,\n cursor: checkpoint.backfillCursor,\n sessions: checkpoint.changes.length,\n });\n }\n\n private readCachedSessionsOrWarn(scope: string, agentName: string): CachedSessions | null {\n const outcome = readCachedSessions(agentName);\n if (outcome.status === \"failed\") {\n appLogger.warn(`${scope}.cache_state_unavailable`, {\n agent: agentName,\n state: \"cached_sessions\",\n });\n return null;\n }\n return outcome.value;\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 let cachedSessions = cached;\n if (reloadCached || cached === undefined) {\n const outcome = readCachedSessions(agent.name);\n if (outcome.status === \"failed\") {\n // A broken cache read must not masquerade as a truncated cache and\n // trigger a full-history backfill against unknown state.\n appLogger.warn(\"scan.backfill.cache_state_unavailable\", {\n agent: agent.name,\n state: \"cached_sessions\",\n });\n return false;\n }\n cachedSessions = outcome.value;\n }\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.statusReporter.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.statusReporter.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.statusReporter.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.statusReporter.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 = this.readCachedSessionsOrWarn(\"scan.backfill\", 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 if (!markAgentFullSyncStarted(agentName)) {\n appLogger.warn(\"scan.backfill.cache_state_unavailable\", {\n agent: agentName,\n state: \"full_sync_started\",\n });\n }\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 const completion = buildScanCompletion(result.completeness, result.sourceFailures ?? []);\n this.statusReporter.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.statusReporter.publishBackfillProgress(`backfill:${agentName}`, phase);\n }\n };\n updatePublicationPhase(\"publish-queued\");\n const publication = 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 onCommitted: () => {\n durableCommitted = true;\n if (completion.completeness === \"partial\") {\n this.backfills.recordCompletion(attempt, completion);\n }\n },\n });\n durableCommitted = publication.durableCommitted;\n this.options.workerRunner.commit?.(agentName);\n if (!markAgentFullSyncCompleted(agentName)) {\n appLogger.warn(\"scan.backfill.completion_not_durable\", { agent: agentName });\n }\n appLogger.info(\n result.sourceFailures?.length ? \"scan.backfill.partial\" : \"scan.backfill.done\",\n {\n agent: agentName,\n duration_ms: Math.round(performance.now() - startedAt),\n sessions: fullSessions.length,\n changed: result.changedIds?.length ?? 0,\n failed_sources: result.sourceFailures?.length ?? 0,\n },\n );\n if (result.sourceFailures?.length) {\n appLogger.warn(\"scan.backfill.source_failures\", {\n agent: agentName,\n failures: result.sourceFailures,\n });\n }\n return \"committed\";\n } catch (error) {\n if (durableCommitted) {\n this.reportPostCommitError(\"scan.backfill\", agentName, error);\n return \"committed\";\n }\n 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 async commitSessionPublication(\n publication: SessionPublication,\n ): Promise<SessionPublicationResult> {\n const publicationId = this.indexPublisher.publicationId(\n publication.context,\n publication.agentName,\n );\n await this.indexPublisher.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 const result: SessionPublicationResult = { durableCommitted: true, event, diffDuration };\n publication.onCommitted?.(result);\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 result;\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 // Reached from watcher timers; an escaped throw would be an uncaught\n // exception, and one broken listener must not starve the rest.\n for (const listener of this.listeners) {\n try {\n listener(new Set(agentNames));\n } catch (error) {\n appLogger.error(\"watch.agents_listener.error\", { error });\n }\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 PersistedSessionHeadChange,\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 {\n AGENT_UNAVAILABLE_DURING_SCAN_ERROR_CODE,\n AgentUnavailableDuringScanError,\n} from \"./scan-refresh-error.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: PersistedSessionHeadChange[],\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(\n message.errorCode === AGENT_UNAVAILABLE_DURING_SCAN_ERROR_CODE\n ? new AgentUnavailableDuringScanError(slot.agentName)\n : new Error(message.error),\n );\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 formatCacheFailureDiagnostics(\n snapshot: Pick<LiveSnapshot, \"cacheFailures\">,\n): string[] {\n return Object.values(snapshot.cacheFailures ?? {}).map(\n (failure) =>\n `[${failure.agentName}] Cache persistence failed; serving in-memory results without advancing the durable baseline`,\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","resolve","isIP","isIP","__dirname","resolve","Hono","url","existsSync","fileURLToPath","existsSync","fileURLToPath","Worker","toError","resolve","SHUTDOWN_ERROR_MESSAGE","toError","Worker","existsSync","fileURLToPath","toError","key","currentPhase","nextPhase","toError","scanStartedAt","sessions","existsSync","dirname","resolve","resolve","existsSync","dirname","agents","Worker","SHUTDOWN_ERROR_MESSAGE","applySessionChanges","resolve","toError","Worker","existsSync","fileURLToPath","readFileSync","resolve","dirname","fileURLToPath"]}