codesesh 0.17.0 → 0.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -4
- package/dist/{chunk-7APNDHQ6.js → chunk-G2BTNW3C.js} +2262 -495
- package/dist/chunk-G2BTNW3C.js.map +1 -0
- package/dist/{chunk-A4U2SMJJ.js → chunk-KD3DGWZY.js} +20 -12
- package/dist/chunk-KD3DGWZY.js.map +1 -0
- package/dist/{dist-KEPJFHOC.js → dist-ALXOBKV2.js} +26 -4
- package/dist/index.js +382 -114
- package/dist/index.js.map +1 -1
- package/dist/scan-refresh-worker.js +243 -24
- package/dist/scan-refresh-worker.js.map +1 -1
- package/dist/search-index-worker.js +73 -39
- package/dist/search-index-worker.js.map +1 -1
- package/dist/smart-tag-worker.js +2 -2
- package/dist/web/assets/AgentIcon-CEj7HO1m.js +1 -0
- package/dist/web/assets/BookmarkButton-DLEnIyeE.js +1 -0
- package/dist/web/assets/Dashboard-DUG0IFcy.js +39 -0
- package/dist/web/assets/DialogTitle-Dv6DQPIb.js +1 -0
- package/dist/web/assets/InteractiveReceipt-xnRqJvfd.js +1 -0
- package/dist/web/assets/PrismHighlighter-C7OfXHq2.js +6 -0
- package/dist/web/assets/Projects-BMaZc6J5.js +1 -0
- package/dist/web/assets/SearchFilterBar-iP6pzlZo.js +1 -0
- package/dist/web/assets/SearchResultsPanel-RuiLPkbP.js +1 -0
- package/dist/web/assets/SessionDetail-De1Wl3mu.js +54 -0
- package/dist/web/assets/index-B-CV7pFu.css +2 -0
- package/dist/web/assets/index-CQI8F_8X.js +1930 -0
- package/dist/web/assets/index.dom-CCLJ9_FR.js +1 -0
- package/dist/web/assets/jsx-runtime-n5LQ9ujS.js +1 -0
- package/dist/web/assets/session-indexes-BuxBafvh.js +4 -0
- package/dist/web/assets/session-title-CNhapdPJ.js +1 -0
- package/dist/web/assets/useTheme-CwDcVdGz.js +1 -0
- package/dist/web/assets/utils-B6KiDbIe.js +1 -0
- package/dist/web/index.html +10 -7
- package/package.json +3 -3
- package/dist/chunk-7APNDHQ6.js.map +0 -1
- package/dist/chunk-A4U2SMJJ.js.map +0 -1
- package/dist/web/assets/index-B076CRkD.js +0 -109
- package/dist/web/assets/index-CWNbVhet.css +0 -2
- package/dist/web/assets/markdown-dR4kAewZ.js +0 -14
- package/dist/web/assets/react-D9s532MZ.js +0 -1821
- package/dist/web/assets/rolldown-runtime-QTnfLwEv.js +0 -1
- package/dist/web/assets/syntax-mZXQuVcd.js +0 -6
- package/dist/web/assets/vendor-i9U7_fNF.js +0 -41
- /package/dist/{dist-KEPJFHOC.js.map → dist-ALXOBKV2.js.map} +0 -0
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/server.ts","../src/api/routes.ts","../src/time-window-resolution.ts","../src/api/query-params.ts","../src/api/session-aliases-view.ts","../src/api/handlers.ts","../src/remote-access.ts","../src/live-scan.ts","../src/agent-operation-scheduler.ts","../src/live-session-index.ts","../src/search-index-job-runner.ts","../src/pending-search-index-jobs.ts","../src/scan-status-model.ts","../src/agent-sync-engine.ts","../src/session-watcher.ts","../src/worker-runner.ts","../src/output.ts","../src/version.ts","../src/runtime-plan.ts","../src/ports.ts"],"sourcesContent":["import \"./diagnostics-bridge.js\";\nimport { defineCommand, runMain } from \"citty\";\nimport { createServer, getServerStartupErrorMessage } from \"./server.js\";\nimport { LiveScanStore } from \"./live-scan.js\";\nimport { printScanResults } from \"./output.js\";\nimport { VERSION } from \"./version.js\";\nimport { appLogger } from \"./logging.js\";\nimport { isLoopbackHostname } 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, getAgentInfoMap, refreshPricingCache, perf } from \"@codesesh/core\";\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 agent: {\n type: \"string\",\n alias: \"a\",\n description: \"Filter to specific agent(s), comma-separated\",\n },\n days: {\n type: \"string\",\n alias: \"d\",\n description: \"Only include sessions active in the last N days (0 = all time)\",\n default: \"7\",\n },\n cwd: {\n type: \"string\",\n description: \"Filter to sessions from a specific project directory (use '.' for current dir)\",\n },\n from: {\n type: \"string\",\n description: \"Sessions active after this date, YYYY-MM-DD (overrides --days)\",\n },\n to: {\n type: \"string\",\n description: \"Sessions active before this date (YYYY-MM-DD)\",\n },\n session: {\n type: \"string\",\n alias: \"s\",\n description: \"Directly open a specific session (agent://session-id)\",\n },\n json: {\n type: \"boolean\",\n alias: \"j\",\n description: \"Output session index as JSON to stdout (no server)\",\n default: false,\n },\n noOpen: {\n type: \"boolean\",\n description: \"Don't auto-open browser\",\n default: false,\n },\n trace: {\n type: \"boolean\",\n description: \"Show performance trace logs\",\n default: false,\n },\n cache: {\n type: \"boolean\",\n description: \"Use cached scan results if available\",\n default: true,\n },\n \"clear-cache\": {\n type: \"boolean\",\n description: \"Clear scan cache before starting\",\n default: false,\n },\n },\n async run({ args }) {\n const startedAt = performance.now();\n const port = parsePort(args.port as string | undefined);\n const explicitPort = hasExplicitPortArg(process.argv.slice(2));\n const noOpen = args.noOpen as boolean;\n const jsonOnly = args.json as boolean;\n const trace = args.trace as boolean;\n const useCache = args.cache as boolean;\n const clearCache = args[\"clear-cache\"] as boolean;\n const hostname = args.host as string;\n const remoteAccess = args[\"remote-access\"] as boolean;\n\n if (!isLoopbackHostname(hostname) && !remoteAccess) {\n console.error(\n `Refusing to expose CodeSesh on ${hostname} without authentication. Add --remote-access to continue.`,\n );\n process.exit(1);\n }\n\n if (trace) {\n perf.enable();\n }\n\n appLogger.info(\"cli.start\", {\n version: VERSION,\n argv: process.argv.slice(2),\n port,\n json: jsonOnly,\n no_open: noOpen,\n cache: useCache,\n log_path: appLogger.getLogPath(),\n });\n\n if (clearCache) {\n const { clearCache: clear } = await import(\"@codesesh/core\");\n clear();\n appLogger.info(\"cache.clear\");\n console.log(\"Cache cleared.\");\n }\n\n void refreshPricingCache();\n\n // Parse session URI if provided\n let targetSession: { agent: string; sessionId: string } | null = null;\n if (args.session) {\n targetSession = parseSessionUri(args.session as string);\n if (!targetSession) {\n console.error(`Invalid session format: ${args.session}. Expected: agent://session-id`);\n process.exit(1);\n }\n }\n\n const { listWindow, scanOptions, startupScanOptions } = buildCliRuntimePlan(\n {\n agent: args.agent as string | undefined,\n cwd: args.cwd as string | undefined,\n from: args.from as string | undefined,\n to: args.to as string | undefined,\n days: args.days as string | undefined,\n jsonOnly,\n targetSession,\n useCache,\n },\n { currentWorkingDirectory: process.cwd() },\n );\n const { from: listDefaultFrom, to: listDefaultTo, days: listDefaultDays } = listWindow;\n\n const store = new LiveScanStore({\n watchEnabled: !jsonOnly,\n scanOptions,\n startupScanOptions,\n deferInitialRefresh: !jsonOnly,\n });\n await store.initialize();\n const result = store.getSnapshot();\n appLogger.info(\"cli.scan_ready\", {\n duration_ms: Math.round(performance.now() - startedAt),\n sessions: result.sessions.length,\n agents: Object.fromEntries(\n Object.entries(result.byAgent).map(([key, value]) => [key, value.length]),\n ),\n startup_from: startupScanOptions.from,\n startup_to: startupScanOptions.to,\n });\n\n if (trace) {\n console.log(perf.getReport());\n }\n\n if (jsonOnly) {\n // Apply --days/--from/--to window to the JSON output so CLI semantics are preserved.\n const windowed = result.sessions.filter((s) => {\n const activity = s.time_updated ?? s.time_created;\n if (listDefaultFrom != null && activity < listDefaultFrom) return false;\n if (listDefaultTo != null && activity > listDefaultTo) return false;\n return true;\n });\n const info = getAgentInfoMap(\n Object.fromEntries(Object.entries(result.byAgent).map(([k, v]) => [k, v.length])),\n );\n const output = {\n agents: info.map(({ name, displayName, count }) => ({\n name,\n displayName,\n count,\n available: count > 0,\n })),\n sessions: windowed,\n };\n appLogger.info(\"cli.json_output\", {\n sessions: windowed.length,\n duration_ms: Math.round(performance.now() - startedAt),\n });\n console.log(JSON.stringify(output, null, 2));\n return;\n }\n\n // Print console output\n const agents = createRegisteredAgents();\n printScanResults(agents);\n\n // Start server\n let app: Awaited<ReturnType<typeof createServer>>;\n try {\n app = await createServer(port, store, {\n defaultSessionFrom: listDefaultFrom,\n defaultSessionTo: listDefaultTo,\n defaultSessionDays: listDefaultDays,\n portFallbackAttempts: explicitPort ? 1 : DEFAULT_PORT_FALLBACK_ATTEMPTS,\n hostname,\n remoteAccess,\n });\n } catch (error) {\n console.error(getServerStartupErrorMessage(error, port));\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 app.shutdown();\n process.exit(0);\n };\n process.once(\"SIGINT\", (signal) => {\n void shutdown(signal);\n });\n process.once(\"SIGTERM\", (signal) => {\n void shutdown(signal);\n });\n\n console.log(` ${url}`);\n console.log(\"\");\n appLogger.info(\"cli.ready\", {\n url: redactStartupUrl(url),\n duration_ms: Math.round(performance.now() - startedAt),\n log_path: appLogger.getLogPath(),\n });\n\n if (!noOpen) {\n const open = (await import(\"open\")).default;\n const targetUrl = resolveStartupUrl(url, targetSession);\n appLogger.info(\"browser.open\", { url: redactStartupUrl(targetUrl) });\n await open(targetUrl);\n }\n },\n});\n\nif (process.argv.slice(2).includes(\"-v\")) {\n console.log(VERSION);\n process.exit(0);\n}\n\nrunMain(main);\n","import { Hono } from \"hono\";\nimport { bodyLimit } from \"hono/body-limit\";\nimport { compress } from \"hono/compress\";\nimport { serve } from \"@hono/node-server\";\nimport type { ServerType } from \"@hono/node-server\";\nimport { serveStatic } from \"@hono/node-server/serve-static\";\nimport { existsSync } from \"node:fs\";\nimport type { AddressInfo } from \"node:net\";\nimport { resolve, dirname } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport type { ScanResultSource } from \"./api/handlers.js\";\nimport { createApiRoutes, type ApiRouteOptions } from \"./api/routes.js\";\nimport { appLogger } from \"./logging.js\";\nimport {\n createRemoteAccessToken,\n isLoopbackHostname,\n REMOTE_ACCESS_QUERY_PARAM,\n remoteAccessAuth,\n} from \"./remote-access.js\";\nimport type { ScanEventSource } from \"./scan-source.js\";\n\nconst MAX_API_REQUEST_BYTES = 1024 * 1024;\n\nexport interface CreateServerOptions {\n defaultSessionFrom?: number;\n defaultSessionTo?: number;\n defaultSessionDays?: number;\n portFallbackAttempts?: number;\n hostname?: string;\n remoteAccess?: boolean;\n remoteAccessToken?: string;\n}\n\nfunction findWebDistPath(): string | null {\n const __dirname = dirname(fileURLToPath(import.meta.url));\n\n // Priority 1: Packaged web dist (copied during build)\n const packagedPath = resolve(__dirname, \"web\");\n if (existsSync(packagedPath)) {\n return packagedPath;\n }\n\n // Priority 2: Development path (monorepo)\n const devPath = resolve(__dirname, \"../../../apps/web/dist\");\n if (existsSync(devPath)) {\n return devPath;\n }\n\n return null;\n}\n\nfunction waitForListening(server: ServerType): Promise<void> {\n return new Promise((resolve, reject) => {\n const handleListening = () => {\n server.off(\"error\", handleError);\n resolve();\n };\n const handleError = (error: Error) => {\n server.off(\"listening\", handleListening);\n reject(error);\n };\n\n server.once(\"listening\", handleListening);\n server.once(\"error\", handleError);\n });\n}\n\nexport function getServerStartupErrorMessage(error: unknown, port: number): string {\n if (\n typeof error === \"object\" &&\n error !== null &&\n \"code\" in error &&\n error.code === \"EADDRINUSE\"\n ) {\n return `Port ${port} 已被占用,请关闭现有 CodeSesh 进程或改用 --port 指定其他端口。`;\n }\n\n return error instanceof Error ? error.message : `启动服务器失败: ${String(error)}`;\n}\n\nfunction isAddressInUse(error: unknown): boolean {\n return (\n typeof error === \"object\" && error !== null && \"code\" in error && error.code === \"EADDRINUSE\"\n );\n}\n\nfunction getListeningPort(server: ServerType, fallback: number): number {\n const address = server.address();\n return typeof address === \"object\" && address !== null ? (address as AddressInfo).port : fallback;\n}\n\nexport async function createServer(\n port: number,\n store: ScanResultSource & ScanEventSource & { shutdown(): Promise<void> },\n options: CreateServerOptions = {},\n): Promise<{ url: string; shutdown: () => Promise<void> }> {\n const app = new Hono();\n const hostname = options.hostname ?? \"127.0.0.1\";\n const isLoopback = isLoopbackHostname(hostname);\n const remoteAccessToken = !isLoopback\n ? (options.remoteAccessToken ?? (options.remoteAccess ? createRemoteAccessToken() : null))\n : null;\n\n if (!isLoopback && !remoteAccessToken) {\n throw new Error(\n `Refusing to expose CodeSesh on ${hostname} without authentication. Add --remote-access to continue.`,\n );\n }\n\n app.use(\"*\", async (c, next) => {\n const startedAt = performance.now();\n let thrown: unknown;\n\n try {\n await next();\n } catch (error) {\n thrown = error;\n throw error;\n } finally {\n const url = new URL(c.req.url);\n appLogger.info(\"http.request\", {\n method: c.req.method,\n path: url.pathname,\n query_keys: [...url.searchParams.keys()].toSorted(),\n status: c.res.status,\n duration_ms: Math.round(performance.now() - startedAt),\n error: thrown instanceof Error ? thrown.message : undefined,\n });\n }\n });\n\n if (remoteAccessToken) {\n app.use(\"/api/*\", remoteAccessAuth(remoteAccessToken));\n }\n app.use(\n \"/api/*\",\n bodyLimit({\n maxSize: MAX_API_REQUEST_BYTES,\n onError: (c) => c.json({ error: \"Request body too large\" }, 413),\n }),\n );\n // Hono's default filter already excludes text/event-stream, so this does not\n // interfere with the /api/events SSE stream.\n app.use(\"/api/*\", compress());\n\n // API routes\n const routeOptions: ApiRouteOptions = {\n defaultSessionFrom: options.defaultSessionFrom,\n defaultSessionTo: options.defaultSessionTo,\n defaultSessionDays: options.defaultSessionDays,\n };\n app.route(\"/api\", createApiRoutes(store, store, routeOptions));\n\n // Serve static files from web dist (if available)\n const webDistPath = findWebDistPath();\n\n if (webDistPath) {\n app.use(\"/*\", serveStatic({ root: webDistPath }));\n app.get(\"/*\", serveStatic({ root: webDistPath, path: \"index.html\" }));\n }\n\n const attempts = Math.max(1, options.portFallbackAttempts ?? 1);\n let server: ServerType | null = null;\n let actualPort = port;\n\n for (let offset = 0; offset < attempts; offset += 1) {\n const candidatePort = port + offset;\n server = serve({ fetch: app.fetch, port: candidatePort, hostname });\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 const baseUrl = isLoopback\n ? `http://localhost:${actualPort}`\n : `http://${hostname}:${actualPort}`;\n const url = remoteAccessToken\n ? `${baseUrl}/?${REMOTE_ACCESS_QUERY_PARAM}=${encodeURIComponent(remoteAccessToken)}`\n : baseUrl;\n appLogger.info(\"server.listen\", {\n port: actualPort,\n requested_port: port,\n hostname,\n remote_access: Boolean(remoteAccessToken),\n });\n\n if (!isLoopback) {\n appLogger.warn(\"server.listen.remote_access\", { hostname, port: actualPort });\n console.warn(`\\n⚠ 远程访问已启用。任何持有启动 URL 的人都可以读取你的 AI 会话记录。\\n`);\n }\n\n return {\n url,\n shutdown: async () => {\n appLogger.info(\"server.shutdown\", { port: actualPort });\n await new Promise<void>((resolve) => {\n if (!server) {\n resolve();\n return;\n }\n server.close(() => resolve());\n });\n await store.shutdown();\n },\n };\n}\n","import { Hono } from \"hono\";\nimport {\n handleGetAgents,\n handleGetBookmarks,\n handleGetConfig,\n handleGetDashboard,\n handleGetFileActivity,\n handleGetProjects,\n handleGetScanStatus,\n handleDeleteBookmark,\n handleDeleteSessionAlias,\n handleImportBookmarks,\n handlePostClientLog,\n handleSearchSessions,\n handleGetSessions,\n handleGetSessionData,\n handlePutBookmark,\n handlePutSessionAlias,\n type ScanResultSource,\n type SessionListDefaults,\n} from \"./handlers.js\";\nimport type { ScanEventSource } from \"../scan-source.js\";\n\nexport interface ApiRouteOptions {\n defaultSessionFrom?: number;\n defaultSessionTo?: number;\n defaultSessionDays?: number;\n}\n\nfunction createSseResponse(eventSource: ScanEventSource, signal: AbortSignal): Response {\n const encoder = new TextEncoder();\n let cancelStream = () => {};\n\n return new Response(\n new ReadableStream({\n start(controller) {\n let isClosed = false;\n const write = (event: string, data: unknown) => {\n if (isClosed) return;\n controller.enqueue(encoder.encode(`event: ${event}\\n`));\n controller.enqueue(encoder.encode(`data: ${JSON.stringify(data)}\\n\\n`));\n };\n\n write(\"connected\", { timestamp: Date.now() });\n write(\"scan-status\", eventSource.getScanStatus());\n\n const unsubscribeSessions = eventSource.subscribe((event) => {\n write(event.type, event);\n });\n const unsubscribeScanStatus = eventSource.subscribeScanStatus((event) => {\n write(event.type, event);\n });\n\n const heartbeat = setInterval(() => {\n if (!isClosed) controller.enqueue(encoder.encode(\": keepalive\\n\\n\"));\n }, 15000);\n\n const cleanup = () => {\n if (isClosed) return false;\n isClosed = true;\n clearInterval(heartbeat);\n unsubscribeSessions();\n unsubscribeScanStatus();\n signal.removeEventListener(\"abort\", abortStream);\n return true;\n };\n const abortStream = () => {\n if (cleanup()) controller.close();\n };\n cancelStream = () => {\n cleanup();\n };\n\n if (signal.aborted) abortStream();\n else signal.addEventListener(\"abort\", abortStream, { once: true });\n },\n cancel() {\n cancelStream();\n },\n }),\n {\n headers: {\n \"Cache-Control\": \"no-cache\",\n Connection: \"keep-alive\",\n \"Content-Type\": \"text/event-stream\",\n },\n },\n );\n}\n\nexport function createApiRoutes(\n scanSource: ScanResultSource,\n eventSource?: ScanEventSource,\n options: ApiRouteOptions = {},\n): Hono {\n const api = new Hono();\n const listDefaults: SessionListDefaults = {\n from: options.defaultSessionFrom,\n to: options.defaultSessionTo,\n days: options.defaultSessionDays,\n };\n\n api.get(\"/config\", (c) => handleGetConfig(c, listDefaults));\n if (eventSource) {\n api.get(\"/status\", (c) => handleGetScanStatus(c, eventSource));\n }\n api.get(\"/agents\", (c) => handleGetAgents(c, scanSource, listDefaults));\n api.get(\"/projects\", (c) => handleGetProjects(c, scanSource, listDefaults));\n api.get(\"/sessions\", (c) => handleGetSessions(c, scanSource, listDefaults));\n api.get(\"/search\", (c) => handleSearchSessions(c, scanSource, listDefaults));\n api.get(\"/file-activity\", (c) => handleGetFileActivity(c, listDefaults));\n api.get(\"/sessions/:agent/:id\", (c) => handleGetSessionData(c, scanSource));\n api.get(\"/dashboard\", (c) => handleGetDashboard(c, scanSource, listDefaults));\n api.get(\"/bookmarks\", (c) => handleGetBookmarks(c));\n api.put(\"/bookmarks\", (c) => handlePutBookmark(c));\n api.post(\"/bookmarks/import\", (c) => handleImportBookmarks(c));\n api.delete(\"/bookmarks/:agent/:id\", (c) => handleDeleteBookmark(c));\n api.put(\"/session-aliases/:agent/:id\", (c) => handlePutSessionAlias(c));\n api.delete(\"/session-aliases/:agent/:id\", (c) => handleDeleteSessionAlias(c));\n api.post(\"/logs\", (c) => handlePostClientLog(c));\n if (eventSource) {\n api.get(\"/events\", (c) => createSseResponse(eventSource, c.req.raw.signal));\n }\n\n return api;\n}\n","import { startOfLocalDay } from \"@codesesh/core\";\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 RawTimeWindow {\n from?: string;\n to?: string;\n days?: string;\n}\n\ninterface CliTimeWindowRequest extends RawTimeWindow {\n mode: \"cli\";\n now?: number;\n}\n\ninterface DashboardTimeWindowRequest {\n mode: \"dashboard\";\n query: RawTimeWindow;\n defaults?: TimeWindow;\n now?: number;\n}\n\ninterface DashboardTimeWindow extends TimeWindow {\n to: number;\n}\n\ntype TimeWindowRequest = CliTimeWindowRequest | DashboardTimeWindowRequest;\n\nexport function resolveTimeWindow(request: CliTimeWindowRequest): TimeWindow;\nexport function resolveTimeWindow(request: DashboardTimeWindowRequest): DashboardTimeWindow;\nexport function resolveTimeWindow(request: TimeWindowRequest): TimeWindow {\n return request.mode === \"cli\" ? resolveCliWindow(request) : resolveDashboardWindow(request);\n}\n\nfunction resolveCliWindow(request: CliTimeWindowRequest): TimeWindow {\n const now = request.now ?? Date.now();\n const from = parseRequiredDate(request.from);\n const to = parseRequiredDate(request.to);\n if (from != null) return { from, to };\n\n const days = parseDays(request.days);\n if (days === 0) return { to, days };\n if (days == null || days < 0) return { to };\n\n const rollingFrom = now - days * DAY_MS;\n return Number.isFinite(rollingFrom) ? { from: rollingFrom, to, days } : { to };\n}\n\nfunction resolveDashboardWindow(request: DashboardTimeWindowRequest): DashboardTimeWindow {\n const now = request.now ?? Date.now();\n const defaults = request.defaults ?? {};\n const to = parseOptionalDate(request.query.to) ?? defaults.to ?? now;\n const hasQueryDays = Boolean(request.query.days?.trim());\n const parsedDays = hasQueryDays ? parseDays(request.query.days) : undefined;\n let days = parsedDays != null && parsedDays > 0 ? parsedDays : defaults.days;\n\n const queryFrom = parseOptionalDate(request.query.from);\n if (queryFrom != null) {\n days ??= elapsedDays(queryFrom, to);\n return { from: queryFrom, to, days };\n }\n\n if (parsedDays === 0 || (!hasQueryDays && defaults.days === 0)) {\n return { to, days: 0 };\n }\n\n if (defaults.from != null) {\n days ??= elapsedDays(defaults.from, to);\n return { from: defaults.from, to, days };\n }\n\n const resolvedDays = days != null && days > 0 ? days : DEFAULT_DASHBOARD_DAYS;\n return {\n from: startOfLocalDay(to) - (resolvedDays - 1) * DAY_MS,\n to,\n days: resolvedDays,\n };\n}\n\nfunction parseRequiredDate(value: string | undefined): number | undefined {\n if (!value) return undefined;\n const timestamp = new Date(value).getTime();\n if (Number.isNaN(timestamp)) throw new Error(`Invalid date: ${value}`);\n return timestamp;\n}\n\nfunction parseOptionalDate(value: string | undefined): number | undefined {\n if (value == null) return undefined;\n const timestamp = new Date(value).getTime();\n return Number.isNaN(timestamp) ? undefined : timestamp;\n}\n\nfunction parseDays(value: string | undefined): number | undefined {\n if (value == null) return undefined;\n const days = Number.parseInt(value, 10);\n return Number.isSafeInteger(days) && Number.isSafeInteger(days * DAY_MS) ? days : undefined;\n}\n\nfunction elapsedDays(from: number, to: number): number {\n return Math.max(1, Math.ceil((to - from) / DAY_MS));\n}\n","/**\n * Request-parameter parsing for the HTTP API. Everything here turns raw query\n * strings into the option objects the domain layer expects; no domain logic,\n * no storage access.\n */\nimport type { Context } from \"hono\";\nimport type { SessionHead, SmartTag } from \"@codesesh/core\";\nimport {\n getSessionActivityTime,\n isProjectIdentityKind,\n type FileActivityKind,\n type ProjectIdentityRef,\n type SearchOptions,\n} from \"@codesesh/core\";\nimport type { TimeWindow } from \"../time-window-resolution.js\";\n\nexport type SessionListDefaults = TimeWindow;\n\nconst SMART_TAGS: readonly string[] = [\n \"bugfix\",\n \"refactoring\",\n \"feature-dev\",\n \"testing\",\n \"docs\",\n \"git-ops\",\n \"build-deploy\",\n \"exploration\",\n \"planning\",\n];\n\nconst SEARCH_LIMIT_MAX = 100;\nconst SEARCH_LIMIT_DEFAULT = 50;\n\nexport function searchParams(c: Context): URLSearchParams {\n return new URL(c.req.url ?? \"http://localhost/\", \"http://localhost/\").searchParams;\n}\n\n/** Collects repeated and comma-separated values across several parameter names. */\nexport function queryValues(params: URLSearchParams, ...names: string[]): string[] {\n return names.flatMap((name) =>\n params\n .getAll(name)\n .flatMap((value) => value.split(\",\"))\n .map((value) => value.trim())\n .filter(Boolean),\n );\n}\n\nexport function optionalQueryValue(value: string | undefined): string | undefined {\n const normalized = value?.trim();\n return normalized ? normalized : undefined;\n}\n\nexport function parseDateParam(\n value: string | undefined,\n fallback: number | undefined,\n): number | undefined {\n if (value == null) return fallback;\n const ts = new Date(value).getTime();\n return Number.isNaN(ts) ? fallback : ts;\n}\n\nexport function parseNumberParam(value: string | undefined): number | undefined {\n if (value == null || !value.trim()) return undefined;\n const number = Number(value);\n return Number.isFinite(number) ? number : undefined;\n}\n\nexport function parseSmartTags(values: string[]): SmartTag[] | undefined {\n const tags = values\n .map((value) => value.toLowerCase())\n .filter((value): value is SmartTag => SMART_TAGS.includes(value));\n return tags.length > 0 ? [...new Set(tags)] : undefined;\n}\n\nexport function parseFileActivityKind(value: string | undefined): FileActivityKind | undefined {\n if (value === \"read\" || value === \"edit\" || value === \"write\" || value === \"delete\") {\n return value;\n }\n return undefined;\n}\n\n/**\n * Returns the identity when both halves are present and valid, `undefined` when\n * neither is supplied, and `null` when the pair is incomplete or malformed —\n * callers turn that `null` into a 400.\n */\nexport function parseProjectIdentityFilter(\n kindValue: string | undefined,\n keyValue: string | undefined,\n): ProjectIdentityRef | null | undefined {\n const kind = optionalQueryValue(kindValue);\n const key = optionalQueryValue(keyValue);\n if (!kind && !key) return undefined;\n if (!kind || !key || !isProjectIdentityKind(kind)) return null;\n return { kind, key };\n}\n\nexport function parseSearchOptions(\n c: Context,\n defaults: SessionListDefaults,\n projectIdentity?: ProjectIdentityRef,\n): SearchOptions {\n const params = searchParams(c);\n const limitValue = parseNumberParam(params.get(\"limit\") ?? undefined);\n return {\n agent: optionalQueryValue(params.get(\"agent\") ?? undefined),\n project: optionalQueryValue(params.get(\"project\") ?? undefined),\n projectKind: projectIdentity?.kind,\n projectKey: projectIdentity?.key,\n cwd: optionalQueryValue(params.get(\"cwd\") ?? undefined),\n tags: parseSmartTags(queryValues(params, \"tag\", \"tags\", \"signal\")),\n tools: queryValues(params, \"tool\", \"tools\").map((tool) => tool.toLowerCase()),\n file: optionalQueryValue(params.get(\"file\") ?? params.get(\"path\") ?? undefined),\n fileKind: parseFileActivityKind(\n optionalQueryValue(params.get(\"fileKind\") ?? params.get(\"fileActivity\") ?? undefined),\n ),\n costMin: parseNumberParam(params.get(\"costMin\") ?? undefined),\n costMax: parseNumberParam(params.get(\"costMax\") ?? undefined),\n from: parseDateParam(params.get(\"from\") ?? undefined, defaults.from),\n to: parseDateParam(params.get(\"to\") ?? undefined, defaults.to),\n limit:\n limitValue && limitValue > 0 ? Math.min(limitValue, SEARCH_LIMIT_MAX) : SEARCH_LIMIT_DEFAULT,\n };\n}\n\nexport function filterSessionsByActivityWindow(\n sessions: SessionHead[],\n from: number | undefined,\n to: number | undefined,\n): SessionHead[] {\n if (from == null && to == null) return sessions;\n return sessions.filter((session) => {\n const activity = getSessionActivityTime(session);\n if (from != null && activity < from) return false;\n if (to != null && activity > to) return false;\n return true;\n });\n}\n","/**\n * Session aliases as a read model for the HTTP layer: load the user's local\n * renames once, then decorate outgoing records with `display_title`.\n */\nimport type { BookmarkRecord, SessionAlias, SessionHead } from \"@codesesh/core\";\nimport type { SearchResult, SessionReference } from \"@codesesh/core/contract\";\nimport {\n filterSessionSearchCandidates,\n getSessionActivityTime,\n listSessionAliases,\n mergeSearchQueryOptions,\n StateStorageUnavailableError,\n type FileActivityResult,\n type LiveSnapshot,\n type SearchOptions,\n} from \"@codesesh/core\";\nimport { appLogger } from \"../logging.js\";\n\n/** Anything the API returns that can carry a locally-renamed title. */\ntype Titled = { id: string; title: string; display_title?: string };\n\nexport interface AliasView {\n readonly size: number;\n get(reference: SessionReference): string | undefined;\n /** Returns the record unchanged when no alias applies, so callers can pass through freely. */\n decorate<T extends Titled>(record: T, reference: SessionReference): T;\n entries(): IterableIterator<SessionAlias>;\n}\n\nfunction aliasKey(reference: SessionReference): string {\n return `${reference.agentName.toLowerCase()}\\0${reference.sessionId}`;\n}\n\nfunction loadAliasMap(): Map<string, SessionAlias> {\n try {\n return new Map(listSessionAliases().map((alias) => [aliasKey(alias.reference), alias]));\n } catch (error) {\n if (!(error instanceof StateStorageUnavailableError)) {\n appLogger.warn(\"api.session_aliases.load_failed\", {\n error: error instanceof Error ? error.message : String(error),\n });\n }\n return new Map();\n }\n}\n\nfunction buildAliasView(): AliasView {\n const aliases = loadAliasMap();\n return {\n size: aliases.size,\n get: (reference) => aliases.get(aliasKey(reference))?.alias,\n decorate(record, reference) {\n const alias = aliases.get(aliasKey(reference))?.alias;\n return alias ? { ...record, display_title: alias } : record;\n },\n entries: () => aliases.values(),\n };\n}\n\n/**\n * Aliases change only through this process's own PUT/DELETE handlers, so the\n * read model is built once and reused until one of them invalidates it. Six read\n * handlers call this per request; without the cache each one re-queries the whole\n * table. A storage failure is cached too — it does not heal between requests, and\n * invalidateAliasView() is what lets a recovered store be retried.\n */\nlet cachedView: AliasView | null = null;\n\nexport function loadAliasView(): AliasView {\n return (cachedView ??= buildAliasView());\n}\n\nexport function invalidateAliasView(): void {\n cachedView = null;\n}\n\nexport function decorateBookmark(bookmark: BookmarkRecord, aliases: AliasView): BookmarkRecord {\n return {\n ...bookmark,\n session: aliases.decorate(bookmark.session, bookmark.reference),\n };\n}\n\nexport function decorateFileActivity(\n activity: FileActivityResult,\n aliases: AliasView,\n): FileActivityResult {\n return {\n ...activity,\n session: aliases.decorate(activity.session, activity.reference),\n };\n}\n\n/**\n * Aliases are stored outside the search index, so a query matching only a local\n * rename has to be resolved here. Hits still have to satisfy the same\n * time-window / project / agent filters as the main search, otherwise an aliased\n * session could surface outside its search scope.\n */\nexport function findAliasSearchResults(\n query: string,\n options: SearchOptions,\n scanResult: LiveSnapshot,\n aliases: AliasView,\n): SearchResult[] {\n const search = mergeSearchQueryOptions(query, options);\n const needle = search.text.trim().toLowerCase();\n if (!needle || aliases.size === 0) return [];\n\n const sessionsByAgent = new Map<string, Map<string, SessionHead>>();\n const lookupSession = (agentName: string, sessionId: string): SessionHead | undefined => {\n let byId = sessionsByAgent.get(agentName);\n if (!byId) {\n byId = new Map((scanResult.byAgent[agentName] ?? []).map((item) => [item.id, item]));\n sessionsByAgent.set(agentName, byId);\n }\n return byId.get(sessionId);\n };\n\n const results: SearchResult[] = [];\n for (const alias of aliases.entries()) {\n if (!alias.alias.toLowerCase().includes(needle)) continue;\n const { agentName, sessionId } = alias.reference;\n const session = lookupSession(agentName, sessionId);\n if (!session) continue;\n results.push({\n reference: alias.reference,\n session: aliases.decorate(session, alias.reference),\n snippet: `Alias · ${session.directory}`,\n matchType: \"title\",\n });\n }\n\n return filterSessionSearchCandidates(results, search.options).sort(\n (a, b) => getSessionActivityTime(b.session) - getSessionActivityTime(a.session),\n );\n}\n","import type { Context } from \"hono\";\nimport type {\n BookmarkRecord,\n LiveSnapshot,\n SessionDetail,\n SessionHead,\n SmartTag,\n} from \"@codesesh/core\";\nimport {\n formatSessionReference,\n getSessionAgentKey,\n normalizeSessionReference,\n type AppConfig,\n type ScanStatusEvent,\n type SessionReference,\n} from \"@codesesh/core/contract\";\nimport {\n SessionAliasValidationError,\n StateStorageUnavailableError,\n attachProjectMetrics,\n createProjectScopeMatcher,\n deleteBookmark,\n getAgentInfoMap,\n executeSessionSearch,\n importBookmarks,\n listFileActivity,\n listCachedProjectGroups,\n listBookmarks,\n deleteSessionAlias,\n materializeSessionDetailResponse,\n upsertSessionAlias,\n upsertBookmark,\n matchesProjectScope as sessionMatchesProjectScope,\n matchesProjectIdentity,\n buildDashboard,\n startOfLocalDay,\n type DashboardData,\n type DashboardScope,\n} from \"@codesesh/core\";\nimport { appLogger } from \"../logging.js\";\nimport { resolveTimeWindow } from \"../time-window-resolution.js\";\nimport {\n filterSessionsByActivityWindow,\n parseDateParam,\n parseFileActivityKind,\n parseProjectIdentityFilter,\n parseSearchOptions,\n optionalQueryValue,\n type SessionListDefaults,\n} from \"./query-params.js\";\nimport {\n decorateBookmark,\n decorateFileActivity,\n findAliasSearchResults,\n invalidateAliasView,\n loadAliasView,\n} from \"./session-aliases-view.js\";\n\nexport type { SessionListDefaults };\n\nexport interface ScanResultSource {\n getSnapshot(): LiveSnapshot;\n}\n\nexport interface ScanStatusSource {\n getScanStatus(): ScanStatusEvent;\n}\n\ninterface SnapshotAggregationCache {\n sessions: SessionHead[];\n values: Map<string, unknown>;\n}\n\nconst SNAPSHOT_AGGREGATION_CACHE_LIMIT = 64;\nconst snapshotAggregationCaches = new WeakMap<ScanResultSource, SnapshotAggregationCache>();\n\n/**\n * LiveScanStore replaces its canonical sessions array whenever the snapshot\n * changes, so that existing reference is the snapshot version.\n */\nfunction getSnapshotAggregation<T>(\n source: ScanResultSource,\n sessions: SessionHead[],\n key: readonly unknown[],\n build: () => T,\n): T {\n let cache = snapshotAggregationCaches.get(source);\n if (!cache || cache.sessions !== sessions) {\n cache = { sessions, values: new Map() };\n snapshotAggregationCaches.set(source, cache);\n }\n\n const cacheKey = JSON.stringify(key);\n if (cache.values.has(cacheKey)) return cache.values.get(cacheKey) as T;\n\n const value = build();\n if (cache.values.size >= SNAPSHOT_AGGREGATION_CACHE_LIMIT) {\n const oldestKey = cache.values.keys().next().value;\n if (oldestKey != null) cache.values.delete(oldestKey);\n }\n cache.values.set(cacheKey, value);\n return value;\n}\n\ninterface ClientLogPayload {\n event?: unknown;\n data?: unknown;\n}\n\ninterface SessionAliasPayload {\n alias?: unknown;\n}\n\nfunction withStorageErrors<TResult, TFallback>(\n handler: () => TResult,\n onUnavailable: () => TFallback,\n): TResult | TFallback {\n try {\n return handler();\n } catch (error) {\n if (error instanceof StateStorageUnavailableError) {\n return onUnavailable();\n }\n throw error;\n }\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null;\n}\n\nfunction isSessionStats(value: unknown): value is SessionHead[\"stats\"] {\n if (!isRecord(value)) return false;\n return (\n typeof value.message_count === \"number\" &&\n typeof value.total_input_tokens === \"number\" &&\n typeof value.total_output_tokens === \"number\" &&\n typeof value.total_cost === \"number\" &&\n (value.total_tokens == null || typeof value.total_tokens === \"number\")\n );\n}\n\ntype BookmarkInput = Omit<BookmarkRecord, \"bookmarkedAt\">;\n\nfunction parseBookmarkSession(\n value: unknown,\n reference: SessionReference,\n): BookmarkInput[\"session\"] | null {\n if (!isRecord(value)) return null;\n if (\n value.id !== reference.sessionId ||\n typeof value.slug !== \"string\" ||\n typeof value.title !== \"string\" ||\n typeof value.directory !== \"string\" ||\n typeof value.time_created !== \"number\" ||\n (value.time_updated != null && typeof value.time_updated !== \"number\") ||\n !isSessionStats(value.stats)\n ) {\n return null;\n }\n\n return {\n id: reference.sessionId,\n slug: formatSessionReference(reference),\n title: value.title,\n directory: value.directory,\n time_created: value.time_created,\n time_updated: value.time_updated ?? undefined,\n stats: value.stats,\n };\n}\n\nfunction parseSessionReferencePayload(value: unknown): SessionReference | null {\n if (\n !isRecord(value) ||\n typeof value.agentName !== \"string\" ||\n typeof value.sessionId !== \"string\" ||\n !value.agentName.trim() ||\n !value.sessionId\n ) {\n return null;\n }\n return normalizeSessionReference({\n agentName: value.agentName.trim().toLowerCase(),\n sessionId: value.sessionId,\n });\n}\n\nfunction parseBookmarkPayload(value: unknown): BookmarkInput | null {\n if (!isRecord(value)) return null;\n\n const reference = parseSessionReferencePayload(value.reference);\n if (reference) {\n const session = parseBookmarkSession(value.session, reference);\n return session ? { reference, session } : null;\n }\n\n if (\n typeof value.agentKey !== \"string\" ||\n typeof value.sessionId !== \"string\" ||\n typeof value.fullPath !== \"string\" ||\n !value.agentKey.trim() ||\n !value.sessionId\n ) {\n return null;\n }\n const legacyReference = normalizeSessionReference({\n agentName: value.agentKey.trim().toLowerCase(),\n sessionId: value.sessionId,\n });\n const session = parseBookmarkSession(\n {\n ...value,\n id: value.sessionId,\n slug: value.fullPath,\n },\n legacyReference,\n );\n return session ? { reference: legacyReference, session } : null;\n}\n\nfunction sanitizeClientLogData(value: unknown): Record<string, unknown> {\n if (!isRecord(value)) return {};\n\n return Object.fromEntries(\n Object.entries(value)\n .slice(0, 30)\n .map(([key, item]) => {\n if (typeof item === \"string\") return [key, item.slice(0, 300)];\n if (typeof item === \"number\" || typeof item === \"boolean\" || item == null) {\n return [key, item];\n }\n return [key, String(item).slice(0, 300)];\n }),\n );\n}\n\nfunction toSessionListItem(session: SessionHead): SessionHead {\n if (!session.model_usage) return session;\n const item = { ...session };\n delete item.model_usage;\n return item;\n}\n\nfunction getSessionHeadReference(session: SessionHead): SessionReference {\n return {\n agentName: getSessionAgentKey(session),\n sessionId: session.id,\n };\n}\n\nfunction createSessionDetailJsonResponse(\n data: Omit<SessionDetail, \"messages\">,\n messages: Iterable<string>,\n): Response {\n const encoder = new TextEncoder();\n const headerJson = JSON.stringify(data);\n const iterator = messages[Symbol.iterator]();\n let wroteHeader = false;\n let wroteMessage = false;\n\n return new Response(\n new ReadableStream<Uint8Array>({\n pull(controller) {\n if (!wroteHeader) {\n controller.enqueue(encoder.encode(`${headerJson.slice(0, -1)},\"messages\":[`));\n wroteHeader = true;\n return;\n }\n\n const next = iterator.next();\n if (!next.done) {\n controller.enqueue(encoder.encode(`${wroteMessage ? \",\" : \"\"}${next.value}`));\n wroteMessage = true;\n return;\n }\n\n controller.enqueue(encoder.encode(\"]}\"));\n controller.close();\n },\n cancel() {\n iterator.return?.();\n },\n }),\n { headers: { \"Content-Type\": \"application/json; charset=UTF-8\" } },\n );\n}\n\nexport function handleGetConfig(c: Context, defaults: SessionListDefaults) {\n const payload: AppConfig = {\n window: {\n from: defaults.from,\n to: defaults.to,\n days: defaults.days,\n },\n };\n return c.json(payload);\n}\n\nexport function handleGetScanStatus(c: Context, scanSource: ScanStatusSource) {\n return c.json(scanSource.getScanStatus());\n}\n\nexport function handleGetAgents(\n c: Context,\n scanSource: ScanResultSource,\n defaults: SessionListDefaults = {},\n) {\n const scanResult = scanSource.getSnapshot();\n const from = parseDateParam(c.req.query(\"from\"), defaults.from);\n const to = parseDateParam(c.req.query(\"to\"), defaults.to);\n const agents = getSnapshotAggregation(\n scanSource,\n scanResult.sessions,\n [\"agents\", from, to],\n () => {\n const counts = Object.fromEntries(\n Object.entries(scanResult.byAgent).map(([agentName, sessions]) => [\n agentName,\n filterSessionsByActivityWindow(sessions, from, to).length,\n ]),\n );\n return getAgentInfoMap(counts);\n },\n );\n return c.json(agents);\n}\n\nexport function handleGetProjects(\n c: Context,\n scanSource: ScanResultSource,\n defaults: SessionListDefaults = {},\n) {\n const scanResult = scanSource.getSnapshot();\n const from = parseDateParam(c.req.query(\"from\"), defaults.from);\n const to = parseDateParam(c.req.query(\"to\"), defaults.to);\n const projects = getSnapshotAggregation(\n scanSource,\n scanResult.sessions,\n [\"projects\", from, to],\n () => {\n const sessions = filterSessionsByActivityWindow(scanResult.sessions, from, to);\n return {\n projects: attachProjectMetrics(listCachedProjectGroups(sessions), sessions),\n };\n },\n );\n return c.json(projects);\n}\n\nexport function handleGetSessions(\n c: Context,\n scanSource: ScanResultSource,\n defaults: SessionListDefaults = {},\n) {\n const scanResult = scanSource.getSnapshot();\n const agent = c.req.query(\"agent\");\n const q = c.req.query(\"q\")?.toLowerCase();\n const cwd = c.req.query(\"cwd\");\n const projectIdentity = parseProjectIdentityFilter(\n c.req.query(\"projectKind\"),\n c.req.query(\"projectKey\"),\n );\n if (projectIdentity === null) {\n return c.json({ error: \"projectKind and projectKey must form a valid project identity\" }, 400);\n }\n const tag = c.req.query(\"tag\")?.toLowerCase();\n const from = parseDateParam(c.req.query(\"from\"), defaults.from);\n const to = parseDateParam(c.req.query(\"to\"), defaults.to);\n\n let sessions: SessionHead[] = [];\n\n // If agent filter is specified, use byAgent directly\n if (agent && scanResult.byAgent[agent]) {\n sessions = [...scanResult.byAgent[agent]!];\n } else {\n sessions = [...scanResult.sessions];\n }\n\n if (projectIdentity) {\n sessions = sessions.filter((session) =>\n matchesProjectIdentity(session.project_identity, projectIdentity),\n );\n } else if (cwd) {\n const projectScope = createProjectScopeMatcher(cwd);\n sessions = sessions.filter((s) => sessionMatchesProjectScope(s, projectScope));\n }\n sessions = filterSessionsByActivityWindow(sessions, from, to);\n if (tag) {\n sessions = sessions.filter((s) => s.smart_tags?.includes(tag as SmartTag));\n }\n\n const aliases = loadAliasView();\n if (q) {\n sessions = sessions.filter((session) => {\n const alias = aliases.get(getSessionHeadReference(session));\n return session.title.toLowerCase().includes(q) || alias?.toLowerCase().includes(q);\n });\n }\n return c.json({\n sessions: sessions.map((session) =>\n toSessionListItem(aliases.decorate(session, getSessionHeadReference(session))),\n ),\n });\n}\n\nexport function handleSearchSessions(\n c: Context,\n scanSource: ScanResultSource,\n defaults: SessionListDefaults = {},\n) {\n const query = c.req.query(\"q\")?.trim() ?? \"\";\n const scanResult = scanSource.getSnapshot();\n const projectIdentity = parseProjectIdentityFilter(\n c.req.query(\"projectKind\"),\n c.req.query(\"projectKey\"),\n );\n if (projectIdentity === null) {\n return c.json({ error: \"projectKind and projectKey must form a valid project identity\" }, 400);\n }\n const searchOptions = parseSearchOptions(c, defaults, projectIdentity);\n const aliases = loadAliasView();\n const results = executeSessionSearch(query, searchOptions, scanResult).map((result) => ({\n ...result,\n session: aliases.decorate(result.session, result.reference),\n }));\n const aliasResults = findAliasSearchResults(query, searchOptions, scanResult, aliases);\n const deduped = new Map<string, (typeof results)[number]>();\n for (const result of [...aliasResults, ...results]) {\n deduped.set(`${result.reference.agentName}\\0${result.reference.sessionId}`, result);\n }\n return c.json({ results: [...deduped.values()].slice(0, searchOptions.limit ?? 50) });\n}\n\nexport function handleGetFileActivity(c: Context, defaults: SessionListDefaults = {}) {\n const limitValue = Number(c.req.query(\"limit\"));\n const limit = Number.isFinite(limitValue) && limitValue > 0 ? Math.min(limitValue, 200) : 50;\n const projectIdentity = parseProjectIdentityFilter(\n c.req.query(\"projectKind\"),\n c.req.query(\"projectKey\"),\n );\n if (projectIdentity === null) {\n return c.json({ error: \"projectKind and projectKey must form a valid project identity\" }, 400);\n }\n\n const aliases = loadAliasView();\n return c.json({\n activity: listFileActivity({\n agent: optionalQueryValue(c.req.query(\"agent\")),\n sessionId: optionalQueryValue(c.req.query(\"sessionId\")),\n projectKind: projectIdentity?.kind,\n projectKey: projectIdentity?.key,\n project: optionalQueryValue(c.req.query(\"project\")),\n cwd: optionalQueryValue(c.req.query(\"cwd\")),\n path: optionalQueryValue(c.req.query(\"path\")),\n kind: parseFileActivityKind(optionalQueryValue(c.req.query(\"kind\"))),\n from: parseDateParam(c.req.query(\"from\"), defaults.from),\n to: parseDateParam(c.req.query(\"to\"), defaults.to),\n limit,\n }).map((activity) => decorateFileActivity(activity, aliases)),\n });\n}\n\nexport async function handleGetSessionData(c: Context, scanSource: ScanResultSource) {\n const startedAt = performance.now();\n const agentName = c.req.param(\"agent\");\n const sessionId = c.req.param(\"id\");\n\n if (!agentName) {\n return c.json({ error: \"Missing agent name\" }, 400);\n }\n\n if (!sessionId) {\n return c.json({ error: \"Missing session ID\" }, 400);\n }\n\n try {\n const result = materializeSessionDetailResponse(scanSource.getSnapshot(), {\n agentName,\n sessionId,\n });\n if (result.status === \"unknown-agent\") {\n return c.json({ error: `Unknown agent: ${agentName}` }, 404);\n }\n if (result.status === \"not-ready\") {\n appLogger.warn(\"api.session_data.cache_miss\", {\n agent: agentName,\n session_id: sessionId,\n duration_ms: Math.round(performance.now() - startedAt),\n });\n return c.json({ error: \"Session cache not ready\" }, 404);\n }\n\n appLogger.info(\"api.session_data\", {\n agent: agentName,\n session_id: sessionId,\n messages: result.status === \"found-json\" ? result.messageCount : result.data.messages.length,\n duration_ms: Math.round(performance.now() - startedAt),\n });\n const aliases = loadAliasView();\n if (result.status === \"found-json\") {\n return createSessionDetailJsonResponse(\n aliases.decorate(result.data, result.data.reference),\n result.messages,\n );\n }\n return c.json(aliases.decorate(result.data, result.data.reference));\n } catch (err) {\n const message = err instanceof Error ? err.message : \"Failed to load session\";\n appLogger.error(\"api.session_data.error\", {\n agent: agentName,\n session_id: sessionId,\n duration_ms: Math.round(performance.now() - startedAt),\n error: message,\n });\n return c.json({ error: message }, 500);\n }\n}\n\nexport async function handlePostClientLog(c: Context) {\n const payload = (await c.req.json().catch(() => null)) as ClientLogPayload | null;\n const rawEvent = payload?.event;\n\n if (typeof rawEvent !== \"string\" || !rawEvent.trim()) {\n return c.json({ ok: false }, 400);\n }\n\n const event = rawEvent\n .trim()\n .replace(/[^a-zA-Z0-9_.:-]/g, \"_\")\n .slice(0, 120);\n appLogger.info(`client.${event}`, sanitizeClientLogData(payload?.data));\n return c.json({ ok: true });\n}\n\nexport function handleGetBookmarks(c: Context) {\n return withStorageErrors(\n () => {\n const aliases = loadAliasView();\n return c.json({\n bookmarks: listBookmarks().map((bookmark) => decorateBookmark(bookmark, aliases)),\n storageAvailable: true,\n });\n },\n () => c.json({ bookmarks: [], storageAvailable: false }),\n );\n}\n\nexport async function handlePutBookmark(c: Context) {\n const payload = parseBookmarkPayload(await c.req.json().catch(() => null));\n if (!payload) {\n return c.json({ error: \"Invalid bookmark payload\" }, 400);\n }\n\n return withStorageErrors(\n () => c.json({ bookmark: upsertBookmark(payload), storageAvailable: true }),\n () => c.json({ error: \"Bookmark storage is unavailable\" }, 503),\n );\n}\n\nexport async function handleImportBookmarks(c: Context) {\n const payload = await c.req.json().catch(() => null);\n if (!Array.isArray(payload)) {\n return c.json({ error: \"Invalid bookmark payload\" }, 400);\n }\n\n const bookmarks = payload\n .map((entry) => parseBookmarkPayload(entry))\n .filter((entry): entry is NonNullable<typeof entry> => entry !== null);\n\n if (bookmarks.length !== payload.length) {\n return c.json({ error: \"Invalid bookmark payload\" }, 400);\n }\n\n return withStorageErrors(\n () => c.json({ bookmarks: importBookmarks(bookmarks), storageAvailable: true }),\n () => c.json({ error: \"Bookmark storage is unavailable\" }, 503),\n );\n}\n\nexport function handleDeleteBookmark(c: Context) {\n const agentKey = c.req.param(\"agent\");\n const sessionId = c.req.param(\"id\");\n if (!agentKey || !sessionId) {\n return c.json({ error: \"Missing bookmark identifier\" }, 400);\n }\n\n return withStorageErrors(\n () => {\n deleteBookmark({ agentName: agentKey, sessionId });\n return c.json({ ok: true, storageAvailable: true });\n },\n () => c.json({ error: \"Bookmark storage is unavailable\" }, 503),\n );\n}\n\nexport async function handlePutSessionAlias(c: Context) {\n const agentKey = c.req.param(\"agent\");\n const sessionId = c.req.param(\"id\");\n const payload = (await c.req.json().catch(() => null)) as SessionAliasPayload | null;\n const aliasValue = payload?.alias;\n if (!agentKey || !sessionId || typeof aliasValue !== \"string\") {\n return c.json({ error: \"Invalid session alias payload\" }, 400);\n }\n\n try {\n return withStorageErrors(\n () => {\n const alias = upsertSessionAlias({ agentName: agentKey, sessionId }, aliasValue);\n invalidateAliasView();\n return c.json({ alias });\n },\n () => c.json({ error: \"Session alias storage is unavailable\" }, 503),\n );\n } catch (error) {\n if (error instanceof SessionAliasValidationError) {\n return c.json({ error: \"Session alias must be non-empty and at most 160 characters\" }, 400);\n }\n throw error;\n }\n}\n\nexport function handleDeleteSessionAlias(c: Context) {\n const agentKey = c.req.param(\"agent\");\n const sessionId = c.req.param(\"id\");\n if (!agentKey || !sessionId) {\n return c.json({ error: \"Missing session alias identifier\" }, 400);\n }\n\n return withStorageErrors(\n () => {\n deleteSessionAlias({ agentName: agentKey, sessionId });\n invalidateAliasView();\n return c.json({ ok: true });\n },\n () => c.json({ error: \"Session alias storage is unavailable\" }, 503),\n );\n}\n\nexport function handleGetDashboard(\n c: Context,\n scanSource: ScanResultSource,\n defaults: SessionListDefaults = {},\n) {\n const scanResult = scanSource.getSnapshot();\n const projectIdentity = parseProjectIdentityFilter(\n c.req.query(\"projectKind\"),\n c.req.query(\"projectKey\"),\n );\n if (projectIdentity === null) {\n return c.json({ error: \"projectKind and projectKey must form a valid project identity\" }, 400);\n }\n const { from, to, days } = resolveTimeWindow({\n mode: \"dashboard\",\n query: {\n days: c.req.query(\"days\"),\n from: c.req.query(\"from\"),\n to: c.req.query(\"to\"),\n },\n defaults,\n });\n const scope: DashboardScope = {\n agent: optionalQueryValue(c.req.query(\"agent\"))?.toLowerCase(),\n projectKind: projectIdentity?.kind,\n projectKey: projectIdentity?.key,\n };\n\n const fixedTo = parseDateParam(c.req.query(\"to\"), defaults.to);\n const aggregate = getSnapshotAggregation(\n scanSource,\n scanResult.sessions,\n [\n \"dashboard\",\n scope.agent,\n scope.projectKind,\n scope.projectKey,\n from,\n fixedTo ?? startOfLocalDay(to),\n ],\n () => {\n const agentInfo = getAgentInfoMap({});\n const agentInfoMap = new Map(agentInfo.map((agent) => [agent.name, agent]));\n return buildDashboard(scanResult.sessions, {\n byAgentNames: Object.keys(scanResult.byAgent),\n scope,\n from,\n to,\n agentInfoMap,\n });\n },\n );\n\n const data: DashboardData = {\n ...aggregate,\n recentFileActivities: listFileActivity({\n agent: scope.agent,\n projectKind: scope.projectKind,\n projectKey: scope.projectKey,\n from,\n to,\n limit: 12,\n }),\n window: { from, to, days },\n };\n\n const aliases = loadAliasView();\n return c.json({\n ...data,\n recentSessions: data.recentSessions.map((item) => ({\n ...item,\n session: aliases.decorate(item.session, item.reference),\n })),\n recentFileActivities: data.recentFileActivities.map((activity) =>\n decorateFileActivity(activity, aliases),\n ),\n });\n}\n","import { randomBytes, timingSafeEqual } from \"node:crypto\";\nimport { isIP } from \"node:net\";\nimport type { Context, MiddlewareHandler } from \"hono\";\n\nexport const REMOTE_ACCESS_QUERY_PARAM = \"access_token\";\n\nexport function createRemoteAccessToken(): string {\n return randomBytes(32).toString(\"base64url\");\n}\n\nexport function isLoopbackHostname(hostname: string): boolean {\n const normalized = hostname.toLowerCase().replace(/^\\[(.*)\\]$/, \"$1\");\n if (normalized === \"localhost\" || normalized === \"::1\") return true;\n return isIP(normalized) === 4 && normalized.startsWith(\"127.\");\n}\n\nfunction tokenMatches(actual: string | undefined, expected: string): boolean {\n if (!actual) return false;\n const actualBuffer = Buffer.from(actual);\n const expectedBuffer = Buffer.from(expected);\n return (\n actualBuffer.length === expectedBuffer.length && timingSafeEqual(actualBuffer, expectedBuffer)\n );\n}\n\nfunction bearerToken(c: Context): string | undefined {\n const authorization = c.req.header(\"Authorization\");\n if (!authorization?.startsWith(\"Bearer \")) return undefined;\n return authorization.slice(\"Bearer \".length);\n}\n\nfunction requestToken(c: Context): string | undefined {\n const bearer = bearerToken(c);\n if (bearer) return bearer;\n if (c.req.method !== \"GET\") return undefined;\n return c.req.query(REMOTE_ACCESS_QUERY_PARAM);\n}\n\nexport function remoteAccessAuth(expectedToken: string): MiddlewareHandler {\n return async (c, next) => {\n if (!tokenMatches(requestToken(c), expectedToken)) {\n return c.json({ error: \"Remote access authentication required\" }, 401);\n }\n await next();\n };\n}\n","import { existsSync } from \"node:fs\";\nimport { fileURLToPath } from \"node:url\";\nimport {\n createRegisteredAgents,\n scanSessions,\n type LiveSnapshot,\n type ScanOptions,\n type SessionReference,\n} from \"@codesesh/core\";\nimport type {\n AgentScanStatus,\n BackfillStatus,\n ReferencedSessionHead,\n ScanStatusEvent,\n SessionsUpdatedEvent,\n} from \"@codesesh/core/contract\";\nimport { AgentSyncEngine } from \"./agent-sync-engine.js\";\nimport { appLogger } from \"./logging.js\";\nimport { SessionWatcher } from \"./session-watcher.js\";\nimport { ThreadWorkerRunner, type WorkerRunner } from \"./worker-runner.js\";\n\nexport type { AgentScanStatus, BackfillStatus, ScanStatusEvent, SessionsUpdatedEvent };\n\ntype StoreListener = (event: SessionsUpdatedEvent) => void;\ntype ScanStatusListener = (event: ScanStatusEvent) => void;\n\nexport interface LiveScanStoreOptions {\n watchEnabled?: boolean;\n scanOptions?: ScanOptions;\n startupScanOptions?: Pick<ScanOptions, \"from\" | \"to\">;\n deferInitialRefresh?: boolean;\n workerRunner?: WorkerRunner;\n}\n\nconst NEW_SESSION_EVENT_WINDOW_MS = 250;\n\nfunction mergeEvents(\n previous: SessionsUpdatedEvent,\n next: SessionsUpdatedEvent,\n): SessionsUpdatedEvent {\n const changedSessionHeads = new Map<string, ReferencedSessionHead>();\n const removedSessionRefs = new Map<string, SessionReference>();\n const sessionKey = (agentName: string, sessionId: string) => `${agentName}\\0${sessionId}`;\n const addChanged = (item: ReferencedSessionHead) => {\n const key = sessionKey(item.reference.agentName, item.reference.sessionId);\n removedSessionRefs.delete(key);\n changedSessionHeads.set(key, item);\n };\n const addRemoved = (item: SessionReference) => {\n const key = sessionKey(item.agentName, item.sessionId);\n changedSessionHeads.delete(key);\n removedSessionRefs.set(key, item);\n };\n for (const item of previous.changedSessionHeads) addChanged(item);\n for (const item of previous.removedSessionRefs) addRemoved(item);\n for (const item of next.changedSessionHeads) addChanged(item);\n for (const item of next.removedSessionRefs) addRemoved(item);\n return {\n type: \"sessions-updated\",\n changedAgents: Array.from(new Set([...previous.changedAgents, ...next.changedAgents])),\n newSessions: previous.newSessions + next.newSessions,\n updatedSessions: previous.updatedSessions + next.updatedSessions,\n removedSessions: previous.removedSessions + next.removedSessions,\n totalSessions: next.totalSessions,\n timestamp: next.timestamp,\n changedSessionHeads: [...changedSessionHeads.values()],\n removedSessionRefs: [...removedSessionRefs.values()],\n };\n}\n\nexport class LiveScanStore {\n private readonly watchEnabled: boolean;\n private readonly scanOptions: ScanOptions;\n private readonly startupScanOptions: Pick<ScanOptions, \"from\" | \"to\">;\n private readonly deferInitialRefresh: boolean;\n private readonly syncEngine: AgentSyncEngine;\n private listeners = new Set<StoreListener>();\n private watcher: SessionWatcher | null = null;\n private pendingEvent: SessionsUpdatedEvent | null = null;\n private pendingEventTimer: NodeJS.Timeout | null = null;\n private shutdownPromise: Promise<void> | null = null;\n private shuttingDown = false;\n\n constructor(options: LiveScanStoreOptions = {}) {\n this.watchEnabled = options.watchEnabled ?? true;\n this.scanOptions = options.scanOptions ?? {};\n this.startupScanOptions = options.startupScanOptions ?? {};\n this.deferInitialRefresh = options.deferInitialRefresh === true;\n const workerRunner =\n options.workerRunner ??\n new ThreadWorkerRunner(new URL(\"./scan-refresh-worker.js\", import.meta.url));\n this.syncEngine = new AgentSyncEngine({\n startupScanOptions: this.startupScanOptions,\n workerRunner,\n });\n this.syncEngine.subscribeSessionsChanged((change) => {\n if (change.event) this.emit(change.event);\n });\n }\n\n async initialize(): Promise<void> {\n const startedAt = performance.now();\n appLogger.info(\"scan.initial.start\", {\n watch_enabled: this.watchEnabled,\n agents: this.scanOptions.agents,\n use_cache: this.scanOptions.useCache ?? true,\n startup_from: this.startupScanOptions.from,\n startup_to: this.startupScanOptions.to,\n deferred: this.deferInitialRefresh || undefined,\n });\n const initialResult = await scanSessions({\n ...this.scanOptions,\n useCache: this.scanOptions.useCache ?? true,\n smartRefresh: false,\n cacheOnly: this.deferInitialRefresh,\n writeCache: this.deferInitialRefresh ? false : this.scanOptions.writeCache,\n smartTagWorkerUrl: this.getSmartTagWorkerUrl() ?? undefined,\n includeSmartTags: this.deferInitialRefresh ? false : undefined,\n });\n this.syncEngine.initialize(initialResult, {\n cacheTimestamps: initialResult.cacheTimestamps,\n registeredAgents: createRegisteredAgents(),\n allowedAgents: this.getAllowedAgents(),\n });\n const snapshot = this.getSnapshot();\n const indexStartedAt = performance.now();\n if (!this.deferInitialRefresh) await this.syncEngine.syncInitialIndex();\n const indexDuration = performance.now() - indexStartedAt;\n appLogger.info(\"scan.initial.done\", {\n duration_ms: Math.round(performance.now() - startedAt),\n index_ms: this.deferInitialRefresh ? undefined : Math.round(indexDuration),\n deferred: this.deferInitialRefresh || undefined,\n sessions: snapshot.sessions.length,\n agents: Object.fromEntries(\n Object.entries(snapshot.byAgent).map(([key, value]) => [key, value.length]),\n ),\n agent_timings: initialResult.timings\n ? Object.fromEntries(\n Object.entries(initialResult.timings).map(([name, timing]) => [\n name,\n {\n total_ms: Math.round(timing.total),\n cache_load_ms: timing.cacheLoad != null ? Math.round(timing.cacheLoad) : undefined,\n check_changes_ms:\n timing.checkChanges != null ? Math.round(timing.checkChanges) : undefined,\n scan_ms: timing.scan != null ? Math.round(timing.scan) : undefined,\n identity_ms: timing.identity != null ? Math.round(timing.identity) : undefined,\n tags_ms: timing.tags != null ? Math.round(timing.tags) : undefined,\n },\n ]),\n )\n : undefined,\n });\n if (!this.watchEnabled) return;\n this.watcher = new SessionWatcher();\n this.watcher.onAgentsChanged((agentNames) => this.syncEngine.handleAgentsChanged(agentNames));\n this.watcher.start(snapshot.agents);\n }\n\n startBackgroundRefresh(): void {\n this.syncEngine.startBackgroundRefresh();\n }\n\n getSnapshot(): LiveSnapshot {\n return this.syncEngine.snapshot();\n }\n\n getScanStatus(): ScanStatusEvent {\n return this.syncEngine.status();\n }\n\n subscribe(listener: StoreListener): () => void {\n this.listeners.add(listener);\n return () => this.listeners.delete(listener);\n }\n\n subscribeScanStatus(listener: ScanStatusListener): () => void {\n return this.syncEngine.subscribeStatusChanged(listener);\n }\n\n shutdown(): Promise<void> {\n this.shutdownPromise ??= this.performShutdown();\n return this.shutdownPromise;\n }\n\n private async performShutdown(): Promise<void> {\n this.shuttingDown = true;\n if (this.pendingEventTimer) {\n clearTimeout(this.pendingEventTimer);\n this.pendingEventTimer = null;\n }\n await this.syncEngine.shutdown();\n this.pendingEvent = null;\n if (this.watcher) {\n await this.watcher.dispose();\n this.watcher = null;\n }\n }\n\n private emit(event: SessionsUpdatedEvent): void {\n if (this.shuttingDown) return;\n if (this.pendingEvent || event.newSessions > 0) {\n this.queueEvent(event);\n return;\n }\n this.emitNow(event);\n }\n\n private emitNow(event: SessionsUpdatedEvent): void {\n for (const listener of this.listeners) listener(event);\n }\n\n private queueEvent(event: SessionsUpdatedEvent): void {\n this.pendingEvent = this.pendingEvent ? mergeEvents(this.pendingEvent, event) : event;\n if (this.pendingEventTimer) return;\n this.pendingEventTimer = setTimeout(() => {\n const pending = this.pendingEvent;\n this.pendingEvent = null;\n this.pendingEventTimer = null;\n if (pending) this.emitNow(pending);\n }, NEW_SESSION_EVENT_WINDOW_MS);\n }\n\n private getSmartTagWorkerUrl(): URL | null {\n const workerUrl = new URL(\"./smart-tag-worker.js\", import.meta.url);\n if (workerUrl.protocol === \"file:\" && !existsSync(fileURLToPath(workerUrl))) return null;\n return workerUrl;\n }\n\n private getAllowedAgents(): Set<string> | null {\n if (!this.scanOptions.agents?.length) return null;\n return new Set(this.scanOptions.agents.map((agent) => agent.toLowerCase()));\n }\n}\n","import { appLogger } from \"./logging.js\";\n\nexport type AgentOperationKind = \"backfill\" | \"refresh\";\nexport type AgentOperationResult = \"committed\" | \"failed\" | \"skipped\" | \"unchanged\";\n\ninterface AgentScheduleState {\n timer: NodeJS.Timeout | null;\n timerDeadline: number;\n isRefreshRunning: boolean;\n hasPendingRefresh: boolean;\n lastRefreshDurationMs: number;\n pendingSignalCount: number;\n}\n\ninterface AgentOperationLifecycle {\n agentName: string;\n kind: AgentOperationKind;\n generation: number;\n startedAt: number;\n}\n\nexport interface AgentOperationSchedulerSnapshot {\n activeOperations: number;\n activeRefreshes: number;\n}\n\nconst PENDING_REFRESH_DELAY_MS = 100;\nconst MAX_ADAPTIVE_REFRESH_DELAY_MS = 30_000;\nconst ADAPTIVE_REFRESH_DELAY_MULTIPLIER = 4;\n\nexport class AgentOperationScheduler {\n private readonly states = new Map<string, AgentScheduleState>();\n private readonly operationGenerations = new Map<string, number>();\n private readonly operationTails = new Map<string, Promise<void>>();\n private isStopped = false;\n\n constructor(private readonly runRefresh: (agentName: string) => Promise<AgentOperationResult>) {}\n\n notify(agentName: string, delayMs: number): void {\n if (this.isStopped) return;\n this.state(agentName).pendingSignalCount += 1;\n this.schedule(agentName, delayMs);\n }\n\n schedule(agentName: string, delayMs: number): void {\n if (this.isStopped) return;\n const state = this.state(agentName);\n const adaptiveDelayMs = Math.min(\n state.lastRefreshDurationMs * ADAPTIVE_REFRESH_DELAY_MULTIPLIER,\n MAX_ADAPTIVE_REFRESH_DELAY_MS,\n );\n const effectiveDelayMs = Math.max(delayMs, adaptiveDelayMs);\n const deadline = Date.now() + effectiveDelayMs;\n if (state.timer) {\n if (deadline >= state.timerDeadline) return;\n clearTimeout(state.timer);\n }\n\n appLogger.debug(\"scan.refresh.schedule\", { agent: agentName, delay_ms: effectiveDelayMs });\n state.timerDeadline = deadline;\n state.timer = setTimeout(() => {\n state.timer = null;\n state.timerDeadline = 0;\n void this.refresh(agentName);\n }, effectiveDelayMs);\n }\n\n async refresh(agentName: string): Promise<void> {\n if (this.isStopped) return;\n const state = this.state(agentName);\n if (state.isRefreshRunning) {\n appLogger.debug(\"scan.refresh.pending\", { agent: agentName });\n state.hasPendingRefresh = true;\n return;\n }\n\n state.isRefreshRunning = true;\n try {\n await this.run(agentName, \"refresh\", () => this.runRefresh(agentName));\n } finally {\n state.isRefreshRunning = false;\n if (state.hasPendingRefresh && !this.isStopped) {\n state.hasPendingRefresh = false;\n this.schedule(agentName, PENDING_REFRESH_DELAY_MS);\n }\n }\n }\n\n run(\n agentName: string,\n kind: AgentOperationKind,\n operation: () => Promise<AgentOperationResult>,\n ): Promise<AgentOperationResult> {\n const previous = this.operationTails.get(agentName) ?? Promise.resolve();\n const run = previous.then(async () => {\n if (this.isStopped) return \"skipped\";\n const lifecycle = this.beginOperation(agentName, kind);\n try {\n const result = await operation();\n this.completeOperation(lifecycle, result);\n return result;\n } catch (error) {\n this.completeOperation(lifecycle, \"failed\");\n throw error;\n }\n });\n const tail = run.then(\n () => undefined,\n () => undefined,\n );\n this.operationTails.set(agentName, tail);\n void tail.finally(() => {\n if (this.operationTails.get(agentName) === tail) this.operationTails.delete(agentName);\n });\n return run;\n }\n\n takePendingSignalCount(agentName: string): number {\n const state = this.state(agentName);\n const count = state.pendingSignalCount;\n state.pendingSignalCount = 0;\n return count;\n }\n\n recordRefreshDuration(agentName: string, durationMs: number): void {\n this.state(agentName).lastRefreshDurationMs = durationMs;\n }\n\n snapshot(): AgentOperationSchedulerSnapshot {\n return {\n activeOperations: this.operationTails.size,\n activeRefreshes: [...this.states.values()].filter((state) => state.isRefreshRunning).length,\n };\n }\n\n stop(): void {\n this.isStopped = true;\n for (const state of this.states.values()) {\n if (state.timer) clearTimeout(state.timer);\n state.timer = null;\n state.timerDeadline = 0;\n state.hasPendingRefresh = false;\n state.pendingSignalCount = 0;\n }\n }\n\n async waitForIdle(): Promise<void> {\n await Promise.allSettled(this.operationTails.values());\n }\n\n private state(agentName: string): AgentScheduleState {\n const existing = this.states.get(agentName);\n if (existing) return existing;\n const state: AgentScheduleState = {\n timer: null,\n timerDeadline: 0,\n isRefreshRunning: false,\n hasPendingRefresh: false,\n lastRefreshDurationMs: 0,\n pendingSignalCount: 0,\n };\n this.states.set(agentName, state);\n return state;\n }\n\n private beginOperation(agentName: string, kind: AgentOperationKind): AgentOperationLifecycle {\n const generation = (this.operationGenerations.get(agentName) ?? 0) + 1;\n const startedAt = Date.now();\n this.operationGenerations.set(agentName, generation);\n appLogger.info(\"scan.agent_operation.started\", {\n agent: agentName,\n operation: kind,\n generation,\n started_at: startedAt,\n });\n return { agentName, kind, generation, startedAt };\n }\n\n private completeOperation(\n lifecycle: AgentOperationLifecycle,\n result: AgentOperationResult,\n ): void {\n const completedAt = Date.now();\n appLogger.info(\"scan.agent_operation.completed\", {\n agent: lifecycle.agentName,\n operation: lifecycle.kind,\n generation: lifecycle.generation,\n started_at: lifecycle.startedAt,\n completed_at: completedAt,\n duration_ms: completedAt - lifecycle.startedAt,\n result,\n });\n }\n}\n","import {\n computeSessionDiff,\n mergeSortedSessions,\n sessionSignature,\n sortSessions,\n type BaseAgent,\n type LiveSnapshot,\n type SessionHead,\n} from \"@codesesh/core\";\nimport type { SessionsUpdatedEvent } from \"@codesesh/core/contract\";\n\nexport interface LiveSessionIndexOptions {\n registeredAgents?: BaseAgent[];\n allowedAgents?: ReadonlySet<string> | null;\n}\n\nexport class LiveSessionIndex {\n private agents: BaseAgent[] = [];\n private agentsByName = new Map<string, BaseAgent>();\n private byAgent: Record<string, SessionHead[]> = {};\n private sessions: SessionHead[] = [];\n private signatureCaches = new Map<string, Map<string, string>>();\n\n initialize(snapshot: LiveSnapshot, options: LiveSessionIndexOptions = {}): void {\n const agentMap = new Map<string, BaseAgent>();\n for (const agent of snapshot.agents) agentMap.set(agent.name, agent);\n for (const agent of options.registeredAgents ?? []) {\n if (!agentMap.has(agent.name)) agentMap.set(agent.name, agent);\n }\n\n this.agents = [...agentMap.values()].filter(\n (agent) => !options.allowedAgents || options.allowedAgents.has(agent.name.toLowerCase()),\n );\n this.agentsByName = new Map(this.agents.map((agent) => [agent.name, agent]));\n this.byAgent = Object.fromEntries(\n this.agents.map((agent) => [agent.name, sortSessions(snapshot.byAgent[agent.name] ?? [])]),\n );\n this.sessions = mergeSortedSessions(Object.values(this.byAgent));\n this.signatureCaches.clear();\n }\n\n snapshot(): LiveSnapshot {\n return {\n agents: this.agents,\n byAgent: this.byAgent,\n sessions: this.sessions,\n };\n }\n\n findAgent(agentName: string): BaseAgent | undefined {\n return this.agentsByName.get(agentName);\n }\n\n commitAgentSessions(\n agentName: string,\n nextSessions: SessionHead[],\n candidateChangedIds: string[] = [],\n ): SessionsUpdatedEvent | null {\n const previousSessions = this.byAgent[agentName] ?? [];\n const signatureCache = this.signatureCache(agentName);\n const { changes, removedSessionIds, counts } = computeSessionDiff(\n previousSessions,\n nextSessions,\n candidateChangedIds,\n sessionSignature,\n signatureCache,\n );\n for (const removedId of removedSessionIds) signatureCache.delete(removedId);\n\n this.byAgent[agentName] = sortSessions(nextSessions);\n this.sessions = mergeSortedSessions(Object.values(this.byAgent));\n if (counts.new === 0 && counts.updated === 0 && counts.removed === 0) return null;\n\n return {\n type: \"sessions-updated\",\n changedAgents: [agentName],\n newSessions: counts.new,\n updatedSessions: counts.updated,\n removedSessions: counts.removed,\n totalSessions: this.sessions.length,\n timestamp: Date.now(),\n changedSessionHeads: changes.map(({ session }) => ({\n reference: { agentName, sessionId: session.id },\n session,\n })),\n removedSessionRefs: removedSessionIds.map((sessionId) => ({ agentName, sessionId })),\n };\n }\n\n private signatureCache(agentName: string): Map<string, string> {\n const existing = this.signatureCaches.get(agentName);\n if (existing) return existing;\n const cache = new Map<string, string>();\n this.signatureCaches.set(agentName, cache);\n return cache;\n }\n}\n","import { existsSync } from \"node:fs\";\nimport { fileURLToPath } from \"node:url\";\nimport { Worker } from \"node:worker_threads\";\nimport { appLogger, logSearchIndexSync } from \"./logging.js\";\nimport { PendingSearchIndexJobs, type SearchIndexJobBatch } from \"./pending-search-index-jobs.js\";\nimport type { SearchIndexWorkerJob, SearchIndexWorkerMessage } from \"./search-index-worker.js\";\n\nconst SHUTDOWN_ERROR_MESSAGE = \"Live scan store shut down\";\n\nexport interface SearchIndexJobRunnerSnapshot {\n activeBatchId?: number;\n pendingBatches: number;\n pendingJobs: number;\n pendingChanges: number;\n}\n\nexport class SearchIndexJobRunner {\n private worker: Worker | null = null;\n private activeBatch: SearchIndexJobBatch | null = null;\n private nextBatchId = 1;\n private pendingJobs = new PendingSearchIndexJobs();\n private isShuttingDown = false;\n\n enqueue(context: string, jobs: SearchIndexWorkerJob[]): Promise<void> {\n if (jobs.length === 0) return Promise.resolve();\n if (this.isShuttingDown) return Promise.reject(new Error(SHUTDOWN_ERROR_MESSAGE));\n\n const batchId = this.nextBatchId++;\n const completion = this.pendingJobs.enqueue(batchId, context, jobs);\n if (this.worker) {\n const snapshot = this.snapshot();\n appLogger.debug(\"search_index.worker_queued\", {\n batch_id: batchId,\n context,\n jobs: jobs.length,\n pending_batches: snapshot.pendingBatches,\n pending_jobs: snapshot.pendingJobs,\n pending_changes: snapshot.pendingChanges,\n });\n } else {\n this.startNextBatch();\n }\n return completion;\n }\n\n snapshot(): SearchIndexJobRunnerSnapshot {\n return {\n activeBatchId: this.activeBatch?.id,\n pendingBatches: this.pendingJobs.batchCount,\n pendingJobs: this.pendingJobs.jobCount,\n pendingChanges: this.pendingJobs.changeCount,\n };\n }\n\n async shutdown(): Promise<void> {\n this.isShuttingDown = true;\n const activeBatch = this.activeBatch;\n const worker = this.worker;\n this.activeBatch = null;\n this.worker = null;\n\n const shutdownError = new Error(SHUTDOWN_ERROR_MESSAGE);\n if (activeBatch) this.settle(activeBatch, shutdownError);\n this.pendingJobs.rejectAll(shutdownError);\n if (worker) await worker.terminate();\n }\n\n private startNextBatch(): void {\n if (this.isShuttingDown || this.worker) return;\n const batch = this.pendingJobs.take();\n if (!batch) return;\n\n appLogger.info(\"search_index.worker_dequeued\", {\n batch_id: batch.id,\n context: batch.context,\n pending_batches: this.pendingJobs.batchCount,\n });\n this.startBatch(batch);\n }\n\n private startBatch(batch: SearchIndexJobBatch): void {\n if (this.isShuttingDown) {\n this.settle(batch, new Error(SHUTDOWN_ERROR_MESSAGE));\n return;\n }\n\n const workerUrl = this.workerUrl();\n if (!workerUrl) {\n appLogger.warn(\"search_index.worker_missing\", { context: batch.context });\n this.settle(batch);\n return;\n }\n appLogger.info(\"search_index.worker_started\", {\n batch_id: batch.id,\n context: batch.context,\n jobs: batch.jobs.length,\n });\n\n const worker = new Worker(workerUrl, {\n workerData: {\n context: batch.context,\n jobs: batch.jobs,\n agentNames: [],\n sessionsByAgent: {},\n metaByAgent: {},\n },\n });\n worker.unref();\n this.worker = worker;\n this.activeBatch = batch;\n\n worker.on(\"message\", (message: SearchIndexWorkerMessage) => {\n if (message.type === \"sync-result\") {\n logSearchIndexSync(message.context, message.result);\n return;\n }\n if (message.type !== \"done\") return;\n\n appLogger.info(`${message.context}.done`, {\n duration_ms: Math.round(message.durationMs),\n sessions: message.sessions,\n });\n this.settle(batch);\n });\n worker.on(\"error\", (error) => {\n appLogger.error(\"search_index.worker_error\", { context: batch.context, error });\n this.settle(batch, error);\n });\n worker.on(\"exit\", (code) => this.finishWorker(worker, batch, code));\n }\n\n private finishWorker(worker: Worker, batch: SearchIndexJobBatch, code: number): void {\n appLogger.info(\"search_index.worker_exited\", {\n batch_id: batch.id,\n context: batch.context,\n code,\n shutting_down: this.isShuttingDown || undefined,\n });\n if (this.worker === worker) this.worker = null;\n if (this.activeBatch === batch) this.activeBatch = null;\n\n const error =\n code === 0\n ? new Error(\"Search index worker exited before completing its batch\")\n : new Error(`Search index worker exited with code ${code}`);\n if (code !== 0) appLogger.warn(\"search_index.worker_exit\", { context: batch.context, code });\n this.settle(batch, error);\n this.startNextBatch();\n }\n\n private settle(batch: SearchIndexJobBatch, error?: Error): void {\n if (!this.pendingJobs.settle(batch, error)) return;\n appLogger.info(\"search_index.worker_settled\", {\n batch_id: batch.id,\n context: batch.context,\n result: error ? \"rejected\" : \"resolved\",\n });\n }\n\n private workerUrl(): URL | null {\n const workerUrl = new URL(\"./search-index-worker.js\", import.meta.url);\n if (workerUrl.protocol === \"file:\" && !existsSync(fileURLToPath(workerUrl))) return null;\n return workerUrl;\n }\n}\n","import type { SearchIndexSyncOptions, SessionCacheMeta, SessionHeadChange } from \"@codesesh/core\";\nimport type { SearchIndexWorkerJob } from \"./search-index-worker.js\";\n\ntype FullSearchIndexJob = Extract<SearchIndexWorkerJob, { kind: \"full\" }>;\ntype ChangesSearchIndexJob = Extract<SearchIndexWorkerJob, { kind: \"changes\" }>;\n\ninterface JobWaiter {\n resolve: () => void;\n reject: (error: Error) => void;\n}\n\ninterface PendingChanges {\n context: string;\n agentName: string;\n changesBySessionId: Map<string, SessionHeadChange>;\n removedSessionIds: Set<string>;\n meta: Record<string, SessionCacheMeta>;\n searchIndexOptions?: SearchIndexSyncOptions;\n}\n\ninterface PendingAgentJobs {\n full?: FullSearchIndexJob;\n changes?: PendingChanges;\n}\n\nexport interface SearchIndexJobBatch {\n readonly id: number;\n readonly context: string;\n readonly jobs: SearchIndexWorkerJob[];\n}\n\nclass PendingSearchIndexJobBatch implements SearchIndexJobBatch {\n context: string;\n private readonly jobsByAgent = new Map<string, PendingAgentJobs>();\n private readonly waiters: JobWaiter[] = [];\n private settled = false;\n\n constructor(\n readonly id: number,\n context: string,\n jobs: SearchIndexWorkerJob[],\n waiter: JobWaiter,\n ) {\n this.context = context;\n this.merge(context, jobs, waiter);\n }\n\n get jobs(): SearchIndexWorkerJob[] {\n const jobs: SearchIndexWorkerJob[] = [];\n for (const pending of this.jobsByAgent.values()) {\n if (pending.full) jobs.push(pending.full);\n if (pending.changes) jobs.push(changesJobFromPending(pending.changes));\n }\n return jobs;\n }\n\n get changeCount(): number {\n let count = 0;\n for (const pending of this.jobsByAgent.values()) {\n if (!pending.changes) continue;\n count += pending.changes.changesBySessionId.size + pending.changes.removedSessionIds.size;\n }\n return count;\n }\n\n merge(context: string, jobs: SearchIndexWorkerJob[], waiter: JobWaiter): void {\n this.context = context;\n this.waiters.push(waiter);\n for (const job of jobs) this.mergeJob(job);\n }\n\n settle(error?: Error): boolean {\n if (this.settled) return false;\n this.settled = true;\n for (const waiter of this.waiters) {\n if (error) waiter.reject(error);\n else waiter.resolve();\n }\n this.waiters.length = 0;\n return true;\n }\n\n private mergeJob(job: SearchIndexWorkerJob): void {\n const pending = this.jobsByAgent.get(job.agentName) ?? {};\n this.jobsByAgent.set(job.agentName, pending);\n\n if (job.kind === \"full\") {\n pending.full = job;\n pending.changes = undefined;\n return;\n }\n\n pending.changes ??= createPendingChanges(job);\n mergeChanges(pending.changes, job);\n }\n}\n\nexport class PendingSearchIndexJobs {\n private pendingBatch: PendingSearchIndexJobBatch | null = null;\n\n get batchCount(): number {\n return this.pendingBatch ? 1 : 0;\n }\n\n get jobCount(): number {\n return this.pendingBatch?.jobs.length ?? 0;\n }\n\n get changeCount(): number {\n return this.pendingBatch?.changeCount ?? 0;\n }\n\n enqueue(id: number, context: string, jobs: SearchIndexWorkerJob[]): Promise<void> {\n if (jobs.length === 0) return Promise.resolve();\n\n return new Promise((resolve, reject) => {\n const waiter = { resolve, reject };\n if (this.pendingBatch) {\n this.pendingBatch.merge(context, jobs, waiter);\n } else {\n this.pendingBatch = new PendingSearchIndexJobBatch(id, context, jobs, waiter);\n }\n });\n }\n\n take(): SearchIndexJobBatch | null {\n const batch = this.pendingBatch;\n this.pendingBatch = null;\n return batch;\n }\n\n settle(batch: SearchIndexJobBatch, error?: Error): boolean {\n return batch instanceof PendingSearchIndexJobBatch && batch.settle(error);\n }\n\n rejectAll(error: Error): void {\n const batch = this.take();\n if (batch) this.settle(batch, error);\n }\n}\n\nfunction createPendingChanges(job: ChangesSearchIndexJob): PendingChanges {\n return {\n context: job.context,\n agentName: job.agentName,\n changesBySessionId: new Map(),\n removedSessionIds: new Set(),\n meta: {},\n searchIndexOptions: job.searchIndexOptions,\n };\n}\n\nfunction mergeChanges(pending: PendingChanges, job: ChangesSearchIndexJob): void {\n pending.context = job.context;\n pending.searchIndexOptions = mergeSearchIndexOptions(\n pending.searchIndexOptions,\n job.searchIndexOptions,\n );\n\n for (const sessionId of job.removedSessionIds) {\n pending.changesBySessionId.delete(sessionId);\n pending.removedSessionIds.add(sessionId);\n delete pending.meta[sessionId];\n }\n\n for (const change of job.changes) {\n const sessionId = change.session.id;\n pending.removedSessionIds.delete(sessionId);\n pending.changesBySessionId.set(sessionId, change);\n if (Object.hasOwn(job.meta, sessionId)) pending.meta[sessionId] = job.meta[sessionId]!;\n else delete pending.meta[sessionId];\n }\n\n for (const [sessionId, meta] of Object.entries(job.meta)) {\n if (!pending.removedSessionIds.has(sessionId)) pending.meta[sessionId] = meta;\n }\n}\n\nfunction mergeSearchIndexOptions(\n current: SearchIndexSyncOptions | undefined,\n incoming: SearchIndexSyncOptions | undefined,\n): SearchIndexSyncOptions | undefined {\n if (!current) return incoming;\n if (!incoming) return current;\n return { ...current, ...incoming };\n}\n\nfunction changesJobFromPending(pending: PendingChanges): ChangesSearchIndexJob {\n return {\n kind: \"changes\",\n context: pending.context,\n agentName: pending.agentName,\n changes: [...pending.changesBySessionId.values()],\n removedSessionIds: [...pending.removedSessionIds],\n meta: pending.meta,\n ...(pending.searchIndexOptions ? { searchIndexOptions: pending.searchIndexOptions } : {}),\n };\n}\n","import type { AgentScanProgress } from \"@codesesh/core\";\nimport type { BackfillStatus, ScanStatusEvent } from \"@codesesh/core/contract\";\n\ntype ScanStatus = Omit<ScanStatusEvent, \"type\">;\n\nexport class ScanStatusModel {\n private status: ScanStatus = {\n active: false,\n phase: \"idle\",\n pendingAgents: [],\n scanningAgents: [],\n completedAgents: [],\n agentStatuses: {},\n totalAgents: 0,\n updatedAt: Date.now(),\n backfill: { active: false, pendingAgents: [], completedAgents: [], failedAgents: [] },\n };\n\n snapshot(): ScanStatusEvent {\n return {\n type: \"scan-status\",\n ...this.status,\n pendingAgents: [...this.status.pendingAgents],\n scanningAgents: [...this.status.scanningAgents],\n completedAgents: [...this.status.completedAgents],\n agentStatuses: Object.fromEntries(\n Object.entries(this.status.agentStatuses).map(([agentName, status]) => [\n agentName,\n { ...status },\n ]),\n ),\n backfill: {\n ...this.status.backfill,\n pendingAgents: [...this.status.backfill.pendingAgents],\n completedAgents: [...this.status.backfill.completedAgents],\n failedAgents: [...this.status.backfill.failedAgents],\n },\n };\n }\n\n startBatch(\n agentNames: string[],\n phase: ScanStatusEvent[\"phase\"],\n sessionCounts: Record<string, number>,\n ): ScanStatusEvent {\n const uniqueAgentNames = [...new Set(agentNames)];\n const now = Date.now();\n const agentStatuses = Object.fromEntries(\n uniqueAgentNames.map((agentName) => [\n agentName,\n {\n agentName,\n status: \"pending\" as const,\n processed: 0,\n sessions: sessionCounts[agentName] ?? 0,\n updatedAt: now,\n },\n ]),\n );\n return this.set({\n ...this.status,\n active: uniqueAgentNames.length > 0,\n phase: uniqueAgentNames.length > 0 ? phase : \"idle\",\n pendingAgents: uniqueAgentNames,\n scanningAgents: [],\n completedAgents: [],\n agentStatuses,\n totalAgents: uniqueAgentNames.length,\n startedAt: uniqueAgentNames.length > 0 ? now : undefined,\n updatedAt: now,\n completedAt: uniqueAgentNames.length > 0 ? undefined : now,\n });\n }\n\n setPhase(phase: ScanStatusEvent[\"phase\"]): ScanStatusEvent | null {\n if (!this.status.active) return null;\n return this.set({ ...this.status, phase, updatedAt: Date.now() });\n }\n\n beginAgent(agentName: string, sessionCount: number): ScanStatusEvent {\n if (!this.status.active)\n this.startBatch([agentName], \"scanning\", { [agentName]: sessionCount });\n\n const pendingAgents = this.status.pendingAgents.filter((agent) => agent !== agentName);\n const scanningAgents = [...new Set([...this.status.scanningAgents, agentName])];\n const completedAgents = this.status.completedAgents.filter((agent) => agent !== agentName);\n const existingStatus = this.status.agentStatuses[agentName];\n const now = Date.now();\n return this.set({\n ...this.status,\n active: true,\n phase: this.status.phase === \"initializing\" ? \"initializing\" : \"scanning\",\n pendingAgents,\n scanningAgents,\n completedAgents,\n agentStatuses: {\n ...this.status.agentStatuses,\n [agentName]: {\n agentName,\n status: \"scanning\",\n total: existingStatus?.total,\n processed: existingStatus?.processed ?? 0,\n sessions: existingStatus?.sessions ?? sessionCount,\n startedAt: existingStatus?.startedAt ?? now,\n updatedAt: now,\n },\n },\n totalAgents: Math.max(this.status.totalAgents, pendingAgents.length + scanningAgents.length),\n updatedAt: now,\n completedAt: undefined,\n });\n }\n\n updateAgent(agentName: string, progress: AgentScanProgress): ScanStatusEvent | null {\n const status = this.status.agentStatuses[agentName];\n if (!status || status.status !== \"scanning\") return null;\n const now = Date.now();\n return this.set({\n ...this.status,\n agentStatuses: {\n ...this.status.agentStatuses,\n [agentName]: {\n ...status,\n total: progress.total ?? status.total,\n processed: progress.processed ?? status.processed,\n sessions: progress.sessions ?? status.sessions,\n updatedAt: now,\n },\n },\n updatedAt: now,\n });\n }\n\n indexAgent(agentName: string): ScanStatusEvent | null {\n const status = this.status.agentStatuses[agentName];\n if (!this.status.active || !status || status.status !== \"scanning\") return null;\n\n const now = Date.now();\n const agentStatuses = {\n ...this.status.agentStatuses,\n [agentName]: { ...status, status: \"indexing\" as const, updatedAt: now },\n };\n return this.set({\n ...this.status,\n phase: this.activePhase(this.status.pendingAgents, this.status.scanningAgents, agentStatuses),\n agentStatuses,\n updatedAt: now,\n });\n }\n\n finishAgent(agentName: string, sessionCount?: number): ScanStatusEvent {\n const pendingAgents = this.status.pendingAgents.filter((agent) => agent !== agentName);\n const scanningAgents = this.status.scanningAgents.filter((agent) => agent !== agentName);\n const completedAgents = [...new Set([...this.status.completedAgents, agentName])];\n const isActive = pendingAgents.length > 0 || scanningAgents.length > 0;\n const now = Date.now();\n const previousStatus = this.status.agentStatuses[agentName];\n const total = previousStatus?.total ?? previousStatus?.processed;\n const agentStatuses = {\n ...this.status.agentStatuses,\n [agentName]: {\n agentName,\n status: \"complete\" as const,\n total,\n processed: total,\n sessions: sessionCount ?? previousStatus?.sessions ?? 0,\n startedAt: previousStatus?.startedAt,\n updatedAt: now,\n completedAt: now,\n },\n };\n\n return this.set({\n ...this.status,\n active: isActive,\n phase: isActive ? this.activePhase(pendingAgents, scanningAgents, agentStatuses) : \"idle\",\n pendingAgents,\n scanningAgents,\n completedAgents,\n agentStatuses,\n updatedAt: now,\n completedAt: isActive ? undefined : now,\n });\n }\n\n finishBatch(): ScanStatusEvent {\n const now = Date.now();\n return this.set({\n ...this.status,\n active: false,\n phase: \"idle\",\n pendingAgents: [],\n scanningAgents: [],\n agentStatuses: Object.fromEntries(\n Object.entries(this.status.agentStatuses).map(([agentName, status]) => [\n agentName,\n { ...status, status: \"complete\", completedAt: status.completedAt ?? now, updatedAt: now },\n ]),\n ),\n updatedAt: now,\n completedAt: now,\n });\n }\n\n updateBackfill(patch: Partial<BackfillStatus>): ScanStatusEvent {\n return this.set({\n ...this.status,\n backfill: { ...this.status.backfill, ...patch },\n updatedAt: Date.now(),\n });\n }\n\n private activePhase(\n pendingAgents: string[],\n scanningAgents: string[],\n agentStatuses: ScanStatus[\"agentStatuses\"],\n ): ScanStatusEvent[\"phase\"] {\n if (\n pendingAgents.length === 0 &&\n scanningAgents.length > 0 &&\n scanningAgents.every((agentName) => agentStatuses[agentName]?.status === \"indexing\")\n ) {\n return \"indexing\";\n }\n return this.status.phase === \"initializing\" ? \"initializing\" : \"scanning\";\n }\n\n private set(status: ScanStatus): ScanStatusEvent {\n this.status = status;\n return this.snapshot();\n }\n}\n","import {\n FileSystemSessionSource,\n attachMissingProjectIdentities,\n buildAgentCacheMeta,\n computeSessionDiff,\n getAgentLastFullSyncAt,\n isAgentCacheInitialized,\n loadCachedSessions,\n markAgentFullSyncCompleted,\n sessionSignature,\n type AgentScanProgress,\n type BaseAgent,\n type ScanOptions,\n type LiveSnapshot,\n type SessionHead,\n type SessionHeadChange,\n} from \"@codesesh/core\";\nimport type {\n BackfillStatus,\n ScanStatusEvent,\n SessionsUpdatedEvent,\n} from \"@codesesh/core/contract\";\nimport { AgentOperationScheduler, type AgentOperationResult } from \"./agent-operation-scheduler.js\";\nimport { LiveSessionIndex, type LiveSessionIndexOptions } from \"./live-session-index.js\";\nimport { appLogger, logSearchIndexSync } from \"./logging.js\";\nimport { SearchIndexJobRunner } from \"./search-index-job-runner.js\";\nimport type { SearchIndexWorkerJob } from \"./search-index-worker.js\";\nimport { ScanStatusModel } from \"./scan-status-model.js\";\nimport type { WorkerRunner } from \"./worker-runner.js\";\n\nexport type { AgentOperationResult } from \"./agent-operation-scheduler.js\";\n\nexport interface AgentSessionsChanged {\n agentName: string;\n sessions: SessionHead[];\n event: SessionsUpdatedEvent | null;\n}\n\nexport interface AgentSyncEngineOptions {\n startupScanOptions?: Pick<ScanOptions, \"from\" | \"to\">;\n workerRunner: WorkerRunner;\n}\n\nexport interface AgentSyncEngineInitializationOptions extends LiveSessionIndexOptions {\n cacheTimestamps?: Record<string, number>;\n}\n\ntype SessionsChangedListener = (change: AgentSessionsChanged) => void;\ntype StatusChangedListener = (event: ScanStatusEvent) => void;\ntype CachedSessions = NonNullable<ReturnType<typeof loadCachedSessions>>;\n\ninterface SessionPersistenceDiff {\n changedSessions: SessionHeadChange[];\n removedSessionIds: string[];\n}\n\ninterface SessionPublication {\n context: \"scan.refresh\" | \"scan.backfill\";\n agentName: string;\n sessions: SessionHead[];\n candidateChangedIds: string[];\n indexJob: SearchIndexWorkerJob;\n}\n\ninterface SessionPublicationResult {\n event: SessionsUpdatedEvent | null;\n diffDuration: number;\n}\n\ninterface RefreshStrategyResult {\n status: \"continue\" | \"unchanged\";\n nextSessions: SessionHead[];\n fullScanSessions: SessionHead[] | null;\n preciseChangedIds: string[] | null;\n persistenceDiff: SessionPersistenceDiff | null;\n checkDuration: number;\n scanDuration: number;\n}\n\nconst REFRESH_DEBOUNCE_MS = 200;\nconst EMPTY_AGENT_REFRESH_DEBOUNCE_MS = 30_000;\nconst SEARCH_INDEX_BULK_PENDING_PATH_THRESHOLD = 100;\nconst BACKFILL_INTERVAL_MS = 24 * 60 * 60 * 1000;\n\nfunction buildPersistenceDiff(\n previousSessions: SessionHead[],\n nextSessions: SessionHead[],\n candidateChangedIds: string[] = [],\n): SessionPersistenceDiff {\n const { changes, removedSessionIds } = computeSessionDiff(\n previousSessions,\n nextSessions,\n candidateChangedIds,\n sessionSignature,\n );\n return { changedSessions: changes, removedSessionIds };\n}\n\nfunction restoreAgentCacheMeta(agent: BaseAgent, cached: CachedSessions): void {\n agent.setSessionMetaMap(new Map(Object.entries(cached.meta)));\n}\n\nexport class AgentSyncEngine {\n private lastRefreshAtByAgent = new Map<string, number>();\n private readonly scheduler: AgentOperationScheduler;\n private readonly sessionIndex = new LiveSessionIndex();\n private backfillQueue: string[] = [];\n private currentBackfillAgent: string | undefined;\n private completedBackfillAgents: string[] = [];\n private failedBackfillAgents: string[] = [];\n private sessionsChangedListeners = new Set<SessionsChangedListener>();\n private statusChangedListeners = new Set<StatusChangedListener>();\n private scanStatus = new ScanStatusModel();\n private searchIndexJobs = new SearchIndexJobRunner();\n private nextPublicationId = 1;\n private backgroundRefreshTimer: NodeJS.Timeout | null = null;\n private isShuttingDown = false;\n\n constructor(private readonly options: AgentSyncEngineOptions) {\n this.scheduler = new AgentOperationScheduler((agentName) => this.performRefresh(agentName));\n }\n\n initialize(snapshot: LiveSnapshot, options: AgentSyncEngineInitializationOptions = {}): void {\n this.sessionIndex.initialize(snapshot, options);\n this.lastRefreshAtByAgent.clear();\n for (const agent of this.sessionIndex.snapshot().agents) {\n this.lastRefreshAtByAgent.set(\n agent.name,\n options.cacheTimestamps?.[agent.name] ?? Date.now(),\n );\n }\n }\n\n snapshot(): LiveSnapshot {\n return this.sessionIndex.snapshot();\n }\n\n status(): ScanStatusEvent {\n return this.scanStatus.snapshot();\n }\n\n subscribeSessionsChanged(listener: SessionsChangedListener): () => void {\n this.sessionsChangedListeners.add(listener);\n return () => this.sessionsChangedListeners.delete(listener);\n }\n\n subscribeStatusChanged(listener: StatusChangedListener): () => void {\n this.statusChangedListeners.add(listener);\n return () => this.statusChangedListeners.delete(listener);\n }\n\n async syncInitialIndex(): Promise<void> {\n const jobs = this.buildFullSearchIndexJobs(\"scan.initial\");\n await this.commitSearchIndex(\"scan.initial\", jobs, {\n publicationId: this.publicationId(\"scan.initial\"),\n agents: jobs.map((job) => job.agentName),\n });\n }\n\n handleAgentsChanged(agentNames: Iterable<string>): void {\n const snapshot = this.sessionIndex.snapshot();\n for (const agentName of agentNames) {\n const delayMs =\n (snapshot.byAgent[agentName]?.length ?? 0) === 0\n ? EMPTY_AGENT_REFRESH_DEBOUNCE_MS\n : REFRESH_DEBOUNCE_MS;\n this.scheduler.notify(agentName, delayMs);\n }\n }\n\n startBackgroundRefresh(): void {\n if (this.backgroundRefreshTimer) return;\n const agentNames = this.sessionIndex.snapshot().agents.map((agent) => agent.name);\n this.startScanBatch(agentNames, \"scanning\");\n this.backgroundRefreshTimer = setTimeout(() => {\n this.backgroundRefreshTimer = null;\n for (const agentName of agentNames) this.scheduler.schedule(agentName, 0);\n if (agentNames.length === 0) this.finishScanBatch();\n }, 0);\n }\n\n async refresh(agentName: string): Promise<void> {\n await this.scheduler.refresh(agentName);\n }\n\n async shutdown(): Promise<void> {\n this.isShuttingDown = true;\n const schedulerSnapshot = this.scheduler.snapshot();\n const activeOperations = {\n agent_operations: schedulerSnapshot.activeOperations,\n refreshes: schedulerSnapshot.activeRefreshes,\n backfill_running: this.currentBackfillAgent != null || undefined,\n scan_workers: this.options.workerRunner.activeCount,\n };\n if (activeOperations.agent_operations > 0 || activeOperations.scan_workers > 0) {\n appLogger.warn(\"scan.shutdown.active_operations\", activeOperations);\n }\n this.scheduler.stop();\n if (this.backgroundRefreshTimer) {\n clearTimeout(this.backgroundRefreshTimer);\n this.backgroundRefreshTimer = null;\n }\n this.backfillQueue.length = 0;\n this.currentBackfillAgent = undefined;\n const searchIndexSnapshot = this.searchIndexJobs.snapshot();\n appLogger.info(\"search_index.shutdown.started\", {\n active_batch_id: searchIndexSnapshot.activeBatchId,\n pending_batches: searchIndexSnapshot.pendingBatches,\n });\n await this.searchIndexJobs.shutdown();\n await this.options.workerRunner.shutdown();\n await this.scheduler.waitForIdle();\n const stoppedSearchIndexSnapshot = this.searchIndexJobs.snapshot();\n appLogger.info(\"search_index.shutdown.completed\", {\n active_batch_id: searchIndexSnapshot.activeBatchId,\n pending_batches: stoppedSearchIndexSnapshot.pendingBatches,\n });\n }\n\n private startScanBatch(agentNames: string[], phase: ScanStatusEvent[\"phase\"]): void {\n const snapshot = this.sessionIndex.snapshot();\n const sessionCounts = Object.fromEntries(\n agentNames.map((agentName) => [agentName, snapshot.byAgent[agentName]?.length ?? 0]),\n );\n this.publishStatus(this.scanStatus.startBatch(agentNames, phase, sessionCounts));\n }\n\n private setScanPhase(phase: ScanStatusEvent[\"phase\"]): void {\n this.publishStatus(this.scanStatus.setPhase(phase));\n }\n\n private beginAgentScan(agentName: string): void {\n const snapshot = this.sessionIndex.snapshot();\n if (!this.scanStatus.snapshot().active) this.startScanBatch([agentName], \"scanning\");\n this.publishStatus(\n this.scanStatus.beginAgent(agentName, snapshot.byAgent[agentName]?.length ?? 0),\n );\n }\n\n private updateAgentScanProgress(agentName: string, progress: AgentScanProgress): void {\n this.publishStatus(this.scanStatus.updateAgent(agentName, progress));\n }\n\n private beginAgentIndexing(agentName: string): void {\n this.publishStatus(this.scanStatus.indexAgent(agentName));\n }\n\n private finishAgentScan(agentName: string): void {\n const count = this.sessionIndex.snapshot().byAgent[agentName]?.length;\n this.publishStatus(this.scanStatus.finishAgent(agentName, count));\n }\n\n private finishScanBatch(): void {\n this.publishStatus(this.scanStatus.finishBatch());\n }\n\n private publishBackfillStatus(): void {\n this.publishStatus(this.scanStatus.updateBackfill(this.backfillStatus()));\n }\n\n private publishStatus(event: ScanStatusEvent | null): void {\n if (!event || this.isShuttingDown) return;\n for (const listener of this.statusChangedListeners) listener(event);\n }\n\n private emitSessionsChanged(change: AgentSessionsChanged): void {\n if (this.isShuttingDown) return;\n for (const listener of this.sessionsChangedListeners) listener(change);\n }\n\n private async performRefresh(agentName: string): Promise<AgentOperationResult> {\n this.beginAgentScan(agentName);\n try {\n return await this.runRefresh(agentName);\n } catch (error) {\n appLogger.error(\"scan.refresh.error\", { agent: agentName, error });\n console.error(`[${agentName}] Session refresh failed:`, error);\n return \"failed\";\n } finally {\n this.finishAgentScan(agentName);\n const agent = this.findAgent(agentName);\n if (agent && this.needsBackfill(agent)) this.enqueueBackfill(agentName);\n }\n }\n\n private async runRefresh(agentName: string): Promise<Exclude<AgentOperationResult, \"failed\">> {\n const startedAt = performance.now();\n const pendingPathCount = this.scheduler.takePendingSignalCount(agentName);\n const agent = this.findAgent(agentName);\n if (!agent) {\n appLogger.warn(\"scan.refresh.missing_agent\", { agent: agentName });\n return \"skipped\";\n }\n const previousSessions = this.sessionIndex.snapshot().byAgent[agentName] ?? [];\n const cached = loadCachedSessions(agentName);\n const refreshBaseline = cached?.sessions ?? previousSessions;\n const cacheTimestamp = cached?.timestamp ?? this.lastRefreshAtByAgent.get(agentName) ?? 0;\n if (cached) restoreAgentCacheMeta(agent, cached);\n const isInitialized = isAgentCacheInitialized(agentName);\n const availabilityStartedAt = performance.now();\n const isAvailable = agent.isAvailable();\n const availabilityDuration = performance.now() - availabilityStartedAt;\n let strategyResult: RefreshStrategyResult;\n if (!isAvailable) {\n strategyResult = this.refreshUnavailableAgent(agentName);\n } else if (!isInitialized) {\n strategyResult = await this.initializeAgent(agent, previousSessions);\n } else if (cached && agent instanceof FileSystemSessionSource) {\n strategyResult = await this.syncAgentSources(agent, cached, startedAt);\n } else if (refreshBaseline.length > 0) {\n strategyResult = await this.refreshChangedAgent(\n agent,\n refreshBaseline,\n cacheTimestamp,\n startedAt,\n );\n } else {\n strategyResult = await this.scanAgentFully(agent, previousSessions);\n }\n if (strategyResult.status === \"unchanged\") return \"unchanged\";\n\n const nextSessions = attachMissingProjectIdentities(strategyResult.nextSessions);\n const searchIndexOptions =\n pendingPathCount >= SEARCH_INDEX_BULK_PENDING_PATH_THRESHOLD ? { isBulk: true } : undefined;\n const persistenceDiff = strategyResult.persistenceDiff;\n const changedSessionIds = persistenceDiff\n ? new Set(persistenceDiff.changedSessions.map(({ session }) => session.id))\n : undefined;\n const persistStartedAt = performance.now();\n const persistentJob: SearchIndexWorkerJob = persistenceDiff\n ? {\n kind: \"changes\",\n context: \"scan.refresh\",\n agentName,\n changes: persistenceDiff.changedSessions,\n removedSessionIds: persistenceDiff.removedSessionIds,\n meta: buildAgentCacheMeta(agent, changedSessionIds),\n ...(searchIndexOptions ? { searchIndexOptions } : {}),\n }\n : {\n kind: \"full\",\n context: \"scan.refresh\",\n agentName,\n sessions: strategyResult.fullScanSessions ?? nextSessions,\n meta: buildAgentCacheMeta(agent),\n saveCache: true,\n ...(searchIndexOptions ? { searchIndexOptions } : {}),\n };\n this.beginAgentIndexing(agentName);\n const publication = await this.commitSessionPublication({\n context: \"scan.refresh\",\n agentName,\n sessions: nextSessions,\n candidateChangedIds: strategyResult.preciseChangedIds ?? [],\n indexJob: persistentJob,\n });\n const persistDuration = performance.now() - persistStartedAt;\n logSearchIndexSync(\"scan.refresh\", null, { pending_paths: pendingPathCount });\n\n const totalDurationMs = performance.now() - startedAt;\n this.scheduler.recordRefreshDuration(agentName, totalDurationMs);\n appLogger.info(\"scan.refresh.done\", {\n agent: agentName,\n duration_ms: Math.round(totalDurationMs),\n sessions: nextSessions.length,\n new_sessions: publication.event?.newSessions ?? 0,\n updated_sessions: publication.event?.updatedSessions ?? 0,\n removed_sessions: publication.event?.removedSessions ?? 0,\n pending_paths: pendingPathCount,\n availability_ms: Math.round(availabilityDuration),\n check_ms: Math.round(strategyResult.checkDuration),\n scan_ms: Math.round(strategyResult.scanDuration),\n diff_ms: Math.round(publication.diffDuration),\n persist_ms: Math.round(persistDuration),\n search_index_ms: Math.round(persistDuration),\n persistent_index_worker_job: persistentJob.kind,\n });\n return \"committed\";\n }\n\n private refreshUnavailableAgent(agentName: string): RefreshStrategyResult {\n this.lastRefreshAtByAgent.set(agentName, Date.now());\n return this.refreshStrategyResult([]);\n }\n\n private async initializeAgent(\n agent: BaseAgent,\n previousSessions: SessionHead[],\n ): Promise<RefreshStrategyResult> {\n this.setScanPhase(\"initializing\");\n const scanStartedAt = performance.now();\n const result = await this.runWorker(agent, previousSessions, null, this.startupScanOptions());\n agent.setSessionMetaMap(new Map(Object.entries(result.meta)));\n const sessions = attachMissingProjectIdentities(result.sessions);\n this.lastRefreshAtByAgent.set(agent.name, Date.now());\n return this.refreshStrategyResult(sessions, {\n fullScanSessions: sessions,\n scanDuration: performance.now() - scanStartedAt,\n });\n }\n\n private async syncAgentSources(\n agent: FileSystemSessionSource,\n cached: CachedSessions,\n refreshStartedAt: number,\n ): Promise<RefreshStrategyResult> {\n const scanStartedAt = performance.now();\n const result = await this.runWorker(agent, cached.sessions, null, this.startupScanOptions(), {\n sourceSync: true,\n meta: cached.meta,\n });\n agent.setSessionMetaMap(new Map(Object.entries(result.meta)));\n const sessions = attachMissingProjectIdentities(result.sessions);\n const preciseChangedIds = result.changedIds ?? [];\n const persistenceDiff = buildPersistenceDiff(cached.sessions, sessions, preciseChangedIds);\n this.lastRefreshAtByAgent.set(agent.name, Date.now());\n if (\n persistenceDiff.changedSessions.length === 0 &&\n persistenceDiff.removedSessionIds.length === 0\n ) {\n this.logUnchangedRefresh(agent.name, refreshStartedAt);\n return this.refreshStrategyResult(sessions, {\n status: \"unchanged\",\n scanDuration: performance.now() - scanStartedAt,\n });\n }\n return this.refreshStrategyResult(sessions, {\n preciseChangedIds,\n persistenceDiff,\n scanDuration: performance.now() - scanStartedAt,\n });\n }\n\n private async refreshChangedAgent(\n agent: BaseAgent,\n baseline: SessionHead[],\n cacheTimestamp: number,\n refreshStartedAt: number,\n ): Promise<RefreshStrategyResult> {\n const checkStartedAt = performance.now();\n const checkResult = await Promise.resolve(agent.checkForChanges(cacheTimestamp, baseline));\n const checkDuration = performance.now() - checkStartedAt;\n this.lastRefreshAtByAgent.set(agent.name, checkResult.timestamp);\n if (!checkResult.hasChanges) {\n this.logUnchangedRefresh(agent.name, refreshStartedAt);\n return this.refreshStrategyResult(baseline, { status: \"unchanged\", checkDuration });\n }\n const preciseChangedIds = checkResult.changedIds ?? null;\n const scanStartedAt = performance.now();\n if (preciseChangedIds === null) {\n const result = await this.runWorker(agent, baseline, null, {});\n agent.setSessionMetaMap(new Map(Object.entries(result.meta)));\n const sessions = attachMissingProjectIdentities(result.sessions);\n return this.refreshStrategyResult(sessions, {\n persistenceDiff: buildPersistenceDiff(baseline, sessions),\n checkDuration,\n scanDuration: performance.now() - scanStartedAt,\n });\n }\n const sessions = attachMissingProjectIdentities(\n await Promise.resolve(agent.incrementalScan(baseline, preciseChangedIds, checkResult.refs)),\n );\n return this.refreshStrategyResult(sessions, {\n preciseChangedIds,\n persistenceDiff: buildPersistenceDiff(baseline, sessions, preciseChangedIds),\n checkDuration,\n scanDuration: performance.now() - scanStartedAt,\n });\n }\n\n private async scanAgentFully(\n agent: BaseAgent,\n previousSessions: SessionHead[],\n ): Promise<RefreshStrategyResult> {\n const scanStartedAt = performance.now();\n const result = await this.runWorker(agent, previousSessions, null, {});\n agent.setSessionMetaMap(new Map(Object.entries(result.meta)));\n const sessions = attachMissingProjectIdentities(result.sessions);\n this.lastRefreshAtByAgent.set(agent.name, Date.now());\n return this.refreshStrategyResult(sessions, {\n fullScanSessions: sessions,\n scanDuration: performance.now() - scanStartedAt,\n });\n }\n\n private refreshStrategyResult(\n nextSessions: SessionHead[],\n overrides: Partial<Omit<RefreshStrategyResult, \"nextSessions\">> = {},\n ): RefreshStrategyResult {\n return {\n status: \"continue\",\n nextSessions,\n fullScanSessions: null,\n preciseChangedIds: null,\n persistenceDiff: null,\n checkDuration: 0,\n scanDuration: 0,\n ...overrides,\n };\n }\n\n private runWorker(\n agent: BaseAgent,\n previousSessions: SessionHead[],\n changedIds: string[] | null,\n scanOptions: Pick<ScanOptions, \"from\" | \"to\" | \"fast\">,\n workerOptions: { sourceSync?: boolean; meta?: CachedSessions[\"meta\"] } = {},\n ) {\n return this.options.workerRunner.run(agent.name, {\n previousSessions,\n changedIds,\n scanOptions,\n sourceSync: workerOptions.sourceSync,\n meta: workerOptions.meta ?? buildAgentCacheMeta(agent),\n onProgress: (progress) => this.updateAgentScanProgress(agent.name, progress),\n });\n }\n\n private needsBackfill(agent: BaseAgent): boolean {\n const startupScanOptions = this.startupScanOptions();\n if (startupScanOptions.from == null && startupScanOptions.to == null) return false;\n if (!agent.isAvailable()) return false;\n const lastSyncAt = getAgentLastFullSyncAt(agent.name);\n return lastSyncAt == null || Date.now() - lastSyncAt > BACKFILL_INTERVAL_MS;\n }\n\n private enqueueBackfill(agentName: string): void {\n if (\n this.isShuttingDown ||\n this.currentBackfillAgent === agentName ||\n this.backfillQueue.includes(agentName)\n ) {\n return;\n }\n this.backfillQueue.push(agentName);\n this.publishBackfillStatus();\n this.pumpBackfillQueue();\n }\n\n private pumpBackfillQueue(): void {\n if (this.isShuttingDown || this.currentBackfillAgent) return;\n const agentName = this.backfillQueue.shift();\n if (!agentName) return;\n this.currentBackfillAgent = agentName;\n this.publishBackfillStatus();\n void this.runBackfill(agentName).then((result) => {\n if (this.isShuttingDown) return;\n this.currentBackfillAgent = undefined;\n if (result === \"committed\") {\n if (!this.completedBackfillAgents.includes(agentName)) {\n this.completedBackfillAgents.push(agentName);\n }\n this.failedBackfillAgents = this.failedBackfillAgents.filter(\n (failedAgent) => failedAgent !== agentName,\n );\n } else if (!this.failedBackfillAgents.includes(agentName)) {\n this.failedBackfillAgents.push(agentName);\n }\n this.publishBackfillStatus();\n this.pumpBackfillQueue();\n });\n }\n\n private runBackfill(agentName: string): Promise<AgentOperationResult> {\n return this.scheduler.run(agentName, \"backfill\", () => this.performBackfill(agentName));\n }\n\n private async performBackfill(agentName: string): Promise<AgentOperationResult> {\n const startedAt = performance.now();\n const agent = this.findAgent(agentName);\n if (!agent || !agent.isAvailable()) return \"skipped\";\n const snapshot = this.sessionIndex.snapshot();\n const cached = loadCachedSessions(agentName);\n const baseline = cached?.sessions ?? snapshot.byAgent[agentName] ?? [];\n const meta = cached?.meta ?? buildAgentCacheMeta(agent);\n if (cached) restoreAgentCacheMeta(agent, cached);\n try {\n const result = await this.runWorker(\n agent,\n baseline,\n null,\n {},\n {\n sourceSync: agent instanceof FileSystemSessionSource,\n meta,\n },\n );\n agent.setSessionMetaMap(new Map(Object.entries(result.meta)));\n const fullSessions = attachMissingProjectIdentities(result.sessions);\n await this.commitSessionPublication({\n context: \"scan.backfill\",\n agentName,\n sessions: fullSessions,\n candidateChangedIds: result.changedIds ?? [],\n indexJob: {\n kind: \"full\",\n context: \"scan.backfill\",\n agentName,\n sessions: fullSessions,\n meta: buildAgentCacheMeta(agent),\n saveCache: true,\n },\n });\n markAgentFullSyncCompleted(agentName);\n appLogger.info(\"scan.backfill.done\", {\n agent: agentName,\n duration_ms: Math.round(performance.now() - startedAt),\n sessions: fullSessions.length,\n changed: result.changedIds?.length ?? 0,\n });\n return \"committed\";\n } catch (error) {\n appLogger.error(\"scan.backfill.error\", { agent: agentName, error });\n console.error(`[${agentName}] Backfill failed:`, error);\n return \"failed\";\n }\n }\n\n private backfillStatus(): BackfillStatus {\n return {\n active: this.currentBackfillAgent != null || this.backfillQueue.length > 0,\n pendingAgents: [...this.backfillQueue],\n currentAgent: this.currentBackfillAgent,\n completedAgents: [...this.completedBackfillAgents],\n failedAgents: [...this.failedBackfillAgents],\n };\n }\n\n private buildFullSearchIndexJobs(context: string): SearchIndexWorkerJob[] {\n const snapshot = this.sessionIndex.snapshot();\n return snapshot.agents.map((agent) => {\n const cached = loadCachedSessions(agent.name);\n return cached\n ? {\n kind: \"full\",\n context,\n agentName: agent.name,\n sessions: cached.sessions,\n meta: cached.meta,\n }\n : {\n kind: \"full\",\n context,\n agentName: agent.name,\n sessions: snapshot.byAgent[agent.name] ?? [],\n meta: buildAgentCacheMeta(agent),\n };\n });\n }\n\n private publicationId(context: string, agentName?: string): string {\n const id = this.nextPublicationId++;\n return agentName ? `${context}:${agentName}:${id}` : `${context}:${id}`;\n }\n\n private async commitSearchIndex(\n context: string,\n jobs: SearchIndexWorkerJob[],\n details: { publicationId: string; agent?: string; agents?: string[] },\n ): Promise<void> {\n appLogger.info(\"session.publication.prepared\", {\n publication_id: details.publicationId,\n context,\n agent: details.agent,\n agents: details.agents,\n jobs: jobs.length,\n });\n try {\n await this.searchIndexJobs.enqueue(context, jobs);\n } catch (error) {\n appLogger.error(\"session.publication.failed\", {\n publication_id: details.publicationId,\n context,\n agent: details.agent,\n stage: \"search_index\",\n error,\n });\n throw error;\n }\n appLogger.info(\"session.publication.index_committed\", {\n publication_id: details.publicationId,\n context,\n agent: details.agent,\n });\n }\n\n private async commitSessionPublication(\n publication: SessionPublication,\n ): Promise<SessionPublicationResult> {\n const publicationId = this.publicationId(publication.context, publication.agentName);\n await this.commitSearchIndex(publication.context, [publication.indexJob], {\n publicationId,\n agent: publication.agentName,\n });\n const diffStartedAt = performance.now();\n const event = this.sessionIndex.commitAgentSessions(\n publication.agentName,\n publication.sessions,\n publication.candidateChangedIds,\n );\n const diffDuration = performance.now() - diffStartedAt;\n this.emitSessionsChanged({\n agentName: publication.agentName,\n sessions: this.sessionIndex.snapshot().byAgent[publication.agentName] ?? [],\n event,\n });\n appLogger.info(\"session.publication.published\", {\n publication_id: publicationId,\n context: publication.context,\n agent: publication.agentName,\n sessions: publication.sessions.length,\n has_event: event != null,\n });\n return { event, diffDuration };\n }\n\n private findAgent(agentName: string): BaseAgent | undefined {\n return this.sessionIndex.findAgent(agentName);\n }\n\n private startupScanOptions(): Pick<ScanOptions, \"from\" | \"to\"> {\n return this.options.startupScanOptions ?? {};\n }\n\n private logUnchangedRefresh(agentName: string, startedAt: number): void {\n appLogger.debug(\"scan.refresh.unchanged\", {\n agent: agentName,\n duration_ms: Math.round(performance.now() - startedAt),\n });\n }\n}\n","/**\n * SessionWatcher — a deep module that hides platform-specific file watching\n * (recursive watch availability, non-recursive fallback trees, write-stability\n * polling, debounce) behind a tiny interface.\n *\n * Consumers only need to know: start watching these agent sources, stop, and get\n * notified (post write-stability + debounce) which agents' data changed. The\n * recursive-vs-fallback strategy, APFS mtime quirks, and path-stability polling\n * are all internal details.\n */\nimport { existsSync, readdirSync, statSync, watch, type FSWatcher } from \"node:fs\";\nimport { dirname, isAbsolute, join, relative, resolve } from \"node:path\";\nimport type { SessionWatchPlan } from \"@codesesh/core\";\nimport { appLogger } from \"./logging.js\";\n\nconst WRITE_STABILITY_THRESHOLD_MS = 250;\nconst WRITE_STABILITY_POLL_MS = 100;\n\nexport interface SessionWatchSource {\n readonly name: string;\n getSessionWatchPlan(): SessionWatchPlan;\n}\n\ninterface WatchScope {\n agentName: string;\n targetPath: string;\n}\n\ninterface StablePathState {\n path: string;\n agentNames: Set<string>;\n lastMtimeMs: number | null;\n lastSize: number | null;\n stableSince: number;\n timer: NodeJS.Timeout | null;\n}\n\nexport type AgentsChangedListener = (agentNames: Set<string>) => void;\n\nexport function toAbsolutePath(path: string): string {\n return isAbsolute(path) ? path : resolve(path);\n}\n\nfunction closestWatchablePath(targetPath: string): string | null {\n if (!isAbsolute(targetPath) && !existsSync(targetPath)) {\n return null;\n }\n\n let current = toAbsolutePath(targetPath);\n\n while (!existsSync(current)) {\n const parent = dirname(current);\n if (parent === current) {\n return null;\n }\n current = parent;\n }\n\n return current;\n}\n\nfunction getWatchRoot(path: string): string {\n const stat = statSync(path);\n return stat.isDirectory() ? path : dirname(path);\n}\n\nexport function isRecursiveWatchSupported(\n // \"ibmi\" is a real process.platform value on IBM i (PASE) but is not yet\n // declared in @types/node's Platform union.\n platform: NodeJS.Platform | \"ibmi\" = process.platform,\n nodeVersion = process.versions.node,\n): boolean {\n if (platform === \"darwin\" || platform === \"win32\") {\n return true;\n }\n if (platform !== \"linux\" && platform !== \"aix\" && platform !== \"ibmi\") {\n return false;\n }\n\n const [major = 0, minor = 0] = nodeVersion.split(\".\").map((part) => Number(part));\n return major > 19 || (major === 19 && minor >= 1);\n}\n\nfunction isRecursiveWatchUnavailable(error: unknown): boolean {\n return (\n typeof error === \"object\" &&\n error !== null &&\n \"code\" in error &&\n error.code === \"ERR_FEATURE_UNAVAILABLE_ON_PLATFORM\"\n );\n}\n\nfunction isSameOrChildPath(parentPath: string, childPath: string): boolean {\n const path = relative(parentPath, childPath);\n return path === \"\" || (!path.startsWith(\"..\") && !isAbsolute(path));\n}\n\nfunction isRelatedPath(changedPath: string, targetPath: string): boolean {\n return isSameOrChildPath(targetPath, changedPath) || isSameOrChildPath(changedPath, targetPath);\n}\n\nfunction mergeScopes(target: WatchScope[], scopes: WatchScope[]): void {\n for (const scope of scopes) {\n if (\n !target.some(\n (item) => item.agentName === scope.agentName && item.targetPath === scope.targetPath,\n )\n ) {\n target.push(scope);\n }\n }\n}\n\nfunction resolveWatchEventPath(watchPath: string, filename: string | Buffer | null): string {\n const filenameText = filename?.toString();\n if (!filenameText) {\n return watchPath;\n }\n return isAbsolute(filenameText) ? filenameText : join(watchPath, filenameText);\n}\n\nexport class SessionWatcher {\n private watchers: FSWatcher[] = [];\n private fallbackWatchScopes = new Map<string, WatchScope[]>();\n private stablePaths = new Map<string, StablePathState>();\n private listeners = new Set<AgentsChangedListener>();\n\n /** Register a listener fired (after write-stability polling) with the changed agent set. */\n onAgentsChanged(cb: AgentsChangedListener): () => void {\n this.listeners.add(cb);\n return () => {\n this.listeners.delete(cb);\n };\n }\n\n /** Begin watching the session sources declared by each agent adapter. */\n start(agents: SessionWatchSource[]): void {\n const scopesByRoot = new Map<string, WatchScope[]>();\n\n for (const agent of agents) {\n const plan = agent.getSessionWatchPlan();\n if (plan.status !== \"supported\") {\n appLogger.debug(\"watch.skip\", {\n agent: agent.name,\n status: plan.status,\n reason: plan.reason,\n });\n continue;\n }\n if (plan.targets.length === 0) {\n appLogger.debug(\"watch.skip\", { agent: agent.name, status: plan.status });\n continue;\n }\n\n for (const target of plan.targets) {\n const watchRootPath = closestWatchablePath(target.root ?? target.path);\n if (!watchRootPath) continue;\n\n let rootPath: string;\n try {\n rootPath = getWatchRoot(watchRootPath);\n } catch (error) {\n this.reportWatchError(\"watch.resolve.error\", { path: watchRootPath, error });\n continue;\n }\n const targetPath = toAbsolutePath(target.path);\n const scopes = scopesByRoot.get(rootPath) ?? [];\n if (\n !scopes.some((scope) => scope.agentName === agent.name && scope.targetPath === targetPath)\n ) {\n scopes.push({ agentName: agent.name, targetPath });\n }\n scopesByRoot.set(rootPath, scopes);\n }\n }\n\n for (const [rootPath, scopes] of scopesByRoot.entries()) {\n const agents = Array.from(new Set(scopes.map((scope) => scope.agentName)));\n appLogger.info(\"watch.start\", {\n root: rootPath,\n agents,\n targets: scopes.map((scope) => ({\n agent: scope.agentName,\n path: scope.targetPath,\n })),\n });\n\n if (isRecursiveWatchSupported()) {\n const started = this.watchDirectory(rootPath, scopes, true);\n if (started) {\n continue;\n }\n }\n\n this.watchDirectoryTree(rootPath, scopes);\n }\n }\n\n /** Stop all watchers and clear pending stability polls. */\n async dispose(): Promise<void> {\n for (const state of this.stablePaths.values()) {\n if (state.timer) {\n clearTimeout(state.timer);\n }\n }\n this.stablePaths.clear();\n\n await Promise.all(this.watchers.map((watcher) => watcher.close()));\n this.watchers = [];\n this.fallbackWatchScopes.clear();\n this.listeners.clear();\n }\n\n private watchDirectory(path: string, scopes: WatchScope[], recursive: boolean): boolean {\n try {\n const watcher = watch(path, { recursive }, (eventType, filename) => {\n queueMicrotask(() => {\n try {\n const activeScopes = recursive\n ? scopes\n : (this.fallbackWatchScopes.get(path) ?? scopes);\n this.handleWatchEvent(path, activeScopes, eventType, filename);\n if (!recursive) {\n this.watchNewDirectories(path, filename, activeScopes);\n }\n } catch (error) {\n this.reportWatchError(\"watch.event.error\", { path, recursive, error });\n }\n });\n });\n\n watcher.on(\"error\", (error) => {\n this.reportWatchError(\"watch.error\", { path, recursive, error });\n });\n\n this.watchers.push(watcher);\n return true;\n } catch (error) {\n if (recursive && isRecursiveWatchUnavailable(error)) {\n appLogger.warn(\"watch.recursive_unavailable\", { path, error });\n return false;\n }\n\n this.reportWatchError(\"watch.start.error\", { path, recursive, error });\n return false;\n }\n }\n\n private watchDirectoryTree(rootPath: string, scopes: WatchScope[]): void {\n const pending = [rootPath];\n\n while (pending.length > 0) {\n const dirPath = pending.pop()!;\n this.watchFallbackDirectory(dirPath, scopes);\n\n try {\n for (const entry of readdirSync(dirPath, { withFileTypes: true })) {\n if (entry.isDirectory()) {\n pending.push(join(dirPath, entry.name));\n }\n }\n } catch (error) {\n this.reportWatchError(\"watch.scan.error\", { path: dirPath, error });\n }\n }\n }\n\n private watchFallbackDirectory(path: string, scopes: WatchScope[]): void {\n const existingScopes = this.fallbackWatchScopes.get(path);\n if (existingScopes) {\n mergeScopes(existingScopes, scopes);\n return;\n }\n\n const storedScopes = [...scopes];\n this.fallbackWatchScopes.set(path, storedScopes);\n if (!this.watchDirectory(path, storedScopes, false)) {\n this.fallbackWatchScopes.delete(path);\n }\n }\n\n private watchNewDirectories(\n watchPath: string,\n filename: string | Buffer | null,\n scopes: WatchScope[],\n ): void {\n const path = resolveWatchEventPath(watchPath, filename);\n try {\n if (statSync(path).isDirectory()) {\n this.watchDirectoryTree(path, scopes);\n }\n } catch {}\n }\n\n private handleWatchEvent(\n watchPath: string,\n scopes: WatchScope[],\n eventType: string,\n filename: string | Buffer | null,\n ): void {\n const changedPath = resolveWatchEventPath(watchPath, filename);\n const agentNames = new Set(\n scopes\n .filter((scope) => isRelatedPath(changedPath, scope.targetPath))\n .map((scope) => scope.agentName),\n );\n\n if (agentNames.size === 0) {\n return;\n }\n\n appLogger.debug(\"watch.event\", {\n event: eventType,\n path: changedPath,\n agents: Array.from(agentNames),\n });\n this.waitForStablePath(changedPath, agentNames);\n }\n\n private waitForStablePath(path: string, agentNames: Set<string>): void {\n const existing = this.stablePaths.get(path);\n if (existing) {\n for (const agentName of agentNames) {\n existing.agentNames.add(agentName);\n }\n return;\n }\n\n const state: StablePathState = {\n path,\n agentNames: new Set(agentNames),\n lastMtimeMs: null,\n lastSize: null,\n stableSince: Date.now(),\n timer: null,\n };\n this.stablePaths.set(path, state);\n this.pollStablePath(path);\n }\n\n private pollStablePath(path: string): void {\n const state = this.stablePaths.get(path);\n if (!state) {\n return;\n }\n\n let size: number;\n let mtimeMs: number;\n try {\n const stat = statSync(path);\n size = stat.size;\n mtimeMs = stat.mtimeMs;\n } catch {\n this.stablePaths.delete(path);\n this.emitAgentsChanged(state.agentNames);\n return;\n }\n\n const now = Date.now();\n const unchanged = state.lastSize === size && state.lastMtimeMs === mtimeMs;\n if (!unchanged) {\n state.lastSize = size;\n state.lastMtimeMs = mtimeMs;\n state.stableSince = now;\n }\n\n if (unchanged && now - state.stableSince >= WRITE_STABILITY_THRESHOLD_MS) {\n this.stablePaths.delete(path);\n this.emitAgentsChanged(state.agentNames);\n return;\n }\n\n state.timer = setTimeout(() => this.pollStablePath(path), WRITE_STABILITY_POLL_MS);\n }\n\n private emitAgentsChanged(agentNames: Set<string>): void {\n if (agentNames.size === 0) return;\n for (const listener of this.listeners) {\n listener(new Set(agentNames));\n }\n }\n\n private reportWatchError(event: string, data: Record<string, unknown>): void {\n appLogger.error(event, data);\n console.error(\"[watch] File watcher failed:\", data.error);\n }\n}\n","import { Worker } from \"node:worker_threads\";\nimport type {\n AgentScanProgress,\n ScanOptions,\n SessionCacheMeta,\n SessionHead,\n SessionHeadChange,\n} from \"@codesesh/core\";\nimport { appLogger } from \"./logging.js\";\nimport type { ScanRefreshWorkerMessage, ScanRefreshWorkerRequest } from \"./scan-refresh-worker.js\";\n\nexport interface WorkerPayload {\n previousSessions: SessionHead[];\n changedIds: string[] | null;\n sourceSync?: boolean;\n scanOptions: Pick<ScanOptions, \"from\" | \"to\" | \"fast\">;\n meta: Record<string, SessionCacheMeta>;\n onProgress?: (progress: AgentScanProgress) => void;\n}\n\nexport interface WorkerResult {\n sessions: SessionHead[];\n meta: Record<string, SessionCacheMeta>;\n changedIds?: string[];\n}\n\nexport interface WorkerRunner {\n readonly activeCount: number;\n run(agentName: string, payload: WorkerPayload): Promise<WorkerResult>;\n shutdown(): Promise<void>;\n}\n\ninterface PendingRequest {\n resolve: (result: WorkerResult) => void;\n reject: (error: Error) => void;\n payload: WorkerPayload;\n onProgress?: (progress: AgentScanProgress) => void;\n}\n\ninterface WorkerSlot {\n worker: Worker;\n pending: Map<number, PendingRequest>;\n closed: boolean;\n}\n\nconst SHUTDOWN_ERROR_MESSAGE = \"Scan refresh worker shut down\";\n\nfunction applySessionChanges(\n previousSessions: SessionHead[],\n changes: SessionHeadChange[],\n removedSessionIds: string[],\n): SessionHead[] {\n const replacedIds = new Set(removedSessionIds);\n for (const { session } of changes) replacedIds.add(session.id);\n const retained = previousSessions.filter((session) => !replacedIds.has(session.id));\n const next: Array<SessionHead | undefined> = Array.from({\n length: retained.length + changes.length,\n });\n\n for (const { session, sortIndex } of changes) {\n if (sortIndex < 0 || sortIndex >= next.length || next[sortIndex]) {\n throw new Error(`Invalid scan refresh sort index: ${sortIndex}`);\n }\n next[sortIndex] = session;\n }\n\n let retainedIndex = 0;\n for (let index = 0; index < next.length; index += 1) {\n if (!next[index]) next[index] = retained[retainedIndex++];\n }\n if (retainedIndex !== retained.length || next.some((session) => !session)) {\n throw new Error(\"Invalid scan refresh delta\");\n }\n return next as SessionHead[];\n}\n\nfunction applyMetaChanges(\n previous: Record<string, SessionCacheMeta>,\n changed: Record<string, SessionCacheMeta>,\n replacedSessionIds: Iterable<string>,\n): Record<string, SessionCacheMeta> {\n const next = { ...previous };\n for (const id of replacedSessionIds) delete next[id];\n return Object.assign(next, changed);\n}\n\nexport class ThreadWorkerRunner implements WorkerRunner {\n private workers = new Map<string, WorkerSlot>();\n private nextRequestId = 1;\n private isShuttingDown = false;\n\n constructor(private readonly workerUrl: URL) {}\n\n get activeCount(): number {\n let count = 0;\n for (const slot of this.workers.values()) count += slot.pending.size;\n return count;\n }\n\n run(agentName: string, payload: WorkerPayload): Promise<WorkerResult> {\n if (this.isShuttingDown) return Promise.reject(new Error(SHUTDOWN_ERROR_MESSAGE));\n\n const request: ScanRefreshWorkerRequest = {\n type: \"run\",\n requestId: this.nextRequestId++,\n agentName,\n previousSessions: payload.previousSessions,\n changedIds: payload.changedIds,\n sourceSync: payload.sourceSync,\n scanOptions: payload.scanOptions,\n meta: payload.meta,\n };\n\n return new Promise((resolve, reject) => {\n let slot = this.workers.get(agentName);\n const isNewWorker = !slot;\n if (!slot) {\n try {\n slot = this.createWorker(agentName, request);\n } catch (error) {\n reject(error instanceof Error ? error : new Error(String(error)));\n return;\n }\n }\n\n slot.pending.set(request.requestId, {\n resolve,\n reject,\n payload,\n onProgress: payload.onProgress,\n });\n\n if (!isNewWorker) {\n try {\n slot.worker.postMessage(request);\n } catch (error) {\n slot.pending.delete(request.requestId);\n reject(error instanceof Error ? error : new Error(String(error)));\n }\n }\n });\n }\n\n async shutdown(): Promise<void> {\n this.isShuttingDown = true;\n const slots = [...this.workers.values()];\n this.workers.clear();\n const shutdownError = new Error(SHUTDOWN_ERROR_MESSAGE);\n for (const slot of slots) {\n slot.closed = true;\n for (const pending of slot.pending.values()) pending.reject(shutdownError);\n slot.pending.clear();\n }\n await Promise.allSettled(slots.map((slot) => slot.worker.terminate()));\n }\n\n private createWorker(agentName: string, request: ScanRefreshWorkerRequest): WorkerSlot {\n const worker = new Worker(this.workerUrl, { workerData: request });\n const slot: WorkerSlot = { worker, pending: new Map(), closed: false };\n worker.unref();\n this.workers.set(agentName, slot);\n worker.on(\"message\", (message: ScanRefreshWorkerMessage) => {\n this.handleMessage(slot, message);\n });\n worker.on(\"error\", (error) => {\n this.closeWorker(agentName, slot, error);\n });\n worker.on(\"exit\", (code) => {\n if (slot.closed) return;\n const error = new Error(`Scan refresh worker exited before completing (code ${code})`);\n if (slot.pending.size > 0) {\n appLogger.warn(\"scan.refresh_worker.exit_before_done\", { agent: agentName, code });\n }\n this.closeWorker(agentName, slot, error);\n });\n return slot;\n }\n\n private handleMessage(slot: WorkerSlot, message: ScanRefreshWorkerMessage): void {\n const pending = slot.pending.get(message.requestId);\n if (!pending) return;\n if (message.type === \"progress\") {\n pending.onProgress?.(message.progress);\n return;\n }\n\n slot.pending.delete(message.requestId);\n if (message.type === \"error\") {\n pending.reject(new Error(message.error));\n return;\n }\n const changedIds = message.changes.map(({ session }) => session.id);\n const replacedSessionIds = [...changedIds, ...message.removedSessionIds];\n const removedMetaIds = [...message.removedSessionIds, ...message.removedMetaIds];\n try {\n pending.resolve({\n sessions: applySessionChanges(\n pending.payload.previousSessions,\n message.changes,\n message.removedSessionIds,\n ),\n meta: applyMetaChanges(pending.payload.meta, message.meta, removedMetaIds),\n changedIds: pending.payload.sourceSync ? replacedSessionIds : undefined,\n });\n } catch (error) {\n pending.reject(error instanceof Error ? error : new Error(String(error)));\n }\n }\n\n private closeWorker(agentName: string, slot: WorkerSlot, error: Error): void {\n if (slot.closed) return;\n slot.closed = true;\n if (this.workers.get(agentName) === slot) this.workers.delete(agentName);\n for (const pending of slot.pending.values()) pending.reject(error);\n slot.pending.clear();\n }\n}\n","import { consola } from \"consola\";\nimport type { BaseAgent } from \"@codesesh/core\";\nimport { VERSION } from \"./version.js\";\n\nexport function printScanResults(agents: BaseAgent[]): void {\n consola.log(\"\");\n consola.box({\n title: \"CodeSesh\",\n message: `v${VERSION} • local session browser`,\n style: {\n padding: 1,\n borderColor: \"cyan\",\n },\n });\n consola.log(\"\");\n consola.info(\n `Indexing ${agents.map((agent) => agent.displayName).join(\", \")} sessions in the background.`,\n );\n consola.info(\"The Web UI will update automatically as sessions are discovered.\");\n consola.log(\"\");\n}\n","import { readFileSync } from \"node:fs\";\nimport { resolve, dirname } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\nconst pkg = JSON.parse(readFileSync(resolve(__dirname, \"../package.json\"), \"utf-8\"));\n\nexport const VERSION = pkg.version;\n","import type { ScanOptions } from \"@codesesh/core\";\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 = `/${targetSession.agent.toLowerCase()}/${targetSession.sessionId}`;\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"],"mappings":"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","names":["Hono","session","__dirname","resolve","Hono","url","existsSync","fileURLToPath","existsSync","fileURLToPath","resolve","existsSync","fileURLToPath","sessions","existsSync","dirname","resolve","resolve","existsSync","dirname","agents","Worker","SHUTDOWN_ERROR_MESSAGE","applySessionChanges","resolve","Worker","existsSync","fileURLToPath","resolve","dirname","fileURLToPath"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/server.ts","../src/api/routes.ts","../src/time-window-resolution.ts","../src/api/query-params.ts","../src/api/session-aliases-view.ts","../src/api/handlers.ts","../src/remote-access.ts","../src/live-scan.ts","../src/agent-operation-scheduler.ts","../src/live-session-index.ts","../src/search-index-job-runner.ts","../src/pending-search-index-jobs.ts","../src/scan-status-model.ts","../src/agent-sync-engine.ts","../src/session-watcher.ts","../src/worker-runner.ts","../src/output.ts","../src/version.ts","../src/session-index-output.ts","../src/runtime-plan.ts","../src/ports.ts","../src/pricing-refresh.ts"],"sourcesContent":["import \"./diagnostics-bridge.js\";\nimport { defineCommand, runMain } from \"citty\";\nimport { createServer, getServerStartupErrorMessage } from \"./server.js\";\nimport { LiveScanStore } from \"./live-scan.js\";\nimport { printScanResults } from \"./output.js\";\nimport { VERSION } from \"./version.js\";\nimport { appLogger } from \"./logging.js\";\nimport { buildSessionIndexOutput } from \"./session-index-output.js\";\nimport {\n isLoopbackHostname,\n resolveRemoteTransport,\n type RemoteTransport,\n} from \"./remote-access.js\";\nimport {\n buildCliRuntimePlan,\n parseSessionUri,\n redactStartupUrl,\n resolveStartupUrl,\n} from \"./runtime-plan.js\";\nimport {\n DEFAULT_PORT,\n DEFAULT_PORT_FALLBACK_ATTEMPTS,\n hasExplicitPortArg,\n parsePort,\n} from \"./ports.js\";\nimport { createRegisteredAgents, perf } from \"@codesesh/core\";\nimport { startPricingRefresh } from \"./pricing-refresh.js\";\n\nconst main = defineCommand({\n meta: {\n name: \"codesesh\",\n description: \"Discover, aggregate, and visualize AI coding agent sessions\",\n version: VERSION,\n },\n args: {\n port: {\n type: \"string\",\n alias: \"p\",\n description: \"HTTP server port\",\n default: String(DEFAULT_PORT),\n },\n host: {\n type: \"string\",\n description: \"HTTP server bind address (default 127.0.0.1, local access only)\",\n default: \"127.0.0.1\",\n },\n \"remote-access\": {\n type: \"boolean\",\n description: \"Allow authenticated access when binding to a non-loopback address\",\n default: false,\n },\n \"tls-cert\": {\n type: \"string\",\n description: \"Path to a TLS certificate; serve remote access over HTTPS\",\n },\n \"tls-key\": {\n type: \"string\",\n description: \"Path to the TLS private key matching --tls-cert\",\n },\n \"trust-proxy\": {\n type: \"boolean\",\n description: \"A reverse proxy in front of CodeSesh terminates TLS\",\n default: false,\n },\n agent: {\n type: \"string\",\n alias: \"a\",\n description: \"Filter to specific agent(s), comma-separated\",\n },\n days: {\n type: \"string\",\n alias: \"d\",\n description: \"Only include sessions active in the last N days (0 = all time)\",\n default: \"7\",\n },\n cwd: {\n type: \"string\",\n description: \"Filter to sessions from a specific project directory (use '.' for current dir)\",\n },\n from: {\n type: \"string\",\n description: \"Sessions active after this date, YYYY-MM-DD (overrides --days)\",\n },\n to: {\n type: \"string\",\n description: \"Sessions active before this date (YYYY-MM-DD)\",\n },\n session: {\n type: \"string\",\n alias: \"s\",\n description: \"Directly open a specific session (agent://session-id)\",\n },\n json: {\n type: \"boolean\",\n alias: \"j\",\n description: \"Output session index as JSON to stdout (no server)\",\n default: false,\n },\n noOpen: {\n type: \"boolean\",\n description: \"Don't auto-open browser\",\n default: false,\n },\n trace: {\n type: \"boolean\",\n description: \"Show performance trace logs\",\n default: false,\n },\n cache: {\n type: \"boolean\",\n description: \"Use cached scan results if available\",\n default: true,\n },\n \"clear-cache\": {\n type: \"boolean\",\n description: \"Clear scan cache before starting\",\n default: false,\n },\n },\n async run({ args }) {\n const startedAt = performance.now();\n const port = parsePort(args.port as string | undefined);\n const explicitPort = hasExplicitPortArg(process.argv.slice(2));\n const noOpen = args.noOpen as boolean;\n const jsonOnly = args.json as boolean;\n const trace = args.trace as boolean;\n const useCache = args.cache as boolean;\n const clearCache = args[\"clear-cache\"] as boolean;\n const hostname = args.host as string;\n const remoteAccess = args[\"remote-access\"] as boolean;\n\n if (!isLoopbackHostname(hostname) && !remoteAccess) {\n console.error(\n `Refusing to expose CodeSesh on ${hostname} without authentication. Add --remote-access to continue.`,\n );\n process.exit(1);\n }\n\n let transport: RemoteTransport;\n try {\n transport = resolveRemoteTransport({\n hostname,\n tlsCertPath: args[\"tls-cert\"] as string | undefined,\n tlsKeyPath: args[\"tls-key\"] as string | undefined,\n trustProxy: args[\"trust-proxy\"] as boolean,\n });\n } catch (error) {\n console.error(error instanceof Error ? error.message : String(error));\n process.exit(1);\n }\n\n if (trace) {\n perf.enable();\n }\n\n appLogger.info(\"cli.start\", {\n version: VERSION,\n argv: process.argv.slice(2),\n port,\n json: jsonOnly,\n no_open: noOpen,\n cache: useCache,\n log_path: appLogger.getLogPath(),\n });\n\n if (clearCache) {\n const { clearCache: clear } = await import(\"@codesesh/core\");\n clear();\n appLogger.info(\"cache.clear\");\n console.log(\"Cache cleared.\");\n }\n\n // Owns the refresh: bounded, cancellable, and published only between scans\n // so a scan never spans two price generations.\n const pricingRefresh = startPricingRefresh();\n\n // Parse session URI if provided\n let targetSession: { agent: string; sessionId: string } | null = null;\n if (args.session) {\n targetSession = parseSessionUri(args.session as string);\n if (!targetSession) {\n console.error(`Invalid session format: ${args.session}. Expected: agent://session-id`);\n process.exit(1);\n }\n }\n\n const { listWindow, scanOptions, startupScanOptions } = buildCliRuntimePlan(\n {\n agent: args.agent as string | undefined,\n cwd: args.cwd as string | undefined,\n from: args.from as string | undefined,\n to: args.to as string | undefined,\n days: args.days as string | undefined,\n jsonOnly,\n targetSession,\n useCache,\n },\n { currentWorkingDirectory: process.cwd() },\n );\n const { from: listDefaultFrom, to: listDefaultTo, days: listDefaultDays } = listWindow;\n\n const store = new LiveScanStore({\n watchEnabled: !jsonOnly,\n scanOptions,\n startupScanOptions,\n deferInitialRefresh: !jsonOnly,\n });\n await store.initialize();\n const result = store.getSnapshot();\n appLogger.info(\"cli.scan_ready\", {\n duration_ms: Math.round(performance.now() - startedAt),\n sessions: result.sessions.length,\n agents: Object.fromEntries(\n Object.entries(result.byAgent).map(([key, value]) => [key, value.length]),\n ),\n startup_from: startupScanOptions.from,\n startup_to: startupScanOptions.to,\n });\n\n if (trace) {\n console.log(perf.getReport());\n }\n\n if (jsonOnly) {\n // Nothing will consume a later generation, so stop waiting for it.\n await pricingRefresh.cancel();\n const output = buildSessionIndexOutput(result, { from: listDefaultFrom, to: listDefaultTo });\n appLogger.info(\"cli.json_output\", {\n sessions: output.sessions.length,\n duration_ms: Math.round(performance.now() - startedAt),\n });\n console.log(JSON.stringify(output, null, 2));\n return;\n }\n\n // Print console output\n const agents = createRegisteredAgents();\n printScanResults(agents);\n\n // Start server\n let app: Awaited<ReturnType<typeof createServer>>;\n try {\n app = await createServer(port, store, {\n defaultSessionFrom: listDefaultFrom,\n defaultSessionTo: listDefaultTo,\n defaultSessionDays: listDefaultDays,\n portFallbackAttempts: explicitPort ? 1 : DEFAULT_PORT_FALLBACK_ATTEMPTS,\n hostname,\n remoteAccess,\n transport,\n });\n } catch (error) {\n console.error(getServerStartupErrorMessage(error, port));\n process.exit(1);\n }\n\n const { url } = app;\n if (!jsonOnly) {\n // The startup scan has finished and background scans have not begun.\n pricingRefresh.publish();\n store.startBackgroundRefresh();\n }\n let shuttingDown = false;\n const shutdown = async (signal: NodeJS.Signals) => {\n if (shuttingDown) return;\n shuttingDown = true;\n appLogger.info(\"cli.shutdown\", { signal });\n await pricingRefresh.cancel();\n await app.shutdown();\n process.exit(0);\n };\n process.once(\"SIGINT\", (signal) => {\n void shutdown(signal);\n });\n process.once(\"SIGTERM\", (signal) => {\n void shutdown(signal);\n });\n\n console.log(` ${url}`);\n console.log(\"\");\n appLogger.info(\"cli.ready\", {\n url: redactStartupUrl(url),\n duration_ms: Math.round(performance.now() - startedAt),\n log_path: appLogger.getLogPath(),\n });\n\n if (!noOpen) {\n const open = (await import(\"open\")).default;\n const targetUrl = resolveStartupUrl(url, targetSession);\n appLogger.info(\"browser.open\", { url: redactStartupUrl(targetUrl) });\n await open(targetUrl);\n }\n },\n});\n\nif (process.argv.slice(2).includes(\"-v\")) {\n console.log(VERSION);\n process.exit(0);\n}\n\nrunMain(main);\n","import { Hono } from \"hono\";\nimport { bodyLimit } from \"hono/body-limit\";\nimport { compress } from \"hono/compress\";\nimport { serve } from \"@hono/node-server\";\nimport type { ServerType } from \"@hono/node-server\";\nimport { serveStatic } from \"@hono/node-server/serve-static\";\nimport { existsSync } from \"node:fs\";\nimport { createServer as createHttpsServer } from \"node:https\";\nimport type { AddressInfo } from \"node:net\";\nimport { resolve, dirname } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport type { ScanResultSource } from \"./api/handlers.js\";\nimport { createApiRoutes, type ApiRouteOptions } from \"./api/routes.js\";\nimport { appLogger } from \"./logging.js\";\nimport {\n createRemoteAccessToken,\n isLoopbackHostname,\n REMOTE_ACCESS_QUERY_PARAM,\n remoteAccessAuth,\n requireProxyTls,\n type RemoteTransport,\n} from \"./remote-access.js\";\nimport type { ScanEventSource } from \"./scan-source.js\";\n\nconst MAX_API_REQUEST_BYTES = 1024 * 1024;\n\nexport interface CreateServerOptions {\n defaultSessionFrom?: number;\n defaultSessionTo?: number;\n defaultSessionDays?: number;\n portFallbackAttempts?: number;\n hostname?: string;\n remoteAccess?: boolean;\n remoteAccessToken?: string;\n /** How the listener is protected; defaults to plaintext for a non-loopback host. */\n transport?: RemoteTransport;\n /** Overrides the auto-detected web build directory; used to pin the static root in tests. */\n webDistPath?: string;\n}\n\nfunction findWebDistPath(): string | null {\n const __dirname = dirname(fileURLToPath(import.meta.url));\n\n // Priority 1: Packaged web dist (copied during build)\n const packagedPath = resolve(__dirname, \"web\");\n if (existsSync(packagedPath)) {\n return packagedPath;\n }\n\n // Priority 2: Development path (monorepo)\n const devPath = resolve(__dirname, \"../../../apps/web/dist\");\n if (existsSync(devPath)) {\n return devPath;\n }\n\n return null;\n}\n\nfunction waitForListening(server: ServerType): Promise<void> {\n return new Promise((resolve, reject) => {\n const handleListening = () => {\n server.off(\"error\", handleError);\n resolve();\n };\n const handleError = (error: Error) => {\n server.off(\"listening\", handleListening);\n reject(error);\n };\n\n server.once(\"listening\", handleListening);\n server.once(\"error\", handleError);\n });\n}\n\nexport function getServerStartupErrorMessage(error: unknown, port: number): string {\n if (\n typeof error === \"object\" &&\n error !== null &&\n \"code\" in error &&\n error.code === \"EADDRINUSE\"\n ) {\n return `Port ${port} 已被占用,请关闭现有 CodeSesh 进程或改用 --port 指定其他端口。`;\n }\n\n return error instanceof Error ? error.message : `启动服务器失败: ${String(error)}`;\n}\n\nfunction isAddressInUse(error: unknown): boolean {\n return (\n typeof error === \"object\" && error !== null && \"code\" in error && error.code === \"EADDRINUSE\"\n );\n}\n\nfunction getListeningPort(server: ServerType, fallback: number): number {\n const address = server.address();\n return typeof address === \"object\" && address !== null ? (address as AddressInfo).port : fallback;\n}\n\nexport async function createServer(\n port: number,\n store: ScanResultSource & ScanEventSource & { shutdown(): Promise<void> },\n options: CreateServerOptions = {},\n): Promise<{ url: string; shutdown: () => Promise<void> }> {\n const app = new Hono();\n const hostname = options.hostname ?? \"127.0.0.1\";\n const isLoopback = isLoopbackHostname(hostname);\n const transport: RemoteTransport =\n options.transport ?? (isLoopback ? { kind: \"loopback\" } : { kind: \"plaintext\" });\n const remoteAccessToken = !isLoopback\n ? (options.remoteAccessToken ?? (options.remoteAccess ? createRemoteAccessToken() : null))\n : null;\n\n if (!isLoopback && !remoteAccessToken) {\n throw new Error(\n `Refusing to expose CodeSesh on ${hostname} without authentication. Add --remote-access to continue.`,\n );\n }\n\n app.use(\"*\", async (c, next) => {\n const startedAt = performance.now();\n let thrown: unknown;\n\n try {\n await next();\n } catch (error) {\n thrown = error;\n throw error;\n } finally {\n const url = new URL(c.req.url);\n appLogger.info(\"http.request\", {\n method: c.req.method,\n path: url.pathname,\n query_keys: [...url.searchParams.keys()].toSorted(),\n status: c.res.status,\n duration_ms: Math.round(performance.now() - startedAt),\n error: thrown instanceof Error ? thrown.message : undefined,\n });\n }\n });\n\n // Ordered before authentication: a request that bypassed the proxy must be\n // refused outright, not given a chance to present a token in the clear.\n if (transport.kind === \"trusted-proxy\") {\n app.use(\"/api/*\", requireProxyTls());\n }\n if (remoteAccessToken) {\n app.use(\"/api/*\", remoteAccessAuth(remoteAccessToken));\n }\n app.use(\n \"/api/*\",\n bodyLimit({\n maxSize: MAX_API_REQUEST_BYTES,\n onError: (c) => c.json({ error: \"Request body too large\" }, 413),\n }),\n );\n // Hono's default filter already excludes text/event-stream, so this does not\n // interfere with the /api/events SSE stream.\n app.use(\"/api/*\", compress());\n\n // API routes\n const routeOptions: ApiRouteOptions = {\n defaultSessionFrom: options.defaultSessionFrom,\n defaultSessionTo: options.defaultSessionTo,\n defaultSessionDays: options.defaultSessionDays,\n };\n app.route(\"/api\", createApiRoutes(store, store, routeOptions));\n\n // Serve static files from web dist (if available)\n const webDistPath = options.webDistPath ?? findWebDistPath();\n\n if (webDistPath) {\n app.use(\"/*\", serveStatic({ root: webDistPath }));\n app.get(\"/*\", serveStatic({ root: webDistPath, path: \"index.html\" }));\n }\n\n const attempts = Math.max(1, options.portFallbackAttempts ?? 1);\n let server: ServerType | null = null;\n let actualPort = port;\n\n for (let offset = 0; offset < attempts; offset += 1) {\n const candidatePort = port + offset;\n server = serve({\n fetch: app.fetch,\n port: candidatePort,\n hostname,\n ...(transport.kind === \"tls\"\n ? {\n createServer: createHttpsServer,\n serverOptions: { cert: transport.cert, key: transport.key },\n }\n : {}),\n });\n\n try {\n await waitForListening(server);\n actualPort = getListeningPort(server, candidatePort);\n break;\n } catch (error) {\n appLogger.error(\"server.listen.error\", { port: candidatePort, error });\n server.close();\n\n if (isAddressInUse(error) && offset < attempts - 1) {\n continue;\n }\n\n await store.shutdown();\n\n if (isAddressInUse(error) && attempts > 1) {\n throw new Error(\n `端口 ${port}-${port + attempts - 1} 均已被占用,请关闭现有进程或改用 --port 指定其他端口。`,\n );\n }\n\n throw new Error(getServerStartupErrorMessage(error, candidatePort));\n }\n }\n\n // A trusted proxy publishes its own https origin, so only direct TLS changes\n // the scheme CodeSesh prints for itself.\n const scheme = transport.kind === \"tls\" ? \"https\" : \"http\";\n const baseUrl = isLoopback\n ? `${scheme}://localhost:${actualPort}`\n : `${scheme}://${hostname}:${actualPort}`;\n const url = remoteAccessToken\n ? `${baseUrl}/?${REMOTE_ACCESS_QUERY_PARAM}=${encodeURIComponent(remoteAccessToken)}`\n : baseUrl;\n appLogger.info(\"server.listen\", {\n port: actualPort,\n requested_port: port,\n hostname,\n remote_access: Boolean(remoteAccessToken),\n transport: transport.kind,\n });\n\n if (!isLoopback) {\n appLogger.warn(\"server.listen.remote_access\", {\n hostname,\n port: actualPort,\n transport: transport.kind,\n });\n console.warn(`\\n⚠ 远程访问已启用。任何持有启动 URL 的人都可以读取你的 AI 会话记录。\\n`);\n if (transport.kind === \"plaintext\") {\n appLogger.warn(\"server.listen.plaintext\", { hostname, port: actualPort });\n console.warn(\n `⚠ 传输未加密。访问令牌与完整会话内容以明文经过网络,URL 中的令牌还可能写入代理访问日志。\\n` +\n ` 使用 --tls-cert/--tls-key 直接启用 TLS,或在受信反向代理后使用 --trust-proxy。\\n`,\n );\n }\n }\n\n return {\n url,\n shutdown: async () => {\n appLogger.info(\"server.shutdown\", { port: actualPort });\n await new Promise<void>((resolve) => {\n if (!server) {\n resolve();\n return;\n }\n server.close(() => resolve());\n });\n await store.shutdown();\n },\n };\n}\n","import { Hono } from \"hono\";\nimport {\n handleGetAgents,\n handleGetBookmarks,\n handleGetConfig,\n handleGetDashboard,\n handleGetFileActivity,\n handleGetProjects,\n handleGetScanStatus,\n handleDeleteBookmark,\n handleDeleteSessionAlias,\n handleImportBookmarks,\n handlePostClientLog,\n handleSearchSessions,\n handleGetSessions,\n handleGetSessionData,\n handlePutBookmark,\n handlePutSessionAlias,\n type ScanResultSource,\n type SessionListDefaults,\n} from \"./handlers.js\";\nimport type { ScanEventSource } from \"../scan-source.js\";\n\nexport interface ApiRouteOptions {\n defaultSessionFrom?: number;\n defaultSessionTo?: number;\n defaultSessionDays?: number;\n}\n\nfunction createSseResponse(eventSource: ScanEventSource, signal: AbortSignal): Response {\n const encoder = new TextEncoder();\n let cancelStream = () => {};\n\n return new Response(\n new ReadableStream({\n start(controller) {\n let isClosed = false;\n const write = (event: string, data: unknown) => {\n if (isClosed) return;\n controller.enqueue(encoder.encode(`event: ${event}\\n`));\n controller.enqueue(encoder.encode(`data: ${JSON.stringify(data)}\\n\\n`));\n };\n\n write(\"connected\", { timestamp: Date.now() });\n write(\"scan-status\", eventSource.getScanStatus());\n\n const unsubscribeSessions = eventSource.subscribe((event) => {\n write(event.type, event);\n });\n const unsubscribeScanStatus = eventSource.subscribeScanStatus((event) => {\n write(event.type, event);\n });\n\n const heartbeat = setInterval(() => {\n if (!isClosed) controller.enqueue(encoder.encode(\": keepalive\\n\\n\"));\n }, 15000);\n\n const cleanup = () => {\n if (isClosed) return false;\n isClosed = true;\n clearInterval(heartbeat);\n unsubscribeSessions();\n unsubscribeScanStatus();\n signal.removeEventListener(\"abort\", abortStream);\n return true;\n };\n const abortStream = () => {\n if (cleanup()) controller.close();\n };\n cancelStream = () => {\n cleanup();\n };\n\n if (signal.aborted) abortStream();\n else signal.addEventListener(\"abort\", abortStream, { once: true });\n },\n cancel() {\n cancelStream();\n },\n }),\n {\n headers: {\n \"Cache-Control\": \"no-cache\",\n Connection: \"keep-alive\",\n \"Content-Type\": \"text/event-stream\",\n },\n },\n );\n}\n\nexport function createApiRoutes(\n scanSource: ScanResultSource,\n eventSource?: ScanEventSource,\n options: ApiRouteOptions = {},\n): Hono {\n const api = new Hono();\n const listDefaults: SessionListDefaults = {\n from: options.defaultSessionFrom,\n to: options.defaultSessionTo,\n days: options.defaultSessionDays,\n };\n\n api.get(\"/config\", (c) => handleGetConfig(c, listDefaults));\n if (eventSource) {\n api.get(\"/status\", (c) => handleGetScanStatus(c, eventSource));\n }\n api.get(\"/agents\", (c) => handleGetAgents(c, scanSource, listDefaults));\n api.get(\"/projects\", (c) => handleGetProjects(c, scanSource, listDefaults));\n api.get(\"/sessions\", (c) => handleGetSessions(c, scanSource, listDefaults));\n api.get(\"/search\", (c) => handleSearchSessions(c, scanSource, listDefaults));\n api.get(\"/file-activity\", (c) => handleGetFileActivity(c, listDefaults));\n api.get(\"/sessions/:agent/:id\", (c) => handleGetSessionData(c, scanSource));\n api.get(\"/dashboard\", (c) => handleGetDashboard(c, scanSource, listDefaults));\n api.get(\"/bookmarks\", (c) => handleGetBookmarks(c));\n api.put(\"/bookmarks\", (c) => handlePutBookmark(c));\n api.post(\"/bookmarks/import\", (c) => handleImportBookmarks(c));\n api.delete(\"/bookmarks/:agent/:id\", (c) => handleDeleteBookmark(c));\n api.put(\"/session-aliases/:agent/:id\", (c) => handlePutSessionAlias(c));\n api.delete(\"/session-aliases/:agent/:id\", (c) => handleDeleteSessionAlias(c));\n api.post(\"/logs\", (c) => handlePostClientLog(c));\n if (eventSource) {\n api.get(\"/events\", (c) => createSseResponse(eventSource, c.req.raw.signal));\n }\n\n return api;\n}\n","import { addCalendarDays, countCalendarDays, startOfCalendarDay } from \"@codesesh/core/contract\";\n\n/** Rolling duration for CLI --days, which is a span of hours, not a calendar range. */\nconst ROLLING_DAY_MS = 24 * 60 * 60 * 1000;\nconst DEFAULT_DASHBOARD_DAYS = 30;\n\nexport interface TimeWindow {\n from?: number;\n to?: number;\n /** Original relative window value used by the UI label. */\n days?: number;\n}\n\ninterface RawTimeWindow {\n from?: string;\n to?: string;\n days?: string;\n}\n\ninterface CliTimeWindowRequest extends RawTimeWindow {\n mode: \"cli\";\n now?: number;\n}\n\ninterface DashboardTimeWindowRequest {\n mode: \"dashboard\";\n query: RawTimeWindow;\n defaults?: TimeWindow;\n now?: number;\n}\n\ninterface DashboardTimeWindow extends TimeWindow {\n to: number;\n}\n\ntype TimeWindowRequest = CliTimeWindowRequest | DashboardTimeWindowRequest;\n\nexport function resolveTimeWindow(request: CliTimeWindowRequest): TimeWindow;\nexport function resolveTimeWindow(request: DashboardTimeWindowRequest): DashboardTimeWindow;\nexport function resolveTimeWindow(request: TimeWindowRequest): TimeWindow {\n return request.mode === \"cli\" ? resolveCliWindow(request) : resolveDashboardWindow(request);\n}\n\nfunction resolveCliWindow(request: CliTimeWindowRequest): TimeWindow {\n const now = request.now ?? Date.now();\n const from = parseRequiredDate(request.from);\n const to = parseRequiredDate(request.to);\n if (from != null) return { from, to };\n\n const days = parseDays(request.days);\n if (days === 0) return { to, days };\n if (days == null || days < 0) return { to };\n\n const rollingFrom = now - days * ROLLING_DAY_MS;\n return Number.isFinite(rollingFrom) ? { from: rollingFrom, to, days } : { to };\n}\n\nfunction resolveDashboardWindow(request: DashboardTimeWindowRequest): DashboardTimeWindow {\n const now = request.now ?? Date.now();\n const defaults = request.defaults ?? {};\n const to = parseOptionalDate(request.query.to) ?? defaults.to ?? now;\n const hasQueryDays = Boolean(request.query.days?.trim());\n const parsedDays = hasQueryDays ? parseDays(request.query.days) : undefined;\n let days = parsedDays != null && parsedDays > 0 ? parsedDays : defaults.days;\n\n const queryFrom = parseOptionalDate(request.query.from);\n if (queryFrom != null) {\n days ??= countCalendarDays(queryFrom, to);\n return { from: queryFrom, to, days };\n }\n\n if (parsedDays === 0 || (!hasQueryDays && defaults.days === 0)) {\n return { to, days: 0 };\n }\n\n if (defaults.from != null) {\n days ??= countCalendarDays(defaults.from, to);\n return { from: defaults.from, to, days };\n }\n\n const resolvedDays = days != null && days > 0 ? days : DEFAULT_DASHBOARD_DAYS;\n return {\n from: addCalendarDays(startOfCalendarDay(to), -(resolvedDays - 1)),\n to,\n days: resolvedDays,\n };\n}\n\nfunction parseRequiredDate(value: string | undefined): number | undefined {\n if (!value) return undefined;\n const timestamp = new Date(value).getTime();\n if (Number.isNaN(timestamp)) throw new Error(`Invalid date: ${value}`);\n return timestamp;\n}\n\nfunction parseOptionalDate(value: string | undefined): number | undefined {\n if (value == null) return undefined;\n const timestamp = new Date(value).getTime();\n return Number.isNaN(timestamp) ? undefined : timestamp;\n}\n\nfunction parseDays(value: string | undefined): number | undefined {\n if (value == null) return undefined;\n const days = Number.parseInt(value, 10);\n return Number.isSafeInteger(days) && Number.isSafeInteger(days * ROLLING_DAY_MS)\n ? days\n : undefined;\n}\n","/**\n * Request-parameter parsing for the HTTP API. Everything here turns raw query\n * strings into the option objects the domain layer expects; no domain logic,\n * no storage access.\n */\nimport type { Context } from \"hono\";\nimport type { SessionHead, SmartTag } from \"@codesesh/core\";\nimport {\n filterSessionTreeByActivityWindow,\n isProjectIdentityKind,\n type FileActivityKind,\n type ProjectIdentityRef,\n type SearchOptions,\n} from \"@codesesh/core\";\nimport type { TimeWindow } from \"../time-window-resolution.js\";\n\nexport type SessionListDefaults = TimeWindow;\n\nconst SMART_TAGS: readonly string[] = [\n \"bugfix\",\n \"refactoring\",\n \"feature-dev\",\n \"testing\",\n \"docs\",\n \"git-ops\",\n \"build-deploy\",\n \"exploration\",\n \"planning\",\n];\n\nconst SEARCH_LIMIT_MAX = 100;\nconst SEARCH_LIMIT_DEFAULT = 50;\n\nexport function searchParams(c: Context): URLSearchParams {\n return new URL(c.req.url ?? \"http://localhost/\", \"http://localhost/\").searchParams;\n}\n\n/** Collects repeated and comma-separated values across several parameter names. */\nexport function queryValues(params: URLSearchParams, ...names: string[]): string[] {\n return names.flatMap((name) =>\n params\n .getAll(name)\n .flatMap((value) => value.split(\",\"))\n .map((value) => value.trim())\n .filter(Boolean),\n );\n}\n\nexport function optionalQueryValue(value: string | undefined): string | undefined {\n const normalized = value?.trim();\n return normalized ? normalized : undefined;\n}\n\nexport function parseDateParam(\n value: string | undefined,\n fallback: number | undefined,\n): number | undefined {\n if (value == null) return fallback;\n const ts = new Date(value).getTime();\n return Number.isNaN(ts) ? fallback : ts;\n}\n\nexport function parseNumberParam(value: string | undefined): number | undefined {\n if (value == null || !value.trim()) return undefined;\n const number = Number(value);\n return Number.isFinite(number) ? number : undefined;\n}\n\nexport function parseSmartTags(values: string[]): SmartTag[] | undefined {\n const tags = values\n .map((value) => value.toLowerCase())\n .filter((value): value is SmartTag => SMART_TAGS.includes(value));\n return tags.length > 0 ? [...new Set(tags)] : undefined;\n}\n\nexport function parseFileActivityKind(value: string | undefined): FileActivityKind | undefined {\n if (value === \"read\" || value === \"edit\" || value === \"write\" || value === \"delete\") {\n return value;\n }\n return undefined;\n}\n\n/**\n * Returns the identity when both halves are present and valid, `undefined` when\n * neither is supplied, and `null` when the pair is incomplete or malformed —\n * callers turn that `null` into a 400.\n */\nexport function parseProjectIdentityFilter(\n kindValue: string | undefined,\n keyValue: string | undefined,\n): ProjectIdentityRef | null | undefined {\n const kind = optionalQueryValue(kindValue);\n const key = optionalQueryValue(keyValue);\n if (!kind && !key) return undefined;\n if (!kind || !key || !isProjectIdentityKind(kind)) return null;\n return { kind, key };\n}\n\nexport function parseSearchOptions(\n c: Context,\n defaults: SessionListDefaults,\n projectIdentity?: ProjectIdentityRef,\n): SearchOptions {\n const params = searchParams(c);\n const limitValue = parseNumberParam(params.get(\"limit\") ?? undefined);\n return {\n agent: optionalQueryValue(params.get(\"agent\") ?? undefined),\n project: optionalQueryValue(params.get(\"project\") ?? undefined),\n projectKind: projectIdentity?.kind,\n projectKey: projectIdentity?.key,\n cwd: optionalQueryValue(params.get(\"cwd\") ?? undefined),\n tags: parseSmartTags(queryValues(params, \"tag\", \"tags\", \"signal\")),\n tools: queryValues(params, \"tool\", \"tools\").map((tool) => tool.toLowerCase()),\n file: optionalQueryValue(params.get(\"file\") ?? params.get(\"path\") ?? undefined),\n fileKind: parseFileActivityKind(\n optionalQueryValue(params.get(\"fileKind\") ?? params.get(\"fileActivity\") ?? undefined),\n ),\n costMin: parseNumberParam(params.get(\"costMin\") ?? undefined),\n costMax: parseNumberParam(params.get(\"costMax\") ?? undefined),\n from: parseDateParam(params.get(\"from\") ?? undefined, defaults.from),\n to: parseDateParam(params.get(\"to\") ?? undefined, defaults.to),\n limit:\n limitValue && limitValue > 0 ? Math.min(limitValue, SEARCH_LIMIT_MAX) : SEARCH_LIMIT_DEFAULT,\n };\n}\n\nexport function filterSessionsByActivityWindow(\n sessions: SessionHead[],\n from: number | undefined,\n to: number | undefined,\n): SessionHead[] {\n return filterSessionTreeByActivityWindow(sessions, from, to);\n}\n","/**\n * Session aliases as a read model for the HTTP layer: load the user's local\n * renames once, then decorate outgoing records with `display_title`.\n */\nimport type { BookmarkRecord, SessionAlias, SessionHead } from \"@codesesh/core\";\nimport type { SearchResult, SessionReference } from \"@codesesh/core/contract\";\nimport {\n filterSessionSearchCandidates,\n getSessionActivityTime,\n listSessionAliases,\n mergeSearchQueryOptions,\n StateStorageUnavailableError,\n type FileActivityResult,\n type LiveSnapshot,\n type SearchOptions,\n} from \"@codesesh/core\";\nimport { appLogger } from \"../logging.js\";\n\n/** Anything the API returns that can carry a locally-renamed title. */\ntype Titled = { id: string; title: string; display_title?: string };\n\nexport interface AliasView {\n readonly size: number;\n get(reference: SessionReference): string | undefined;\n /** Returns the record unchanged when no alias applies, so callers can pass through freely. */\n decorate<T extends Titled>(record: T, reference: SessionReference): T;\n entries(): IterableIterator<SessionAlias>;\n}\n\nfunction aliasKey(reference: SessionReference): string {\n return `${reference.agentName.toLowerCase()}\\0${reference.sessionId}`;\n}\n\nfunction loadAliasMap(): Map<string, SessionAlias> {\n try {\n return new Map(listSessionAliases().map((alias) => [aliasKey(alias.reference), alias]));\n } catch (error) {\n if (!(error instanceof StateStorageUnavailableError)) {\n appLogger.warn(\"api.session_aliases.load_failed\", {\n error: error instanceof Error ? error.message : String(error),\n });\n }\n return new Map();\n }\n}\n\nfunction buildAliasView(): AliasView {\n const aliases = loadAliasMap();\n return {\n size: aliases.size,\n get: (reference) => aliases.get(aliasKey(reference))?.alias,\n decorate(record, reference) {\n const alias = aliases.get(aliasKey(reference))?.alias;\n return alias ? { ...record, display_title: alias } : record;\n },\n entries: () => aliases.values(),\n };\n}\n\n/**\n * Aliases change only through this process's own PUT/DELETE handlers, so the\n * read model is built once and reused until one of them invalidates it. Six read\n * handlers call this per request; without the cache each one re-queries the whole\n * table. A storage failure is cached too — it does not heal between requests, and\n * invalidateAliasView() is what lets a recovered store be retried.\n */\nlet cachedView: AliasView | null = null;\n\nexport function loadAliasView(): AliasView {\n return (cachedView ??= buildAliasView());\n}\n\nexport function invalidateAliasView(): void {\n cachedView = null;\n}\n\nexport function decorateBookmark(bookmark: BookmarkRecord, aliases: AliasView): BookmarkRecord {\n return {\n ...bookmark,\n session: aliases.decorate(bookmark.session, bookmark.reference),\n };\n}\n\nexport function decorateFileActivity(\n activity: FileActivityResult,\n aliases: AliasView,\n): FileActivityResult {\n return {\n ...activity,\n session: aliases.decorate(activity.session, activity.reference),\n };\n}\n\n/**\n * Aliases are stored outside the search index, so a query matching only a local\n * rename has to be resolved here. Hits still have to satisfy the same\n * time-window / project / agent filters as the main search, otherwise an aliased\n * session could surface outside its search scope.\n */\nexport function findAliasSearchResults(\n query: string,\n options: SearchOptions,\n scanResult: LiveSnapshot,\n aliases: AliasView,\n): SearchResult[] {\n const search = mergeSearchQueryOptions(query, options);\n const needle = search.text.trim().toLowerCase();\n if (!needle || aliases.size === 0) return [];\n\n const sessionsByAgent = new Map<string, Map<string, SessionHead>>();\n const lookupSession = (agentName: string, sessionId: string): SessionHead | undefined => {\n let byId = sessionsByAgent.get(agentName);\n if (!byId) {\n byId = new Map((scanResult.byAgent[agentName] ?? []).map((item) => [item.id, item]));\n sessionsByAgent.set(agentName, byId);\n }\n return byId.get(sessionId);\n };\n\n const results: SearchResult[] = [];\n for (const alias of aliases.entries()) {\n if (!alias.alias.toLowerCase().includes(needle)) continue;\n const { agentName, sessionId } = alias.reference;\n const session = lookupSession(agentName, sessionId);\n if (!session) continue;\n results.push({\n reference: alias.reference,\n session: aliases.decorate(session, alias.reference),\n snippet: `Alias · ${session.directory}`,\n matchType: \"title\",\n });\n }\n\n return filterSessionSearchCandidates(results, search.options).sort(\n (a, b) => getSessionActivityTime(b.session) - getSessionActivityTime(a.session),\n );\n}\n","import type { Context } from \"hono\";\nimport type {\n BookmarkRecord,\n LiveSnapshot,\n SessionDetail,\n SessionHead,\n SmartTag,\n} from \"@codesesh/core\";\nimport {\n formatSessionReference,\n getSessionAgentKey,\n normalizeSessionReference,\n type AppConfig,\n type ScanStatusEvent,\n type SessionReference,\n startOfCalendarDay,\n} from \"@codesesh/core/contract\";\nimport {\n SessionAliasValidationError,\n StateStorageUnavailableError,\n attachProjectMetrics,\n createProjectScopeMatcher,\n deleteBookmark,\n getAgentInfoMap,\n executeSessionSearch,\n importBookmarks,\n listFileActivity,\n listCachedProjectGroups,\n listBookmarks,\n deleteSessionAlias,\n materializeSessionDetailResponse,\n upsertSessionAlias,\n upsertBookmark,\n matchesProjectScope as sessionMatchesProjectScope,\n matchesProjectIdentity,\n buildDashboard,\n type DashboardData,\n type DashboardScope,\n} from \"@codesesh/core\";\nimport { appLogger } from \"../logging.js\";\nimport { resolveTimeWindow } from \"../time-window-resolution.js\";\nimport {\n filterSessionsByActivityWindow,\n parseDateParam,\n parseFileActivityKind,\n parseProjectIdentityFilter,\n parseSearchOptions,\n optionalQueryValue,\n type SessionListDefaults,\n} from \"./query-params.js\";\nimport {\n decorateBookmark,\n decorateFileActivity,\n findAliasSearchResults,\n invalidateAliasView,\n loadAliasView,\n} from \"./session-aliases-view.js\";\n\nexport type { SessionListDefaults };\n\nexport interface ScanResultSource {\n getSnapshot(): LiveSnapshot;\n}\n\nexport interface ScanStatusSource {\n getScanStatus(): ScanStatusEvent;\n}\n\ninterface SnapshotAggregationCache {\n sessions: SessionHead[];\n values: Map<string, unknown>;\n}\n\nconst SNAPSHOT_AGGREGATION_CACHE_LIMIT = 64;\nconst snapshotAggregationCaches = new WeakMap<ScanResultSource, SnapshotAggregationCache>();\n\n/**\n * LiveScanStore replaces its canonical sessions array whenever the snapshot\n * changes, so that existing reference is the snapshot version.\n */\nfunction getSnapshotAggregation<T>(\n source: ScanResultSource,\n sessions: SessionHead[],\n key: readonly unknown[],\n build: () => T,\n): T {\n let cache = snapshotAggregationCaches.get(source);\n if (!cache || cache.sessions !== sessions) {\n cache = { sessions, values: new Map() };\n snapshotAggregationCaches.set(source, cache);\n }\n\n const cacheKey = JSON.stringify(key);\n if (cache.values.has(cacheKey)) return cache.values.get(cacheKey) as T;\n\n const value = build();\n if (cache.values.size >= SNAPSHOT_AGGREGATION_CACHE_LIMIT) {\n const oldestKey = cache.values.keys().next().value;\n if (oldestKey != null) cache.values.delete(oldestKey);\n }\n cache.values.set(cacheKey, value);\n return value;\n}\n\ninterface ClientLogPayload {\n event?: unknown;\n data?: unknown;\n}\n\ninterface SessionAliasPayload {\n alias?: unknown;\n}\n\nfunction withStorageErrors<TResult, TFallback>(\n handler: () => TResult,\n onUnavailable: () => TFallback,\n): TResult | TFallback {\n try {\n return handler();\n } catch (error) {\n if (error instanceof StateStorageUnavailableError) {\n return onUnavailable();\n }\n throw error;\n }\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null;\n}\n\nfunction isSessionStats(value: unknown): value is SessionHead[\"stats\"] {\n if (!isRecord(value)) return false;\n return (\n typeof value.message_count === \"number\" &&\n typeof value.total_input_tokens === \"number\" &&\n typeof value.total_output_tokens === \"number\" &&\n typeof value.total_cost === \"number\" &&\n (value.total_tokens == null || typeof value.total_tokens === \"number\")\n );\n}\n\ntype BookmarkInput = Omit<BookmarkRecord, \"bookmarkedAt\">;\n\nfunction parseBookmarkSession(\n value: unknown,\n reference: SessionReference,\n): BookmarkInput[\"session\"] | null {\n if (!isRecord(value)) return null;\n if (\n value.id !== reference.sessionId ||\n typeof value.slug !== \"string\" ||\n typeof value.title !== \"string\" ||\n typeof value.directory !== \"string\" ||\n typeof value.time_created !== \"number\" ||\n (value.time_updated != null && typeof value.time_updated !== \"number\") ||\n !isSessionStats(value.stats)\n ) {\n return null;\n }\n\n return {\n id: reference.sessionId,\n slug: formatSessionReference(reference),\n title: value.title,\n directory: value.directory,\n time_created: value.time_created,\n time_updated: value.time_updated ?? undefined,\n stats: value.stats,\n };\n}\n\nfunction parseSessionReferencePayload(value: unknown): SessionReference | null {\n if (\n !isRecord(value) ||\n typeof value.agentName !== \"string\" ||\n typeof value.sessionId !== \"string\" ||\n !value.agentName.trim() ||\n !value.sessionId\n ) {\n return null;\n }\n return normalizeSessionReference({\n agentName: value.agentName.trim().toLowerCase(),\n sessionId: value.sessionId,\n });\n}\n\nfunction parseBookmarkPayload(value: unknown): BookmarkInput | null {\n if (!isRecord(value)) return null;\n\n const reference = parseSessionReferencePayload(value.reference);\n if (reference) {\n const session = parseBookmarkSession(value.session, reference);\n return session ? { reference, session } : null;\n }\n\n if (\n typeof value.agentKey !== \"string\" ||\n typeof value.sessionId !== \"string\" ||\n typeof value.fullPath !== \"string\" ||\n !value.agentKey.trim() ||\n !value.sessionId\n ) {\n return null;\n }\n const legacyReference = normalizeSessionReference({\n agentName: value.agentKey.trim().toLowerCase(),\n sessionId: value.sessionId,\n });\n const session = parseBookmarkSession(\n {\n ...value,\n id: value.sessionId,\n slug: value.fullPath,\n },\n legacyReference,\n );\n return session ? { reference: legacyReference, session } : null;\n}\n\nfunction sanitizeClientLogData(value: unknown): Record<string, unknown> {\n if (!isRecord(value)) return {};\n\n return Object.fromEntries(\n Object.entries(value)\n .slice(0, 30)\n .map(([key, item]) => {\n if (typeof item === \"string\") return [key, item.slice(0, 300)];\n if (typeof item === \"number\" || typeof item === \"boolean\" || item == null) {\n return [key, item];\n }\n return [key, String(item).slice(0, 300)];\n }),\n );\n}\n\nfunction toSessionListItem(session: SessionHead): SessionHead {\n if (!session.model_usage) return session;\n const item = { ...session };\n delete item.model_usage;\n return item;\n}\n\nfunction getSessionHeadReference(session: SessionHead): SessionReference {\n return {\n agentName: getSessionAgentKey(session),\n sessionId: session.id,\n };\n}\n\nconst SESSION_DETAIL_STREAM_BATCH_CHARS = 64 * 1024;\n\nfunction createSessionDetailJsonResponse(\n data: Omit<SessionDetail, \"messages\">,\n messages: Iterable<string>,\n): Response {\n const encoder = new TextEncoder();\n const headerJson = JSON.stringify(data);\n const iterator = messages[Symbol.iterator]();\n let wroteHeader = false;\n let wroteMessage = false;\n\n return new Response(\n new ReadableStream<Uint8Array>({\n pull(controller) {\n if (!wroteHeader) {\n controller.enqueue(encoder.encode(`${headerJson.slice(0, -1)},\"messages\":[`));\n wroteHeader = true;\n return;\n }\n\n const batch: string[] = [];\n let batchLength = 0;\n let next = iterator.next();\n while (!next.done) {\n const prefix = wroteMessage ? \",\" : \"\";\n batch.push(prefix, next.value);\n batchLength += prefix.length + next.value.length;\n wroteMessage = true;\n if (batchLength >= SESSION_DETAIL_STREAM_BATCH_CHARS) break;\n next = iterator.next();\n }\n\n if (next.done) {\n batch.push(\"]}\");\n controller.enqueue(encoder.encode(batch.join(\"\")));\n controller.close();\n return;\n }\n\n controller.enqueue(encoder.encode(batch.join(\"\")));\n },\n cancel() {\n iterator.return?.();\n },\n }),\n { headers: { \"Content-Type\": \"application/json; charset=UTF-8\" } },\n );\n}\n\nexport function handleGetConfig(c: Context, defaults: SessionListDefaults) {\n const payload: AppConfig = {\n window: {\n from: defaults.from,\n to: defaults.to,\n days: defaults.days,\n },\n };\n return c.json(payload);\n}\n\nexport function handleGetScanStatus(c: Context, scanSource: ScanStatusSource) {\n return c.json(scanSource.getScanStatus());\n}\n\nexport function handleGetAgents(\n c: Context,\n scanSource: ScanResultSource,\n defaults: SessionListDefaults = {},\n) {\n const scanResult = scanSource.getSnapshot();\n const from = parseDateParam(c.req.query(\"from\"), defaults.from);\n const to = parseDateParam(c.req.query(\"to\"), defaults.to);\n const agents = getSnapshotAggregation(\n scanSource,\n scanResult.sessions,\n [\"agents\", from, to],\n () => {\n const counts = Object.fromEntries(\n Object.entries(scanResult.byAgent).map(([agentName, sessions]) => [\n agentName,\n filterSessionsByActivityWindow(sessions, from, to).length,\n ]),\n );\n return getAgentInfoMap(counts);\n },\n );\n return c.json(agents);\n}\n\nexport function handleGetProjects(\n c: Context,\n scanSource: ScanResultSource,\n defaults: SessionListDefaults = {},\n) {\n const scanResult = scanSource.getSnapshot();\n const from = parseDateParam(c.req.query(\"from\"), defaults.from);\n const to = parseDateParam(c.req.query(\"to\"), defaults.to);\n const projects = getSnapshotAggregation(\n scanSource,\n scanResult.sessions,\n [\"projects\", from, to],\n () => {\n const sessions = filterSessionsByActivityWindow(scanResult.sessions, from, to);\n return {\n projects: attachProjectMetrics(listCachedProjectGroups(sessions), sessions),\n };\n },\n );\n return c.json(projects);\n}\n\nexport function handleGetSessions(\n c: Context,\n scanSource: ScanResultSource,\n defaults: SessionListDefaults = {},\n) {\n const scanResult = scanSource.getSnapshot();\n const agent = c.req.query(\"agent\");\n const q = c.req.query(\"q\")?.toLowerCase();\n const cwd = c.req.query(\"cwd\");\n const projectIdentity = parseProjectIdentityFilter(\n c.req.query(\"projectKind\"),\n c.req.query(\"projectKey\"),\n );\n if (projectIdentity === null) {\n return c.json({ error: \"projectKind and projectKey must form a valid project identity\" }, 400);\n }\n const tag = c.req.query(\"tag\")?.toLowerCase();\n const from = parseDateParam(c.req.query(\"from\"), defaults.from);\n const to = parseDateParam(c.req.query(\"to\"), defaults.to);\n\n let sessions: SessionHead[] = [];\n\n // If agent filter is specified, use byAgent directly\n if (agent && scanResult.byAgent[agent]) {\n sessions = [...scanResult.byAgent[agent]!];\n } else {\n sessions = [...scanResult.sessions];\n }\n\n if (projectIdentity) {\n sessions = sessions.filter((session) =>\n matchesProjectIdentity(session.project_identity, projectIdentity),\n );\n } else if (cwd) {\n const projectScope = createProjectScopeMatcher(cwd);\n sessions = sessions.filter((s) => sessionMatchesProjectScope(s, projectScope));\n }\n sessions = filterSessionsByActivityWindow(sessions, from, to);\n if (tag) {\n sessions = sessions.filter((s) => s.smart_tags?.includes(tag as SmartTag));\n }\n\n const aliases = loadAliasView();\n if (q) {\n sessions = sessions.filter((session) => {\n const alias = aliases.get(getSessionHeadReference(session));\n return session.title.toLowerCase().includes(q) || alias?.toLowerCase().includes(q);\n });\n }\n return c.json({\n sessions: sessions.map((session) =>\n toSessionListItem(aliases.decorate(session, getSessionHeadReference(session))),\n ),\n });\n}\n\nexport function handleSearchSessions(\n c: Context,\n scanSource: ScanResultSource,\n defaults: SessionListDefaults = {},\n) {\n const query = c.req.query(\"q\")?.trim() ?? \"\";\n const scanResult = scanSource.getSnapshot();\n const projectIdentity = parseProjectIdentityFilter(\n c.req.query(\"projectKind\"),\n c.req.query(\"projectKey\"),\n );\n if (projectIdentity === null) {\n return c.json({ error: \"projectKind and projectKey must form a valid project identity\" }, 400);\n }\n const searchOptions = parseSearchOptions(c, defaults, projectIdentity);\n const aliases = loadAliasView();\n const results = executeSessionSearch(query, searchOptions, scanResult).map((result) => ({\n ...result,\n session: aliases.decorate(result.session, result.reference),\n }));\n const aliasResults = findAliasSearchResults(query, searchOptions, scanResult, aliases);\n const deduped = new Map<string, (typeof results)[number]>();\n for (const result of [...aliasResults, ...results]) {\n deduped.set(`${result.reference.agentName}\\0${result.reference.sessionId}`, result);\n }\n return c.json({ results: [...deduped.values()].slice(0, searchOptions.limit ?? 50) });\n}\n\nexport function handleGetFileActivity(c: Context, defaults: SessionListDefaults = {}) {\n const limitValue = Number(c.req.query(\"limit\"));\n const limit = Number.isFinite(limitValue) && limitValue > 0 ? Math.min(limitValue, 200) : 50;\n const projectIdentity = parseProjectIdentityFilter(\n c.req.query(\"projectKind\"),\n c.req.query(\"projectKey\"),\n );\n if (projectIdentity === null) {\n return c.json({ error: \"projectKind and projectKey must form a valid project identity\" }, 400);\n }\n\n const aliases = loadAliasView();\n return c.json({\n activity: listFileActivity({\n agent: optionalQueryValue(c.req.query(\"agent\")),\n sessionId: optionalQueryValue(c.req.query(\"sessionId\")),\n projectKind: projectIdentity?.kind,\n projectKey: projectIdentity?.key,\n project: optionalQueryValue(c.req.query(\"project\")),\n cwd: optionalQueryValue(c.req.query(\"cwd\")),\n path: optionalQueryValue(c.req.query(\"path\")),\n kind: parseFileActivityKind(optionalQueryValue(c.req.query(\"kind\"))),\n from: parseDateParam(c.req.query(\"from\"), defaults.from),\n to: parseDateParam(c.req.query(\"to\"), defaults.to),\n limit,\n }).map((activity) => decorateFileActivity(activity, aliases)),\n });\n}\n\nexport async function handleGetSessionData(c: Context, scanSource: ScanResultSource) {\n const startedAt = performance.now();\n const agentName = c.req.param(\"agent\");\n const sessionId = c.req.param(\"id\");\n\n if (!agentName) {\n return c.json({ error: \"Missing agent name\" }, 400);\n }\n\n if (!sessionId) {\n return c.json({ error: \"Missing session ID\" }, 400);\n }\n\n try {\n const result = materializeSessionDetailResponse(scanSource.getSnapshot(), {\n agentName,\n sessionId,\n });\n if (result.status === \"unknown-agent\") {\n return c.json({ error: `Unknown agent: ${agentName}` }, 404);\n }\n if (result.status === \"not-ready\") {\n appLogger.warn(\"api.session_data.cache_miss\", {\n agent: agentName,\n session_id: sessionId,\n duration_ms: Math.round(performance.now() - startedAt),\n });\n return c.json({ error: \"Session cache not ready\" }, 404);\n }\n\n appLogger.info(\"api.session_data\", {\n agent: agentName,\n session_id: sessionId,\n messages: result.status === \"found-json\" ? result.messageCount : result.data.messages.length,\n duration_ms: Math.round(performance.now() - startedAt),\n });\n const aliases = loadAliasView();\n if (result.status === \"found-json\") {\n return createSessionDetailJsonResponse(\n aliases.decorate(result.data, result.data.reference),\n result.messages,\n );\n }\n return c.json(aliases.decorate(result.data, result.data.reference));\n } catch (err) {\n const message = err instanceof Error ? err.message : \"Failed to load session\";\n appLogger.error(\"api.session_data.error\", {\n agent: agentName,\n session_id: sessionId,\n duration_ms: Math.round(performance.now() - startedAt),\n error: message,\n });\n return c.json({ error: message }, 500);\n }\n}\n\nexport async function handlePostClientLog(c: Context) {\n const payload = (await c.req.json().catch(() => null)) as ClientLogPayload | null;\n const rawEvent = payload?.event;\n\n if (typeof rawEvent !== \"string\" || !rawEvent.trim()) {\n return c.json({ ok: false }, 400);\n }\n\n const event = rawEvent\n .trim()\n .replace(/[^a-zA-Z0-9_.:-]/g, \"_\")\n .slice(0, 120);\n appLogger.info(`client.${event}`, sanitizeClientLogData(payload?.data));\n return c.json({ ok: true });\n}\n\nexport function handleGetBookmarks(c: Context) {\n return withStorageErrors(\n () => {\n const aliases = loadAliasView();\n return c.json({\n bookmarks: listBookmarks().map((bookmark) => decorateBookmark(bookmark, aliases)),\n storageAvailable: true,\n });\n },\n () => c.json({ bookmarks: [], storageAvailable: false }),\n );\n}\n\nexport async function handlePutBookmark(c: Context) {\n const payload = parseBookmarkPayload(await c.req.json().catch(() => null));\n if (!payload) {\n return c.json({ error: \"Invalid bookmark payload\" }, 400);\n }\n\n return withStorageErrors(\n () => c.json({ bookmark: upsertBookmark(payload), storageAvailable: true }),\n () => c.json({ error: \"Bookmark storage is unavailable\" }, 503),\n );\n}\n\nexport async function handleImportBookmarks(c: Context) {\n const payload = await c.req.json().catch(() => null);\n if (!Array.isArray(payload)) {\n return c.json({ error: \"Invalid bookmark payload\" }, 400);\n }\n\n const bookmarks = payload\n .map((entry) => parseBookmarkPayload(entry))\n .filter((entry): entry is NonNullable<typeof entry> => entry !== null);\n\n if (bookmarks.length !== payload.length) {\n return c.json({ error: \"Invalid bookmark payload\" }, 400);\n }\n\n return withStorageErrors(\n () => c.json({ bookmarks: importBookmarks(bookmarks), storageAvailable: true }),\n () => c.json({ error: \"Bookmark storage is unavailable\" }, 503),\n );\n}\n\nexport function handleDeleteBookmark(c: Context) {\n const agentKey = c.req.param(\"agent\");\n const sessionId = c.req.param(\"id\");\n if (!agentKey || !sessionId) {\n return c.json({ error: \"Missing bookmark identifier\" }, 400);\n }\n\n return withStorageErrors(\n () => {\n deleteBookmark({ agentName: agentKey, sessionId });\n return c.json({ ok: true, storageAvailable: true });\n },\n () => c.json({ error: \"Bookmark storage is unavailable\" }, 503),\n );\n}\n\nexport async function handlePutSessionAlias(c: Context) {\n const agentKey = c.req.param(\"agent\");\n const sessionId = c.req.param(\"id\");\n const payload = (await c.req.json().catch(() => null)) as SessionAliasPayload | null;\n const aliasValue = payload?.alias;\n if (!agentKey || !sessionId || typeof aliasValue !== \"string\") {\n return c.json({ error: \"Invalid session alias payload\" }, 400);\n }\n\n try {\n return withStorageErrors(\n () => {\n const alias = upsertSessionAlias({ agentName: agentKey, sessionId }, aliasValue);\n invalidateAliasView();\n return c.json({ alias });\n },\n () => c.json({ error: \"Session alias storage is unavailable\" }, 503),\n );\n } catch (error) {\n if (error instanceof SessionAliasValidationError) {\n return c.json({ error: \"Session alias must be non-empty and at most 160 characters\" }, 400);\n }\n throw error;\n }\n}\n\nexport function handleDeleteSessionAlias(c: Context) {\n const agentKey = c.req.param(\"agent\");\n const sessionId = c.req.param(\"id\");\n if (!agentKey || !sessionId) {\n return c.json({ error: \"Missing session alias identifier\" }, 400);\n }\n\n return withStorageErrors(\n () => {\n deleteSessionAlias({ agentName: agentKey, sessionId });\n invalidateAliasView();\n return c.json({ ok: true });\n },\n () => c.json({ error: \"Session alias storage is unavailable\" }, 503),\n );\n}\n\nexport function handleGetDashboard(\n c: Context,\n scanSource: ScanResultSource,\n defaults: SessionListDefaults = {},\n) {\n const scanResult = scanSource.getSnapshot();\n const projectIdentity = parseProjectIdentityFilter(\n c.req.query(\"projectKind\"),\n c.req.query(\"projectKey\"),\n );\n if (projectIdentity === null) {\n return c.json({ error: \"projectKind and projectKey must form a valid project identity\" }, 400);\n }\n const { from, to, days } = resolveTimeWindow({\n mode: \"dashboard\",\n query: {\n days: c.req.query(\"days\"),\n from: c.req.query(\"from\"),\n to: c.req.query(\"to\"),\n },\n defaults,\n });\n const scope: DashboardScope = {\n agent: optionalQueryValue(c.req.query(\"agent\"))?.toLowerCase(),\n projectKind: projectIdentity?.kind,\n projectKey: projectIdentity?.key,\n };\n\n const fixedTo = parseDateParam(c.req.query(\"to\"), defaults.to);\n const aggregate = getSnapshotAggregation(\n scanSource,\n scanResult.sessions,\n [\n \"dashboard\",\n scope.agent,\n scope.projectKind,\n scope.projectKey,\n from,\n fixedTo ?? startOfCalendarDay(to),\n ],\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 });\n },\n );\n\n const data: DashboardData = {\n ...aggregate,\n recentFileActivities: listFileActivity({\n agent: scope.agent,\n projectKind: scope.projectKind,\n projectKey: scope.projectKey,\n from,\n to,\n limit: 12,\n }),\n window: { from, to, days },\n };\n\n const aliases = loadAliasView();\n return c.json({\n ...data,\n recentSessions: data.recentSessions.map((item) => ({\n ...item,\n session: aliases.decorate(item.session, item.reference),\n })),\n recentFileActivities: data.recentFileActivities.map((activity) =>\n decorateFileActivity(activity, aliases),\n ),\n });\n}\n","import { randomBytes, timingSafeEqual } from \"node:crypto\";\nimport { readFileSync } from \"node:fs\";\nimport { isIP } from \"node:net\";\nimport type { Context, MiddlewareHandler } from \"hono\";\n\nexport const REMOTE_ACCESS_QUERY_PARAM = \"access_token\";\n\n/**\n * How a remote listener's traffic is protected. A token proves who is asking;\n * it says nothing about who else can read the answer, so confidentiality is\n * modelled separately from authentication.\n */\nexport type RemoteTransport =\n | { kind: \"loopback\" }\n /** CodeSesh terminates TLS itself. */\n | { kind: \"tls\"; cert: Buffer; key: Buffer }\n /** A reverse proxy in front of CodeSesh terminates TLS. */\n | { kind: \"trusted-proxy\" }\n /** The operator accepted plaintext on an untrusted network. */\n | { kind: \"plaintext\" };\n\nexport interface RemoteTransportRequest {\n hostname: string;\n tlsCertPath?: string;\n tlsKeyPath?: string;\n trustProxy?: boolean;\n}\n\nexport class RemoteTransportError extends Error {}\n\n/**\n * Resolves the transport from the CLI flags. Loopback stays plaintext without\n * ceremony: nothing leaves the machine.\n */\nexport function resolveRemoteTransport(request: RemoteTransportRequest): RemoteTransport {\n const hasCert = Boolean(request.tlsCertPath);\n const hasKey = Boolean(request.tlsKeyPath);\n if (hasCert !== hasKey) {\n throw new RemoteTransportError(\"TLS requires both --tls-cert and --tls-key.\");\n }\n if (hasCert && request.trustProxy) {\n throw new RemoteTransportError(\n \"Use either --tls-cert/--tls-key or --trust-proxy, not both: only one of them terminates TLS.\",\n );\n }\n\n if (hasCert) {\n try {\n return {\n kind: \"tls\",\n cert: readFileSync(request.tlsCertPath!),\n key: readFileSync(request.tlsKeyPath!),\n };\n } catch (error) {\n throw new RemoteTransportError(\n `Unable to read the TLS certificate or key: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n\n if (request.trustProxy) return { kind: \"trusted-proxy\" };\n return isLoopbackHostname(request.hostname) ? { kind: \"loopback\" } : { kind: \"plaintext\" };\n}\n\n/** Whether the transport keeps request and response bodies off the wire in the clear. */\nexport function isConfidentialTransport(transport: RemoteTransport): boolean {\n return transport.kind !== \"plaintext\";\n}\n\nconst FORWARDED_PROTO_HEADER = \"X-Forwarded-Proto\";\n\n/**\n * Behind a trusted proxy, a request arriving without the proxy's own\n * `X-Forwarded-Proto: https` did not come through it. Trusting the header is\n * only sound because the deployment is expected to make CodeSesh unreachable\n * except via that proxy — which is what --trust-proxy asserts.\n */\nexport function requireProxyTls(): MiddlewareHandler {\n return async (c, next) => {\n const proto = c.req.header(FORWARDED_PROTO_HEADER)?.split(\",\")[0]?.trim().toLowerCase();\n if (proto !== \"https\") {\n return c.json({ error: \"Requests must arrive over TLS through the trusted proxy\" }, 403);\n }\n await next();\n };\n}\n\nexport function createRemoteAccessToken(): string {\n return randomBytes(32).toString(\"base64url\");\n}\n\nexport function isLoopbackHostname(hostname: string): boolean {\n const normalized = hostname.toLowerCase().replace(/^\\[(.*)\\]$/, \"$1\");\n if (normalized === \"localhost\" || normalized === \"::1\") return true;\n return isIP(normalized) === 4 && normalized.startsWith(\"127.\");\n}\n\nfunction tokenMatches(actual: string | undefined, expected: string): boolean {\n if (!actual) return false;\n const actualBuffer = Buffer.from(actual);\n const expectedBuffer = Buffer.from(expected);\n return (\n actualBuffer.length === expectedBuffer.length && timingSafeEqual(actualBuffer, expectedBuffer)\n );\n}\n\nfunction bearerToken(c: Context): string | undefined {\n const authorization = c.req.header(\"Authorization\");\n if (!authorization?.startsWith(\"Bearer \")) return undefined;\n return authorization.slice(\"Bearer \".length);\n}\n\nfunction requestToken(c: Context): string | undefined {\n const bearer = bearerToken(c);\n if (bearer) return bearer;\n if (c.req.method !== \"GET\") return undefined;\n return c.req.query(REMOTE_ACCESS_QUERY_PARAM);\n}\n\nexport function remoteAccessAuth(expectedToken: string): MiddlewareHandler {\n return async (c, next) => {\n if (!tokenMatches(requestToken(c), expectedToken)) {\n return c.json({ error: \"Remote access authentication required\" }, 401);\n }\n await next();\n };\n}\n","import { existsSync } from \"node:fs\";\nimport { fileURLToPath } from \"node:url\";\nimport {\n createRegisteredAgents,\n scanSessions,\n type LiveSnapshot,\n type ScanOptions,\n} from \"@codesesh/core\";\nimport type {\n AgentScanStatus,\n BackfillStatus,\n ScanStatusEvent,\n SessionsUpdatedEvent,\n} from \"@codesesh/core/contract\";\nimport { mergeSessionsUpdatedEvents } from \"@codesesh/core/contract\";\nimport { AgentSyncEngine } from \"./agent-sync-engine.js\";\nimport { appLogger } from \"./logging.js\";\nimport { SessionWatcher } from \"./session-watcher.js\";\nimport { ThreadWorkerRunner, type WorkerRunner } from \"./worker-runner.js\";\n\nexport type { AgentScanStatus, BackfillStatus, ScanStatusEvent, SessionsUpdatedEvent };\n\ntype StoreListener = (event: SessionsUpdatedEvent) => void;\ntype ScanStatusListener = (event: ScanStatusEvent) => void;\n\nexport interface LiveScanStoreOptions {\n watchEnabled?: boolean;\n scanOptions?: ScanOptions;\n startupScanOptions?: Pick<ScanOptions, \"from\" | \"to\">;\n deferInitialRefresh?: boolean;\n workerRunner?: WorkerRunner;\n}\n\nconst NEW_SESSION_EVENT_WINDOW_MS = 250;\n\nexport class LiveScanStore {\n private readonly watchEnabled: boolean;\n private readonly scanOptions: ScanOptions;\n private readonly startupScanOptions: Pick<ScanOptions, \"from\" | \"to\">;\n private readonly deferInitialRefresh: boolean;\n private readonly syncEngine: AgentSyncEngine;\n private listeners = new Set<StoreListener>();\n private watcher: SessionWatcher | null = null;\n private pendingEvent: SessionsUpdatedEvent | null = null;\n private pendingEventTimer: NodeJS.Timeout | null = null;\n private shutdownPromise: Promise<void> | null = null;\n private shuttingDown = false;\n\n constructor(options: LiveScanStoreOptions = {}) {\n this.watchEnabled = options.watchEnabled ?? true;\n this.scanOptions = options.scanOptions ?? {};\n this.startupScanOptions = options.startupScanOptions ?? {};\n this.deferInitialRefresh = options.deferInitialRefresh === true;\n const workerRunner =\n options.workerRunner ??\n new ThreadWorkerRunner(new URL(\"./scan-refresh-worker.js\", import.meta.url));\n this.syncEngine = new AgentSyncEngine({\n startupScanOptions: this.startupScanOptions,\n workerRunner,\n });\n this.syncEngine.subscribeSessionsChanged((change) => {\n if (change.event) this.emit(change.event);\n });\n }\n\n async initialize(): Promise<void> {\n const startedAt = performance.now();\n appLogger.info(\"scan.initial.start\", {\n watch_enabled: this.watchEnabled,\n agents: this.scanOptions.agents,\n use_cache: this.scanOptions.useCache ?? true,\n startup_from: this.startupScanOptions.from,\n startup_to: this.startupScanOptions.to,\n deferred: this.deferInitialRefresh || undefined,\n });\n const initialResult = await scanSessions({\n ...this.scanOptions,\n useCache: this.scanOptions.useCache ?? true,\n smartRefresh: false,\n cacheOnly: this.deferInitialRefresh,\n writeCache: this.deferInitialRefresh ? false : this.scanOptions.writeCache,\n smartTagWorkerUrl: this.getSmartTagWorkerUrl() ?? undefined,\n includeSmartTags: this.deferInitialRefresh ? false : undefined,\n });\n this.syncEngine.initialize(initialResult, {\n cacheTimestamps: initialResult.cacheTimestamps,\n registeredAgents: createRegisteredAgents(),\n allowedAgents: this.getAllowedAgents(),\n });\n const snapshot = this.getSnapshot();\n const indexStartedAt = performance.now();\n if (!this.deferInitialRefresh) {\n // The snapshot is already served from memory, so an index-write failure\n // degrades search freshness rather than startup.\n await this.syncEngine.syncInitialIndex().catch((error: unknown) => {\n appLogger.error(\"scan.initial.index_failed\", { error });\n });\n }\n const indexDuration = performance.now() - indexStartedAt;\n appLogger.info(\"scan.initial.done\", {\n duration_ms: Math.round(performance.now() - startedAt),\n index_ms: this.deferInitialRefresh ? undefined : Math.round(indexDuration),\n deferred: this.deferInitialRefresh || undefined,\n sessions: snapshot.sessions.length,\n agents: Object.fromEntries(\n Object.entries(snapshot.byAgent).map(([key, value]) => [key, value.length]),\n ),\n agent_timings: initialResult.timings\n ? Object.fromEntries(\n Object.entries(initialResult.timings).map(([name, timing]) => [\n name,\n {\n total_ms: Math.round(timing.total),\n cache_load_ms: timing.cacheLoad != null ? Math.round(timing.cacheLoad) : undefined,\n check_changes_ms:\n timing.checkChanges != null ? Math.round(timing.checkChanges) : undefined,\n scan_ms: timing.scan != null ? Math.round(timing.scan) : undefined,\n identity_ms: timing.identity != null ? Math.round(timing.identity) : undefined,\n tags_ms: timing.tags != null ? Math.round(timing.tags) : undefined,\n },\n ]),\n )\n : undefined,\n });\n if (!this.watchEnabled) return;\n this.watcher = new SessionWatcher();\n this.watcher.onAgentsChanged((agentNames) => this.syncEngine.handleAgentsChanged(agentNames));\n this.watcher.start(snapshot.agents);\n }\n\n startBackgroundRefresh(): void {\n this.syncEngine.startBackgroundRefresh();\n }\n\n getSnapshot(): LiveSnapshot {\n return this.syncEngine.snapshot();\n }\n\n getScanStatus(): ScanStatusEvent {\n return this.syncEngine.status();\n }\n\n subscribe(listener: StoreListener): () => void {\n this.listeners.add(listener);\n return () => this.listeners.delete(listener);\n }\n\n subscribeScanStatus(listener: ScanStatusListener): () => void {\n return this.syncEngine.subscribeStatusChanged(listener);\n }\n\n shutdown(): Promise<void> {\n this.shutdownPromise ??= this.performShutdown();\n return this.shutdownPromise;\n }\n\n private async performShutdown(): Promise<void> {\n this.shuttingDown = true;\n if (this.pendingEventTimer) {\n clearTimeout(this.pendingEventTimer);\n this.pendingEventTimer = null;\n }\n await this.syncEngine.shutdown();\n this.pendingEvent = null;\n if (this.watcher) {\n await this.watcher.dispose();\n this.watcher = null;\n }\n }\n\n private emit(event: SessionsUpdatedEvent): void {\n if (this.shuttingDown) return;\n if (this.pendingEvent || event.newSessions > 0) {\n this.queueEvent(event);\n return;\n }\n this.emitNow(event);\n }\n\n private emitNow(event: SessionsUpdatedEvent): void {\n for (const listener of this.listeners) listener(event);\n }\n\n private queueEvent(event: SessionsUpdatedEvent): void {\n this.pendingEvent = this.pendingEvent\n ? mergeSessionsUpdatedEvents(this.pendingEvent, event)\n : event;\n if (this.pendingEventTimer) return;\n this.pendingEventTimer = setTimeout(() => {\n const pending = this.pendingEvent;\n this.pendingEvent = null;\n this.pendingEventTimer = null;\n if (pending) this.emitNow(pending);\n }, NEW_SESSION_EVENT_WINDOW_MS);\n }\n\n private getSmartTagWorkerUrl(): URL | null {\n const workerUrl = new URL(\"./smart-tag-worker.js\", import.meta.url);\n if (workerUrl.protocol === \"file:\" && !existsSync(fileURLToPath(workerUrl))) return null;\n return workerUrl;\n }\n\n private getAllowedAgents(): Set<string> | null {\n if (!this.scanOptions.agents?.length) return null;\n return new Set(this.scanOptions.agents.map((agent) => agent.toLowerCase()));\n }\n}\n","import { appLogger } from \"./logging.js\";\n\nexport type AgentOperationKind = \"backfill\" | \"refresh\";\nexport type AgentOperationResult = \"committed\" | \"failed\" | \"skipped\" | \"unchanged\";\n\ninterface AgentScheduleState {\n timer: NodeJS.Timeout | null;\n timerDeadline: number;\n isRefreshRunning: boolean;\n hasPendingRefresh: boolean;\n lastRefreshDurationMs: number;\n pendingSignalCount: number;\n}\n\ninterface AgentOperationLifecycle {\n agentName: string;\n kind: AgentOperationKind;\n generation: number;\n startedAt: number;\n}\n\nexport interface AgentOperationSchedulerSnapshot {\n activeOperations: number;\n activeRefreshes: number;\n}\n\nconst PENDING_REFRESH_DELAY_MS = 100;\nconst MAX_ADAPTIVE_REFRESH_DELAY_MS = 30_000;\nconst ADAPTIVE_REFRESH_DELAY_MULTIPLIER = 4;\n\nexport class AgentOperationScheduler {\n private readonly states = new Map<string, AgentScheduleState>();\n private readonly operationGenerations = new Map<string, number>();\n private readonly operationTails = new Map<string, Promise<void>>();\n private isStopped = false;\n\n constructor(private readonly runRefresh: (agentName: string) => Promise<AgentOperationResult>) {}\n\n notify(agentName: string, delayMs: number): void {\n if (this.isStopped) return;\n this.state(agentName).pendingSignalCount += 1;\n this.schedule(agentName, delayMs);\n }\n\n schedule(agentName: string, delayMs: number): void {\n if (this.isStopped) return;\n const state = this.state(agentName);\n const adaptiveDelayMs = Math.min(\n state.lastRefreshDurationMs * ADAPTIVE_REFRESH_DELAY_MULTIPLIER,\n MAX_ADAPTIVE_REFRESH_DELAY_MS,\n );\n const effectiveDelayMs = Math.max(delayMs, adaptiveDelayMs);\n const deadline = Date.now() + effectiveDelayMs;\n if (state.timer) {\n if (deadline >= state.timerDeadline) return;\n clearTimeout(state.timer);\n }\n\n appLogger.debug(\"scan.refresh.schedule\", { agent: agentName, delay_ms: effectiveDelayMs });\n state.timerDeadline = deadline;\n state.timer = setTimeout(() => {\n state.timer = null;\n state.timerDeadline = 0;\n void this.refresh(agentName);\n }, effectiveDelayMs);\n }\n\n async refresh(agentName: string): Promise<void> {\n if (this.isStopped) return;\n const state = this.state(agentName);\n if (state.isRefreshRunning) {\n appLogger.debug(\"scan.refresh.pending\", { agent: agentName });\n state.hasPendingRefresh = true;\n return;\n }\n\n state.isRefreshRunning = true;\n try {\n await this.run(agentName, \"refresh\", () => this.runRefresh(agentName));\n } finally {\n state.isRefreshRunning = false;\n if (state.hasPendingRefresh && !this.isStopped) {\n state.hasPendingRefresh = false;\n this.schedule(agentName, PENDING_REFRESH_DELAY_MS);\n }\n }\n }\n\n run(\n agentName: string,\n kind: AgentOperationKind,\n operation: () => Promise<AgentOperationResult>,\n ): Promise<AgentOperationResult> {\n const previous = this.operationTails.get(agentName) ?? Promise.resolve();\n const run = previous.then(async () => {\n if (this.isStopped) return \"skipped\";\n const lifecycle = this.beginOperation(agentName, kind);\n try {\n const result = await operation();\n this.completeOperation(lifecycle, result);\n return result;\n } catch (error) {\n this.completeOperation(lifecycle, \"failed\");\n throw error;\n }\n });\n const tail = run.then(\n () => undefined,\n () => undefined,\n );\n this.operationTails.set(agentName, tail);\n void tail.finally(() => {\n if (this.operationTails.get(agentName) === tail) this.operationTails.delete(agentName);\n });\n return run;\n }\n\n takePendingSignalCount(agentName: string): number {\n const state = this.state(agentName);\n const count = state.pendingSignalCount;\n state.pendingSignalCount = 0;\n return count;\n }\n\n recordRefreshDuration(agentName: string, durationMs: number): void {\n this.state(agentName).lastRefreshDurationMs = durationMs;\n }\n\n snapshot(): AgentOperationSchedulerSnapshot {\n return {\n activeOperations: this.operationTails.size,\n activeRefreshes: [...this.states.values()].filter((state) => state.isRefreshRunning).length,\n };\n }\n\n stop(): void {\n this.isStopped = true;\n for (const state of this.states.values()) {\n if (state.timer) clearTimeout(state.timer);\n state.timer = null;\n state.timerDeadline = 0;\n state.hasPendingRefresh = false;\n state.pendingSignalCount = 0;\n }\n }\n\n async waitForIdle(): Promise<void> {\n await Promise.allSettled(this.operationTails.values());\n }\n\n private state(agentName: string): AgentScheduleState {\n const existing = this.states.get(agentName);\n if (existing) return existing;\n const state: AgentScheduleState = {\n timer: null,\n timerDeadline: 0,\n isRefreshRunning: false,\n hasPendingRefresh: false,\n lastRefreshDurationMs: 0,\n pendingSignalCount: 0,\n };\n this.states.set(agentName, state);\n return state;\n }\n\n private beginOperation(agentName: string, kind: AgentOperationKind): AgentOperationLifecycle {\n const generation = (this.operationGenerations.get(agentName) ?? 0) + 1;\n const startedAt = Date.now();\n this.operationGenerations.set(agentName, generation);\n appLogger.info(\"scan.agent_operation.started\", {\n agent: agentName,\n operation: kind,\n generation,\n started_at: startedAt,\n });\n return { agentName, kind, generation, startedAt };\n }\n\n private completeOperation(\n lifecycle: AgentOperationLifecycle,\n result: AgentOperationResult,\n ): void {\n const completedAt = Date.now();\n appLogger.info(\"scan.agent_operation.completed\", {\n agent: lifecycle.agentName,\n operation: lifecycle.kind,\n generation: lifecycle.generation,\n started_at: lifecycle.startedAt,\n completed_at: completedAt,\n duration_ms: completedAt - lifecycle.startedAt,\n result,\n });\n }\n}\n","import {\n computeSessionDiff,\n mergeSortedSessions,\n sessionSignature,\n sortSessions,\n type BaseAgent,\n type LiveSnapshot,\n type SessionHead,\n} from \"@codesesh/core\";\nimport type { SessionsUpdatedEvent } from \"@codesesh/core/contract\";\n\nexport interface LiveSessionIndexOptions {\n registeredAgents?: BaseAgent[];\n allowedAgents?: ReadonlySet<string> | null;\n}\n\nexport class LiveSessionIndex {\n private agents: BaseAgent[] = [];\n private agentsByName = new Map<string, BaseAgent>();\n private byAgent: Record<string, SessionHead[]> = {};\n private sessions: SessionHead[] = [];\n private signatureCaches = new Map<string, Map<string, string>>();\n\n initialize(snapshot: LiveSnapshot, options: LiveSessionIndexOptions = {}): void {\n const agentMap = new Map<string, BaseAgent>();\n for (const agent of snapshot.agents) agentMap.set(agent.name, agent);\n for (const agent of options.registeredAgents ?? []) {\n if (!agentMap.has(agent.name)) agentMap.set(agent.name, agent);\n }\n\n this.agents = [...agentMap.values()].filter(\n (agent) => !options.allowedAgents || options.allowedAgents.has(agent.name.toLowerCase()),\n );\n this.agentsByName = new Map(this.agents.map((agent) => [agent.name, agent]));\n this.byAgent = Object.fromEntries(\n this.agents.map((agent) => [agent.name, sortSessions(snapshot.byAgent[agent.name] ?? [])]),\n );\n this.sessions = mergeSortedSessions(Object.values(this.byAgent));\n this.signatureCaches.clear();\n }\n\n snapshot(): LiveSnapshot {\n return {\n agents: this.agents,\n byAgent: this.byAgent,\n sessions: this.sessions,\n };\n }\n\n findAgent(agentName: string): BaseAgent | undefined {\n return this.agentsByName.get(agentName);\n }\n\n commitAgentSessions(\n agentName: string,\n nextSessions: SessionHead[],\n candidateChangedIds: string[] = [],\n ): SessionsUpdatedEvent | null {\n const previousSessions = this.byAgent[agentName] ?? [];\n const signatureCache = this.signatureCache(agentName);\n const { changes, removedSessionIds, counts } = computeSessionDiff(\n previousSessions,\n nextSessions,\n candidateChangedIds,\n sessionSignature,\n signatureCache,\n );\n for (const removedId of removedSessionIds) signatureCache.delete(removedId);\n\n this.byAgent[agentName] = sortSessions(nextSessions);\n this.sessions = mergeSortedSessions(Object.values(this.byAgent));\n if (counts.new === 0 && counts.updated === 0 && counts.removed === 0) return null;\n\n return {\n type: \"sessions-updated\",\n changedAgents: [agentName],\n newSessions: counts.new,\n updatedSessions: counts.updated,\n removedSessions: counts.removed,\n totalSessions: this.sessions.length,\n timestamp: Date.now(),\n changedSessionHeads: changes.map(({ session }) => ({\n reference: { agentName, sessionId: session.id },\n session,\n })),\n removedSessionRefs: removedSessionIds.map((sessionId) => ({ agentName, sessionId })),\n };\n }\n\n private signatureCache(agentName: string): Map<string, string> {\n const existing = this.signatureCaches.get(agentName);\n if (existing) return existing;\n const cache = new Map<string, string>();\n this.signatureCaches.set(agentName, cache);\n return cache;\n }\n}\n","import { existsSync } from \"node:fs\";\nimport { fileURLToPath } from \"node:url\";\nimport { Worker } from \"node:worker_threads\";\nimport { appLogger, logSearchIndexSync } from \"./logging.js\";\nimport { PendingSearchIndexJobs, type SearchIndexJobBatch } from \"./pending-search-index-jobs.js\";\nimport type { SearchIndexWorkerJob, SearchIndexWorkerMessage } from \"./search-index-worker.js\";\n\nconst SHUTDOWN_ERROR_MESSAGE = \"Live scan store shut down\";\n\nexport interface SearchIndexJobRunnerSnapshot {\n activeBatchId?: number;\n pendingBatches: number;\n pendingJobs: number;\n pendingChanges: number;\n}\n\nexport class SearchIndexJobRunner {\n private worker: Worker | null = null;\n private activeBatch: SearchIndexJobBatch | null = null;\n private nextBatchId = 1;\n private pendingJobs = new PendingSearchIndexJobs();\n private isShuttingDown = false;\n\n enqueue(context: string, jobs: SearchIndexWorkerJob[]): Promise<void> {\n if (jobs.length === 0) return Promise.resolve();\n if (this.isShuttingDown) return Promise.reject(new Error(SHUTDOWN_ERROR_MESSAGE));\n\n const batchId = this.nextBatchId++;\n const completion = this.pendingJobs.enqueue(batchId, context, jobs);\n if (this.worker) {\n const snapshot = this.snapshot();\n appLogger.debug(\"search_index.worker_queued\", {\n batch_id: batchId,\n context,\n jobs: jobs.length,\n pending_batches: snapshot.pendingBatches,\n pending_jobs: snapshot.pendingJobs,\n pending_changes: snapshot.pendingChanges,\n });\n } else {\n this.startNextBatch();\n }\n return completion;\n }\n\n snapshot(): SearchIndexJobRunnerSnapshot {\n return {\n activeBatchId: this.activeBatch?.id,\n pendingBatches: this.pendingJobs.batchCount,\n pendingJobs: this.pendingJobs.jobCount,\n pendingChanges: this.pendingJobs.changeCount,\n };\n }\n\n async shutdown(): Promise<void> {\n this.isShuttingDown = true;\n const activeBatch = this.activeBatch;\n const worker = this.worker;\n this.activeBatch = null;\n this.worker = null;\n\n const shutdownError = new Error(SHUTDOWN_ERROR_MESSAGE);\n if (activeBatch) this.settle(activeBatch, shutdownError);\n this.pendingJobs.rejectAll(shutdownError);\n if (worker) await worker.terminate();\n }\n\n private startNextBatch(): void {\n if (this.isShuttingDown || this.worker) return;\n const batch = this.pendingJobs.take();\n if (!batch) return;\n\n appLogger.info(\"search_index.worker_dequeued\", {\n batch_id: batch.id,\n context: batch.context,\n pending_batches: this.pendingJobs.batchCount,\n });\n this.startBatch(batch);\n }\n\n private startBatch(batch: SearchIndexJobBatch): void {\n if (this.isShuttingDown) {\n this.settle(batch, new Error(SHUTDOWN_ERROR_MESSAGE));\n return;\n }\n\n const workerUrl = this.workerUrl();\n if (!workerUrl) {\n appLogger.warn(\"search_index.worker_missing\", { context: batch.context });\n this.settle(batch);\n return;\n }\n appLogger.info(\"search_index.worker_started\", {\n batch_id: batch.id,\n context: batch.context,\n jobs: batch.jobs.length,\n });\n\n const worker = new Worker(workerUrl, {\n workerData: {\n context: batch.context,\n jobs: batch.jobs,\n agentNames: [],\n sessionsByAgent: {},\n metaByAgent: {},\n },\n });\n worker.unref();\n this.worker = worker;\n this.activeBatch = batch;\n\n worker.on(\"message\", (message: SearchIndexWorkerMessage) => {\n if (message.type === \"sync-result\") {\n logSearchIndexSync(message.context, message.result);\n return;\n }\n if (message.type === \"persist-failed\") {\n appLogger.error(\"search_index.persist_failed\", {\n batch_id: batch.id,\n context: message.context,\n stage: message.stage,\n agent: message.agentName,\n sessions: message.sessions,\n });\n this.settle(\n batch,\n new Error(\n `Search index worker failed to persist ${message.stage} for ${message.agentName}`,\n ),\n );\n return;\n }\n if (message.type !== \"done\") return;\n\n appLogger.info(`${message.context}.done`, {\n duration_ms: Math.round(message.durationMs),\n sessions: message.sessions,\n });\n this.settle(batch);\n });\n worker.on(\"error\", (error) => {\n appLogger.error(\"search_index.worker_error\", { context: batch.context, error });\n this.settle(batch, error);\n });\n worker.on(\"exit\", (code) => this.finishWorker(worker, batch, code));\n }\n\n private finishWorker(worker: Worker, batch: SearchIndexJobBatch, code: number): void {\n appLogger.info(\"search_index.worker_exited\", {\n batch_id: batch.id,\n context: batch.context,\n code,\n shutting_down: this.isShuttingDown || undefined,\n });\n if (this.worker === worker) this.worker = null;\n if (this.activeBatch === batch) this.activeBatch = null;\n\n const error =\n code === 0\n ? new Error(\"Search index worker exited before completing its batch\")\n : new Error(`Search index worker exited with code ${code}`);\n if (code !== 0) appLogger.warn(\"search_index.worker_exit\", { context: batch.context, code });\n this.settle(batch, error);\n this.startNextBatch();\n }\n\n private settle(batch: SearchIndexJobBatch, error?: Error): void {\n if (!this.pendingJobs.settle(batch, error)) return;\n appLogger.info(\"search_index.worker_settled\", {\n batch_id: batch.id,\n context: batch.context,\n result: error ? \"rejected\" : \"resolved\",\n });\n }\n\n private workerUrl(): URL | null {\n const workerUrl = new URL(\"./search-index-worker.js\", import.meta.url);\n if (workerUrl.protocol === \"file:\" && !existsSync(fileURLToPath(workerUrl))) return null;\n return workerUrl;\n }\n}\n","import type { SearchIndexSyncOptions, SessionCacheMeta, SessionHeadChange } from \"@codesesh/core\";\nimport type { SearchIndexWorkerJob } from \"./search-index-worker.js\";\n\ntype FullSearchIndexJob = Extract<SearchIndexWorkerJob, { kind: \"full\" }>;\ntype ChangesSearchIndexJob = Extract<SearchIndexWorkerJob, { kind: \"changes\" }>;\n\ninterface JobWaiter {\n resolve: () => void;\n reject: (error: Error) => void;\n}\n\ninterface PendingChanges {\n context: string;\n agentName: string;\n changesBySessionId: Map<string, SessionHeadChange>;\n removedSessionIds: Set<string>;\n meta: Record<string, SessionCacheMeta>;\n searchIndexOptions?: SearchIndexSyncOptions;\n}\n\ninterface PendingAgentJobs {\n full?: FullSearchIndexJob;\n changes?: PendingChanges;\n}\n\nexport interface SearchIndexJobBatch {\n readonly id: number;\n readonly context: string;\n readonly jobs: SearchIndexWorkerJob[];\n}\n\nclass PendingSearchIndexJobBatch implements SearchIndexJobBatch {\n context: string;\n private readonly jobsByAgent = new Map<string, PendingAgentJobs>();\n private readonly waiters: JobWaiter[] = [];\n private settled = false;\n\n constructor(\n readonly id: number,\n context: string,\n jobs: SearchIndexWorkerJob[],\n waiter: JobWaiter,\n ) {\n this.context = context;\n this.merge(context, jobs, waiter);\n }\n\n get jobs(): SearchIndexWorkerJob[] {\n const jobs: SearchIndexWorkerJob[] = [];\n for (const pending of this.jobsByAgent.values()) {\n if (pending.full) jobs.push(pending.full);\n if (pending.changes) jobs.push(changesJobFromPending(pending.changes));\n }\n return jobs;\n }\n\n get changeCount(): number {\n let count = 0;\n for (const pending of this.jobsByAgent.values()) {\n if (!pending.changes) continue;\n count += pending.changes.changesBySessionId.size + pending.changes.removedSessionIds.size;\n }\n return count;\n }\n\n merge(context: string, jobs: SearchIndexWorkerJob[], waiter: JobWaiter): void {\n this.context = context;\n this.waiters.push(waiter);\n for (const job of jobs) this.mergeJob(job);\n }\n\n settle(error?: Error): boolean {\n if (this.settled) return false;\n this.settled = true;\n for (const waiter of this.waiters) {\n if (error) waiter.reject(error);\n else waiter.resolve();\n }\n this.waiters.length = 0;\n return true;\n }\n\n private mergeJob(job: SearchIndexWorkerJob): void {\n const pending = this.jobsByAgent.get(job.agentName) ?? {};\n this.jobsByAgent.set(job.agentName, pending);\n\n if (job.kind === \"full\") {\n pending.full = job;\n pending.changes = undefined;\n return;\n }\n\n pending.changes ??= createPendingChanges(job);\n mergeChanges(pending.changes, job);\n }\n}\n\nexport class PendingSearchIndexJobs {\n private pendingBatch: PendingSearchIndexJobBatch | null = null;\n\n get batchCount(): number {\n return this.pendingBatch ? 1 : 0;\n }\n\n get jobCount(): number {\n return this.pendingBatch?.jobs.length ?? 0;\n }\n\n get changeCount(): number {\n return this.pendingBatch?.changeCount ?? 0;\n }\n\n enqueue(id: number, context: string, jobs: SearchIndexWorkerJob[]): Promise<void> {\n if (jobs.length === 0) return Promise.resolve();\n\n return new Promise((resolve, reject) => {\n const waiter = { resolve, reject };\n if (this.pendingBatch) {\n this.pendingBatch.merge(context, jobs, waiter);\n } else {\n this.pendingBatch = new PendingSearchIndexJobBatch(id, context, jobs, waiter);\n }\n });\n }\n\n take(): SearchIndexJobBatch | null {\n const batch = this.pendingBatch;\n this.pendingBatch = null;\n return batch;\n }\n\n settle(batch: SearchIndexJobBatch, error?: Error): boolean {\n return batch instanceof PendingSearchIndexJobBatch && batch.settle(error);\n }\n\n rejectAll(error: Error): void {\n const batch = this.take();\n if (batch) this.settle(batch, error);\n }\n}\n\nfunction createPendingChanges(job: ChangesSearchIndexJob): PendingChanges {\n return {\n context: job.context,\n agentName: job.agentName,\n changesBySessionId: new Map(),\n removedSessionIds: new Set(),\n meta: {},\n searchIndexOptions: job.searchIndexOptions,\n };\n}\n\nfunction mergeChanges(pending: PendingChanges, job: ChangesSearchIndexJob): void {\n pending.context = job.context;\n pending.searchIndexOptions = mergeSearchIndexOptions(\n pending.searchIndexOptions,\n job.searchIndexOptions,\n );\n\n for (const sessionId of job.removedSessionIds) {\n pending.changesBySessionId.delete(sessionId);\n pending.removedSessionIds.add(sessionId);\n delete pending.meta[sessionId];\n }\n\n for (const change of job.changes) {\n const sessionId = change.session.id;\n pending.removedSessionIds.delete(sessionId);\n pending.changesBySessionId.set(sessionId, change);\n if (Object.hasOwn(job.meta, sessionId)) pending.meta[sessionId] = job.meta[sessionId]!;\n else delete pending.meta[sessionId];\n }\n\n for (const [sessionId, meta] of Object.entries(job.meta)) {\n if (!pending.removedSessionIds.has(sessionId)) pending.meta[sessionId] = meta;\n }\n}\n\nfunction mergeSearchIndexOptions(\n current: SearchIndexSyncOptions | undefined,\n incoming: SearchIndexSyncOptions | undefined,\n): SearchIndexSyncOptions | undefined {\n if (!current) return incoming;\n if (!incoming) return current;\n return { ...current, ...incoming };\n}\n\nfunction changesJobFromPending(pending: PendingChanges): ChangesSearchIndexJob {\n return {\n kind: \"changes\",\n context: pending.context,\n agentName: pending.agentName,\n changes: [...pending.changesBySessionId.values()],\n removedSessionIds: [...pending.removedSessionIds],\n meta: pending.meta,\n ...(pending.searchIndexOptions ? { searchIndexOptions: pending.searchIndexOptions } : {}),\n };\n}\n","import type { AgentScanProgress } from \"@codesesh/core\";\nimport type { BackfillStatus, ScanStatusEvent } from \"@codesesh/core/contract\";\n\ntype ScanStatus = Omit<ScanStatusEvent, \"type\">;\n\nexport class ScanStatusModel {\n private status: ScanStatus = {\n active: false,\n phase: \"idle\",\n pendingAgents: [],\n scanningAgents: [],\n completedAgents: [],\n agentStatuses: {},\n totalAgents: 0,\n updatedAt: Date.now(),\n backfill: { active: false, pendingAgents: [], completedAgents: [], failedAgents: [] },\n };\n\n snapshot(): ScanStatusEvent {\n const backfill = {\n ...this.status.backfill,\n pendingAgents: [...this.status.backfill.pendingAgents],\n completedAgents: [...this.status.backfill.completedAgents],\n failedAgents: [...this.status.backfill.failedAgents],\n };\n if (this.status.backfill.progress) {\n backfill.progress = { ...this.status.backfill.progress };\n } else {\n delete backfill.progress;\n }\n return {\n type: \"scan-status\",\n ...this.status,\n pendingAgents: [...this.status.pendingAgents],\n scanningAgents: [...this.status.scanningAgents],\n completedAgents: [...this.status.completedAgents],\n agentStatuses: Object.fromEntries(\n Object.entries(this.status.agentStatuses).map(([agentName, status]) => [\n agentName,\n { ...status },\n ]),\n ),\n backfill,\n };\n }\n\n startBatch(\n agentNames: string[],\n phase: ScanStatusEvent[\"phase\"],\n sessionCounts: Record<string, number>,\n ): ScanStatusEvent {\n const uniqueAgentNames = [...new Set(agentNames)];\n const now = Date.now();\n const agentStatuses = Object.fromEntries(\n uniqueAgentNames.map((agentName) => [\n agentName,\n {\n agentName,\n status: \"pending\" as const,\n processed: 0,\n sessions: sessionCounts[agentName] ?? 0,\n updatedAt: now,\n },\n ]),\n );\n return this.set({\n ...this.status,\n active: uniqueAgentNames.length > 0,\n phase: uniqueAgentNames.length > 0 ? phase : \"idle\",\n pendingAgents: uniqueAgentNames,\n scanningAgents: [],\n completedAgents: [],\n agentStatuses,\n totalAgents: uniqueAgentNames.length,\n startedAt: uniqueAgentNames.length > 0 ? now : undefined,\n updatedAt: now,\n completedAt: uniqueAgentNames.length > 0 ? undefined : now,\n });\n }\n\n setPhase(phase: ScanStatusEvent[\"phase\"]): ScanStatusEvent | null {\n if (!this.status.active) return null;\n return this.set({ ...this.status, phase, updatedAt: Date.now() });\n }\n\n beginAgent(agentName: string, sessionCount: number): ScanStatusEvent {\n if (!this.status.active)\n this.startBatch([agentName], \"scanning\", { [agentName]: sessionCount });\n\n const pendingAgents = this.status.pendingAgents.filter((agent) => agent !== agentName);\n const scanningAgents = [...new Set([...this.status.scanningAgents, agentName])];\n const completedAgents = this.status.completedAgents.filter((agent) => agent !== agentName);\n const existingStatus = this.status.agentStatuses[agentName];\n const now = Date.now();\n return this.set({\n ...this.status,\n active: true,\n phase: this.status.phase === \"initializing\" ? \"initializing\" : \"scanning\",\n pendingAgents,\n scanningAgents,\n completedAgents,\n agentStatuses: {\n ...this.status.agentStatuses,\n [agentName]: {\n agentName,\n status: \"scanning\",\n total: existingStatus?.total,\n processed: existingStatus?.processed ?? 0,\n sessions: existingStatus?.sessions ?? sessionCount,\n startedAt: existingStatus?.startedAt ?? now,\n updatedAt: now,\n },\n },\n totalAgents: Math.max(this.status.totalAgents, pendingAgents.length + scanningAgents.length),\n updatedAt: now,\n completedAt: undefined,\n });\n }\n\n updateAgent(agentName: string, progress: AgentScanProgress): ScanStatusEvent | null {\n const status = this.status.agentStatuses[agentName];\n if (\n !status ||\n status.status === \"pending\" ||\n status.status === \"complete\" ||\n (status.status === \"indexing\" && progress.phase !== \"finalizing\")\n ) {\n return null;\n }\n const now = Date.now();\n const nextStatus: \"finalizing\" | \"scanning\" =\n progress.phase === \"finalizing\" ? \"finalizing\" : \"scanning\";\n const agentStatuses = {\n ...this.status.agentStatuses,\n [agentName]: {\n ...status,\n status: nextStatus,\n total: progress.total ?? status.total,\n processed: progress.processed ?? status.processed,\n sessions: progress.sessions ?? status.sessions,\n updatedAt: now,\n },\n };\n return this.set({\n ...this.status,\n phase: this.activePhase(this.status.pendingAgents, this.status.scanningAgents, agentStatuses),\n agentStatuses,\n updatedAt: now,\n });\n }\n\n indexAgent(agentName: string): ScanStatusEvent | null {\n const status = this.status.agentStatuses[agentName];\n if (\n !this.status.active ||\n !status ||\n (status.status !== \"scanning\" && status.status !== \"finalizing\")\n ) {\n return null;\n }\n\n const now = Date.now();\n const agentStatuses = {\n ...this.status.agentStatuses,\n [agentName]: { ...status, status: \"indexing\" as const, updatedAt: now },\n };\n return this.set({\n ...this.status,\n phase: this.activePhase(this.status.pendingAgents, this.status.scanningAgents, agentStatuses),\n agentStatuses,\n updatedAt: now,\n });\n }\n\n finishAgent(agentName: string, sessionCount?: number): ScanStatusEvent {\n const pendingAgents = this.status.pendingAgents.filter((agent) => agent !== agentName);\n const scanningAgents = this.status.scanningAgents.filter((agent) => agent !== agentName);\n const completedAgents = [...new Set([...this.status.completedAgents, agentName])];\n const isActive = pendingAgents.length > 0 || scanningAgents.length > 0;\n const now = Date.now();\n const previousStatus = this.status.agentStatuses[agentName];\n const total = previousStatus?.total ?? previousStatus?.processed;\n const agentStatuses = {\n ...this.status.agentStatuses,\n [agentName]: {\n agentName,\n status: \"complete\" as const,\n total,\n processed: total,\n sessions: sessionCount ?? previousStatus?.sessions ?? 0,\n startedAt: previousStatus?.startedAt,\n updatedAt: now,\n completedAt: now,\n },\n };\n\n return this.set({\n ...this.status,\n active: isActive,\n phase: isActive ? this.activePhase(pendingAgents, scanningAgents, agentStatuses) : \"idle\",\n pendingAgents,\n scanningAgents,\n completedAgents,\n agentStatuses,\n updatedAt: now,\n completedAt: isActive ? undefined : now,\n });\n }\n\n finishBatch(): ScanStatusEvent {\n const now = Date.now();\n return this.set({\n ...this.status,\n active: false,\n phase: \"idle\",\n pendingAgents: [],\n scanningAgents: [],\n agentStatuses: Object.fromEntries(\n Object.entries(this.status.agentStatuses).map(([agentName, status]) => [\n agentName,\n { ...status, status: \"complete\", completedAt: status.completedAt ?? now, updatedAt: now },\n ]),\n ),\n updatedAt: now,\n completedAt: now,\n });\n }\n\n updateBackfill(patch: Partial<BackfillStatus>): ScanStatusEvent {\n return this.set({\n ...this.status,\n backfill: { ...this.status.backfill, ...patch },\n updatedAt: Date.now(),\n });\n }\n\n private activePhase(\n pendingAgents: string[],\n scanningAgents: string[],\n agentStatuses: ScanStatus[\"agentStatuses\"],\n ): ScanStatusEvent[\"phase\"] {\n if (\n pendingAgents.length === 0 &&\n scanningAgents.length > 0 &&\n scanningAgents.every((agentName) => {\n const status = agentStatuses[agentName]?.status;\n return status === \"finalizing\" || status === \"indexing\";\n })\n ) {\n return \"indexing\";\n }\n return this.status.phase === \"initializing\" ? \"initializing\" : \"scanning\";\n }\n\n private set(status: ScanStatus): ScanStatusEvent {\n this.status = status;\n return this.snapshot();\n }\n}\n","import {\n FileSystemSessionSource,\n attachMissingProjectIdentities,\n buildAgentCacheMeta,\n getAgentFullSyncCursor,\n computeSessionDiff,\n getAgentLastFullSyncAt,\n isAgentCacheInitialized,\n loadCachedSessions,\n markAgentCacheInitialized,\n markAgentFullSyncProgress,\n markAgentFullSyncStarted,\n markAgentFullSyncCompleted,\n saveCachedSessionChanges,\n saveCachedSessions,\n sessionSignature,\n type AgentScanProgress,\n type BaseAgent,\n type ScanOptions,\n type LiveSnapshot,\n type SessionHead,\n type SessionHeadChange,\n} from \"@codesesh/core\";\nimport type {\n BackfillProgress,\n BackfillStatus,\n ScanStatusEvent,\n SessionsUpdatedEvent,\n} from \"@codesesh/core/contract\";\nimport { AgentOperationScheduler, type AgentOperationResult } from \"./agent-operation-scheduler.js\";\nimport { LiveSessionIndex, type LiveSessionIndexOptions } from \"./live-session-index.js\";\nimport { appLogger, logSearchIndexSync } from \"./logging.js\";\nimport { SearchIndexJobRunner } from \"./search-index-job-runner.js\";\nimport type { SearchIndexWorkerJob } from \"./search-index-worker.js\";\nimport { ScanStatusModel } from \"./scan-status-model.js\";\nimport type { ScanRefreshWorkerCheckpoint } from \"./scan-refresh-worker.js\";\nimport type { WorkerRunner } from \"./worker-runner.js\";\n\nexport type { AgentOperationResult } from \"./agent-operation-scheduler.js\";\n\nexport interface AgentSessionsChanged {\n agentName: string;\n sessions: SessionHead[];\n event: SessionsUpdatedEvent | null;\n}\n\nexport interface AgentSyncEngineOptions {\n startupScanOptions?: Pick<ScanOptions, \"from\" | \"to\">;\n workerRunner: WorkerRunner;\n}\n\nexport interface AgentSyncEngineInitializationOptions extends LiveSessionIndexOptions {\n cacheTimestamps?: Record<string, number>;\n}\n\ntype SessionsChangedListener = (change: AgentSessionsChanged) => void;\ntype StatusChangedListener = (event: ScanStatusEvent) => void;\ntype CachedSessions = NonNullable<ReturnType<typeof loadCachedSessions>>;\n\ninterface SessionPersistenceDiff {\n changedSessions: SessionHeadChange[];\n removedSessionIds: string[];\n}\n\ninterface SessionPublication {\n context: \"scan.refresh\" | \"scan.backfill\";\n agentName: string;\n sessions: SessionHead[];\n candidateChangedIds: string[];\n indexJob: SearchIndexWorkerJob;\n}\n\ninterface SessionPublicationResult {\n event: SessionsUpdatedEvent | null;\n diffDuration: number;\n}\n\ninterface RefreshStrategyResult {\n status: \"continue\" | \"unchanged\";\n nextSessions: SessionHead[];\n fullScanSessions: SessionHead[] | null;\n preciseChangedIds: string[] | null;\n persistenceDiff: SessionPersistenceDiff | null;\n checkDuration: number;\n scanDuration: number;\n}\n\nconst REFRESH_DEBOUNCE_MS = 200;\nconst EMPTY_AGENT_REFRESH_DEBOUNCE_MS = 30_000;\nconst SEARCH_INDEX_BULK_PENDING_PATH_THRESHOLD = 100;\nconst BACKFILL_INTERVAL_MS = 24 * 60 * 60 * 1000;\nconst CACHE_TRUNCATION_COVERAGE = 0.5;\n\nfunction buildPersistenceDiff(\n previousSessions: SessionHead[],\n nextSessions: SessionHead[],\n candidateChangedIds: string[] = [],\n): SessionPersistenceDiff {\n const { changes, removedSessionIds } = computeSessionDiff(\n previousSessions,\n nextSessions,\n candidateChangedIds,\n sessionSignature,\n );\n return { changedSessions: changes, removedSessionIds };\n}\n\nfunction restoreAgentCacheMeta(agent: BaseAgent, cached: CachedSessions): void {\n agent.setSessionMetaMap(new Map(Object.entries(cached.meta)));\n}\n\nexport class AgentSyncEngine {\n private lastRefreshAtByAgent = new Map<string, number>();\n private readonly scheduler: AgentOperationScheduler;\n private readonly sessionIndex = new LiveSessionIndex();\n private backfillQueue: string[] = [];\n private currentBackfillAgent: string | undefined;\n private currentBackfillProgress: BackfillProgress | undefined;\n private cacheIntegrityCheckedAgents = new Set<string>();\n private completedBackfillAgents: string[] = [];\n private failedBackfillAgents: string[] = [];\n private sessionsChangedListeners = new Set<SessionsChangedListener>();\n private statusChangedListeners = new Set<StatusChangedListener>();\n private scanStatus = new ScanStatusModel();\n private searchIndexJobs = new SearchIndexJobRunner();\n private nextPublicationId = 1;\n private backgroundRefreshTimer: NodeJS.Timeout | null = null;\n private isShuttingDown = false;\n\n constructor(private readonly options: AgentSyncEngineOptions) {\n this.scheduler = new AgentOperationScheduler((agentName) => this.performRefresh(agentName));\n }\n\n initialize(snapshot: LiveSnapshot, options: AgentSyncEngineInitializationOptions = {}): void {\n this.sessionIndex.initialize(snapshot, options);\n this.lastRefreshAtByAgent.clear();\n for (const agent of this.sessionIndex.snapshot().agents) {\n this.lastRefreshAtByAgent.set(\n agent.name,\n options.cacheTimestamps?.[agent.name] ?? Date.now(),\n );\n }\n }\n\n snapshot(): LiveSnapshot {\n return this.sessionIndex.snapshot();\n }\n\n status(): ScanStatusEvent {\n return this.scanStatus.snapshot();\n }\n\n subscribeSessionsChanged(listener: SessionsChangedListener): () => void {\n this.sessionsChangedListeners.add(listener);\n return () => this.sessionsChangedListeners.delete(listener);\n }\n\n subscribeStatusChanged(listener: StatusChangedListener): () => void {\n this.statusChangedListeners.add(listener);\n return () => this.statusChangedListeners.delete(listener);\n }\n\n async syncInitialIndex(): Promise<void> {\n const jobs = this.buildFullSearchIndexJobs(\"scan.initial\");\n await this.commitSearchIndex(\"scan.initial\", jobs, {\n publicationId: this.publicationId(\"scan.initial\"),\n agents: jobs.map((job) => job.agentName),\n });\n }\n\n handleAgentsChanged(agentNames: Iterable<string>): void {\n const snapshot = this.sessionIndex.snapshot();\n for (const agentName of agentNames) {\n const delayMs =\n (snapshot.byAgent[agentName]?.length ?? 0) === 0\n ? EMPTY_AGENT_REFRESH_DEBOUNCE_MS\n : REFRESH_DEBOUNCE_MS;\n this.scheduler.notify(agentName, delayMs);\n }\n }\n\n startBackgroundRefresh(): void {\n if (this.backgroundRefreshTimer) return;\n const agentNames = this.sessionIndex.snapshot().agents.map((agent) => agent.name);\n this.startScanBatch(agentNames, \"scanning\");\n this.backgroundRefreshTimer = setTimeout(() => {\n this.backgroundRefreshTimer = null;\n for (const agentName of agentNames) this.scheduler.schedule(agentName, 0);\n if (agentNames.length === 0) this.finishScanBatch();\n }, 0);\n }\n\n async refresh(agentName: string): Promise<void> {\n await this.scheduler.refresh(agentName);\n }\n\n async shutdown(): Promise<void> {\n this.isShuttingDown = true;\n const schedulerSnapshot = this.scheduler.snapshot();\n const activeOperations = {\n agent_operations: schedulerSnapshot.activeOperations,\n refreshes: schedulerSnapshot.activeRefreshes,\n backfill_running: this.currentBackfillAgent != null || undefined,\n scan_workers: this.options.workerRunner.activeCount,\n };\n if (activeOperations.agent_operations > 0 || activeOperations.scan_workers > 0) {\n appLogger.warn(\"scan.shutdown.active_operations\", activeOperations);\n }\n this.scheduler.stop();\n if (this.backgroundRefreshTimer) {\n clearTimeout(this.backgroundRefreshTimer);\n this.backgroundRefreshTimer = null;\n }\n this.backfillQueue.length = 0;\n this.currentBackfillAgent = undefined;\n this.currentBackfillProgress = undefined;\n this.cacheIntegrityCheckedAgents.clear();\n const searchIndexSnapshot = this.searchIndexJobs.snapshot();\n appLogger.info(\"search_index.shutdown.started\", {\n active_batch_id: searchIndexSnapshot.activeBatchId,\n pending_batches: searchIndexSnapshot.pendingBatches,\n });\n await this.searchIndexJobs.shutdown();\n await this.options.workerRunner.shutdown();\n await this.scheduler.waitForIdle();\n const stoppedSearchIndexSnapshot = this.searchIndexJobs.snapshot();\n appLogger.info(\"search_index.shutdown.completed\", {\n active_batch_id: searchIndexSnapshot.activeBatchId,\n pending_batches: stoppedSearchIndexSnapshot.pendingBatches,\n });\n }\n\n private startScanBatch(agentNames: string[], phase: ScanStatusEvent[\"phase\"]): void {\n const snapshot = this.sessionIndex.snapshot();\n const sessionCounts = Object.fromEntries(\n agentNames.map((agentName) => [agentName, snapshot.byAgent[agentName]?.length ?? 0]),\n );\n this.publishStatus(this.scanStatus.startBatch(agentNames, phase, sessionCounts));\n }\n\n private setScanPhase(phase: ScanStatusEvent[\"phase\"]): void {\n this.publishStatus(this.scanStatus.setPhase(phase));\n }\n\n private beginAgentScan(agentName: string): void {\n const snapshot = this.sessionIndex.snapshot();\n if (!this.scanStatus.snapshot().active) this.startScanBatch([agentName], \"scanning\");\n this.publishStatus(\n this.scanStatus.beginAgent(agentName, snapshot.byAgent[agentName]?.length ?? 0),\n );\n }\n\n private updateAgentScanProgress(agentName: string, progress: AgentScanProgress): void {\n if (this.currentBackfillAgent === agentName) {\n this.currentBackfillProgress = {\n phase: progress.phase,\n total: progress.total,\n processed: progress.processed,\n sessions: progress.sessions,\n };\n this.publishBackfillStatus();\n return;\n }\n this.publishStatus(this.scanStatus.updateAgent(agentName, progress));\n }\n\n private beginAgentIndexing(agentName: string): void {\n this.publishStatus(this.scanStatus.indexAgent(agentName));\n }\n\n private finishAgentScan(agentName: string): void {\n const count = this.sessionIndex.snapshot().byAgent[agentName]?.length;\n this.publishStatus(this.scanStatus.finishAgent(agentName, count));\n }\n\n private finishScanBatch(): void {\n this.publishStatus(this.scanStatus.finishBatch());\n }\n\n private publishBackfillStatus(): void {\n this.publishStatus(this.scanStatus.updateBackfill(this.backfillStatus()));\n }\n\n private publishStatus(event: ScanStatusEvent | null): void {\n if (!event || this.isShuttingDown) return;\n for (const listener of this.statusChangedListeners) listener(event);\n }\n\n private emitSessionsChanged(change: AgentSessionsChanged): void {\n if (this.isShuttingDown) return;\n for (const listener of this.sessionsChangedListeners) listener(change);\n }\n\n private async performRefresh(agentName: string): Promise<AgentOperationResult> {\n this.beginAgentScan(agentName);\n try {\n return await this.runRefresh(agentName);\n } catch (error) {\n appLogger.error(\"scan.refresh.error\", { agent: agentName, error });\n console.error(`[${agentName}] Session refresh failed:`, error);\n return \"failed\";\n } finally {\n this.finishAgentScan(agentName);\n const agent = this.findAgent(agentName);\n if (agent && this.needsBackfill(agent)) this.enqueueBackfill(agentName);\n }\n }\n\n private async runRefresh(agentName: string): Promise<Exclude<AgentOperationResult, \"failed\">> {\n const startedAt = performance.now();\n const pendingPathCount = this.scheduler.takePendingSignalCount(agentName);\n const agent = this.findAgent(agentName);\n if (!agent) {\n appLogger.warn(\"scan.refresh.missing_agent\", { agent: agentName });\n return \"skipped\";\n }\n const previousSessions = this.sessionIndex.snapshot().byAgent[agentName] ?? [];\n const cached = loadCachedSessions(agentName);\n const refreshBaseline = cached?.sessions ?? previousSessions;\n const cacheTimestamp = cached?.timestamp ?? this.lastRefreshAtByAgent.get(agentName) ?? 0;\n if (cached) restoreAgentCacheMeta(agent, cached);\n const isInitialized = isAgentCacheInitialized(agentName);\n const availabilityStartedAt = performance.now();\n const isAvailable = agent.isAvailable();\n const availabilityDuration = performance.now() - availabilityStartedAt;\n let strategyResult: RefreshStrategyResult;\n if (!isAvailable) {\n strategyResult = this.refreshUnavailableAgent(agentName);\n } else if (!isInitialized) {\n strategyResult = await this.initializeAgent(agent, previousSessions);\n } else if (cached && agent instanceof FileSystemSessionSource) {\n strategyResult = await this.syncAgentSources(agent, cached, startedAt);\n } else if (refreshBaseline.length > 0) {\n strategyResult = await this.refreshChangedAgent(\n agent,\n refreshBaseline,\n cacheTimestamp,\n startedAt,\n );\n } else {\n strategyResult = await this.scanAgentFully(agent, previousSessions);\n }\n if (strategyResult.status === \"unchanged\") return \"unchanged\";\n\n const nextSessions = attachMissingProjectIdentities(strategyResult.nextSessions);\n const searchIndexOptions =\n pendingPathCount >= SEARCH_INDEX_BULK_PENDING_PATH_THRESHOLD ? { isBulk: true } : undefined;\n const persistenceDiff = strategyResult.persistenceDiff;\n const changedSessionIds = persistenceDiff\n ? new Set(persistenceDiff.changedSessions.map(({ session }) => session.id))\n : undefined;\n const persistStartedAt = performance.now();\n const persistentJob: SearchIndexWorkerJob = persistenceDiff\n ? {\n kind: \"changes\",\n context: \"scan.refresh\",\n agentName,\n changes: persistenceDiff.changedSessions,\n removedSessionIds: persistenceDiff.removedSessionIds,\n meta: buildAgentCacheMeta(agent, changedSessionIds),\n ...(searchIndexOptions ? { searchIndexOptions } : {}),\n }\n : {\n kind: \"full\",\n context: \"scan.refresh\",\n agentName,\n sessions: strategyResult.fullScanSessions ?? nextSessions,\n meta: buildAgentCacheMeta(agent),\n saveCache: true,\n ...(searchIndexOptions ? { searchIndexOptions } : {}),\n };\n this.beginAgentIndexing(agentName);\n const publication = await this.commitSessionPublication({\n context: \"scan.refresh\",\n agentName,\n sessions: nextSessions,\n candidateChangedIds: strategyResult.preciseChangedIds ?? [],\n indexJob: persistentJob,\n });\n const persistDuration = performance.now() - persistStartedAt;\n logSearchIndexSync(\"scan.refresh\", null, { pending_paths: pendingPathCount });\n\n const totalDurationMs = performance.now() - startedAt;\n this.scheduler.recordRefreshDuration(agentName, totalDurationMs);\n appLogger.info(\"scan.refresh.done\", {\n agent: agentName,\n duration_ms: Math.round(totalDurationMs),\n sessions: nextSessions.length,\n new_sessions: publication.event?.newSessions ?? 0,\n updated_sessions: publication.event?.updatedSessions ?? 0,\n removed_sessions: publication.event?.removedSessions ?? 0,\n pending_paths: pendingPathCount,\n availability_ms: Math.round(availabilityDuration),\n check_ms: Math.round(strategyResult.checkDuration),\n scan_ms: Math.round(strategyResult.scanDuration),\n diff_ms: Math.round(publication.diffDuration),\n persist_ms: Math.round(persistDuration),\n search_index_ms: Math.round(persistDuration),\n persistent_index_worker_job: persistentJob.kind,\n });\n return \"committed\";\n }\n\n /**\n * An agent that cannot be reached was never scanned, so there is nothing to\n * compare against. Publishing an empty result here would diff every known\n * session into a removal — the same mistake as reading a failed query as an\n * empty database.\n */\n private refreshUnavailableAgent(agentName: string): RefreshStrategyResult {\n this.lastRefreshAtByAgent.set(agentName, Date.now());\n const previousSessions = this.sessionIndex.snapshot().byAgent[agentName] ?? [];\n if (previousSessions.length > 0) {\n appLogger.warn(\"scan.refresh.agent_unavailable\", {\n agent: agentName,\n retained_sessions: previousSessions.length,\n });\n return this.refreshStrategyResult(previousSessions, { status: \"unchanged\" });\n }\n return this.refreshStrategyResult([]);\n }\n\n private async initializeAgent(\n agent: BaseAgent,\n previousSessions: SessionHead[],\n ): Promise<RefreshStrategyResult> {\n this.setScanPhase(\"initializing\");\n const scanStartedAt = performance.now();\n const result = await this.runWorker(agent, previousSessions, null, this.startupScanOptions(), {\n checkpoint: true,\n });\n agent.setSessionMetaMap(new Map(Object.entries(result.meta)));\n const sessions = attachMissingProjectIdentities(result.sessions);\n this.lastRefreshAtByAgent.set(agent.name, Date.now());\n return this.refreshStrategyResult(sessions, {\n fullScanSessions: sessions,\n scanDuration: performance.now() - scanStartedAt,\n });\n }\n\n private async syncAgentSources(\n agent: FileSystemSessionSource,\n cached: CachedSessions,\n refreshStartedAt: number,\n ): Promise<RefreshStrategyResult> {\n const scanStartedAt = performance.now();\n const result = await this.runWorker(agent, cached.sessions, null, this.startupScanOptions(), {\n sourceSync: true,\n meta: cached.meta,\n });\n agent.setSessionMetaMap(new Map(Object.entries(result.meta)));\n const sessions = attachMissingProjectIdentities(result.sessions);\n const preciseChangedIds = result.changedIds ?? [];\n const persistenceDiff = buildPersistenceDiff(cached.sessions, sessions, preciseChangedIds);\n this.lastRefreshAtByAgent.set(agent.name, Date.now());\n if (\n persistenceDiff.changedSessions.length === 0 &&\n persistenceDiff.removedSessionIds.length === 0\n ) {\n this.logUnchangedRefresh(agent.name, refreshStartedAt);\n return this.refreshStrategyResult(sessions, {\n status: \"unchanged\",\n scanDuration: performance.now() - scanStartedAt,\n });\n }\n return this.refreshStrategyResult(sessions, {\n preciseChangedIds,\n persistenceDiff,\n scanDuration: performance.now() - scanStartedAt,\n });\n }\n\n private async refreshChangedAgent(\n agent: BaseAgent,\n baseline: SessionHead[],\n cacheTimestamp: number,\n refreshStartedAt: number,\n ): Promise<RefreshStrategyResult> {\n const checkStartedAt = performance.now();\n const checkResult = await Promise.resolve(agent.checkForChanges(cacheTimestamp, baseline));\n const checkDuration = performance.now() - checkStartedAt;\n this.lastRefreshAtByAgent.set(agent.name, checkResult.timestamp);\n if (!checkResult.hasChanges) {\n this.logUnchangedRefresh(agent.name, refreshStartedAt);\n return this.refreshStrategyResult(baseline, { status: \"unchanged\", checkDuration });\n }\n const preciseChangedIds = checkResult.changedIds ?? null;\n const scanStartedAt = performance.now();\n if (preciseChangedIds === null) {\n const result = await this.runWorker(agent, baseline, null, {}, { checkpoint: true });\n agent.setSessionMetaMap(new Map(Object.entries(result.meta)));\n const sessions = attachMissingProjectIdentities(result.sessions);\n return this.refreshStrategyResult(sessions, {\n persistenceDiff: buildPersistenceDiff(baseline, sessions),\n checkDuration,\n scanDuration: performance.now() - scanStartedAt,\n });\n }\n const sessions = attachMissingProjectIdentities(\n await Promise.resolve(agent.incrementalScan(baseline, preciseChangedIds, checkResult.refs)),\n );\n return this.refreshStrategyResult(sessions, {\n preciseChangedIds,\n persistenceDiff: buildPersistenceDiff(baseline, sessions, preciseChangedIds),\n checkDuration,\n scanDuration: performance.now() - scanStartedAt,\n });\n }\n\n private async scanAgentFully(\n agent: BaseAgent,\n previousSessions: SessionHead[],\n ): Promise<RefreshStrategyResult> {\n const scanStartedAt = performance.now();\n const result = await this.runWorker(agent, previousSessions, null, {}, { checkpoint: true });\n agent.setSessionMetaMap(new Map(Object.entries(result.meta)));\n const sessions = attachMissingProjectIdentities(result.sessions);\n this.lastRefreshAtByAgent.set(agent.name, Date.now());\n return this.refreshStrategyResult(sessions, {\n fullScanSessions: sessions,\n scanDuration: performance.now() - scanStartedAt,\n });\n }\n\n private refreshStrategyResult(\n nextSessions: SessionHead[],\n overrides: Partial<Omit<RefreshStrategyResult, \"nextSessions\">> = {},\n ): RefreshStrategyResult {\n return {\n status: \"continue\",\n nextSessions,\n fullScanSessions: null,\n preciseChangedIds: null,\n persistenceDiff: null,\n checkDuration: 0,\n scanDuration: 0,\n ...overrides,\n };\n }\n\n private runWorker(\n agent: BaseAgent,\n previousSessions: SessionHead[],\n changedIds: string[] | null,\n scanOptions: Pick<ScanOptions, \"from\" | \"to\" | \"fast\">,\n workerOptions: {\n sourceSync?: boolean;\n backfill?: boolean;\n backfillCursor?: string | null;\n checkpoint?: boolean;\n meta?: CachedSessions[\"meta\"];\n } = {},\n ) {\n return this.options.workerRunner.run(agent.name, {\n previousSessions,\n changedIds,\n scanOptions,\n sourceSync: workerOptions.sourceSync,\n backfill: workerOptions.backfill,\n backfillCursor: workerOptions.backfillCursor,\n checkpoint: workerOptions.checkpoint,\n meta: workerOptions.meta ?? buildAgentCacheMeta(agent),\n onProgress: (progress) => this.updateAgentScanProgress(agent.name, progress),\n onCheckpoint: (checkpoint) => this.handleWorkerCheckpoint(agent, checkpoint),\n });\n }\n\n private handleWorkerCheckpoint(agent: BaseAgent, checkpoint: ScanRefreshWorkerCheckpoint): void {\n if (this.isShuttingDown) return;\n\n if (checkpoint.stage === \"scanned\") {\n let persisted = false;\n try {\n persisted = saveCachedSessions(agent.name, checkpoint.sessions, checkpoint.meta);\n if (persisted) markAgentCacheInitialized(agent.name);\n } catch (error) {\n appLogger.error(\"scan.checkpoint.failed\", {\n agent: agent.name,\n stage: checkpoint.stage,\n error,\n });\n }\n agent.setSessionMetaMap(new Map(Object.entries(checkpoint.meta)));\n\n const event = this.sessionIndex.commitAgentSessions(agent.name, checkpoint.sessions);\n this.emitSessionsChanged({\n agentName: agent.name,\n sessions: this.sessionIndex.snapshot().byAgent[agent.name] ?? [],\n event,\n });\n appLogger.info(\"scan.checkpoint.persisted\", {\n agent: agent.name,\n stage: checkpoint.stage,\n sessions: checkpoint.sessions.length,\n persisted,\n });\n return;\n }\n\n let persisted = false;\n try {\n persisted = saveCachedSessionChanges(agent.name, checkpoint.changes, [], checkpoint.meta);\n } catch (error) {\n appLogger.error(\"scan.checkpoint.failed\", {\n agent: agent.name,\n stage: checkpoint.stage,\n sessions: checkpoint.changes.length,\n error,\n });\n }\n if (persisted && checkpoint.backfillCursor) {\n markAgentFullSyncProgress(agent.name, checkpoint.backfillCursor);\n }\n appLogger.debug(\"scan.checkpoint.persisted\", {\n agent: agent.name,\n stage: checkpoint.stage,\n sessions: checkpoint.changes.length,\n backfill_cursor: checkpoint.backfillCursor,\n persisted,\n });\n }\n\n private needsBackfill(agent: BaseAgent): boolean {\n const startupScanOptions = this.startupScanOptions();\n if (startupScanOptions.from == null && startupScanOptions.to == null) return false;\n if (!agent.isAvailable()) return false;\n const lastSyncAt = getAgentLastFullSyncAt(agent.name);\n if (lastSyncAt == null || Date.now() - lastSyncAt > BACKFILL_INTERVAL_MS) return true;\n if (!(agent instanceof FileSystemSessionSource)) return false;\n if (this.cacheIntegrityCheckedAgents.has(agent.name)) return false;\n\n const cached = loadCachedSessions(agent.name);\n const sourceCount = agent.listSessionSources().length;\n const cachedCount = cached?.sessions.length ?? 0;\n this.cacheIntegrityCheckedAgents.add(agent.name);\n if (sourceCount > 0 && cachedCount / sourceCount < CACHE_TRUNCATION_COVERAGE) {\n appLogger.warn(\"scan.backfill.cache_truncated\", {\n agent: agent.name,\n cached_sessions: cachedCount,\n source_files: sourceCount,\n last_sync_at: lastSyncAt,\n });\n return true;\n }\n return false;\n }\n\n private enqueueBackfill(agentName: string): void {\n if (\n this.isShuttingDown ||\n this.currentBackfillAgent === agentName ||\n this.backfillQueue.includes(agentName)\n ) {\n return;\n }\n this.backfillQueue.push(agentName);\n this.publishBackfillStatus();\n this.pumpBackfillQueue();\n }\n\n private pumpBackfillQueue(): void {\n if (this.isShuttingDown || this.currentBackfillAgent) return;\n const agentName = this.backfillQueue.shift();\n if (!agentName) return;\n this.currentBackfillAgent = agentName;\n this.currentBackfillProgress = undefined;\n this.publishBackfillStatus();\n void this.runBackfill(agentName).then((result) => {\n if (this.isShuttingDown) return;\n this.currentBackfillAgent = undefined;\n this.currentBackfillProgress = undefined;\n if (result === \"committed\") {\n if (!this.completedBackfillAgents.includes(agentName)) {\n this.completedBackfillAgents.push(agentName);\n }\n this.failedBackfillAgents = this.failedBackfillAgents.filter(\n (failedAgent) => failedAgent !== agentName,\n );\n } else if (!this.failedBackfillAgents.includes(agentName)) {\n this.failedBackfillAgents.push(agentName);\n this.cacheIntegrityCheckedAgents.delete(agentName);\n }\n this.publishBackfillStatus();\n this.pumpBackfillQueue();\n });\n }\n\n private runBackfill(agentName: string): Promise<AgentOperationResult> {\n return this.scheduler.run(agentName, \"backfill\", () => this.performBackfill(agentName));\n }\n\n private async performBackfill(agentName: string): Promise<AgentOperationResult> {\n const startedAt = performance.now();\n const agent = this.findAgent(agentName);\n if (!agent || !agent.isAvailable()) return \"skipped\";\n const snapshot = this.sessionIndex.snapshot();\n const cached = loadCachedSessions(agentName);\n const baseline = cached?.sessions ?? snapshot.byAgent[agentName] ?? [];\n const meta = cached?.meta ?? buildAgentCacheMeta(agent);\n const backfillCursor = getAgentFullSyncCursor(agentName);\n if (cached) restoreAgentCacheMeta(agent, cached);\n try {\n markAgentFullSyncStarted(agentName);\n const result = await this.runWorker(\n agent,\n baseline,\n null,\n {},\n {\n sourceSync: agent instanceof FileSystemSessionSource,\n backfill: true,\n backfillCursor,\n meta,\n checkpoint: true,\n },\n );\n agent.setSessionMetaMap(new Map(Object.entries(result.meta)));\n const fullSessions = attachMissingProjectIdentities(result.sessions);\n this.currentBackfillProgress = { phase: \"indexing\", sessions: fullSessions.length };\n this.publishBackfillStatus();\n await this.commitSessionPublication({\n context: \"scan.backfill\",\n agentName,\n sessions: fullSessions,\n candidateChangedIds: result.changedIds ?? [],\n indexJob: {\n kind: \"full\",\n context: \"scan.backfill\",\n agentName,\n sessions: fullSessions,\n meta: buildAgentCacheMeta(agent),\n saveCache: true,\n },\n });\n markAgentFullSyncCompleted(agentName);\n appLogger.info(\"scan.backfill.done\", {\n agent: agentName,\n duration_ms: Math.round(performance.now() - startedAt),\n sessions: fullSessions.length,\n changed: result.changedIds?.length ?? 0,\n });\n return \"committed\";\n } catch (error) {\n appLogger.error(\"scan.backfill.error\", { agent: agentName, error });\n console.error(`[${agentName}] Backfill failed:`, error);\n return \"failed\";\n }\n }\n\n private backfillStatus(): BackfillStatus {\n return {\n active: this.currentBackfillAgent != null || this.backfillQueue.length > 0,\n pendingAgents: [...this.backfillQueue],\n currentAgent: this.currentBackfillAgent,\n progress: this.currentBackfillProgress,\n completedAgents: [...this.completedBackfillAgents],\n failedAgents: [...this.failedBackfillAgents],\n };\n }\n\n private buildFullSearchIndexJobs(context: string): SearchIndexWorkerJob[] {\n const snapshot = this.sessionIndex.snapshot();\n return snapshot.agents.map((agent) => {\n const cached = loadCachedSessions(agent.name);\n return cached\n ? {\n kind: \"full\",\n context,\n agentName: agent.name,\n sessions: cached.sessions,\n meta: cached.meta,\n }\n : {\n kind: \"full\",\n context,\n agentName: agent.name,\n sessions: snapshot.byAgent[agent.name] ?? [],\n meta: buildAgentCacheMeta(agent),\n };\n });\n }\n\n private publicationId(context: string, agentName?: string): string {\n const id = this.nextPublicationId++;\n return agentName ? `${context}:${agentName}:${id}` : `${context}:${id}`;\n }\n\n private async commitSearchIndex(\n context: string,\n jobs: SearchIndexWorkerJob[],\n details: { publicationId: string; agent?: string; agents?: string[] },\n ): Promise<void> {\n appLogger.info(\"session.publication.prepared\", {\n publication_id: details.publicationId,\n context,\n agent: details.agent,\n agents: details.agents,\n jobs: jobs.length,\n });\n try {\n await this.searchIndexJobs.enqueue(context, jobs);\n } catch (error) {\n appLogger.error(\"session.publication.failed\", {\n publication_id: details.publicationId,\n context,\n agent: details.agent,\n stage: \"search_index\",\n error,\n });\n throw error;\n }\n appLogger.info(\"session.publication.index_committed\", {\n publication_id: details.publicationId,\n context,\n agent: details.agent,\n });\n }\n\n private async commitSessionPublication(\n publication: SessionPublication,\n ): Promise<SessionPublicationResult> {\n const publicationId = this.publicationId(publication.context, publication.agentName);\n await this.commitSearchIndex(publication.context, [publication.indexJob], {\n publicationId,\n agent: publication.agentName,\n });\n const diffStartedAt = performance.now();\n const event = this.sessionIndex.commitAgentSessions(\n publication.agentName,\n publication.sessions,\n publication.candidateChangedIds,\n );\n const diffDuration = performance.now() - diffStartedAt;\n this.emitSessionsChanged({\n agentName: publication.agentName,\n sessions: this.sessionIndex.snapshot().byAgent[publication.agentName] ?? [],\n event,\n });\n appLogger.info(\"session.publication.published\", {\n publication_id: publicationId,\n context: publication.context,\n agent: publication.agentName,\n sessions: publication.sessions.length,\n has_event: event != null,\n });\n return { event, diffDuration };\n }\n\n private findAgent(agentName: string): BaseAgent | undefined {\n return this.sessionIndex.findAgent(agentName);\n }\n\n private startupScanOptions(): Pick<ScanOptions, \"from\" | \"to\"> {\n return this.options.startupScanOptions ?? {};\n }\n\n private logUnchangedRefresh(agentName: string, startedAt: number): void {\n appLogger.debug(\"scan.refresh.unchanged\", {\n agent: agentName,\n duration_ms: Math.round(performance.now() - startedAt),\n });\n }\n}\n","/**\n * SessionWatcher — a deep module that hides platform-specific file watching\n * (recursive watch availability, non-recursive fallback trees, write-stability\n * polling, debounce) behind a tiny interface.\n *\n * Consumers only need to know: start watching these agent sources, stop, and get\n * notified (post write-stability + debounce) which agents' data changed. The\n * recursive-vs-fallback strategy, APFS mtime quirks, and path-stability polling\n * are all internal details.\n */\nimport { existsSync, readdirSync, statSync, watch, type FSWatcher } from \"node:fs\";\nimport { dirname, isAbsolute, join, relative, resolve } from \"node:path\";\nimport type { SessionWatchPlan } from \"@codesesh/core\";\nimport { appLogger } from \"./logging.js\";\n\nconst WRITE_STABILITY_THRESHOLD_MS = 250;\nconst WRITE_STABILITY_POLL_MS = 100;\n\nexport interface SessionWatchSource {\n readonly name: string;\n getSessionWatchPlan(): SessionWatchPlan;\n}\n\ninterface WatchScope {\n agentName: string;\n targetPath: string;\n}\n\ninterface StablePathState {\n path: string;\n agentNames: Set<string>;\n lastMtimeMs: number | null;\n lastSize: number | null;\n stableSince: number;\n timer: NodeJS.Timeout | null;\n}\n\nexport type AgentsChangedListener = (agentNames: Set<string>) => void;\n\nexport function toAbsolutePath(path: string): string {\n return isAbsolute(path) ? path : resolve(path);\n}\n\nfunction closestWatchablePath(targetPath: string): string | null {\n if (!isAbsolute(targetPath) && !existsSync(targetPath)) {\n return null;\n }\n\n let current = toAbsolutePath(targetPath);\n\n while (!existsSync(current)) {\n const parent = dirname(current);\n if (parent === current) {\n return null;\n }\n current = parent;\n }\n\n return current;\n}\n\nfunction getWatchRoot(path: string): string {\n const stat = statSync(path);\n return stat.isDirectory() ? path : dirname(path);\n}\n\nexport function isRecursiveWatchSupported(\n // \"ibmi\" is a real process.platform value on IBM i (PASE) but is not yet\n // declared in @types/node's Platform union.\n platform: NodeJS.Platform | \"ibmi\" = process.platform,\n nodeVersion = process.versions.node,\n): boolean {\n if (platform === \"darwin\" || platform === \"win32\") {\n return true;\n }\n if (platform !== \"linux\" && platform !== \"aix\" && platform !== \"ibmi\") {\n return false;\n }\n\n const [major = 0, minor = 0] = nodeVersion.split(\".\").map((part) => Number(part));\n return major > 19 || (major === 19 && minor >= 1);\n}\n\nfunction isRecursiveWatchUnavailable(error: unknown): boolean {\n return (\n typeof error === \"object\" &&\n error !== null &&\n \"code\" in error &&\n error.code === \"ERR_FEATURE_UNAVAILABLE_ON_PLATFORM\"\n );\n}\n\nfunction isSameOrChildPath(parentPath: string, childPath: string): boolean {\n const path = relative(parentPath, childPath);\n return path === \"\" || (!path.startsWith(\"..\") && !isAbsolute(path));\n}\n\n/**\n * Sidecars a SQLite commit writes. `-shm` is excluded because a read-only open\n * rewrites it, which would make every scan look like a new change.\n */\nconst SQLITE_SIDECAR_SUFFIXES = [\"-wal\", \"-journal\"];\n\n/** True for `foo.db-wal` against `foo.db`, but not for `foo.db.bak`. */\nfunction isSqliteSidecarOf(changedPath: string, targetPath: string): boolean {\n return SQLITE_SIDECAR_SUFFIXES.some((suffix) => changedPath === `${targetPath}${suffix}`);\n}\n\nfunction isRelatedPath(changedPath: string, targetPath: string): boolean {\n return (\n isSameOrChildPath(targetPath, changedPath) ||\n isSameOrChildPath(changedPath, targetPath) ||\n isSqliteSidecarOf(changedPath, targetPath)\n );\n}\n\nfunction mergeScopes(target: WatchScope[], scopes: WatchScope[]): void {\n for (const scope of scopes) {\n if (\n !target.some(\n (item) => item.agentName === scope.agentName && item.targetPath === scope.targetPath,\n )\n ) {\n target.push(scope);\n }\n }\n}\n\nfunction resolveWatchEventPath(watchPath: string, filename: string | Buffer | null): string {\n const filenameText = filename?.toString();\n if (!filenameText) {\n return watchPath;\n }\n return isAbsolute(filenameText) ? filenameText : join(watchPath, filenameText);\n}\n\nexport class SessionWatcher {\n private watchers: FSWatcher[] = [];\n private fallbackWatchScopes = new Map<string, WatchScope[]>();\n private stablePaths = new Map<string, StablePathState>();\n private listeners = new Set<AgentsChangedListener>();\n\n /** Register a listener fired (after write-stability polling) with the changed agent set. */\n onAgentsChanged(cb: AgentsChangedListener): () => void {\n this.listeners.add(cb);\n return () => {\n this.listeners.delete(cb);\n };\n }\n\n /** Begin watching the session sources declared by each agent adapter. */\n start(agents: SessionWatchSource[]): void {\n const scopesByRoot = new Map<string, WatchScope[]>();\n\n for (const agent of agents) {\n const plan = agent.getSessionWatchPlan();\n if (plan.status !== \"supported\") {\n appLogger.debug(\"watch.skip\", {\n agent: agent.name,\n status: plan.status,\n reason: plan.reason,\n });\n continue;\n }\n if (plan.targets.length === 0) {\n appLogger.debug(\"watch.skip\", { agent: agent.name, status: plan.status });\n continue;\n }\n\n for (const target of plan.targets) {\n const watchRootPath = closestWatchablePath(target.root ?? target.path);\n if (!watchRootPath) continue;\n\n let rootPath: string;\n try {\n rootPath = getWatchRoot(watchRootPath);\n } catch (error) {\n this.reportWatchError(\"watch.resolve.error\", { path: watchRootPath, error });\n continue;\n }\n const targetPath = toAbsolutePath(target.path);\n const scopes = scopesByRoot.get(rootPath) ?? [];\n if (\n !scopes.some((scope) => scope.agentName === agent.name && scope.targetPath === targetPath)\n ) {\n scopes.push({ agentName: agent.name, targetPath });\n }\n scopesByRoot.set(rootPath, scopes);\n }\n }\n\n for (const [rootPath, scopes] of scopesByRoot.entries()) {\n const agents = Array.from(new Set(scopes.map((scope) => scope.agentName)));\n appLogger.info(\"watch.start\", {\n root: rootPath,\n agents,\n targets: scopes.map((scope) => ({\n agent: scope.agentName,\n path: scope.targetPath,\n })),\n });\n\n if (isRecursiveWatchSupported()) {\n const started = this.watchDirectory(rootPath, scopes, true);\n if (started) {\n continue;\n }\n }\n\n this.watchDirectoryTree(rootPath, scopes);\n }\n }\n\n /** Stop all watchers and clear pending stability polls. */\n async dispose(): Promise<void> {\n for (const state of this.stablePaths.values()) {\n if (state.timer) {\n clearTimeout(state.timer);\n }\n }\n this.stablePaths.clear();\n\n await Promise.all(this.watchers.map((watcher) => watcher.close()));\n this.watchers = [];\n this.fallbackWatchScopes.clear();\n this.listeners.clear();\n }\n\n private watchDirectory(path: string, scopes: WatchScope[], recursive: boolean): boolean {\n try {\n const watcher = watch(path, { recursive }, (eventType, filename) => {\n queueMicrotask(() => {\n try {\n const activeScopes = recursive\n ? scopes\n : (this.fallbackWatchScopes.get(path) ?? scopes);\n this.handleWatchEvent(path, activeScopes, eventType, filename);\n if (!recursive) {\n this.watchNewDirectories(path, filename, activeScopes);\n }\n } catch (error) {\n this.reportWatchError(\"watch.event.error\", { path, recursive, error });\n }\n });\n });\n\n watcher.on(\"error\", (error) => {\n this.reportWatchError(\"watch.error\", { path, recursive, error });\n });\n\n this.watchers.push(watcher);\n return true;\n } catch (error) {\n if (recursive && isRecursiveWatchUnavailable(error)) {\n appLogger.warn(\"watch.recursive_unavailable\", { path, error });\n return false;\n }\n\n this.reportWatchError(\"watch.start.error\", { path, recursive, error });\n return false;\n }\n }\n\n private watchDirectoryTree(rootPath: string, scopes: WatchScope[]): void {\n const pending = [rootPath];\n\n while (pending.length > 0) {\n const dirPath = pending.pop()!;\n this.watchFallbackDirectory(dirPath, scopes);\n\n try {\n for (const entry of readdirSync(dirPath, { withFileTypes: true })) {\n if (entry.isDirectory()) {\n pending.push(join(dirPath, entry.name));\n }\n }\n } catch (error) {\n this.reportWatchError(\"watch.scan.error\", { path: dirPath, error });\n }\n }\n }\n\n private watchFallbackDirectory(path: string, scopes: WatchScope[]): void {\n const existingScopes = this.fallbackWatchScopes.get(path);\n if (existingScopes) {\n mergeScopes(existingScopes, scopes);\n return;\n }\n\n const storedScopes = [...scopes];\n this.fallbackWatchScopes.set(path, storedScopes);\n if (!this.watchDirectory(path, storedScopes, false)) {\n this.fallbackWatchScopes.delete(path);\n }\n }\n\n private watchNewDirectories(\n watchPath: string,\n filename: string | Buffer | null,\n scopes: WatchScope[],\n ): void {\n const path = resolveWatchEventPath(watchPath, filename);\n try {\n if (statSync(path).isDirectory()) {\n this.watchDirectoryTree(path, scopes);\n }\n } catch {}\n }\n\n private handleWatchEvent(\n watchPath: string,\n scopes: WatchScope[],\n eventType: string,\n filename: string | Buffer | null,\n ): void {\n const changedPath = resolveWatchEventPath(watchPath, filename);\n const agentNames = new Set(\n scopes\n .filter((scope) => isRelatedPath(changedPath, scope.targetPath))\n .map((scope) => scope.agentName),\n );\n\n if (agentNames.size === 0) {\n return;\n }\n\n appLogger.debug(\"watch.event\", {\n event: eventType,\n path: changedPath,\n agents: Array.from(agentNames),\n });\n this.waitForStablePath(changedPath, agentNames);\n }\n\n private waitForStablePath(path: string, agentNames: Set<string>): void {\n const existing = this.stablePaths.get(path);\n if (existing) {\n for (const agentName of agentNames) {\n existing.agentNames.add(agentName);\n }\n return;\n }\n\n const state: StablePathState = {\n path,\n agentNames: new Set(agentNames),\n lastMtimeMs: null,\n lastSize: null,\n stableSince: Date.now(),\n timer: null,\n };\n this.stablePaths.set(path, state);\n this.pollStablePath(path);\n }\n\n private pollStablePath(path: string): void {\n const state = this.stablePaths.get(path);\n if (!state) {\n return;\n }\n\n let size: number;\n let mtimeMs: number;\n try {\n const stat = statSync(path);\n size = stat.size;\n mtimeMs = stat.mtimeMs;\n } catch {\n this.stablePaths.delete(path);\n this.emitAgentsChanged(state.agentNames);\n return;\n }\n\n const now = Date.now();\n const unchanged = state.lastSize === size && state.lastMtimeMs === mtimeMs;\n if (!unchanged) {\n state.lastSize = size;\n state.lastMtimeMs = mtimeMs;\n state.stableSince = now;\n }\n\n if (unchanged && now - state.stableSince >= WRITE_STABILITY_THRESHOLD_MS) {\n this.stablePaths.delete(path);\n this.emitAgentsChanged(state.agentNames);\n return;\n }\n\n state.timer = setTimeout(() => this.pollStablePath(path), WRITE_STABILITY_POLL_MS);\n }\n\n private emitAgentsChanged(agentNames: Set<string>): void {\n if (agentNames.size === 0) return;\n for (const listener of this.listeners) {\n listener(new Set(agentNames));\n }\n }\n\n private reportWatchError(event: string, data: Record<string, unknown>): void {\n appLogger.error(event, data);\n console.error(\"[watch] File watcher failed:\", data.error);\n }\n}\n","import { Worker } from \"node:worker_threads\";\nimport type {\n AgentScanProgress,\n ScanOptions,\n SessionCacheMeta,\n SessionHead,\n SessionHeadChange,\n} from \"@codesesh/core\";\nimport { appLogger } from \"./logging.js\";\nimport type {\n ScanRefreshWorkerCheckpoint,\n ScanRefreshWorkerMessage,\n ScanRefreshWorkerRequest,\n} from \"./scan-refresh-worker.js\";\n\nexport interface WorkerPayload {\n previousSessions: SessionHead[];\n changedIds: string[] | null;\n sourceSync?: boolean;\n backfill?: boolean;\n backfillCursor?: string | null;\n checkpoint?: boolean;\n scanOptions: Pick<ScanOptions, \"from\" | \"to\" | \"fast\">;\n meta: Record<string, SessionCacheMeta>;\n onProgress?: (progress: AgentScanProgress) => void;\n onCheckpoint?: (checkpoint: ScanRefreshWorkerCheckpoint) => void;\n}\n\nexport interface WorkerResult {\n sessions: SessionHead[];\n meta: Record<string, SessionCacheMeta>;\n changedIds?: string[];\n}\n\nexport interface WorkerRunner {\n readonly activeCount: number;\n run(agentName: string, payload: WorkerPayload): Promise<WorkerResult>;\n shutdown(): Promise<void>;\n}\n\ninterface PendingRequest {\n resolve: (result: WorkerResult) => void;\n reject: (error: Error) => void;\n payload: WorkerPayload;\n onProgress?: (progress: AgentScanProgress) => void;\n onCheckpoint?: (checkpoint: ScanRefreshWorkerCheckpoint) => void;\n}\n\ninterface WorkerSlot {\n worker: Worker;\n pending: Map<number, PendingRequest>;\n closed: boolean;\n}\n\nconst SHUTDOWN_ERROR_MESSAGE = \"Scan refresh worker shut down\";\n\nfunction applySessionChanges(\n previousSessions: SessionHead[],\n changes: SessionHeadChange[],\n removedSessionIds: string[],\n): SessionHead[] {\n const replacedIds = new Set(removedSessionIds);\n for (const { session } of changes) replacedIds.add(session.id);\n const retained = previousSessions.filter((session) => !replacedIds.has(session.id));\n const next: Array<SessionHead | undefined> = Array.from({\n length: retained.length + changes.length,\n });\n\n for (const { session, sortIndex } of changes) {\n if (sortIndex < 0 || sortIndex >= next.length || next[sortIndex]) {\n throw new Error(`Invalid scan refresh sort index: ${sortIndex}`);\n }\n next[sortIndex] = session;\n }\n\n let retainedIndex = 0;\n for (let index = 0; index < next.length; index += 1) {\n if (!next[index]) next[index] = retained[retainedIndex++];\n }\n if (retainedIndex !== retained.length || next.some((session) => !session)) {\n throw new Error(\"Invalid scan refresh delta\");\n }\n return next as SessionHead[];\n}\n\nfunction applyMetaChanges(\n previous: Record<string, SessionCacheMeta>,\n changed: Record<string, SessionCacheMeta>,\n replacedSessionIds: Iterable<string>,\n): Record<string, SessionCacheMeta> {\n const next = { ...previous };\n for (const id of replacedSessionIds) delete next[id];\n return Object.assign(next, changed);\n}\n\nexport class ThreadWorkerRunner implements WorkerRunner {\n private workers = new Map<string, WorkerSlot>();\n private nextRequestId = 1;\n private isShuttingDown = false;\n\n constructor(private readonly workerUrl: URL) {}\n\n get activeCount(): number {\n let count = 0;\n for (const slot of this.workers.values()) count += slot.pending.size;\n return count;\n }\n\n run(agentName: string, payload: WorkerPayload): Promise<WorkerResult> {\n if (this.isShuttingDown) return Promise.reject(new Error(SHUTDOWN_ERROR_MESSAGE));\n\n const request: ScanRefreshWorkerRequest = {\n type: \"run\",\n requestId: this.nextRequestId++,\n agentName,\n previousSessions: payload.previousSessions,\n changedIds: payload.changedIds,\n sourceSync: payload.sourceSync,\n backfill: payload.backfill,\n backfillCursor: payload.backfillCursor,\n checkpoint: payload.checkpoint,\n scanOptions: payload.scanOptions,\n meta: payload.meta,\n };\n\n return new Promise((resolve, reject) => {\n let slot = this.workers.get(agentName);\n const isNewWorker = !slot;\n if (!slot) {\n try {\n slot = this.createWorker(agentName, request);\n } catch (error) {\n reject(error instanceof Error ? error : new Error(String(error)));\n return;\n }\n }\n\n slot.pending.set(request.requestId, {\n resolve,\n reject,\n payload,\n onProgress: payload.onProgress,\n onCheckpoint: payload.onCheckpoint,\n });\n\n if (!isNewWorker) {\n try {\n slot.worker.postMessage(request);\n } catch (error) {\n slot.pending.delete(request.requestId);\n reject(error instanceof Error ? error : new Error(String(error)));\n }\n }\n });\n }\n\n async shutdown(): Promise<void> {\n this.isShuttingDown = true;\n const slots = [...this.workers.values()];\n this.workers.clear();\n const shutdownError = new Error(SHUTDOWN_ERROR_MESSAGE);\n for (const slot of slots) {\n slot.closed = true;\n for (const pending of slot.pending.values()) pending.reject(shutdownError);\n slot.pending.clear();\n }\n await Promise.allSettled(slots.map((slot) => slot.worker.terminate()));\n }\n\n private createWorker(agentName: string, request: ScanRefreshWorkerRequest): WorkerSlot {\n const worker = new Worker(this.workerUrl, { workerData: request });\n const slot: WorkerSlot = { worker, pending: new Map(), closed: false };\n worker.unref();\n this.workers.set(agentName, slot);\n worker.on(\"message\", (message: ScanRefreshWorkerMessage) => {\n this.handleMessage(slot, message);\n });\n worker.on(\"error\", (error) => {\n this.closeWorker(agentName, slot, error);\n });\n worker.on(\"exit\", (code) => {\n if (slot.closed) return;\n const error = new Error(`Scan refresh worker exited before completing (code ${code})`);\n if (slot.pending.size > 0) {\n appLogger.warn(\"scan.refresh_worker.exit_before_done\", { agent: agentName, code });\n }\n this.closeWorker(agentName, slot, error);\n });\n return slot;\n }\n\n private handleMessage(slot: WorkerSlot, message: ScanRefreshWorkerMessage): void {\n const pending = slot.pending.get(message.requestId);\n if (!pending) return;\n if (message.type === \"progress\") {\n pending.onProgress?.(message.progress);\n return;\n }\n if (message.type === \"checkpoint\") {\n pending.onCheckpoint?.(message.checkpoint);\n return;\n }\n\n slot.pending.delete(message.requestId);\n if (message.type === \"error\") {\n pending.reject(new Error(message.error));\n return;\n }\n const changedIds = message.changes.map(({ session }) => session.id);\n const replacedSessionIds = [...changedIds, ...message.removedSessionIds];\n const removedMetaIds = [...message.removedSessionIds, ...message.removedMetaIds];\n try {\n pending.resolve({\n sessions: applySessionChanges(\n pending.payload.previousSessions,\n message.changes,\n message.removedSessionIds,\n ),\n meta: applyMetaChanges(pending.payload.meta, message.meta, removedMetaIds),\n changedIds: pending.payload.sourceSync ? replacedSessionIds : undefined,\n });\n } catch (error) {\n pending.reject(error instanceof Error ? error : new Error(String(error)));\n }\n }\n\n private closeWorker(agentName: string, slot: WorkerSlot, error: Error): void {\n if (slot.closed) return;\n slot.closed = true;\n if (this.workers.get(agentName) === slot) this.workers.delete(agentName);\n for (const pending of slot.pending.values()) pending.reject(error);\n slot.pending.clear();\n }\n}\n","import { consola } from \"consola\";\nimport type { BaseAgent } from \"@codesesh/core\";\nimport { VERSION } from \"./version.js\";\n\nexport function printScanResults(agents: BaseAgent[]): void {\n consola.log(\"\");\n consola.box({\n title: \"CodeSesh\",\n message: `v${VERSION} • local session browser`,\n style: {\n padding: 1,\n borderColor: \"cyan\",\n },\n });\n consola.log(\"\");\n consola.info(\n `Indexing ${agents.map((agent) => agent.displayName).join(\", \")} sessions in the background.`,\n );\n consola.info(\"The Web UI will update automatically as sessions are discovered.\");\n consola.log(\"\");\n}\n","import { readFileSync } from \"node:fs\";\nimport { resolve, dirname } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\nconst pkg = JSON.parse(readFileSync(resolve(__dirname, \"../package.json\"), \"utf-8\"));\n\nexport const VERSION = pkg.version;\n","/**\n * Shape of `--json`: an index of what exists, not an archive of what was said.\n *\n * Sessions are reported as heads — metadata only. Messages, tool calls,\n * reasoning and file activity stay in each agent's own data directory, so this\n * output is deliberately not a backup, and must not quietly grow into one.\n */\nimport {\n filterSessionTreeByActivityWindow,\n getAgentInfoMap,\n type LiveSnapshot,\n type SessionHead,\n} from \"@codesesh/core\";\n\nexport interface SessionIndexAgent {\n name: string;\n displayName: string;\n count: number;\n available: boolean;\n}\n\nexport interface SessionIndexOutput {\n agents: SessionIndexAgent[];\n sessions: SessionHead[];\n}\n\nexport interface SessionIndexWindow {\n from?: number;\n to?: number;\n}\n\nexport function buildSessionIndexOutput(\n snapshot: Pick<LiveSnapshot, \"sessions\" | \"byAgent\">,\n window: SessionIndexWindow = {},\n): SessionIndexOutput {\n // Keep --days/--from/--to meaningful for the JSON output too.\n const sessions = filterSessionTreeByActivityWindow(snapshot.sessions, window.from, window.to);\n\n const agents = getAgentInfoMap(\n Object.fromEntries(\n Object.entries(snapshot.byAgent).map(([name, list]) => [\n name,\n filterSessionTreeByActivityWindow(list, window.from, window.to).length,\n ]),\n ),\n ).map(({ name, displayName, count }) => ({\n name,\n displayName,\n count,\n available: count > 0,\n }));\n\n return { agents, sessions };\n}\n","import type { ScanOptions } from \"@codesesh/core\";\nimport { sessionRoutePath } from \"@codesesh/core/contract\";\nimport { resolveTimeWindow, type TimeWindow } from \"./time-window-resolution.js\";\n\nexport interface TargetSession {\n agent: string;\n sessionId: string;\n}\n\ninterface CliRuntimePlanInput {\n agent?: string;\n cwd?: string;\n from?: string;\n to?: string;\n days?: string;\n jsonOnly: boolean;\n useCache: boolean;\n targetSession: TargetSession | null;\n}\n\ninterface CliRuntimeEnvironment {\n currentWorkingDirectory: string;\n now?: number;\n}\n\nexport interface CliRuntimePlan {\n listWindow: TimeWindow;\n scanOptions: ScanOptions;\n startupScanOptions: Pick<ScanOptions, \"from\" | \"to\">;\n}\n\nexport function parseSessionUri(uri: string): TargetSession | null {\n const match = uri.match(/^([a-z]+):\\/\\/(.+)$/i);\n if (!match) return null;\n return { agent: match[1]!, sessionId: match[2]! };\n}\n\nexport function buildCliRuntimePlan(\n input: CliRuntimePlanInput,\n environment: CliRuntimeEnvironment,\n): CliRuntimePlan {\n const listWindow = resolveTimeWindow({\n mode: \"cli\",\n from: input.from,\n to: input.to,\n days: input.days,\n now: environment.now,\n });\n const cwd = input.cwd === \".\" ? environment.currentWorkingDirectory : input.cwd;\n const agents = input.targetSession\n ? [input.targetSession.agent]\n : input.agent\n ? input.agent.split(\",\").map((agent) => agent.trim())\n : undefined;\n\n return {\n listWindow,\n scanOptions: { agents, cwd, useCache: input.useCache },\n startupScanOptions:\n input.targetSession || input.jsonOnly ? {} : { from: listWindow.from, to: listWindow.to },\n };\n}\n\nexport function resolveStartupUrl(startupUrl: string, targetSession: TargetSession | null): string {\n if (!targetSession) return startupUrl;\n const url = new URL(startupUrl);\n url.pathname = sessionRoutePath({\n agentName: targetSession.agent,\n sessionId: targetSession.sessionId,\n });\n return url.toString();\n}\n\nexport function redactStartupUrl(startupUrl: string): string {\n const url = new URL(startupUrl);\n for (const key of url.searchParams.keys()) {\n url.searchParams.set(key, \"[redacted]\");\n }\n return url.toString();\n}\n","export const DEFAULT_PORT = 4521;\nexport const DEFAULT_PORT_FALLBACK_ATTEMPTS = 20;\n\nexport function parsePort(value: string | undefined): number {\n const port = parseInt(value ?? \"\", 10);\n return Number.isNaN(port) ? DEFAULT_PORT : port;\n}\n\nexport function hasExplicitPortArg(argv: string[]): boolean {\n return argv.some((arg, index) => {\n if (arg === \"--port\" || arg === \"-p\") return index < argv.length - 1;\n return arg.startsWith(\"--port=\") || /^-p\\d+$/.test(arg);\n });\n}\n","/**\n * Lifecycle owner for the background price refresh.\n *\n * The refresh used to be fired and forgotten: no timeout, no cancellation, and\n * it replaced the live prices the moment it returned — so one scan could price\n * its first sessions differently from its last. Here it is bounded, cancellable\n * on shutdown, and published only at a point where no scan is running.\n */\nimport { publishPendingPricing, refreshPricingCache } from \"@codesesh/core\";\nimport { appLogger } from \"./logging.js\";\n\n/** Long enough for a cold network, short enough not to outlive a --json run. */\nconst REFRESH_TIMEOUT_MS = 10_000;\n\nexport interface PricingRefresh {\n /** Makes a completed refresh current. Safe to call more than once. */\n publish(): void;\n /** Cancels an in-flight refresh and waits for it to settle. */\n cancel(): Promise<void>;\n}\n\nexport function startPricingRefresh(timeoutMs = REFRESH_TIMEOUT_MS): PricingRefresh {\n const controller = new AbortController();\n const completion = refreshPricingCache({ signal: controller.signal, timeoutMs }).catch(\n (error: unknown) => {\n appLogger.warn(\"pricing.refresh.error\", { error });\n return false;\n },\n );\n\n return {\n publish() {\n if (publishPendingPricing()) appLogger.info(\"pricing.refresh.published\", {});\n },\n async cancel() {\n controller.abort();\n await completion;\n },\n };\n}\n"],"mappings":"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","names":["Hono","session","__dirname","resolve","Hono","url","existsSync","fileURLToPath","existsSync","fileURLToPath","resolve","existsSync","fileURLToPath","sessions","persisted","existsSync","dirname","resolve","resolve","existsSync","dirname","agents","Worker","SHUTDOWN_ERROR_MESSAGE","applySessionChanges","resolve","Worker","existsSync","fileURLToPath","readFileSync","resolve","dirname","fileURLToPath"]}
|