codesesh 1.0.6 → 1.0.8

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 (64) hide show
  1. package/README.md +1 -1
  2. package/dist/{chunk-COZSWVCH.js → chunk-AGUAXTKC.js} +2 -2
  3. package/dist/{chunk-XQDYKKRC.js → chunk-DHQPM5FF.js} +98 -14
  4. package/dist/chunk-DHQPM5FF.js.map +1 -0
  5. package/dist/{chunk-YZ6XCSVQ.js → chunk-KVTLNX7V.js} +3 -3
  6. package/dist/chunk-KVTLNX7V.js.map +1 -0
  7. package/dist/{chunk-A3MT6L6Z.js → chunk-L4G3LE7I.js} +25 -26
  8. package/dist/chunk-L4G3LE7I.js.map +1 -0
  9. package/dist/{chunk-L3DDWTYV.js → chunk-RBCCNCDO.js} +12 -10
  10. package/dist/chunk-RBCCNCDO.js.map +1 -0
  11. package/dist/{chunk-4QFNZCBR.js → chunk-V3HKVTIO.js} +3 -2
  12. package/dist/chunk-V3HKVTIO.js.map +1 -0
  13. package/dist/{chunk-4ND6AT6W.js → chunk-YLXHGL4S.js} +6 -6
  14. package/dist/chunk-YLXHGL4S.js.map +1 -0
  15. package/dist/{discovery-ADSQARBV.js → discovery-KEZQU6RL.js} +7 -5
  16. package/dist/index.js +42 -16
  17. package/dist/index.js.map +1 -1
  18. package/dist/project-identity-worker.js +4 -4
  19. package/dist/scan-refresh-worker.js +6 -6
  20. package/dist/search-index-worker.js +6 -6
  21. package/dist/session-detail-worker.js +6 -6
  22. package/dist/smart-tag-worker.js +3 -3
  23. package/dist/web/assets/CustomTimeWindowDialog-z5xtqkBF.js +1 -0
  24. package/dist/web/assets/DetailLanding-CpV0jLmT.js +1 -0
  25. package/dist/web/assets/DialogTitle-B8zPwJB8.js +1 -0
  26. package/dist/web/assets/InteractiveReceipt-Bsj37HtN.js +1 -0
  27. package/dist/web/assets/OverviewScreen-B9qZqEQA.js +1 -0
  28. package/dist/web/assets/PrismHighlighter-DWS6Nx_X.js +6 -0
  29. package/dist/web/assets/Projects-oY3KCgS4.js +1 -0
  30. package/dist/web/assets/SearchResultsPanel-BAManMmt.js +1 -0
  31. package/dist/web/assets/SessionDetail-KSgkmLV7.js +53 -0
  32. package/dist/web/assets/SmartTagChips-BMP9pPRw.js +1 -0
  33. package/dist/web/assets/api-CtZGdxlN.js +1 -0
  34. package/dist/web/assets/index-BSLHxV0w.css +1 -0
  35. package/dist/web/assets/index-DNw59Qsn.js +1423 -0
  36. package/dist/web/assets/jsx-runtime-D3jfb0Ew.js +1 -0
  37. package/dist/web/assets/panel-DcOuALYX.js +1 -0
  38. package/dist/web/assets/session-indexes-DKukxoe1.js +4 -0
  39. package/dist/web/assets/translate-CLoII3EO.js +2 -0
  40. package/dist/web/assets/utils-Dk_44zMo.js +1 -0
  41. package/dist/web/index.html +9 -8
  42. package/package.json +2 -2
  43. package/dist/chunk-4ND6AT6W.js.map +0 -1
  44. package/dist/chunk-4QFNZCBR.js.map +0 -1
  45. package/dist/chunk-A3MT6L6Z.js.map +0 -1
  46. package/dist/chunk-L3DDWTYV.js.map +0 -1
  47. package/dist/chunk-XQDYKKRC.js.map +0 -1
  48. package/dist/chunk-YZ6XCSVQ.js.map +0 -1
  49. package/dist/web/assets/CustomTimeWindowDialog-D2bx7uDv.js +0 -1
  50. package/dist/web/assets/InteractiveReceipt-BFpIdno8.js +0 -1
  51. package/dist/web/assets/OverviewScreen-D_KXfiJi.js +0 -1
  52. package/dist/web/assets/PrismHighlighter-BgVkYu_S.js +0 -6
  53. package/dist/web/assets/Projects-CN44UpuR.js +0 -1
  54. package/dist/web/assets/SearchResultsPanel-CWD01v-a.js +0 -1
  55. package/dist/web/assets/SessionDetail-D8taQ6Tl.js +0 -53
  56. package/dist/web/assets/api-B9lJtVbO.js +0 -1
  57. package/dist/web/assets/index-XpolWMY4.js +0 -1423
  58. package/dist/web/assets/index-xbEEMszv.css +0 -1
  59. package/dist/web/assets/jsx-runtime-B-hcVAMW.js +0 -1
  60. package/dist/web/assets/session-indexes-fib48ZKn.js +0 -4
  61. package/dist/web/assets/translate-Dmym1ZDl.js +0 -2
  62. package/dist/web/assets/utils-Bk66u8b3.js +0 -1
  63. /package/dist/{chunk-COZSWVCH.js.map → chunk-AGUAXTKC.js.map} +0 -0
  64. /package/dist/{discovery-ADSQARBV.js.map → discovery-KEZQU6RL.js.map} +0 -0
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/cli-exit.ts","../src/server.ts","../src/api/routes.ts","../src/project-identity-resolver.ts","../src/api/query-params.ts","../src/api/handler-support.ts","../src/api/snapshot-pagination.ts","../src/api/snapshot-aggregation.ts","../src/api/catalog-handlers.ts","../src/time-window-resolution.ts","../../core/src/search/session-search.ts","../../core/src/state/database.ts","../../core/src/state/bookmarks.ts","../../core/src/state/session-aliases.ts","../../core/src/bookmarks/materialize.ts","../src/api/session-aliases-view.ts","../src/api/dashboard-handler.ts","../src/api/search-result-merge.ts","../src/api/search-handlers.ts","../src/session-detail-loader.ts","../src/api/session-detail-stream.ts","../src/api/session-handlers.ts","../src/api/request-payloads.ts","../src/api/client-log-handler.ts","../src/api/bookmark-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-backfill-scheduler.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/session-publication.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 { closeLoggerBeforeTermination } from \"./cli-exit.js\";\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 resolvePublicOrigin,\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 } from \"@codesesh/core/runtime/agents\";\nimport { perf } from \"@codesesh/core/runtime/diagnostics\";\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 appLogger.flushSync();\n throw reason;\n});\nprocess.on(\"uncaughtExceptionMonitor\", (error, origin) => {\n appLogger.error(\"process.uncaught_exception\", { error, exception_origin: origin });\n appLogger.flushSync();\n});\n\nconst closeApplicationLog = (exitCode: string | number) =>\n closeLoggerBeforeTermination(() => appLogger.close(), exitCode);\n\nlet shutdownOnSignal: (signal: NodeJS.Signals) => void = (signal) => {\n appLogger.info(\"cli.shutdown\", { signal, phase: \"startup\" });\n appLogger.flushSync();\n process.exit(0);\n};\nconst dispatchSignal = (signal: NodeJS.Signals) => shutdownOnSignal(signal);\nprocess.once(\"SIGINT\", dispatchSignal);\nprocess.once(\"SIGTERM\", dispatchSignal);\nprocess.once(\"SIGHUP\", dispatchSignal);\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 \"public-url\": {\n type: \"string\",\n description: \"Public HTTPS origin served by the trusted reverse proxy\",\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 local calendar 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 on or after this date, YYYY-MM-DD (overrides --days)\",\n },\n to: {\n type: \"string\",\n description: \"Sessions active on or 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 let publicOrigin: string | undefined;\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 publicOrigin = resolvePublicOrigin(args[\"public-url\"] as string | undefined, transport);\n } catch (error) {\n console.error(error instanceof Error ? error.message : String(error));\n process.exit(1);\n }\n\n if (resolveRemoteAccessPolicy(hostname, transport).remoteAccessRequired && !remoteAccess) {\n console.error(\n `Refusing to expose CodeSesh on ${hostname} without explicit remote access. 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 public_url: publicOrigin,\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/runtime/discovery\");\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 await closeApplicationLog(1);\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 await pricingRefresh.ready();\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 await pricingRefresh.cancel();\n const scanFailureDiagnostics = formatScanFailureDiagnostics(result);\n if (scanFailureDiagnostics.length > 0) {\n for (const diagnostic of scanFailureDiagnostics) console.error(diagnostic);\n process.exitCode = 1;\n } else {\n for (const diagnostic of formatCacheFailureDiagnostics(result)) console.error(diagnostic);\n const output = buildSessionIndexOutput(result, {\n from: listDefaultFrom,\n to: listDefaultTo,\n });\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 }\n // Worker threads and the SQLite connections hold the event loop open;\n // without this the one-shot process prints its output and never exits.\n await store.shutdown();\n await closeApplicationLog(process.exitCode ?? 0);\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 publicUrl: publicOrigin,\n });\n } catch (error) {\n console.error(getServerStartupErrorMessage(error, port));\n await closeApplicationLog(1);\n process.exit(1);\n }\n\n const { url } = app;\n if (!jsonOnly) {\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 await closeApplicationLog(0);\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 shutdownOnSignal = (signal: NodeJS.Signals) => {\n shutdown(signal).catch(async (error) => {\n appLogger.error(\"cli.shutdown_failed\", { signal, error });\n await closeApplicationLog(1);\n process.exit(1);\n });\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\nconst runCliCommand = main.run;\nif (!runCliCommand) throw new Error(\"CLI command is missing its runner\");\nmain.run = async (context) => {\n try {\n return await runCliCommand(context);\n } catch (error) {\n appLogger.error(\"cli.fatal\", { error });\n await closeApplicationLog(1);\n throw error;\n }\n};\n\nif (process.argv.slice(2).includes(\"-v\")) {\n console.log(VERSION);\n process.exit(0);\n}\n\nrunMain(main);\n","const LOG_CLOSE_TIMEOUT_MS = 2_000;\nconst LOG_CLOSE_TIMEOUT_MESSAGE = \"[codesesh] Timed out closing application log; forcing exit\\n\";\n\nexport async function closeLoggerBeforeTermination(\n closeLogger: () => Promise<void>,\n exitCode: string | number,\n): Promise<void> {\n let watchdog: ReturnType<typeof setTimeout> | undefined;\n const timedOut = new Promise<false>((resolve) => {\n watchdog = setTimeout(() => resolve(false), LOG_CLOSE_TIMEOUT_MS);\n });\n\n try {\n const closed = await Promise.race([closeLogger().then(() => true as const), timedOut]);\n if (closed) return;\n try {\n process.stderr.write(LOG_CLOSE_TIMEOUT_MESSAGE);\n } finally {\n process.exit(exitCode);\n }\n } finally {\n if (watchdog) clearTimeout(watchdog);\n }\n}\n","import { Hono, type Context } from \"hono\";\nimport { matchedRoutes } from \"hono/route\";\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 { randomUUID } from \"node:crypto\";\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/scan-sources.js\";\nimport { createApiRoutes, type ApiRouteOptions } from \"./api/routes.js\";\nimport { appLogger } from \"./logging.js\";\nimport { ThreadSessionDetailLoader } from \"./session-detail-loader.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 ACCESS_TOKEN_QUERY_PARAM,\n accessTokenAuth,\n createAccessToken,\n requireProxyTls,\n resolvePublicOrigin,\n resolveRemoteAccessPolicy,\n resolveRemoteTransport,\n type RemoteTransport,\n} from \"./remote-access.js\";\nimport type { ScanEventSource } from \"./scan-source.js\";\nimport { CODESESH_OPERATION_ID_HEADER, CODESESH_REQUEST_ID_HEADER } from \"@codesesh/core/contract\";\n\nconst MAX_API_REQUEST_BYTES = 1024 * 1024;\nconst SERVER_CLOSE_GRACE_MS = 1_000;\nconst OPERATION_ID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\nconst OBSERVABLE_QUERY_KEYS = new Set([\n \"agent\",\n \"costMax\",\n \"costMin\",\n \"cursor\",\n \"cwd\",\n \"days\",\n \"fileActivity\",\n \"from\",\n \"kind\",\n \"limit\",\n \"messageCursor\",\n \"path\",\n \"project\",\n \"projectKey\",\n \"projectKind\",\n \"q\",\n \"sessionId\",\n \"tag\",\n \"to\",\n \"tool\",\n]);\n\nexport interface CreateServerOptions {\n defaultSessionFrom?: number;\n defaultSessionTo?: number;\n defaultSessionDays?: number;\n portFallbackAttempts?: number;\n hostname?: string;\n remoteAccess?: boolean;\n accessToken?: string;\n publicUrl?: 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\nfunction optionalOperationId(value: string | undefined): string | undefined {\n return value && OPERATION_ID_PATTERN.test(value) ? value : undefined;\n}\n\nfunction errorStatus(error: unknown): number {\n try {\n if (typeof error !== \"object\" || error === null) return 500;\n const status = Reflect.get(error, \"status\");\n if (typeof status === \"number\" && status >= 400 && status <= 599) return status;\n } catch {}\n return 500;\n}\n\nfunction matchedRoute(context: Context): string {\n try {\n return (\n matchedRoutes(context)\n .map((route) => route.path)\n .filter((path) => !path.includes(\"*\"))\n .at(-1) ?? \"<unmatched>\"\n );\n } catch {\n return \"<unmatched>\";\n }\n}\n\nfunction queryKeys(url: string): string[] {\n try {\n return [...new Set(new URL(url).searchParams.keys())]\n .filter((key) => OBSERVABLE_QUERY_KEYS.has(key))\n .toSorted();\n } catch {\n return [];\n }\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; listenerUrl: 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 publicOrigin = resolvePublicOrigin(options.publicUrl, transport);\n const accessToken = options.accessToken || createAccessToken();\n const loopbackAuthorityEnabled = !accessPolicy.remoteAccessRequired;\n const shutdownController = new AbortController();\n const projectIdentityResolver =\n options.projectIdentityResolver ?? createProjectIdentityResolver();\n const sessionDetailLoader = new ThreadSessionDetailLoader();\n let actualPort: number | null = null;\n\n appLogger.info(\"server.access_policy\", {\n bind_category: accessPolicy.bindCategory,\n transport: transport.kind,\n authentication: \"token\",\n loopback_authority: loopbackAuthorityEnabled ? \"enabled\" : \"disabled\",\n });\n\n if (accessPolicy.remoteAccessRequired && !options.remoteAccess && !options.accessToken) {\n throw new Error(\n `Refusing to expose CodeSesh on ${hostname} without explicit remote access. 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 app.use(\"*\", async (c, next) => {\n const startedAt = performance.now();\n const requestId = randomUUID();\n const actualPath = c.req.path;\n const operationId = optionalOperationId(c.req.header(CODESESH_OPERATION_ID_HEADER));\n const context =\n actualPath === \"/api/events\"\n ? {}\n : { request_id: requestId, ...(operationId ? { operation_id: operationId } : {}) };\n c.header(CODESESH_REQUEST_ID_HEADER, requestId);\n\n return appLogger.restoreContext(context, async () => {\n let thrown: unknown;\n try {\n await next();\n } catch (error) {\n thrown = error;\n throw error;\n } finally {\n const requestError = thrown ?? c.error;\n appLogger.info(\"http.request\", {\n method: c.req.method,\n route: matchedRoute(c),\n query_keys: queryKeys(c.req.url),\n status: requestError == null ? c.res.status : errorStatus(requestError),\n duration_ms: Math.round(performance.now() - startedAt),\n ...(requestError == null ? {} : { error: requestError }),\n });\n }\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 route: \"<rejected>\",\n reason: decision.reason,\n authority_present: Boolean(decision.authority),\n });\n return c.json({ error: \"Loopback request authority rejected\" }, 403);\n }\n await next();\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 app.use(\"/api/*\", accessTokenAuth(accessToken));\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 loadSessionDetail: sessionDetailLoader.load,\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 // The backend stays HTTP behind a trusted proxy; its separately configured\n // public origin is used only for browser startup.\n const scheme = transport.kind === \"tls\" ? \"https\" : \"http\";\n const listenerUrl =\n accessPolicy.bindCategory === \"loopback\"\n ? `${scheme}://localhost:${actualPort}`\n : `${scheme}://${hostname}:${actualPort}`;\n const url = `${publicOrigin ?? listenerUrl}/?${ACCESS_TOKEN_QUERY_PARAM}=${encodeURIComponent(accessToken)}`;\n appLogger.info(\"server.listen\", {\n port: actualPort,\n requested_port: port,\n hostname,\n public_origin: publicOrigin,\n remote_access: accessPolicy.remoteAccessRequired,\n transport: transport.kind,\n });\n\n if (accessPolicy.remoteAccessRequired) {\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 listenerUrl,\n shutdown: async () => {\n appLogger.info(\"server.shutdown\", { port: actualPort });\n shutdownController.abort();\n try {\n await sessionDetailLoader.shutdown();\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 { randomUUID } from \"node:crypto\";\nimport {\n handleGetAgents,\n handleGetConfig,\n handleGetProjects,\n handleGetScanStatus,\n} from \"./catalog-handlers.js\";\nimport { handleGetDashboard } from \"./dashboard-handler.js\";\nimport { handleGetFileActivity, handleSearchSessions } from \"./search-handlers.js\";\nimport { handleGetSessions, handleGetSessionData } from \"./session-handlers.js\";\nimport { handlePostClientLog } from \"./client-log-handler.js\";\nimport type { ScanResultSource } from \"./scan-sources.js\";\nimport type { SessionListDefaults } from \"./query-params.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 { appLogger } from \"../logging.js\";\nimport type { SessionDetailLoader } from \"../session-detail-loader.js\";\nimport { SseEventBuffer } from \"./sse-event-buffer.js\";\n\nexport const MAX_ACTIVE_SSE_CONNECTIONS = 32;\n\ntype SseConnectionCloseReason =\n | \"client_cancelled\"\n | \"client_disconnected\"\n | \"client_too_slow\"\n | \"server_shutdown\"\n | \"setup_failed\";\n\nexport interface ApiRouteOptions {\n defaultSessionFrom?: number;\n defaultSessionTo?: number;\n defaultSessionDays?: number;\n shutdownSignal?: AbortSignal;\n projectIdentityResolver?: ProjectIdentityResolver;\n loadSessionDetail?: SessionDetailLoader;\n}\n\ninterface SseConnectionBudget {\n acquire(): (() => void) | null;\n activeCount(): number;\n}\n\nfunction createSseConnectionBudget(maxConnections: number): SseConnectionBudget {\n let activeConnections = 0;\n return {\n acquire() {\n if (activeConnections >= maxConnections) return null;\n activeConnections += 1;\n let released = false;\n return () => {\n if (released) return;\n released = true;\n activeConnections -= 1;\n };\n },\n activeCount() {\n return activeConnections;\n },\n };\n}\n\nfunction createSseResponse(\n eventSource: ScanEventSource,\n requestSignal: AbortSignal,\n shutdownSignal: AbortSignal | undefined,\n closeConnection: (reason: SseConnectionCloseReason) => void,\n): 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 disconnectStream = () => {};\n let shutdownStream = () => {};\n let heartbeat: ReturnType<typeof setInterval> | undefined;\n let buffer: SseEventBuffer | undefined;\n\n const cleanup = (reason: SseConnectionCloseReason) => {\n if (isClosed) return false;\n isClosed = true;\n buffer?.close();\n if (heartbeat) clearInterval(heartbeat);\n unsubscribeSessions();\n unsubscribeScanStatus();\n requestSignal.removeEventListener(\"abort\", disconnectStream);\n shutdownSignal?.removeEventListener(\"abort\", shutdownStream);\n closeConnection(reason);\n return true;\n };\n disconnectStream = () => {\n if (cleanup(\"client_disconnected\")) controller.close();\n };\n shutdownStream = () => {\n if (cleanup(\"server_shutdown\")) controller.close();\n };\n buffer = new SseEventBuffer(controller, () => {\n if (cleanup(\"client_too_slow\")) controller.error(new Error(\"SSE client fell behind\"));\n });\n drainStream = () => buffer.drain();\n\n try {\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(\"client_cancelled\");\n };\n\n if (shutdownSignal?.aborted) shutdownStream();\n else if (requestSignal.aborted) disconnectStream();\n else {\n requestSignal.addEventListener(\"abort\", disconnectStream, { once: true });\n shutdownSignal?.addEventListener(\"abort\", shutdownStream, { once: true });\n }\n } catch (error) {\n cleanup(\"setup_failed\");\n throw error;\n }\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 sseConnections = createSseConnectionBudget(MAX_ACTIVE_SSE_CONNECTIONS);\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, scanSource, listDefaults, options.projectIdentityResolver),\n );\n api.get(\"/sessions/:agent/:id\", (c) =>\n handleGetSessionData(c, scanSource, options.loadSessionDetail),\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 releaseConnection = sseConnections.acquire();\n if (!releaseConnection) {\n appLogger.warn(\"api.sse.connection_limit_reached\", {\n active_connections: sseConnections.activeCount(),\n connection_limit: MAX_ACTIVE_SSE_CONNECTIONS,\n });\n c.header(\"Retry-After\", \"1\");\n return c.json({ error: \"Too many active event streams\" }, 429);\n }\n const connectionId = randomUUID();\n const connectedAt = performance.now();\n let isClosed = false;\n appLogger.info(\"api.sse.connection.opened\", {\n connection_id: connectionId,\n active_connections: sseConnections.activeCount(),\n connection_limit: MAX_ACTIVE_SSE_CONNECTIONS,\n });\n const closeConnection = (reason: SseConnectionCloseReason) => {\n if (isClosed) return;\n isClosed = true;\n releaseConnection();\n appLogger.info(\"api.sse.connection.closed\", {\n connection_id: connectionId,\n close_reason: reason,\n duration_ms: Math.max(0, Math.round(performance.now() - connectedAt)),\n active_connections: sseConnections.activeCount(),\n });\n };\n try {\n return createSseResponse(\n eventSource,\n c.req.raw.signal,\n options.shutdownSignal,\n closeConnection,\n );\n } catch (error) {\n closeConnection(\"setup_failed\");\n throw error;\n }\n });\n }\n\n return api;\n}\n","import { Worker } from \"node:worker_threads\";\nimport {\n normalizeProjectDirectory,\n type ProjectIdentityProjection,\n} from \"@codesesh/core/runtime/projects\";\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;\nexport const PROJECT_IDENTITY_RESOLVER_MAX_QUEUED_REQUESTS = 8;\nexport const PROJECT_IDENTITY_RESOLVER_TIMEOUT_MS = 2_000;\n\nconst SHUTDOWN_ERROR_MESSAGE = \"Project identity resolver shut down\";\n\nexport interface ProjectIdentityResolver {\n resolve(cwd: string, signal?: AbortSignal): Promise<ProjectIdentityProjection>;\n shutdown(): Promise<void>;\n}\n\nexport interface ProjectIdentityResolverOptions {\n maxWorkers?: number;\n maxQueuedRequests?: number;\n timeoutMs?: number;\n}\n\nexport class ProjectIdentityQueueFullError extends Error {\n constructor() {\n super(\"Project identity resolver queue is full\");\n this.name = \"ProjectIdentityQueueFullError\";\n }\n}\n\nexport class ProjectIdentityTimeoutError extends Error {\n constructor() {\n super(\"Project identity resolution timed out\");\n this.name = \"ProjectIdentityTimeoutError\";\n }\n}\n\nexport class ProjectIdentityRequestAbortedError extends Error {\n constructor() {\n super(\"Project identity resolution was aborted\");\n this.name = \"ProjectIdentityRequestAbortedError\";\n }\n}\n\ninterface RequestSubscriber {\n resolve: (projection: ProjectIdentityProjection) => void;\n reject: (error: Error) => void;\n signal?: AbortSignal;\n abortHandler?: () => void;\n}\n\ninterface PendingRequest {\n requestId: number;\n cwd: string;\n subscribers: Set<RequestSubscriber>;\n timeout: ReturnType<typeof setTimeout> | null;\n}\n\ninterface WorkerSlot {\n worker: Worker;\n pending: PendingRequest | null;\n closed: boolean;\n retirement: Promise<void> | null;\n}\n\nfunction toError(error: unknown): Error {\n return error instanceof Error ? error : new Error(String(error));\n}\n\nfunction requireSafeInteger(value: number, minimum: number, name: string): number {\n if (!Number.isSafeInteger(value) || value < minimum) {\n throw new RangeError(`${name} must be a safe integer greater than or equal to ${minimum}`);\n }\n return value;\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 readonly requestsByDirectory = new Map<string, PendingRequest>();\n private readonly maxWorkers: number;\n private readonly maxOutstandingRequests: number;\n private readonly timeoutMs: number;\n private nextRequestId = 1;\n private isShuttingDown = false;\n\n constructor(\n private readonly workerUrl: URL,\n options: ProjectIdentityResolverOptions = {},\n ) {\n this.maxWorkers = requireSafeInteger(\n options.maxWorkers ?? PROJECT_IDENTITY_RESOLVER_MAX_WORKERS,\n 1,\n \"maxWorkers\",\n );\n const maxQueuedRequests = requireSafeInteger(\n options.maxQueuedRequests ?? PROJECT_IDENTITY_RESOLVER_MAX_QUEUED_REQUESTS,\n 0,\n \"maxQueuedRequests\",\n );\n this.timeoutMs = requireSafeInteger(\n options.timeoutMs ?? PROJECT_IDENTITY_RESOLVER_TIMEOUT_MS,\n 1,\n \"timeoutMs\",\n );\n this.maxOutstandingRequests = requireSafeInteger(\n this.maxWorkers + maxQueuedRequests,\n this.maxWorkers,\n \"request capacity\",\n );\n }\n\n resolve(cwd: string, signal?: AbortSignal): Promise<ProjectIdentityProjection> {\n if (this.isShuttingDown) return Promise.reject(new Error(SHUTDOWN_ERROR_MESSAGE));\n if (signal?.aborted) return Promise.reject(new ProjectIdentityRequestAbortedError());\n\n const normalizedCwd = normalizeProjectDirectory(cwd);\n let request = this.requestsByDirectory.get(normalizedCwd);\n if (!request) {\n if (this.requestsByDirectory.size >= this.maxOutstandingRequests) {\n appLogger.warn(\"project_identity.queue.full\", {\n active_workers: this.activeWorkerCount(),\n queued_requests: this.queue.length,\n request_capacity: this.maxOutstandingRequests,\n });\n return Promise.reject(new ProjectIdentityQueueFullError());\n }\n request = {\n requestId: this.nextRequestId++,\n cwd: normalizedCwd,\n subscribers: new Set(),\n timeout: null,\n };\n this.requestsByDirectory.set(normalizedCwd, request);\n this.queue.push(request);\n }\n\n const resolution = this.subscribe(request, signal);\n this.pump();\n return resolution;\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 while (this.queue.length > 0) this.rejectRequest(this.queue[0]!, error);\n\n const retirements = [...this.workers].map((slot) => this.retireWorker(slot, error));\n await Promise.allSettled(retirements);\n this.workers.clear();\n }\n\n private subscribe(\n request: PendingRequest,\n signal?: AbortSignal,\n ): Promise<ProjectIdentityProjection> {\n return new Promise((resolve, reject) => {\n const subscriber: RequestSubscriber = { resolve, reject, signal };\n request.subscribers.add(subscriber);\n if (!signal) return;\n\n subscriber.abortHandler = () => this.abortSubscriber(request, subscriber);\n signal.addEventListener(\"abort\", subscriber.abortHandler, { once: true });\n });\n }\n\n private abortSubscriber(request: PendingRequest, subscriber: RequestSubscriber): void {\n if (!request.subscribers.delete(subscriber)) return;\n this.removeAbortHandler(subscriber);\n subscriber.reject(new ProjectIdentityRequestAbortedError());\n if (request.subscribers.size > 0) return;\n\n const slot = this.workerForRequest(request);\n if (slot) slot.pending = null;\n this.releaseRequest(request);\n if (slot) void this.retireWorker(slot);\n else this.pump();\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 request.timeout = setTimeout(() => {\n if (slot.pending !== request || slot.closed) return;\n appLogger.warn(\"project_identity.request.timeout\", {\n request_id: request.requestId,\n timeout_ms: this.timeoutMs,\n });\n void this.retireWorker(slot, new ProjectIdentityTimeoutError());\n }, this.timeoutMs);\n request.timeout.unref();\n try {\n slot.worker.postMessage({\n type: \"resolve\",\n requestId: request.requestId,\n cwd: request.cwd,\n } satisfies ProjectIdentityWorkerRequest);\n } catch (error) {\n void this.retireWorker(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 activeWorkerCount(): number {\n let count = 0;\n for (const slot of this.workers) {\n if (!slot.closed && slot.pending != null) count += 1;\n }\n return count;\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 = {\n worker,\n pending: null,\n closed: false,\n retirement: null,\n };\n this.workers.add(slot);\n worker.on(\"message\", (message: unknown) => {\n if (appLogger.consumeWorkerMessage(message)) return;\n this.handleWorkerMessage(slot, message);\n });\n worker.on(\"error\", (error) => {\n void this.retireWorker(slot, toError(error));\n });\n worker.on(\"exit\", (code) => {\n if (!slot.closed) {\n this.closeExitedWorker(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\") this.resolveRequest(request, message.projection);\n else this.rejectRequest(request, new Error(message.error));\n this.pump();\n }\n\n private closeExitedWorker(slot: WorkerSlot, error: Error): void {\n slot.closed = true;\n this.workers.delete(slot);\n const request = slot.pending;\n slot.pending = null;\n if (request) this.rejectRequest(request, error);\n if (!this.isShuttingDown) this.pump();\n }\n\n private retireWorker(slot: WorkerSlot, error?: Error): Promise<void> {\n if (slot.retirement) return slot.retirement;\n slot.closed = true;\n const request = slot.pending;\n slot.pending = null;\n if (request && error) this.rejectRequest(request, error);\n\n const retirement = (async () => {\n try {\n await slot.worker.terminate();\n } catch (terminationError) {\n appLogger.warn(\"project_identity.worker.termination_failed\", {\n error: toError(terminationError).message,\n });\n } finally {\n this.workers.delete(slot);\n if (!this.isShuttingDown) this.pump();\n }\n })();\n slot.retirement = retirement;\n return retirement;\n }\n\n private workerForRequest(request: PendingRequest): WorkerSlot | null {\n for (const slot of this.workers) {\n if (slot.pending === request) return slot;\n }\n return null;\n }\n\n private resolveRequest(request: PendingRequest, projection: ProjectIdentityProjection): void {\n this.releaseRequest(request);\n for (const subscriber of request.subscribers) {\n this.removeAbortHandler(subscriber);\n subscriber.resolve(projection);\n }\n request.subscribers.clear();\n }\n\n private rejectRequest(request: PendingRequest, error: Error): void {\n this.releaseRequest(request);\n for (const subscriber of request.subscribers) {\n this.removeAbortHandler(subscriber);\n subscriber.reject(error);\n }\n request.subscribers.clear();\n }\n\n private releaseRequest(request: PendingRequest): void {\n if (request.timeout) clearTimeout(request.timeout);\n request.timeout = null;\n if (this.requestsByDirectory.get(request.cwd) === request) {\n this.requestsByDirectory.delete(request.cwd);\n }\n const queueIndex = this.queue.indexOf(request);\n if (queueIndex >= 0) this.queue.splice(queueIndex, 1);\n }\n\n private removeAbortHandler(subscriber: RequestSubscriber): void {\n if (subscriber.signal && subscriber.abortHandler) {\n subscriber.signal.removeEventListener(\"abort\", subscriber.abortHandler);\n }\n }\n\n private rejectQueued(error: Error): void {\n while (this.queue.length > 0) this.rejectRequest(this.queue[0]!, 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","/**\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/runtime/discovery\";\nimport {\n filterSessionTreeByActivityWindow,\n isSmartTag,\n type FileActivityKind,\n type SearchRequestOptions,\n} from \"@codesesh/core/runtime/discovery\";\nimport { isProjectIdentityKind, type ProjectIdentityRef } from \"@codesesh/core/runtime/projects\";\nimport type { TimeWindow } from \"../time-window-resolution.js\";\n\nexport type SessionListDefaults = TimeWindow;\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 PROJECT_PAGE_LIMIT_POLICY: LimitPolicy = { defaultValue: 100, maxValue: 250 };\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 | {\n kind: \"valid\";\n from: number | undefined;\n to: number | undefined;\n hasExplicitFrom: boolean;\n }\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 {\n kind: \"valid\",\n from: from.value,\n to: to.value,\n hasExplicitFrom: from.kind === \"valid\",\n };\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\nexport function 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.map((value) => value.toLowerCase()).filter(isSmartTag);\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<T extends SessionHead>(\n sessions: T[],\n from: number | undefined,\n to: number | undefined,\n): T[] {\n return filterSessionTreeByActivityWindow(sessions, from, to);\n}\n","import { getAgentInfoMap } from \"@codesesh/core/runtime/agents\";\nimport type { IdentifiedSessionHead } from \"@codesesh/core/runtime/discovery\";\nimport {\n createProjectScopeMatcherFromIdentity,\n normalizeProjectDirectory,\n PROJECT_IDENTITY_RESOLVER_REVISION,\n type ProjectScopeMatcher,\n} from \"@codesesh/core/runtime/projects\";\nimport type { Context } from \"hono\";\nimport { appLogger } from \"../logging.js\";\nimport {\n ProjectIdentityQueueFullError,\n ProjectIdentityRequestAbortedError,\n type ProjectIdentityResolver,\n} from \"../project-identity-resolver.js\";\nimport { parseDateWindow, searchParams, type SessionListDefaults } from \"./query-params.js\";\n\nexport const KNOWN_AGENT_NAMES = getAgentInfoMap({}).map((agent) => agent.name);\nexport const KNOWN_AGENT_NAME_SET = new Set(KNOWN_AGENT_NAMES);\n\nexport async function resolveProjectScope(\n cwd: string,\n sessions: readonly IdentifiedSessionHead[],\n resolver: ProjectIdentityResolver | undefined,\n signal: AbortSignal,\n): Promise<ProjectScopeMatcher> {\n const normalizedCwd = normalizeProjectDirectory(cwd);\n const matchingSession = sessions.find(\n (session) =>\n normalizeProjectDirectory(session.directory) === normalizedCwd &&\n session.project_identity_resolver_revision === PROJECT_IDENTITY_RESOLVER_REVISION &&\n Boolean(session.project_identity_input_signature),\n );\n if (matchingSession) {\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, signal);\n return createProjectScopeMatcherFromIdentity(cwd, projection.identity);\n}\n\nexport function projectScopeResolutionFailureResponse(\n c: Context,\n endpoint: string,\n error: unknown,\n) {\n if (error instanceof ProjectIdentityRequestAbortedError) throw error;\n appLogger.warn(\"api.project_scope.unavailable\", {\n endpoint,\n error: error instanceof Error ? error.message : String(error),\n });\n if (error instanceof ProjectIdentityQueueFullError) {\n return c.json({ error: \"Project scope busy; retry later\" }, 429);\n }\n return c.json({ error: \"Project scope unavailable\" }, 503);\n}\n\nexport function 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\nexport function parseDateWindowRequest(\n c: Context,\n endpoint: string,\n defaults: SessionListDefaults,\n) {\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","import { createHash, randomUUID } from \"node:crypto\";\n\ninterface CursorPayload {\n version: 1;\n snapshot: string;\n offset: number;\n}\n\ninterface PaginationRequest {\n cursor?: string;\n limit: number;\n query: URLSearchParams;\n}\n\ninterface PaginationSnapshot<T, View> {\n items: readonly T[];\n view: View;\n}\n\ninterface RetainedSnapshot<T, View> extends PaginationSnapshot<T, View> {\n query: string;\n expiresAt: number;\n}\n\ntype PaginationResult<T, View> =\n | { kind: \"page\"; items: T[]; view: View; nextCursor?: string }\n | { kind: \"invalid_cursor\" }\n | { kind: \"stale_snapshot\" };\n\nconst SNAPSHOT_TTL_MS = 60_000;\nconst SNAPSHOT_LIMIT = 32;\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 !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\nexport function createSnapshotPaginator<T, View>() {\n const snapshotsBySource = new WeakMap<object, Map<string, RetainedSnapshot<T, View>>>();\n\n return function paginateSnapshot(\n source: object,\n request: PaginationRequest,\n load: () => PaginationSnapshot<T, View>,\n ): PaginationResult<T, View> {\n const snapshots = snapshotsBySource.get(source) ?? new Map<string, RetainedSnapshot<T, View>>();\n const now = Date.now();\n for (const [id, snapshot] of snapshots) {\n if (snapshot.expiresAt <= now) snapshots.delete(id);\n }\n const query = queryFingerprint(request.query);\n let snapshot: RetainedSnapshot<T, View>;\n let snapshotId: string;\n let offset = 0;\n\n if (request.cursor) {\n const cursor = decodeCursor(request.cursor);\n if (!cursor) return { kind: \"invalid_cursor\" };\n const retained = snapshots.get(cursor.snapshot);\n if (!retained) return { kind: \"stale_snapshot\" };\n if (retained.query !== query || cursor.offset >= retained.items.length) {\n return { kind: \"invalid_cursor\" };\n }\n snapshot = retained;\n snapshotId = cursor.snapshot;\n offset = cursor.offset;\n } else {\n const loaded = load();\n snapshot = { ...loaded, items: [...loaded.items], query, expiresAt: now + SNAPSHOT_TTL_MS };\n snapshotId = randomUUID();\n }\n\n const end = Math.min(offset + request.limit, snapshot.items.length);\n const nextCursor =\n end < snapshot.items.length\n ? encodeCursor({ version: 1, snapshot: snapshotId, offset: end })\n : undefined;\n if (!request.cursor && nextCursor) {\n if (snapshots.size >= SNAPSHOT_LIMIT) snapshots.delete(snapshots.keys().next().value!);\n snapshots.set(snapshotId, snapshot);\n snapshotsBySource.set(source, snapshots);\n }\n return {\n kind: \"page\",\n items: snapshot.items.slice(offset, end),\n view: snapshot.view,\n ...(nextCursor ? { nextCursor } : {}),\n };\n };\n}\n","import {\n listFileActivity,\n listDashboardCostFacts,\n type SessionHead,\n} from \"@codesesh/core/runtime/discovery\";\nimport {\n type DashboardCostFacts,\n type DashboardData,\n type DashboardScope,\n} from \"@codesesh/core/runtime/analytics\";\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 getSnapshotCostFacts(\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 // Effective message timestamps are positive; the UI uses epoch zero for All time.\n const costFrom = from === 0 ? undefined : from;\n const build = () => listDashboardCostFacts({ from: costFrom, to });\n if (analyticsRevision === null) return build();\n\n return getSnapshotAggregation(\n source,\n sessions,\n [\"cost-facts\", costFrom, 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 {\n agent: scope.agent,\n projectKind: scope.projectKind,\n projectKey: scope.projectKey,\n from,\n to,\n limit: 12,\n },\n source.queryScope,\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 { AppConfig, ApiProjectGroup, ApiProjectPage } from \"@codesesh/core/contract\";\nimport { getAgentInfoMap } from \"@codesesh/core/runtime/agents\";\nimport {\n getAnalyticsRevision,\n listCachedProjectGroups,\n listDashboardCostFacts,\n} from \"@codesesh/core/runtime/discovery\";\nimport { attachProjectMetricsFromTree, summarizeProjects } from \"@codesesh/core/runtime/projects\";\nimport type { Context } from \"hono\";\nimport { parseDateWindowRequest, reportInvalidQueryParameter } from \"./handler-support.js\";\nimport {\n filterSessionsByActivityWindow,\n parseLimit,\n parseProjectIdentityFilter,\n PROJECT_PAGE_LIMIT_POLICY,\n searchParams,\n type SessionListDefaults,\n} from \"./query-params.js\";\nimport type { ScanResultSource, ScanStatusSource } from \"./scan-sources.js\";\nimport { createSnapshotPaginator } from \"./snapshot-pagination.js\";\nimport {\n getSnapshotAggregation,\n getSnapshotCostFacts,\n getSnapshotSessionTree,\n} from \"./snapshot-aggregation.js\";\n\nconst paginateProjects = createSnapshotPaginator<ApiProjectGroup, ApiProjectPage[\"summary\"]>();\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 params = searchParams(c);\n const limit = parseLimit(params.get(\"limit\"), PROJECT_PAGE_LIMIT_POLICY);\n if (limit.kind === \"invalid\") {\n reportInvalidQueryParameter(\"projects\", \"limit\", \"rejected\");\n return c.json({ error: 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, \"projects\", defaults);\n if (window.kind === \"rejected\") return window.response;\n const { from, to } = window;\n const loadSnapshot = () => {\n const analyticsRevision = getAnalyticsRevision();\n const catalog = getSnapshotAggregation(\n scanSource,\n scanResult.sessions,\n [\"projects\", from, to, analyticsRevision],\n () => {\n const tree = getSnapshotSessionTree(scanSource, scanResult.sessions);\n const costFacts =\n (from == null || from === 0) && to == null\n ? getSnapshotCostFacts(scanSource, scanResult.sessions, from, to, to, analyticsRevision)\n : listDashboardCostFacts({ from, to, includeModelCosts: false });\n const 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 return { projects, summary: summarizeProjects(projects) };\n },\n );\n const projects = projectIdentity\n ? catalog.projects.filter(\n (project) =>\n project.identityKind === projectIdentity.kind &&\n project.identityKey === projectIdentity.key,\n )\n : catalog.projects;\n return {\n items: projects,\n view: projectIdentity ? summarizeProjects(projects) : catalog.summary,\n };\n };\n const page = paginateProjects(\n scanSource,\n {\n cursor: params.get(\"cursor\") ?? undefined,\n limit: limit.value,\n query: params,\n },\n loadSnapshot,\n );\n if (page.kind === \"invalid_cursor\") {\n reportInvalidQueryParameter(\"projects\", \"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: \"project snapshot expired; restart pagination\" }, 409);\n }\n return c.json({\n projects: page.items,\n summary: page.view,\n ...(page.nextCursor ? { nextCursor: page.nextCursor } : {}),\n });\n}\n","import {\n addCalendarDays,\n countCalendarDays,\n parseCalendarDayBoundary,\n startOfCalendarDay,\n} from \"@codesesh/core/contract\";\n\nconst 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 RawCliTimeWindow {\n from?: string;\n to?: string;\n days?: string;\n}\n\ninterface CliTimeWindowRequest extends RawCliTimeWindow {\n mode: \"cli\";\n now?: number;\n}\n\ninterface DashboardTimeWindowRequest {\n mode: \"dashboard\";\n window: {\n from?: number;\n to?: number;\n hasExplicitFrom: boolean;\n };\n days?: string;\n defaultDays?: number;\n now?: number;\n}\n\ninterface DashboardTimeWindow extends TimeWindow {\n to: number;\n days: 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, \"start\");\n const to = parseRequiredDate(request.to, \"end\");\n if (from != null && to != null && from > to) {\n throw new Error(\"Invalid time window: from must not be after to\");\n }\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 calendarFrom = addCalendarDays(startOfCalendarDay(to ?? now), -(days - 1));\n return Number.isFinite(calendarFrom) ? { from: calendarFrom, to, days } : { to };\n}\n\nfunction resolveDashboardWindow(request: DashboardTimeWindowRequest): DashboardTimeWindow {\n const now = request.now ?? Date.now();\n const to = request.window.to ?? now;\n const hasQueryDays = Boolean(request.days?.trim());\n const parsedDays = hasQueryDays ? parseDays(request.days) : undefined;\n\n if (request.window.hasExplicitFrom && request.window.from != null) {\n return { from: request.window.from, to, days: countCalendarDays(request.window.from, to) };\n }\n\n const days = parsedDays ?? request.defaultDays;\n if (days === 0) {\n return { to, days: 0 };\n }\n\n if (days != null && days > 0) {\n return {\n from: addCalendarDays(startOfCalendarDay(to), -(days - 1)),\n to,\n days,\n };\n }\n\n if (request.window.from != null) {\n return { from: request.window.from, to, days: countCalendarDays(request.window.from, to) };\n }\n\n return {\n from: addCalendarDays(startOfCalendarDay(to), -(DEFAULT_DASHBOARD_DAYS - 1)),\n to,\n days: DEFAULT_DASHBOARD_DAYS,\n };\n}\n\nfunction parseRequiredDate(\n value: string | undefined,\n boundary: \"start\" | \"end\",\n): number | undefined {\n if (!value) return undefined;\n const calendarBoundary = parseCalendarDayBoundary(value, boundary);\n if (calendarBoundary === null) throw new Error(`Invalid date: ${value}`);\n if (calendarBoundary != null) return calendarBoundary;\n const timestamp = new Date(value).getTime();\n if (Number.isNaN(timestamp)) throw new Error(`Invalid date: ${value}`);\n return timestamp;\n}\n\nfunction parseDays(value: string | undefined): number | undefined {\n if (value == null) return undefined;\n const normalized = value.trim();\n if (!/^-?\\d+$/.test(normalized)) return undefined;\n const days = Number(normalized);\n return Number.isSafeInteger(days) && Number.isSafeInteger(days * DAY_MS) ? days : undefined;\n}\n","/**\n * Deep session search: single owner for search-query interpretation\n * (qualifier parsing/merging), source selection between the live LiveSnapshot\n * snapshot (\"recent\" path) and the SQLite search index (FTS / file-activity\n * paths), and cross-source result merging.\n */\nimport type { SessionHead } from \"../types/index.js\";\nimport {\n buildSessionTree,\n getSessionReferenceKey,\n type SearchResult,\n type SessionTree,\n} from \"../contract/index.js\";\nimport {\n filterIndexedSessionReferences,\n mergeSearchQueryOptions,\n searchSessions,\n sessionMatchesSearchCost,\n type ParsedSearchQuery,\n type SearchOptions,\n} from \"../discovery/cache/search.js\";\nimport { searchFileActivitySessions } from \"../discovery/cache/file-activity.js\";\nimport { matchesProjectScope, type ProjectScopeMatcher } from \"../projects/scope.js\";\nimport { matchesProjectIdentity } from \"../projects/identity.js\";\nimport { getSessionActivityTime } from \"../analytics/dashboard.js\";\nimport { matchesSessionQueryScope, type SessionQueryScope } from \"../discovery/session-scope.js\";\n\nexport interface SessionSearchSnapshot {\n /** Globally sorted by activity descending; ties preserve the canonical live-index order. */\n sessions: SessionHead[];\n /** Each shard follows the same activity ordering as `sessions`. */\n byAgent: Record<string, SessionHead[]>;\n}\n\nexport interface SessionSearchContext {\n sessionTree?: SessionTree;\n queryScope?: SessionQueryScope;\n}\n\nexport interface SessionSearchFilterContext extends SessionSearchContext {\n sessionSnapshot?: SessionHead[];\n}\n\nexport function executeSessionSearch(\n query: string,\n options: SearchOptions,\n snapshot: SessionSearchSnapshot,\n context: SessionSearchContext = {},\n): SearchResult[] {\n const merged = mergeSearchQueryOptions(query, options);\n\n if (!needsIndexedSearch(merged.text, merged.options)) {\n return searchRecentSessions(snapshot, merged.options, context);\n }\n\n return searchIndexedSessions(\n query,\n merged.text,\n merged.parsed,\n merged.options,\n context.queryScope,\n );\n}\n\n// Qualifiers alone (tag:/cost:/agent:/project:) do not force the indexed\n// path -- only text, file, fileKind, or tool do. A qualifier-only query is\n// treated identically to an empty query for source selection.\nfunction needsIndexedSearch(textQuery: string, options: SearchOptions): boolean {\n return Boolean(textQuery || options.file || options.fileKind || options.tools?.length);\n}\n\nfunction matchesRecentSearchFilters(\n session: SessionHead,\n options: SearchOptions,\n projectScope: ProjectScopeMatcher | null,\n inclusiveCost: number,\n): boolean {\n if (options.projectKind || options.projectKey) {\n if (\n !options.projectKind ||\n !options.projectKey ||\n !matchesProjectIdentity(session.project_identity, {\n kind: options.projectKind,\n key: options.projectKey,\n })\n ) {\n return false;\n }\n }\n if (projectScope && !matchesProjectScope(session, projectScope)) return false;\n if (options.project) {\n const projectNeedle = options.project.toLowerCase();\n const projectText = [\n session.project_identity?.key,\n session.project_identity?.displayName,\n session.directory,\n ]\n .filter(Boolean)\n .join(\"\\n\")\n .toLowerCase();\n if (!projectText.includes(projectNeedle)) return false;\n }\n if (options.tags?.length && !options.tags.every((tag) => session.smart_tags?.includes(tag))) {\n return false;\n }\n if (!sessionMatchesSearchCost(session, options, inclusiveCost)) return false;\n return true;\n}\n\n// Evaluates filters answerable from SessionHead. File and tool predicates\n// require the indexed batch seam in filterSessionSearchCandidates.\nexport function matchesSessionSearchFilters(\n agentName: string,\n session: SessionHead,\n options: SearchOptions,\n projectScope: ProjectScopeMatcher | null = null,\n inclusiveCost = session.stats.total_cost,\n): boolean {\n if (options.agent && agentName !== options.agent) return false;\n const activity = getSessionActivityTime(session);\n if (options.from != null && activity < options.from) return false;\n if (options.to != null && activity > options.to) return false;\n return matchesRecentSearchFilters(session, options, projectScope, inclusiveCost);\n}\n\nexport function filterSessionSearchCandidates(\n candidates: SearchResult[],\n options: SearchOptions,\n context: SessionSearchFilterContext = {},\n): SearchResult[] {\n const projectScope = options.projectScope ?? null;\n const sessionSnapshot =\n context.sessionSnapshot ?? candidates.map((candidate) => candidate.session);\n const inclusiveCosts = buildInclusiveCostLookup(sessionSnapshot, options, context.sessionTree);\n const headMatches = candidates.filter(\n (candidate) =>\n matchesSessionQueryScope(candidate.session, context.queryScope) &&\n matchesSessionSearchFilters(\n candidate.reference.agentName,\n candidate.session,\n options,\n projectScope,\n inclusiveCostFor(candidate.reference.agentName, candidate.session, inclusiveCosts),\n ),\n );\n if (!options.file && !options.fileKind && !options.tools?.length) return headMatches;\n\n const indexedMatches = filterIndexedSessionReferences(\n headMatches.map((candidate) => ({\n agentName: candidate.reference.agentName,\n sessionId: candidate.reference.sessionId,\n })),\n {\n file: options.file,\n fileKind: options.fileKind,\n tools: options.tools,\n },\n );\n return headMatches.filter((candidate) =>\n indexedMatches.has(getSessionReferenceKey(candidate.reference)),\n );\n}\n\nfunction searchRecentSessions(\n snapshot: SessionSearchSnapshot,\n options: SearchOptions,\n context: SessionSearchContext,\n): SearchResult[] {\n const limit = Math.max(0, Math.trunc(options.limit ?? 50));\n if (limit === 0) return [];\n\n const projectScope = options.projectScope ?? null;\n const inclusiveCosts = buildInclusiveCostLookup(snapshot.sessions, options, context.sessionTree);\n const sessions = options.agent ? (snapshot.byAgent[options.agent] ?? []) : snapshot.sessions;\n const results: SearchResult[] = [];\n\n for (const session of sessions) {\n const agentName = options.agent ?? session.reference.agentName;\n if (\n !matchesSessionQueryScope(session, context.queryScope) ||\n !matchesSessionSearchFilters(\n agentName,\n session,\n options,\n projectScope,\n inclusiveCostFor(agentName, session, inclusiveCosts),\n )\n ) {\n continue;\n }\n results.push({\n reference: session.reference,\n session,\n snippet: `Recent session · ${session.directory}`,\n snippetHighlights: [],\n matchType: \"recent\",\n });\n if (results.length >= limit) break;\n }\n\n return results;\n}\n\nfunction buildInclusiveCostLookup(\n sessions: SessionHead[],\n options: SearchOptions,\n sessionTree?: SessionTree,\n): ReturnType<typeof buildSessionTree>[\"byRouteKey\"] | null {\n if (options.costMin == null && options.costMax == null) return null;\n return (sessionTree ?? buildSessionTree(sessions)).byRouteKey;\n}\n\nfunction inclusiveCostFor(\n agentName: string,\n session: SessionHead,\n lookup: ReturnType<typeof buildSessionTree>[\"byRouteKey\"] | null,\n): number {\n return (\n lookup?.get(getSessionReferenceKey({ agentName, sessionId: session.reference.sessionId }))\n ?.inclusiveStats.cost ?? session.stats.total_cost\n );\n}\n\n// `options.file` already carries the qualifier's `file:`/`path:` value once\n// merged (options.file ?? filters.file), so the middle branch only matters\n// when options.file was merged from something other than this parse. When\n// the query has no qualifiers at all, a bare text search is also attempted\n// as a file-path search (usually a no-op match, but it is why plain text\n// queries still touch the file-activity path).\nfunction deriveFileQuery(query: string, parsed: ParsedSearchQuery, options: SearchOptions): string {\n return (\n options.file ??\n (!parsed.text ? parsed.filters.file : undefined) ??\n (!parsed.hasQualifiers && query ? parsed.text || query : \"\")\n );\n}\n\nfunction mergeSearchResultSources(results: SearchResult[], limit: number): SearchResult[] {\n const seen = new Set<string>();\n const merged: SearchResult[] = [];\n\n for (const result of results) {\n const key = getSessionReferenceKey(result.reference);\n if (seen.has(key)) continue;\n seen.add(key);\n merged.push(result);\n if (merged.length >= limit) break;\n }\n\n return merged;\n}\n\nfunction canSkipSessionsSearch(fileQuery: string, textQuery: string): boolean {\n return Boolean(fileQuery && !textQuery);\n}\n\nfunction searchIndexedSessions(\n query: string,\n textQuery: string,\n parsed: ParsedSearchQuery,\n options: SearchOptions,\n queryScope?: SessionQueryScope,\n): SearchResult[] {\n const fileQuery = deriveFileQuery(query, parsed, options);\n const fileResults = fileQuery ? searchFileActivitySessions(fileQuery, options, queryScope) : [];\n const sessionResults = canSkipSessionsSearch(fileQuery, textQuery)\n ? []\n : searchSessions(query, options, queryScope);\n const textMatchReferences =\n textQuery && options.file\n ? new Set(sessionResults.map((result) => getSessionReferenceKey(result.reference)))\n : null;\n const matchingFileResults = textMatchReferences\n ? fileResults.filter((result) =>\n textMatchReferences.has(getSessionReferenceKey(result.reference)),\n )\n : fileResults;\n\n return mergeSearchResultSources([...matchingFileResults, ...sessionResults], options.limit ?? 50);\n}\n","import { homedir, platform } from \"node:os\";\nimport { join } from \"node:path\";\nimport {\n columnExists,\n getUserVersion,\n openDb,\n runSchemaMigrations,\n setUserVersion,\n tableExists,\n type DatabaseRow,\n type SQLiteDatabase,\n} from \"../utils/sqlite.js\";\n\nconst STATE_DB_FILENAME = \"state.db\";\nconst STATE_SCHEMA_VERSION = 3;\nconst MEMORY_STATE_STORE = \"memory\";\n\n// One-shot per-process ensureSchema guard, mirroring the cache side's\n// schemaEnsuredPath (discovery/cache/db.ts). Keyed by dbPath so tests can\n// switch state directories; exported so tests can reset it between runs.\nlet stateSchemaEnsuredPath: string | null = null;\n\nexport function getStateSchemaEnsuredPath(): string | null {\n return stateSchemaEnsuredPath;\n}\n\nexport function setStateSchemaEnsuredPath(path: string | null): void {\n stateSchemaEnsuredPath = path;\n}\n\nexport class StateStorageUnavailableError extends Error {\n constructor() {\n super(\"SQLite state database is unavailable\");\n this.name = \"StateStorageUnavailableError\";\n }\n}\n\nfunction getStateDir(): string {\n if (process.env.CODESESH_STATE_DIR) return process.env.CODESESH_STATE_DIR;\n\n const currentPlatform = platform();\n if (currentPlatform === \"darwin\") {\n return join(homedir(), \"Library\", \"Application Support\", \"codesesh\");\n }\n if (currentPlatform === \"win32\") {\n const appData = process.env.APPDATA ?? process.env.LOCALAPPDATA;\n return join(appData ?? join(homedir(), \"AppData\", \"Roaming\"), \"codesesh\");\n }\n return join(process.env.XDG_DATA_HOME ?? join(homedir(), \".local\", \"share\"), \"codesesh\");\n}\n\nfunction getStateDbPath(): string {\n return join(getStateDir(), STATE_DB_FILENAME);\n}\n\nexport function useMemoryStateStore(): boolean {\n return process.env.CODESESH_STATE_STORE === MEMORY_STATE_STORE;\n}\n\nfunction createBookmarksTable(db: SQLiteDatabase): void {\n db.exec(`\n CREATE TABLE IF NOT EXISTS bookmarks (\n agent_name TEXT NOT NULL,\n session_id TEXT NOT NULL,\n bookmarked_at INTEGER NOT NULL,\n PRIMARY KEY (agent_name, session_id)\n );\n `);\n}\n\nfunction migrateBookmarkFacts(db: SQLiteDatabase): void {\n db.exec(\"ALTER TABLE bookmarks RENAME TO bookmarks_with_snapshots\");\n createBookmarksTable(db);\n db.exec(`\n INSERT INTO bookmarks(agent_name, session_id, bookmarked_at)\n SELECT agent_name, session_id, bookmarked_at\n FROM bookmarks_with_snapshots;\n\n DROP TABLE bookmarks_with_snapshots;\n `);\n}\n\nfunction createSessionAliasesTable(db: SQLiteDatabase): void {\n db.exec(`\n CREATE TABLE IF NOT EXISTS session_aliases (\n agent_name TEXT NOT NULL,\n session_id TEXT NOT NULL,\n alias TEXT NOT NULL,\n updated_at INTEGER NOT NULL,\n PRIMARY KEY (agent_name, session_id)\n );\n `);\n}\n\nfunction createStateSchema(db: SQLiteDatabase): void {\n db.exec(`\n CREATE TABLE IF NOT EXISTS state_meta (\n key TEXT PRIMARY KEY,\n value TEXT NOT NULL\n );\n `);\n createBookmarksTable(db);\n createSessionAliasesTable(db);\n}\n\nfunction readLegacyStateVersion(db: SQLiteDatabase): number {\n if (\n !tableExists(db, \"state_meta\") ||\n !columnExists(db, \"state_meta\", \"key\") ||\n !columnExists(db, \"state_meta\", \"value\")\n ) {\n return 0;\n }\n\n const row = db.prepare(\"SELECT value FROM state_meta WHERE key = 'version'\").get() as\n | DatabaseRow\n | undefined;\n return Number(row?.value ?? 0);\n}\n\nfunction getCurrentStateSchemaVersion(db: SQLiteDatabase): number {\n const userVersion = getUserVersion(db);\n if (userVersion > 0) return userVersion;\n\n const legacyVersion = readLegacyStateVersion(db);\n if (legacyVersion > 0) return legacyVersion;\n\n return tableExists(db, \"bookmarks\") ? 1 : 0;\n}\n\nfunction hasAnyStateSchema(db: SQLiteDatabase): boolean {\n return tableExists(db, \"state_meta\") || tableExists(db, \"bookmarks\");\n}\n\nfunction setStateSchemaVersion(db: SQLiteDatabase): void {\n createStateSchema(db);\n setUserVersion(db, STATE_SCHEMA_VERSION);\n db.prepare(\n `\n INSERT INTO state_meta(key, value)\n VALUES ('version', ?)\n ON CONFLICT(key) DO UPDATE SET value = excluded.value\n `,\n ).run(String(STATE_SCHEMA_VERSION));\n}\n\nfunction ensureSchema(db: SQLiteDatabase, dbPath: string): void {\n const currentVersion = getCurrentStateSchemaVersion(db);\n if (currentVersion > STATE_SCHEMA_VERSION) return;\n if (currentVersion === 0 && !hasAnyStateSchema(db)) {\n setStateSchemaVersion(db);\n return;\n }\n\n runSchemaMigrations(db, {\n dbPath,\n currentVersion,\n targetVersion: STATE_SCHEMA_VERSION,\n backupLabel: \"state-migration\",\n backupTables: [\"bookmarks\", \"session_aliases\"],\n migrations: [\n { version: 1, migrate: createBookmarksTable },\n { version: 2, migrate: createSessionAliasesTable },\n { version: 3, destructive: true, migrate: migrateBookmarkFacts },\n ],\n });\n\n if (currentVersion < STATE_SCHEMA_VERSION) {\n setStateSchemaVersion(db);\n }\n}\n\nexport function withStateDb<T>(fn: (db: SQLiteDatabase) => T): T {\n const statePath = getStateDbPath();\n const db = openDb(statePath);\n if (!db) throw new StateStorageUnavailableError();\n\n try {\n if (getStateSchemaEnsuredPath() !== statePath) {\n ensureSchema(db, statePath);\n setStateSchemaEnsuredPath(statePath);\n }\n return fn(db);\n } finally {\n db.close();\n }\n}\n","import {\n normalizeSessionReference,\n type BookmarkRecord,\n type SessionReference,\n} from \"../contract/index.js\";\nimport { StateStorageUnavailableError, useMemoryStateStore, withStateDb } from \"./database.js\";\nimport type { DatabaseRow, SQLiteDatabase } from \"../utils/sqlite.js\";\n\nconst memoryBookmarks = new Map<string, BookmarkRecord>();\n\nexport { StateStorageUnavailableError as BookmarkStorageUnavailableError };\n\nexport type { BookmarkRecord };\n\ninterface BookmarkRow extends DatabaseRow {\n agent_name?: string;\n session_id?: string;\n bookmarked_at?: number;\n}\n\nfunction getBookmarkKey(reference: SessionReference): string {\n const normalized = normalizeSessionReference(reference);\n return JSON.stringify([normalized.agentName, normalized.sessionId]);\n}\n\nfunction compareBookmarks(left: BookmarkRecord, right: BookmarkRecord): number {\n if (left.bookmarkedAt !== right.bookmarkedAt) {\n return left.bookmarkedAt > right.bookmarkedAt ? -1 : 1;\n }\n return getBookmarkKey(left.reference).localeCompare(getBookmarkKey(right.reference));\n}\n\nfunction normalizeBookmark(bookmark: BookmarkRecord): BookmarkRecord {\n return {\n reference: normalizeSessionReference(bookmark.reference),\n bookmarkedAt: bookmark.bookmarkedAt,\n };\n}\n\nfunction toBookmarkRecord(row: BookmarkRow): BookmarkRecord {\n return {\n reference: normalizeSessionReference({\n agentName: String(row.agent_name ?? \"\"),\n sessionId: String(row.session_id ?? \"\"),\n }),\n bookmarkedAt: Number(row.bookmarked_at ?? 0),\n };\n}\n\nfunction readBookmarks(db: SQLiteDatabase): BookmarkRecord[] {\n const rows = db\n .prepare(\n `\n SELECT agent_name, session_id, bookmarked_at\n FROM bookmarks\n ORDER BY bookmarked_at DESC, agent_name ASC, session_id ASC\n `,\n )\n .all() as BookmarkRow[];\n return rows.map(toBookmarkRecord);\n}\n\nfunction listMemoryBookmarks(): BookmarkRecord[] {\n return [...memoryBookmarks.values()].sort(compareBookmarks);\n}\n\nexport function listBookmarks(): BookmarkRecord[] {\n if (useMemoryStateStore()) return listMemoryBookmarks();\n return withStateDb(readBookmarks);\n}\n\nexport function upsertBookmark(reference: SessionReference): BookmarkRecord {\n const normalized = normalizeSessionReference(reference);\n const key = getBookmarkKey(normalized);\n if (useMemoryStateStore()) {\n const bookmark = memoryBookmarks.get(key) ?? {\n reference: normalized,\n bookmarkedAt: Date.now(),\n };\n memoryBookmarks.set(key, bookmark);\n return bookmark;\n }\n\n return withStateDb((db) => {\n const row = db\n .prepare(\n `\n INSERT INTO bookmarks(agent_name, session_id, bookmarked_at)\n VALUES (?, ?, ?)\n ON CONFLICT(agent_name, session_id) DO UPDATE\n SET bookmarked_at = bookmarks.bookmarked_at\n RETURNING agent_name, session_id, bookmarked_at\n `,\n )\n .get(normalized.agentName, normalized.sessionId, Date.now()) as BookmarkRow | undefined;\n if (!row) {\n throw new Error(\"Bookmark upsert returned no row\");\n }\n return toBookmarkRecord(row);\n });\n}\n\nexport function importBookmarks(bookmarks: readonly BookmarkRecord[]): BookmarkRecord[] {\n const unique = new Map<string, BookmarkRecord>();\n for (const bookmark of bookmarks) {\n const normalized = normalizeBookmark(bookmark);\n const key = getBookmarkKey(normalized.reference);\n if (!unique.has(key)) unique.set(key, normalized);\n }\n\n if (useMemoryStateStore()) {\n for (const [key, bookmark] of unique) {\n if (!memoryBookmarks.has(key)) memoryBookmarks.set(key, bookmark);\n }\n return listMemoryBookmarks();\n }\n\n return withStateDb((db) => {\n const insert = db.prepare(\n `\n INSERT INTO bookmarks(agent_name, session_id, bookmarked_at)\n VALUES (?, ?, ?)\n ON CONFLICT(agent_name, session_id) DO NOTHING\n `,\n );\n const write = db.transaction(() => {\n for (const bookmark of unique.values()) {\n insert.run(\n bookmark.reference.agentName,\n bookmark.reference.sessionId,\n bookmark.bookmarkedAt,\n );\n }\n });\n write.immediate();\n return readBookmarks(db);\n });\n}\n\nexport function deleteBookmark(reference: SessionReference): void {\n const normalized = normalizeSessionReference(reference);\n if (useMemoryStateStore()) {\n memoryBookmarks.delete(getBookmarkKey(normalized));\n return;\n }\n\n withStateDb((db) => {\n db.prepare(\n `\n DELETE FROM bookmarks\n WHERE agent_name = ? AND session_id = ?\n `,\n ).run(normalized.agentName, normalized.sessionId);\n });\n}\n","import { StateStorageUnavailableError, useMemoryStateStore, withStateDb } from \"./database.js\";\nimport type { DatabaseRow } from \"../utils/sqlite.js\";\nimport { normalizeSessionReference, type SessionReference } from \"../contract/index.js\";\n\nexport const SESSION_ALIAS_MAX_LENGTH = 160;\n\nexport class SessionAliasValidationError extends Error {\n constructor() {\n super(\"Invalid session alias\");\n this.name = \"SessionAliasValidationError\";\n }\n}\n\nexport interface SessionAlias {\n reference: SessionReference;\n alias: string;\n updatedAt: number;\n}\n\ninterface SessionAliasRow extends DatabaseRow {\n agent_name?: string;\n session_id?: string;\n alias?: string;\n updated_at?: number;\n}\n\nconst memoryAliases = new Map<string, SessionAlias>();\n\nfunction getAliasKey(reference: SessionReference): string {\n const normalized = normalizeSessionReference(reference);\n return JSON.stringify([normalized.agentName, normalized.sessionId]);\n}\n\nfunction toSessionAlias(row: SessionAliasRow): SessionAlias {\n const reference = normalizeSessionReference({\n agentName: String(row.agent_name ?? \"\"),\n sessionId: String(row.session_id ?? \"\"),\n });\n return {\n reference,\n alias: String(row.alias ?? \"\"),\n updatedAt: Number(row.updated_at ?? 0),\n };\n}\n\nexport function normalizeSessionAlias(value: string): string | null {\n const alias = value.trim();\n if (!alias || alias.length > SESSION_ALIAS_MAX_LENGTH) return null;\n return alias;\n}\n\nexport function listSessionAliases(): SessionAlias[] {\n if (useMemoryStateStore()) return [...memoryAliases.values()];\n\n return withStateDb((db) =>\n (\n db\n .prepare(\n `\n SELECT agent_name, session_id, alias, updated_at\n FROM session_aliases\n ORDER BY updated_at DESC\n `,\n )\n .all() as SessionAliasRow[]\n ).map(toSessionAlias),\n );\n}\n\nexport function upsertSessionAlias(reference: SessionReference, alias: string): SessionAlias {\n const normalizedAlias = normalizeSessionAlias(alias);\n if (!normalizedAlias) {\n throw new SessionAliasValidationError();\n }\n\n const normalizedReference = normalizeSessionReference(reference);\n const saved: SessionAlias = {\n reference: normalizedReference,\n alias: normalizedAlias,\n updatedAt: Date.now(),\n };\n if (useMemoryStateStore()) {\n memoryAliases.set(getAliasKey(normalizedReference), saved);\n return saved;\n }\n\n return withStateDb((db) => {\n db.prepare(\n `\n INSERT INTO session_aliases(agent_name, session_id, alias, updated_at)\n VALUES (?, ?, ?, ?)\n ON CONFLICT(agent_name, session_id) DO UPDATE SET\n alias = excluded.alias,\n updated_at = excluded.updated_at\n `,\n ).run(saved.reference.agentName, saved.reference.sessionId, saved.alias, saved.updatedAt);\n return saved;\n });\n}\n\nexport function deleteSessionAlias(reference: SessionReference): void {\n const normalizedReference = normalizeSessionReference(reference);\n if (useMemoryStateStore()) {\n memoryAliases.delete(getAliasKey(normalizedReference));\n return;\n }\n\n withStateDb((db) => {\n db.prepare(\n `\n DELETE FROM session_aliases\n WHERE agent_name = ? AND session_id = ?\n `,\n ).run(normalizedReference.agentName, normalizedReference.sessionId);\n });\n}\n\nexport { StateStorageUnavailableError };\n","import type {\n BookmarkRecord,\n BookmarkView,\n ReferencedSessionHead,\n SessionHead,\n SessionReference,\n} from \"../contract/index.js\";\nimport {\n assertSessionIdentity,\n getSessionReferenceKey,\n normalizeSessionReference,\n} from \"../contract/index.js\";\n\nexport interface BookmarkMaterializationOptions {\n liveSessionsByReference: ReadonlyMap<string, SessionHead>;\n knownAgentNames: ReadonlySet<string>;\n resolveCachedSessions?: (\n references: readonly SessionReference[],\n ) => readonly ReferencedSessionHead[];\n}\n\nfunction canonicalSession(reference: SessionReference, session: SessionHead): SessionHead {\n const normalized = normalizeSessionReference(reference);\n assertSessionIdentity(session, normalized.agentName);\n if (session.reference.sessionId !== normalized.sessionId) {\n throw new Error(\"Session reference does not match expected session\");\n }\n return session;\n}\n\nfunction compareDescending(left: number, right: number): number {\n if (left === right) return 0;\n return left > right ? -1 : 1;\n}\n\nfunction getBookmarkViewTime(bookmark: BookmarkView): number {\n return bookmark.availability === \"available\"\n ? (bookmark.session.time_updated ?? bookmark.session.time_created)\n : bookmark.bookmarkedAt;\n}\n\nexport function compareBookmarkViews(left: BookmarkView, right: BookmarkView): number {\n return (\n compareDescending(getBookmarkViewTime(left), getBookmarkViewTime(right)) ||\n compareDescending(left.bookmarkedAt, right.bookmarkedAt) ||\n getSessionReferenceKey(left.reference).localeCompare(getSessionReferenceKey(right.reference))\n );\n}\n\nexport function materializeBookmarkViews(\n bookmarks: readonly BookmarkRecord[],\n options: BookmarkMaterializationOptions,\n): BookmarkView[] {\n const liveByKey = new Map<string, SessionHead>();\n const missingByKey = new Map<string, SessionReference>();\n const normalizedBookmarks = bookmarks.map((bookmark) => {\n const reference = normalizeSessionReference(bookmark.reference);\n return {\n bookmark: { reference, bookmarkedAt: bookmark.bookmarkedAt },\n key: getSessionReferenceKey(reference),\n };\n });\n\n for (const { bookmark, key } of normalizedBookmarks) {\n const { reference } = bookmark;\n const live = options.liveSessionsByReference.get(key);\n if (live) liveByKey.set(key, canonicalSession(reference, live));\n else if (!missingByKey.has(key)) missingByKey.set(key, reference);\n }\n\n const cachedByKey = new Map<string, SessionHead>();\n if (missingByKey.size > 0 && options.resolveCachedSessions) {\n for (const cached of options.resolveCachedSessions([...missingByKey.values()])) {\n const reference = normalizeSessionReference(cached.reference);\n const key = getSessionReferenceKey(reference);\n if (missingByKey.has(key) && !cachedByKey.has(key)) {\n cachedByKey.set(key, canonicalSession(reference, cached.session));\n }\n }\n }\n\n const views = normalizedBookmarks.map(({ bookmark, key }): BookmarkView => {\n const session = liveByKey.get(key) ?? cachedByKey.get(key);\n if (session) return { ...bookmark, availability: \"available\", session };\n\n return {\n ...bookmark,\n availability: options.knownAgentNames.has(bookmark.reference.agentName)\n ? \"session-unavailable\"\n : \"agent-unavailable\",\n };\n });\n\n return views.sort(compareBookmarkViews);\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 } from \"@codesesh/core/runtime/state\";\nimport type { SessionHead } from \"@codesesh/core/runtime/discovery\";\nimport type { SearchResult, SessionReference } from \"@codesesh/core/contract\";\nimport {\n filterSessionSearchCandidates,\n type SessionSearchContext,\n} from \"@codesesh/core/runtime/search\";\nimport { getSessionActivityTime } from \"@codesesh/core/runtime/analytics\";\nimport { listSessionAliases, StateStorageUnavailableError } from \"@codesesh/core/runtime/state\";\nimport {\n mergeSearchQueryOptions,\n type FileActivityResult,\n type LiveSnapshot,\n type SearchOptions,\n} from \"@codesesh/core/runtime/discovery\";\nimport { appLogger } from \"../logging.js\";\n\n/** Anything the API returns that can carry a locally-renamed title. */\ntype Titled = { 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 buildAliasView(aliases: Map<string, SessionAlias>): AliasView {\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\nfunction readAliasView(): AliasView | null {\n try {\n return buildAliasView(\n new Map(listSessionAliases().map((alias) => [aliasKey(alias.reference), alias])),\n );\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 null;\n }\n}\n\nconst EMPTY_ALIAS_VIEW = buildAliasView(new Map());\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. Failed reads return an empty view for that request but are not published,\n * so a recovered store is retried on the next request.\n */\nlet cachedView: AliasView | null = null;\n\nexport function loadAliasView(): AliasView {\n if (cachedView) return cachedView;\n const loaded = readAliasView();\n if (!loaded) return EMPTY_ALIAS_VIEW;\n cachedView = loaded;\n return loaded;\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(\n (scanResult.byAgent[agentName] ?? []).map((item) => [item.reference.sessionId, item]),\n );\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 queryScope: context.queryScope,\n }).sort((a, b) => getSessionActivityTime(b.session) - getSessionActivityTime(a.session));\n}\n","import {\n addCalendarDays,\n startOfCalendarDay,\n toPublicReferencedSessionHead,\n} from \"@codesesh/core/contract\";\nimport { getAgentInfoMap } from \"@codesesh/core/runtime/agents\";\nimport {\n buildDashboard,\n type DashboardData,\n type DashboardScope,\n} from \"@codesesh/core/runtime/analytics\";\nimport { getAnalyticsRevision } from \"@codesesh/core/runtime/discovery\";\nimport type { Context } from \"hono\";\nimport { resolveTimeWindow } from \"../time-window-resolution.js\";\nimport { parseDateWindowRequest } from \"./handler-support.js\";\nimport {\n optionalQueryValue,\n parseProjectIdentityFilter,\n type SessionListDefaults,\n} from \"./query-params.js\";\nimport type { ScanResultSource } from \"./scan-sources.js\";\nimport { decorateFileActivity, loadAliasView } from \"./session-aliases-view.js\";\nimport {\n getSnapshotCostFacts,\n getDashboardStorageAggregation,\n getSnapshotAggregation,\n} from \"./snapshot-aggregation.js\";\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 window: dateWindow,\n days: c.req.query(\"days\"),\n defaultDays: defaults.days,\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 = from == null ? undefined : { from: addCalendarDays(from, -days), to: from - 1 };\n const fixedTo = dateWindow.to;\n const cacheTo = fixedTo ?? startOfCalendarDay(to);\n const analyticsRevision = getAnalyticsRevision();\n // Keep all-time facts reusable by Projects; buildDashboard applies the current-time bound.\n const costFacts = getSnapshotCostFacts(\n scanSource,\n scanResult.sessions,\n compare?.from ?? from,\n from == null && fixedTo == null ? undefined : to,\n from == null && fixedTo == null ? undefined : 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 toPublicReferencedSessionHead({\n ...item,\n session: aliases.decorate(item.session, item.reference),\n }),\n ),\n recentFileActivities: data.recentFileActivities.map((activity) =>\n toPublicReferencedSessionHead(decorateFileActivity(activity, aliases)),\n ),\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","import { toPublicReferencedSessionHead, type SessionTree } from \"@codesesh/core/contract\";\nimport {\n getSearchProjectDirectory,\n listFileActivity,\n mergeSearchQueryOptions,\n} from \"@codesesh/core/runtime/discovery\";\nimport type { ProjectScopeMatcher } from \"@codesesh/core/runtime/projects\";\nimport { executeSessionSearch } from \"@codesesh/core/runtime/search\";\nimport type { Context } from \"hono\";\nimport type { ProjectIdentityResolver } from \"../project-identity-resolver.js\";\nimport {\n KNOWN_AGENT_NAMES,\n parseDateWindowRequest,\n projectScopeResolutionFailureResponse,\n reportInvalidQueryParameter,\n resolveProjectScope,\n} from \"./handler-support.js\";\nimport {\n FILE_ACTIVITY_LIMIT_POLICY,\n optionalQueryValue,\n parseFileActivityKind,\n parseProjectIdentityFilter,\n parseSearchOptions,\n parseSessionQuery,\n SEARCH_LIMIT_POLICY,\n searchParams,\n type SessionListDefaults,\n} from \"./query-params.js\";\nimport type { ScanResultSource } from \"./scan-sources.js\";\nimport { mergeAliasSearchResults, withParentContext } from \"./search-result-merge.js\";\nimport {\n decorateFileActivity,\n findAliasSearchResults,\n loadAliasView,\n} from \"./session-aliases-view.js\";\nimport { getSnapshotSessionTree } from \"./snapshot-aggregation.js\";\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(\n cwd,\n scanResult.sessions,\n resolver,\n c.req.raw.signal,\n );\n } catch (error) {\n return projectScopeResolutionFailureResponse(c, \"search\", error);\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 queryScope: scanSource.queryScope,\n ...(effectiveSearchOptions.costMin != null || effectiveSearchOptions.costMax != null\n ? { sessionTree: getSessionTree() }\n : {}),\n };\n const searchResults = executeSessionSearch(\n query,\n resolvedSearchOptions,\n scanResult,\n searchContext,\n );\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).map(\n toPublicReferencedSessionHead,\n ),\n });\n}\n\nexport async function handleGetFileActivity(\n c: Context,\n scanSource: ScanResultSource,\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, c.req.raw.signal);\n } catch (error) {\n return projectScopeResolutionFailureResponse(c, \"file-activity\", error);\n }\n }\n\n const aliases = loadAliasView();\n return c.json({\n activity: listFileActivity(\n {\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 },\n scanSource.queryScope,\n ).map((activity) => toPublicReferencedSessionHead(decorateFileActivity(activity, aliases))),\n });\n}\n","import { Worker } from \"node:worker_threads\";\nimport {\n materializeCachedSessionDetailResponse,\n type LiveSnapshot,\n type SessionDetailResponseResult,\n type SessionReference,\n} from \"@codesesh/core/runtime/discovery\";\nimport { getPricingGeneration } from \"@codesesh/core/runtime/pricing\";\nimport { appLogger } from \"./logging.js\";\nimport type {\n SessionDetailWorkerMessage,\n SessionDetailWorkerRequest,\n} from \"./session-detail-worker.js\";\nimport { terminateWorkerAfterLogDrain } from \"./worker-log-drain.js\";\n\nexport type SessionDetailLoader = (\n snapshot: LiveSnapshot,\n reference: SessionReference,\n options?: { messageCursor?: string },\n signal?: AbortSignal,\n) => SessionDetailResponseResult | Promise<SessionDetailResponseResult>;\n\nexport class SessionDetailBusyError extends Error {\n constructor() {\n super(\"Session detail workers are busy\");\n }\n}\n\nconst MAX_DETAIL_WORKERS = 2;\nconst DETAIL_TIMEOUT_MS = 60_000;\n\nexport class ThreadSessionDetailLoader {\n private readonly workers = new Set<Worker>();\n private readonly shutdownController = new AbortController();\n\n constructor(\n private readonly workerUrl = new URL(\"./session-detail-worker.js\", import.meta.url),\n ) {}\n\n readonly load: SessionDetailLoader = async (snapshot, reference, options = {}, signal) => {\n const requestSignal = signal\n ? AbortSignal.any([signal, this.shutdownController.signal])\n : this.shutdownController.signal;\n requestSignal.throwIfAborted();\n const cached = materializeCachedSessionDetailResponse(snapshot, reference, options);\n if (cached) return cached;\n if (this.workers.size >= MAX_DETAIL_WORKERS) throw new SessionDetailBusyError();\n const agent = snapshot.agents.find((item) => item.name === reference.agentName);\n const head = snapshot.byAgent[reference.agentName]?.find(\n (item) => item.reference.sessionId === reference.sessionId,\n );\n const meta = agent?.getSessionCacheMeta(reference.sessionId);\n const request: SessionDetailWorkerRequest = {\n reference,\n head,\n meta: meta ? { [reference.sessionId]: meta } : {},\n messageCursor: options.messageCursor,\n pricingGenerationId: getPricingGeneration().id,\n logContext: appLogger.captureContext(),\n };\n appLogger.info(\"session_detail.worker.started\", {\n agent: reference.agentName,\n session_id: reference.sessionId,\n });\n const worker = new Worker(this.workerUrl, { workerData: request });\n const exited = new Promise<void>((resolve) =>\n worker.once(\"exit\", () => {\n this.workers.delete(worker);\n resolve();\n }),\n );\n let timeout: ReturnType<typeof setTimeout> | undefined;\n let abort = () => {};\n try {\n return await new Promise<SessionDetailResponseResult>((resolve, reject) => {\n abort = () => reject(requestSignal.reason);\n requestSignal.addEventListener(\"abort\", abort, { once: true });\n this.workers.add(worker);\n timeout = setTimeout(\n () => reject(new Error(\"Session detail loading timed out\")),\n DETAIL_TIMEOUT_MS,\n );\n timeout.unref();\n worker.on(\"message\", (message: SessionDetailWorkerMessage) => {\n if (appLogger.consumeWorkerMessage(message)) return;\n if (message.type === \"result\") resolve(message.result);\n else if (message.type === \"error\") reject(new Error(message.error));\n });\n worker.once(\"error\", reject);\n worker.once(\"exit\", (code) =>\n reject(new Error(`Session detail worker exited without a result (${code})`)),\n );\n });\n } finally {\n clearTimeout(timeout);\n requestSignal.removeEventListener(\"abort\", abort);\n await terminateWorkerAfterLogDrain(worker);\n await exited;\n }\n };\n\n async shutdown(): Promise<void> {\n this.shutdownController.abort();\n await Promise.allSettled(\n [...this.workers].map((worker) => terminateWorkerAfterLogDrain(worker)),\n );\n }\n}\n","import type { SessionDetail } from \"@codesesh/core/runtime/discovery\";\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 { toPublicSessionHead, type SessionReference } from \"@codesesh/core/contract\";\nimport {\n materializeSessionDetailResponse,\n type SessionHead,\n type SmartTag,\n} from \"@codesesh/core/runtime/discovery\";\nimport {\n matchesProjectIdentity,\n matchesProjectScope as sessionMatchesProjectScope,\n type ProjectScopeMatcher,\n} from \"@codesesh/core/runtime/projects\";\nimport type { Context } from \"hono\";\nimport { appLogger } from \"../logging.js\";\nimport type { ProjectIdentityResolver } from \"../project-identity-resolver.js\";\nimport { SessionDetailBusyError, type SessionDetailLoader } from \"../session-detail-loader.js\";\nimport {\n KNOWN_AGENT_NAMES,\n parseDateWindowRequest,\n projectScopeResolutionFailureResponse,\n reportInvalidQueryParameter,\n resolveProjectScope,\n} from \"./handler-support.js\";\nimport {\n filterSessionsByActivityWindow,\n optionalQueryValue,\n parseProjectIdentityFilter,\n parseSessionQuery,\n searchParams,\n SESSION_PAGE_LIMIT_POLICY,\n type SessionListDefaults,\n} from \"./query-params.js\";\nimport type { ScanResultSource } from \"./scan-sources.js\";\nimport { createSessionDetailJsonResponse } from \"./session-detail-stream.js\";\nimport { loadAliasView, type AliasView } from \"./session-aliases-view.js\";\nimport { createSnapshotPaginator } from \"./snapshot-pagination.js\";\nimport { getSnapshotAggregation } from \"./snapshot-aggregation.js\";\n\nconst paginateSessions = createSnapshotPaginator<SessionHead, AliasView>();\n\nfunction getSessionHeadReference(session: SessionHead): SessionReference {\n return session.reference;\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(\n cwd,\n scanResult.sessions,\n resolver,\n c.req.raw.signal,\n );\n } catch (error) {\n return projectScopeResolutionFailureResponse(c, \"sessions\", error);\n }\n }\n\n if (sessionQuery.agent.kind === \"unknown\") {\n reportInvalidQueryParameter(\"sessions\", \"agent\", \"empty_result\");\n }\n\n const loadSnapshot = () => {\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) =>\n sessionMatchesProjectScope(session, projectScope),\n );\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 return { items: sessions, view: aliases };\n };\n\n if (paginationRequested) {\n const page = paginateSessions(\n scanSource,\n {\n cursor: params.get(\"cursor\") ?? undefined,\n limit: sessionQuery.limit.value,\n query: params,\n },\n loadSnapshot,\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 expired; restart pagination\" }, 409);\n }\n return c.json({\n sessions: page.items.map((session) =>\n toPublicSessionHead(page.view.decorate(session, getSessionHeadReference(session))),\n ),\n ...(page.nextCursor ? { nextCursor: page.nextCursor } : {}),\n });\n }\n\n const { items: sessions, view: aliases } = loadSnapshot();\n return c.json({\n sessions: sessions.map((session) =>\n toPublicSessionHead(aliases.decorate(session, getSessionHeadReference(session))),\n ),\n });\n}\n\nexport async function handleGetSessionData(\n c: Context,\n scanSource: ScanResultSource,\n loadDetail: SessionDetailLoader = materializeSessionDetailResponse,\n) {\n const startedAt = performance.now();\n const agentName = c.req.param(\"agent\");\n const sessionId = c.req.param(\"id\");\n\n if (!agentName) return c.json({ error: \"Missing agent name\" }, 400);\n if (!sessionId) return c.json({ error: \"Missing session ID\" }, 400);\n\n try {\n const reference = { agentName, sessionId };\n const messageCursor = optionalQueryValue(c.req.query(\"messageCursor\"));\n const result = await loadDetail(\n scanSource.getSnapshot(),\n reference,\n messageCursor ? { messageCursor } : {},\n c.req.raw.signal,\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 (error) {\n if (error instanceof SessionDetailBusyError) {\n c.header(\"Retry-After\", \"1\");\n return c.json({ error: \"Session details busy; retry later\" }, 503);\n }\n const message = error instanceof Error ? error.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","import type { BookmarkRecord } from \"@codesesh/core/runtime/state\";\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 const sanitized: Record<string, unknown> = {};\n for (const [key, item] of Object.entries(value)) {\n if (CLIENT_LOG_STRING_FIELDS.has(key) && typeof item === \"string\") {\n if (key === \"operation_id\" && !UUID_PATTERN.test(item)) continue;\n sanitized[key] = item.slice(0, 300);\n continue;\n }\n if (\n CLIENT_LOG_NUMBER_FIELDS.has(key) &&\n typeof item === \"number\" &&\n Number.isFinite(item) &&\n item >= 0\n ) {\n sanitized[key] = item;\n continue;\n }\n if (CLIENT_LOG_NULLABLE_FIELDS.has(key) && item === null) sanitized[key] = null;\n }\n return sanitized;\n}\n\nconst CLIENT_LOG_STRING_FIELDS = new Set([\n \"agent\",\n \"error_name\",\n \"mode\",\n \"operation_id\",\n \"phase\",\n \"profiler_id\",\n \"reason\",\n \"request_key\",\n \"session\",\n \"source\",\n \"trigger\",\n]);\n\nconst CLIENT_LOG_NUMBER_FIELDS = new Set([\n \"actual_duration_ms\",\n \"agents\",\n \"base_duration_ms\",\n \"commit_time_ms\",\n \"duration_ms\",\n \"error_status\",\n \"messages\",\n \"query_length\",\n \"results\",\n \"sessions\",\n \"start_time_ms\",\n]);\n\nconst CLIENT_LOG_NULLABLE_FIELDS = new Set([\"agent\", \"session\"]);\nconst UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;\n","import type { Context } from \"hono\";\nimport { appLogger } from \"../logging.js\";\nimport { sanitizeClientLogData } from \"./request-payloads.js\";\n\ninterface ClientLogPayload {\n event?: unknown;\n data?: unknown;\n}\n\nconst CLIENT_LOG_EVENTS = new Set<string>([\n \"app.load.done\",\n \"app.load.error\",\n \"app.load.start\",\n \"bookmark.add\",\n \"bookmark.delete\",\n \"react.profiler.commit\",\n \"route.change\",\n \"search.done\",\n \"search.error\",\n \"search.start\",\n \"session.markdown_copy.done\",\n \"session.markdown_copy.error\",\n \"session.open.cancel\",\n \"session.open.done\",\n \"session.open.error\",\n \"session.open.start\",\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\") {\n return c.json({ ok: false }, 400);\n }\n\n const event = rawEvent.trim();\n if (!CLIENT_LOG_EVENTS.has(event)) return c.json({ ok: false }, 400);\n\n appLogger.info(`client.${event}`, sanitizeClientLogData(payload?.data));\n return c.json({ ok: true });\n}\n","import type { Context } from \"hono\";\nimport type { BookmarkRecord, BookmarkView } from \"@codesesh/core/runtime/state\";\nimport { createSessionIndex, toPublicSessionHead } from \"@codesesh/core/contract\";\nimport {\n SessionAliasValidationError,\n StateStorageUnavailableError,\n deleteBookmark,\n deleteSessionAlias,\n importBookmarks,\n listBookmarks,\n materializeBookmarkViews,\n upsertBookmark,\n upsertSessionAlias,\n} from \"@codesesh/core/runtime/state\";\nimport { loadCachedSessionHeads } from \"@codesesh/core/runtime/discovery\";\nimport { KNOWN_AGENT_NAME_SET } from \"./handler-support.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) => {\n const decorated = decorateBookmark(bookmark, aliases);\n return decorated.availability === \"available\"\n ? { ...decorated, session: toPublicSessionHead(decorated.session) }\n : decorated;\n });\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({ error: \"Bookmark storage is unavailable\" }, 503),\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 { 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 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 ACCESS_TOKEN_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 remoteAccessRequired: 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\nfunction assertTrustedProxyListener(hostname: string, transport: RemoteTransport): void {\n if (transport.kind === \"trusted-proxy\" && !isLoopbackHostname(hostname)) {\n throw new RemoteTransportError(\n \"--trust-proxy requires a loopback --host so clients cannot reach the HTTP backend directly.\",\n );\n }\n}\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) {\n const transport = { kind: \"trusted-proxy\" } as const;\n assertTrustedProxyListener(request.hostname, transport);\n return transport;\n }\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 assertTrustedProxyListener(hostname, transport);\n const bindCategory = isLoopbackHostname(hostname) ? \"loopback\" : \"network\";\n const directLoopback = bindCategory === \"loopback\" && transport.kind === \"loopback\";\n return {\n bindCategory,\n remoteAccessRequired: !directLoopback,\n };\n}\n\nexport function resolvePublicOrigin(\n value: string | undefined,\n transport: RemoteTransport,\n): string | undefined {\n if (transport.kind !== \"trusted-proxy\") {\n if (value) throw new RemoteTransportError(\"--public-url requires --trust-proxy.\");\n return undefined;\n }\n if (!value) {\n throw new RemoteTransportError(\n \"--trust-proxy requires an HTTPS --public-url for browser startup links.\",\n );\n }\n\n let url: URL;\n try {\n url = new URL(value);\n } catch {\n throw new RemoteTransportError(\"--public-url must be a valid HTTPS origin.\");\n }\n if (\n url.protocol !== \"https:\" ||\n url.username ||\n url.password ||\n url.pathname !== \"/\" ||\n url.search ||\n url.hash\n ) {\n throw new RemoteTransportError(\n \"--public-url must be an HTTPS origin without credentials, path, query, or fragment.\",\n );\n }\n return url.origin;\n}\n\nconst FORWARDED_PROTO_HEADER = \"X-Forwarded-Proto\";\n\n/**\n * The forwarded scheme validates proxy configuration, not client identity.\n * The enforced loopback listener supplies the network boundary; the access\n * token still authenticates every request that reaches it.\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 createAccessToken(): 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(ACCESS_TOKEN_QUERY_PARAM);\n}\n\nexport function accessTokenAuth(expectedToken: string): MiddlewareHandler {\n return async (c, next) => {\n if (!tokenMatches(requestToken(c), expectedToken)) {\n return c.json({ error: \"API access token required\" }, 401);\n }\n await next();\n };\n}\n","import { existsSync } from \"node:fs\";\nimport { fileURLToPath } from \"node:url\";\nimport {\n closeCacheStorage,\n scanSessions,\n type LiveSnapshot,\n type ScanOptions,\n type SessionQueryScope,\n} from \"@codesesh/core/runtime/discovery\";\nimport { createRegisteredAgents } from \"@codesesh/core/runtime/agents\";\nimport { createProjectScopeMatcher } from \"@codesesh/core/runtime/projects\";\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 readonly queryScope: SessionQueryScope;\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.queryScope = {\n ...(this.scanOptions.agents?.length\n ? { agents: this.scanOptions.agents.map((agent) => agent.toLowerCase()) }\n : {}),\n ...(this.scanOptions.cwd\n ? { projectScope: createProjectScopeMatcher(this.scanOptions.cwd) }\n : {}),\n };\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 { cwd: _cwd, ...scanOptions } = this.scanOptions;\n const initialResult = await scanSessions({\n ...scanOptions,\n useCache: this.scanOptions.useCache ?? true,\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 queryScope: this.queryScope,\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 source_enumeration_ms:\n timing.sourceEnumeration != null\n ? Math.round(timing.sourceEnumeration)\n : undefined,\n source_diff_ms:\n timing.sourceDiff != null ? Math.round(timing.sourceDiff) : undefined,\n source_parse_ms:\n timing.sourceParse != null ? Math.round(timing.sourceParse) : undefined,\n enumerated_sources: timing.enumeratedSources,\n changed_sources: timing.changedSources,\n processed_sources: timing.processedSources,\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.newSessionRefs.length > 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","import { readAgentLastFullSyncAt, type ScanOptions } from \"@codesesh/core/runtime/discovery\";\nimport { type BaseAgent } from \"@codesesh/core/runtime/agents\";\nimport type {\n BackfillAttemptRef,\n BackfillLifecycle,\n BackfillTerminalStatus,\n} from \"./backfill-lifecycle.js\";\nimport { appLogger } from \"./logging.js\";\nimport type { ScanStatusReporter } from \"./scan-status-reporter.js\";\n\nexport interface AgentBackfillSchedulerOptions {\n lifecycle: BackfillLifecycle;\n statusReporter: ScanStatusReporter;\n startupScanOptions: Pick<ScanOptions, \"from\" | \"to\">;\n runAttempt(attempt: BackfillAttemptRef): Promise<BackfillTerminalStatus>;\n scheduleRefresh(agentName: string, delayMs: number): void;\n}\n\nconst BACKFILL_INTERVAL_MS = 24 * 60 * 60 * 1000;\nconst PARTIAL_BACKFILL_RETRY_DELAY_MS = 5 * 60 * 1000;\n\n/**\n * Owns backfill eligibility, queue progression, retries, and full-sync\n * validity windows. The sync engine supplies only the actual scan operation.\n */\nexport class AgentBackfillScheduler {\n private readonly cacheIntegrityValidUntilByAgent = new Map<string, number>();\n private isShuttingDown = false;\n\n constructor(private readonly options: AgentBackfillSchedulerOptions) {}\n\n needsBackfill(agent: BaseAgent): boolean {\n const { from, to } = this.options.startupScanOptions;\n if (from == null && 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 this.cacheIntegrityValidUntilByAgent.set(agent.name, lastSyncAt + BACKFILL_INTERVAL_MS);\n return false;\n }\n\n enqueue(agentName: string): void {\n if (this.isShuttingDown || !this.options.lifecycle.enqueue(agentName)) return;\n this.options.statusReporter.publishBackfillStatus();\n this.pump();\n }\n\n shutdown(): void {\n this.isShuttingDown = true;\n this.options.lifecycle.cancelAll();\n this.cacheIntegrityValidUntilByAgent.clear();\n }\n\n private pump(): void {\n if (this.isShuttingDown) return;\n const attempt = this.options.lifecycle.startNext();\n if (!attempt) return;\n this.options.statusReporter.publishBackfillStatus();\n void this.options\n .runAttempt(attempt)\n .then((result) => this.complete(attempt, result))\n .catch((error) => this.reject(attempt, error));\n }\n\n private complete(attempt: BackfillAttemptRef, result: BackfillTerminalStatus): void {\n if (this.isShuttingDown) return;\n const current = this.options.lifecycle.stateFor(attempt.agentName);\n if (current?.status === \"running\" && current.attemptId === attempt.attemptId) {\n this.options.statusReporter.flushProgressStatus(`backfill:${attempt.agentName}`);\n if (this.options.lifecycle.complete(attempt, result)) {\n if (result === \"failed\") {\n this.cacheIntegrityValidUntilByAgent.delete(attempt.agentName);\n } else if (result === \"committed\") {\n if (current.completion?.completeness === \"partial\") {\n this.cacheIntegrityValidUntilByAgent.delete(attempt.agentName);\n this.options.scheduleRefresh(attempt.agentName, PARTIAL_BACKFILL_RETRY_DELAY_MS);\n appLogger.info(\"scan.backfill.retry_scheduled\", {\n agent: attempt.agentName,\n delay_ms: PARTIAL_BACKFILL_RETRY_DELAY_MS,\n });\n } else {\n this.cacheIntegrityValidUntilByAgent.set(\n attempt.agentName,\n Date.now() + BACKFILL_INTERVAL_MS,\n );\n }\n }\n this.options.statusReporter.publishBackfillStatus();\n }\n }\n this.pump();\n }\n\n private reject(attempt: BackfillAttemptRef, error: unknown): void {\n appLogger.error(\"scan.backfill.queue_error\", { agent: attempt.agentName, error });\n this.complete(attempt, \"failed\");\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 operationId: string;\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 return appLogger.runWithContext({ operation_id: lifecycle.operationId }, async () => {\n this.logOperationStarted(lifecycle);\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 });\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 return {\n agentName,\n kind,\n generation,\n operationId: `${agentName}:${generation}`,\n startedAt,\n };\n }\n\n private logOperationStarted(lifecycle: AgentOperationLifecycle): void {\n appLogger.info(\"scan.agent_operation.started\", {\n agent: lifecycle.agentName,\n operation: lifecycle.kind,\n generation: lifecycle.generation,\n started_at: lifecycle.startedAt,\n });\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 const phaseChanged = progress.phase != null && progress.phase !== current.progress?.phase;\n this.attempts.set(attempt.agentName, {\n ...current,\n progress: phaseChanged ? { ...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 matchesSessionQueryScope,\n sessionSignature,\n type AgentCacheFailure,\n sortSessions,\n type IdentifiedSessionHead,\n type LiveSnapshot,\n type SessionQueryScope,\n} from \"@codesesh/core/runtime/discovery\";\nimport { type AgentScanFailure, type BaseAgent } from \"@codesesh/core/runtime/agents\";\nimport {\n assertIdentifiedSessionHead,\n assertSessionIdentity,\n createSessionProjectionContext,\n toPublicReferencedSessionHead,\n type SessionsUpdatedEvent,\n} from \"@codesesh/core/contract\";\n\nexport interface LiveSessionIndexOptions {\n registeredAgents?: BaseAgent[];\n queryScope?: SessionQueryScope;\n}\n\nexport class LiveSessionIndex {\n private agents: BaseAgent[] = [];\n private agentsByName = new Map<string, BaseAgent>();\n private queryScope?: SessionQueryScope;\n private allByAgent: Record<string, IdentifiedSessionHead[]> = {};\n private byAgent: Record<string, IdentifiedSessionHead[]> = {};\n private sessions: IdentifiedSessionHead[] = [];\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 this.queryScope = options.queryScope;\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) =>\n !this.queryScope?.agents?.length ||\n this.queryScope.agents.includes(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.allByAgent = {};\n this.byAgent = Object.fromEntries(\n this.agents.flatMap((agent) => {\n if (this.scanFailures[agent.name] && !(agent.name in snapshot.byAgent)) return [];\n const sessions = snapshot.byAgent[agent.name] ?? [];\n for (const session of sessions) {\n assertSessionIdentity(session, agent.name);\n assertIdentifiedSessionHead(session);\n }\n this.allByAgent[agent.name] = sortSessions(sessions);\n return [[agent.name, this.visibleSessions(this.allByAgent[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 agentSessions(agentName: string): IdentifiedSessionHead[] {\n return this.allByAgent[agentName] ?? [];\n }\n\n commitAgentSessions(\n agentName: string,\n nextSessions: IdentifiedSessionHead[],\n candidateChangedIds: string[] = [],\n ): SessionsUpdatedEvent | null {\n for (const session of nextSessions) {\n assertSessionIdentity(session, agentName);\n assertIdentifiedSessionHead(session);\n }\n const visibleSessions = this.visibleSessions(nextSessions);\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 visibleSessions,\n candidateChangedIds,\n sessionSignature,\n signatureCache,\n );\n for (const removedId of removedSessionIds) signatureCache.delete(removedId);\n\n this.allByAgent[agentName] = sortSessions(nextSessions);\n const hasChanges = counts.new > 0 || counts.updated > 0 || counts.removed > 0;\n if (!hasChanges && agentName in this.byAgent) return null;\n this.byAgent[agentName] = this.visibleSessions(this.allByAgent[agentName]!);\n this.sessions = mergeSortedSessions(Object.values(this.byAgent));\n if (!hasChanges) return null;\n\n const changedSessionHeads = changes.map(({ session }) => ({\n reference: session.reference,\n session,\n }));\n const previousSessionIds = new Set(\n previousSessions.map((session) => session.reference.sessionId),\n );\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 newSessionRefs,\n totalSessions: this.sessions.length,\n timestamp: Date.now(),\n changedSessionHeads: changedSessionHeads.map(toPublicReferencedSessionHead),\n projectionRelatedSessionHeads: projectionContext.relatedSessionHeads.map(\n toPublicReferencedSessionHead,\n ),\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 private visibleSessions(sessions: IdentifiedSessionHead[]): IdentifiedSessionHead[] {\n if (!this.queryScope?.projectScope) return sessions;\n return sessions.filter((session) => matchesSessionQueryScope(session, this.queryScope));\n }\n}\n","import { existsSync } from \"node:fs\";\nimport { fileURLToPath } from \"node:url\";\nimport { Worker } from \"node:worker_threads\";\nimport { getPricingGeneration } from \"@codesesh/core/runtime/pricing\";\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 SearchIndexPublicationProgress,\n SearchIndexWorkerRunRequest,\n} from \"./search-index-worker.js\";\nimport { terminateWorkerAfterLogDrain } from \"./worker-log-drain.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 private retirements = new Set<Promise<number>>();\n\n enqueue(\n context: string,\n jobs: SearchIndexWorkerJob[],\n onStarted?: () => void,\n onProgress?: (progress: SearchIndexPublicationProgress) => void,\n ): Promise<void> {\n return this.enqueueIn(this.pendingJobs, context, jobs, onStarted, onProgress);\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 onProgress?: (progress: SearchIndexPublicationProgress) => 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(\n batchId,\n context,\n jobs,\n onStarted,\n onProgress,\n appLogger.captureContext(),\n );\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 const activeRetirement = worker ? this.retireWorker(worker) : null;\n const retirements = [...this.retirements];\n try {\n if (activeRetirement) await activeRetirement;\n } finally {\n await Promise.allSettled(retirements);\n }\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.restoreContext(batch.logContext, () => {\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\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 logContext: batch.logContext,\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 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 appLogger.restoreContext(activeBatch.logContext, () => {\n this.handleWorkerMessage(activeBatch, message);\n });\n });\n worker.on(\"error\", (error) => {\n const activeBatch = this.worker === worker ? this.activeBatch : null;\n appLogger.restoreContext(activeBatch?.logContext ?? {}, () => {\n appLogger.error(\"search_index.worker_error\", {\n context: activeBatch?.context,\n error,\n });\n this.invalidateWorker(worker, toError(error));\n });\n });\n worker.on(\"exit\", (code) => {\n const activeBatch = this.worker === worker ? this.activeBatch : null;\n appLogger.restoreContext(activeBatch?.logContext ?? {}, () =>\n this.finishWorker(worker, code),\n );\n });\n }\n\n private handleWorkerMessage(\n activeBatch: SearchIndexJobBatch,\n message: SearchIndexWorkerMessage,\n ): void {\n if (message.type === \"publication-progress\") {\n const { agentName, stage } = message;\n activeBatch.progress({ agentName, stage }, (error) => {\n appLogger.error(\"search_index.worker_progress_listener_failed\", {\n batch_id: activeBatch.id,\n context: activeBatch.context,\n error: toError(error),\n });\n });\n return;\n }\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\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 this.retireWorker(worker);\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 appLogger.restoreContext(batch.logContext, () => {\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\n private retireWorker(worker: Worker): Promise<number> {\n const retirement = terminateWorkerAfterLogDrain(worker);\n this.retirements.add(retirement);\n void retirement.finally(() => this.retirements.delete(retirement)).catch(() => undefined);\n return retirement;\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 IdentifiedSessionHead,\n PersistedSessionHeadChange,\n} from \"@codesesh/core/runtime/discovery\";\nimport type { SessionCacheMeta } from \"@codesesh/core/runtime/agents\";\nimport type {\n SearchIndexPublicationProgress,\n SearchIndexWorkerJob,\n SearchIndexWorkerOptions,\n} from \"./search-index-worker.js\";\nimport type { LogContext } from \"./logging.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\nconst LOG_CONTEXT_KEYS = [\"request_id\", \"operation_id\", \"publication_id\"] as const;\n\nfunction commonLogContext(left: LogContext, right: LogContext): LogContext {\n const common: LogContext = {};\n for (const key of LOG_CONTEXT_KEYS) {\n if (left[key] !== undefined && left[key] === right[key]) common[key] = left[key];\n }\n return common;\n}\n\ninterface JobWaiter {\n resolve: () => void;\n reject: (error: Error) => void;\n onStarted?: () => void;\n onProgress?: (progress: SearchIndexPublicationProgress) => void;\n agentNames: Set<string>;\n}\n\ninterface PendingChanges {\n kind: IncrementalSearchIndexJob[\"kind\"];\n context: string;\n agentName: string;\n publicationId?: string;\n changesBySessionId: Map<string, PersistedSessionHeadChange<IdentifiedSessionHead>>;\n removedSessionIds: Set<string>;\n meta: Record<string, SessionCacheMeta>;\n searchIndexOptions?: SearchIndexWorkerOptions;\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 logContext: LogContext;\n readonly jobs: SearchIndexWorkerJob[];\n start(onError: (error: unknown) => void): void;\n progress(progress: SearchIndexPublicationProgress, onError: (error: unknown) => void): void;\n}\n\nclass PendingSearchIndexJobBatch implements SearchIndexJobBatch {\n context: string;\n logContext: LogContext;\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 logContext: LogContext,\n ) {\n this.context = context;\n this.logContext = logContext;\n this.merge(context, jobs, waiter, logContext);\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 progress(progress: SearchIndexPublicationProgress, onError: (error: unknown) => void): void {\n for (const waiter of this.waiters) {\n if (!waiter.agentNames.has(progress.agentName)) continue;\n try {\n waiter.onProgress?.(progress);\n } catch (error) {\n onError(error);\n }\n }\n }\n\n merge(\n context: string,\n jobs: SearchIndexWorkerJob[],\n waiter: JobWaiter,\n logContext: LogContext,\n ): void {\n this.context = context;\n this.logContext = commonLogContext(this.logContext, logContext);\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 onProgress?: (progress: SearchIndexPublicationProgress) => void,\n logContext: LogContext = {},\n ): Promise<void> {\n if (jobs.length === 0) return Promise.resolve();\n\n return new Promise((resolve, reject) => {\n const waiter = {\n resolve,\n reject,\n onStarted,\n onProgress,\n agentNames: new Set(jobs.map((job) => job.agentName)),\n };\n if (this.pendingBatch) {\n this.pendingBatch.merge(context, jobs, waiter, logContext);\n } else {\n this.pendingBatch = new PendingSearchIndexJobBatch(id, context, jobs, waiter, logContext);\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.reference.sessionId;\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: SearchIndexWorkerOptions | undefined,\n incoming: SearchIndexWorkerOptions | undefined,\n): SearchIndexWorkerOptions | 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 readCachedSessions,\n readPendingSearchIndexMaintenance,\n type CachedResult,\n type IdentifiedSessionHead,\n type PersistedSessionHeadChange,\n} from \"@codesesh/core/runtime/discovery\";\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\ninterface IndexedSessionCache {\n sessionsById: Map<string, PersistedSessionHeadChange<IdentifiedSessionHead>>;\n meta: CachedResult[\"meta\"];\n}\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<string, IndexedSessionCache>();\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 let cached = this.cachedSessionsByAgent.get(agentName);\n if (!cached) {\n const outcome = readCachedSessions(agentName);\n if (outcome.status === \"failed\") {\n throw new Error(`Session cache read failed for ${agentName}`);\n }\n if (!outcome.value) throw new Error(`Session cache is unavailable for ${agentName}`);\n cached = {\n sessionsById: new Map(\n outcome.value.sessions.map((session, sortIndex) => [\n session.reference.sessionId,\n { session, sortIndex },\n ]),\n ),\n meta: outcome.value.meta,\n };\n this.cachedSessionsByAgent.set(agentName, cached);\n }\n const changes = pending.sessionIds.flatMap(\n (sessionId): PersistedSessionHeadChange<IdentifiedSessionHead>[] => {\n const change = cached.sessionsById.get(sessionId);\n return change ? [change] : [];\n },\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 sessionId = session.reference.sessionId;\n const sessionMeta = cached.meta[sessionId];\n return sessionMeta ? [[sessionId, 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/runtime/agents\";\nimport type {\n BackfillStatus,\n ScanCompletion,\n ScanStatusEvent,\n SearchIndexMaintenanceStatus,\n} from \"@codesesh/core/contract\";\n\ntype ScanStatus = Omit<\n ScanStatusEvent,\n | \"type\"\n | \"active\"\n | \"pendingAgents\"\n | \"scanningAgents\"\n | \"completedAgents\"\n | \"totalAgents\"\n | \"searchIndexMaintenance\"\n> & {\n searchIndexMaintenance: SearchIndexMaintenanceStatus;\n};\n\ninterface AgentLists {\n pendingAgents: string[];\n scanningAgents: string[];\n completedAgents: string[];\n}\n\nexport class ScanStatusModel {\n private status: ScanStatus = {\n phase: \"idle\",\n agentStatuses: {},\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 agentLists = this.agentLists(this.status.agentStatuses);\n const active = this.hasActiveAgents(this.status.agentStatuses);\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 active,\n ...agentLists,\n totalAgents: Object.keys(this.status.agentStatuses).length,\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 phase: uniqueAgentNames.length > 0 ? phase : \"idle\",\n agentStatuses,\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.hasActiveAgents(this.status.agentStatuses)) return null;\n return this.set({ ...this.status, phase, updatedAt: Date.now() });\n }\n\n beginAgent(agentName: string, sessionCount: number): ScanStatusEvent {\n if (!this.hasActiveAgents(this.status.agentStatuses)) {\n this.startBatch([agentName], \"scanning\", { [agentName]: sessionCount });\n }\n\n const existingStatus = this.status.agentStatuses[agentName];\n const now = Date.now();\n return this.set({\n ...this.status,\n phase: this.status.phase === \"initializing\" ? \"initializing\" : \"scanning\",\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 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(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.hasActiveAgents(this.status.agentStatuses) ||\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(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.hasActiveAgents(this.status.agentStatuses) ||\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(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 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 const isActive = this.hasActiveAgents(agentStatuses);\n\n return this.set({\n ...this.status,\n phase: isActive ? this.activePhase(agentStatuses) : \"idle\",\n agentStatuses,\n updatedAt: now,\n completedAt: isActive ? undefined : now,\n });\n }\n\n failAgent(agentName: string, error: string, sessionCount?: number): ScanStatusEvent {\n const now = Date.now();\n const previousStatus = this.status.agentStatuses[agentName];\n const agentStatuses = {\n ...this.status.agentStatuses,\n [agentName]: {\n agentName,\n status: \"failed\" as const,\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 const isActive = this.hasActiveAgents(agentStatuses);\n return this.set({\n ...this.status,\n phase: isActive ? this.activePhase(agentStatuses) : \"idle\",\n agentStatuses,\n updatedAt: now,\n completedAt: isActive ? undefined : now,\n });\n }\n\n finishBatch(): ScanStatusEvent {\n const now = Date.now();\n return this.set({\n ...this.status,\n phase: \"idle\",\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(agentStatuses: ScanStatus[\"agentStatuses\"]): ScanStatusEvent[\"phase\"] {\n const { pendingAgents, scanningAgents } = this.agentLists(agentStatuses);\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 agentLists(agentStatuses: ScanStatus[\"agentStatuses\"]): AgentLists {\n const pendingAgents: string[] = [];\n const scanningAgents: string[] = [];\n const completedAgents: string[] = [];\n\n for (const [agentName, status] of Object.entries(agentStatuses)) {\n if (status.status === \"pending\") pendingAgents.push(agentName);\n else if (status.status === \"complete\") completedAgents.push(agentName);\n else if (status.status !== \"failed\") scanningAgents.push(agentName);\n }\n\n return { pendingAgents, scanningAgents, completedAgents };\n }\n\n private hasActiveAgents(agentStatuses: ScanStatus[\"agentStatuses\"]): boolean {\n return Object.values(agentStatuses).some(\n (status) => status.status !== \"complete\" && status.status !== \"failed\",\n );\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/runtime/agents\";\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 {\n buildAgentCacheMeta,\n type CachedResult,\n type LiveSnapshot,\n type IdentifiedSessionHead,\n} from \"@codesesh/core/runtime/discovery\";\nimport { appLogger } from \"./logging.js\";\nimport type { SearchIndexJobRunner } from \"./search-index-job-runner.js\";\nimport type {\n SearchIndexPublicationProgress,\n SearchIndexWorkerJob,\n} from \"./search-index-worker.js\";\n\nexport interface SearchIndexPublisherOptions {\n jobs: SearchIndexJobRunner;\n snapshot(): LiveSnapshot;\n agentSessions(agentName: string): IdentifiedSessionHead[];\n readCachedSessions(agentName: string): CachedResult | 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: this.options.agentSessions(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 onProgress?: (progress: SearchIndexPublicationProgress) => 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.onProgress\n ? this.options.jobs.enqueue(context, publicationJobs, details.onStarted, details.onProgress)\n : 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 type { IdentifiedSessionHead } from \"@codesesh/core/runtime/discovery\";\nimport type { SessionsUpdatedEvent } from \"@codesesh/core/contract\";\nimport type { LiveSessionIndex } from \"./live-session-index.js\";\nimport { appLogger } from \"./logging.js\";\nimport type { SearchIndexPublisher } from \"./search-index-publisher.js\";\nimport type {\n SearchIndexPublicationProgress,\n SearchIndexWorkerJob,\n} from \"./search-index-worker.js\";\nimport type { StagedWorkerRun } from \"./worker-runner.js\";\n\nexport interface AgentSessionsChanged {\n agentName: string;\n sessions: IdentifiedSessionHead[];\n event: SessionsUpdatedEvent | null;\n}\n\nexport interface SessionPublication {\n context: \"scan.refresh\" | \"scan.backfill\";\n agentName: string;\n sessions: IdentifiedSessionHead[];\n candidateChangedIds: string[];\n indexJob: SearchIndexWorkerJob;\n stagedRun?: StagedWorkerRun;\n onPublishing?: () => void;\n onPublicationProgress?: (progress: SearchIndexPublicationProgress) => void;\n onCommitted?: (result: SessionPublicationResult) => void;\n}\n\nexport interface SessionPublicationResult {\n event: SessionsUpdatedEvent | null;\n diffDuration: number;\n}\n\ntype SessionsChangedListener = (change: AgentSessionsChanged) => void;\n\n/**\n * Commits one durable search-index publication before updating the in-memory\n * session projection and notifying subscribers.\n */\nexport class SessionPublicationCoordinator {\n private readonly listeners = new Set<SessionsChangedListener>();\n private isShuttingDown = false;\n\n constructor(\n private readonly indexPublisher: SearchIndexPublisher,\n private readonly sessionIndex: LiveSessionIndex,\n ) {}\n\n subscribe(listener: SessionsChangedListener): () => void {\n this.listeners.add(listener);\n return () => this.listeners.delete(listener);\n }\n\n markShuttingDown(): void {\n this.isShuttingDown = true;\n }\n\n async commit(publication: SessionPublication): 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 ...(publication.onPublicationProgress\n ? { onProgress: publication.onPublicationProgress }\n : {}),\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 = { event, diffDuration };\n this.runPostCommit(publication, \"worker_commit\", () => publication.stagedRun?.commit());\n this.runPostCommit(publication, \"callback\", () => publication.onCommitted?.(result));\n this.runPostCommit(publication, \"notification\", () =>\n this.emit({\n agentName: publication.agentName,\n sessions: this.sessionIndex.snapshot().byAgent[publication.agentName] ?? [],\n event,\n }),\n );\n this.runPostCommit(publication, \"logging\", () =>\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 );\n return result;\n }\n\n private runPostCommit(\n publication: SessionPublication,\n stage: \"worker_commit\" | \"callback\" | \"notification\" | \"logging\",\n action: () => void,\n ): void {\n try {\n action();\n } catch (error) {\n try {\n appLogger.error(\"session.publication.post_commit_error\", {\n context: publication.context,\n agent: publication.agentName,\n stage,\n error,\n });\n } catch {}\n }\n }\n\n private emit(change: AgentSessionsChanged): void {\n if (this.isShuttingDown) return;\n for (const listener of this.listeners) {\n try {\n listener(change);\n } catch (error) {\n appLogger.error(\"session.publication.post_commit_error\", {\n agent: change.agentName,\n error,\n });\n }\n }\n }\n}\n","import {\n attachMissingProjectIdentities,\n beginAgentRefresh,\n buildAgentCacheMeta,\n buildSessionPersistenceDiff,\n getAgentFullSyncCursor,\n markAgentFullSyncProgress,\n markAgentFullSyncStarted,\n markAgentFullSyncCompleted,\n readCachedSessions,\n readAgentCacheInitialization,\n resolveSessionSnapshotCompleteness,\n type AgentRefreshTransaction,\n type AgentRefreshSelection,\n type CachedResult,\n type IdentifiedSessionHead,\n type ScanOptions,\n type LiveSnapshot,\n type SessionHead,\n type SessionPersistenceDiff,\n type SessionSnapshotCompleteness,\n} from \"@codesesh/core/runtime/discovery\";\nimport { type BaseAgent, type SessionSourceFailure } from \"@codesesh/core/runtime/agents\";\nimport type {\n ScanCompletion,\n ScanStatusEvent,\n SessionsUpdatedEvent,\n} from \"@codesesh/core/contract\";\nimport { AgentBackfillScheduler } from \"./agent-backfill-scheduler.js\";\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 {\n SessionPublicationCoordinator,\n type AgentSessionsChanged,\n type SessionPublicationResult,\n} from \"./session-publication.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 { StagedWorkerRun, WorkerRunner } from \"./worker-runner.js\";\nimport { toError } from \"./errors.js\";\n\nexport type { AgentOperationResult } from \"./agent-operation-scheduler.js\";\nexport type { AgentSessionsChanged } from \"./session-publication.js\";\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 = CachedResult;\n\ninterface RefreshResult {\n result: Exclude<AgentOperationResult, \"failed\">;\n completion: ScanCompletion;\n}\n\ninterface PendingAgentState {\n meta: CachedSessions[\"meta\"];\n refreshedAt?: number;\n refreshTransaction?: AgentRefreshTransaction;\n}\n\nfunction countSessionUpdates(event: SessionsUpdatedEvent | null): {\n newSessions: number;\n updatedSessions: number;\n removedSessions: number;\n} {\n if (!event) return { newSessions: 0, updatedSessions: 0, removedSessions: 0 };\n return {\n newSessions: event.newSessionRefs.length,\n updatedSessions: event.changedSessionHeads.length - event.newSessionRefs.length,\n removedSessions: event.removedSessionRefs.length,\n };\n}\n\ninterface RefreshStrategyBase {\n nextSessions: IdentifiedSessionHead[];\n checkDuration: number;\n scanDuration: number;\n sourceFailures: SessionSourceFailure[];\n completeness: SessionSnapshotCompleteness;\n scope: Pick<ScanOptions, \"from\" | \"to\">;\n workerRun?: StagedWorkerRun;\n pendingAgentState?: PendingAgentState;\n}\n\ntype RefreshPublication =\n | {\n kind: \"changes\";\n diff: SessionPersistenceDiff<IdentifiedSessionHead>;\n candidateChangedIds: string[];\n }\n | {\n kind: \"full\";\n sessions: IdentifiedSessionHead[];\n explicitRemovedSessionIds: string[];\n };\n\ntype RefreshStrategyResult =\n | (RefreshStrategyBase & { status: \"unchanged\" })\n | (RefreshStrategyBase & { status: \"continue\"; publication: RefreshPublication });\n\nconst REFRESH_DEBOUNCE_MS = 200;\nconst EMPTY_AGENT_REFRESH_DEBOUNCE_MS = 30_000;\n// SSE carries one compact summary; logs retain the complete failure list.\nconst SOURCE_FAILURE_SUMMARY_MAX_LENGTH = 160;\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 selectCacheMeta(\n meta: CachedSessions[\"meta\"],\n sessionIds?: ReadonlySet<string>,\n): CachedSessions[\"meta\"] {\n if (!sessionIds) return { ...meta };\n const selected: CachedSessions[\"meta\"] = {};\n for (const sessionId of sessionIds) {\n const entry = meta[sessionId];\n if (entry) selected[sessionId] = entry;\n }\n return selected;\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 readonly backfillScheduler: AgentBackfillScheduler;\n private readonly statusReporter: ScanStatusReporter;\n private readonly indexPublisher: SearchIndexPublisher;\n private readonly sessionPublication: SessionPublicationCoordinator;\n private readonly searchIndexJobs: SearchIndexJobRunner;\n private readonly searchIndexMaintenance: SearchIndexMaintenanceScheduler;\n private backgroundRefreshTimer: NodeJS.Timeout | null = null;\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 agentSessions: (agentName) => this.sessionIndex.agentSessions(agentName),\n readCachedSessions: (agentName) => this.readCachedSessionsOrWarn(\"search.index\", agentName),\n });\n this.sessionPublication = new SessionPublicationCoordinator(\n this.indexPublisher,\n this.sessionIndex,\n );\n this.backfillScheduler = new AgentBackfillScheduler({\n lifecycle: this.backfills,\n statusReporter: this.statusReporter,\n startupScanOptions: this.startupScanOptions(),\n runAttempt: (attempt) => this.runBackfill(attempt),\n scheduleRefresh: (agentName, delayMs) => this.scheduler.schedule(agentName, delayMs),\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 return this.sessionPublication.subscribe(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.sessionPublication.markShuttingDown();\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.backfillScheduler.shutdown();\n this.searchIndexMaintenance.stop();\n this.statusReporter.markShuttingDown();\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 reportPostCommitError(\n operation: \"scan.refresh\" | \"scan.backfill\",\n agentName: string,\n error: unknown,\n ): void {\n appLogger.error(`${operation}.post_commit_error`, { agent: agentName, error });\n }\n\n private commitAgentState(\n operation: \"scan.refresh\" | \"scan.backfill\",\n agent: BaseAgent,\n state?: PendingAgentState,\n ): void {\n if (!state) return;\n try {\n agent.restoreSessionCacheMeta(state.meta);\n if (state.refreshedAt != null) {\n this.lastRefreshAtByAgent.set(agent.name, state.refreshedAt);\n }\n } catch (error) {\n this.reportPostCommitError(operation, agent.name, error);\n return;\n }\n try {\n state.refreshTransaction?.commit();\n } catch (error) {\n this.reportPostCommitError(operation, agent.name, error);\n }\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 cached: CachedSessions | null = null;\n let refresh: { result: AgentOperationResult; completion: ScanCompletion } = {\n result: \"failed\",\n completion: { completeness: \"complete\" },\n };\n try {\n if (this.findAgent(agentName))\n cached = this.readCachedSessionsOrWarn(\"scan.refresh\", agentName);\n refresh = await this.runRefresh(agentName, cached, startedAt);\n } catch (error) {\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 try {\n if (refresh.result !== \"failed\") {\n if (refresh.result === \"committed\")\n this.finishCommittedAgentScan(agentName, refresh.completion);\n else this.statusReporter.finishAgentScan(agentName, refresh.completion);\n }\n } catch (error) {\n if (refresh.result !== \"committed\") throw error;\n this.reportPostCommitError(\"scan.refresh\", agentName, error);\n }\n // The backfill probe touches cache state and may check agent availability;\n // either operation can throw on transient errors, but that must not\n // fail — let alone reject — an otherwise finished refresh.\n try {\n const agent = this.findAgent(agentName);\n if (agent && this.backfillScheduler.needsBackfill(agent)) {\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 refresh.result;\n }\n\n private async runRefresh(\n agentName: string,\n cached: CachedSessions | null,\n startedAt: number,\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.agentSessions(agentName);\n const refreshBaseline = cached?.sessions ?? previousSessions;\n const cacheTimestamp = cached?.timestamp ?? this.lastRefreshAtByAgent.get(agentName) ?? 0;\n if (cached) agent.restoreSessionCacheMeta(cached.meta);\n const durableMeta = agent.snapshotSessionCacheMeta();\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 refreshTransaction = await beginAgentRefresh(agent, {\n initialized: isInitialized,\n sinceTimestamp: cacheTimestamp,\n cachedSessions: refreshBaseline,\n });\n const refresh = refreshTransaction.selection;\n const availabilityDuration = refresh.availabilityDurationMs;\n let strategyResult: RefreshStrategyResult;\n try {\n if (refresh.kind === \"unavailable\") {\n strategyResult = this.refreshUnavailableAgent(agentName);\n } else if (refresh.kind === \"initialize\") {\n strategyResult = await this.initializeAgent(agent, previousSessions);\n } else if (refresh.kind === \"synchronize\") {\n strategyResult = await this.syncAgentSources(\n agent,\n cached ?? {\n sessions: refreshBaseline,\n meta: durableMeta,\n },\n startedAt,\n );\n } else {\n strategyResult = await this.refreshChangedAgent(\n agent,\n refresh,\n refreshTransaction,\n refreshBaseline,\n startedAt,\n );\n }\n } finally {\n agent.restoreSessionCacheMeta(durableMeta);\n }\n const stagedRun = strategyResult.workerRun;\n if (strategyResult.status === \"unchanged\") {\n stagedRun?.commit();\n this.commitAgentState(\"scan.refresh\", agent, strategyResult.pendingAgentState);\n return {\n result: \"unchanged\",\n completion: buildScanCompletion(strategyResult.completeness, strategyResult.sourceFailures),\n };\n }\n\n const nextSessions = attachMissingProjectIdentities(strategyResult.nextSessions);\n const persistenceDiff =\n strategyResult.publication.kind === \"changes\" ? strategyResult.publication.diff : null;\n const publicationSessions =\n strategyResult.publication.kind === \"full\"\n ? strategyResult.publication.sessions\n : nextSessions;\n const explicitRemovedSessionIds =\n strategyResult.publication.kind === \"full\"\n ? strategyResult.publication.explicitRemovedSessionIds\n : [];\n const publicationSessionIds = new Set(\n publicationSessions.map((session) => session.reference.sessionId),\n );\n const missingBaselineSessions = refreshBaseline.reduce(\n (count, session) => count + Number(!publicationSessionIds.has(session.reference.sessionId)),\n 0,\n );\n const replacementDeleteCandidates = persistenceDiff\n ? persistenceDiff.removedSessionIds.length\n : strategyResult.completeness === \"complete\"\n ? missingBaselineSessions\n : 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.reference.sessionId))\n : undefined;\n const pendingMeta = strategyResult.pendingAgentState?.meta ?? durableMeta;\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: selectCacheMeta(pendingMeta, changedSessionIds),\n }\n : {\n kind: \"full\",\n context: \"scan.refresh\",\n agentName,\n sessions: publicationSessions,\n meta: selectCacheMeta(pendingMeta),\n completeness: strategyResult.completeness,\n removedSessionIds: explicitRemovedSessionIds,\n saveCache: true,\n };\n const completion = buildScanCompletion(\n strategyResult.completeness,\n strategyResult.sourceFailures,\n );\n this.statusReporter.queueAgentPublication(agentName);\n let publication: SessionPublicationResult;\n try {\n publication = await this.sessionPublication.commit({\n context: \"scan.refresh\",\n agentName,\n sessions: nextSessions,\n candidateChangedIds:\n strategyResult.publication.kind === \"changes\"\n ? strategyResult.publication.candidateChangedIds\n : [],\n indexJob: persistentJob,\n stagedRun,\n onPublishing: () => this.statusReporter.beginAgentPublishing(agentName),\n });\n } catch (error) {\n stagedRun?.discard();\n throw error;\n }\n this.commitAgentState(\"scan.refresh\", agent, strategyResult.pendingAgentState);\n const persistDuration = performance.now() - persistStartedAt;\n const totalDurationMs = performance.now() - startedAt;\n try {\n logSearchIndexSync(\"scan.refresh\", null, { pending_paths: pendingPathCount });\n this.scheduler.recordRefreshDuration(agentName, totalDurationMs);\n const sessionUpdateCounts = countSessionUpdates(publication.event);\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: sessionUpdateCounts.newSessions,\n updated_sessions: sessionUpdateCounts.updatedSessions,\n removed_sessions: sessionUpdateCounts.removedSessions,\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 } catch (error) {\n this.reportPostCommitError(\"scan.refresh\", agentName, error);\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 const previousSessions = this.sessionIndex.agentSessions(agentName);\n if (previousSessions.length > 0) {\n appLogger.warn(\"scan.refresh.agent_unavailable\", {\n agent: agentName,\n retained_sessions: previousSessions.length,\n });\n return {\n ...this.refreshStrategyBase(previousSessions, \"partial\", {}),\n status: \"unchanged\",\n };\n }\n return {\n ...this.refreshStrategyBase([], \"partial\", {}),\n status: \"continue\",\n publication: { kind: \"full\", sessions: [], explicitRemovedSessionIds: [] },\n };\n }\n\n private async initializeAgent(\n agent: BaseAgent,\n previousSessions: IdentifiedSessionHead[],\n ): Promise<RefreshStrategyResult> {\n this.statusReporter.setScanPhase(\"initializing\");\n const scanStartedAt = performance.now();\n const scope = this.startupScanOptions();\n const workerRun = await this.runWorker(agent, previousSessions, { kind: \"full-scan\" }, scope);\n try {\n const { result } = workerRun;\n const sessions = attachMissingProjectIdentities(result.sessions);\n return {\n ...this.refreshStrategyBase(sessions, result.completeness, scope, {\n scanDuration: performance.now() - scanStartedAt,\n sourceFailures: result.sourceFailures ?? [],\n workerRun,\n pendingAgentState: { meta: result.meta, refreshedAt: Date.now() },\n }),\n status: \"continue\",\n publication: {\n kind: \"full\",\n sessions,\n explicitRemovedSessionIds: result.explicitRemovedSessionIds,\n },\n };\n } catch (error) {\n workerRun.discard();\n throw error;\n }\n }\n\n private async syncAgentSources(\n agent: BaseAgent,\n baseline: Pick<CachedSessions, \"sessions\" | \"meta\">,\n refreshStartedAt: number,\n ): Promise<RefreshStrategyResult> {\n const scanStartedAt = performance.now();\n const scope = this.startupScanOptions();\n const workerRun = await this.runWorker(\n agent,\n baseline.sessions,\n { kind: \"source-refresh\" },\n scope,\n {\n meta: baseline.meta,\n },\n );\n try {\n const { result } = workerRun;\n const sessions = attachMissingProjectIdentities(result.sessions);\n const preciseChangedIds = result.changedIds ?? [];\n const persistenceDiff = buildSessionPersistenceDiff(baseline.sessions, sessions, {\n candidateChangedIds: preciseChangedIds,\n });\n const pendingAgentState = { meta: result.meta, refreshedAt: 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 {\n ...this.refreshStrategyBase(sessions, result.completeness, scope, {\n scanDuration: performance.now() - scanStartedAt,\n workerRun,\n pendingAgentState,\n }),\n status: \"unchanged\",\n };\n }\n return {\n ...this.refreshStrategyBase(sessions, result.completeness, scope, {\n scanDuration: performance.now() - scanStartedAt,\n sourceFailures: result.sourceFailures ?? [],\n workerRun,\n pendingAgentState,\n }),\n status: \"continue\",\n publication: {\n kind: \"changes\",\n diff: persistenceDiff,\n candidateChangedIds: preciseChangedIds,\n },\n };\n } catch (error) {\n workerRun.discard();\n throw error;\n }\n }\n\n private async refreshChangedAgent(\n agent: BaseAgent,\n refresh: Exclude<AgentRefreshSelection, { kind: \"unavailable\" | \"initialize\" | \"synchronize\" }>,\n refreshTransaction: AgentRefreshTransaction,\n baseline: IdentifiedSessionHead[],\n refreshStartedAt: number,\n ): Promise<RefreshStrategyResult> {\n const scope = this.startupScanOptions();\n if (refresh.kind === \"failed\") {\n appLogger.warn(\"scan.refresh.change_check_failed\", {\n agent: agent.name,\n source_path: refresh.failure.sourcePath,\n error_class: refresh.failure.errorClass,\n message: refresh.failure.message,\n });\n return {\n ...this.refreshStrategyBase(\n baseline,\n \"partial\",\n {},\n {\n checkDuration: refresh.checkDurationMs,\n },\n ),\n status: \"unchanged\",\n };\n }\n const { check: checkResult, source } = refresh;\n const checkDuration = refresh.checkDurationMs;\n if (refresh.kind === \"recompute-derived\") {\n const scanStartedAt = performance.now();\n const workerRun = await this.runWorker(agent, baseline, { kind: \"recompute-derived\" }, {});\n try {\n const { result } = workerRun;\n const sessions = attachMissingProjectIdentities(result.sessions);\n const pendingAgentState = {\n meta: result.meta,\n refreshedAt: checkResult.timestamp,\n refreshTransaction,\n };\n const persistenceDiff = buildSessionPersistenceDiff(baseline, sessions);\n if (\n persistenceDiff.changedSessions.length === 0 &&\n persistenceDiff.removedSessionIds.length === 0\n ) {\n this.logUnchangedRefresh(agent.name, refreshStartedAt);\n return {\n ...this.refreshStrategyBase(\n sessions,\n result.completeness,\n {},\n {\n checkDuration,\n scanDuration: performance.now() - scanStartedAt,\n workerRun,\n pendingAgentState,\n },\n ),\n status: \"unchanged\",\n };\n }\n return {\n ...this.refreshStrategyBase(\n sessions,\n result.completeness,\n {},\n {\n checkDuration,\n scanDuration: performance.now() - scanStartedAt,\n sourceFailures: result.sourceFailures ?? [],\n workerRun,\n pendingAgentState,\n },\n ),\n status: \"continue\",\n publication: { kind: \"changes\", diff: persistenceDiff, candidateChangedIds: [] },\n };\n } catch (error) {\n workerRun.discard();\n throw error;\n }\n }\n const scanStartedAt = performance.now();\n if (refresh.kind === \"full-scan\") {\n const workerRun = await this.runWorker(agent, baseline, { kind: \"full-scan\" }, scope);\n try {\n const { result } = workerRun;\n const sessions = attachMissingProjectIdentities(result.sessions);\n const persistenceDiff = buildSessionPersistenceDiff(baseline, sessions, {\n // Worker-reported IDs also preserve metadata-only pricing repairs.\n candidateChangedIds: result.changedIds ?? [],\n completeness: result.completeness,\n explicitRemovedSessionIds: result.explicitRemovedSessionIds,\n });\n const strategy = this.refreshStrategyBase(sessions, result.completeness, scope, {\n checkDuration,\n scanDuration: performance.now() - scanStartedAt,\n sourceFailures: result.sourceFailures ?? [],\n workerRun,\n pendingAgentState: {\n meta: result.meta,\n refreshedAt: checkResult.timestamp,\n refreshTransaction,\n },\n });\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 { ...strategy, status: \"unchanged\" };\n }\n return {\n ...strategy,\n status: \"continue\",\n publication: { kind: \"changes\", diff: persistenceDiff, candidateChangedIds: [] },\n };\n } catch (error) {\n workerRun.discard();\n throw error;\n }\n }\n const preciseChangedIds = refresh.check.changedIds;\n this.options.workerRunner.reset(agent.name);\n const sessions = attachMissingProjectIdentities(\n await Promise.resolve(\n source.incrementalScan(baseline, preciseChangedIds, checkResult.refs, scope),\n ),\n );\n const sourceFailures = checkResult.sourceFailures ?? [];\n const completeness = resolveSessionSnapshotCompleteness(scope, sourceFailures);\n return {\n ...this.refreshStrategyBase(sessions, completeness, scope, {\n checkDuration,\n scanDuration: performance.now() - scanStartedAt,\n sourceFailures,\n pendingAgentState: {\n meta: agent.snapshotSessionCacheMeta(),\n refreshedAt: checkResult.timestamp,\n refreshTransaction,\n },\n }),\n status: \"continue\",\n publication: {\n kind: \"changes\",\n diff: buildSessionPersistenceDiff(baseline, sessions, {\n candidateChangedIds: preciseChangedIds,\n completeness,\n explicitRemovedSessionIds: preciseChangedIds,\n }),\n candidateChangedIds: preciseChangedIds,\n },\n };\n }\n\n private refreshStrategyBase(\n nextSessions: IdentifiedSessionHead[],\n completeness: SessionSnapshotCompleteness,\n scope: Pick<ScanOptions, \"from\" | \"to\">,\n overrides: Partial<Omit<RefreshStrategyBase, \"nextSessions\" | \"completeness\" | \"scope\">> = {},\n ): RefreshStrategyBase {\n return {\n nextSessions,\n checkDuration: 0,\n scanDuration: 0,\n sourceFailures: [],\n completeness,\n scope,\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 enqueueBackfill(agentName: string): void {\n this.backfillScheduler.enqueue(agentName);\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 cached = this.readCachedSessionsOrWarn(\"scan.backfill\", agentName);\n const baseline = cached?.sessions ?? this.sessionIndex.agentSessions(agentName);\n const meta = cached?.meta ?? buildAgentCacheMeta(agent);\n const backfillCursor = getAgentFullSyncCursor(agentName);\n if (cached) agent.restoreSessionCacheMeta(cached.meta);\n let workerRun: StagedWorkerRun | undefined;\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 kind: \"backfill\",\n cursor: backfillCursor,\n checkpoint: \"durable\",\n };\n appLogger.info(\"scan.backfill.started\", {\n agent: agentName,\n cursor: backfillCursor ?? undefined,\n durable_checkpoints: operation.checkpoint === \"durable\",\n });\n workerRun = 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 const { result } = workerRun;\n const fullSessions = attachMissingProjectIdentities(result.sessions);\n const completion = buildScanCompletion(result.completeness, result.sourceFailures ?? []);\n this.statusReporter.flushProgressStatus(`backfill:${agentName}`);\n const updatePublicationPhase = (\n phase: \"publish-queued\" | \"publishing\" | \"indexing\" | \"committing\",\n ) => {\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 await this.sessionPublication.commit({\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: result.meta,\n completeness: result.completeness,\n removedSessionIds: result.explicitRemovedSessionIds,\n saveCache: true,\n },\n stagedRun: workerRun,\n onPublishing: () => updatePublicationPhase(\"publishing\"),\n onPublicationProgress: ({ stage }) => {\n if (stage === \"prepared\") updatePublicationPhase(\"indexing\");\n if (stage === \"search_staged\") updatePublicationPhase(\"committing\");\n },\n onCommitted: () => {\n if (completion.completeness === \"partial\") {\n this.backfills.recordCompletion(attempt, completion);\n }\n },\n });\n this.commitAgentState(\"scan.backfill\", agent, { meta: result.meta });\n try {\n if (completion.completeness === \"complete\" && !markAgentFullSyncCompleted(agentName)) {\n appLogger.warn(\"scan.backfill.completion_not_durable\", { agent: agentName });\n }\n appLogger.info(\n completion.completeness === \"partial\" ? \"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 } catch (error) {\n this.reportPostCommitError(\"scan.backfill\", agentName, error);\n }\n return \"committed\";\n } catch (error) {\n workerRun?.discard();\n appLogger.error(\"scan.backfill.error\", { agent: agentName, error });\n console.error(`[${agentName}] Backfill failed:`, error);\n return \"failed\";\n }\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 { basename, dirname, isAbsolute, join, relative, resolve } from \"node:path\";\nimport type { SessionWatchPlan } from \"@codesesh/core/runtime/agents\";\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 ignoredFileNames?: readonly 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({\n agentName: agent.name,\n targetPath,\n ignoredFileNames: target.ignoredFileNames,\n });\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(\n (scope) =>\n isRelatedPath(changedPath, scope.targetPath) &&\n !(\n scope.ignoredFileNames?.includes(basename(changedPath)) &&\n changedPath !== scope.targetPath &&\n isSameOrChildPath(scope.targetPath, changedPath)\n ),\n )\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 { getPricingGeneration } from \"@codesesh/core/runtime/pricing\";\nimport {\n type AgentScanProgress,\n type SessionCacheMeta,\n type SessionSourceFailure,\n} from \"@codesesh/core/runtime/agents\";\nimport {\n type ScanOptions,\n type SessionHead,\n type PersistedSessionHeadChange,\n type SessionSnapshotCompleteness,\n} from \"@codesesh/core/runtime/discovery\";\nimport { appLogger, type LogContext } 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\";\nimport { terminateWorkerAfterLogDrain } from \"./worker-log-drain.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 StagedWorkerRun {\n readonly result: WorkerResult;\n commit(): void;\n discard(): void;\n}\n\nexport interface WorkerRunner {\n readonly activeCount: number;\n run(agentName: string, payload: WorkerPayload): Promise<StagedWorkerRun>;\n reset(agentName: string): void;\n shutdown(): Promise<void>;\n}\n\ninterface PendingRequest {\n resolve: (run: StagedWorkerRun) => void;\n reject: (error: Error) => void;\n payload: WorkerPayload;\n generation: number;\n logContext: LogContext;\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; logContext: LogContext } | 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.reference.sessionId);\n const retained = previousSessions.filter(\n (session) => !replacedIds.has(session.reference.sessionId),\n );\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 retirements = new Set<Promise<number>>();\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<StagedWorkerRun> {\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 logContext: appLogger.captureContext(),\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 logContext: request.logContext ?? {},\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 reset(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 for (const slot of slots) this.retireWorker(slot.worker);\n await Promise.allSettled(this.retirements);\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 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 appLogger.restoreContext(this.slotLogContext(slot), () => {\n this.closeWorker(agentName, slot, toError(error));\n void this.retireWorker(worker);\n });\n });\n worker.on(\"exit\", (code) => {\n appLogger.restoreContext(this.slotLogContext(slot), () => {\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 });\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 appLogger.restoreContext(pending.logContext, () => {\n this.handlePendingMessage(slot, message, pending);\n });\n }\n\n private handlePendingMessage(\n slot: WorkerSlot,\n message: ScanRefreshWorkerMessage,\n pending: PendingRequest,\n ): void {\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.reference.sessionId);\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 logContext: pending.logContext,\n };\n pending.resolve(this.createStagedRun(slot, message.requestId, message.generation, result));\n } catch (error) {\n pending.reject(toError(error));\n this.invalidateWorker(slot.agentName, slot);\n }\n }\n\n private createStagedRun(\n slot: WorkerSlot,\n requestId: number,\n generation: number,\n result: WorkerResult,\n ): StagedWorkerRun {\n let finalized = false;\n return {\n result,\n commit: () => {\n if (finalized) return;\n finalized = true;\n this.commitStagedRun(slot, requestId, generation);\n },\n discard: () => {\n if (finalized) return;\n finalized = true;\n this.discardStagedRun(slot, requestId, generation);\n },\n };\n }\n\n private commitStagedRun(slot: WorkerSlot, requestId: number, generation: number): void {\n const awaiting = slot.awaitingCommit;\n if (\n this.workers.get(slot.agentName) !== slot ||\n awaiting?.requestId !== requestId ||\n awaiting.generation !== generation\n ) {\n return;\n }\n const request: ScanRefreshWorkerCommitRequest = {\n type: \"commit\",\n requestId,\n generation,\n logContext: awaiting.logContext,\n };\n try {\n slot.worker.postMessage(request);\n slot.awaitingCommit = null;\n slot.generation += 1;\n } catch {\n this.invalidateWorker(slot.agentName, slot);\n }\n }\n\n private discardStagedRun(slot: WorkerSlot, requestId: number, generation: number): void {\n const awaiting = slot.awaitingCommit;\n if (\n this.workers.get(slot.agentName) === slot &&\n awaiting?.requestId === requestId &&\n awaiting.generation === generation\n ) {\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 slotLogContext(slot: WorkerSlot): LogContext {\n for (const pending of slot.pending.values()) return pending.logContext;\n return slot.awaitingCommit?.logContext ?? {};\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 this.retireWorker(slot.worker);\n }\n\n private retireWorker(worker: Worker): Promise<number> {\n const retirement = terminateWorkerAfterLogDrain(worker);\n this.retirements.add(retirement);\n void retirement.finally(() => this.retirements.delete(retirement)).catch(() => undefined);\n return retirement;\n }\n}\n","import { consola } from \"consola\";\nimport type { BaseAgent } from \"@codesesh/core/runtime/agents\";\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 type IdentifiedSessionHead,\n type LiveSnapshot,\n} from \"@codesesh/core/runtime/discovery\";\nimport { getAgentInfoMap } from \"@codesesh/core/runtime/agents\";\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: IdentifiedSessionHead[];\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((failure) =>\n failure.operation === \"read\"\n ? `[${failure.agentName}] Cache read failed; durable baseline is unavailable`\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/runtime/discovery\";\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","import { publishPendingPricing, refreshPricingCache } from \"@codesesh/core/runtime/pricing\";\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 /** Waits for the bounded refresh and publishes prices before scanning. */\n ready(): Promise<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 async ready() {\n await completion;\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":["resolve","Hono","randomUUID","randomUUID","resolve","snapshot","projects","Worker","Worker","resolve","sessions","aliases","randomUUID","isIP","isIP","__dirname","resolve","Hono","randomUUID","existsSync","fileURLToPath","existsSync","fileURLToPath","Worker","toError","resolve","SHUTDOWN_ERROR_MESSAGE","toError","Worker","existsSync","fileURLToPath","toError","key","currentPhase","nextPhase","toError","scanStartedAt","sessions","existsSync","dirname","join","resolve","resolve","existsSync","dirname","platform","join","agents","Worker","SHUTDOWN_ERROR_MESSAGE","resolve","toError","Worker","existsSync","fileURLToPath","readFileSync","resolve","dirname","fileURLToPath"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/cli-exit.ts","../src/server.ts","../src/api/routes.ts","../src/project-identity-resolver.ts","../src/api/query-params.ts","../src/api/handler-support.ts","../src/api/snapshot-pagination.ts","../src/api/snapshot-aggregation.ts","../src/api/catalog-handlers.ts","../src/time-window-resolution.ts","../../core/src/search/session-search.ts","../../core/src/state/database.ts","../../core/src/state/bookmarks.ts","../../core/src/state/session-aliases.ts","../../core/src/bookmarks/materialize.ts","../src/api/session-aliases-view.ts","../src/api/dashboard-handler.ts","../src/api/search-result-merge.ts","../src/api/search-handlers.ts","../src/session-detail-loader.ts","../src/api/session-detail-stream.ts","../src/api/session-handlers.ts","../src/api/request-payloads.ts","../src/api/client-log-handler.ts","../src/api/bookmark-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-backfill-scheduler.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/session-publication.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 { closeLoggerBeforeTermination } from \"./cli-exit.js\";\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 resolvePublicOrigin,\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 } from \"@codesesh/core/runtime/agents\";\nimport { perf } from \"@codesesh/core/runtime/diagnostics\";\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 appLogger.flushSync();\n throw reason;\n});\nprocess.on(\"uncaughtExceptionMonitor\", (error, origin) => {\n appLogger.error(\"process.uncaught_exception\", { error, exception_origin: origin });\n appLogger.flushSync();\n});\n\nconst closeApplicationLog = (exitCode: string | number) =>\n closeLoggerBeforeTermination(() => appLogger.close(), exitCode);\n\nlet shutdownOnSignal: (signal: NodeJS.Signals) => void = (signal) => {\n appLogger.info(\"cli.shutdown\", { signal, phase: \"startup\" });\n appLogger.flushSync();\n process.exit(0);\n};\nconst dispatchSignal = (signal: NodeJS.Signals) => shutdownOnSignal(signal);\nprocess.once(\"SIGINT\", dispatchSignal);\nprocess.once(\"SIGTERM\", dispatchSignal);\nprocess.once(\"SIGHUP\", dispatchSignal);\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 \"public-url\": {\n type: \"string\",\n description: \"Public HTTPS origin served by the trusted reverse proxy\",\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 local calendar 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 on or after this date, YYYY-MM-DD (overrides --days)\",\n },\n to: {\n type: \"string\",\n description: \"Sessions active on or 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 let publicOrigin: string | undefined;\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 publicOrigin = resolvePublicOrigin(args[\"public-url\"] as string | undefined, transport);\n } catch (error) {\n console.error(error instanceof Error ? error.message : String(error));\n process.exit(1);\n }\n\n if (resolveRemoteAccessPolicy(hostname, transport).remoteAccessRequired && !remoteAccess) {\n console.error(\n `Refusing to expose CodeSesh on ${hostname} without explicit remote access. 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 public_url: publicOrigin,\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/runtime/discovery\");\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 await closeApplicationLog(1);\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 await pricingRefresh.ready();\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 await pricingRefresh.cancel();\n const scanFailureDiagnostics = formatScanFailureDiagnostics(result);\n if (scanFailureDiagnostics.length > 0) {\n for (const diagnostic of scanFailureDiagnostics) console.error(diagnostic);\n process.exitCode = 1;\n } else {\n for (const diagnostic of formatCacheFailureDiagnostics(result)) console.error(diagnostic);\n const output = buildSessionIndexOutput(result, {\n from: listDefaultFrom,\n to: listDefaultTo,\n });\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 }\n // Worker threads and the SQLite connections hold the event loop open;\n // without this the one-shot process prints its output and never exits.\n await store.shutdown();\n await closeApplicationLog(process.exitCode ?? 0);\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 publicUrl: publicOrigin,\n });\n } catch (error) {\n console.error(getServerStartupErrorMessage(error, port));\n await closeApplicationLog(1);\n process.exit(1);\n }\n\n const { url } = app;\n if (!jsonOnly) {\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 await closeApplicationLog(0);\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 shutdownOnSignal = (signal: NodeJS.Signals) => {\n shutdown(signal).catch(async (error) => {\n appLogger.error(\"cli.shutdown_failed\", { signal, error });\n await closeApplicationLog(1);\n process.exit(1);\n });\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\nconst runCliCommand = main.run;\nif (!runCliCommand) throw new Error(\"CLI command is missing its runner\");\nmain.run = async (context) => {\n try {\n return await runCliCommand(context);\n } catch (error) {\n appLogger.error(\"cli.fatal\", { error });\n await closeApplicationLog(1);\n throw error;\n }\n};\n\nif (process.argv.slice(2).includes(\"-v\")) {\n console.log(VERSION);\n process.exit(0);\n}\n\nrunMain(main);\n","const LOG_CLOSE_TIMEOUT_MS = 2_000;\nconst LOG_CLOSE_TIMEOUT_MESSAGE = \"[codesesh] Timed out closing application log; forcing exit\\n\";\n\nexport async function closeLoggerBeforeTermination(\n closeLogger: () => Promise<void>,\n exitCode: string | number,\n): Promise<void> {\n let watchdog: ReturnType<typeof setTimeout> | undefined;\n const timedOut = new Promise<false>((resolve) => {\n watchdog = setTimeout(() => resolve(false), LOG_CLOSE_TIMEOUT_MS);\n });\n\n try {\n const closed = await Promise.race([closeLogger().then(() => true as const), timedOut]);\n if (closed) return;\n try {\n process.stderr.write(LOG_CLOSE_TIMEOUT_MESSAGE);\n } finally {\n process.exit(exitCode);\n }\n } finally {\n if (watchdog) clearTimeout(watchdog);\n }\n}\n","import { Hono, type Context } from \"hono\";\nimport { matchedRoutes } from \"hono/route\";\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 { randomUUID } from \"node:crypto\";\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/scan-sources.js\";\nimport { createApiRoutes, type ApiRouteOptions } from \"./api/routes.js\";\nimport { appLogger } from \"./logging.js\";\nimport { ThreadSessionDetailLoader } from \"./session-detail-loader.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 ACCESS_TOKEN_QUERY_PARAM,\n accessTokenAuth,\n createAccessToken,\n requireProxyTls,\n resolvePublicOrigin,\n resolveRemoteAccessPolicy,\n resolveRemoteTransport,\n type RemoteTransport,\n} from \"./remote-access.js\";\nimport type { ScanEventSource } from \"./scan-source.js\";\nimport { CODESESH_OPERATION_ID_HEADER, CODESESH_REQUEST_ID_HEADER } from \"@codesesh/core/contract\";\n\nconst MAX_API_REQUEST_BYTES = 1024 * 1024;\nconst SERVER_CLOSE_GRACE_MS = 1_000;\nconst OPERATION_ID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\nconst OBSERVABLE_QUERY_KEYS = new Set([\n \"agent\",\n \"costMax\",\n \"costMin\",\n \"cursor\",\n \"cwd\",\n \"days\",\n \"fileActivity\",\n \"from\",\n \"kind\",\n \"limit\",\n \"messageCursor\",\n \"path\",\n \"project\",\n \"projectKey\",\n \"projectKind\",\n \"q\",\n \"sessionId\",\n \"tag\",\n \"to\",\n \"tool\",\n]);\n\nexport interface CreateServerOptions {\n defaultSessionFrom?: number;\n defaultSessionTo?: number;\n defaultSessionDays?: number;\n portFallbackAttempts?: number;\n hostname?: string;\n remoteAccess?: boolean;\n accessToken?: string;\n publicUrl?: 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\nfunction optionalOperationId(value: string | undefined): string | undefined {\n return value && OPERATION_ID_PATTERN.test(value) ? value : undefined;\n}\n\nfunction errorStatus(error: unknown): number {\n try {\n if (typeof error !== \"object\" || error === null || !(\"status\" in error)) return 500;\n const status = error.status;\n if (typeof status === \"number\" && status >= 400 && status <= 599) return status;\n } catch {}\n return 500;\n}\n\nfunction matchedRoute(context: Context): string {\n try {\n return (\n matchedRoutes(context)\n .map((route) => route.path)\n .filter((path) => !path.includes(\"*\"))\n .at(-1) ?? \"<unmatched>\"\n );\n } catch {\n return \"<unmatched>\";\n }\n}\n\nfunction queryKeys(url: string): string[] {\n try {\n return [...new Set(new URL(url).searchParams.keys())]\n .filter((key) => OBSERVABLE_QUERY_KEYS.has(key))\n .toSorted();\n } catch {\n return [];\n }\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; listenerUrl: 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 publicOrigin = resolvePublicOrigin(options.publicUrl, transport);\n const accessToken = options.accessToken || createAccessToken();\n const loopbackAuthorityEnabled = !accessPolicy.remoteAccessRequired;\n const shutdownController = new AbortController();\n const projectIdentityResolver =\n options.projectIdentityResolver ?? createProjectIdentityResolver();\n const sessionDetailLoader = new ThreadSessionDetailLoader();\n let actualPort: number | null = null;\n\n appLogger.info(\"server.access_policy\", {\n bind_category: accessPolicy.bindCategory,\n transport: transport.kind,\n authentication: \"token\",\n loopback_authority: loopbackAuthorityEnabled ? \"enabled\" : \"disabled\",\n });\n\n if (accessPolicy.remoteAccessRequired && !options.remoteAccess && !options.accessToken) {\n throw new Error(\n `Refusing to expose CodeSesh on ${hostname} without explicit remote access. 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 app.use(\"*\", async (c, next) => {\n const startedAt = performance.now();\n const requestId = randomUUID();\n const actualPath = c.req.path;\n const operationId = optionalOperationId(c.req.header(CODESESH_OPERATION_ID_HEADER));\n const context =\n actualPath === \"/api/events\"\n ? {}\n : { request_id: requestId, ...(operationId ? { operation_id: operationId } : {}) };\n c.header(CODESESH_REQUEST_ID_HEADER, requestId);\n\n return appLogger.restoreContext(context, async () => {\n let thrown: unknown;\n try {\n await next();\n } catch (error) {\n thrown = error;\n throw error;\n } finally {\n const requestError = thrown ?? c.error;\n appLogger.info(\"http.request\", {\n method: c.req.method,\n route: matchedRoute(c),\n query_keys: queryKeys(c.req.url),\n status: requestError == null ? c.res.status : errorStatus(requestError),\n duration_ms: Math.round(performance.now() - startedAt),\n ...(requestError == null ? {} : { error: requestError }),\n });\n }\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 route: \"<rejected>\",\n reason: decision.reason,\n authority_present: Boolean(decision.authority),\n });\n return c.json({ error: \"Loopback request authority rejected\" }, 403);\n }\n await next();\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 app.use(\"/api/*\", accessTokenAuth(accessToken));\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 loadSessionDetail: sessionDetailLoader.load,\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 // The backend stays HTTP behind a trusted proxy; its separately configured\n // public origin is used only for browser startup.\n const scheme = transport.kind === \"tls\" ? \"https\" : \"http\";\n const listenerUrl =\n accessPolicy.bindCategory === \"loopback\"\n ? `${scheme}://localhost:${actualPort}`\n : `${scheme}://${hostname}:${actualPort}`;\n const url = `${publicOrigin ?? listenerUrl}/?${ACCESS_TOKEN_QUERY_PARAM}=${encodeURIComponent(accessToken)}`;\n appLogger.info(\"server.listen\", {\n port: actualPort,\n requested_port: port,\n hostname,\n public_origin: publicOrigin,\n remote_access: accessPolicy.remoteAccessRequired,\n transport: transport.kind,\n });\n\n if (accessPolicy.remoteAccessRequired) {\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 listenerUrl,\n shutdown: async () => {\n appLogger.info(\"server.shutdown\", { port: actualPort });\n shutdownController.abort();\n try {\n await sessionDetailLoader.shutdown();\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 { randomUUID } from \"node:crypto\";\nimport {\n handleGetAgents,\n handleGetConfig,\n handleGetProjects,\n handleGetScanStatus,\n} from \"./catalog-handlers.js\";\nimport { handleGetDashboard } from \"./dashboard-handler.js\";\nimport { handleGetFileActivity, handleSearchSessions } from \"./search-handlers.js\";\nimport { handleGetSessions, handleGetSessionData } from \"./session-handlers.js\";\nimport { handlePostClientLog } from \"./client-log-handler.js\";\nimport type { ScanResultSource } from \"./scan-sources.js\";\nimport type { SessionListDefaults } from \"./query-params.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 { appLogger } from \"../logging.js\";\nimport type { SessionDetailLoader } from \"../session-detail-loader.js\";\nimport { loadAliasView } from \"./session-aliases-view.js\";\nimport { SseEventBuffer } from \"./sse-event-buffer.js\";\n\nexport const MAX_ACTIVE_SSE_CONNECTIONS = 32;\n\ntype SseConnectionCloseReason =\n | \"client_cancelled\"\n | \"client_disconnected\"\n | \"client_too_slow\"\n | \"server_shutdown\"\n | \"setup_failed\";\n\nexport interface ApiRouteOptions {\n defaultSessionFrom?: number;\n defaultSessionTo?: number;\n defaultSessionDays?: number;\n shutdownSignal?: AbortSignal;\n projectIdentityResolver?: ProjectIdentityResolver;\n loadSessionDetail?: SessionDetailLoader;\n}\n\ninterface SseConnectionBudget {\n acquire(): (() => void) | null;\n activeCount(): number;\n}\n\nfunction createSseConnectionBudget(maxConnections: number): SseConnectionBudget {\n let activeConnections = 0;\n return {\n acquire() {\n if (activeConnections >= maxConnections) return null;\n activeConnections += 1;\n let released = false;\n return () => {\n if (released) return;\n released = true;\n activeConnections -= 1;\n };\n },\n activeCount() {\n return activeConnections;\n },\n };\n}\n\nfunction createSseResponse(\n eventSource: ScanEventSource,\n requestSignal: AbortSignal,\n shutdownSignal: AbortSignal | undefined,\n closeConnection: (reason: SseConnectionCloseReason) => void,\n): 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 disconnectStream = () => {};\n let shutdownStream = () => {};\n let heartbeat: ReturnType<typeof setInterval> | undefined;\n let buffer: SseEventBuffer | undefined;\n\n const cleanup = (reason: SseConnectionCloseReason) => {\n if (isClosed) return false;\n isClosed = true;\n buffer?.close();\n if (heartbeat) clearInterval(heartbeat);\n unsubscribeSessions();\n unsubscribeScanStatus();\n requestSignal.removeEventListener(\"abort\", disconnectStream);\n shutdownSignal?.removeEventListener(\"abort\", shutdownStream);\n closeConnection(reason);\n return true;\n };\n disconnectStream = () => {\n if (cleanup(\"client_disconnected\")) controller.close();\n };\n shutdownStream = () => {\n if (cleanup(\"server_shutdown\")) controller.close();\n };\n buffer = new SseEventBuffer(controller, () => {\n if (cleanup(\"client_too_slow\")) controller.error(new Error(\"SSE client fell behind\"));\n });\n drainStream = () => buffer.drain();\n\n try {\n buffer.enqueue(\"connected\", { timestamp: Date.now() });\n buffer.enqueueScanStatus(eventSource.getScanStatus());\n\n unsubscribeSessions = eventSource.subscribe((event) => {\n if (isClosed) return;\n const aliases = loadAliasView();\n buffer?.enqueue(event.type, {\n ...event,\n changedSessionHeads: event.changedSessionHeads.map((change) => ({\n ...change,\n session: aliases.decorate(change.session, change.reference),\n })),\n projectionRelatedSessionHeads: event.projectionRelatedSessionHeads?.map((change) => ({\n ...change,\n session: aliases.decorate(change.session, change.reference),\n })),\n });\n });\n unsubscribeScanStatus = eventSource.subscribeScanStatus((event) => {\n buffer?.enqueueScanStatus(event);\n });\n\n heartbeat = setInterval(() => buffer?.enqueueHeartbeat(), 15000);\n cancelStream = () => {\n cleanup(\"client_cancelled\");\n };\n\n if (shutdownSignal?.aborted) shutdownStream();\n else if (requestSignal.aborted) disconnectStream();\n else {\n requestSignal.addEventListener(\"abort\", disconnectStream, { once: true });\n shutdownSignal?.addEventListener(\"abort\", shutdownStream, { once: true });\n }\n } catch (error) {\n cleanup(\"setup_failed\");\n throw error;\n }\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 sseConnections = createSseConnectionBudget(MAX_ACTIVE_SSE_CONNECTIONS);\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, scanSource, listDefaults, options.projectIdentityResolver),\n );\n api.get(\"/sessions/:agent/:id\", (c) =>\n handleGetSessionData(c, scanSource, options.loadSessionDetail),\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 releaseConnection = sseConnections.acquire();\n if (!releaseConnection) {\n appLogger.warn(\"api.sse.connection_limit_reached\", {\n active_connections: sseConnections.activeCount(),\n connection_limit: MAX_ACTIVE_SSE_CONNECTIONS,\n });\n c.header(\"Retry-After\", \"1\");\n return c.json({ error: \"Too many active event streams\" }, 429);\n }\n const connectionId = randomUUID();\n const connectedAt = performance.now();\n let isClosed = false;\n appLogger.info(\"api.sse.connection.opened\", {\n connection_id: connectionId,\n active_connections: sseConnections.activeCount(),\n connection_limit: MAX_ACTIVE_SSE_CONNECTIONS,\n });\n const closeConnection = (reason: SseConnectionCloseReason) => {\n if (isClosed) return;\n isClosed = true;\n releaseConnection();\n appLogger.info(\"api.sse.connection.closed\", {\n connection_id: connectionId,\n close_reason: reason,\n duration_ms: Math.max(0, Math.round(performance.now() - connectedAt)),\n active_connections: sseConnections.activeCount(),\n });\n };\n try {\n return createSseResponse(\n eventSource,\n c.req.raw.signal,\n options.shutdownSignal,\n closeConnection,\n );\n } catch (error) {\n closeConnection(\"setup_failed\");\n throw error;\n }\n });\n }\n\n return api;\n}\n","import { Worker } from \"node:worker_threads\";\nimport {\n normalizeProjectDirectory,\n type ProjectIdentityProjection,\n} from \"@codesesh/core/runtime/projects\";\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;\nexport const PROJECT_IDENTITY_RESOLVER_MAX_QUEUED_REQUESTS = 8;\nexport const PROJECT_IDENTITY_RESOLVER_TIMEOUT_MS = 2_000;\n\nconst SHUTDOWN_ERROR_MESSAGE = \"Project identity resolver shut down\";\n\nexport interface ProjectIdentityResolver {\n resolve(cwd: string, signal?: AbortSignal): Promise<ProjectIdentityProjection>;\n shutdown(): Promise<void>;\n}\n\nexport interface ProjectIdentityResolverOptions {\n maxWorkers?: number;\n maxQueuedRequests?: number;\n timeoutMs?: number;\n}\n\nexport class ProjectIdentityQueueFullError extends Error {\n constructor() {\n super(\"Project identity resolver queue is full\");\n this.name = \"ProjectIdentityQueueFullError\";\n }\n}\n\nexport class ProjectIdentityTimeoutError extends Error {\n constructor() {\n super(\"Project identity resolution timed out\");\n this.name = \"ProjectIdentityTimeoutError\";\n }\n}\n\nexport class ProjectIdentityRequestAbortedError extends Error {\n constructor() {\n super(\"Project identity resolution was aborted\");\n this.name = \"ProjectIdentityRequestAbortedError\";\n }\n}\n\ninterface RequestSubscriber {\n resolve: (projection: ProjectIdentityProjection) => void;\n reject: (error: Error) => void;\n signal?: AbortSignal;\n abortHandler?: () => void;\n}\n\ninterface PendingRequest {\n requestId: number;\n cwd: string;\n subscribers: Set<RequestSubscriber>;\n timeout: ReturnType<typeof setTimeout> | null;\n}\n\ninterface WorkerSlot {\n worker: Worker;\n pending: PendingRequest | null;\n closed: boolean;\n retirement: Promise<void> | null;\n}\n\nfunction toError(error: unknown): Error {\n return error instanceof Error ? error : new Error(String(error));\n}\n\nfunction requireSafeInteger(value: number, minimum: number, name: string): number {\n if (!Number.isSafeInteger(value) || value < minimum) {\n throw new RangeError(`${name} must be a safe integer greater than or equal to ${minimum}`);\n }\n return value;\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 readonly requestsByDirectory = new Map<string, PendingRequest>();\n private readonly maxWorkers: number;\n private readonly maxOutstandingRequests: number;\n private readonly timeoutMs: number;\n private nextRequestId = 1;\n private isShuttingDown = false;\n\n constructor(\n private readonly workerUrl: URL,\n options: ProjectIdentityResolverOptions = {},\n ) {\n this.maxWorkers = requireSafeInteger(\n options.maxWorkers ?? PROJECT_IDENTITY_RESOLVER_MAX_WORKERS,\n 1,\n \"maxWorkers\",\n );\n const maxQueuedRequests = requireSafeInteger(\n options.maxQueuedRequests ?? PROJECT_IDENTITY_RESOLVER_MAX_QUEUED_REQUESTS,\n 0,\n \"maxQueuedRequests\",\n );\n this.timeoutMs = requireSafeInteger(\n options.timeoutMs ?? PROJECT_IDENTITY_RESOLVER_TIMEOUT_MS,\n 1,\n \"timeoutMs\",\n );\n this.maxOutstandingRequests = requireSafeInteger(\n this.maxWorkers + maxQueuedRequests,\n this.maxWorkers,\n \"request capacity\",\n );\n }\n\n resolve(cwd: string, signal?: AbortSignal): Promise<ProjectIdentityProjection> {\n if (this.isShuttingDown) return Promise.reject(new Error(SHUTDOWN_ERROR_MESSAGE));\n if (signal?.aborted) return Promise.reject(new ProjectIdentityRequestAbortedError());\n\n const normalizedCwd = normalizeProjectDirectory(cwd);\n let request = this.requestsByDirectory.get(normalizedCwd);\n if (!request) {\n if (this.requestsByDirectory.size >= this.maxOutstandingRequests) {\n appLogger.warn(\"project_identity.queue.full\", {\n active_workers: this.activeWorkerCount(),\n queued_requests: this.queue.length,\n request_capacity: this.maxOutstandingRequests,\n });\n return Promise.reject(new ProjectIdentityQueueFullError());\n }\n request = {\n requestId: this.nextRequestId++,\n cwd: normalizedCwd,\n subscribers: new Set(),\n timeout: null,\n };\n this.requestsByDirectory.set(normalizedCwd, request);\n this.queue.push(request);\n }\n\n const resolution = this.subscribe(request, signal);\n this.pump();\n return resolution;\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 while (this.queue.length > 0) this.rejectRequest(this.queue[0]!, error);\n\n const retirements = [...this.workers].map((slot) => this.retireWorker(slot, error));\n await Promise.allSettled(retirements);\n this.workers.clear();\n }\n\n private subscribe(\n request: PendingRequest,\n signal?: AbortSignal,\n ): Promise<ProjectIdentityProjection> {\n return new Promise((resolve, reject) => {\n const subscriber: RequestSubscriber = { resolve, reject, signal };\n request.subscribers.add(subscriber);\n if (!signal) return;\n\n subscriber.abortHandler = () => this.abortSubscriber(request, subscriber);\n signal.addEventListener(\"abort\", subscriber.abortHandler, { once: true });\n });\n }\n\n private abortSubscriber(request: PendingRequest, subscriber: RequestSubscriber): void {\n if (!request.subscribers.delete(subscriber)) return;\n this.removeAbortHandler(subscriber);\n subscriber.reject(new ProjectIdentityRequestAbortedError());\n if (request.subscribers.size > 0) return;\n\n const slot = this.workerForRequest(request);\n if (slot) slot.pending = null;\n this.releaseRequest(request);\n if (slot) void this.retireWorker(slot);\n else this.pump();\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 request.timeout = setTimeout(() => {\n if (slot.pending !== request || slot.closed) return;\n appLogger.warn(\"project_identity.request.timeout\", {\n request_id: request.requestId,\n timeout_ms: this.timeoutMs,\n });\n void this.retireWorker(slot, new ProjectIdentityTimeoutError());\n }, this.timeoutMs);\n request.timeout.unref();\n try {\n slot.worker.postMessage({\n type: \"resolve\",\n requestId: request.requestId,\n cwd: request.cwd,\n } satisfies ProjectIdentityWorkerRequest);\n } catch (error) {\n void this.retireWorker(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 activeWorkerCount(): number {\n let count = 0;\n for (const slot of this.workers) {\n if (!slot.closed && slot.pending != null) count += 1;\n }\n return count;\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 = {\n worker,\n pending: null,\n closed: false,\n retirement: null,\n };\n this.workers.add(slot);\n worker.on(\"message\", (message: unknown) => {\n if (appLogger.consumeWorkerMessage(message)) return;\n this.handleWorkerMessage(slot, message);\n });\n worker.on(\"error\", (error) => {\n void this.retireWorker(slot, toError(error));\n });\n worker.on(\"exit\", (code) => {\n if (!slot.closed) {\n this.closeExitedWorker(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\") this.resolveRequest(request, message.projection);\n else this.rejectRequest(request, new Error(message.error));\n this.pump();\n }\n\n private closeExitedWorker(slot: WorkerSlot, error: Error): void {\n slot.closed = true;\n this.workers.delete(slot);\n const request = slot.pending;\n slot.pending = null;\n if (request) this.rejectRequest(request, error);\n if (!this.isShuttingDown) this.pump();\n }\n\n private retireWorker(slot: WorkerSlot, error?: Error): Promise<void> {\n if (slot.retirement) return slot.retirement;\n slot.closed = true;\n const request = slot.pending;\n slot.pending = null;\n if (request && error) this.rejectRequest(request, error);\n\n const retirement = (async () => {\n try {\n await slot.worker.terminate();\n } catch (terminationError) {\n appLogger.warn(\"project_identity.worker.termination_failed\", {\n error: toError(terminationError).message,\n });\n } finally {\n this.workers.delete(slot);\n if (!this.isShuttingDown) this.pump();\n }\n })();\n slot.retirement = retirement;\n return retirement;\n }\n\n private workerForRequest(request: PendingRequest): WorkerSlot | null {\n for (const slot of this.workers) {\n if (slot.pending === request) return slot;\n }\n return null;\n }\n\n private resolveRequest(request: PendingRequest, projection: ProjectIdentityProjection): void {\n this.releaseRequest(request);\n for (const subscriber of request.subscribers) {\n this.removeAbortHandler(subscriber);\n subscriber.resolve(projection);\n }\n request.subscribers.clear();\n }\n\n private rejectRequest(request: PendingRequest, error: Error): void {\n this.releaseRequest(request);\n for (const subscriber of request.subscribers) {\n this.removeAbortHandler(subscriber);\n subscriber.reject(error);\n }\n request.subscribers.clear();\n }\n\n private releaseRequest(request: PendingRequest): void {\n if (request.timeout) clearTimeout(request.timeout);\n request.timeout = null;\n if (this.requestsByDirectory.get(request.cwd) === request) {\n this.requestsByDirectory.delete(request.cwd);\n }\n const queueIndex = this.queue.indexOf(request);\n if (queueIndex >= 0) this.queue.splice(queueIndex, 1);\n }\n\n private removeAbortHandler(subscriber: RequestSubscriber): void {\n if (subscriber.signal && subscriber.abortHandler) {\n subscriber.signal.removeEventListener(\"abort\", subscriber.abortHandler);\n }\n }\n\n private rejectQueued(error: Error): void {\n while (this.queue.length > 0) this.rejectRequest(this.queue[0]!, 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","/**\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/runtime/discovery\";\nimport {\n filterSessionTreeByActivityWindow,\n isSmartTag,\n type FileActivityKind,\n type SearchRequestOptions,\n} from \"@codesesh/core/runtime/discovery\";\nimport { isProjectIdentityKind, type ProjectIdentityRef } from \"@codesesh/core/runtime/projects\";\nimport type { TimeWindow } from \"../time-window-resolution.js\";\n\nexport type SessionListDefaults = TimeWindow;\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 PROJECT_PAGE_LIMIT_POLICY: LimitPolicy = { defaultValue: 100, maxValue: 250 };\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 | {\n kind: \"valid\";\n from: number | undefined;\n to: number | undefined;\n hasExplicitFrom: boolean;\n }\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 {\n kind: \"valid\",\n from: from.value,\n to: to.value,\n hasExplicitFrom: from.kind === \"valid\",\n };\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\nexport function 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.map((value) => value.toLowerCase()).filter(isSmartTag);\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<T extends SessionHead>(\n sessions: T[],\n from: number | undefined,\n to: number | undefined,\n): T[] {\n return filterSessionTreeByActivityWindow(sessions, from, to);\n}\n","import { getAgentInfoMap } from \"@codesesh/core/runtime/agents\";\nimport type { IdentifiedSessionHead } from \"@codesesh/core/runtime/discovery\";\nimport {\n createProjectScopeMatcherFromIdentity,\n normalizeProjectDirectory,\n PROJECT_IDENTITY_RESOLVER_REVISION,\n type ProjectScopeMatcher,\n} from \"@codesesh/core/runtime/projects\";\nimport type { Context } from \"hono\";\nimport { appLogger } from \"../logging.js\";\nimport {\n ProjectIdentityQueueFullError,\n ProjectIdentityRequestAbortedError,\n type ProjectIdentityResolver,\n} from \"../project-identity-resolver.js\";\nimport { parseDateWindow, searchParams, type SessionListDefaults } from \"./query-params.js\";\n\nexport const KNOWN_AGENT_NAMES = getAgentInfoMap({}).map((agent) => agent.name);\nexport const KNOWN_AGENT_NAME_SET = new Set(KNOWN_AGENT_NAMES);\n\nexport async function resolveProjectScope(\n cwd: string,\n sessions: readonly IdentifiedSessionHead[],\n resolver: ProjectIdentityResolver | undefined,\n signal: AbortSignal,\n): Promise<ProjectScopeMatcher> {\n const normalizedCwd = normalizeProjectDirectory(cwd);\n const matchingSession = sessions.find(\n (session) =>\n normalizeProjectDirectory(session.directory) === normalizedCwd &&\n session.project_identity_resolver_revision === PROJECT_IDENTITY_RESOLVER_REVISION &&\n Boolean(session.project_identity_input_signature),\n );\n if (matchingSession) {\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, signal);\n return createProjectScopeMatcherFromIdentity(cwd, projection.identity);\n}\n\nexport function projectScopeResolutionFailureResponse(\n c: Context,\n endpoint: string,\n error: unknown,\n) {\n if (error instanceof ProjectIdentityRequestAbortedError) throw error;\n appLogger.warn(\"api.project_scope.unavailable\", {\n endpoint,\n error: error instanceof Error ? error.message : String(error),\n });\n if (error instanceof ProjectIdentityQueueFullError) {\n return c.json({ error: \"Project scope busy; retry later\" }, 429);\n }\n return c.json({ error: \"Project scope unavailable\" }, 503);\n}\n\nexport function 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\nexport function parseDateWindowRequest(\n c: Context,\n endpoint: string,\n defaults: SessionListDefaults,\n) {\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","import { createHash, randomUUID } from \"node:crypto\";\n\ninterface CursorPayload {\n version: 1;\n snapshot: string;\n offset: number;\n}\n\ninterface PaginationRequest {\n cursor?: string;\n limit: number;\n query: URLSearchParams;\n}\n\ninterface PaginationSnapshot<T, View> {\n items: readonly T[];\n view: View;\n}\n\ninterface RetainedSnapshot<T, View> extends PaginationSnapshot<T, View> {\n query: string;\n expiresAt: number;\n}\n\ntype PaginationResult<T, View> =\n | { kind: \"page\"; items: T[]; view: View; nextCursor?: string }\n | { kind: \"invalid_cursor\" }\n | { kind: \"stale_snapshot\" };\n\nconst SNAPSHOT_TTL_MS = 60_000;\nconst SNAPSHOT_LIMIT = 32;\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 !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\nexport function createSnapshotPaginator<T, View>() {\n const snapshotsBySource = new WeakMap<object, Map<string, RetainedSnapshot<T, View>>>();\n\n return function paginateSnapshot(\n // oxlint-disable-next-line anti-slop/no-object-parameters -- The source is a WeakMap identity token; pagination never reads its fields.\n source: object,\n request: PaginationRequest,\n load: () => PaginationSnapshot<T, View>,\n ): PaginationResult<T, View> {\n const snapshots = snapshotsBySource.get(source) ?? new Map<string, RetainedSnapshot<T, View>>();\n const now = Date.now();\n for (const [id, snapshot] of snapshots) {\n if (snapshot.expiresAt <= now) snapshots.delete(id);\n }\n const query = queryFingerprint(request.query);\n let snapshot: RetainedSnapshot<T, View>;\n let snapshotId: string;\n let offset = 0;\n\n if (request.cursor) {\n const cursor = decodeCursor(request.cursor);\n if (!cursor) return { kind: \"invalid_cursor\" };\n const retained = snapshots.get(cursor.snapshot);\n if (!retained) return { kind: \"stale_snapshot\" };\n if (retained.query !== query || cursor.offset >= retained.items.length) {\n return { kind: \"invalid_cursor\" };\n }\n snapshot = retained;\n snapshotId = cursor.snapshot;\n offset = cursor.offset;\n } else {\n const loaded = load();\n snapshot = { ...loaded, items: [...loaded.items], query, expiresAt: now + SNAPSHOT_TTL_MS };\n snapshotId = randomUUID();\n }\n\n const end = Math.min(offset + request.limit, snapshot.items.length);\n const nextCursor =\n end < snapshot.items.length\n ? encodeCursor({ version: 1, snapshot: snapshotId, offset: end })\n : undefined;\n if (!request.cursor && nextCursor) {\n if (snapshots.size >= SNAPSHOT_LIMIT) snapshots.delete(snapshots.keys().next().value!);\n snapshots.set(snapshotId, snapshot);\n snapshotsBySource.set(source, snapshots);\n }\n return {\n kind: \"page\",\n items: snapshot.items.slice(offset, end),\n view: snapshot.view,\n ...(nextCursor ? { nextCursor } : {}),\n };\n };\n}\n","import {\n listFileActivity,\n listDashboardActiveHours,\n listDashboardCostFacts,\n type SessionHead,\n} from \"@codesesh/core/runtime/discovery\";\nimport {\n type DashboardCostFacts,\n type DashboardData,\n type DashboardScope,\n} from \"@codesesh/core/runtime/analytics\";\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>();\n\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\" | \"activeHours\">;\n\nexport function getSnapshotCostFacts(\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 // Effective message timestamps are positive; the UI uses epoch zero for All time.\n const costFrom = from === 0 ? undefined : from;\n const build = () => listDashboardCostFacts({ from: costFrom, to });\n if (analyticsRevision === null) return build();\n\n return getSnapshotAggregation(\n source,\n sessions,\n [\"cost-facts\", costFrom, 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 timeZone: string,\n): DashboardStorageAggregation {\n const build = (): DashboardStorageAggregation => ({\n activeHours: listDashboardActiveHours({ ...scope, from, to, timeZone }, source.queryScope),\n recentFileActivities: listFileActivity(\n {\n agent: scope.agent,\n projectKind: scope.projectKind,\n projectKey: scope.projectKey,\n from,\n to,\n limit: 12,\n },\n source.queryScope,\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 timeZone,\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 { AppConfig, ApiProjectGroup, ApiProjectPage } from \"@codesesh/core/contract\";\nimport { getAgentInfoMap } from \"@codesesh/core/runtime/agents\";\nimport {\n getAnalyticsRevision,\n listCachedProjectGroups,\n listDashboardCostFacts,\n} from \"@codesesh/core/runtime/discovery\";\nimport { attachProjectMetricsFromTree, summarizeProjects } from \"@codesesh/core/runtime/projects\";\nimport type { Context } from \"hono\";\nimport { parseDateWindowRequest, reportInvalidQueryParameter } from \"./handler-support.js\";\nimport {\n filterSessionsByActivityWindow,\n parseLimit,\n parseProjectIdentityFilter,\n PROJECT_PAGE_LIMIT_POLICY,\n searchParams,\n type SessionListDefaults,\n} from \"./query-params.js\";\nimport type { ScanResultSource, ScanStatusSource } from \"./scan-sources.js\";\nimport { createSnapshotPaginator } from \"./snapshot-pagination.js\";\nimport {\n getSnapshotAggregation,\n getSnapshotCostFacts,\n getSnapshotSessionTree,\n} from \"./snapshot-aggregation.js\";\n\nconst paginateProjects = createSnapshotPaginator<ApiProjectGroup, ApiProjectPage[\"summary\"]>();\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 params = searchParams(c);\n const limit = parseLimit(params.get(\"limit\"), PROJECT_PAGE_LIMIT_POLICY);\n if (limit.kind === \"invalid\") {\n reportInvalidQueryParameter(\"projects\", \"limit\", \"rejected\");\n return c.json({ error: 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, \"projects\", defaults);\n if (window.kind === \"rejected\") return window.response;\n const { from, to } = window;\n const loadSnapshot = () => {\n const analyticsRevision = getAnalyticsRevision();\n const catalog = getSnapshotAggregation(\n scanSource,\n scanResult.sessions,\n [\"projects\", from, to, analyticsRevision],\n () => {\n const tree = getSnapshotSessionTree(scanSource, scanResult.sessions);\n const costFacts =\n (from == null || from === 0) && to == null\n ? getSnapshotCostFacts(scanSource, scanResult.sessions, from, to, to, analyticsRevision)\n : listDashboardCostFacts({ from, to, includeModelCosts: false });\n const 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 return { projects, summary: summarizeProjects(projects) };\n },\n );\n const projects = projectIdentity\n ? catalog.projects.filter(\n (project) =>\n project.identityKind === projectIdentity.kind &&\n project.identityKey === projectIdentity.key,\n )\n : catalog.projects;\n return {\n items: projects,\n view: projectIdentity ? summarizeProjects(projects) : catalog.summary,\n };\n };\n const page = paginateProjects(\n scanSource,\n {\n cursor: params.get(\"cursor\") ?? undefined,\n limit: limit.value,\n query: params,\n },\n loadSnapshot,\n );\n if (page.kind === \"invalid_cursor\") {\n reportInvalidQueryParameter(\"projects\", \"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: \"project snapshot expired; restart pagination\" }, 409);\n }\n return c.json({\n projects: page.items,\n summary: page.view,\n ...(page.nextCursor ? { nextCursor: page.nextCursor } : {}),\n });\n}\n","import {\n addCalendarDays,\n countCalendarDays,\n parseCalendarDayBoundary,\n startOfCalendarDay,\n} from \"@codesesh/core/contract\";\n\nconst 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 RawCliTimeWindow {\n from?: string;\n to?: string;\n days?: string;\n}\n\ninterface CliTimeWindowRequest extends RawCliTimeWindow {\n mode: \"cli\";\n now?: number;\n}\n\ninterface DashboardTimeWindowRequest {\n mode: \"dashboard\";\n window: {\n from?: number;\n to?: number;\n hasExplicitFrom: boolean;\n };\n days?: string;\n defaultDays?: number;\n now?: number;\n}\n\ninterface DashboardTimeWindow extends TimeWindow {\n to: number;\n days: 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, \"start\");\n const to = parseRequiredDate(request.to, \"end\");\n if (from != null && to != null && from > to) {\n throw new Error(\"Invalid time window: from must not be after to\");\n }\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 calendarFrom = addCalendarDays(startOfCalendarDay(to ?? now), -(days - 1));\n return Number.isFinite(calendarFrom) ? { from: calendarFrom, to, days } : { to };\n}\n\nfunction resolveDashboardWindow(request: DashboardTimeWindowRequest): DashboardTimeWindow {\n const now = request.now ?? Date.now();\n const to = request.window.to ?? now;\n const hasQueryDays = Boolean(request.days?.trim());\n const parsedDays = hasQueryDays ? parseDays(request.days) : undefined;\n\n if (request.window.hasExplicitFrom && request.window.from != null) {\n return { from: request.window.from, to, days: countCalendarDays(request.window.from, to) };\n }\n\n const days = parsedDays ?? request.defaultDays;\n if (days === 0) {\n return { to, days: 0 };\n }\n\n if (days != null && days > 0) {\n return {\n from: addCalendarDays(startOfCalendarDay(to), -(days - 1)),\n to,\n days,\n };\n }\n\n if (request.window.from != null) {\n return { from: request.window.from, to, days: countCalendarDays(request.window.from, to) };\n }\n\n return {\n from: addCalendarDays(startOfCalendarDay(to), -(DEFAULT_DASHBOARD_DAYS - 1)),\n to,\n days: DEFAULT_DASHBOARD_DAYS,\n };\n}\n\nfunction parseRequiredDate(\n value: string | undefined,\n boundary: \"start\" | \"end\",\n): number | undefined {\n if (!value) return undefined;\n const calendarBoundary = parseCalendarDayBoundary(value, boundary);\n if (calendarBoundary === null) throw new Error(`Invalid date: ${value}`);\n if (calendarBoundary != null) return calendarBoundary;\n const timestamp = new Date(value).getTime();\n if (Number.isNaN(timestamp)) throw new Error(`Invalid date: ${value}`);\n return timestamp;\n}\n\nfunction parseDays(value: string | undefined): number | undefined {\n if (value == null) return undefined;\n const normalized = value.trim();\n if (!/^-?\\d+$/.test(normalized)) return undefined;\n const days = Number(normalized);\n return Number.isSafeInteger(days) && Number.isSafeInteger(days * DAY_MS) ? days : undefined;\n}\n","/**\n * Deep session search: single owner for search-query interpretation\n * (qualifier parsing/merging), source selection between the live LiveSnapshot\n * snapshot (\"recent\" path) and the SQLite search index (FTS / file-activity\n * paths), and cross-source result merging.\n */\nimport type { SessionHead } from \"../types/index.js\";\nimport {\n buildSessionTree,\n getSessionReferenceKey,\n type SearchResult,\n type SessionTree,\n} from \"../contract/index.js\";\nimport {\n filterIndexedSessionReferences,\n mergeSearchQueryOptions,\n searchSessions,\n sessionMatchesSearchCost,\n type ParsedSearchQuery,\n type SearchOptions,\n} from \"../discovery/cache/search.js\";\nimport { searchFileActivitySessions } from \"../discovery/cache/file-activity.js\";\nimport { matchesProjectScope, type ProjectScopeMatcher } from \"../projects/scope.js\";\nimport { matchesProjectIdentity } from \"../projects/identity.js\";\nimport { getSessionActivityTime } from \"../analytics/dashboard.js\";\nimport { matchesSessionQueryScope, type SessionQueryScope } from \"../discovery/session-scope.js\";\n\nexport interface SessionSearchSnapshot {\n /** Globally sorted by activity descending; ties preserve the canonical live-index order. */\n sessions: SessionHead[];\n /** Each shard follows the same activity ordering as `sessions`. */\n byAgent: Record<string, SessionHead[]>;\n}\n\nexport interface SessionSearchContext {\n sessionTree?: SessionTree;\n queryScope?: SessionQueryScope;\n}\n\nexport interface SessionSearchFilterContext extends SessionSearchContext {\n sessionSnapshot?: SessionHead[];\n}\n\nexport function executeSessionSearch(\n query: string,\n options: SearchOptions,\n snapshot: SessionSearchSnapshot,\n context: SessionSearchContext = {},\n): SearchResult[] {\n const merged = mergeSearchQueryOptions(query, options);\n\n if (!needsIndexedSearch(merged.text, merged.options)) {\n return searchRecentSessions(snapshot, merged.options, context);\n }\n\n return searchIndexedSessions(\n query,\n merged.text,\n merged.parsed,\n merged.options,\n context.queryScope,\n );\n}\n\n// Qualifiers alone (tag:/cost:/agent:/project:) do not force the indexed\n// path -- only text, file, fileKind, or tool do. A qualifier-only query is\n// treated identically to an empty query for source selection.\nfunction needsIndexedSearch(textQuery: string, options: SearchOptions): boolean {\n return Boolean(textQuery || options.file || options.fileKind || options.tools?.length);\n}\n\nfunction matchesRecentSearchFilters(\n session: SessionHead,\n options: SearchOptions,\n projectScope: ProjectScopeMatcher | null,\n inclusiveCost: number,\n): boolean {\n if (options.projectKind || options.projectKey) {\n if (\n !options.projectKind ||\n !options.projectKey ||\n !matchesProjectIdentity(session.project_identity, {\n kind: options.projectKind,\n key: options.projectKey,\n })\n ) {\n return false;\n }\n }\n if (projectScope && !matchesProjectScope(session, projectScope)) return false;\n if (options.project) {\n const projectNeedle = options.project.toLowerCase();\n const projectText = [\n session.project_identity?.key,\n session.project_identity?.displayName,\n session.directory,\n ]\n .filter(Boolean)\n .join(\"\\n\")\n .toLowerCase();\n if (!projectText.includes(projectNeedle)) return false;\n }\n if (options.tags?.length && !options.tags.every((tag) => session.smart_tags?.includes(tag))) {\n return false;\n }\n if (!sessionMatchesSearchCost(session, options, inclusiveCost)) return false;\n return true;\n}\n\n// Evaluates filters answerable from SessionHead. File and tool predicates\n// require the indexed batch seam in filterSessionSearchCandidates.\nexport function matchesSessionSearchFilters(\n agentName: string,\n session: SessionHead,\n options: SearchOptions,\n projectScope: ProjectScopeMatcher | null = null,\n inclusiveCost = session.stats.total_cost,\n): boolean {\n if (options.agent && agentName !== options.agent) return false;\n const activity = getSessionActivityTime(session);\n if (options.from != null && activity < options.from) return false;\n if (options.to != null && activity > options.to) return false;\n return matchesRecentSearchFilters(session, options, projectScope, inclusiveCost);\n}\n\nexport function filterSessionSearchCandidates(\n candidates: SearchResult[],\n options: SearchOptions,\n context: SessionSearchFilterContext = {},\n): SearchResult[] {\n const projectScope = options.projectScope ?? null;\n const sessionSnapshot =\n context.sessionSnapshot ?? candidates.map((candidate) => candidate.session);\n const inclusiveCosts = buildInclusiveCostLookup(sessionSnapshot, options, context.sessionTree);\n const headMatches = candidates.filter(\n (candidate) =>\n matchesSessionQueryScope(candidate.session, context.queryScope) &&\n matchesSessionSearchFilters(\n candidate.reference.agentName,\n candidate.session,\n options,\n projectScope,\n inclusiveCostFor(candidate.reference.agentName, candidate.session, inclusiveCosts),\n ),\n );\n if (!options.file && !options.fileKind && !options.tools?.length) return headMatches;\n\n const indexedMatches = filterIndexedSessionReferences(\n headMatches.map((candidate) => ({\n agentName: candidate.reference.agentName,\n sessionId: candidate.reference.sessionId,\n })),\n {\n file: options.file,\n fileKind: options.fileKind,\n tools: options.tools,\n },\n );\n return headMatches.filter((candidate) =>\n indexedMatches.has(getSessionReferenceKey(candidate.reference)),\n );\n}\n\nfunction searchRecentSessions(\n snapshot: SessionSearchSnapshot,\n options: SearchOptions,\n context: SessionSearchContext,\n): SearchResult[] {\n const limit = Math.max(0, Math.trunc(options.limit ?? 50));\n if (limit === 0) return [];\n\n const projectScope = options.projectScope ?? null;\n const inclusiveCosts = buildInclusiveCostLookup(snapshot.sessions, options, context.sessionTree);\n const sessions = options.agent ? (snapshot.byAgent[options.agent] ?? []) : snapshot.sessions;\n const results: SearchResult[] = [];\n\n for (const session of sessions) {\n const agentName = options.agent ?? session.reference.agentName;\n if (\n !matchesSessionQueryScope(session, context.queryScope) ||\n !matchesSessionSearchFilters(\n agentName,\n session,\n options,\n projectScope,\n inclusiveCostFor(agentName, session, inclusiveCosts),\n )\n ) {\n continue;\n }\n results.push({\n reference: session.reference,\n session,\n snippet: `Recent session · ${session.directory}`,\n snippetHighlights: [],\n matchType: \"recent\",\n });\n if (results.length >= limit) break;\n }\n\n return results;\n}\n\nfunction buildInclusiveCostLookup(\n sessions: SessionHead[],\n options: SearchOptions,\n sessionTree?: SessionTree,\n): ReturnType<typeof buildSessionTree>[\"byRouteKey\"] | null {\n if (options.costMin == null && options.costMax == null) return null;\n return (sessionTree ?? buildSessionTree(sessions)).byRouteKey;\n}\n\nfunction inclusiveCostFor(\n agentName: string,\n session: SessionHead,\n lookup: ReturnType<typeof buildSessionTree>[\"byRouteKey\"] | null,\n): number {\n return (\n lookup?.get(getSessionReferenceKey({ agentName, sessionId: session.reference.sessionId }))\n ?.inclusiveStats.cost ?? session.stats.total_cost\n );\n}\n\n// `options.file` already carries the qualifier's `file:`/`path:` value once\n// merged (options.file ?? filters.file), so the middle branch only matters\n// when options.file was merged from something other than this parse. When\n// the query has no qualifiers at all, a bare text search is also attempted\n// as a file-path search (usually a no-op match, but it is why plain text\n// queries still touch the file-activity path).\nfunction deriveFileQuery(query: string, parsed: ParsedSearchQuery, options: SearchOptions): string {\n return (\n options.file ??\n (!parsed.text ? parsed.filters.file : undefined) ??\n (!parsed.hasQualifiers && query ? parsed.text || query : \"\")\n );\n}\n\nfunction mergeSearchResultSources(results: SearchResult[], limit: number): SearchResult[] {\n const seen = new Set<string>();\n const merged: SearchResult[] = [];\n\n for (const result of results) {\n const key = getSessionReferenceKey(result.reference);\n if (seen.has(key)) continue;\n seen.add(key);\n merged.push(result);\n if (merged.length >= limit) break;\n }\n\n return merged;\n}\n\nfunction canSkipSessionsSearch(fileQuery: string, textQuery: string): boolean {\n return Boolean(fileQuery && !textQuery);\n}\n\nfunction searchIndexedSessions(\n query: string,\n textQuery: string,\n parsed: ParsedSearchQuery,\n options: SearchOptions,\n queryScope?: SessionQueryScope,\n): SearchResult[] {\n const fileQuery = deriveFileQuery(query, parsed, options);\n const fileResults = fileQuery ? searchFileActivitySessions(fileQuery, options, queryScope) : [];\n const sessionResults = canSkipSessionsSearch(fileQuery, textQuery)\n ? []\n : searchSessions(query, options, queryScope);\n const textMatchReferences =\n textQuery && options.file\n ? new Set(sessionResults.map((result) => getSessionReferenceKey(result.reference)))\n : null;\n const matchingFileResults = textMatchReferences\n ? fileResults.filter((result) =>\n textMatchReferences.has(getSessionReferenceKey(result.reference)),\n )\n : fileResults;\n\n return mergeSearchResultSources([...matchingFileResults, ...sessionResults], options.limit ?? 50);\n}\n","import { homedir, platform } from \"node:os\";\nimport { join } from \"node:path\";\nimport {\n columnExists,\n getUserVersion,\n openDb,\n runSchemaMigrations,\n setUserVersion,\n tableExists,\n type DatabaseRow,\n type SQLiteDatabase,\n} from \"../utils/sqlite.js\";\n\nconst STATE_DB_FILENAME = \"state.db\";\nconst STATE_SCHEMA_VERSION = 3;\nconst MEMORY_STATE_STORE = \"memory\";\n\n// One-shot per-process ensureSchema guard, mirroring the cache side's\n// schemaEnsuredPath (discovery/cache/db.ts). Keyed by dbPath so tests can\n// switch state directories; exported so tests can reset it between runs.\nlet stateSchemaEnsuredPath: string | null = null;\n\nexport function getStateSchemaEnsuredPath(): string | null {\n return stateSchemaEnsuredPath;\n}\n\nexport function setStateSchemaEnsuredPath(path: string | null): void {\n stateSchemaEnsuredPath = path;\n}\n\nexport class StateStorageUnavailableError extends Error {\n constructor() {\n super(\"SQLite state database is unavailable\");\n this.name = \"StateStorageUnavailableError\";\n }\n}\n\nfunction getStateDir(): string {\n if (process.env.CODESESH_STATE_DIR) return process.env.CODESESH_STATE_DIR;\n\n const currentPlatform = platform();\n if (currentPlatform === \"darwin\") {\n return join(homedir(), \"Library\", \"Application Support\", \"codesesh\");\n }\n if (currentPlatform === \"win32\") {\n const appData = process.env.APPDATA ?? process.env.LOCALAPPDATA;\n return join(appData ?? join(homedir(), \"AppData\", \"Roaming\"), \"codesesh\");\n }\n return join(process.env.XDG_DATA_HOME ?? join(homedir(), \".local\", \"share\"), \"codesesh\");\n}\n\nfunction getStateDbPath(): string {\n return join(getStateDir(), STATE_DB_FILENAME);\n}\n\nexport function useMemoryStateStore(): boolean {\n return process.env.CODESESH_STATE_STORE === MEMORY_STATE_STORE;\n}\n\nfunction createBookmarksTable(db: SQLiteDatabase): void {\n db.exec(`\n CREATE TABLE IF NOT EXISTS bookmarks (\n agent_name TEXT NOT NULL,\n session_id TEXT NOT NULL,\n bookmarked_at INTEGER NOT NULL,\n PRIMARY KEY (agent_name, session_id)\n );\n `);\n}\n\nfunction migrateBookmarkFacts(db: SQLiteDatabase): void {\n db.exec(\"ALTER TABLE bookmarks RENAME TO bookmarks_with_snapshots\");\n createBookmarksTable(db);\n db.exec(`\n INSERT INTO bookmarks(agent_name, session_id, bookmarked_at)\n SELECT agent_name, session_id, bookmarked_at\n FROM bookmarks_with_snapshots;\n\n DROP TABLE bookmarks_with_snapshots;\n `);\n}\n\nfunction createSessionAliasesTable(db: SQLiteDatabase): void {\n db.exec(`\n CREATE TABLE IF NOT EXISTS session_aliases (\n agent_name TEXT NOT NULL,\n session_id TEXT NOT NULL,\n alias TEXT NOT NULL,\n updated_at INTEGER NOT NULL,\n PRIMARY KEY (agent_name, session_id)\n );\n `);\n}\n\nfunction createStateSchema(db: SQLiteDatabase): void {\n db.exec(`\n CREATE TABLE IF NOT EXISTS state_meta (\n key TEXT PRIMARY KEY,\n value TEXT NOT NULL\n );\n `);\n createBookmarksTable(db);\n createSessionAliasesTable(db);\n}\n\nfunction readLegacyStateVersion(db: SQLiteDatabase): number {\n if (\n !tableExists(db, \"state_meta\") ||\n !columnExists(db, \"state_meta\", \"key\") ||\n !columnExists(db, \"state_meta\", \"value\")\n ) {\n return 0;\n }\n\n const row = db.prepare(\"SELECT value FROM state_meta WHERE key = 'version'\").get() as\n | DatabaseRow\n | undefined;\n return Number(row?.value ?? 0);\n}\n\nfunction getCurrentStateSchemaVersion(db: SQLiteDatabase): number {\n const userVersion = getUserVersion(db);\n if (userVersion > 0) return userVersion;\n\n const legacyVersion = readLegacyStateVersion(db);\n if (legacyVersion > 0) return legacyVersion;\n\n return tableExists(db, \"bookmarks\") ? 1 : 0;\n}\n\nfunction hasAnyStateSchema(db: SQLiteDatabase): boolean {\n return tableExists(db, \"state_meta\") || tableExists(db, \"bookmarks\");\n}\n\nfunction setStateSchemaVersion(db: SQLiteDatabase): void {\n createStateSchema(db);\n setUserVersion(db, STATE_SCHEMA_VERSION);\n db.prepare(\n `\n INSERT INTO state_meta(key, value)\n VALUES ('version', ?)\n ON CONFLICT(key) DO UPDATE SET value = excluded.value\n `,\n ).run(String(STATE_SCHEMA_VERSION));\n}\n\nfunction ensureSchema(db: SQLiteDatabase, dbPath: string): void {\n const currentVersion = getCurrentStateSchemaVersion(db);\n if (currentVersion > STATE_SCHEMA_VERSION) return;\n if (currentVersion === 0 && !hasAnyStateSchema(db)) {\n setStateSchemaVersion(db);\n return;\n }\n\n runSchemaMigrations(db, {\n dbPath,\n currentVersion,\n targetVersion: STATE_SCHEMA_VERSION,\n backupLabel: \"state-migration\",\n backupTables: [\"bookmarks\", \"session_aliases\"],\n migrations: [\n { version: 1, migrate: createBookmarksTable },\n { version: 2, migrate: createSessionAliasesTable },\n { version: 3, destructive: true, migrate: migrateBookmarkFacts },\n ],\n });\n\n if (currentVersion < STATE_SCHEMA_VERSION) {\n setStateSchemaVersion(db);\n }\n}\n\nexport function withStateDb<T>(fn: (db: SQLiteDatabase) => T): T {\n const statePath = getStateDbPath();\n const db = openDb(statePath);\n if (!db) throw new StateStorageUnavailableError();\n\n try {\n if (getStateSchemaEnsuredPath() !== statePath) {\n ensureSchema(db, statePath);\n setStateSchemaEnsuredPath(statePath);\n }\n return fn(db);\n } finally {\n db.close();\n }\n}\n","import {\n normalizeSessionReference,\n type BookmarkRecord,\n type SessionReference,\n} from \"../contract/index.js\";\nimport { StateStorageUnavailableError, useMemoryStateStore, withStateDb } from \"./database.js\";\nimport type { DatabaseRow, SQLiteDatabase } from \"../utils/sqlite.js\";\n\nconst memoryBookmarks = new Map<string, BookmarkRecord>();\n\nexport { StateStorageUnavailableError as BookmarkStorageUnavailableError };\n\nexport type { BookmarkRecord };\n\ninterface BookmarkRow extends DatabaseRow {\n agent_name?: string;\n session_id?: string;\n bookmarked_at?: number;\n}\n\nfunction getBookmarkKey(reference: SessionReference): string {\n const normalized = normalizeSessionReference(reference);\n return JSON.stringify([normalized.agentName, normalized.sessionId]);\n}\n\nfunction compareBookmarks(left: BookmarkRecord, right: BookmarkRecord): number {\n if (left.bookmarkedAt !== right.bookmarkedAt) {\n return left.bookmarkedAt > right.bookmarkedAt ? -1 : 1;\n }\n return getBookmarkKey(left.reference).localeCompare(getBookmarkKey(right.reference));\n}\n\nfunction normalizeBookmark(bookmark: BookmarkRecord): BookmarkRecord {\n return {\n reference: normalizeSessionReference(bookmark.reference),\n bookmarkedAt: bookmark.bookmarkedAt,\n };\n}\n\nfunction toBookmarkRecord(row: BookmarkRow): BookmarkRecord {\n return {\n reference: normalizeSessionReference({\n agentName: String(row.agent_name ?? \"\"),\n sessionId: String(row.session_id ?? \"\"),\n }),\n bookmarkedAt: Number(row.bookmarked_at ?? 0),\n };\n}\n\nfunction readBookmarks(db: SQLiteDatabase): BookmarkRecord[] {\n const rows = db\n .prepare(\n `\n SELECT agent_name, session_id, bookmarked_at\n FROM bookmarks\n ORDER BY bookmarked_at DESC, agent_name ASC, session_id ASC\n `,\n )\n .all() as BookmarkRow[];\n return rows.map(toBookmarkRecord);\n}\n\nfunction listMemoryBookmarks(): BookmarkRecord[] {\n return [...memoryBookmarks.values()].sort(compareBookmarks);\n}\n\nexport function listBookmarks(): BookmarkRecord[] {\n if (useMemoryStateStore()) return listMemoryBookmarks();\n return withStateDb(readBookmarks);\n}\n\nexport function upsertBookmark(reference: SessionReference): BookmarkRecord {\n const normalized = normalizeSessionReference(reference);\n const key = getBookmarkKey(normalized);\n if (useMemoryStateStore()) {\n const bookmark = memoryBookmarks.get(key) ?? {\n reference: normalized,\n bookmarkedAt: Date.now(),\n };\n memoryBookmarks.set(key, bookmark);\n return bookmark;\n }\n\n return withStateDb((db) => {\n const row = db\n .prepare(\n `\n INSERT INTO bookmarks(agent_name, session_id, bookmarked_at)\n VALUES (?, ?, ?)\n ON CONFLICT(agent_name, session_id) DO UPDATE\n SET bookmarked_at = bookmarks.bookmarked_at\n RETURNING agent_name, session_id, bookmarked_at\n `,\n )\n .get(normalized.agentName, normalized.sessionId, Date.now()) as BookmarkRow | undefined;\n if (!row) {\n throw new Error(\"Bookmark upsert returned no row\");\n }\n return toBookmarkRecord(row);\n });\n}\n\nexport function importBookmarks(bookmarks: readonly BookmarkRecord[]): BookmarkRecord[] {\n const unique = new Map<string, BookmarkRecord>();\n for (const bookmark of bookmarks) {\n const normalized = normalizeBookmark(bookmark);\n const key = getBookmarkKey(normalized.reference);\n if (!unique.has(key)) unique.set(key, normalized);\n }\n\n if (useMemoryStateStore()) {\n for (const [key, bookmark] of unique) {\n if (!memoryBookmarks.has(key)) memoryBookmarks.set(key, bookmark);\n }\n return listMemoryBookmarks();\n }\n\n return withStateDb((db) => {\n const insert = db.prepare(\n `\n INSERT INTO bookmarks(agent_name, session_id, bookmarked_at)\n VALUES (?, ?, ?)\n ON CONFLICT(agent_name, session_id) DO NOTHING\n `,\n );\n const write = db.transaction(() => {\n for (const bookmark of unique.values()) {\n insert.run(\n bookmark.reference.agentName,\n bookmark.reference.sessionId,\n bookmark.bookmarkedAt,\n );\n }\n });\n write.immediate();\n return readBookmarks(db);\n });\n}\n\nexport function deleteBookmark(reference: SessionReference): void {\n const normalized = normalizeSessionReference(reference);\n if (useMemoryStateStore()) {\n memoryBookmarks.delete(getBookmarkKey(normalized));\n return;\n }\n\n withStateDb((db) => {\n db.prepare(\n `\n DELETE FROM bookmarks\n WHERE agent_name = ? AND session_id = ?\n `,\n ).run(normalized.agentName, normalized.sessionId);\n });\n}\n","import { StateStorageUnavailableError, useMemoryStateStore, withStateDb } from \"./database.js\";\nimport type { DatabaseRow } from \"../utils/sqlite.js\";\nimport { normalizeSessionReference, type SessionReference } from \"../contract/index.js\";\n\nexport const SESSION_ALIAS_MAX_LENGTH = 160;\n\nexport class SessionAliasValidationError extends Error {\n constructor() {\n super(\"Invalid session alias\");\n this.name = \"SessionAliasValidationError\";\n }\n}\n\nexport interface SessionAlias {\n reference: SessionReference;\n alias: string;\n updatedAt: number;\n}\n\ninterface SessionAliasRow extends DatabaseRow {\n agent_name?: string;\n session_id?: string;\n alias?: string;\n updated_at?: number;\n}\n\nconst memoryAliases = new Map<string, SessionAlias>();\n\nfunction getAliasKey(reference: SessionReference): string {\n const normalized = normalizeSessionReference(reference);\n return JSON.stringify([normalized.agentName, normalized.sessionId]);\n}\n\nfunction toSessionAlias(row: SessionAliasRow): SessionAlias {\n const reference = normalizeSessionReference({\n agentName: String(row.agent_name ?? \"\"),\n sessionId: String(row.session_id ?? \"\"),\n });\n return {\n reference,\n alias: String(row.alias ?? \"\"),\n updatedAt: Number(row.updated_at ?? 0),\n };\n}\n\nexport function normalizeSessionAlias(value: string): string | null {\n const alias = value.trim();\n if (!alias || alias.length > SESSION_ALIAS_MAX_LENGTH) return null;\n return alias;\n}\n\nexport function listSessionAliases(): SessionAlias[] {\n if (useMemoryStateStore()) return [...memoryAliases.values()];\n\n return withStateDb((db) =>\n (\n db\n .prepare(\n `\n SELECT agent_name, session_id, alias, updated_at\n FROM session_aliases\n ORDER BY updated_at DESC\n `,\n )\n .all() as SessionAliasRow[]\n ).map(toSessionAlias),\n );\n}\n\nexport function upsertSessionAlias(reference: SessionReference, alias: string): SessionAlias {\n const normalizedAlias = normalizeSessionAlias(alias);\n if (!normalizedAlias) {\n throw new SessionAliasValidationError();\n }\n\n const normalizedReference = normalizeSessionReference(reference);\n const saved: SessionAlias = {\n reference: normalizedReference,\n alias: normalizedAlias,\n updatedAt: Date.now(),\n };\n if (useMemoryStateStore()) {\n memoryAliases.set(getAliasKey(normalizedReference), saved);\n return saved;\n }\n\n return withStateDb((db) => {\n db.prepare(\n `\n INSERT INTO session_aliases(agent_name, session_id, alias, updated_at)\n VALUES (?, ?, ?, ?)\n ON CONFLICT(agent_name, session_id) DO UPDATE SET\n alias = excluded.alias,\n updated_at = excluded.updated_at\n `,\n ).run(saved.reference.agentName, saved.reference.sessionId, saved.alias, saved.updatedAt);\n return saved;\n });\n}\n\nexport function deleteSessionAlias(reference: SessionReference): void {\n const normalizedReference = normalizeSessionReference(reference);\n if (useMemoryStateStore()) {\n memoryAliases.delete(getAliasKey(normalizedReference));\n return;\n }\n\n withStateDb((db) => {\n db.prepare(\n `\n DELETE FROM session_aliases\n WHERE agent_name = ? AND session_id = ?\n `,\n ).run(normalizedReference.agentName, normalizedReference.sessionId);\n });\n}\n\nexport { StateStorageUnavailableError };\n","import type {\n BookmarkRecord,\n BookmarkView,\n ReferencedSessionHead,\n SessionHead,\n SessionReference,\n} from \"../contract/index.js\";\nimport {\n assertSessionIdentity,\n getSessionReferenceKey,\n normalizeSessionReference,\n} from \"../contract/index.js\";\n\nexport interface BookmarkMaterializationOptions {\n liveSessionsByReference: ReadonlyMap<string, SessionHead>;\n knownAgentNames: ReadonlySet<string>;\n resolveCachedSessions?: (\n references: readonly SessionReference[],\n ) => readonly ReferencedSessionHead[];\n}\n\nfunction canonicalSession(reference: SessionReference, session: SessionHead): SessionHead {\n const normalized = normalizeSessionReference(reference);\n assertSessionIdentity(session, normalized.agentName);\n if (session.reference.sessionId !== normalized.sessionId) {\n throw new Error(\"Session reference does not match expected session\");\n }\n return session;\n}\n\nfunction compareDescending(left: number, right: number): number {\n if (left === right) return 0;\n return left > right ? -1 : 1;\n}\n\nfunction getBookmarkViewTime(bookmark: BookmarkView): number {\n return bookmark.availability === \"available\"\n ? (bookmark.session.time_updated ?? bookmark.session.time_created)\n : bookmark.bookmarkedAt;\n}\n\nexport function compareBookmarkViews(left: BookmarkView, right: BookmarkView): number {\n return (\n compareDescending(getBookmarkViewTime(left), getBookmarkViewTime(right)) ||\n compareDescending(left.bookmarkedAt, right.bookmarkedAt) ||\n getSessionReferenceKey(left.reference).localeCompare(getSessionReferenceKey(right.reference))\n );\n}\n\nexport function materializeBookmarkViews(\n bookmarks: readonly BookmarkRecord[],\n options: BookmarkMaterializationOptions,\n): BookmarkView[] {\n const liveByKey = new Map<string, SessionHead>();\n const missingByKey = new Map<string, SessionReference>();\n const normalizedBookmarks = bookmarks.map((bookmark) => {\n const reference = normalizeSessionReference(bookmark.reference);\n return {\n bookmark: { reference, bookmarkedAt: bookmark.bookmarkedAt },\n key: getSessionReferenceKey(reference),\n };\n });\n\n for (const { bookmark, key } of normalizedBookmarks) {\n const { reference } = bookmark;\n const live = options.liveSessionsByReference.get(key);\n if (live) liveByKey.set(key, canonicalSession(reference, live));\n else if (!missingByKey.has(key)) missingByKey.set(key, reference);\n }\n\n const cachedByKey = new Map<string, SessionHead>();\n if (missingByKey.size > 0 && options.resolveCachedSessions) {\n for (const cached of options.resolveCachedSessions([...missingByKey.values()])) {\n const reference = normalizeSessionReference(cached.reference);\n const key = getSessionReferenceKey(reference);\n if (missingByKey.has(key) && !cachedByKey.has(key)) {\n cachedByKey.set(key, canonicalSession(reference, cached.session));\n }\n }\n }\n\n const views = normalizedBookmarks.map(({ bookmark, key }): BookmarkView => {\n const session = liveByKey.get(key) ?? cachedByKey.get(key);\n if (session) return { ...bookmark, availability: \"available\", session };\n\n return {\n ...bookmark,\n availability: options.knownAgentNames.has(bookmark.reference.agentName)\n ? \"session-unavailable\"\n : \"agent-unavailable\",\n };\n });\n\n return views.sort(compareBookmarkViews);\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 } from \"@codesesh/core/runtime/state\";\nimport type { SessionHead } from \"@codesesh/core/runtime/discovery\";\nimport type { SearchResult, SessionReference } from \"@codesesh/core/contract\";\nimport {\n filterSessionSearchCandidates,\n type SessionSearchContext,\n} from \"@codesesh/core/runtime/search\";\nimport { getSessionActivityTime } from \"@codesesh/core/runtime/analytics\";\nimport { listSessionAliases, StateStorageUnavailableError } from \"@codesesh/core/runtime/state\";\nimport {\n mergeSearchQueryOptions,\n type FileActivityResult,\n type LiveSnapshot,\n type SearchOptions,\n} from \"@codesesh/core/runtime/discovery\";\nimport { appLogger } from \"../logging.js\";\n\n/** Anything the API returns that can carry a locally-renamed title. */\ntype Titled = { 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 buildAliasView(aliases: Map<string, SessionAlias>): AliasView {\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\nfunction readAliasView(): AliasView | null {\n try {\n return buildAliasView(\n new Map(listSessionAliases().map((alias) => [aliasKey(alias.reference), alias])),\n );\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 null;\n }\n}\n\nconst EMPTY_ALIAS_VIEW = buildAliasView(new Map());\n\n// Other CLI instances share state.db but cannot invalidate this process's view.\nconst ALIAS_VIEW_TTL_MS = 1_000;\nlet cachedView: { view: AliasView; expiresAt: number } | null = null;\n\nexport function loadAliasView(): AliasView {\n if (cachedView && Date.now() < cachedView.expiresAt) return cachedView.view;\n const loaded = readAliasView();\n if (!loaded) return EMPTY_ALIAS_VIEW;\n cachedView = { view: loaded, expiresAt: Date.now() + ALIAS_VIEW_TTL_MS };\n return loaded;\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(\n (scanResult.byAgent[agentName] ?? []).map((item) => [item.reference.sessionId, item]),\n );\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 queryScope: context.queryScope,\n }).sort((a, b) => getSessionActivityTime(b.session) - getSessionActivityTime(a.session));\n}\n","import {\n addCalendarDays,\n startOfCalendarDay,\n toPublicReferencedSessionHead,\n} from \"@codesesh/core/contract\";\nimport { getAgentInfoMap } from \"@codesesh/core/runtime/agents\";\nimport {\n buildDashboard,\n type DashboardData,\n type DashboardScope,\n} from \"@codesesh/core/runtime/analytics\";\nimport { getAnalyticsRevision } from \"@codesesh/core/runtime/discovery\";\nimport type { Context } from \"hono\";\nimport { resolveTimeWindow } from \"../time-window-resolution.js\";\nimport { parseDateWindowRequest } from \"./handler-support.js\";\nimport {\n optionalQueryValue,\n parseProjectIdentityFilter,\n type SessionListDefaults,\n} from \"./query-params.js\";\nimport type { ScanResultSource } from \"./scan-sources.js\";\nimport { decorateFileActivity, loadAliasView } from \"./session-aliases-view.js\";\nimport {\n getSnapshotCostFacts,\n getDashboardStorageAggregation,\n getSnapshotAggregation,\n} from \"./snapshot-aggregation.js\";\n\nexport function handleGetDashboard(\n c: Context,\n scanSource: ScanResultSource,\n defaults: SessionListDefaults = {},\n) {\n let timeZone: string;\n try {\n timeZone = new Intl.DateTimeFormat(\"en\", {\n timeZone:\n optionalQueryValue(c.req.query(\"timeZone\")) ??\n Intl.DateTimeFormat().resolvedOptions().timeZone,\n }).resolvedOptions().timeZone;\n } catch {\n return c.json({ error: \"timeZone must be a valid IANA time zone\" }, 400);\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 window: dateWindow,\n days: c.req.query(\"days\"),\n defaultDays: defaults.days,\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 = from == null ? undefined : { from: addCalendarDays(from, -days), to: from - 1 };\n const fixedTo = dateWindow.to;\n const cacheTo = fixedTo ?? startOfCalendarDay(to);\n const analyticsRevision = getAnalyticsRevision();\n // Keep all-time facts reusable by Projects; buildDashboard applies the current-time bound.\n const costFacts = getSnapshotCostFacts(\n scanSource,\n scanResult.sessions,\n compare?.from ?? from,\n from == null && fixedTo == null ? undefined : to,\n from == null && fixedTo == null ? undefined : 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 timeZone,\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 toPublicReferencedSessionHead({\n ...item,\n session: aliases.decorate(item.session, item.reference),\n }),\n ),\n recentFileActivities: data.recentFileActivities.map((activity) =>\n toPublicReferencedSessionHead(decorateFileActivity(activity, aliases)),\n ),\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","import { toPublicReferencedSessionHead, type SessionTree } from \"@codesesh/core/contract\";\nimport {\n getSearchProjectDirectory,\n listFileActivity,\n mergeSearchQueryOptions,\n} from \"@codesesh/core/runtime/discovery\";\nimport type { ProjectScopeMatcher } from \"@codesesh/core/runtime/projects\";\nimport { executeSessionSearch } from \"@codesesh/core/runtime/search\";\nimport type { Context } from \"hono\";\nimport type { ProjectIdentityResolver } from \"../project-identity-resolver.js\";\nimport {\n KNOWN_AGENT_NAMES,\n parseDateWindowRequest,\n projectScopeResolutionFailureResponse,\n reportInvalidQueryParameter,\n resolveProjectScope,\n} from \"./handler-support.js\";\nimport {\n FILE_ACTIVITY_LIMIT_POLICY,\n optionalQueryValue,\n parseFileActivityKind,\n parseProjectIdentityFilter,\n parseSearchOptions,\n parseSessionQuery,\n SEARCH_LIMIT_POLICY,\n searchParams,\n type SessionListDefaults,\n} from \"./query-params.js\";\nimport type { ScanResultSource } from \"./scan-sources.js\";\nimport { mergeAliasSearchResults, withParentContext } from \"./search-result-merge.js\";\nimport {\n decorateFileActivity,\n findAliasSearchResults,\n loadAliasView,\n} from \"./session-aliases-view.js\";\nimport { getSnapshotSessionTree } from \"./snapshot-aggregation.js\";\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(\n cwd,\n scanResult.sessions,\n resolver,\n c.req.raw.signal,\n );\n } catch (error) {\n return projectScopeResolutionFailureResponse(c, \"search\", error);\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 queryScope: scanSource.queryScope,\n ...(effectiveSearchOptions.costMin != null || effectiveSearchOptions.costMax != null\n ? { sessionTree: getSessionTree() }\n : {}),\n };\n const searchResults = executeSessionSearch(\n query,\n resolvedSearchOptions,\n scanResult,\n searchContext,\n );\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).map(\n toPublicReferencedSessionHead,\n ),\n });\n}\n\nexport async function handleGetFileActivity(\n c: Context,\n scanSource: ScanResultSource,\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, c.req.raw.signal);\n } catch (error) {\n return projectScopeResolutionFailureResponse(c, \"file-activity\", error);\n }\n }\n\n const aliases = loadAliasView();\n return c.json({\n activity: listFileActivity(\n {\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 },\n scanSource.queryScope,\n ).map((activity) => toPublicReferencedSessionHead(decorateFileActivity(activity, aliases))),\n });\n}\n","import { Worker } from \"node:worker_threads\";\nimport {\n materializeCachedSessionDetailResponse,\n type LiveSnapshot,\n type SessionDetailResponseResult,\n type SessionReference,\n} from \"@codesesh/core/runtime/discovery\";\nimport { getPricingGeneration } from \"@codesesh/core/runtime/pricing\";\nimport { appLogger } from \"./logging.js\";\nimport type {\n SessionDetailWorkerMessage,\n SessionDetailWorkerRequest,\n} from \"./session-detail-worker.js\";\nimport { terminateWorkerAfterLogDrain } from \"./worker-log-drain.js\";\n\nexport type SessionDetailLoader = (\n snapshot: LiveSnapshot,\n reference: SessionReference,\n options?: { messageCursor?: string },\n signal?: AbortSignal,\n) => SessionDetailResponseResult | Promise<SessionDetailResponseResult>;\n\nexport class SessionDetailBusyError extends Error {\n constructor() {\n super(\"Session detail workers are busy\");\n }\n}\n\nconst MAX_DETAIL_WORKERS = 2;\nconst DETAIL_TIMEOUT_MS = 60_000;\n\nexport class ThreadSessionDetailLoader {\n private readonly workers = new Set<Worker>();\n private readonly shutdownController = new AbortController();\n\n constructor(\n private readonly workerUrl = new URL(\"./session-detail-worker.js\", import.meta.url),\n ) {}\n\n readonly load: SessionDetailLoader = async (snapshot, reference, options = {}, signal) => {\n const requestSignal = signal\n ? AbortSignal.any([signal, this.shutdownController.signal])\n : this.shutdownController.signal;\n requestSignal.throwIfAborted();\n const cached = materializeCachedSessionDetailResponse(snapshot, reference, options);\n if (cached) return cached;\n if (this.workers.size >= MAX_DETAIL_WORKERS) throw new SessionDetailBusyError();\n const agent = snapshot.agents.find((item) => item.name === reference.agentName);\n const head = snapshot.byAgent[reference.agentName]?.find(\n (item) => item.reference.sessionId === reference.sessionId,\n );\n const meta = agent?.getSessionCacheMeta(reference.sessionId);\n const request: SessionDetailWorkerRequest = {\n reference,\n head,\n meta: meta ? { [reference.sessionId]: meta } : {},\n messageCursor: options.messageCursor,\n pricingGenerationId: getPricingGeneration().id,\n logContext: appLogger.captureContext(),\n };\n appLogger.info(\"session_detail.worker.started\", {\n agent: reference.agentName,\n session_id: reference.sessionId,\n });\n const worker = new Worker(this.workerUrl, { workerData: request });\n const exited = new Promise<void>((resolve) =>\n worker.once(\"exit\", () => {\n this.workers.delete(worker);\n resolve();\n }),\n );\n let timeout: ReturnType<typeof setTimeout> | undefined;\n let abort = () => {};\n try {\n return await new Promise<SessionDetailResponseResult>((resolve, reject) => {\n abort = () => reject(requestSignal.reason);\n requestSignal.addEventListener(\"abort\", abort, { once: true });\n this.workers.add(worker);\n timeout = setTimeout(\n () => reject(new Error(\"Session detail loading timed out\")),\n DETAIL_TIMEOUT_MS,\n );\n timeout.unref();\n worker.on(\"message\", (message: SessionDetailWorkerMessage) => {\n if (appLogger.consumeWorkerMessage(message)) return;\n if (message.type === \"result\") resolve(message.result);\n else if (message.type === \"error\") reject(new Error(message.error));\n });\n worker.once(\"error\", reject);\n worker.once(\"exit\", (code) =>\n reject(new Error(`Session detail worker exited without a result (${code})`)),\n );\n });\n } finally {\n clearTimeout(timeout);\n requestSignal.removeEventListener(\"abort\", abort);\n await terminateWorkerAfterLogDrain(worker);\n await exited;\n }\n };\n\n async shutdown(): Promise<void> {\n this.shutdownController.abort();\n await Promise.allSettled(\n [...this.workers].map((worker) => terminateWorkerAfterLogDrain(worker)),\n );\n }\n}\n","import type { SessionDetail } from \"@codesesh/core/runtime/discovery\";\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 { toPublicSessionHead, type SessionReference } from \"@codesesh/core/contract\";\nimport {\n materializeSessionDetailResponse,\n type SessionHead,\n type SmartTag,\n} from \"@codesesh/core/runtime/discovery\";\nimport {\n matchesProjectIdentity,\n matchesProjectScope as sessionMatchesProjectScope,\n type ProjectScopeMatcher,\n} from \"@codesesh/core/runtime/projects\";\nimport type { Context } from \"hono\";\nimport { appLogger } from \"../logging.js\";\nimport type { ProjectIdentityResolver } from \"../project-identity-resolver.js\";\nimport { SessionDetailBusyError, type SessionDetailLoader } from \"../session-detail-loader.js\";\nimport {\n KNOWN_AGENT_NAMES,\n parseDateWindowRequest,\n projectScopeResolutionFailureResponse,\n reportInvalidQueryParameter,\n resolveProjectScope,\n} from \"./handler-support.js\";\nimport {\n filterSessionsByActivityWindow,\n optionalQueryValue,\n parseProjectIdentityFilter,\n parseSessionQuery,\n searchParams,\n SESSION_PAGE_LIMIT_POLICY,\n type SessionListDefaults,\n} from \"./query-params.js\";\nimport type { ScanResultSource } from \"./scan-sources.js\";\nimport { createSessionDetailJsonResponse } from \"./session-detail-stream.js\";\nimport { loadAliasView, type AliasView } from \"./session-aliases-view.js\";\nimport { createSnapshotPaginator } from \"./snapshot-pagination.js\";\nimport { getSnapshotAggregation } from \"./snapshot-aggregation.js\";\n\nconst paginateSessions = createSnapshotPaginator<SessionHead, AliasView>();\n\nfunction getSessionHeadReference(session: SessionHead): SessionReference {\n return session.reference;\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(\n cwd,\n scanResult.sessions,\n resolver,\n c.req.raw.signal,\n );\n } catch (error) {\n return projectScopeResolutionFailureResponse(c, \"sessions\", error);\n }\n }\n\n if (sessionQuery.agent.kind === \"unknown\") {\n reportInvalidQueryParameter(\"sessions\", \"agent\", \"empty_result\");\n }\n\n const loadSnapshot = () => {\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) =>\n sessionMatchesProjectScope(session, projectScope),\n );\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 return { items: sessions, view: aliases };\n };\n\n if (paginationRequested) {\n const page = paginateSessions(\n scanSource,\n {\n cursor: params.get(\"cursor\") ?? undefined,\n limit: sessionQuery.limit.value,\n query: params,\n },\n loadSnapshot,\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 expired; restart pagination\" }, 409);\n }\n return c.json({\n sessions: page.items.map((session) =>\n toPublicSessionHead(page.view.decorate(session, getSessionHeadReference(session))),\n ),\n ...(page.nextCursor ? { nextCursor: page.nextCursor } : {}),\n });\n }\n\n const { items: sessions, view: aliases } = loadSnapshot();\n return c.json({\n sessions: sessions.map((session) =>\n toPublicSessionHead(aliases.decorate(session, getSessionHeadReference(session))),\n ),\n });\n}\n\nexport async function handleGetSessionData(\n c: Context,\n scanSource: ScanResultSource,\n loadDetail: SessionDetailLoader = materializeSessionDetailResponse,\n) {\n const startedAt = performance.now();\n const agentName = c.req.param(\"agent\");\n const sessionId = c.req.param(\"id\");\n\n if (!agentName) return c.json({ error: \"Missing agent name\" }, 400);\n if (!sessionId) return c.json({ error: \"Missing session ID\" }, 400);\n\n try {\n const reference = { agentName, sessionId };\n const messageCursor = optionalQueryValue(c.req.query(\"messageCursor\"));\n const result = await loadDetail(\n scanSource.getSnapshot(),\n reference,\n messageCursor ? { messageCursor } : {},\n c.req.raw.signal,\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 c.header(\"Retry-After\", \"1\");\n return c.json({ error: \"Session detail not ready; retry later\" }, 503);\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 (error) {\n if (error instanceof SessionDetailBusyError) {\n c.header(\"Retry-After\", \"1\");\n return c.json({ error: \"Session details busy; retry later\" }, 503);\n }\n const message = error instanceof Error ? error.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","import type { BookmarkRecord } from \"@codesesh/core/runtime/state\";\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, string | number | null> {\n if (!isRecord(value)) return {};\n\n const sanitized: Record<string, string | number | null> = {};\n for (const [key, item] of Object.entries(value)) {\n if (CLIENT_LOG_STRING_FIELDS.has(key) && typeof item === \"string\") {\n if (key === \"operation_id\" && !UUID_PATTERN.test(item)) continue;\n sanitized[key] = item.slice(0, 300);\n continue;\n }\n if (\n CLIENT_LOG_NUMBER_FIELDS.has(key) &&\n typeof item === \"number\" &&\n Number.isFinite(item) &&\n item >= 0\n ) {\n sanitized[key] = item;\n continue;\n }\n if (CLIENT_LOG_NULLABLE_FIELDS.has(key) && item === null) sanitized[key] = null;\n }\n return sanitized;\n}\n\nconst CLIENT_LOG_STRING_FIELDS = new Set([\n \"agent\",\n \"error_name\",\n \"mode\",\n \"operation_id\",\n \"phase\",\n \"profiler_id\",\n \"reason\",\n \"request_key\",\n \"session\",\n \"source\",\n \"trigger\",\n]);\n\nconst CLIENT_LOG_NUMBER_FIELDS = new Set([\n \"actual_duration_ms\",\n \"agents\",\n \"base_duration_ms\",\n \"commit_time_ms\",\n \"duration_ms\",\n \"error_status\",\n \"messages\",\n \"query_length\",\n \"results\",\n \"sessions\",\n \"start_time_ms\",\n]);\n\nconst CLIENT_LOG_NULLABLE_FIELDS = new Set([\"agent\", \"session\"]);\nconst UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;\n","import type { Context } from \"hono\";\nimport { appLogger } from \"../logging.js\";\nimport { sanitizeClientLogData } from \"./request-payloads.js\";\n\ninterface ClientLogPayload {\n event?: unknown;\n data?: unknown;\n}\n\nconst CLIENT_LOG_EVENTS = new Set<string>([\n \"app.load.done\",\n \"app.load.error\",\n \"app.load.start\",\n \"bookmark.add\",\n \"bookmark.delete\",\n \"react.profiler.commit\",\n \"route.change\",\n \"search.done\",\n \"search.error\",\n \"search.start\",\n \"session.markdown_copy.done\",\n \"session.markdown_copy.error\",\n \"session.open.cancel\",\n \"session.open.done\",\n \"session.open.error\",\n \"session.open.start\",\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\") {\n return c.json({ ok: false }, 400);\n }\n\n const event = rawEvent.trim();\n if (!CLIENT_LOG_EVENTS.has(event)) return c.json({ ok: false }, 400);\n\n appLogger.info(`client.${event}`, sanitizeClientLogData(payload?.data));\n return c.json({ ok: true });\n}\n","import type { Context } from \"hono\";\nimport type { BookmarkRecord, BookmarkView } from \"@codesesh/core/runtime/state\";\nimport { createSessionIndex, toPublicSessionHead } from \"@codesesh/core/contract\";\nimport {\n SessionAliasValidationError,\n StateStorageUnavailableError,\n deleteBookmark,\n deleteSessionAlias,\n importBookmarks,\n listBookmarks,\n materializeBookmarkViews,\n upsertBookmark,\n upsertSessionAlias,\n} from \"@codesesh/core/runtime/state\";\nimport { loadCachedSessionHeads } from \"@codesesh/core/runtime/discovery\";\nimport { KNOWN_AGENT_NAME_SET } from \"./handler-support.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) => {\n const decorated = decorateBookmark(bookmark, aliases);\n return decorated.availability === \"available\"\n ? { ...decorated, session: toPublicSessionHead(decorated.session) }\n : decorated;\n });\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({ error: \"Bookmark storage is unavailable\" }, 503),\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 { 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 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 ACCESS_TOKEN_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 remoteAccessRequired: 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\nfunction assertTrustedProxyListener(hostname: string, transport: RemoteTransport): void {\n if (transport.kind === \"trusted-proxy\" && !isLoopbackHostname(hostname)) {\n throw new RemoteTransportError(\n \"--trust-proxy requires a loopback --host so clients cannot reach the HTTP backend directly.\",\n );\n }\n}\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) {\n const transport = { kind: \"trusted-proxy\" } as const;\n assertTrustedProxyListener(request.hostname, transport);\n return transport;\n }\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 assertTrustedProxyListener(hostname, transport);\n const bindCategory = isLoopbackHostname(hostname) ? \"loopback\" : \"network\";\n const directLoopback = bindCategory === \"loopback\" && transport.kind === \"loopback\";\n return {\n bindCategory,\n remoteAccessRequired: !directLoopback,\n };\n}\n\nexport function resolvePublicOrigin(\n value: string | undefined,\n transport: RemoteTransport,\n): string | undefined {\n if (transport.kind !== \"trusted-proxy\") {\n if (value) throw new RemoteTransportError(\"--public-url requires --trust-proxy.\");\n return undefined;\n }\n if (!value) {\n throw new RemoteTransportError(\n \"--trust-proxy requires an HTTPS --public-url for browser startup links.\",\n );\n }\n\n let url: URL;\n try {\n url = new URL(value);\n } catch {\n throw new RemoteTransportError(\"--public-url must be a valid HTTPS origin.\");\n }\n if (\n url.protocol !== \"https:\" ||\n url.username ||\n url.password ||\n url.pathname !== \"/\" ||\n url.search ||\n url.hash\n ) {\n throw new RemoteTransportError(\n \"--public-url must be an HTTPS origin without credentials, path, query, or fragment.\",\n );\n }\n return url.origin;\n}\n\nconst FORWARDED_PROTO_HEADER = \"X-Forwarded-Proto\";\n\n/**\n * The forwarded scheme validates proxy configuration, not client identity.\n * The enforced loopback listener supplies the network boundary; the access\n * token still authenticates every request that reaches it.\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 createAccessToken(): 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(ACCESS_TOKEN_QUERY_PARAM);\n}\n\nexport function accessTokenAuth(expectedToken: string): MiddlewareHandler {\n return async (c, next) => {\n if (!tokenMatches(requestToken(c), expectedToken)) {\n return c.json({ error: \"API access token required\" }, 401);\n }\n await next();\n };\n}\n","import { existsSync } from \"node:fs\";\nimport { fileURLToPath } from \"node:url\";\nimport {\n closeCacheStorage,\n scanSessions,\n type LiveSnapshot,\n type ScanOptions,\n type SessionQueryScope,\n} from \"@codesesh/core/runtime/discovery\";\nimport { createRegisteredAgents } from \"@codesesh/core/runtime/agents\";\nimport { createProjectScopeMatcher } from \"@codesesh/core/runtime/projects\";\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;\n\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 readonly queryScope: SessionQueryScope;\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.queryScope = {\n ...(this.scanOptions.agents?.length\n ? { agents: this.scanOptions.agents.map((agent) => agent.toLowerCase()) }\n : {}),\n ...(this.scanOptions.cwd\n ? { projectScope: createProjectScopeMatcher(this.scanOptions.cwd) }\n : {}),\n };\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 { cwd: _cwd, ...scanOptions } = this.scanOptions;\n const initialResult = await scanSessions({\n ...scanOptions,\n useCache: this.scanOptions.useCache ?? true,\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 queryScope: this.queryScope,\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 source_enumeration_ms:\n timing.sourceEnumeration != null\n ? Math.round(timing.sourceEnumeration)\n : undefined,\n source_diff_ms:\n timing.sourceDiff != null ? Math.round(timing.sourceDiff) : undefined,\n source_parse_ms:\n timing.sourceParse != null ? Math.round(timing.sourceParse) : undefined,\n enumerated_sources: timing.enumeratedSources,\n changed_sources: timing.changedSources,\n processed_sources: timing.processedSources,\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.newSessionRefs.length > 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","import { readAgentLastFullSyncAt, type ScanOptions } from \"@codesesh/core/runtime/discovery\";\nimport { type BaseAgent } from \"@codesesh/core/runtime/agents\";\nimport type {\n BackfillAttemptRef,\n BackfillLifecycle,\n BackfillTerminalStatus,\n} from \"./backfill-lifecycle.js\";\nimport { appLogger } from \"./logging.js\";\nimport type { ScanStatusReporter } from \"./scan-status-reporter.js\";\n\nexport interface AgentBackfillSchedulerOptions {\n lifecycle: BackfillLifecycle;\n statusReporter: ScanStatusReporter;\n startupScanOptions: Pick<ScanOptions, \"from\" | \"to\">;\n runAttempt(attempt: BackfillAttemptRef): Promise<BackfillTerminalStatus>;\n scheduleRefresh(agentName: string, delayMs: number): void;\n}\n\nconst BACKFILL_INTERVAL_MS = 24 * 60 * 60 * 1000;\nconst PARTIAL_BACKFILL_RETRY_DELAY_MS = 5 * 60 * 1000;\n\n/**\n * Owns backfill eligibility, queue progression, retries, and full-sync\n * validity windows. The sync engine supplies only the actual scan operation.\n */\nexport class AgentBackfillScheduler {\n private readonly cacheIntegrityValidUntilByAgent = new Map<string, number>();\n private isShuttingDown = false;\n\n constructor(private readonly options: AgentBackfillSchedulerOptions) {}\n\n needsBackfill(agent: BaseAgent): boolean {\n const { from, to } = this.options.startupScanOptions;\n if (from == null && 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 this.cacheIntegrityValidUntilByAgent.set(agent.name, lastSyncAt + BACKFILL_INTERVAL_MS);\n return false;\n }\n\n enqueue(agentName: string): void {\n if (this.isShuttingDown || !this.options.lifecycle.enqueue(agentName)) return;\n this.options.statusReporter.publishBackfillStatus();\n this.pump();\n }\n\n shutdown(): void {\n this.isShuttingDown = true;\n this.options.lifecycle.cancelAll();\n this.cacheIntegrityValidUntilByAgent.clear();\n }\n\n private pump(): void {\n if (this.isShuttingDown) return;\n const attempt = this.options.lifecycle.startNext();\n if (!attempt) return;\n this.options.statusReporter.publishBackfillStatus();\n void this.options\n .runAttempt(attempt)\n .then((result) => this.complete(attempt, result))\n .catch((error) => this.reject(attempt, error));\n }\n\n private complete(attempt: BackfillAttemptRef, result: BackfillTerminalStatus): void {\n if (this.isShuttingDown) return;\n const current = this.options.lifecycle.stateFor(attempt.agentName);\n if (current?.status === \"running\" && current.attemptId === attempt.attemptId) {\n this.options.statusReporter.flushProgressStatus(`backfill:${attempt.agentName}`);\n if (this.options.lifecycle.complete(attempt, result)) {\n if (result === \"failed\") {\n this.cacheIntegrityValidUntilByAgent.delete(attempt.agentName);\n } else if (result === \"committed\") {\n if (current.completion?.completeness === \"partial\") {\n this.cacheIntegrityValidUntilByAgent.delete(attempt.agentName);\n this.options.scheduleRefresh(attempt.agentName, PARTIAL_BACKFILL_RETRY_DELAY_MS);\n appLogger.info(\"scan.backfill.retry_scheduled\", {\n agent: attempt.agentName,\n delay_ms: PARTIAL_BACKFILL_RETRY_DELAY_MS,\n });\n } else {\n this.cacheIntegrityValidUntilByAgent.set(\n attempt.agentName,\n Date.now() + BACKFILL_INTERVAL_MS,\n );\n }\n }\n this.options.statusReporter.publishBackfillStatus();\n }\n }\n this.pump();\n }\n\n private reject(attempt: BackfillAttemptRef, error: unknown): void {\n appLogger.error(\"scan.backfill.queue_error\", { agent: attempt.agentName, error });\n this.complete(attempt, \"failed\");\n }\n}\n","import { appLogger } from \"./logging.js\";\n\nexport type AgentOperationKind = \"backfill\" | \"refresh\";\n\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 operationId: string;\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 return appLogger.runWithContext({ operation_id: lifecycle.operationId }, async () => {\n this.logOperationStarted(lifecycle);\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 });\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 return {\n agentName,\n kind,\n generation,\n operationId: `${agentName}:${generation}`,\n startedAt,\n };\n }\n\n private logOperationStarted(lifecycle: AgentOperationLifecycle): void {\n appLogger.info(\"scan.agent_operation.started\", {\n agent: lifecycle.agentName,\n operation: lifecycle.kind,\n generation: lifecycle.generation,\n started_at: lifecycle.startedAt,\n });\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 const phaseChanged = progress.phase != null && progress.phase !== current.progress?.phase;\n this.attempts.set(attempt.agentName, {\n ...current,\n progress: phaseChanged ? { ...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 matchesSessionQueryScope,\n sessionSignature,\n type AgentCacheFailure,\n sortSessions,\n type IdentifiedSessionHead,\n type LiveSnapshot,\n type SessionQueryScope,\n} from \"@codesesh/core/runtime/discovery\";\nimport { type AgentScanFailure, type BaseAgent } from \"@codesesh/core/runtime/agents\";\nimport {\n assertIdentifiedSessionHead,\n assertSessionIdentity,\n createSessionProjectionContext,\n toPublicReferencedSessionHead,\n type SessionsUpdatedEvent,\n} from \"@codesesh/core/contract\";\n\nexport interface LiveSessionIndexOptions {\n registeredAgents?: BaseAgent[];\n queryScope?: SessionQueryScope;\n}\n\nexport class LiveSessionIndex {\n private agents: BaseAgent[] = [];\n private agentsByName = new Map<string, BaseAgent>();\n private queryScope?: SessionQueryScope;\n private allByAgent: Record<string, IdentifiedSessionHead[]> = {};\n private byAgent: Record<string, IdentifiedSessionHead[]> = {};\n private sessions: IdentifiedSessionHead[] = [];\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 this.queryScope = options.queryScope;\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) =>\n !this.queryScope?.agents?.length ||\n this.queryScope.agents.includes(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.allByAgent = {};\n this.byAgent = Object.fromEntries(\n this.agents.flatMap((agent) => {\n if (this.scanFailures[agent.name] && !(agent.name in snapshot.byAgent)) return [];\n const sessions = snapshot.byAgent[agent.name] ?? [];\n for (const session of sessions) {\n assertSessionIdentity(session, agent.name);\n assertIdentifiedSessionHead(session);\n }\n this.allByAgent[agent.name] = sortSessions(sessions);\n return [[agent.name, this.visibleSessions(this.allByAgent[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 agentSessions(agentName: string): IdentifiedSessionHead[] {\n return this.allByAgent[agentName] ?? [];\n }\n\n commitAgentSessions(\n agentName: string,\n nextSessions: IdentifiedSessionHead[],\n candidateChangedIds: string[] = [],\n ): SessionsUpdatedEvent | null {\n for (const session of nextSessions) {\n assertSessionIdentity(session, agentName);\n assertIdentifiedSessionHead(session);\n }\n const visibleSessions = this.visibleSessions(nextSessions);\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 visibleSessions,\n candidateChangedIds,\n sessionSignature,\n signatureCache,\n );\n for (const removedId of removedSessionIds) signatureCache.delete(removedId);\n\n this.allByAgent[agentName] = sortSessions(nextSessions);\n const hasChanges = counts.new > 0 || counts.updated > 0 || counts.removed > 0;\n if (!hasChanges && agentName in this.byAgent) return null;\n this.byAgent[agentName] = this.visibleSessions(this.allByAgent[agentName]!);\n this.sessions = mergeSortedSessions(Object.values(this.byAgent));\n if (!hasChanges) return null;\n\n const changedSessionHeads = changes.map(({ session }) => ({\n reference: session.reference,\n session,\n }));\n const previousSessionIds = new Set(\n previousSessions.map((session) => session.reference.sessionId),\n );\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 newSessionRefs,\n totalSessions: this.sessions.length,\n timestamp: Date.now(),\n changedSessionHeads: changedSessionHeads.map(toPublicReferencedSessionHead),\n projectionRelatedSessionHeads: projectionContext.relatedSessionHeads.map(\n toPublicReferencedSessionHead,\n ),\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 private visibleSessions(sessions: IdentifiedSessionHead[]): IdentifiedSessionHead[] {\n if (!this.queryScope?.projectScope) return sessions;\n return sessions.filter((session) => matchesSessionQueryScope(session, this.queryScope));\n }\n}\n","import { existsSync } from \"node:fs\";\nimport { fileURLToPath } from \"node:url\";\nimport { Worker } from \"node:worker_threads\";\nimport { getPricingGeneration } from \"@codesesh/core/runtime/pricing\";\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 SearchIndexPublicationProgress,\n SearchIndexWorkerRunRequest,\n} from \"./search-index-worker.js\";\nimport { terminateWorkerAfterLogDrain } from \"./worker-log-drain.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 private retirements = new Set<Promise<number>>();\n\n enqueue(\n context: string,\n jobs: SearchIndexWorkerJob[],\n onStarted?: () => void,\n onProgress?: (progress: SearchIndexPublicationProgress) => void,\n ): Promise<void> {\n return this.enqueueIn(this.pendingJobs, context, jobs, onStarted, onProgress);\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 onProgress?: (progress: SearchIndexPublicationProgress) => 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(\n batchId,\n context,\n jobs,\n onStarted,\n onProgress,\n appLogger.captureContext(),\n );\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 const activeRetirement = worker ? this.retireWorker(worker) : null;\n const retirements = [...this.retirements];\n try {\n if (activeRetirement) await activeRetirement;\n } finally {\n await Promise.allSettled(retirements);\n }\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.restoreContext(batch.logContext, () => {\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\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 logContext: batch.logContext,\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 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 appLogger.restoreContext(activeBatch.logContext, () => {\n this.handleWorkerMessage(activeBatch, message);\n });\n });\n worker.on(\"error\", (error) => {\n const activeBatch = this.worker === worker ? this.activeBatch : null;\n appLogger.restoreContext(activeBatch?.logContext ?? {}, () => {\n appLogger.error(\"search_index.worker_error\", {\n context: activeBatch?.context,\n error,\n });\n this.invalidateWorker(worker, toError(error));\n });\n });\n worker.on(\"exit\", (code) => {\n const activeBatch = this.worker === worker ? this.activeBatch : null;\n appLogger.restoreContext(activeBatch?.logContext ?? {}, () =>\n this.finishWorker(worker, code),\n );\n });\n }\n\n private handleWorkerMessage(\n activeBatch: SearchIndexJobBatch,\n message: SearchIndexWorkerMessage,\n ): void {\n if (message.type === \"publication-progress\") {\n const { agentName, stage } = message;\n activeBatch.progress({ agentName, stage }, (error) => {\n appLogger.error(\"search_index.worker_progress_listener_failed\", {\n batch_id: activeBatch.id,\n context: activeBatch.context,\n error: toError(error),\n });\n });\n return;\n }\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\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 this.retireWorker(worker);\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 appLogger.restoreContext(batch.logContext, () => {\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\n private retireWorker(worker: Worker): Promise<number> {\n const retirement = terminateWorkerAfterLogDrain(worker);\n this.retirements.add(retirement);\n void retirement.finally(() => this.retirements.delete(retirement)).catch(() => undefined);\n return retirement;\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 IdentifiedSessionHead,\n PersistedSessionHeadChange,\n} from \"@codesesh/core/runtime/discovery\";\nimport type { SessionCacheMeta } from \"@codesesh/core/runtime/agents\";\nimport type {\n SearchIndexPublicationProgress,\n SearchIndexWorkerJob,\n SearchIndexWorkerOptions,\n} from \"./search-index-worker.js\";\nimport type { LogContext } from \"./logging.js\";\n\ntype FullSearchIndexJob = Extract<SearchIndexWorkerJob, { kind: \"full\" }>;\n\ntype ChangesSearchIndexJob = Extract<SearchIndexWorkerJob, { kind: \"changes\" }>;\n\ntype MaintenanceSearchIndexJob = Extract<SearchIndexWorkerJob, { kind: \"maintenance\" }>;\n\ntype IncrementalSearchIndexJob = ChangesSearchIndexJob | MaintenanceSearchIndexJob;\n\nconst LOG_CONTEXT_KEYS = [\"request_id\", \"operation_id\", \"publication_id\"] as const;\n\nfunction commonLogContext(left: LogContext, right: LogContext): LogContext {\n const common: LogContext = {};\n for (const key of LOG_CONTEXT_KEYS) {\n if (left[key] !== undefined && left[key] === right[key]) common[key] = left[key];\n }\n return common;\n}\n\ninterface JobWaiter {\n resolve: () => void;\n reject: (error: Error) => void;\n onStarted?: () => void;\n onProgress?: (progress: SearchIndexPublicationProgress) => void;\n agentNames: Set<string>;\n}\n\ninterface PendingChanges {\n kind: IncrementalSearchIndexJob[\"kind\"];\n context: string;\n agentName: string;\n publicationId?: string;\n changesBySessionId: Map<string, PersistedSessionHeadChange<IdentifiedSessionHead>>;\n removedSessionIds: Set<string>;\n meta: Record<string, SessionCacheMeta>;\n searchIndexOptions?: SearchIndexWorkerOptions;\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 logContext: LogContext;\n readonly jobs: SearchIndexWorkerJob[];\n start(onError: (error: unknown) => void): void;\n progress(progress: SearchIndexPublicationProgress, onError: (error: unknown) => void): void;\n}\n\nclass PendingSearchIndexJobBatch implements SearchIndexJobBatch {\n context: string;\n logContext: LogContext;\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 logContext: LogContext,\n ) {\n this.context = context;\n this.logContext = logContext;\n this.merge(context, jobs, waiter, logContext);\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 progress(progress: SearchIndexPublicationProgress, onError: (error: unknown) => void): void {\n for (const waiter of this.waiters) {\n if (!waiter.agentNames.has(progress.agentName)) continue;\n try {\n waiter.onProgress?.(progress);\n } catch (error) {\n onError(error);\n }\n }\n }\n\n merge(\n context: string,\n jobs: SearchIndexWorkerJob[],\n waiter: JobWaiter,\n logContext: LogContext,\n ): void {\n this.context = context;\n this.logContext = commonLogContext(this.logContext, logContext);\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 onProgress?: (progress: SearchIndexPublicationProgress) => void,\n logContext: LogContext = {},\n ): Promise<void> {\n if (jobs.length === 0) return Promise.resolve();\n\n return new Promise((resolve, reject) => {\n const waiter = {\n resolve,\n reject,\n onStarted,\n onProgress,\n agentNames: new Set(jobs.map((job) => job.agentName)),\n };\n if (this.pendingBatch) {\n this.pendingBatch.merge(context, jobs, waiter, logContext);\n } else {\n this.pendingBatch = new PendingSearchIndexJobBatch(id, context, jobs, waiter, logContext);\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.reference.sessionId;\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: SearchIndexWorkerOptions | undefined,\n incoming: SearchIndexWorkerOptions | undefined,\n): SearchIndexWorkerOptions | 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 readCachedSessions,\n readPendingSearchIndexMaintenance,\n type CachedResult,\n type IdentifiedSessionHead,\n type PersistedSessionHeadChange,\n} from \"@codesesh/core/runtime/discovery\";\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\ninterface IndexedSessionCache {\n sessionsById: Map<string, PersistedSessionHeadChange<IdentifiedSessionHead>>;\n meta: CachedResult[\"meta\"];\n}\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<string, IndexedSessionCache>();\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: Pick<SearchIndexJobRunner, \"enqueueMaintenance\">,\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 let cached = this.cachedSessionsByAgent.get(agentName);\n if (!cached) {\n const outcome = readCachedSessions(agentName);\n if (outcome.status === \"failed\") {\n throw new Error(`Session cache read failed for ${agentName}`);\n }\n if (!outcome.value) throw new Error(`Session cache is unavailable for ${agentName}`);\n cached = {\n sessionsById: new Map(\n outcome.value.sessions.map((session, sortIndex) => [\n session.reference.sessionId,\n { session, sortIndex },\n ]),\n ),\n meta: outcome.value.meta,\n };\n this.cachedSessionsByAgent.set(agentName, cached);\n }\n const changes = pending.sessionIds.flatMap(\n (sessionId): PersistedSessionHeadChange<IdentifiedSessionHead>[] => {\n const change = cached.sessionsById.get(sessionId);\n return change ? [change] : [];\n },\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 sessionId = session.reference.sessionId;\n const sessionMeta = cached.meta[sessionId];\n return sessionMeta ? [[sessionId, 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/runtime/agents\";\nimport type {\n BackfillStatus,\n ScanCompletion,\n ScanStatusEvent,\n SearchIndexMaintenanceStatus,\n} from \"@codesesh/core/contract\";\n\ntype ScanStatus = Omit<\n ScanStatusEvent,\n | \"type\"\n | \"active\"\n | \"pendingAgents\"\n | \"scanningAgents\"\n | \"completedAgents\"\n | \"totalAgents\"\n | \"searchIndexMaintenance\"\n> & {\n searchIndexMaintenance: SearchIndexMaintenanceStatus;\n};\n\ninterface AgentLists {\n pendingAgents: string[];\n scanningAgents: string[];\n completedAgents: string[];\n}\n\nexport class ScanStatusModel {\n private status: ScanStatus = {\n phase: \"idle\",\n agentStatuses: {},\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 agentLists = this.agentLists(this.status.agentStatuses);\n const active = this.hasActiveAgents(this.status.agentStatuses);\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 active,\n ...agentLists,\n totalAgents: Object.keys(this.status.agentStatuses).length,\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 phase: uniqueAgentNames.length > 0 ? phase : \"idle\",\n agentStatuses,\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.hasActiveAgents(this.status.agentStatuses)) return null;\n return this.set({ ...this.status, phase, updatedAt: Date.now() });\n }\n\n beginAgent(agentName: string, sessionCount: number): ScanStatusEvent {\n if (!this.hasActiveAgents(this.status.agentStatuses)) {\n this.startBatch([agentName], \"scanning\", { [agentName]: sessionCount });\n }\n\n const existingStatus = this.status.agentStatuses[agentName];\n const now = Date.now();\n return this.set({\n ...this.status,\n phase: this.status.phase === \"initializing\" ? \"initializing\" : \"scanning\",\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 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(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.hasActiveAgents(this.status.agentStatuses) ||\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(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.hasActiveAgents(this.status.agentStatuses) ||\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(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 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 const isActive = this.hasActiveAgents(agentStatuses);\n\n return this.set({\n ...this.status,\n phase: isActive ? this.activePhase(agentStatuses) : \"idle\",\n agentStatuses,\n updatedAt: now,\n completedAt: isActive ? undefined : now,\n });\n }\n\n failAgent(agentName: string, error: string, sessionCount?: number): ScanStatusEvent {\n const now = Date.now();\n const previousStatus = this.status.agentStatuses[agentName];\n const agentStatuses = {\n ...this.status.agentStatuses,\n [agentName]: {\n agentName,\n status: \"failed\" as const,\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 const isActive = this.hasActiveAgents(agentStatuses);\n return this.set({\n ...this.status,\n phase: isActive ? this.activePhase(agentStatuses) : \"idle\",\n agentStatuses,\n updatedAt: now,\n completedAt: isActive ? undefined : now,\n });\n }\n\n finishBatch(): ScanStatusEvent {\n const now = Date.now();\n return this.set({\n ...this.status,\n phase: \"idle\",\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(agentStatuses: ScanStatus[\"agentStatuses\"]): ScanStatusEvent[\"phase\"] {\n const { pendingAgents, scanningAgents } = this.agentLists(agentStatuses);\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 agentLists(agentStatuses: ScanStatus[\"agentStatuses\"]): AgentLists {\n const pendingAgents: string[] = [];\n const scanningAgents: string[] = [];\n const completedAgents: string[] = [];\n\n for (const [agentName, status] of Object.entries(agentStatuses)) {\n if (status.status === \"pending\") pendingAgents.push(agentName);\n else if (status.status === \"complete\") completedAgents.push(agentName);\n else if (status.status !== \"failed\") scanningAgents.push(agentName);\n }\n\n return { pendingAgents, scanningAgents, completedAgents };\n }\n\n private hasActiveAgents(agentStatuses: ScanStatus[\"agentStatuses\"]): boolean {\n return Object.values(agentStatuses).some(\n (status) => status.status !== \"complete\" && status.status !== \"failed\",\n );\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/runtime/agents\";\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 {\n buildAgentCacheMeta,\n type CachedResult,\n type LiveSnapshot,\n type IdentifiedSessionHead,\n} from \"@codesesh/core/runtime/discovery\";\nimport { appLogger } from \"./logging.js\";\nimport type { SearchIndexJobRunner } from \"./search-index-job-runner.js\";\nimport type {\n SearchIndexPublicationProgress,\n SearchIndexWorkerJob,\n} from \"./search-index-worker.js\";\n\nexport interface SearchIndexPublisherOptions {\n jobs: SearchIndexJobRunner;\n snapshot(): LiveSnapshot;\n agentSessions(agentName: string): IdentifiedSessionHead[];\n readCachedSessions(agentName: string): CachedResult | 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: this.options.agentSessions(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 onProgress?: (progress: SearchIndexPublicationProgress) => 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.onProgress\n ? this.options.jobs.enqueue(context, publicationJobs, details.onStarted, details.onProgress)\n : 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 type { IdentifiedSessionHead } from \"@codesesh/core/runtime/discovery\";\nimport type { SessionsUpdatedEvent } from \"@codesesh/core/contract\";\nimport type { LiveSessionIndex } from \"./live-session-index.js\";\nimport { appLogger } from \"./logging.js\";\nimport type { SearchIndexPublisher } from \"./search-index-publisher.js\";\nimport type {\n SearchIndexPublicationProgress,\n SearchIndexWorkerJob,\n} from \"./search-index-worker.js\";\nimport type { StagedWorkerRun } from \"./worker-runner.js\";\n\nexport interface AgentSessionsChanged {\n agentName: string;\n sessions: IdentifiedSessionHead[];\n event: SessionsUpdatedEvent | null;\n}\n\nexport interface SessionPublication {\n context: \"scan.refresh\" | \"scan.backfill\";\n agentName: string;\n sessions: IdentifiedSessionHead[];\n candidateChangedIds: string[];\n indexJob: SearchIndexWorkerJob;\n stagedRun?: StagedWorkerRun;\n onPublishing?: () => void;\n onPublicationProgress?: (progress: SearchIndexPublicationProgress) => void;\n onCommitted?: (result: SessionPublicationResult) => void;\n}\n\nexport interface SessionPublicationResult {\n event: SessionsUpdatedEvent | null;\n diffDuration: number;\n}\n\ntype SessionsChangedListener = (change: AgentSessionsChanged) => void;\n\n/**\n * Commits one durable search-index publication before updating the in-memory\n * session projection and notifying subscribers.\n */\nexport class SessionPublicationCoordinator {\n private readonly listeners = new Set<SessionsChangedListener>();\n private isShuttingDown = false;\n\n constructor(\n private readonly indexPublisher: SearchIndexPublisher,\n private readonly sessionIndex: LiveSessionIndex,\n ) {}\n\n subscribe(listener: SessionsChangedListener): () => void {\n this.listeners.add(listener);\n return () => this.listeners.delete(listener);\n }\n\n markShuttingDown(): void {\n this.isShuttingDown = true;\n }\n\n async commit(publication: SessionPublication): 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 ...(publication.onPublicationProgress\n ? { onProgress: publication.onPublicationProgress }\n : {}),\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 = { event, diffDuration };\n this.runPostCommit(publication, \"worker_commit\", () => publication.stagedRun?.commit());\n this.runPostCommit(publication, \"callback\", () => publication.onCommitted?.(result));\n this.runPostCommit(publication, \"notification\", () =>\n this.emit({\n agentName: publication.agentName,\n sessions: this.sessionIndex.snapshot().byAgent[publication.agentName] ?? [],\n event,\n }),\n );\n this.runPostCommit(publication, \"logging\", () =>\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 );\n return result;\n }\n\n private runPostCommit(\n publication: SessionPublication,\n stage: \"worker_commit\" | \"callback\" | \"notification\" | \"logging\",\n action: () => void,\n ): void {\n try {\n action();\n } catch (error) {\n try {\n appLogger.error(\"session.publication.post_commit_error\", {\n context: publication.context,\n agent: publication.agentName,\n stage,\n error,\n });\n } catch {}\n }\n }\n\n private emit(change: AgentSessionsChanged): void {\n if (this.isShuttingDown) return;\n for (const listener of this.listeners) {\n try {\n listener(change);\n } catch (error) {\n appLogger.error(\"session.publication.post_commit_error\", {\n agent: change.agentName,\n error,\n });\n }\n }\n }\n}\n","import {\n attachMissingProjectIdentities,\n beginAgentRefresh,\n buildAgentCacheMeta,\n buildSessionPersistenceDiff,\n getAgentFullSyncCursor,\n markAgentFullSyncProgress,\n markAgentFullSyncStarted,\n markAgentFullSyncCompleted,\n readCachedSessions,\n readAgentCacheInitialization,\n resolveSessionSnapshotCompleteness,\n type AgentRefreshTransaction,\n type AgentRefreshSelection,\n type CachedResult,\n type IdentifiedSessionHead,\n type ScanOptions,\n type LiveSnapshot,\n type SessionHead,\n type SessionPersistenceDiff,\n type SessionSnapshotCompleteness,\n} from \"@codesesh/core/runtime/discovery\";\nimport { type BaseAgent, type SessionSourceFailure } from \"@codesesh/core/runtime/agents\";\nimport type {\n ScanCompletion,\n ScanStatusEvent,\n SessionsUpdatedEvent,\n} from \"@codesesh/core/contract\";\nimport { AgentBackfillScheduler } from \"./agent-backfill-scheduler.js\";\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 {\n SessionPublicationCoordinator,\n type AgentSessionsChanged,\n type SessionPublicationResult,\n} from \"./session-publication.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 { StagedWorkerRun, WorkerRunner } from \"./worker-runner.js\";\nimport { toError } from \"./errors.js\";\n\nexport type { AgentOperationResult } from \"./agent-operation-scheduler.js\";\nexport type { AgentSessionsChanged } from \"./session-publication.js\";\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;\n\ntype StatusChangedListener = (event: ScanStatusEvent) => void;\n\ntype CachedSessions = CachedResult;\n\ninterface RefreshResult {\n result: Exclude<AgentOperationResult, \"failed\">;\n completion: ScanCompletion;\n}\n\ninterface PendingAgentState {\n meta: CachedSessions[\"meta\"];\n refreshedAt?: number;\n refreshTransaction?: AgentRefreshTransaction;\n}\n\nfunction countSessionUpdates(event: SessionsUpdatedEvent | null): {\n newSessions: number;\n updatedSessions: number;\n removedSessions: number;\n} {\n if (!event) return { newSessions: 0, updatedSessions: 0, removedSessions: 0 };\n return {\n newSessions: event.newSessionRefs.length,\n updatedSessions: event.changedSessionHeads.length - event.newSessionRefs.length,\n removedSessions: event.removedSessionRefs.length,\n };\n}\n\ninterface RefreshStrategyBase {\n nextSessions: IdentifiedSessionHead[];\n checkDuration: number;\n scanDuration: number;\n sourceFailures: SessionSourceFailure[];\n completeness: SessionSnapshotCompleteness;\n scope: Pick<ScanOptions, \"from\" | \"to\">;\n workerRun?: StagedWorkerRun;\n pendingAgentState?: PendingAgentState;\n}\n\ntype RefreshPublication =\n | {\n kind: \"changes\";\n diff: SessionPersistenceDiff<IdentifiedSessionHead>;\n candidateChangedIds: string[];\n }\n | {\n kind: \"full\";\n sessions: IdentifiedSessionHead[];\n explicitRemovedSessionIds: string[];\n };\n\ntype RefreshStrategyResult =\n | (RefreshStrategyBase & { status: \"unchanged\" })\n | (RefreshStrategyBase & { status: \"continue\"; publication: RefreshPublication });\n\nconst REFRESH_DEBOUNCE_MS = 200;\nconst EMPTY_AGENT_REFRESH_DEBOUNCE_MS = 30_000;\n// SSE carries one compact summary; logs retain the complete failure list.\nconst SOURCE_FAILURE_SUMMARY_MAX_LENGTH = 160;\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 selectCacheMeta(\n meta: CachedSessions[\"meta\"],\n sessionIds?: ReadonlySet<string>,\n): CachedSessions[\"meta\"] {\n if (!sessionIds) return { ...meta };\n const selected: CachedSessions[\"meta\"] = {};\n for (const sessionId of sessionIds) {\n const entry = meta[sessionId];\n if (entry) selected[sessionId] = entry;\n }\n return selected;\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 readonly backfillScheduler: AgentBackfillScheduler;\n private readonly statusReporter: ScanStatusReporter;\n private readonly indexPublisher: SearchIndexPublisher;\n private readonly sessionPublication: SessionPublicationCoordinator;\n private readonly searchIndexJobs: SearchIndexJobRunner;\n private readonly searchIndexMaintenance: SearchIndexMaintenanceScheduler;\n private backgroundRefreshTimer: NodeJS.Timeout | null = null;\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 agentSessions: (agentName) => this.sessionIndex.agentSessions(agentName),\n readCachedSessions: (agentName) => this.readCachedSessionsOrWarn(\"search.index\", agentName),\n });\n this.sessionPublication = new SessionPublicationCoordinator(\n this.indexPublisher,\n this.sessionIndex,\n );\n this.backfillScheduler = new AgentBackfillScheduler({\n lifecycle: this.backfills,\n statusReporter: this.statusReporter,\n startupScanOptions: this.startupScanOptions(),\n runAttempt: (attempt) => this.runBackfill(attempt),\n scheduleRefresh: (agentName, delayMs) => this.scheduler.schedule(agentName, delayMs),\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 return this.sessionPublication.subscribe(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.sessionPublication.markShuttingDown();\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.backfillScheduler.shutdown();\n this.searchIndexMaintenance.stop();\n this.statusReporter.markShuttingDown();\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 reportPostCommitError(\n operation: \"scan.refresh\" | \"scan.backfill\",\n agentName: string,\n error: unknown,\n ): void {\n appLogger.error(`${operation}.post_commit_error`, { agent: agentName, error });\n }\n\n private commitAgentState(\n operation: \"scan.refresh\" | \"scan.backfill\",\n agent: BaseAgent,\n state?: PendingAgentState,\n ): void {\n if (!state) return;\n try {\n agent.restoreSessionCacheMeta(state.meta);\n if (state.refreshedAt != null) {\n this.lastRefreshAtByAgent.set(agent.name, state.refreshedAt);\n }\n } catch (error) {\n this.reportPostCommitError(operation, agent.name, error);\n return;\n }\n try {\n state.refreshTransaction?.commit();\n } catch (error) {\n this.reportPostCommitError(operation, agent.name, error);\n }\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 cached: CachedSessions | null = null;\n let refresh: { result: AgentOperationResult; completion: ScanCompletion } = {\n result: \"failed\",\n completion: { completeness: \"complete\" },\n };\n try {\n if (this.findAgent(agentName))\n cached = this.readCachedSessionsOrWarn(\"scan.refresh\", agentName);\n refresh = await this.runRefresh(agentName, cached, startedAt);\n } catch (error) {\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 try {\n if (refresh.result !== \"failed\") {\n if (refresh.result === \"committed\")\n this.finishCommittedAgentScan(agentName, refresh.completion);\n else this.statusReporter.finishAgentScan(agentName, refresh.completion);\n }\n } catch (error) {\n if (refresh.result !== \"committed\") throw error;\n this.reportPostCommitError(\"scan.refresh\", agentName, error);\n }\n // The backfill probe touches cache state and may check agent availability;\n // either operation can throw on transient errors, but that must not\n // fail — let alone reject — an otherwise finished refresh.\n try {\n const agent = this.findAgent(agentName);\n if (agent && this.backfillScheduler.needsBackfill(agent)) {\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 refresh.result;\n }\n\n private async runRefresh(\n agentName: string,\n cached: CachedSessions | null,\n startedAt: number,\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.agentSessions(agentName);\n const refreshBaseline = cached?.sessions ?? previousSessions;\n const cacheTimestamp = cached?.timestamp ?? this.lastRefreshAtByAgent.get(agentName) ?? 0;\n if (cached) agent.restoreSessionCacheMeta(cached.meta);\n const durableMeta = agent.snapshotSessionCacheMeta();\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 refreshTransaction = await beginAgentRefresh(agent, {\n initialized: isInitialized,\n sinceTimestamp: cacheTimestamp,\n cachedSessions: refreshBaseline,\n });\n const refresh = refreshTransaction.selection;\n const availabilityDuration = refresh.availabilityDurationMs;\n let strategyResult: RefreshStrategyResult;\n try {\n if (refresh.kind === \"unavailable\") {\n strategyResult = this.refreshUnavailableAgent(agentName);\n } else if (refresh.kind === \"initialize\") {\n strategyResult = await this.initializeAgent(agent, previousSessions);\n } else if (refresh.kind === \"synchronize\") {\n strategyResult = await this.syncAgentSources(\n agent,\n cached ?? {\n sessions: refreshBaseline,\n meta: durableMeta,\n },\n startedAt,\n );\n } else {\n strategyResult = await this.refreshChangedAgent(\n agent,\n refresh,\n refreshTransaction,\n refreshBaseline,\n startedAt,\n );\n }\n } finally {\n agent.restoreSessionCacheMeta(durableMeta);\n }\n const stagedRun = strategyResult.workerRun;\n if (strategyResult.status === \"unchanged\") {\n stagedRun?.commit();\n this.commitAgentState(\"scan.refresh\", agent, strategyResult.pendingAgentState);\n return {\n result: \"unchanged\",\n completion: buildScanCompletion(strategyResult.completeness, strategyResult.sourceFailures),\n };\n }\n\n const nextSessions = attachMissingProjectIdentities(strategyResult.nextSessions);\n const persistenceDiff =\n strategyResult.publication.kind === \"changes\" ? strategyResult.publication.diff : null;\n const publicationSessions =\n strategyResult.publication.kind === \"full\"\n ? strategyResult.publication.sessions\n : nextSessions;\n const explicitRemovedSessionIds =\n strategyResult.publication.kind === \"full\"\n ? strategyResult.publication.explicitRemovedSessionIds\n : [];\n const publicationSessionIds = new Set(\n publicationSessions.map((session) => session.reference.sessionId),\n );\n const missingBaselineSessions = refreshBaseline.reduce(\n (count, session) => count + Number(!publicationSessionIds.has(session.reference.sessionId)),\n 0,\n );\n const replacementDeleteCandidates = persistenceDiff\n ? persistenceDiff.removedSessionIds.length\n : strategyResult.completeness === \"complete\"\n ? missingBaselineSessions\n : 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.reference.sessionId))\n : undefined;\n const pendingMeta = strategyResult.pendingAgentState?.meta ?? durableMeta;\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: selectCacheMeta(pendingMeta, changedSessionIds),\n }\n : {\n kind: \"full\",\n context: \"scan.refresh\",\n agentName,\n sessions: publicationSessions,\n meta: selectCacheMeta(pendingMeta),\n completeness: strategyResult.completeness,\n removedSessionIds: explicitRemovedSessionIds,\n saveCache: true,\n };\n const completion = buildScanCompletion(\n strategyResult.completeness,\n strategyResult.sourceFailures,\n );\n this.statusReporter.queueAgentPublication(agentName);\n let publication: SessionPublicationResult;\n try {\n publication = await this.sessionPublication.commit({\n context: \"scan.refresh\",\n agentName,\n sessions: nextSessions,\n candidateChangedIds:\n strategyResult.publication.kind === \"changes\"\n ? strategyResult.publication.candidateChangedIds\n : [],\n indexJob: persistentJob,\n stagedRun,\n onPublishing: () => this.statusReporter.beginAgentPublishing(agentName),\n });\n } catch (error) {\n stagedRun?.discard();\n throw error;\n }\n this.commitAgentState(\"scan.refresh\", agent, strategyResult.pendingAgentState);\n const persistDuration = performance.now() - persistStartedAt;\n const totalDurationMs = performance.now() - startedAt;\n try {\n logSearchIndexSync(\"scan.refresh\", null, { pending_paths: pendingPathCount });\n this.scheduler.recordRefreshDuration(agentName, totalDurationMs);\n const sessionUpdateCounts = countSessionUpdates(publication.event);\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: sessionUpdateCounts.newSessions,\n updated_sessions: sessionUpdateCounts.updatedSessions,\n removed_sessions: sessionUpdateCounts.removedSessions,\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 } catch (error) {\n this.reportPostCommitError(\"scan.refresh\", agentName, error);\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 const previousSessions = this.sessionIndex.agentSessions(agentName);\n if (previousSessions.length > 0) {\n appLogger.warn(\"scan.refresh.agent_unavailable\", {\n agent: agentName,\n retained_sessions: previousSessions.length,\n });\n return {\n ...this.refreshStrategyBase(previousSessions, \"partial\", {}),\n status: \"unchanged\",\n };\n }\n return {\n ...this.refreshStrategyBase([], \"partial\", {}),\n status: \"continue\",\n publication: { kind: \"full\", sessions: [], explicitRemovedSessionIds: [] },\n };\n }\n\n private async initializeAgent(\n agent: BaseAgent,\n previousSessions: IdentifiedSessionHead[],\n ): Promise<RefreshStrategyResult> {\n this.statusReporter.setScanPhase(\"initializing\");\n const scanStartedAt = performance.now();\n const scope = this.startupScanOptions();\n const workerRun = await this.runWorker(agent, previousSessions, { kind: \"full-scan\" }, scope);\n try {\n const { result } = workerRun;\n const sessions = attachMissingProjectIdentities(result.sessions);\n return {\n ...this.refreshStrategyBase(sessions, result.completeness, scope, {\n scanDuration: performance.now() - scanStartedAt,\n sourceFailures: result.sourceFailures ?? [],\n workerRun,\n pendingAgentState: { meta: result.meta, refreshedAt: Date.now() },\n }),\n status: \"continue\",\n publication: {\n kind: \"full\",\n sessions,\n explicitRemovedSessionIds: result.explicitRemovedSessionIds,\n },\n };\n } catch (error) {\n workerRun.discard();\n throw error;\n }\n }\n\n private async syncAgentSources(\n agent: BaseAgent,\n baseline: Pick<CachedSessions, \"sessions\" | \"meta\">,\n refreshStartedAt: number,\n ): Promise<RefreshStrategyResult> {\n const scanStartedAt = performance.now();\n const scope = this.startupScanOptions();\n const workerRun = await this.runWorker(\n agent,\n baseline.sessions,\n { kind: \"source-refresh\" },\n scope,\n {\n meta: baseline.meta,\n },\n );\n try {\n const { result } = workerRun;\n const sessions = attachMissingProjectIdentities(result.sessions);\n const preciseChangedIds = result.changedIds ?? [];\n const persistenceDiff = buildSessionPersistenceDiff(baseline.sessions, sessions, {\n candidateChangedIds: preciseChangedIds,\n });\n const pendingAgentState = { meta: result.meta, refreshedAt: 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 {\n ...this.refreshStrategyBase(sessions, result.completeness, scope, {\n scanDuration: performance.now() - scanStartedAt,\n workerRun,\n pendingAgentState,\n }),\n status: \"unchanged\",\n };\n }\n return {\n ...this.refreshStrategyBase(sessions, result.completeness, scope, {\n scanDuration: performance.now() - scanStartedAt,\n sourceFailures: result.sourceFailures ?? [],\n workerRun,\n pendingAgentState,\n }),\n status: \"continue\",\n publication: {\n kind: \"changes\",\n diff: persistenceDiff,\n candidateChangedIds: preciseChangedIds,\n },\n };\n } catch (error) {\n workerRun.discard();\n throw error;\n }\n }\n\n private async refreshChangedAgent(\n agent: BaseAgent,\n refresh: Exclude<AgentRefreshSelection, { kind: \"unavailable\" | \"initialize\" | \"synchronize\" }>,\n refreshTransaction: AgentRefreshTransaction,\n baseline: IdentifiedSessionHead[],\n refreshStartedAt: number,\n ): Promise<RefreshStrategyResult> {\n const scope = this.startupScanOptions();\n if (refresh.kind === \"failed\") {\n appLogger.warn(\"scan.refresh.change_check_failed\", {\n agent: agent.name,\n source_path: refresh.failure.sourcePath,\n error_class: refresh.failure.errorClass,\n message: refresh.failure.message,\n });\n return {\n ...this.refreshStrategyBase(\n baseline,\n \"partial\",\n {},\n {\n checkDuration: refresh.checkDurationMs,\n },\n ),\n status: \"unchanged\",\n };\n }\n const { check: checkResult, source } = refresh;\n const checkDuration = refresh.checkDurationMs;\n if (refresh.kind === \"recompute-derived\") {\n const scanStartedAt = performance.now();\n const workerRun = await this.runWorker(agent, baseline, { kind: \"recompute-derived\" }, {});\n try {\n const { result } = workerRun;\n const sessions = attachMissingProjectIdentities(result.sessions);\n const pendingAgentState = {\n meta: result.meta,\n refreshedAt: checkResult.timestamp,\n refreshTransaction,\n };\n const persistenceDiff = buildSessionPersistenceDiff(baseline, sessions);\n if (\n persistenceDiff.changedSessions.length === 0 &&\n persistenceDiff.removedSessionIds.length === 0\n ) {\n this.logUnchangedRefresh(agent.name, refreshStartedAt);\n return {\n ...this.refreshStrategyBase(\n sessions,\n result.completeness,\n {},\n {\n checkDuration,\n scanDuration: performance.now() - scanStartedAt,\n workerRun,\n pendingAgentState,\n },\n ),\n status: \"unchanged\",\n };\n }\n return {\n ...this.refreshStrategyBase(\n sessions,\n result.completeness,\n {},\n {\n checkDuration,\n scanDuration: performance.now() - scanStartedAt,\n sourceFailures: result.sourceFailures ?? [],\n workerRun,\n pendingAgentState,\n },\n ),\n status: \"continue\",\n publication: { kind: \"changes\", diff: persistenceDiff, candidateChangedIds: [] },\n };\n } catch (error) {\n workerRun.discard();\n throw error;\n }\n }\n const scanStartedAt = performance.now();\n if (refresh.kind === \"full-scan\") {\n const workerRun = await this.runWorker(agent, baseline, { kind: \"full-scan\" }, scope);\n try {\n const { result } = workerRun;\n const sessions = attachMissingProjectIdentities(result.sessions);\n const persistenceDiff = buildSessionPersistenceDiff(baseline, sessions, {\n // Worker-reported IDs also preserve metadata-only pricing repairs.\n candidateChangedIds: result.changedIds ?? [],\n completeness: result.completeness,\n explicitRemovedSessionIds: result.explicitRemovedSessionIds,\n });\n const strategy = this.refreshStrategyBase(sessions, result.completeness, scope, {\n checkDuration,\n scanDuration: performance.now() - scanStartedAt,\n sourceFailures: result.sourceFailures ?? [],\n workerRun,\n pendingAgentState: {\n meta: result.meta,\n refreshedAt: checkResult.timestamp,\n refreshTransaction,\n },\n });\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 { ...strategy, status: \"unchanged\" };\n }\n return {\n ...strategy,\n status: \"continue\",\n publication: { kind: \"changes\", diff: persistenceDiff, candidateChangedIds: [] },\n };\n } catch (error) {\n workerRun.discard();\n throw error;\n }\n }\n const preciseChangedIds = refresh.check.changedIds;\n this.options.workerRunner.reset(agent.name);\n const sessions = attachMissingProjectIdentities(\n await Promise.resolve(\n source.incrementalScan(baseline, preciseChangedIds, checkResult.refs, scope),\n ),\n );\n const sourceFailures = checkResult.sourceFailures ?? [];\n const completeness = resolveSessionSnapshotCompleteness(scope, sourceFailures);\n return {\n ...this.refreshStrategyBase(sessions, completeness, scope, {\n checkDuration,\n scanDuration: performance.now() - scanStartedAt,\n sourceFailures,\n pendingAgentState: {\n meta: agent.snapshotSessionCacheMeta(),\n refreshedAt: checkResult.timestamp,\n refreshTransaction,\n },\n }),\n status: \"continue\",\n publication: {\n kind: \"changes\",\n diff: buildSessionPersistenceDiff(baseline, sessions, {\n candidateChangedIds: preciseChangedIds,\n completeness,\n explicitRemovedSessionIds: preciseChangedIds,\n }),\n candidateChangedIds: preciseChangedIds,\n },\n };\n }\n\n private refreshStrategyBase(\n nextSessions: IdentifiedSessionHead[],\n completeness: SessionSnapshotCompleteness,\n scope: Pick<ScanOptions, \"from\" | \"to\">,\n overrides: Partial<Omit<RefreshStrategyBase, \"nextSessions\" | \"completeness\" | \"scope\">> = {},\n ): RefreshStrategyBase {\n return {\n nextSessions,\n checkDuration: 0,\n scanDuration: 0,\n sourceFailures: [],\n completeness,\n scope,\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 enqueueBackfill(agentName: string): void {\n this.backfillScheduler.enqueue(agentName);\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 cached = this.readCachedSessionsOrWarn(\"scan.backfill\", agentName);\n const baseline = cached?.sessions ?? this.sessionIndex.agentSessions(agentName);\n const meta = cached?.meta ?? buildAgentCacheMeta(agent);\n const backfillCursor = getAgentFullSyncCursor(agentName);\n if (cached) agent.restoreSessionCacheMeta(cached.meta);\n let workerRun: StagedWorkerRun | undefined;\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 kind: \"backfill\",\n cursor: backfillCursor,\n checkpoint: \"durable\",\n };\n appLogger.info(\"scan.backfill.started\", {\n agent: agentName,\n cursor: backfillCursor ?? undefined,\n durable_checkpoints: operation.checkpoint === \"durable\",\n });\n workerRun = 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 const { result } = workerRun;\n const fullSessions = attachMissingProjectIdentities(result.sessions);\n const completion = buildScanCompletion(result.completeness, result.sourceFailures ?? []);\n this.statusReporter.flushProgressStatus(`backfill:${agentName}`);\n const updatePublicationPhase = (\n phase: \"publish-queued\" | \"publishing\" | \"indexing\" | \"committing\",\n ) => {\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 await this.sessionPublication.commit({\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: result.meta,\n completeness: result.completeness,\n removedSessionIds: result.explicitRemovedSessionIds,\n saveCache: true,\n },\n stagedRun: workerRun,\n onPublishing: () => updatePublicationPhase(\"publishing\"),\n onPublicationProgress: ({ stage }) => {\n if (stage === \"prepared\") updatePublicationPhase(\"indexing\");\n if (stage === \"search_staged\") updatePublicationPhase(\"committing\");\n },\n onCommitted: () => {\n if (completion.completeness === \"partial\") {\n this.backfills.recordCompletion(attempt, completion);\n }\n },\n });\n this.commitAgentState(\"scan.backfill\", agent, { meta: result.meta });\n try {\n if (completion.completeness === \"complete\" && !markAgentFullSyncCompleted(agentName)) {\n appLogger.warn(\"scan.backfill.completion_not_durable\", { agent: agentName });\n }\n appLogger.info(\n completion.completeness === \"partial\" ? \"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 } catch (error) {\n this.reportPostCommitError(\"scan.backfill\", agentName, error);\n }\n return \"committed\";\n } catch (error) {\n workerRun?.discard();\n appLogger.error(\"scan.backfill.error\", { agent: agentName, error });\n console.error(`[${agentName}] Backfill failed:`, error);\n return \"failed\";\n }\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 { basename, dirname, isAbsolute, join, relative, resolve } from \"node:path\";\nimport type { SessionWatchPlan } from \"@codesesh/core/runtime/agents\";\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 ignoredFileNames?: readonly 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({\n agentName: agent.name,\n targetPath,\n ignoredFileNames: target.ignoredFileNames,\n });\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(\n (scope) =>\n isRelatedPath(changedPath, scope.targetPath) &&\n !(\n scope.ignoredFileNames?.includes(basename(changedPath)) &&\n changedPath !== scope.targetPath &&\n isSameOrChildPath(scope.targetPath, changedPath)\n ),\n )\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 { getPricingGeneration } from \"@codesesh/core/runtime/pricing\";\nimport {\n type AgentScanProgress,\n type SessionCacheMeta,\n type SessionSourceFailure,\n} from \"@codesesh/core/runtime/agents\";\nimport {\n type ScanOptions,\n type SessionHead,\n type PersistedSessionHeadChange,\n type SessionSnapshotCompleteness,\n} from \"@codesesh/core/runtime/discovery\";\nimport { appLogger, type LogContext } 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\";\nimport { terminateWorkerAfterLogDrain } from \"./worker-log-drain.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 StagedWorkerRun {\n readonly result: WorkerResult;\n commit(): void;\n discard(): void;\n}\n\nexport interface WorkerRunner {\n readonly activeCount: number;\n run(agentName: string, payload: WorkerPayload): Promise<StagedWorkerRun>;\n reset(agentName: string): void;\n shutdown(): Promise<void>;\n}\n\ninterface PendingRequest {\n resolve: (run: StagedWorkerRun) => void;\n reject: (error: Error) => void;\n payload: WorkerPayload;\n generation: number;\n logContext: LogContext;\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; logContext: LogContext } | 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.reference.sessionId);\n const retained = previousSessions.filter(\n (session) => !replacedIds.has(session.reference.sessionId),\n );\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 retirements = new Set<Promise<number>>();\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<StagedWorkerRun> {\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 logContext: appLogger.captureContext(),\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 logContext: request.logContext ?? {},\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 reset(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 for (const slot of slots) this.retireWorker(slot.worker);\n await Promise.allSettled(this.retirements);\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 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 appLogger.restoreContext(this.slotLogContext(slot), () => {\n this.closeWorker(agentName, slot, toError(error));\n void this.retireWorker(worker);\n });\n });\n worker.on(\"exit\", (code) => {\n appLogger.restoreContext(this.slotLogContext(slot), () => {\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 });\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 appLogger.restoreContext(pending.logContext, () => {\n this.handlePendingMessage(slot, message, pending);\n });\n }\n\n private handlePendingMessage(\n slot: WorkerSlot,\n message: ScanRefreshWorkerMessage,\n pending: PendingRequest,\n ): void {\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.reference.sessionId);\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 logContext: pending.logContext,\n };\n pending.resolve(this.createStagedRun(slot, message.requestId, message.generation, result));\n } catch (error) {\n pending.reject(toError(error));\n this.invalidateWorker(slot.agentName, slot);\n }\n }\n\n private createStagedRun(\n slot: WorkerSlot,\n requestId: number,\n generation: number,\n result: WorkerResult,\n ): StagedWorkerRun {\n let finalized = false;\n return {\n result,\n commit: () => {\n if (finalized) return;\n finalized = true;\n this.commitStagedRun(slot, requestId, generation);\n },\n discard: () => {\n if (finalized) return;\n finalized = true;\n this.discardStagedRun(slot, requestId, generation);\n },\n };\n }\n\n private commitStagedRun(slot: WorkerSlot, requestId: number, generation: number): void {\n const awaiting = slot.awaitingCommit;\n if (\n this.workers.get(slot.agentName) !== slot ||\n awaiting?.requestId !== requestId ||\n awaiting.generation !== generation\n ) {\n return;\n }\n const request: ScanRefreshWorkerCommitRequest = {\n type: \"commit\",\n requestId,\n generation,\n logContext: awaiting.logContext,\n };\n try {\n slot.worker.postMessage(request);\n slot.awaitingCommit = null;\n slot.generation += 1;\n } catch {\n this.invalidateWorker(slot.agentName, slot);\n }\n }\n\n private discardStagedRun(slot: WorkerSlot, requestId: number, generation: number): void {\n const awaiting = slot.awaitingCommit;\n if (\n this.workers.get(slot.agentName) === slot &&\n awaiting?.requestId === requestId &&\n awaiting.generation === generation\n ) {\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 slotLogContext(slot: WorkerSlot): LogContext {\n for (const pending of slot.pending.values()) return pending.logContext;\n return slot.awaitingCommit?.logContext ?? {};\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 this.retireWorker(slot.worker);\n }\n\n private retireWorker(worker: Worker): Promise<number> {\n const retirement = terminateWorkerAfterLogDrain(worker);\n this.retirements.add(retirement);\n void retirement.finally(() => this.retirements.delete(retirement)).catch(() => undefined);\n return retirement;\n }\n}\n","import { consola } from \"consola\";\nimport type { BaseAgent } from \"@codesesh/core/runtime/agents\";\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 type IdentifiedSessionHead,\n type LiveSnapshot,\n} from \"@codesesh/core/runtime/discovery\";\nimport { getAgentInfoMap } from \"@codesesh/core/runtime/agents\";\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: IdentifiedSessionHead[];\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((failure) =>\n failure.operation === \"read\"\n ? `[${failure.agentName}] Cache read failed; durable baseline is unavailable`\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/runtime/discovery\";\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","import { publishPendingPricing, refreshPricingCache } from \"@codesesh/core/runtime/pricing\";\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 /** Waits for the bounded refresh and publishes prices before scanning. */\n ready(): Promise<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 async ready() {\n await completion;\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":["resolve","Hono","randomUUID","randomUUID","resolve","snapshot","projects","Worker","Worker","resolve","sessions","aliases","randomUUID","isIP","isIP","__dirname","resolve","Hono","randomUUID","existsSync","fileURLToPath","existsSync","fileURLToPath","Worker","toError","resolve","SHUTDOWN_ERROR_MESSAGE","toError","Worker","existsSync","fileURLToPath","toError","key","currentPhase","nextPhase","toError","scanStartedAt","sessions","existsSync","dirname","join","resolve","resolve","existsSync","dirname","platform","join","agents","Worker","SHUTDOWN_ERROR_MESSAGE","resolve","toError","Worker","existsSync","fileURLToPath","readFileSync","resolve","dirname","fileURLToPath"]}