codesesh 0.15.0 → 0.16.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 +1 -0
- package/dist/chunk-EWC6IODK.js +166 -0
- package/dist/chunk-EWC6IODK.js.map +1 -0
- package/dist/{chunk-NBCLV4CX.js → chunk-MWSJTNOW.js} +682 -356
- package/dist/chunk-MWSJTNOW.js.map +1 -0
- package/dist/{dist-5356XOFP.js → dist-AIDCOQZO.js} +20 -2
- package/dist/index.js +131 -239
- package/dist/index.js.map +1 -1
- package/dist/scan-refresh-worker.js +2 -1
- package/dist/scan-refresh-worker.js.map +1 -1
- package/dist/search-index-worker.js +11 -2
- package/dist/search-index-worker.js.map +1 -1
- package/dist/smart-tag-worker.js +2 -1
- package/dist/smart-tag-worker.js.map +1 -1
- package/dist/web/assets/index-BpmbwB2_.js +113 -0
- package/dist/web/assets/index-Bxe686Vr.css +2 -0
- package/dist/web/assets/{syntax-C_RLNYQn.js → syntax-mZXQuVcd.js} +1 -1
- package/dist/web/assets/vendor-BVE7Fps8.js +41 -0
- package/dist/web/icon/agent/cursor.svg +1 -12
- package/dist/web/icon/agent/pi.svg +2 -2
- package/dist/web/index.html +55 -4
- package/package.json +1 -1
- package/dist/chunk-NBCLV4CX.js.map +0 -1
- package/dist/web/assets/index-B6p64k_Q.js +0 -113
- package/dist/web/assets/index-DiFr4_5-.css +0 -2
- package/dist/web/assets/vendor-CShgXaOi.js +0 -40
- /package/dist/{dist-5356XOFP.js.map → dist-AIDCOQZO.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/logging.ts","../src/time-window-resolution.ts","../src/api/handlers.ts","../src/remote-access.ts","../src/live-scan.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/ports.ts"],"sourcesContent":["import { 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 { resolveTimeWindow } from \"./time-window-resolution.js\";\nimport {\n DEFAULT_PORT,\n DEFAULT_PORT_FALLBACK_ATTEMPTS,\n hasExplicitPortArg,\n parsePort,\n} from \"./ports.js\";\nimport {\n createRegisteredAgents,\n getAgentInfoMap,\n refreshPricingCache,\n type ScanOptions,\n perf,\n} from \"@codesesh/core\";\n\nfunction parseSessionUri(uri: string): { agent: string; sessionId: string } | null {\n const match = uri.match(/^([a-z]+):\\/\\/(.+)$/i);\n if (!match) return null;\n return { agent: match[1]!, sessionId: match[2]! };\n}\n\nfunction appendStartupPath(startupUrl: string, path: string): string {\n const url = new URL(startupUrl);\n url.pathname = path;\n return url.toString();\n}\n\nfunction 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\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 // Resolve cwd filter: '.' => process.cwd()\n let cwdFilter = args.cwd as string | undefined;\n if (cwdFilter === \".\") {\n cwdFilter = process.cwd();\n }\n\n const {\n from: listDefaultFrom,\n to: listDefaultTo,\n days: listDefaultDays,\n } = resolveTimeWindow({\n mode: \"cli\",\n from: args.from as string | undefined,\n to: args.to as string | undefined,\n days: args.days as string | undefined,\n });\n\n const scanOptions: ScanOptions = {\n agents: targetSession\n ? [targetSession.agent]\n : args.agent\n ? (args.agent as string).split(\",\").map((a) => a.trim())\n : undefined,\n cwd: cwdFilter,\n useCache: useCache,\n };\n const startupScanOptions =\n targetSession || jsonOnly ? {} : { from: listDefaultFrom, to: listDefaultTo };\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 = targetSession\n ? appendStartupPath(url, `/${targetSession.agent.toLowerCase()}/${targetSession.sessionId}`)\n : url;\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 { 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\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 {\n appendFileSync,\n existsSync,\n mkdirSync,\n readdirSync,\n renameSync,\n statSync,\n unlinkSync,\n} from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport type { SearchIndexSyncResult } from \"@codesesh/core\";\n\ntype LogLevel = \"debug\" | \"info\" | \"warn\" | \"error\";\n\nconst LEVEL_WEIGHT: Record<LogLevel, number> = {\n debug: 10,\n info: 20,\n warn: 30,\n error: 40,\n};\n\nexport interface LoggerOptions {\n logDir?: string;\n level?: LogLevel;\n maxBytes?: number;\n maxFiles?: number;\n}\n\nfunction parseLevel(value: string | undefined): LogLevel {\n if (value === \"debug\" || value === \"info\" || value === \"warn\" || value === \"error\") {\n return value;\n }\n return \"info\";\n}\n\nfunction parsePositiveInt(value: string | undefined, fallback: number): number {\n const parsed = Number(value);\n return Number.isFinite(parsed) && parsed > 0 ? Math.floor(parsed) : fallback;\n}\n\nfunction getDefaultLogDir(): string {\n const base = process.env.XDG_CACHE_HOME ?? join(homedir(), \".cache\");\n return join(base, \"codesesh\", \"logs\");\n}\n\nfunction toLogValue(value: unknown, depth = 0): unknown {\n if (value == null || typeof value === \"string\" || typeof value === \"number\") return value;\n if (typeof value === \"boolean\") return value;\n if (typeof value === \"bigint\") return value.toString();\n if (value instanceof Error) {\n return {\n name: value.name,\n message: value.message,\n stack: value.stack,\n };\n }\n if (depth >= 4) return \"[truncated]\";\n if (Array.isArray(value)) return value.slice(0, 50).map((item) => toLogValue(item, depth + 1));\n if (typeof value === \"object\") {\n return Object.fromEntries(\n Object.entries(value as Record<string, unknown>).map(([key, item]) => [\n key,\n toLogValue(item, depth + 1),\n ]),\n );\n }\n return String(value);\n}\n\nfunction timestampForFile(date = new Date()): string {\n return date.toISOString().replace(/[:.]/g, \"-\");\n}\n\nexport class AppLogger {\n private readonly logDir: string;\n private readonly level: LogLevel;\n private readonly maxBytes: number;\n private readonly maxFiles: number;\n private readonly currentPath: string;\n private rotationIndex = 0;\n\n constructor(options: LoggerOptions = {}) {\n this.logDir = options.logDir ?? process.env.CODESESH_LOG_DIR ?? getDefaultLogDir();\n this.level = options.level ?? parseLevel(process.env.CODESESH_LOG_LEVEL);\n this.maxBytes =\n options.maxBytes ?? parsePositiveInt(process.env.CODESESH_LOG_MAX_BYTES, 5_000_000);\n this.maxFiles = options.maxFiles ?? parsePositiveInt(process.env.CODESESH_LOG_MAX_FILES, 5);\n this.currentPath = join(this.logDir, \"codesesh.log\");\n }\n\n getLogPath(): string {\n return this.currentPath;\n }\n\n debug(event: string, data: Record<string, unknown> = {}): void {\n this.write(\"debug\", event, data);\n }\n\n info(event: string, data: Record<string, unknown> = {}): void {\n this.write(\"info\", event, data);\n }\n\n warn(event: string, data: Record<string, unknown> = {}): void {\n this.write(\"warn\", event, data);\n }\n\n error(event: string, data: Record<string, unknown> = {}): void {\n this.write(\"error\", event, data);\n }\n\n private write(level: LogLevel, event: string, data: Record<string, unknown>): void {\n if (LEVEL_WEIGHT[level] < LEVEL_WEIGHT[this.level]) return;\n\n try {\n mkdirSync(this.logDir, { recursive: true });\n const line = `${JSON.stringify({\n ts: new Date().toISOString(),\n level,\n event,\n pid: process.pid,\n ...(toLogValue(data) as Record<string, unknown>),\n })}\\n`;\n this.rotateIfNeeded(Buffer.byteLength(line));\n appendFileSync(this.currentPath, line, \"utf8\");\n } catch {}\n }\n\n private rotateIfNeeded(nextBytes: number): void {\n if (!existsSync(this.currentPath)) {\n this.removeExpiredLogs();\n return;\n }\n\n const currentSize = statSync(this.currentPath).size;\n if (currentSize + nextBytes <= this.maxBytes) return;\n\n this.rotationIndex += 1;\n const rotatedPath = join(\n this.logDir,\n `codesesh-${timestampForFile()}-${process.pid}-${this.rotationIndex}.log`,\n );\n renameSync(this.currentPath, rotatedPath);\n this.removeExpiredLogs();\n }\n\n private removeExpiredLogs(): void {\n const rotated = readdirSync(this.logDir)\n .filter((name) => /^codesesh-.+\\.log$/.test(name))\n .map((name) => {\n const path = join(this.logDir, name);\n return { path, mtimeMs: statSync(path).mtimeMs };\n })\n .toSorted((a, b) => b.mtimeMs - a.mtimeMs);\n\n for (const item of rotated.slice(Math.max(0, this.maxFiles - 1))) {\n unlinkSync(item.path);\n }\n }\n}\n\nexport const appLogger = new AppLogger();\n\nexport function logSearchIndexSync(\n context: string,\n result: SearchIndexSyncResult | null,\n data: Record<string, unknown> = {},\n): void {\n if (!result || result.mode !== \"bulk\" || result.rebuildDurationMs == null) {\n return;\n }\n\n appLogger.info(\"search_index.sync\", {\n context,\n agent: result.agentName,\n mode: result.mode,\n sessions: result.sessions,\n changed: result.changed,\n deleted: result.deleted,\n indexed: result.indexed,\n skipped: result.skipped,\n duration_ms: Math.round(result.durationMs),\n rebuild_duration_ms: Math.round(result.rebuildDurationMs),\n ...data,\n });\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","import type { Context } from \"hono\";\nimport type {\n BookmarkRecord,\n ProjectGroup,\n ScanResult,\n SessionData,\n SessionHead,\n SmartTag,\n} from \"@codesesh/core\";\nimport type {\n ApiProjectAgentStat,\n ApiProjectGroup,\n AppConfig,\n ScanStatusEvent,\n} from \"@codesesh/core/contract\";\nimport {\n BookmarkStorageUnavailableError,\n StateStorageUnavailableError,\n createProjectScopeMatcher,\n deleteBookmark,\n getAgentInfoMap,\n classifySessionTags,\n computeIdentity,\n executeSessionSearch,\n extractSessionFileActivity,\n getSmartTagSourceTimestamp,\n importBookmarks,\n isProjectIdentityKind,\n loadCachedSessionData,\n listFileActivity,\n listSessionFileActivity,\n listCachedProjectGroups,\n listBookmarks,\n listSessionAliases,\n mergeSearchQueryOptions,\n deleteSessionAlias,\n upsertSessionAlias,\n realFs,\n upsertBookmark,\n matchesProjectScope as sessionMatchesProjectScope,\n matchesProjectIdentity,\n buildDashboard,\n getSessionAgentName,\n getSessionActivityTime,\n getTotalTokens,\n type DashboardData,\n type DashboardScope,\n type FileActivityKind,\n type FileActivityResult,\n type ProjectIdentityRef,\n type SearchOptions,\n} from \"@codesesh/core\";\nimport { appLogger } from \"../logging.js\";\nimport { resolveTimeWindow, type TimeWindow } from \"../time-window-resolution.js\";\n\nexport interface ScanResultSource {\n getSnapshot(): ScanResult;\n}\n\nexport interface ScanStatusSource {\n getScanStatus(): ScanStatusEvent;\n}\n\nexport type SessionListDefaults = TimeWindow;\n\ninterface ClientLogPayload {\n event?: unknown;\n data?: unknown;\n}\n\ninterface SessionAliasPayload {\n alias?: unknown;\n}\n\ntype SessionAliasMap = Map<string, string>;\n\nfunction getSessionAliasKey(agentKey: string, sessionId: string): string {\n return `${agentKey.toLowerCase()}\\0${sessionId}`;\n}\n\nfunction getSessionAgentKey(session: Pick<SessionHead, \"slug\">): string {\n return session.slug.split(\"/\")[0]?.toLowerCase() ?? \"\";\n}\n\nfunction loadSessionAliasMap(): SessionAliasMap {\n try {\n return new Map(\n listSessionAliases().map((alias) => [\n getSessionAliasKey(alias.agentKey, alias.sessionId),\n alias.alias,\n ]),\n );\n } catch (error) {\n if (!(error instanceof StateStorageUnavailableError)) {\n appLogger.warn(\"api.session_aliases.load_failed\", {\n error: error instanceof Error ? error.message : String(error),\n });\n }\n return new Map();\n }\n}\n\nfunction isStateStorageUnavailable(error: unknown): boolean {\n return error instanceof StateStorageUnavailableError;\n}\n\nfunction withDisplayTitle<T extends { id: string; title: string; display_title?: string }>(\n session: T,\n agentKey: string,\n aliases: SessionAliasMap,\n): T {\n const alias = aliases.get(getSessionAliasKey(agentKey, session.id));\n return alias ? { ...session, display_title: alias } : session;\n}\n\nfunction withBookmarkDisplayTitle(\n bookmark: BookmarkRecord,\n aliases: SessionAliasMap,\n): BookmarkRecord {\n const alias = aliases.get(getSessionAliasKey(bookmark.agentKey, bookmark.sessionId));\n return alias ? { ...bookmark, display_title: alias } : bookmark;\n}\n\nfunction withFileActivityDisplayTitle(\n activity: FileActivityResult,\n aliases: SessionAliasMap,\n): FileActivityResult {\n return {\n ...activity,\n session: withDisplayTitle(activity.session, activity.agent_name, aliases),\n };\n}\n\nfunction findAliasSearchResults(\n query: string,\n options: SearchOptions,\n scanResult: ScanResult,\n aliases: SessionAliasMap,\n) {\n const search = mergeSearchQueryOptions(query, options);\n const needle = search.text.trim().toLowerCase();\n if (!needle || aliases.size === 0) return [];\n\n return executeSessionSearch(\n \"\",\n { ...search.options, limit: Math.max(scanResult.sessions.length, 1) },\n scanResult,\n ).flatMap((result) => {\n const alias = aliases.get(getSessionAliasKey(result.agentName, result.session.id));\n if (!alias || !alias.toLowerCase().includes(needle)) return [];\n return [\n {\n agentName: result.agentName,\n session: withDisplayTitle(result.session, result.agentName, aliases),\n snippet: `Alias · ${result.session.directory}`,\n matchType: \"title\" as const,\n },\n ];\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\nfunction parseBookmarkPayload(value: unknown): Omit<BookmarkRecord, \"bookmarked_at\"> | null {\n if (!isRecord(value)) return null;\n if (\n typeof value.agentKey !== \"string\" ||\n typeof value.sessionId !== \"string\" ||\n typeof value.fullPath !== \"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 agentKey: value.agentKey,\n sessionId: value.sessionId,\n fullPath: value.fullPath,\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 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\nfunction parseNumberParam(value: string | undefined): number | undefined {\n if (value == null || !value.trim()) return undefined;\n const number = Number(value);\n return Number.isFinite(number) ? number : undefined;\n}\n\nfunction searchParams(c: Context): URLSearchParams {\n return new URL(c.req.url ?? \"http://localhost/\", \"http://localhost/\").searchParams;\n}\n\nfunction 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\nfunction parseSmartTags(values: string[]): SmartTag[] | undefined {\n const tags = values\n .map((value) => value.toLowerCase())\n .filter((value): value is SmartTag =>\n [\n \"bugfix\",\n \"refactoring\",\n \"feature-dev\",\n \"testing\",\n \"docs\",\n \"git-ops\",\n \"build-deploy\",\n \"exploration\",\n \"planning\",\n ].includes(value),\n );\n return tags.length > 0 ? [...new Set(tags)] : undefined;\n}\n\nfunction 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: limitValue && limitValue > 0 ? Math.min(limitValue, 100) : 50,\n };\n}\n\nfunction 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\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 getProjectGroupKey(identityKind: string, identityKey: string): string {\n return `${identityKind}:${identityKey}`;\n}\n\nfunction attachProjectMetrics(\n projects: ProjectGroup[],\n sessions: SessionHead[],\n): ApiProjectGroup[] {\n const metrics = new Map<\n string,\n {\n messages: number;\n tokens: number;\n cost: number;\n hasEstimatedCost: boolean;\n agentStats: Map<string, ApiProjectAgentStat>;\n }\n >();\n\n for (const session of sessions) {\n const identity = session.project_identity;\n if (!identity) continue;\n const key = getProjectGroupKey(identity.kind, identity.key);\n let current = metrics.get(key);\n if (!current) {\n current = {\n messages: 0,\n tokens: 0,\n cost: 0,\n hasEstimatedCost: false,\n agentStats: new Map(),\n };\n metrics.set(key, current);\n }\n\n const tokens = getTotalTokens(session.stats);\n const cost = session.stats.total_cost ?? 0;\n current.messages += session.stats.message_count;\n current.tokens += tokens;\n current.cost += cost;\n if (session.stats.cost_source === \"estimated\") current.hasEstimatedCost = true;\n\n const agentName = getSessionAgentName(session);\n const agent = current.agentStats.get(agentName);\n if (agent) {\n agent.sessions += 1;\n agent.messages += session.stats.message_count;\n agent.tokens += tokens;\n agent.cost += cost;\n } else {\n current.agentStats.set(agentName, {\n name: agentName,\n sessions: 1,\n messages: session.stats.message_count,\n tokens,\n cost,\n });\n }\n }\n\n return projects.map((project) => {\n const metric = metrics.get(getProjectGroupKey(project.identityKind, project.identityKey));\n return {\n ...project,\n messages: metric?.messages ?? 0,\n tokens: metric?.tokens ?? 0,\n cost: metric?.cost ?? 0,\n cost_source:\n metric && metric.cost > 0\n ? metric.hasEstimatedCost\n ? \"estimated\"\n : \"recorded\"\n : undefined,\n agentStats: [...(metric?.agentStats.values() ?? [])].sort((a, b) => b.sessions - a.sessions),\n };\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 counts = Object.fromEntries(\n Object.entries(scanResult.byAgent).map(([agentName, sessions]) => [\n agentName,\n filterSessionsByActivityWindow(sessions, from, to).length,\n ]),\n );\n return c.json(getAgentInfoMap(counts));\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 sessions = filterSessionsByActivityWindow(scanResult.sessions, from, to);\n return c.json({\n projects: attachProjectMetrics(listCachedProjectGroups(sessions), sessions),\n });\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 = loadSessionAliasMap();\n if (q) {\n sessions = sessions.filter((session) => {\n const alias = aliases.get(getSessionAliasKey(getSessionAgentKey(session), session.id));\n return session.title.toLowerCase().includes(q) || alias?.toLowerCase().includes(q);\n });\n }\n return c.json({\n sessions: sessions.map((session) =>\n withDisplayTitle(session, getSessionAgentKey(session), aliases),\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 = loadSessionAliasMap();\n const results = executeSessionSearch(query, searchOptions, scanResult).map((result) => ({\n ...result,\n session: withDisplayTitle(result.session, result.agentName, aliases),\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.agentName}\\0${result.session.id}`, result);\n }\n return c.json({ results: [...deduped.values()].slice(0, searchOptions.limit ?? 50) });\n}\n\nfunction 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\nfunction optionalQueryValue(value: string | undefined): string | undefined {\n const normalized = value?.trim();\n return normalized ? normalized : undefined;\n}\n\nfunction 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 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 = loadSessionAliasMap();\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) => withFileActivityDisplayTitle(activity, aliases)),\n });\n}\n\nexport async function handleGetSessionData(c: Context, scanSource: ScanResultSource) {\n const startedAt = performance.now();\n const scanResult = scanSource.getSnapshot();\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 const agent = scanResult.agents.find((a) => a.name === agentName);\n\n if (!agent) {\n return c.json({ error: `Unknown agent: ${agentName}` }, 404);\n }\n\n try {\n const head = scanResult.byAgent[agentName]?.find((item) => item.id === sessionId);\n const loadStartedAt = performance.now();\n const cachedData = loadCachedSessionData(agentName, sessionId);\n const cachedMessageCount = cachedData?.stats.message_count ?? 0;\n const cacheHasExpectedMessages =\n cachedData !== null && (cachedData.messages.length > 0 || cachedMessageCount === 0);\n const data: SessionData | null = cacheHasExpectedMessages\n ? cachedData\n : head\n ? agent.getSessionData(sessionId)\n : null;\n const loadDuration = performance.now() - loadStartedAt;\n if (!data) {\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 const tagStartedAt = performance.now();\n const smartTags = data.smart_tags ?? classifySessionTags(data);\n const tagDuration = performance.now() - tagStartedAt;\n const projectIdentity =\n data.project_identity ?? head?.project_identity ?? computeIdentity(data.directory, realFs);\n const fileActivity =\n data.file_activity ??\n (cacheHasExpectedMessages && cachedData\n ? listSessionFileActivity(agentName, sessionId)\n : extractSessionFileActivity(agentName, sessionId, projectIdentity.key, data.messages));\n appLogger.info(\"api.session_data\", {\n agent: agentName,\n session_id: sessionId,\n messages: data.messages.length,\n load_duration_ms: Math.round(loadDuration),\n tag_duration_ms: Math.round(tagDuration),\n duration_ms: Math.round(performance.now() - startedAt),\n });\n const aliases = loadSessionAliasMap();\n return c.json({\n ...withDisplayTitle(data, agentName, aliases),\n project_identity: projectIdentity,\n smart_tags: smartTags,\n smart_tags_source_updated_at: getSmartTagSourceTimestamp(data),\n file_activity: fileActivity,\n });\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 try {\n const aliases = loadSessionAliasMap();\n return c.json({\n bookmarks: listBookmarks().map((bookmark) => withBookmarkDisplayTitle(bookmark, aliases)),\n storageAvailable: true,\n });\n } catch (error) {\n if (error instanceof BookmarkStorageUnavailableError) {\n return c.json({ bookmarks: [], storageAvailable: false });\n }\n throw error;\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 try {\n return c.json({ bookmark: upsertBookmark(payload), storageAvailable: true });\n } catch (error) {\n if (error instanceof BookmarkStorageUnavailableError) {\n return c.json({ error: \"Bookmark storage is unavailable\" }, 503);\n }\n throw error;\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 try {\n return c.json({ bookmarks: importBookmarks(bookmarks), storageAvailable: true });\n } catch (error) {\n if (error instanceof BookmarkStorageUnavailableError) {\n return c.json({ error: \"Bookmark storage is unavailable\" }, 503);\n }\n throw error;\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 try {\n deleteBookmark(agentKey, sessionId);\n return c.json({ ok: true, storageAvailable: true });\n } catch (error) {\n if (error instanceof BookmarkStorageUnavailableError) {\n return c.json({ error: \"Bookmark storage is unavailable\" }, 503);\n }\n throw error;\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 if (!agentKey || !sessionId || typeof payload?.alias !== \"string\") {\n return c.json({ error: \"Invalid session alias payload\" }, 400);\n }\n\n try {\n return c.json({ alias: upsertSessionAlias(agentKey, sessionId, payload.alias) });\n } catch (error) {\n if (error instanceof TypeError) {\n return c.json({ error: \"Session alias must be non-empty and at most 160 characters\" }, 400);\n }\n if (isStateStorageUnavailable(error)) {\n return c.json({ error: \"Session alias storage is unavailable\" }, 503);\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 try {\n deleteSessionAlias(agentKey, sessionId);\n return c.json({ ok: true });\n } catch (error) {\n if (isStateStorageUnavailable(error)) {\n return c.json({ error: \"Session alias storage is unavailable\" }, 503);\n }\n throw error;\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 agentInfo = getAgentInfoMap({});\n const agentInfoMap = new Map(agentInfo.map((a) => [a.name, a]));\n\n const aggregate = buildDashboard(scanResult.sessions, {\n byAgentNames: Object.keys(scanResult.byAgent),\n scope,\n from,\n to,\n agentInfoMap,\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 = loadSessionAliasMap();\n return c.json({\n ...data,\n recentSessions: data.recentSessions.map((session) =>\n withDisplayTitle(session, session.agentName, aliases),\n ),\n recentFileActivities: data.recentFileActivities.map((activity) =>\n withFileActivityDisplayTitle(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 sortSessions,\n type BaseAgent,\n type ScanOptions,\n type ScanResult,\n type SessionHead,\n} from \"@codesesh/core\";\nimport type {\n AgentScanStatus,\n BackfillStatus,\n ScanStatusEvent,\n SessionsUpdatedEvent,\n} from \"@codesesh/core/contract\";\nimport { AgentSyncEngine, type AgentSessionsChanged } from \"./agent-sync-engine.js\";\nimport { appLogger } from \"./logging.js\";\nimport { SessionWatcher, resolveAgentWatchTargets } from \"./session-watcher.js\";\nimport { ThreadWorkerRunner, type WorkerRunner } from \"./worker-runner.js\";\n\nexport { resolveAgentWatchTargets };\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, { agentName: string; session: SessionHead }>();\n const removedSessionRefs = new Map<string, { agentName: string; sessionId: string }>();\n const sessionKey = (agentName: string, sessionId: string) => `${agentName}\\0${sessionId}`;\n const addChanged = (item: { agentName: string; session: SessionHead }) => {\n const key = sessionKey(item.agentName, item.session.id);\n removedSessionRefs.delete(key);\n changedSessionHeads.set(key, item);\n };\n const addRemoved = (item: { agentName: string; sessionId: string }) => {\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 agents: BaseAgent[] = [];\n private byAgent: Record<string, SessionHead[]> = {};\n private sessions: SessionHead[] = [];\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 snapshot: () => this.getSnapshot(),\n startupScanOptions: this.startupScanOptions,\n workerRunner,\n });\n this.syncEngine.subscribeSessionsChanged((change) => this.applySessionsChanged(change));\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.applyScanResult(initialResult);\n this.syncEngine.initialize(initialResult.cacheTimestamps);\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: this.sessions.length,\n agents: Object.fromEntries(\n Object.entries(this.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(this.agents.map((agent) => agent.name));\n }\n\n startBackgroundRefresh(): void {\n this.syncEngine.startBackgroundRefresh();\n }\n\n getSnapshot(): ScanResult {\n return { sessions: this.sessions, byAgent: this.byAgent, agents: this.agents };\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 applySessionsChanged(change: AgentSessionsChanged): void {\n this.byAgent[change.agentName] = sortSessions(change.sessions);\n this.rebuildSessions();\n if (!change.event) return;\n change.event.totalSessions = this.sessions.length;\n this.emit(change.event);\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 rebuildSessions(): void {\n this.sessions = sortSessions(Object.values(this.byAgent).flat());\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 applyScanResult(result: ScanResult): void {\n const agentMap = new Map<string, BaseAgent>();\n const allowedAgents = this.getAllowedAgents();\n for (const agent of result.agents) agentMap.set(agent.name, agent);\n for (const agent of createRegisteredAgents()) {\n if (!agentMap.has(agent.name)) agentMap.set(agent.name, agent);\n }\n this.agents = [...agentMap.values()].filter(\n (agent) => !allowedAgents || allowedAgents.has(agent.name.toLowerCase()),\n );\n this.byAgent = Object.fromEntries(\n this.agents.map((agent) => [agent.name, sortSessions(result.byAgent[agent.name] ?? [])]),\n );\n this.rebuildSessions();\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 { 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 private hasCheckedFtsIntegrity = 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 skipFtsIntegrityCheck: this.hasCheckedFtsIntegrity,\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.hasCheckedFtsIntegrity = true;\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 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\n return this.set({\n ...this.status,\n active: isActive,\n phase: isActive ? \"scanning\" : \"idle\",\n pendingAgents,\n scanningAgents,\n completedAgents,\n agentStatuses: {\n ...this.status.agentStatuses,\n [agentName]: {\n agentName,\n status: \"complete\",\n total,\n processed: total,\n sessions: sessionCount ?? previousStatus?.sessions ?? 0,\n startedAt: previousStatus?.startedAt,\n updatedAt: now,\n completedAt: now,\n },\n },\n updatedAt: now,\n completedAt: isActive ? undefined : now,\n });\n }\n\n finishBatch(): ScanStatusEvent {\n const now = Date.now();\n return this.set({\n ...this.status,\n active: false,\n phase: \"idle\",\n pendingAgents: [],\n scanningAgents: [],\n agentStatuses: Object.fromEntries(\n Object.entries(this.status.agentStatuses).map(([agentName, status]) => [\n agentName,\n { ...status, status: \"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 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 ScanResult,\n type SessionHead,\n type SessionHeadChange,\n} from \"@codesesh/core\";\nimport type {\n BackfillStatus,\n ScanStatusEvent,\n SessionsUpdatedEvent,\n} from \"@codesesh/core/contract\";\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 = \"committed\" | \"failed\" | \"skipped\" | \"unchanged\";\n\nexport interface AgentSessionsChanged {\n agentName: string;\n sessions: SessionHead[];\n event: SessionsUpdatedEvent | null;\n}\n\nexport interface AgentSyncEngineOptions {\n snapshot: () => ScanResult;\n startupScanOptions?: Pick<ScanOptions, \"from\" | \"to\">;\n workerRunner: WorkerRunner;\n}\n\ntype SessionsChangedListener = (change: AgentSessionsChanged) => void;\ntype StatusChangedListener = (event: ScanStatusEvent) => void;\ntype AgentOperationKind = \"backfill\" | \"refresh\";\ntype CachedSessions = NonNullable<ReturnType<typeof loadCachedSessions>>;\n\ninterface AgentRefreshState {\n timer: NodeJS.Timeout | null;\n timerDeadline: number;\n isRunning: boolean;\n hasPendingRerun: boolean;\n lastRefreshAt: number;\n lastRefreshDurationMs: number;\n pendingPathCount: number;\n}\n\ninterface AgentOperationLifecycle {\n agentName: string;\n kind: AgentOperationKind;\n generation: number;\n startedAt: number;\n}\n\ninterface SessionRefreshDiff {\n event: SessionsUpdatedEvent | null;\n changedSessions: SessionHeadChange[];\n removedSessionIds: string[];\n}\n\ninterface RefreshStrategyResult {\n status: \"continue\" | \"unchanged\";\n nextSessions: SessionHead[];\n fullScanSessions: SessionHead[] | null;\n preciseChangedIds: string[] | null;\n usedIncrementalScan: boolean;\n persistenceDiff: Pick<SessionRefreshDiff, \"changedSessions\" | \"removedSessionIds\"> | null;\n checkDuration: number;\n scanDuration: number;\n}\n\nconst REFRESH_DEBOUNCE_MS = 200;\nconst EMPTY_AGENT_REFRESH_DEBOUNCE_MS = 30_000;\nconst PENDING_REFRESH_DELAY_MS = 100;\nconst MAX_ADAPTIVE_REFRESH_DELAY_MS = 30_000;\nconst ADAPTIVE_REFRESH_DELAY_MULTIPLIER = 4;\nconst SEARCH_INDEX_BULK_PENDING_PATH_THRESHOLD = 100;\nconst BACKFILL_INTERVAL_MS = 24 * 60 * 60 * 1000;\n\nfunction buildRefreshDiff(\n agentName: string,\n previousSessions: SessionHead[],\n nextSessions: SessionHead[],\n candidateChangedIds: string[] = [],\n): SessionRefreshDiff {\n const { changes, removedSessionIds, counts } = computeSessionDiff(\n previousSessions,\n nextSessions,\n candidateChangedIds,\n sessionSignature,\n );\n if (counts.new === 0 && counts.updated === 0 && counts.removed === 0) {\n return { event: null, changedSessions: changes, removedSessionIds };\n }\n return {\n changedSessions: changes,\n removedSessionIds,\n event: {\n type: \"sessions-updated\",\n changedAgents: [agentName],\n newSessions: counts.new,\n updatedSessions: counts.updated,\n removedSessions: counts.removed,\n totalSessions: nextSessions.length,\n timestamp: Date.now(),\n changedSessionHeads: changes.map(({ session }) => ({ agentName, session })),\n removedSessionRefs: removedSessionIds.map((sessionId) => ({ agentName, sessionId })),\n },\n };\n}\n\nfunction restoreAgentCacheMeta(agent: BaseAgent, cached: CachedSessions): void {\n agent.setSessionMetaMap(new Map(Object.entries(cached.meta)));\n}\n\nexport class AgentSyncEngine {\n private refreshStates = new Map<string, AgentRefreshState>();\n private operationGenerations = new Map<string, number>();\n private operationTails = new Map<string, Promise<void>>();\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 backgroundRefreshTimer: NodeJS.Timeout | null = null;\n private isShuttingDown = false;\n\n constructor(private readonly options: AgentSyncEngineOptions) {}\n\n initialize(cacheTimestamps: Record<string, number> = {}): void {\n for (const agent of this.options.snapshot().agents) {\n this.state(agent.name).lastRefreshAt = cacheTimestamps[agent.name] ?? Date.now();\n }\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 await this.searchIndexJobs.enqueue(\n \"scan.initial\",\n this.buildFullSearchIndexJobs(\"scan.initial\"),\n );\n }\n\n handleAgentsChanged(agentNames: Iterable<string>): void {\n const snapshot = this.options.snapshot();\n for (const agentName of agentNames) {\n this.state(agentName).pendingPathCount += 1;\n const delayMs =\n (snapshot.byAgent[agentName]?.length ?? 0) === 0\n ? EMPTY_AGENT_REFRESH_DEBOUNCE_MS\n : REFRESH_DEBOUNCE_MS;\n this.scheduleRefresh(agentName, delayMs);\n }\n }\n\n startBackgroundRefresh(): void {\n if (this.backgroundRefreshTimer) return;\n const agentNames = this.options.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.scheduleRefresh(agentName, 0);\n if (agentNames.length === 0) this.finishScanBatch();\n }, 0);\n }\n\n async refresh(agentName: string): Promise<void> {\n await this.runCoalescedRefresh(agentName);\n }\n\n async shutdown(): Promise<void> {\n this.isShuttingDown = true;\n const activeOperations = {\n agent_operations: this.operationTails.size,\n refreshes: [...this.refreshStates.values()].filter((state) => state.isRunning).length,\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 for (const state of this.refreshStates.values()) {\n if (!state.timer) continue;\n clearTimeout(state.timer);\n state.timer = null;\n state.timerDeadline = 0;\n }\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 Promise.allSettled(this.operationTails.values());\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.options.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.options.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 finishAgentScan(agentName: string): void {\n const count = this.options.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 scheduleRefresh(agentName: string, delayMs: number): void {\n if (this.isShuttingDown) 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 appLogger.debug(\"scan.refresh.schedule\", { agent: agentName, delay_ms: effectiveDelayMs });\n state.timerDeadline = deadline;\n state.timer = setTimeout(() => {\n state.timer = null;\n void this.runCoalescedRefresh(agentName);\n }, effectiveDelayMs);\n }\n\n private async runCoalescedRefresh(agentName: string): Promise<void> {\n const state = this.state(agentName);\n if (state.isRunning) {\n appLogger.debug(\"scan.refresh.pending\", { agent: agentName });\n state.hasPendingRerun = true;\n return;\n }\n state.isRunning = true;\n try {\n await this.serialize(agentName, \"refresh\", () => this.performRefresh(agentName));\n } finally {\n state.isRunning = false;\n if (state.hasPendingRerun && !this.isShuttingDown) {\n state.hasPendingRerun = false;\n this.scheduleRefresh(agentName, PENDING_REFRESH_DELAY_MS);\n }\n }\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 state = this.state(agentName);\n const pendingPathCount = state.pendingPathCount;\n state.pendingPathCount = 0;\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.options.snapshot().byAgent[agentName] ?? [];\n const cached = loadCachedSessions(agentName);\n const refreshBaseline = cached?.sessions ?? previousSessions;\n const cacheTimestamp = cached?.timestamp ?? state.lastRefreshAt;\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 diffStartedAt = performance.now();\n const diff = buildRefreshDiff(\n agentName,\n previousSessions,\n nextSessions,\n strategyResult.preciseChangedIds ?? [],\n );\n const diffDuration = performance.now() - diffStartedAt;\n const searchIndexOptions =\n pendingPathCount >= SEARCH_INDEX_BULK_PENDING_PATH_THRESHOLD ? { isBulk: true } : undefined;\n const persistentChanges =\n strategyResult.persistenceDiff?.changedSessions ?? diff.changedSessions;\n const persistentRemovedSessionIds =\n strategyResult.persistenceDiff?.removedSessionIds ?? diff.removedSessionIds;\n const changedSessionIds = strategyResult.usedIncrementalScan\n ? new Set(persistentChanges.map(({ session }) => session.id))\n : undefined;\n const persistStartedAt = performance.now();\n const persistentJob: SearchIndexWorkerJob | null = strategyResult.usedIncrementalScan\n ? {\n kind: \"changes\",\n context: \"scan.refresh\",\n agentName,\n changes: persistentChanges,\n removedSessionIds: persistentRemovedSessionIds,\n meta: buildAgentCacheMeta(agent, changedSessionIds),\n ...(searchIndexOptions ? { searchIndexOptions } : {}),\n }\n : strategyResult.fullScanSessions\n ? {\n kind: \"full\",\n context: \"scan.refresh\",\n agentName,\n sessions: strategyResult.fullScanSessions,\n meta: buildAgentCacheMeta(agent),\n saveCache: true,\n ...(searchIndexOptions ? { searchIndexOptions } : {}),\n }\n : null;\n if (persistentJob) {\n const persist = this.searchIndexJobs.enqueue(\"scan.refresh\", [persistentJob]);\n if (!isInitialized && persistentJob.kind === \"full\") {\n await persist;\n } else {\n void persist.catch((error) => {\n appLogger.error(\"scan.refresh.persist.error\", { agent: agentName, error });\n console.error(`[${agentName}] Session persistence failed:`, error);\n });\n }\n }\n const persistDuration = performance.now() - persistStartedAt;\n logSearchIndexSync(\"scan.refresh\", null, { pending_paths: pendingPathCount });\n this.emitSessionsChanged({ agentName, sessions: nextSessions, event: diff.event });\n\n const totalDurationMs = performance.now() - startedAt;\n state.lastRefreshDurationMs = totalDurationMs;\n appLogger.info(\"scan.refresh.done\", {\n agent: agentName,\n duration_ms: Math.round(totalDurationMs),\n sessions: nextSessions.length,\n new_sessions: diff.event?.newSessions ?? 0,\n updated_sessions: diff.event?.updatedSessions ?? 0,\n removed_sessions: diff.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(diffDuration),\n persist_ms: Math.round(persistDuration),\n search_index_ms: 0,\n persistent_index_worker_job: persistentJob?.kind,\n persistent_index_skipped: !persistentJob || undefined,\n });\n return \"committed\";\n }\n\n private refreshUnavailableAgent(agentName: string): RefreshStrategyResult {\n this.state(agentName).lastRefreshAt = 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.state(agent.name).lastRefreshAt = 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 = buildRefreshDiff(\n agent.name,\n cached.sessions,\n sessions,\n preciseChangedIds,\n );\n this.state(agent.name).lastRefreshAt = Date.now();\n if (preciseChangedIds.length === 0) this.logUnchangedRefresh(agent.name, refreshStartedAt);\n return this.refreshStrategyResult(sessions, {\n preciseChangedIds,\n usedIncrementalScan: true,\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.state(agent.name).lastRefreshAt = 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 const sessions = attachMissingProjectIdentities(\n await Promise.resolve(agent.incrementalScan(baseline, checkResult.changedIds ?? [])),\n );\n return this.refreshStrategyResult(sessions, {\n preciseChangedIds,\n usedIncrementalScan: Array.isArray(checkResult.changedIds),\n persistenceDiff: buildRefreshDiff(agent.name, 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.state(agent.name).lastRefreshAt = 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 usedIncrementalScan: false,\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.serialize(agentName, \"backfill\", () => this.performBackfill(agentName)).then(\n (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\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.options.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 const diff = buildRefreshDiff(\n agentName,\n snapshot.byAgent[agentName] ?? [],\n fullSessions,\n result.changedIds ?? [],\n );\n await this.searchIndexJobs.enqueue(\"scan.backfill\", [\n {\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 this.emitSessionsChanged({ agentName, sessions: fullSessions, event: diff.event });\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 serialize(\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.isShuttingDown) 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 private state(agentName: string): AgentRefreshState {\n const existing = this.refreshStates.get(agentName);\n if (existing) return existing;\n const state: AgentRefreshState = {\n timer: null,\n timerDeadline: 0,\n isRunning: false,\n hasPendingRerun: false,\n lastRefreshAt: 0,\n lastRefreshDurationMs: 0,\n pendingPathCount: 0,\n };\n this.refreshStates.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 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.options.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 findAgent(agentName: string): BaseAgent | undefined {\n return this.options.snapshot().agents.find((agent) => agent.name === 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 names, 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 { getCursorDataPath, resolveProviderRoots } from \"@codesesh/core\";\nimport { appLogger } from \"./logging.js\";\n\nconst WRITE_STABILITY_THRESHOLD_MS = 250;\nconst WRITE_STABILITY_POLL_MS = 100;\n\nexport interface WatchTarget {\n path: string;\n root?: string;\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 function resolveAgentWatchTargets(agentName: string): WatchTarget[] {\n const roots = resolveProviderRoots();\n const cursorDataPath = getCursorDataPath();\n\n switch (agentName) {\n case \"claudecode\":\n return [\n { root: roots.claudeRoot, path: join(roots.claudeRoot, \"projects\") },\n { path: \"data/claudecode\" },\n ];\n case \"codex\":\n return [\n { path: join(roots.codexRoot, \"sessions\") },\n { path: join(roots.codexRoot, \"session_index.jsonl\") },\n ];\n case \"pi\":\n return [\n { root: roots.piRoot, path: join(roots.piRoot, \"agent\", \"sessions\") },\n { root: \"data/pi\", path: \"data/pi\" },\n ];\n case \"cursor\":\n return cursorDataPath\n ? [\n {\n root: cursorDataPath,\n path: join(cursorDataPath, \"globalStorage\", \"state.vscdb\"),\n },\n { root: cursorDataPath, path: join(cursorDataPath, \"workspaceStorage\") },\n ]\n : [];\n case \"kimi\":\n return [\n { root: roots.kimiRoot, path: join(roots.kimiRoot, \"sessions\") },\n { path: \"data/kimi\" },\n ];\n case \"opencode\":\n return [\n { root: roots.opencodeRoot, path: join(roots.opencodeRoot, \"opencode.db\") },\n { root: \"data/opencode\", path: \"data/opencode/opencode.db\" },\n ];\n case \"zcode\":\n return roots.zcodeRoot\n ? [{ root: roots.zcodeRoot, path: join(roots.zcodeRoot, \"cli\", \"db\", \"db.sqlite\") }]\n : [];\n default:\n return [];\n }\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 given agent names' data directories. */\n start(agentNames: string[]): void {\n const scopesByRoot = new Map<string, WatchScope[]>();\n\n for (const agentName of agentNames) {\n const watchTargets = resolveAgentWatchTargets(agentName);\n\n if (watchTargets.length === 0) {\n appLogger.debug(\"watch.skip\", { agent: agentName });\n continue;\n }\n\n for (const target of watchTargets) {\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 === agentName && scope.targetPath === targetPath)\n ) {\n scopes.push({ agentName, 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 { AgentScanProgress, ScanOptions, SessionCacheMeta, SessionHead } from \"@codesesh/core\";\nimport { appLogger } from \"./logging.js\";\nimport type { ScanRefreshWorkerMessage } 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\nexport class ThreadWorkerRunner implements WorkerRunner {\n private workers = new Set<Worker>();\n\n constructor(private readonly workerUrl: URL) {}\n\n get activeCount(): number {\n return this.workers.size;\n }\n\n run(agentName: string, payload: WorkerPayload): Promise<WorkerResult> {\n return new Promise((resolve, reject) => {\n const worker = new Worker(this.workerUrl, {\n workerData: {\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 worker.unref();\n this.workers.add(worker);\n\n let settled = false;\n const finish = (callback: () => void, terminate = true) => {\n if (settled) return;\n settled = true;\n this.workers.delete(worker);\n if (terminate) void worker.terminate();\n callback();\n };\n\n worker.on(\"message\", (message: ScanRefreshWorkerMessage) => {\n if (message.type === \"progress\") {\n payload.onProgress?.(message.progress);\n return;\n }\n if (message.type === \"done\") {\n finish(() =>\n resolve({\n sessions: message.sessions,\n meta: message.meta,\n changedIds: message.changedIds,\n }),\n );\n return;\n }\n finish(() => reject(new Error(message.error)));\n });\n worker.once(\"error\", (error) => {\n finish(() => reject(error));\n });\n worker.once(\"exit\", (code) => {\n if (settled) return;\n appLogger.warn(\"scan.refresh_worker.exit_before_done\", { agent: agentName, code });\n finish(\n () => reject(new Error(`Scan refresh worker exited before completing (code ${code})`)),\n false,\n );\n });\n });\n }\n\n async shutdown(): Promise<void> {\n const workers = [...this.workers];\n await Promise.allSettled(workers.map((worker) => worker.terminate()));\n this.workers.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","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","existsSync","__dirname","existsSync","resolve","Hono","url","existsSync","fileURLToPath","existsSync","fileURLToPath","resolve","existsSync","fileURLToPath","existsSync","readdirSync","statSync","dirname","join","resolve","resolve","existsSync","dirname","statSync","join","readdirSync","Worker","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/handlers.ts","../src/remote-access.ts","../src/live-scan.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","import type { Context } from \"hono\";\nimport type {\n BookmarkRecord,\n ProjectGroup,\n ScanResult,\n SessionCacheMeta,\n SessionData,\n SessionHead,\n SmartTag,\n} from \"@codesesh/core\";\nimport type {\n ApiProjectAgentStat,\n ApiProjectGroup,\n AppConfig,\n ScanStatusEvent,\n SearchResult,\n} from \"@codesesh/core/contract\";\nimport {\n BookmarkStorageUnavailableError,\n StateStorageUnavailableError,\n createProjectScopeMatcher,\n deleteBookmark,\n getAgentInfoMap,\n classifySessionTags,\n computeIdentity,\n executeSessionSearch,\n extractSessionFileActivity,\n getSmartTagSourceTimestamp,\n importBookmarks,\n isProjectIdentityKind,\n loadCachedSessionDataEntry,\n listFileActivity,\n listSessionFileActivity,\n listCachedProjectGroups,\n listBookmarks,\n listSessionAliases,\n matchesSessionSearchFilters,\n mergeSearchQueryOptions,\n deleteSessionAlias,\n upsertSessionAlias,\n realFs,\n upsertBookmark,\n matchesProjectScope as sessionMatchesProjectScope,\n matchesProjectIdentity,\n buildDashboard,\n getSessionAgentName,\n getSessionActivityTime,\n getTotalTokens,\n type DashboardData,\n type DashboardScope,\n type FileActivityKind,\n type FileActivityResult,\n type ProjectIdentityRef,\n type SearchOptions,\n} from \"@codesesh/core\";\nimport { appLogger } from \"../logging.js\";\nimport { resolveTimeWindow, type TimeWindow } from \"../time-window-resolution.js\";\n\nexport interface ScanResultSource {\n getSnapshot(): ScanResult;\n}\n\nexport interface ScanStatusSource {\n getScanStatus(): ScanStatusEvent;\n}\n\nexport type SessionListDefaults = TimeWindow;\n\ninterface ClientLogPayload {\n event?: unknown;\n data?: unknown;\n}\n\nfunction cacheMatchesCurrentSource(\n cachedMeta: SessionCacheMeta | null,\n currentMeta: SessionCacheMeta | undefined,\n) {\n const currentFingerprint = currentMeta?.sourceFingerprint;\n if (typeof currentFingerprint !== \"string\") return true;\n return cachedMeta?.sourceFingerprint === currentFingerprint;\n}\n\ninterface SessionAliasPayload {\n alias?: unknown;\n}\n\ntype SessionAliasMap = Map<string, string>;\n\nfunction getSessionAliasKey(agentKey: string, sessionId: string): string {\n return `${agentKey.toLowerCase()}\\0${sessionId}`;\n}\n\nfunction getSessionAgentKey(session: Pick<SessionHead, \"slug\">): string {\n return session.slug.split(\"/\")[0]?.toLowerCase() ?? \"\";\n}\n\nfunction loadSessionAliasMap(): SessionAliasMap {\n try {\n return new Map(\n listSessionAliases().map((alias) => [\n getSessionAliasKey(alias.agentKey, alias.sessionId),\n alias.alias,\n ]),\n );\n } catch (error) {\n if (!(error instanceof StateStorageUnavailableError)) {\n appLogger.warn(\"api.session_aliases.load_failed\", {\n error: error instanceof Error ? error.message : String(error),\n });\n }\n return new Map();\n }\n}\n\nfunction isStateStorageUnavailable(error: unknown): boolean {\n return error instanceof StateStorageUnavailableError;\n}\n\nfunction withDisplayTitle<T extends { id: string; title: string; display_title?: string }>(\n session: T,\n agentKey: string,\n aliases: SessionAliasMap,\n): T {\n const alias = aliases.get(getSessionAliasKey(agentKey, session.id));\n return alias ? { ...session, display_title: alias } : session;\n}\n\nfunction withBookmarkDisplayTitle(\n bookmark: BookmarkRecord,\n aliases: SessionAliasMap,\n): BookmarkRecord {\n const alias = aliases.get(getSessionAliasKey(bookmark.agentKey, bookmark.sessionId));\n return alias ? { ...bookmark, display_title: alias } : bookmark;\n}\n\nfunction withFileActivityDisplayTitle(\n activity: FileActivityResult,\n aliases: SessionAliasMap,\n): FileActivityResult {\n return {\n ...activity,\n session: withDisplayTitle(activity.session, activity.agent_name, aliases),\n };\n}\n\nfunction findSessionByAliasKey(scanResult: ScanResult, aliasKey: string): SessionHead | undefined {\n const separatorIndex = aliasKey.indexOf(\"\\0\");\n const agentName = aliasKey.slice(0, separatorIndex);\n const sessionId = aliasKey.slice(separatorIndex + 1);\n return scanResult.byAgent[agentName]?.find((session) => session.id === sessionId);\n}\n\n// Alias hits still have to satisfy the same time-window/project/agent\n// filters as the main search (matchesSessionSearchFilters), otherwise an\n// aliased session could appear in results outside its search scope.\nfunction findAliasSearchResults(\n query: string,\n options: SearchOptions,\n scanResult: ScanResult,\n aliases: SessionAliasMap,\n) {\n const search = mergeSearchQueryOptions(query, options);\n const needle = search.text.trim().toLowerCase();\n if (!needle || aliases.size === 0) return [];\n\n const projectScope = search.options.cwd ? createProjectScopeMatcher(search.options.cwd) : null;\n const results: SearchResult[] = [];\n for (const [aliasKey, alias] of aliases) {\n if (!alias.toLowerCase().includes(needle)) continue;\n const session = findSessionByAliasKey(scanResult, aliasKey);\n if (!session) continue;\n const agentName = aliasKey.slice(0, aliasKey.indexOf(\"\\0\"));\n if (!matchesSessionSearchFilters(agentName, session, search.options, projectScope)) continue;\n results.push({\n agentName,\n session: withDisplayTitle(session, agentName, aliases),\n snippet: `Alias · ${session.directory}`,\n matchType: \"title\",\n });\n }\n return results.sort(\n (a, b) => getSessionActivityTime(b.session) - getSessionActivityTime(a.session),\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\nfunction parseBookmarkPayload(value: unknown): Omit<BookmarkRecord, \"bookmarked_at\"> | null {\n if (!isRecord(value)) return null;\n if (\n typeof value.agentKey !== \"string\" ||\n typeof value.sessionId !== \"string\" ||\n typeof value.fullPath !== \"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 agentKey: value.agentKey,\n sessionId: value.sessionId,\n fullPath: value.fullPath,\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 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\nfunction parseNumberParam(value: string | undefined): number | undefined {\n if (value == null || !value.trim()) return undefined;\n const number = Number(value);\n return Number.isFinite(number) ? number : undefined;\n}\n\nfunction searchParams(c: Context): URLSearchParams {\n return new URL(c.req.url ?? \"http://localhost/\", \"http://localhost/\").searchParams;\n}\n\nfunction 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\nfunction parseSmartTags(values: string[]): SmartTag[] | undefined {\n const tags = values\n .map((value) => value.toLowerCase())\n .filter((value): value is SmartTag =>\n [\n \"bugfix\",\n \"refactoring\",\n \"feature-dev\",\n \"testing\",\n \"docs\",\n \"git-ops\",\n \"build-deploy\",\n \"exploration\",\n \"planning\",\n ].includes(value),\n );\n return tags.length > 0 ? [...new Set(tags)] : undefined;\n}\n\nfunction 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: limitValue && limitValue > 0 ? Math.min(limitValue, 100) : 50,\n };\n}\n\nfunction 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\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 getProjectGroupKey(identityKind: string, identityKey: string): string {\n return `${identityKind}:${identityKey}`;\n}\n\nfunction attachProjectMetrics(\n projects: ProjectGroup[],\n sessions: SessionHead[],\n): ApiProjectGroup[] {\n const metrics = new Map<\n string,\n {\n messages: number;\n tokens: number;\n cost: number;\n hasEstimatedCost: boolean;\n agentStats: Map<string, ApiProjectAgentStat>;\n }\n >();\n\n for (const session of sessions) {\n const identity = session.project_identity;\n if (!identity) continue;\n const key = getProjectGroupKey(identity.kind, identity.key);\n let current = metrics.get(key);\n if (!current) {\n current = {\n messages: 0,\n tokens: 0,\n cost: 0,\n hasEstimatedCost: false,\n agentStats: new Map(),\n };\n metrics.set(key, current);\n }\n\n const tokens = getTotalTokens(session.stats);\n const cost = session.stats.total_cost ?? 0;\n current.messages += session.stats.message_count;\n current.tokens += tokens;\n current.cost += cost;\n if (session.stats.cost_source === \"estimated\") current.hasEstimatedCost = true;\n\n const agentName = getSessionAgentName(session);\n const agent = current.agentStats.get(agentName);\n if (agent) {\n agent.sessions += 1;\n agent.messages += session.stats.message_count;\n agent.tokens += tokens;\n agent.cost += cost;\n } else {\n current.agentStats.set(agentName, {\n name: agentName,\n sessions: 1,\n messages: session.stats.message_count,\n tokens,\n cost,\n });\n }\n }\n\n return projects.map((project) => {\n const metric = metrics.get(getProjectGroupKey(project.identityKind, project.identityKey));\n return {\n ...project,\n messages: metric?.messages ?? 0,\n tokens: metric?.tokens ?? 0,\n cost: metric?.cost ?? 0,\n cost_source:\n metric && metric.cost > 0\n ? metric.hasEstimatedCost\n ? \"estimated\"\n : \"recorded\"\n : undefined,\n agentStats: [...(metric?.agentStats.values() ?? [])].sort((a, b) => b.sessions - a.sessions),\n };\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 counts = Object.fromEntries(\n Object.entries(scanResult.byAgent).map(([agentName, sessions]) => [\n agentName,\n filterSessionsByActivityWindow(sessions, from, to).length,\n ]),\n );\n return c.json(getAgentInfoMap(counts));\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 sessions = filterSessionsByActivityWindow(scanResult.sessions, from, to);\n return c.json({\n projects: attachProjectMetrics(listCachedProjectGroups(sessions), sessions),\n });\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 = loadSessionAliasMap();\n if (q) {\n sessions = sessions.filter((session) => {\n const alias = aliases.get(getSessionAliasKey(getSessionAgentKey(session), session.id));\n return session.title.toLowerCase().includes(q) || alias?.toLowerCase().includes(q);\n });\n }\n return c.json({\n sessions: sessions.map((session) =>\n withDisplayTitle(session, getSessionAgentKey(session), aliases),\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 = loadSessionAliasMap();\n const results = executeSessionSearch(query, searchOptions, scanResult).map((result) => ({\n ...result,\n session: withDisplayTitle(result.session, result.agentName, aliases),\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.agentName}\\0${result.session.id}`, result);\n }\n return c.json({ results: [...deduped.values()].slice(0, searchOptions.limit ?? 50) });\n}\n\nfunction 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\nfunction optionalQueryValue(value: string | undefined): string | undefined {\n const normalized = value?.trim();\n return normalized ? normalized : undefined;\n}\n\nfunction 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 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 = loadSessionAliasMap();\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) => withFileActivityDisplayTitle(activity, aliases)),\n });\n}\n\nexport async function handleGetSessionData(c: Context, scanSource: ScanResultSource) {\n const startedAt = performance.now();\n const scanResult = scanSource.getSnapshot();\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 const agent = scanResult.agents.find((a) => a.name === agentName);\n\n if (!agent) {\n return c.json({ error: `Unknown agent: ${agentName}` }, 404);\n }\n\n try {\n const head = scanResult.byAgent[agentName]?.find((item) => item.id === sessionId);\n const loadStartedAt = performance.now();\n const cachedEntry = loadCachedSessionDataEntry(agentName, sessionId);\n const cachedData = cachedEntry?.data ?? null;\n const cachedMessageCount = cachedData?.stats.message_count ?? 0;\n const currentMeta = head ? agent.getSessionMetaMap().get(sessionId) : undefined;\n const cacheHasExpectedMessages =\n cachedData !== null &&\n cacheMatchesCurrentSource(cachedEntry?.meta ?? null, currentMeta) &&\n (cachedData.messages.length > 0 || cachedMessageCount === 0);\n const data: SessionData | null = cacheHasExpectedMessages\n ? cachedData\n : head\n ? agent.getSessionData(sessionId)\n : null;\n const loadDuration = performance.now() - loadStartedAt;\n if (!data) {\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 const tagStartedAt = performance.now();\n const smartTags = data.smart_tags ?? classifySessionTags(data);\n const tagDuration = performance.now() - tagStartedAt;\n const projectIdentity =\n data.project_identity ?? head?.project_identity ?? computeIdentity(data.directory, realFs);\n const fileActivity =\n data.file_activity ??\n (cacheHasExpectedMessages && cachedData\n ? listSessionFileActivity(agentName, sessionId)\n : extractSessionFileActivity(agentName, sessionId, projectIdentity.key, data.messages));\n appLogger.info(\"api.session_data\", {\n agent: agentName,\n session_id: sessionId,\n messages: data.messages.length,\n load_duration_ms: Math.round(loadDuration),\n tag_duration_ms: Math.round(tagDuration),\n duration_ms: Math.round(performance.now() - startedAt),\n });\n const aliases = loadSessionAliasMap();\n return c.json({\n ...withDisplayTitle(data, agentName, aliases),\n project_identity: projectIdentity,\n smart_tags: smartTags,\n smart_tags_source_updated_at: getSmartTagSourceTimestamp(data),\n file_activity: fileActivity,\n });\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 try {\n const aliases = loadSessionAliasMap();\n return c.json({\n bookmarks: listBookmarks().map((bookmark) => withBookmarkDisplayTitle(bookmark, aliases)),\n storageAvailable: true,\n });\n } catch (error) {\n if (error instanceof BookmarkStorageUnavailableError) {\n return c.json({ bookmarks: [], storageAvailable: false });\n }\n throw error;\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 try {\n return c.json({ bookmark: upsertBookmark(payload), storageAvailable: true });\n } catch (error) {\n if (error instanceof BookmarkStorageUnavailableError) {\n return c.json({ error: \"Bookmark storage is unavailable\" }, 503);\n }\n throw error;\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 try {\n return c.json({ bookmarks: importBookmarks(bookmarks), storageAvailable: true });\n } catch (error) {\n if (error instanceof BookmarkStorageUnavailableError) {\n return c.json({ error: \"Bookmark storage is unavailable\" }, 503);\n }\n throw error;\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 try {\n deleteBookmark(agentKey, sessionId);\n return c.json({ ok: true, storageAvailable: true });\n } catch (error) {\n if (error instanceof BookmarkStorageUnavailableError) {\n return c.json({ error: \"Bookmark storage is unavailable\" }, 503);\n }\n throw error;\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 if (!agentKey || !sessionId || typeof payload?.alias !== \"string\") {\n return c.json({ error: \"Invalid session alias payload\" }, 400);\n }\n\n try {\n return c.json({ alias: upsertSessionAlias(agentKey, sessionId, payload.alias) });\n } catch (error) {\n if (error instanceof TypeError) {\n return c.json({ error: \"Session alias must be non-empty and at most 160 characters\" }, 400);\n }\n if (isStateStorageUnavailable(error)) {\n return c.json({ error: \"Session alias storage is unavailable\" }, 503);\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 try {\n deleteSessionAlias(agentKey, sessionId);\n return c.json({ ok: true });\n } catch (error) {\n if (isStateStorageUnavailable(error)) {\n return c.json({ error: \"Session alias storage is unavailable\" }, 503);\n }\n throw error;\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 agentInfo = getAgentInfoMap({});\n const agentInfoMap = new Map(agentInfo.map((a) => [a.name, a]));\n\n const aggregate = buildDashboard(scanResult.sessions, {\n byAgentNames: Object.keys(scanResult.byAgent),\n scope,\n from,\n to,\n agentInfoMap,\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 = loadSessionAliasMap();\n return c.json({\n ...data,\n recentSessions: data.recentSessions.map((session) =>\n withDisplayTitle(session, session.agentName, aliases),\n ),\n recentFileActivities: data.recentFileActivities.map((activity) =>\n withFileActivityDisplayTitle(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 sortSessions,\n type BaseAgent,\n type ScanOptions,\n type ScanResult,\n type SessionHead,\n} from \"@codesesh/core\";\nimport type {\n AgentScanStatus,\n BackfillStatus,\n ScanStatusEvent,\n SessionsUpdatedEvent,\n} from \"@codesesh/core/contract\";\nimport { AgentSyncEngine, type AgentSessionsChanged } from \"./agent-sync-engine.js\";\nimport { appLogger } from \"./logging.js\";\nimport { SessionWatcher, resolveAgentWatchTargets } from \"./session-watcher.js\";\nimport { ThreadWorkerRunner, type WorkerRunner } from \"./worker-runner.js\";\n\nexport { resolveAgentWatchTargets };\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, { agentName: string; session: SessionHead }>();\n const removedSessionRefs = new Map<string, { agentName: string; sessionId: string }>();\n const sessionKey = (agentName: string, sessionId: string) => `${agentName}\\0${sessionId}`;\n const addChanged = (item: { agentName: string; session: SessionHead }) => {\n const key = sessionKey(item.agentName, item.session.id);\n removedSessionRefs.delete(key);\n changedSessionHeads.set(key, item);\n };\n const addRemoved = (item: { agentName: string; sessionId: string }) => {\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 agents: BaseAgent[] = [];\n private byAgent: Record<string, SessionHead[]> = {};\n private sessions: SessionHead[] = [];\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 snapshot: () => this.getSnapshot(),\n startupScanOptions: this.startupScanOptions,\n workerRunner,\n });\n this.syncEngine.subscribeSessionsChanged((change) => this.applySessionsChanged(change));\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.applyScanResult(initialResult);\n this.syncEngine.initialize(initialResult.cacheTimestamps);\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: this.sessions.length,\n agents: Object.fromEntries(\n Object.entries(this.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(this.agents.map((agent) => agent.name));\n }\n\n startBackgroundRefresh(): void {\n this.syncEngine.startBackgroundRefresh();\n }\n\n getSnapshot(): ScanResult {\n return { sessions: this.sessions, byAgent: this.byAgent, agents: this.agents };\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 applySessionsChanged(change: AgentSessionsChanged): void {\n this.byAgent[change.agentName] = sortSessions(change.sessions);\n this.rebuildSessions();\n if (!change.event) return;\n change.event.totalSessions = this.sessions.length;\n this.emit(change.event);\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 rebuildSessions(): void {\n this.sessions = sortSessions(Object.values(this.byAgent).flat());\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 applyScanResult(result: ScanResult): void {\n const agentMap = new Map<string, BaseAgent>();\n const allowedAgents = this.getAllowedAgents();\n for (const agent of result.agents) agentMap.set(agent.name, agent);\n for (const agent of createRegisteredAgents()) {\n if (!agentMap.has(agent.name)) agentMap.set(agent.name, agent);\n }\n this.agents = [...agentMap.values()].filter(\n (agent) => !allowedAgents || allowedAgents.has(agent.name.toLowerCase()),\n );\n this.byAgent = Object.fromEntries(\n this.agents.map((agent) => [agent.name, sortSessions(result.byAgent[agent.name] ?? [])]),\n );\n this.rebuildSessions();\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 { 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 private hasCheckedFtsIntegrity = 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 skipFtsIntegrityCheck: this.hasCheckedFtsIntegrity,\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.hasCheckedFtsIntegrity = true;\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 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\n return this.set({\n ...this.status,\n active: isActive,\n phase: isActive ? \"scanning\" : \"idle\",\n pendingAgents,\n scanningAgents,\n completedAgents,\n agentStatuses: {\n ...this.status.agentStatuses,\n [agentName]: {\n agentName,\n status: \"complete\",\n total,\n processed: total,\n sessions: sessionCount ?? previousStatus?.sessions ?? 0,\n startedAt: previousStatus?.startedAt,\n updatedAt: now,\n completedAt: now,\n },\n },\n updatedAt: now,\n completedAt: isActive ? undefined : now,\n });\n }\n\n finishBatch(): ScanStatusEvent {\n const now = Date.now();\n return this.set({\n ...this.status,\n active: false,\n phase: \"idle\",\n pendingAgents: [],\n scanningAgents: [],\n agentStatuses: Object.fromEntries(\n Object.entries(this.status.agentStatuses).map(([agentName, status]) => [\n agentName,\n { ...status, status: \"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 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 ScanResult,\n type SessionHead,\n type SessionHeadChange,\n} from \"@codesesh/core\";\nimport type {\n BackfillStatus,\n ScanStatusEvent,\n SessionsUpdatedEvent,\n} from \"@codesesh/core/contract\";\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 = \"committed\" | \"failed\" | \"skipped\" | \"unchanged\";\n\nexport interface AgentSessionsChanged {\n agentName: string;\n sessions: SessionHead[];\n event: SessionsUpdatedEvent | null;\n}\n\nexport interface AgentSyncEngineOptions {\n snapshot: () => ScanResult;\n startupScanOptions?: Pick<ScanOptions, \"from\" | \"to\">;\n workerRunner: WorkerRunner;\n}\n\ntype SessionsChangedListener = (change: AgentSessionsChanged) => void;\ntype StatusChangedListener = (event: ScanStatusEvent) => void;\ntype AgentOperationKind = \"backfill\" | \"refresh\";\ntype CachedSessions = NonNullable<ReturnType<typeof loadCachedSessions>>;\n\ninterface AgentRefreshState {\n timer: NodeJS.Timeout | null;\n timerDeadline: number;\n isRunning: boolean;\n hasPendingRerun: boolean;\n lastRefreshAt: number;\n lastRefreshDurationMs: number;\n pendingPathCount: number;\n /**\n * id → sessionSignature, carried across refreshes so unchanged sessions skip\n * re-stringifying. Only ever passed into the runRefresh event-path diff\n * (previousSessions → nextSessions), whose lineage is the in-memory result of\n * the prior event diff. The strategy-path diffs (DB cached.sessions baseline)\n * must NOT share this cache: that baseline can lag an in-flight persist job,\n * and a cache hit there would both mask the self-heal recheck after a failed\n * persist and, if reused this same cycle, make the event-path diff miss a\n * signature-only change (e.g. smart-tag reclassification) whose new signature\n * was already written back by the strategy-path diff.\n */\n signatureCache: Map<string, string>;\n}\n\ninterface AgentOperationLifecycle {\n agentName: string;\n kind: AgentOperationKind;\n generation: number;\n startedAt: number;\n}\n\ninterface SessionRefreshDiff {\n event: SessionsUpdatedEvent | null;\n changedSessions: SessionHeadChange[];\n removedSessionIds: string[];\n}\n\ninterface RefreshStrategyResult {\n status: \"continue\" | \"unchanged\";\n nextSessions: SessionHead[];\n fullScanSessions: SessionHead[] | null;\n preciseChangedIds: string[] | null;\n usedIncrementalScan: boolean;\n persistenceDiff: Pick<SessionRefreshDiff, \"changedSessions\" | \"removedSessionIds\"> | null;\n checkDuration: number;\n scanDuration: number;\n}\n\nconst REFRESH_DEBOUNCE_MS = 200;\nconst EMPTY_AGENT_REFRESH_DEBOUNCE_MS = 30_000;\nconst PENDING_REFRESH_DELAY_MS = 100;\nconst MAX_ADAPTIVE_REFRESH_DELAY_MS = 30_000;\nconst ADAPTIVE_REFRESH_DELAY_MULTIPLIER = 4;\nconst SEARCH_INDEX_BULK_PENDING_PATH_THRESHOLD = 100;\nconst BACKFILL_INTERVAL_MS = 24 * 60 * 60 * 1000;\n\nfunction buildRefreshDiff(\n agentName: string,\n previousSessions: SessionHead[],\n nextSessions: SessionHead[],\n candidateChangedIds: string[] = [],\n signatureCache?: Map<string, string>,\n): SessionRefreshDiff {\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 if (counts.new === 0 && counts.updated === 0 && counts.removed === 0) {\n return { event: null, changedSessions: changes, removedSessionIds };\n }\n return {\n changedSessions: changes,\n removedSessionIds,\n event: {\n type: \"sessions-updated\",\n changedAgents: [agentName],\n newSessions: counts.new,\n updatedSessions: counts.updated,\n removedSessions: counts.removed,\n totalSessions: nextSessions.length,\n timestamp: Date.now(),\n changedSessionHeads: changes.map(({ session }) => ({ agentName, session })),\n removedSessionRefs: removedSessionIds.map((sessionId) => ({ agentName, sessionId })),\n },\n };\n}\n\nfunction restoreAgentCacheMeta(agent: BaseAgent, cached: CachedSessions): void {\n agent.setSessionMetaMap(new Map(Object.entries(cached.meta)));\n}\n\nexport class AgentSyncEngine {\n private refreshStates = new Map<string, AgentRefreshState>();\n private operationGenerations = new Map<string, number>();\n private operationTails = new Map<string, Promise<void>>();\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 backgroundRefreshTimer: NodeJS.Timeout | null = null;\n private isShuttingDown = false;\n\n constructor(private readonly options: AgentSyncEngineOptions) {}\n\n initialize(cacheTimestamps: Record<string, number> = {}): void {\n for (const agent of this.options.snapshot().agents) {\n this.state(agent.name).lastRefreshAt = cacheTimestamps[agent.name] ?? Date.now();\n }\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 await this.searchIndexJobs.enqueue(\n \"scan.initial\",\n this.buildFullSearchIndexJobs(\"scan.initial\"),\n );\n }\n\n handleAgentsChanged(agentNames: Iterable<string>): void {\n const snapshot = this.options.snapshot();\n for (const agentName of agentNames) {\n this.state(agentName).pendingPathCount += 1;\n const delayMs =\n (snapshot.byAgent[agentName]?.length ?? 0) === 0\n ? EMPTY_AGENT_REFRESH_DEBOUNCE_MS\n : REFRESH_DEBOUNCE_MS;\n this.scheduleRefresh(agentName, delayMs);\n }\n }\n\n startBackgroundRefresh(): void {\n if (this.backgroundRefreshTimer) return;\n const agentNames = this.options.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.scheduleRefresh(agentName, 0);\n if (agentNames.length === 0) this.finishScanBatch();\n }, 0);\n }\n\n async refresh(agentName: string): Promise<void> {\n await this.runCoalescedRefresh(agentName);\n }\n\n async shutdown(): Promise<void> {\n this.isShuttingDown = true;\n const activeOperations = {\n agent_operations: this.operationTails.size,\n refreshes: [...this.refreshStates.values()].filter((state) => state.isRunning).length,\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 for (const state of this.refreshStates.values()) {\n if (!state.timer) continue;\n clearTimeout(state.timer);\n state.timer = null;\n state.timerDeadline = 0;\n }\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 Promise.allSettled(this.operationTails.values());\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.options.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.options.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 finishAgentScan(agentName: string): void {\n const count = this.options.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 scheduleRefresh(agentName: string, delayMs: number): void {\n if (this.isShuttingDown) 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 appLogger.debug(\"scan.refresh.schedule\", { agent: agentName, delay_ms: effectiveDelayMs });\n state.timerDeadline = deadline;\n state.timer = setTimeout(() => {\n state.timer = null;\n void this.runCoalescedRefresh(agentName);\n }, effectiveDelayMs);\n }\n\n private async runCoalescedRefresh(agentName: string): Promise<void> {\n const state = this.state(agentName);\n if (state.isRunning) {\n appLogger.debug(\"scan.refresh.pending\", { agent: agentName });\n state.hasPendingRerun = true;\n return;\n }\n state.isRunning = true;\n try {\n await this.serialize(agentName, \"refresh\", () => this.performRefresh(agentName));\n } finally {\n state.isRunning = false;\n if (state.hasPendingRerun && !this.isShuttingDown) {\n state.hasPendingRerun = false;\n this.scheduleRefresh(agentName, PENDING_REFRESH_DELAY_MS);\n }\n }\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 state = this.state(agentName);\n const pendingPathCount = state.pendingPathCount;\n state.pendingPathCount = 0;\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.options.snapshot().byAgent[agentName] ?? [];\n const cached = loadCachedSessions(agentName);\n const refreshBaseline = cached?.sessions ?? previousSessions;\n const cacheTimestamp = cached?.timestamp ?? state.lastRefreshAt;\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 diffStartedAt = performance.now();\n const diff = buildRefreshDiff(\n agentName,\n previousSessions,\n nextSessions,\n strategyResult.preciseChangedIds ?? [],\n state.signatureCache,\n );\n const diffDuration = performance.now() - diffStartedAt;\n const searchIndexOptions =\n pendingPathCount >= SEARCH_INDEX_BULK_PENDING_PATH_THRESHOLD ? { isBulk: true } : undefined;\n const persistentChanges =\n strategyResult.persistenceDiff?.changedSessions ?? diff.changedSessions;\n const persistentRemovedSessionIds =\n strategyResult.persistenceDiff?.removedSessionIds ?? diff.removedSessionIds;\n const changedSessionIds = strategyResult.usedIncrementalScan\n ? new Set(persistentChanges.map(({ session }) => session.id))\n : undefined;\n const persistStartedAt = performance.now();\n const persistentJob: SearchIndexWorkerJob | null = strategyResult.usedIncrementalScan\n ? {\n kind: \"changes\",\n context: \"scan.refresh\",\n agentName,\n changes: persistentChanges,\n removedSessionIds: persistentRemovedSessionIds,\n meta: buildAgentCacheMeta(agent, changedSessionIds),\n ...(searchIndexOptions ? { searchIndexOptions } : {}),\n }\n : strategyResult.fullScanSessions\n ? {\n kind: \"full\",\n context: \"scan.refresh\",\n agentName,\n sessions: strategyResult.fullScanSessions,\n meta: buildAgentCacheMeta(agent),\n saveCache: true,\n ...(searchIndexOptions ? { searchIndexOptions } : {}),\n }\n : null;\n if (persistentJob) {\n const persist = this.searchIndexJobs.enqueue(\"scan.refresh\", [persistentJob]);\n if (!isInitialized && persistentJob.kind === \"full\") {\n await persist;\n } else {\n void persist.catch((error) => {\n appLogger.error(\"scan.refresh.persist.error\", { agent: agentName, error });\n console.error(`[${agentName}] Session persistence failed:`, error);\n });\n }\n }\n const persistDuration = performance.now() - persistStartedAt;\n logSearchIndexSync(\"scan.refresh\", null, { pending_paths: pendingPathCount });\n this.emitSessionsChanged({ agentName, sessions: nextSessions, event: diff.event });\n\n const totalDurationMs = performance.now() - startedAt;\n state.lastRefreshDurationMs = totalDurationMs;\n appLogger.info(\"scan.refresh.done\", {\n agent: agentName,\n duration_ms: Math.round(totalDurationMs),\n sessions: nextSessions.length,\n new_sessions: diff.event?.newSessions ?? 0,\n updated_sessions: diff.event?.updatedSessions ?? 0,\n removed_sessions: diff.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(diffDuration),\n persist_ms: Math.round(persistDuration),\n search_index_ms: 0,\n persistent_index_worker_job: persistentJob?.kind,\n persistent_index_skipped: !persistentJob || undefined,\n });\n return \"committed\";\n }\n\n private refreshUnavailableAgent(agentName: string): RefreshStrategyResult {\n this.state(agentName).lastRefreshAt = 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.state(agent.name).lastRefreshAt = 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 = buildRefreshDiff(\n agent.name,\n cached.sessions,\n sessions,\n preciseChangedIds,\n );\n this.state(agent.name).lastRefreshAt = Date.now();\n if (preciseChangedIds.length === 0) this.logUnchangedRefresh(agent.name, refreshStartedAt);\n return this.refreshStrategyResult(sessions, {\n preciseChangedIds,\n usedIncrementalScan: true,\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.state(agent.name).lastRefreshAt = 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 const sessions = attachMissingProjectIdentities(\n await Promise.resolve(\n agent.incrementalScan(baseline, checkResult.changedIds ?? [], checkResult.refs),\n ),\n );\n return this.refreshStrategyResult(sessions, {\n preciseChangedIds,\n usedIncrementalScan: Array.isArray(checkResult.changedIds),\n persistenceDiff: buildRefreshDiff(agent.name, 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.state(agent.name).lastRefreshAt = 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 usedIncrementalScan: false,\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.serialize(agentName, \"backfill\", () => this.performBackfill(agentName)).then(\n (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\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.options.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 const diff = buildRefreshDiff(\n agentName,\n snapshot.byAgent[agentName] ?? [],\n fullSessions,\n result.changedIds ?? [],\n );\n await this.searchIndexJobs.enqueue(\"scan.backfill\", [\n {\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 this.emitSessionsChanged({ agentName, sessions: fullSessions, event: diff.event });\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 serialize(\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.isShuttingDown) 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 private state(agentName: string): AgentRefreshState {\n const existing = this.refreshStates.get(agentName);\n if (existing) return existing;\n const state: AgentRefreshState = {\n timer: null,\n timerDeadline: 0,\n isRunning: false,\n hasPendingRerun: false,\n lastRefreshAt: 0,\n lastRefreshDurationMs: 0,\n pendingPathCount: 0,\n signatureCache: new Map(),\n };\n this.refreshStates.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 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.options.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 findAgent(agentName: string): BaseAgent | undefined {\n return this.options.snapshot().agents.find((agent) => agent.name === 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 names, 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 { getCursorDataPath, resolveProviderRoots } from \"@codesesh/core\";\nimport { appLogger } from \"./logging.js\";\n\nconst WRITE_STABILITY_THRESHOLD_MS = 250;\nconst WRITE_STABILITY_POLL_MS = 100;\n\nexport interface WatchTarget {\n path: string;\n root?: string;\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 function resolveAgentWatchTargets(agentName: string): WatchTarget[] {\n const roots = resolveProviderRoots();\n const cursorDataPath = getCursorDataPath();\n\n switch (agentName) {\n case \"claudecode\":\n return [\n { root: roots.claudeRoot, path: join(roots.claudeRoot, \"projects\") },\n { path: \"data/claudecode\" },\n ];\n case \"codex\":\n return [\n { path: join(roots.codexRoot, \"sessions\") },\n { path: join(roots.codexRoot, \"session_index.jsonl\") },\n ];\n case \"pi\":\n return [\n { root: roots.piRoot, path: join(roots.piRoot, \"agent\", \"sessions\") },\n { root: \"data/pi\", path: \"data/pi\" },\n ];\n case \"cursor\":\n return cursorDataPath\n ? [\n {\n root: cursorDataPath,\n path: join(cursorDataPath, \"globalStorage\", \"state.vscdb\"),\n },\n { root: cursorDataPath, path: join(cursorDataPath, \"workspaceStorage\") },\n ]\n : [];\n case \"kimi\":\n return [\n { root: roots.kimiRoot, path: join(roots.kimiRoot, \"sessions\") },\n { path: \"data/kimi\" },\n ];\n case \"opencode\":\n return [\n { root: roots.opencodeRoot, path: join(roots.opencodeRoot, \"opencode.db\") },\n { root: \"data/opencode\", path: \"data/opencode/opencode.db\" },\n ];\n case \"zcode\":\n return roots.zcodeRoot\n ? [{ root: roots.zcodeRoot, path: join(roots.zcodeRoot, \"cli\", \"db\", \"db.sqlite\") }]\n : [];\n default:\n return [];\n }\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 given agent names' data directories. */\n start(agentNames: string[]): void {\n const scopesByRoot = new Map<string, WatchScope[]>();\n\n for (const agentName of agentNames) {\n const watchTargets = resolveAgentWatchTargets(agentName);\n\n if (watchTargets.length === 0) {\n appLogger.debug(\"watch.skip\", { agent: agentName });\n continue;\n }\n\n for (const target of watchTargets) {\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 === agentName && scope.targetPath === targetPath)\n ) {\n scopes.push({ agentName, 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 { AgentScanProgress, ScanOptions, SessionCacheMeta, SessionHead } from \"@codesesh/core\";\nimport { appLogger } from \"./logging.js\";\nimport type { ScanRefreshWorkerMessage } 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\nexport class ThreadWorkerRunner implements WorkerRunner {\n private workers = new Set<Worker>();\n\n constructor(private readonly workerUrl: URL) {}\n\n get activeCount(): number {\n return this.workers.size;\n }\n\n run(agentName: string, payload: WorkerPayload): Promise<WorkerResult> {\n return new Promise((resolve, reject) => {\n const worker = new Worker(this.workerUrl, {\n workerData: {\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 worker.unref();\n this.workers.add(worker);\n\n let settled = false;\n const finish = (callback: () => void, terminate = true) => {\n if (settled) return;\n settled = true;\n this.workers.delete(worker);\n if (terminate) void worker.terminate();\n callback();\n };\n\n worker.on(\"message\", (message: ScanRefreshWorkerMessage) => {\n if (message.type === \"progress\") {\n payload.onProgress?.(message.progress);\n return;\n }\n if (message.type === \"done\") {\n finish(() =>\n resolve({\n sessions: message.sessions,\n meta: message.meta,\n changedIds: message.changedIds,\n }),\n );\n return;\n }\n finish(() => reject(new Error(message.error)));\n });\n worker.once(\"error\", (error) => {\n finish(() => reject(error));\n });\n worker.once(\"exit\", (code) => {\n if (settled) return;\n appLogger.warn(\"scan.refresh_worker.exit_before_done\", { agent: agentName, code });\n finish(\n () => reject(new Error(`Scan refresh worker exited before completing (code ${code})`)),\n false,\n );\n });\n });\n }\n\n async shutdown(): Promise<void> {\n const workers = [...this.workers];\n await Promise.allSettled(workers.map((worker) => worker.terminate()));\n this.workers.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","__dirname","resolve","Hono","url","existsSync","fileURLToPath","existsSync","fileURLToPath","resolve","existsSync","fileURLToPath","existsSync","dirname","resolve","resolve","existsSync","dirname","Worker","resolve","Worker","existsSync","fileURLToPath","resolve","dirname","fileURLToPath"]}
|