codesesh 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -3
- package/dist/{chunk-FZNZAMTZ.js → chunk-SQYHWMQV.js} +2533 -458
- package/dist/chunk-SQYHWMQV.js.map +1 -0
- package/dist/{dist-DMEDEJ2D.js → dist-NT4CH6KD.js} +46 -2
- package/dist/index.js +680 -83
- package/dist/index.js.map +1 -1
- package/dist/search-index-worker.js +40 -0
- package/dist/search-index-worker.js.map +1 -0
- package/dist/web/assets/index-BlSglSCE.css +2 -0
- package/dist/web/assets/index-CnxgGfhM.js +106 -0
- package/dist/web/assets/vendor-Bs5B_LvM.js +43 -0
- package/dist/web/index.html +3 -3
- package/package.json +2 -3
- package/dist/chunk-FZNZAMTZ.js.map +0 -1
- package/dist/web/assets/index-BRW_TBMw.js +0 -106
- package/dist/web/assets/index-CCgk7cPa.css +0 -2
- package/dist/web/assets/vendor-CWmLg_mG.js +0 -43
- /package/dist/{dist-DMEDEJ2D.js.map → dist-NT4CH6KD.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/api/handlers.ts","../src/live-scan.ts","../src/output.ts","../src/version.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 {\n createRegisteredAgents,\n getAgentInfoMap,\n refreshPricingCache,\n type ScanOptions,\n perf,\n} from \"@codesesh/core\";\n\nfunction parseDateToTimestamp(dateStr: string): number {\n const date = new Date(dateStr);\n if (Number.isNaN(date.getTime())) {\n throw new Error(`Invalid date: ${dateStr}`);\n }\n return date.getTime();\n}\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\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: \"4321\",\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 = parseInt(args.port as string, 10) || 4321;\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\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 // Resolve app-level default window (shared across /api/agents, /sessions, /dashboard).\n // Priority: --from (absolute) over --days (relative).\n let listDefaultFrom: number | undefined;\n let listDefaultDays: number | undefined;\n if (args.from) {\n listDefaultFrom = parseDateToTimestamp(args.from as string);\n } else {\n const days = parseInt(args.days as string, 10);\n if (!Number.isNaN(days) && days > 0) {\n listDefaultFrom = Date.now() - days * 24 * 60 * 60 * 1000;\n listDefaultDays = days;\n }\n }\n const listDefaultTo = args.to ? parseDateToTimestamp(args.to as string) : undefined;\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(!jsonOnly, scanOptions, startupScanOptions);\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, result);\n\n // Start server\n let url: string;\n try {\n ({ url } = await createServer(port, store, {\n defaultSessionFrom: listDefaultFrom,\n defaultSessionTo: listDefaultTo,\n defaultSessionDays: listDefaultDays,\n }));\n } catch (error) {\n console.error(getServerStartupErrorMessage(error, port));\n process.exit(1);\n }\n\n console.log(` ${url}`);\n console.log(\"\");\n appLogger.info(\"cli.ready\", {\n 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 ? `${url}/${targetSession.agent.toLowerCase()}/${targetSession.sessionId}`\n : url;\n appLogger.info(\"browser.open\", { url: 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 { serve } from \"@hono/node-server\";\nimport { serveStatic } from \"@hono/node-server/serve-static\";\nimport { existsSync } from \"node:fs\";\nimport type { Server } from \"node:http\";\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 { LiveScanStore } from \"./live-scan.js\";\nimport { appLogger } from \"./logging.js\";\n\nexport interface CreateServerOptions {\n defaultSessionFrom?: number;\n defaultSessionTo?: number;\n defaultSessionDays?: number;\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: Server): 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\nexport async function createServer(\n port: number,\n store: ScanResultSource & Partial<Pick<LiveScanStore, \"subscribe\" | \"shutdown\">>,\n options: CreateServerOptions = {},\n): Promise<{ url: string; shutdown: () => void }> {\n const app = new Hono();\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 // API routes\n const routeOptions: ApiRouteOptions = {\n defaultSessionFrom: options.defaultSessionFrom,\n defaultSessionTo: options.defaultSessionTo,\n defaultSessionDays: options.defaultSessionDays,\n };\n app.route(\n \"/api\",\n createApiRoutes(\n store,\n \"subscribe\" in store ? (store as LiveScanStore) : undefined,\n routeOptions,\n ),\n );\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 server = serve({ fetch: app.fetch, port });\n\n try {\n await waitForListening(server);\n } catch (error) {\n appLogger.error(\"server.listen.error\", { port, error });\n server.close();\n if (store.shutdown) {\n await store.shutdown();\n }\n throw new Error(getServerStartupErrorMessage(error, port));\n }\n\n const url = `http://localhost:${port}`;\n appLogger.info(\"server.listen\", { port, url });\n\n return {\n url,\n shutdown: () => {\n appLogger.info(\"server.shutdown\", { port });\n server.close();\n if (store.shutdown) {\n void store.shutdown();\n }\n },\n };\n}\n","import { Hono } from \"hono\";\nimport {\n handleGetAgents,\n handleGetBookmarks,\n handleGetConfig,\n handleGetDashboard,\n handleGetProjects,\n handleDeleteBookmark,\n handleImportBookmarks,\n handlePostClientLog,\n handleSearchSessions,\n handleGetSessions,\n handleGetSessionData,\n handlePutBookmark,\n type ScanResultSource,\n type SessionListDefaults,\n} from \"./handlers.js\";\nimport type { LiveScanStore } from \"../live-scan.js\";\n\nexport interface ApiRouteOptions {\n defaultSessionFrom?: number;\n defaultSessionTo?: number;\n defaultSessionDays?: number;\n}\n\nfunction createSseResponse(store: LiveScanStore, signal: AbortSignal): Response {\n const encoder = new TextEncoder();\n\n return new Response(\n new ReadableStream({\n start(controller) {\n const write = (event: string, data: unknown) => {\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\n const unsubscribe = store.subscribe((event) => {\n write(event.type, event);\n });\n\n const heartbeat = setInterval(() => {\n controller.enqueue(encoder.encode(\": keepalive\\n\\n\"));\n }, 15000);\n\n const close = () => {\n clearInterval(heartbeat);\n unsubscribe();\n controller.close();\n };\n\n signal.addEventListener(\"abort\", close, { once: true });\n },\n cancel() {\n return;\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 store?: LiveScanStore,\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 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(\"/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.post(\"/logs\", (c) => handlePostClientLog(c));\n if (store) {\n api.get(\"/events\", (c) => createSseResponse(store, 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\";\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),\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","import type { Context } from \"hono\";\nimport type {\n BookmarkRecord,\n ScanResult,\n SessionData,\n SessionHead,\n SmartTag,\n} from \"@codesesh/core\";\nimport {\n BookmarkStorageUnavailableError,\n deleteBookmark,\n getAgentInfoMap,\n classifySessionTags,\n computeIdentity,\n getSmartTagSourceTimestamp,\n importBookmarks,\n listCachedProjectGroups,\n listBookmarks,\n realFs,\n searchSessions,\n syncSessionSearchIndex,\n upsertBookmark,\n} from \"@codesesh/core\";\nimport { appLogger } from \"../logging.js\";\n\nexport interface ScanResultSource {\n getSnapshot(): ScanResult;\n}\n\nexport interface SessionListDefaults {\n from?: number;\n to?: number;\n /** When --days was used, original value — kept for UI \"last N days\" label */\n days?: number;\n}\n\ninterface ClientLogPayload {\n event?: unknown;\n data?: unknown;\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,\n stats: value.stats,\n };\n}\n\nfunction getTotalTokens(stats: SessionHead[\"stats\"]): number {\n return stats.total_tokens ?? stats.total_input_tokens + stats.total_output_tokens;\n}\n\nfunction getSessionActivityTime(session: SessionHead): number {\n return session.time_updated ?? session.time_created;\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 filterSessionsByWindow(\n sessions: SessionHead[],\n from: number | undefined,\n to: number | undefined,\n): SessionHead[] {\n return filterSessionsByActivityWindow(sessions, from, to);\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 matchesProjectScope(session: SessionHead, cwd: string): boolean {\n if (!session.directory) return false;\n const identity = computeIdentity(cwd, realFs);\n if (session.project_identity?.key === identity.key) return true;\n return session.directory.toLowerCase().includes(cwd.toLowerCase());\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\nexport function handleGetConfig(c: Context, defaults: SessionListDefaults) {\n return c.json({\n window: {\n from: defaults.from,\n to: defaults.to,\n days: defaults.days,\n },\n });\n}\n\nexport function handleGetAgents(\n c: Context,\n scanSource: ScanResultSource,\n defaults: SessionListDefaults = {},\n) {\n const scanResult = scanSource.getSnapshot();\n const { from, to } = defaults;\n const counts = Object.fromEntries(\n Object.entries(scanResult.byAgent).map(([agentName, sessions]) => [\n agentName,\n filterSessionsByWindow(sessions, from, to).length,\n ]),\n );\n const info = getAgentInfoMap(counts);\n return c.json(info);\n}\n\nexport function handleGetProjects(\n c: Context,\n scanSource: ScanResultSource,\n defaults: SessionListDefaults = {},\n) {\n const scanResult = scanSource.getSnapshot();\n const { from, to } = defaults;\n return c.json({\n projects: listCachedProjectGroups(\n filterSessionsByActivityWindow(scanResult.sessions, from, to),\n ),\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 projectKey = c.req.query(\"projectKey\");\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 (projectKey) {\n sessions = sessions.filter((s) => s.project_identity?.key === projectKey);\n } else if (cwd) {\n sessions = sessions.filter((s) => matchesProjectScope(s, cwd));\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 if (q) {\n sessions = sessions.filter((s) => s.title.toLowerCase().includes(q));\n }\n\n return c.json({ sessions });\n}\n\nexport function handleSearchSessions(\n c: Context,\n scanSource: ScanResultSource,\n defaults: SessionListDefaults = {},\n) {\n const query = c.req.query(\"q\")?.trim() ?? \"\";\n if (!query) {\n return c.json({ results: [] });\n }\n\n const scanResult = scanSource.getSnapshot();\n const agent = c.req.query(\"agent\");\n const cwd = c.req.query(\"cwd\");\n const from = parseDateParam(c.req.query(\"from\"), defaults.from);\n const to = parseDateParam(c.req.query(\"to\"), defaults.to);\n\n for (const indexedAgent of scanResult.agents) {\n const sessions = scanResult.byAgent[indexedAgent.name] ?? [];\n syncSessionSearchIndex(indexedAgent.name, sessions, (sessionId) =>\n indexedAgent.getSessionData(sessionId),\n );\n }\n\n const results = searchSessions(query, {\n agent,\n cwd,\n from,\n to,\n limit: 50,\n });\n\n return c.json({ results });\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 (!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 loadStartedAt = performance.now();\n const data: SessionData = agent.getSessionData(sessionId);\n const loadDuration = performance.now() - loadStartedAt;\n const tagStartedAt = performance.now();\n const smartTags = classifySessionTags(data);\n const tagDuration = performance.now() - tagStartedAt;\n const head = scanResult.byAgent[agentName]?.find((item) => item.id === sessionId);\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 return c.json({\n ...data,\n project_identity: data.project_identity ?? head?.project_identity,\n smart_tags: smartTags,\n smart_tags_source_updated_at: getSmartTagSourceTimestamp(data),\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 return c.json({ bookmarks: listBookmarks(), storageAvailable: true });\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 interface DashboardAgentStat {\n name: string;\n displayName: string;\n icon: string;\n sessions: number;\n messages: number;\n tokens: number;\n}\n\nexport interface DashboardDailyBucket {\n /** Local YYYY-MM-DD */\n date: string;\n sessions: number;\n messages: number;\n}\n\nexport interface DailyTokenBucket {\n date: string;\n input: number;\n output: number;\n cache_read: number;\n cache_create: number;\n}\n\nexport interface ModelDistributionEntry {\n model: string;\n tokens: number;\n sessions: number;\n}\n\nexport interface DashboardTotals {\n sessions: number;\n messages: number;\n tokens: number;\n cost: number;\n cost_source?: \"recorded\" | \"estimated\";\n latestActivity?: number;\n}\n\nexport interface DashboardRecentSession extends SessionHead {\n agentName: string;\n}\n\nexport interface DashboardData {\n totals: DashboardTotals;\n perAgent: DashboardAgentStat[];\n dailyActivity: DashboardDailyBucket[];\n dailyTokenActivity: DailyTokenBucket[];\n modelDistribution: ModelDistributionEntry[];\n recentSessions: DashboardRecentSession[];\n /** Time window covered by dailyActivity (inclusive, ms) */\n window: { from: number; to: number; days: number };\n}\n\nfunction toLocalDateKey(ts: number): string {\n const d = new Date(ts);\n const year = d.getFullYear();\n const month = `${d.getMonth() + 1}`.padStart(2, \"0\");\n const day = `${d.getDate()}`.padStart(2, \"0\");\n return `${year}-${month}-${day}`;\n}\n\nfunction startOfLocalDay(ts: number): number {\n const d = new Date(ts);\n d.setHours(0, 0, 0, 0);\n return d.getTime();\n}\n\nfunction resolveDashboardWindow(\n defaults: SessionListDefaults,\n queryDays: string | undefined,\n queryFrom: string | undefined,\n queryTo: string | undefined,\n): { from: number; to: number; days: number } {\n const now = Date.now();\n\n const toTs = parseDateParam(queryTo, defaults.to) ?? now;\n\n // Resolve days (preferred): query, defaults.days, or derive from defaults.from\n const parsedDays = queryDays ? parseInt(queryDays, 10) : NaN;\n let days: number | undefined =\n Number.isFinite(parsedDays) && parsedDays > 0 ? parsedDays : defaults.days;\n\n const fromFromQuery = parseDateParam(queryFrom, undefined);\n let fromTs: number;\n if (fromFromQuery != null) {\n fromTs = fromFromQuery;\n days ??= Math.max(1, Math.ceil((toTs - fromTs) / 86400000));\n } else if (defaults.from != null) {\n fromTs = defaults.from;\n days ??= Math.max(1, Math.ceil((toTs - fromTs) / 86400000));\n } else if (days && days > 0) {\n fromTs = startOfLocalDay(toTs) - (days - 1) * 86400000;\n } else {\n days = 30;\n fromTs = startOfLocalDay(toTs) - (days - 1) * 86400000;\n }\n\n return { from: fromTs, to: toTs, days };\n}\n\nexport function handleGetDashboard(\n c: Context,\n scanSource: ScanResultSource,\n defaults: SessionListDefaults = {},\n) {\n const scanResult = scanSource.getSnapshot();\n const { from, to, days } = resolveDashboardWindow(\n defaults,\n c.req.query(\"days\"),\n c.req.query(\"from\"),\n c.req.query(\"to\"),\n );\n\n const windowed = filterSessionsByActivityWindow(scanResult.sessions, from, to);\n\n const agentInfo = getAgentInfoMap(\n Object.fromEntries(\n Object.entries(scanResult.byAgent).map(([name, sessions]) => [\n name,\n filterSessionsByActivityWindow(sessions, from, to).length,\n ]),\n ),\n );\n const agentInfoMap = new Map(agentInfo.map((a) => [a.name, a]));\n\n let totalMessages = 0;\n let totalTokens = 0;\n let totalCost = 0;\n let hasEstimatedCost = false;\n let latestActivity = 0;\n for (const session of windowed) {\n totalMessages += session.stats.message_count;\n totalTokens += getTotalTokens(session.stats);\n totalCost += session.stats.total_cost ?? 0;\n if (session.stats.cost_source === \"estimated\") hasEstimatedCost = true;\n const activity = getSessionActivityTime(session);\n if (activity > latestActivity) latestActivity = activity;\n }\n\n const perAgent: DashboardAgentStat[] = Object.entries(scanResult.byAgent)\n .map(([name, sessions]) => {\n const info = agentInfoMap.get(name);\n const agentWindowed = filterSessionsByActivityWindow(sessions, from, to);\n let messages = 0;\n let tokens = 0;\n for (const s of agentWindowed) {\n messages += s.stats.message_count;\n tokens += getTotalTokens(s.stats);\n }\n return {\n name,\n displayName: info?.displayName ?? name,\n icon: info?.icon ?? \"\",\n sessions: agentWindowed.length,\n messages,\n tokens,\n };\n })\n .filter((item) => item.sessions > 0)\n .sort((a, b) => b.sessions - a.sessions);\n\n // Daily activity buckets — one bucket per local day in [from, to]\n const dailyMap = new Map<string, DashboardDailyBucket>();\n const dailyTokenMap = new Map<string, DailyTokenBucket>();\n const bucketStart = startOfLocalDay(from);\n const bucketDays = Math.floor((startOfLocalDay(to) - bucketStart) / 86400000) + 1;\n for (let i = 0; i < bucketDays; i += 1) {\n const ts = bucketStart + i * 86400000;\n const key = toLocalDateKey(ts);\n dailyMap.set(key, { date: key, sessions: 0, messages: 0 });\n dailyTokenMap.set(key, { date: key, input: 0, output: 0, cache_read: 0, cache_create: 0 });\n }\n\n const modelAgg = new Map<string, { tokens: number; sessions: number }>();\n\n for (const session of windowed) {\n const key = toLocalDateKey(getSessionActivityTime(session));\n const bucket = dailyMap.get(key);\n if (bucket) {\n bucket.sessions += 1;\n bucket.messages += session.stats.message_count;\n }\n\n const tokenBucket = dailyTokenMap.get(key);\n if (tokenBucket) {\n const cacheRead = session.stats.total_cache_read_tokens ?? 0;\n const cacheCreate = session.stats.total_cache_create_tokens ?? 0;\n const pureInput = session.stats.total_input_tokens - cacheRead - cacheCreate;\n tokenBucket.input += Math.max(0, pureInput);\n tokenBucket.output += session.stats.total_output_tokens;\n tokenBucket.cache_read += cacheRead;\n tokenBucket.cache_create += cacheCreate;\n }\n\n if (session.model_usage) {\n for (const [model, tokens] of Object.entries(session.model_usage)) {\n const entry = modelAgg.get(model);\n if (entry) {\n entry.tokens += tokens;\n entry.sessions += 1;\n } else {\n modelAgg.set(model, { tokens, sessions: 1 });\n }\n }\n }\n }\n\n const dailyActivity = [...dailyMap.values()];\n const dailyTokenActivity = [...dailyTokenMap.values()];\n\n const modelDistribution: ModelDistributionEntry[] = [...modelAgg.entries()]\n .map(([model, { tokens, sessions: count }]) => ({ model, tokens, sessions: count }))\n .sort((a, b) => b.tokens - a.tokens);\n\n const recentSessions: DashboardRecentSession[] = [...windowed]\n .sort((a, b) => getSessionActivityTime(b) - getSessionActivityTime(a))\n .slice(0, 10)\n .map((session) => {\n const agentKey = session.slug.split(\"/\")[0] ?? \"unknown\";\n return { ...session, agentName: agentKey };\n });\n\n const data: DashboardData = {\n totals: {\n sessions: windowed.length,\n messages: totalMessages,\n tokens: totalTokens,\n cost: totalCost,\n cost_source: totalCost > 0 ? (hasEstimatedCost ? \"estimated\" : \"recorded\") : undefined,\n latestActivity: latestActivity || undefined,\n },\n perAgent,\n dailyActivity,\n dailyTokenActivity,\n modelDistribution,\n recentSessions,\n window: { from, to, days },\n };\n\n return c.json(data);\n}\n","import { existsSync } from \"node:fs\";\nimport { dirname, isAbsolute, join } from \"node:path\";\nimport chokidar, { type FSWatcher } from \"chokidar\";\nimport {\n createRegisteredAgents,\n filterSessions,\n getCursorDataPath,\n resolveProviderRoots,\n scanSessions,\n syncSessionSearchIndex,\n saveCachedSessions,\n type BaseAgent,\n type ScanResult,\n type ScanOptions,\n type SessionCacheMeta,\n type SessionHead,\n} from \"@codesesh/core\";\nimport { appLogger } from \"./logging.js\";\n\nexport interface SessionsUpdatedEvent {\n type: \"sessions-updated\";\n changedAgents: string[];\n newSessions: number;\n updatedSessions: number;\n removedSessions: number;\n totalSessions: number;\n timestamp: number;\n}\n\ntype StoreListener = (event: SessionsUpdatedEvent) => void;\n\ninterface WatchTarget {\n path: string;\n depth?: number;\n}\n\nfunction sortSessions(sessions: SessionHead[]): SessionHead[] {\n return [...sessions].sort(\n (a, b) => (b.time_updated ?? b.time_created) - (a.time_updated ?? a.time_created),\n );\n}\n\nfunction sessionSignature(session: SessionHead): string {\n return JSON.stringify([\n session.title,\n session.directory,\n session.time_created,\n session.time_updated ?? session.time_created,\n session.stats.message_count,\n session.stats.total_input_tokens,\n session.stats.total_output_tokens,\n session.stats.total_cost,\n session.stats.total_tokens ?? 0,\n ]);\n}\n\nfunction buildAgentCacheMeta(agent: BaseAgent): Record<string, SessionCacheMeta> {\n const metaMap = agent.getSessionMetaMap?.();\n const meta: Record<string, SessionCacheMeta> = {};\n if (!metaMap) return meta;\n\n for (const [id, data] of metaMap.entries()) {\n meta[id] = { id, ...(data as Record<string, unknown>) } as SessionCacheMeta;\n }\n\n return meta;\n}\n\nfunction buildUpdateEvent(\n agentName: string,\n previousSessions: SessionHead[],\n nextSessions: SessionHead[],\n): SessionsUpdatedEvent | null {\n const previousMap = new Map(previousSessions.map((session) => [session.id, session]));\n const nextMap = new Map(nextSessions.map((session) => [session.id, session]));\n\n let newSessions = 0;\n let updatedSessions = 0;\n let removedSessions = 0;\n\n for (const [id, session] of nextMap.entries()) {\n const previous = previousMap.get(id);\n if (!previous) {\n newSessions += 1;\n continue;\n }\n if (sessionSignature(previous) !== sessionSignature(session)) {\n updatedSessions += 1;\n }\n }\n\n for (const id of previousMap.keys()) {\n if (!nextMap.has(id)) {\n removedSessions += 1;\n }\n }\n\n if (newSessions === 0 && updatedSessions === 0 && removedSessions === 0) {\n return null;\n }\n\n return {\n type: \"sessions-updated\",\n changedAgents: [agentName],\n newSessions,\n updatedSessions,\n removedSessions,\n totalSessions: nextSessions.length,\n timestamp: Date.now(),\n };\n}\n\nfunction closestWatchablePath(targetPath: string): string | null {\n if (!isAbsolute(targetPath) && !existsSync(targetPath)) {\n return null;\n }\n\n let current = 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\nexport function resolveAgentWatchTargets(agentName: string): WatchTarget[] {\n const roots = resolveProviderRoots();\n const cursorDataPath = getCursorDataPath();\n\n switch (agentName) {\n case \"claudecode\":\n return [\n { path: join(roots.claudeRoot, \"projects\"), depth: 2 },\n { path: \"data/claudecode\", depth: 2 },\n ];\n case \"codex\":\n return [{ path: join(roots.codexRoot, \"sessions\"), depth: 4 }];\n case \"cursor\":\n return cursorDataPath\n ? [\n { path: join(cursorDataPath, \"globalStorage\", \"state.vscdb\") },\n { path: join(cursorDataPath, \"workspaceStorage\"), depth: 2 },\n ]\n : [];\n case \"kimi\":\n return [\n { path: join(roots.kimiRoot, \"sessions\"), depth: 2 },\n { path: \"data/kimi\", depth: 2 },\n ];\n case \"opencode\":\n return [\n { path: join(roots.opencodeRoot, \"opencode.db\") },\n { path: \"data/opencode/opencode.db\" },\n ];\n default:\n return [];\n }\n}\n\nexport class LiveScanStore {\n private agents: BaseAgent[] = [];\n private byAgent: Record<string, SessionHead[]> = {};\n private sessions: SessionHead[] = [];\n private listeners = new Set<StoreListener>();\n private refreshTimers = new Map<string, NodeJS.Timeout>();\n private refreshTimestamps = new Map<string, number>();\n private refreshInFlight = new Set<string>();\n private pendingRefreshes = new Set<string>();\n private watchers: FSWatcher[] = [];\n\n constructor(\n private readonly watchEnabled = true,\n private readonly scanOptions: ScanOptions = {},\n private readonly startupScanOptions: Pick<ScanOptions, \"from\" | \"to\"> = {},\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 });\n const initialResult = await scanSessions({\n ...this.scanOptions,\n ...this.startupScanOptions,\n useCache: this.scanOptions.useCache ?? true,\n smartRefresh: false,\n writeCache:\n this.startupScanOptions.from != null || this.startupScanOptions.to != null\n ? false\n : undefined,\n includeSmartTags:\n this.startupScanOptions.from != null || this.startupScanOptions.to != null\n ? false\n : undefined,\n });\n this.applyScanResult(initialResult);\n appLogger.info(\"scan.initial.done\", {\n duration_ms: Math.round(performance.now() - startedAt),\n sessions: this.sessions.length,\n agents: Object.fromEntries(\n Object.entries(this.byAgent).map(([key, value]) => [key, value.length]),\n ),\n });\n if (this.watchEnabled) {\n this.startWatching();\n }\n }\n\n getSnapshot(): ScanResult {\n return {\n sessions: this.sessions,\n byAgent: this.byAgent,\n agents: this.agents,\n };\n }\n\n subscribe(listener: StoreListener): () => void {\n this.listeners.add(listener);\n return () => {\n this.listeners.delete(listener);\n };\n }\n\n async shutdown(): Promise<void> {\n for (const timer of this.refreshTimers.values()) {\n clearTimeout(timer);\n }\n this.refreshTimers.clear();\n\n await Promise.all(this.watchers.map((watcher) => watcher.close()));\n this.watchers = [];\n }\n\n private emit(event: SessionsUpdatedEvent): void {\n for (const listener of this.listeners) {\n listener(event);\n }\n }\n\n private rebuildSessions(): void {\n this.sessions = sortSessions(Object.values(this.byAgent).flat());\n }\n\n private hasStartupWindow(): boolean {\n return this.startupScanOptions.from != null || this.startupScanOptions.to != null;\n }\n\n private applyScanResult(result: ScanResult): void {\n const knownAgents = createRegisteredAgents();\n const agentMap = new Map<string, BaseAgent>();\n const allowedAgents = this.getAllowedAgents();\n\n for (const agent of result.agents) {\n agentMap.set(agent.name, agent);\n }\n for (const agent of knownAgents) {\n if (!agentMap.has(agent.name)) {\n agentMap.set(agent.name, agent);\n }\n }\n\n this.agents = [...agentMap.values()].filter((agent) => {\n if (!allowedAgents) {\n return true;\n }\n return allowedAgents.has(agent.name.toLowerCase());\n });\n\n this.byAgent = {};\n for (const agent of this.agents) {\n this.byAgent[agent.name] = sortSessions(result.byAgent[agent.name] ?? []);\n this.refreshTimestamps.set(agent.name, Date.now());\n }\n\n this.rebuildSessions();\n }\n\n private getAllowedAgents(): Set<string> | null {\n if (!this.scanOptions.agents?.length) {\n return null;\n }\n return new Set(this.scanOptions.agents.map((agent) => agent.toLowerCase()));\n }\n\n private applyFilters(sessions: SessionHead[]): SessionHead[] {\n return filterSessions(sessions, { ...this.scanOptions, ...this.startupScanOptions });\n }\n\n private startWatching(): void {\n for (const agent of this.agents) {\n const rawTargets = resolveAgentWatchTargets(agent.name);\n const watchTargets = rawTargets\n .map((target) => {\n const watchPath = closestWatchablePath(target.path);\n return watchPath ? { ...target, path: watchPath } : null;\n })\n .filter((target): target is WatchTarget => target !== null)\n .filter(\n (target, index, items) =>\n items.findIndex((item) => item.path === target.path && item.depth === target.depth) ===\n index,\n );\n\n if (watchTargets.length === 0) {\n appLogger.debug(\"watch.skip\", { agent: agent.name });\n continue;\n }\n\n appLogger.info(\"watch.start\", {\n agent: agent.name,\n targets: watchTargets.map((target) => ({\n path: target.path,\n depth: target.depth ?? 0,\n })),\n });\n const watcher = chokidar.watch(\n watchTargets.map((target) => target.path),\n {\n ignoreInitial: true,\n awaitWriteFinish: {\n stabilityThreshold: 250,\n pollInterval: 100,\n },\n depth: watchTargets.reduce(\n (maxDepth, target) => Math.max(maxDepth, target.depth ?? 0),\n 0,\n ),\n },\n );\n\n watcher.on(\"all\", () => {\n this.scheduleRefresh(agent.name);\n });\n watcher.on(\"error\", (error) => {\n appLogger.error(\"watch.error\", { agent: agent.name, error });\n console.error(`[${agent.name}] File watcher failed:`, error);\n });\n\n this.watchers.push(watcher);\n }\n }\n\n private scheduleRefresh(agentName: string, delayMs = 200): void {\n appLogger.debug(\"scan.refresh.schedule\", { agent: agentName, delay_ms: delayMs });\n const existing = this.refreshTimers.get(agentName);\n if (existing) {\n clearTimeout(existing);\n }\n\n const timer = setTimeout(() => {\n this.refreshTimers.delete(agentName);\n void this.refreshAgent(agentName);\n }, delayMs);\n\n this.refreshTimers.set(agentName, timer);\n }\n\n private async refreshAgent(agentName: string): Promise<void> {\n if (this.refreshInFlight.has(agentName)) {\n appLogger.debug(\"scan.refresh.pending\", { agent: agentName });\n this.pendingRefreshes.add(agentName);\n return;\n }\n\n this.refreshInFlight.add(agentName);\n\n try {\n await this.runRefresh(agentName);\n } finally {\n this.refreshInFlight.delete(agentName);\n\n if (this.pendingRefreshes.delete(agentName)) {\n this.scheduleRefresh(agentName, 100);\n }\n }\n }\n\n private async runRefresh(agentName: string): Promise<void> {\n const startedAt = performance.now();\n const agent = this.agents.find((item) => item.name === agentName);\n if (!agent) {\n appLogger.warn(\"scan.refresh.missing_agent\", { agent: agentName });\n return;\n }\n\n const previousSessions = this.byAgent[agentName] ?? [];\n let nextSessions = previousSessions;\n\n if (!agent.isAvailable()) {\n nextSessions = [];\n this.refreshTimestamps.set(agentName, Date.now());\n } else if (previousSessions.length > 0 && agent.checkForChanges && agent.incrementalScan) {\n const checkResult = await Promise.resolve(\n agent.checkForChanges(this.refreshTimestamps.get(agentName) ?? 0, previousSessions),\n );\n\n this.refreshTimestamps.set(agentName, checkResult.timestamp);\n if (!checkResult.hasChanges) {\n appLogger.debug(\"scan.refresh.unchanged\", {\n agent: agentName,\n duration_ms: Math.round(performance.now() - startedAt),\n });\n return;\n }\n\n nextSessions = await Promise.resolve(\n agent.incrementalScan(previousSessions, checkResult.changedIds ?? []),\n );\n } else {\n nextSessions = await Promise.resolve(agent.scan(this.startupScanOptions));\n this.refreshTimestamps.set(agentName, Date.now());\n }\n\n nextSessions = this.applyFilters(nextSessions);\n if (!this.hasStartupWindow()) {\n saveCachedSessions(agentName, nextSessions, buildAgentCacheMeta(agent));\n }\n syncSessionSearchIndex(agentName, nextSessions, (sessionId) => agent.getSessionData(sessionId));\n\n const event = buildUpdateEvent(agentName, previousSessions, nextSessions);\n this.byAgent[agentName] = sortSessions(nextSessions);\n this.rebuildSessions();\n\n if (event) {\n event.totalSessions = this.sessions.length;\n this.emit(event);\n }\n appLogger.info(\"scan.refresh.done\", {\n agent: agentName,\n duration_ms: Math.round(performance.now() - startedAt),\n sessions: nextSessions.length,\n new_sessions: event?.newSessions ?? 0,\n updated_sessions: event?.updatedSessions ?? 0,\n removed_sessions: event?.removedSessions ?? 0,\n });\n }\n}\n","import { consola } from \"consola\";\nimport type { BaseAgent } from \"@codesesh/core\";\nimport type { ScanResult } from \"@codesesh/core\";\nimport { VERSION } from \"./version.js\";\n\nexport function printScanResults(agents: BaseAgent[], result: ScanResult): void {\n consola.log(\"\");\n consola.box({\n title: \"CodeSesh\",\n message: `v${VERSION} • ${result.sessions.length} sessions discovered`,\n style: {\n padding: 1,\n borderColor: \"cyan\",\n },\n });\n consola.log(\"\");\n\n const rows: string[] = [];\n let availableCount = 0;\n\n for (const agent of agents) {\n const sessions = result.byAgent[agent.name];\n const count = sessions?.length ?? 0;\n if (count > 0) {\n availableCount++;\n rows.push(` ${green(\"✔\")} ${pad(agent.displayName)} ${dim(`${count} sessions`)}`);\n } else {\n rows.push(` ${dim(\"✖\")} ${pad(agent.displayName)} ${dim(\"not found\")}`);\n }\n }\n\n consola.log(rows.join(\"\\n\"));\n consola.log(\"\");\n consola.info(`Active: ${availableCount}/${agents.length} agents`);\n consola.log(\"\");\n}\n\nfunction pad(text: string, length = 16): string {\n return text.padEnd(length);\n}\n\nfunction green(text: string): string {\n return `\\x1b[32m${text}\\x1b[0m`;\n}\n\nfunction dim(text: string): string {\n return `\\x1b[2m${text}\\x1b[0m`;\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"],"mappings":"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","names":["Hono","existsSync","__dirname","existsSync","resolve","Hono","url","existsSync","dirname","join","existsSync","dirname","join","resolve","dirname","fileURLToPath"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/server.ts","../src/api/routes.ts","../src/logging.ts","../src/api/handlers.ts","../src/live-scan.ts","../src/output.ts","../src/version.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 {\n createRegisteredAgents,\n getAgentInfoMap,\n refreshPricingCache,\n type ScanOptions,\n perf,\n} from \"@codesesh/core\";\n\nfunction parseDateToTimestamp(dateStr: string): number {\n const date = new Date(dateStr);\n if (Number.isNaN(date.getTime())) {\n throw new Error(`Invalid date: ${dateStr}`);\n }\n return date.getTime();\n}\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\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: \"4321\",\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 = parseInt(args.port as string, 10) || 4321;\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\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 // Resolve app-level default window (shared across /api/agents, /sessions, /dashboard).\n // Priority: --from (absolute) over --days (relative).\n let listDefaultFrom: number | undefined;\n let listDefaultDays: number | undefined;\n if (args.from) {\n listDefaultFrom = parseDateToTimestamp(args.from as string);\n } else {\n const days = parseInt(args.days as string, 10);\n if (!Number.isNaN(days) && days > 0) {\n listDefaultFrom = Date.now() - days * 24 * 60 * 60 * 1000;\n listDefaultDays = days;\n }\n }\n const listDefaultTo = args.to ? parseDateToTimestamp(args.to as string) : undefined;\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(!jsonOnly, scanOptions, startupScanOptions);\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, result);\n\n // Start server\n let url: string;\n try {\n ({ url } = await createServer(port, store, {\n defaultSessionFrom: listDefaultFrom,\n defaultSessionTo: listDefaultTo,\n defaultSessionDays: listDefaultDays,\n }));\n } catch (error) {\n console.error(getServerStartupErrorMessage(error, port));\n process.exit(1);\n }\n\n console.log(` ${url}`);\n console.log(\"\");\n appLogger.info(\"cli.ready\", {\n 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 ? `${url}/${targetSession.agent.toLowerCase()}/${targetSession.sessionId}`\n : url;\n appLogger.info(\"browser.open\", { url: 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 { serve } from \"@hono/node-server\";\nimport { serveStatic } from \"@hono/node-server/serve-static\";\nimport { existsSync } from \"node:fs\";\nimport type { Server } from \"node:http\";\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 { LiveScanStore } from \"./live-scan.js\";\nimport { appLogger } from \"./logging.js\";\n\nexport interface CreateServerOptions {\n defaultSessionFrom?: number;\n defaultSessionTo?: number;\n defaultSessionDays?: number;\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: Server): 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\nexport async function createServer(\n port: number,\n store: ScanResultSource & Partial<Pick<LiveScanStore, \"subscribe\" | \"shutdown\">>,\n options: CreateServerOptions = {},\n): Promise<{ url: string; shutdown: () => void }> {\n const app = new Hono();\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 // API routes\n const routeOptions: ApiRouteOptions = {\n defaultSessionFrom: options.defaultSessionFrom,\n defaultSessionTo: options.defaultSessionTo,\n defaultSessionDays: options.defaultSessionDays,\n };\n app.route(\n \"/api\",\n createApiRoutes(\n store,\n \"subscribe\" in store ? (store as LiveScanStore) : undefined,\n routeOptions,\n ),\n );\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 server = serve({ fetch: app.fetch, port });\n\n try {\n await waitForListening(server);\n } catch (error) {\n appLogger.error(\"server.listen.error\", { port, error });\n server.close();\n if (store.shutdown) {\n await store.shutdown();\n }\n throw new Error(getServerStartupErrorMessage(error, port));\n }\n\n const url = `http://localhost:${port}`;\n appLogger.info(\"server.listen\", { port, url });\n\n return {\n url,\n shutdown: () => {\n appLogger.info(\"server.shutdown\", { port });\n server.close();\n if (store.shutdown) {\n void store.shutdown();\n }\n },\n };\n}\n","import { Hono } from \"hono\";\nimport {\n handleGetAgents,\n handleGetBookmarks,\n handleGetConfig,\n handleGetDashboard,\n handleGetFileActivity,\n handleGetProjects,\n handleDeleteBookmark,\n handleImportBookmarks,\n handlePostClientLog,\n handleSearchSessions,\n handleGetSessions,\n handleGetSessionData,\n handlePutBookmark,\n type ScanResultSource,\n type SessionListDefaults,\n} from \"./handlers.js\";\nimport type { LiveScanStore } from \"../live-scan.js\";\n\nexport interface ApiRouteOptions {\n defaultSessionFrom?: number;\n defaultSessionTo?: number;\n defaultSessionDays?: number;\n}\n\nfunction createSseResponse(store: LiveScanStore, signal: AbortSignal): Response {\n const encoder = new TextEncoder();\n\n return new Response(\n new ReadableStream({\n start(controller) {\n const write = (event: string, data: unknown) => {\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\n const unsubscribe = store.subscribe((event) => {\n write(event.type, event);\n });\n\n const heartbeat = setInterval(() => {\n controller.enqueue(encoder.encode(\": keepalive\\n\\n\"));\n }, 15000);\n\n const close = () => {\n clearInterval(heartbeat);\n unsubscribe();\n controller.close();\n };\n\n signal.addEventListener(\"abort\", close, { once: true });\n },\n cancel() {\n return;\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 store?: LiveScanStore,\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 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.post(\"/logs\", (c) => handlePostClientLog(c));\n if (store) {\n api.get(\"/events\", (c) => createSseResponse(store, 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),\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 type { Context } from \"hono\";\nimport type {\n BookmarkRecord,\n ProjectGroup,\n ScanResult,\n SessionData,\n SessionHead,\n SmartTag,\n} from \"@codesesh/core\";\nimport {\n BookmarkStorageUnavailableError,\n deleteBookmark,\n extractSessionFileActivity,\n getAgentInfoMap,\n classifySessionTags,\n computeIdentity,\n getSmartTagSourceTimestamp,\n importBookmarks,\n listFileActivity,\n listCachedProjectGroups,\n listBookmarks,\n parseSearchQuery,\n realFs,\n searchFileActivitySessions,\n searchSessions,\n upsertBookmark,\n type FileActivityKind,\n type FileActivityResult,\n type SearchMatchType,\n type SearchOptions,\n type SearchQueryFilters,\n} from \"@codesesh/core\";\nimport { appLogger } from \"../logging.js\";\n\nexport interface ScanResultSource {\n getSnapshot(): ScanResult;\n}\n\nexport interface SessionListDefaults {\n from?: number;\n to?: number;\n /** When --days was used, original value — kept for UI \"last N days\" label */\n days?: number;\n}\n\ninterface ClientLogPayload {\n event?: unknown;\n data?: unknown;\n}\n\ninterface ApiSearchResult {\n agentName: string;\n session: SessionHead;\n snippet: string;\n matchType: SearchMatchType;\n}\n\ninterface ApiProjectAgentStat {\n name: string;\n sessions: number;\n messages: number;\n tokens: number;\n cost: number;\n}\n\ninterface ApiProjectGroup extends ProjectGroup {\n messages: number;\n tokens: number;\n cost: number;\n cost_source?: SessionHead[\"stats\"][\"cost_source\"];\n agentStats: ApiProjectAgentStat[];\n}\n\ninterface DashboardScope {\n agent?: string;\n projectKind?: string;\n projectKey?: string;\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,\n stats: value.stats,\n };\n}\n\nfunction getTotalTokens(stats: SessionHead[\"stats\"]): number {\n return stats.total_tokens ?? stats.total_input_tokens + stats.total_output_tokens;\n}\n\nfunction getSessionAgentName(session: SessionHead): string {\n return session.slug.split(\"/\")[0]?.toLowerCase() || \"unknown\";\n}\n\nfunction getSessionActivityTime(session: SessionHead): number {\n return session.time_updated ?? session.time_created;\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(c: Context, defaults: SessionListDefaults): 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 projectKey: optionalQueryValue(params.get(\"projectKey\") ?? undefined),\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 filterSessionsByWindow(\n sessions: SessionHead[],\n from: number | undefined,\n to: number | undefined,\n): SessionHead[] {\n return filterSessionsByActivityWindow(sessions, from, to);\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 matchesProjectScope(session: SessionHead, cwd: string): boolean {\n if (!session.directory) return false;\n const identity = computeIdentity(cwd, realFs);\n if (session.project_identity?.key === identity.key) return true;\n return session.directory.toLowerCase().includes(cwd.toLowerCase());\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 sessionMatchesCostFilter(session: SessionHead, options: SearchOptions): boolean {\n const cost = session.stats.total_cost;\n if (options.costMin != null) {\n if (options.costMinExclusive ? cost <= options.costMin : cost < options.costMin) return false;\n }\n if (options.costMax != null) {\n if (options.costMaxExclusive ? cost >= options.costMax : cost > options.costMax) return false;\n }\n return true;\n}\n\nfunction mergeSearchLists<T>(left: T[] | undefined, right: T[] | undefined): T[] | undefined {\n const values = [...(left ?? []), ...(right ?? [])];\n return values.length > 0 ? [...new Set(values)] : undefined;\n}\n\nfunction mergeSearchOptions(options: SearchOptions, filters: SearchQueryFilters): SearchOptions {\n return {\n ...options,\n agent: options.agent ?? filters.agent,\n project: options.project ?? filters.project,\n projectKey: options.projectKey ?? filters.projectKey,\n cwd: options.cwd ?? filters.cwd,\n tags: mergeSearchLists(options.tags, filters.tags),\n tools: mergeSearchLists(options.tools, filters.tools),\n file: options.file ?? filters.file,\n fileKind: options.fileKind ?? filters.fileKind,\n costMin: options.costMin ?? filters.costMin,\n costMax: options.costMax ?? filters.costMax,\n costMinExclusive: options.costMinExclusive ?? filters.costMinExclusive,\n costMaxExclusive: options.costMaxExclusive ?? filters.costMaxExclusive,\n };\n}\n\nfunction mergeSearchResults(results: ApiSearchResult[], limit: number): ApiSearchResult[] {\n const seen = new Set<string>();\n const merged: ApiSearchResult[] = [];\n\n for (const result of results) {\n const key = `${result.agentName}/${result.session.id}`;\n if (seen.has(key)) continue;\n seen.add(key);\n merged.push(result);\n if (merged.length >= limit) break;\n }\n\n return merged;\n}\n\nfunction 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\nfunction matchesDashboardScope(session: SessionHead, scope: DashboardScope): boolean {\n if (scope.agent && getSessionAgentName(session) !== scope.agent) return false;\n if (scope.projectKey) {\n const identity = session.project_identity;\n if (!identity || identity.key !== scope.projectKey) return false;\n if (scope.projectKind && identity.kind !== scope.projectKind) return false;\n }\n return true;\n}\n\nfunction filterSessionsByDashboardScope(\n sessions: SessionHead[],\n scope: DashboardScope,\n): SessionHead[] {\n if (!scope.agent && !scope.projectKey) return sessions;\n return sessions.filter((session) => matchesDashboardScope(session, scope));\n}\n\nfunction matchesRecentSearchFilters(session: SessionHead, options: SearchOptions): boolean {\n if (options.projectKey && session.project_identity?.key !== options.projectKey) return false;\n if (options.cwd && !matchesProjectScope(session, options.cwd)) return false;\n if (options.project) {\n const projectNeedle = options.project.toLowerCase();\n const projectText = [\n session.project_identity?.key,\n session.project_identity?.displayName,\n session.directory,\n ]\n .filter(Boolean)\n .join(\"\\n\")\n .toLowerCase();\n if (!projectText.includes(projectNeedle)) return false;\n }\n if (options.tags?.length && !options.tags.every((tag) => session.smart_tags?.includes(tag))) {\n return false;\n }\n if (!sessionMatchesCostFilter(session, options)) return false;\n return true;\n}\n\nfunction recentSearchSessions(\n scanResult: ScanResult,\n options: SearchOptions & { limit: number },\n): ApiSearchResult[] {\n const entries = options.agent\n ? ([[options.agent, scanResult.byAgent[options.agent] ?? []]] as Array<[string, SessionHead[]]>)\n : Object.entries(scanResult.byAgent);\n\n return entries\n .flatMap(([agentName, sessions]) =>\n filterSessionsByActivityWindow(sessions, options.from, options.to)\n .filter((session) => matchesRecentSearchFilters(session, options))\n .map((session) => ({ agentName, session })),\n )\n .toSorted(\n (a, b) =>\n (b.session.time_updated ?? b.session.time_created) -\n (a.session.time_updated ?? a.session.time_created),\n )\n .slice(0, options.limit)\n .map(({ agentName, session }) => ({\n agentName,\n session,\n snippet: `Recent session · ${session.directory}`,\n matchType: \"recent\",\n }));\n}\n\nexport function handleGetConfig(c: Context, defaults: SessionListDefaults) {\n return c.json({\n window: {\n from: defaults.from,\n to: defaults.to,\n days: defaults.days,\n },\n });\n}\n\nexport function handleGetAgents(\n c: Context,\n scanSource: ScanResultSource,\n defaults: SessionListDefaults = {},\n) {\n const scanResult = scanSource.getSnapshot();\n const { from, to } = defaults;\n const counts = Object.fromEntries(\n Object.entries(scanResult.byAgent).map(([agentName, sessions]) => [\n agentName,\n filterSessionsByWindow(sessions, from, to).length,\n ]),\n );\n const info = getAgentInfoMap(counts);\n return c.json(info);\n}\n\nexport function handleGetProjects(\n c: Context,\n scanSource: ScanResultSource,\n defaults: SessionListDefaults = {},\n) {\n const scanResult = scanSource.getSnapshot();\n const { from, to } = defaults;\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 projectKey = c.req.query(\"projectKey\");\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 (projectKey) {\n sessions = sessions.filter((s) => s.project_identity?.key === projectKey);\n } else if (cwd) {\n sessions = sessions.filter((s) => matchesProjectScope(s, cwd));\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 if (q) {\n sessions = sessions.filter((s) => s.title.toLowerCase().includes(q));\n }\n\n return c.json({ sessions });\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 searchOptions = parseSearchOptions(c, defaults);\n const parsedQuery = parseSearchQuery(query);\n const mergedSearchOptions = mergeSearchOptions(searchOptions, parsedQuery.filters);\n const textQuery = parsedQuery.text || (parsedQuery.hasQualifiers ? \"\" : query);\n const needsIndexedSearch = Boolean(\n textQuery ||\n mergedSearchOptions.file ||\n mergedSearchOptions.fileKind ||\n mergedSearchOptions.tools?.length,\n );\n\n if (!needsIndexedSearch) {\n return c.json({\n results: recentSearchSessions(\n scanResult,\n mergedSearchOptions as SearchOptions & { limit: number },\n ),\n });\n }\n\n const fileQuery =\n mergedSearchOptions.file ??\n (!parsedQuery.text ? parsedQuery.filters.file : undefined) ??\n (!parsedQuery.hasQualifiers && query ? parsedQuery.text || query : \"\");\n const results: ApiSearchResult[] = mergeSearchResults(\n [\n ...(fileQuery ? searchFileActivitySessions(fileQuery, mergedSearchOptions) : []),\n ...searchSessions(query, mergedSearchOptions),\n ],\n mergedSearchOptions.limit ?? 50,\n );\n\n return c.json({ results });\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\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\n return c.json({\n activity: listFileActivity({\n agent: optionalQueryValue(c.req.query(\"agent\")),\n sessionId: optionalQueryValue(c.req.query(\"sessionId\")),\n projectKey: optionalQueryValue(c.req.query(\"projectKey\")),\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 }),\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 (!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 loadStartedAt = performance.now();\n const data: SessionData = agent.getSessionData(sessionId);\n const loadDuration = performance.now() - loadStartedAt;\n const tagStartedAt = performance.now();\n const smartTags = classifySessionTags(data);\n const tagDuration = performance.now() - tagStartedAt;\n const head = scanResult.byAgent[agentName]?.find((item) => item.id === sessionId);\n const projectIdentity =\n data.project_identity ?? head?.project_identity ?? computeIdentity(data.directory, realFs);\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 return c.json({\n ...data,\n project_identity: projectIdentity,\n smart_tags: smartTags,\n smart_tags_source_updated_at: getSmartTagSourceTimestamp(data),\n file_activity: extractSessionFileActivity(\n agentName,\n sessionId,\n projectIdentity.key,\n data.messages,\n ),\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 return c.json({ bookmarks: listBookmarks(), storageAvailable: true });\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 interface DashboardAgentStat {\n name: string;\n displayName: string;\n icon: string;\n sessions: number;\n messages: number;\n tokens: number;\n}\n\nexport interface DashboardDailyBucket {\n /** Local YYYY-MM-DD */\n date: string;\n sessions: number;\n messages: number;\n}\n\nexport interface DailyTokenBucket {\n date: string;\n input: number;\n output: number;\n cache_read: number;\n cache_create: number;\n}\n\nexport interface ModelDistributionEntry {\n model: string;\n tokens: number;\n sessions: number;\n}\n\nexport interface DashboardTotals {\n sessions: number;\n messages: number;\n tokens: number;\n cost: number;\n cost_source?: \"recorded\" | \"estimated\";\n latestActivity?: number;\n}\n\nexport interface DashboardRecentSession extends SessionHead {\n agentName: string;\n}\n\nexport interface DashboardData {\n totals: DashboardTotals;\n perAgent: DashboardAgentStat[];\n dailyActivity: DashboardDailyBucket[];\n dailyTokenActivity: DailyTokenBucket[];\n modelDistribution: ModelDistributionEntry[];\n recentSessions: DashboardRecentSession[];\n recentFileActivities: FileActivityResult[];\n /** Time window covered by dailyActivity (inclusive, ms) */\n window: { from: number; to: number; days: number };\n}\n\nfunction toLocalDateKey(ts: number): string {\n const d = new Date(ts);\n const year = d.getFullYear();\n const month = `${d.getMonth() + 1}`.padStart(2, \"0\");\n const day = `${d.getDate()}`.padStart(2, \"0\");\n return `${year}-${month}-${day}`;\n}\n\nfunction startOfLocalDay(ts: number): number {\n const d = new Date(ts);\n d.setHours(0, 0, 0, 0);\n return d.getTime();\n}\n\nfunction resolveDashboardWindow(\n defaults: SessionListDefaults,\n queryDays: string | undefined,\n queryFrom: string | undefined,\n queryTo: string | undefined,\n): { from: number; to: number; days: number } {\n const now = Date.now();\n\n const toTs = parseDateParam(queryTo, defaults.to) ?? now;\n\n // Resolve days (preferred): query, defaults.days, or derive from defaults.from\n const parsedDays = queryDays ? parseInt(queryDays, 10) : NaN;\n let days: number | undefined =\n Number.isFinite(parsedDays) && parsedDays > 0 ? parsedDays : defaults.days;\n\n const fromFromQuery = parseDateParam(queryFrom, undefined);\n let fromTs: number;\n if (fromFromQuery != null) {\n fromTs = fromFromQuery;\n days ??= Math.max(1, Math.ceil((toTs - fromTs) / 86400000));\n } else if (defaults.from != null) {\n fromTs = defaults.from;\n days ??= Math.max(1, Math.ceil((toTs - fromTs) / 86400000));\n } else if (days && days > 0) {\n fromTs = startOfLocalDay(toTs) - (days - 1) * 86400000;\n } else {\n days = 30;\n fromTs = startOfLocalDay(toTs) - (days - 1) * 86400000;\n }\n\n return { from: fromTs, to: toTs, days };\n}\n\nexport function handleGetDashboard(\n c: Context,\n scanSource: ScanResultSource,\n defaults: SessionListDefaults = {},\n) {\n const scanResult = scanSource.getSnapshot();\n const { from, to, days } = resolveDashboardWindow(\n defaults,\n c.req.query(\"days\"),\n c.req.query(\"from\"),\n c.req.query(\"to\"),\n );\n const scope: DashboardScope = {\n agent: optionalQueryValue(c.req.query(\"agent\"))?.toLowerCase(),\n projectKind: optionalQueryValue(c.req.query(\"projectKind\")),\n projectKey: optionalQueryValue(c.req.query(\"projectKey\")),\n };\n\n const scopedSessions = filterSessionsByDashboardScope(scanResult.sessions, scope);\n const windowed = filterSessionsByActivityWindow(scopedSessions, from, to);\n const scopedByAgent = Object.fromEntries(\n Object.entries(scanResult.byAgent)\n .filter(([name]) => !scope.agent || name.toLowerCase() === scope.agent)\n .map(([name, sessions]) => [name, filterSessionsByDashboardScope(sessions, scope)]),\n );\n\n const agentInfo = getAgentInfoMap(\n Object.fromEntries(\n Object.entries(scopedByAgent).map(([name, sessions]) => [\n name,\n filterSessionsByActivityWindow(sessions, from, to).length,\n ]),\n ),\n );\n const agentInfoMap = new Map(agentInfo.map((a) => [a.name, a]));\n\n let totalMessages = 0;\n let totalTokens = 0;\n let totalCost = 0;\n let hasEstimatedCost = false;\n let latestActivity = 0;\n for (const session of windowed) {\n totalMessages += session.stats.message_count;\n totalTokens += getTotalTokens(session.stats);\n totalCost += session.stats.total_cost ?? 0;\n if (session.stats.cost_source === \"estimated\") hasEstimatedCost = true;\n const activity = getSessionActivityTime(session);\n if (activity > latestActivity) latestActivity = activity;\n }\n\n const perAgent: DashboardAgentStat[] = Object.entries(scopedByAgent)\n .map(([name, sessions]) => {\n const info = agentInfoMap.get(name);\n const agentWindowed = filterSessionsByActivityWindow(sessions, from, to);\n let messages = 0;\n let tokens = 0;\n for (const s of agentWindowed) {\n messages += s.stats.message_count;\n tokens += getTotalTokens(s.stats);\n }\n return {\n name,\n displayName: info?.displayName ?? name,\n icon: info?.icon ?? \"\",\n sessions: agentWindowed.length,\n messages,\n tokens,\n };\n })\n .filter((item) => item.sessions > 0)\n .sort((a, b) => b.sessions - a.sessions);\n\n // Daily activity buckets — one bucket per local day in [from, to]\n const dailyMap = new Map<string, DashboardDailyBucket>();\n const dailyTokenMap = new Map<string, DailyTokenBucket>();\n const bucketStart = startOfLocalDay(from);\n const bucketDays = Math.floor((startOfLocalDay(to) - bucketStart) / 86400000) + 1;\n for (let i = 0; i < bucketDays; i += 1) {\n const ts = bucketStart + i * 86400000;\n const key = toLocalDateKey(ts);\n dailyMap.set(key, { date: key, sessions: 0, messages: 0 });\n dailyTokenMap.set(key, { date: key, input: 0, output: 0, cache_read: 0, cache_create: 0 });\n }\n\n const modelAgg = new Map<string, { tokens: number; sessions: number }>();\n\n for (const session of windowed) {\n const key = toLocalDateKey(getSessionActivityTime(session));\n const bucket = dailyMap.get(key);\n if (bucket) {\n bucket.sessions += 1;\n bucket.messages += session.stats.message_count;\n }\n\n const tokenBucket = dailyTokenMap.get(key);\n if (tokenBucket) {\n const cacheRead = session.stats.total_cache_read_tokens ?? 0;\n const cacheCreate = session.stats.total_cache_create_tokens ?? 0;\n const pureInput = session.stats.total_input_tokens - cacheRead - cacheCreate;\n tokenBucket.input += Math.max(0, pureInput);\n tokenBucket.output += session.stats.total_output_tokens;\n tokenBucket.cache_read += cacheRead;\n tokenBucket.cache_create += cacheCreate;\n }\n\n if (session.model_usage) {\n for (const [model, tokens] of Object.entries(session.model_usage)) {\n const entry = modelAgg.get(model);\n if (entry) {\n entry.tokens += tokens;\n entry.sessions += 1;\n } else {\n modelAgg.set(model, { tokens, sessions: 1 });\n }\n }\n }\n }\n\n const dailyActivity = [...dailyMap.values()];\n const dailyTokenActivity = [...dailyTokenMap.values()];\n\n const modelDistribution: ModelDistributionEntry[] = [...modelAgg.entries()]\n .map(([model, { tokens, sessions: count }]) => ({ model, tokens, sessions: count }))\n .sort((a, b) => b.tokens - a.tokens);\n\n const recentSessions: DashboardRecentSession[] = [...windowed]\n .sort((a, b) => getSessionActivityTime(b) - getSessionActivityTime(a))\n .slice(0, 10)\n .map((session) => {\n const agentKey = getSessionAgentName(session);\n return { ...session, agentName: agentKey };\n });\n\n const data: DashboardData = {\n totals: {\n sessions: windowed.length,\n messages: totalMessages,\n tokens: totalTokens,\n cost: totalCost,\n cost_source: totalCost > 0 ? (hasEstimatedCost ? \"estimated\" : \"recorded\") : undefined,\n latestActivity: latestActivity || undefined,\n },\n perAgent,\n dailyActivity,\n dailyTokenActivity,\n modelDistribution,\n recentSessions,\n recentFileActivities: listFileActivity({\n agent: scope.agent,\n projectKey: scope.projectKey,\n from,\n to,\n limit: 12,\n }),\n window: { from, to, days },\n };\n\n return c.json(data);\n}\n","import { existsSync, readdirSync, statSync, watch, type FSWatcher } from \"node:fs\";\nimport { dirname, isAbsolute, join, relative, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { Worker } from \"node:worker_threads\";\nimport {\n createRegisteredAgents,\n filterSessions,\n getCursorDataPath,\n resolveProviderRoots,\n scanSessions,\n syncSessionSearchIndex,\n saveCachedSessions,\n type BaseAgent,\n type ScanResult,\n type ScanOptions,\n type SessionCacheMeta,\n type SessionHead,\n} from \"@codesesh/core\";\nimport type { SearchIndexWorkerMessage } from \"./search-index-worker.js\";\nimport { appLogger, logSearchIndexSync } from \"./logging.js\";\n\nexport interface SessionsUpdatedEvent {\n type: \"sessions-updated\";\n changedAgents: string[];\n newSessions: number;\n updatedSessions: number;\n removedSessions: number;\n totalSessions: number;\n timestamp: number;\n}\n\ntype StoreListener = (event: SessionsUpdatedEvent) => void;\n\ninterface 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\nconst REFRESH_DEBOUNCE_MS = 200;\nconst EMPTY_AGENT_REFRESH_DEBOUNCE_MS = 30_000;\nconst PENDING_REFRESH_DELAY_MS = 100;\nconst WRITE_STABILITY_THRESHOLD_MS = 250;\nconst WRITE_STABILITY_POLL_MS = 100;\nconst NEW_SESSION_EVENT_WINDOW_MS = 250;\nconst SEARCH_INDEX_BULK_PENDING_PATH_THRESHOLD = 100;\n\nfunction sortSessions(sessions: SessionHead[]): SessionHead[] {\n return [...sessions].sort(\n (a, b) => (b.time_updated ?? b.time_created) - (a.time_updated ?? a.time_created),\n );\n}\n\nfunction sessionSignature(session: SessionHead): string {\n return JSON.stringify([\n session.title,\n session.directory,\n session.time_created,\n session.time_updated ?? session.time_created,\n session.stats.message_count,\n session.stats.total_input_tokens,\n session.stats.total_output_tokens,\n session.stats.total_cost,\n session.stats.total_tokens ?? 0,\n ]);\n}\n\nfunction buildAgentCacheMeta(agent: BaseAgent): Record<string, SessionCacheMeta> {\n const metaMap = agent.getSessionMetaMap?.();\n const meta: Record<string, SessionCacheMeta> = {};\n if (!metaMap) return meta;\n\n for (const [id, data] of metaMap.entries()) {\n meta[id] = { id, ...(data as Record<string, unknown>) } as SessionCacheMeta;\n }\n\n return meta;\n}\n\nfunction buildUpdateEvent(\n agentName: string,\n previousSessions: SessionHead[],\n nextSessions: SessionHead[],\n): SessionsUpdatedEvent | null {\n const previousMap = new Map(previousSessions.map((session) => [session.id, session]));\n const nextMap = new Map(nextSessions.map((session) => [session.id, session]));\n\n let newSessions = 0;\n let updatedSessions = 0;\n let removedSessions = 0;\n\n for (const [id, session] of nextMap.entries()) {\n const previous = previousMap.get(id);\n if (!previous) {\n newSessions += 1;\n continue;\n }\n if (sessionSignature(previous) !== sessionSignature(session)) {\n updatedSessions += 1;\n }\n }\n\n for (const id of previousMap.keys()) {\n if (!nextMap.has(id)) {\n removedSessions += 1;\n }\n }\n\n if (newSessions === 0 && updatedSessions === 0 && removedSessions === 0) {\n return null;\n }\n\n return {\n type: \"sessions-updated\",\n changedAgents: [agentName],\n newSessions,\n updatedSessions,\n removedSessions,\n totalSessions: nextSessions.length,\n timestamp: Date.now(),\n };\n}\n\nfunction 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\nfunction isRecursiveWatchSupported(\n platform = 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 mergeEvents(\n previous: SessionsUpdatedEvent,\n next: SessionsUpdatedEvent,\n): SessionsUpdatedEvent {\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 };\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 [{ root: roots.codexRoot, path: join(roots.codexRoot, \"sessions\") }];\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 default:\n return [];\n }\n}\n\nexport class LiveScanStore {\n private agents: BaseAgent[] = [];\n private byAgent: Record<string, SessionHead[]> = {};\n private sessions: SessionHead[] = [];\n private listeners = new Set<StoreListener>();\n private refreshTimers = new Map<string, NodeJS.Timeout>();\n private refreshTimestamps = new Map<string, number>();\n private refreshInFlight = new Set<string>();\n private pendingRefreshes = new Set<string>();\n private pendingRefreshPathCounts = new Map<string, number>();\n private watchers: FSWatcher[] = [];\n private fallbackWatchScopes = new Map<string, WatchScope[]>();\n private stablePaths = new Map<string, StablePathState>();\n private pendingEvent: SessionsUpdatedEvent | null = null;\n private pendingEventTimer: NodeJS.Timeout | null = null;\n private initialSearchIndexTimer: NodeJS.Timeout | null = null;\n private searchIndexWorker: Worker | null = null;\n\n constructor(\n private readonly watchEnabled = true,\n private readonly scanOptions: ScanOptions = {},\n private readonly startupScanOptions: Pick<ScanOptions, \"from\" | \"to\"> = {},\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 });\n const initialResult = await scanSessions({\n ...this.scanOptions,\n ...this.startupScanOptions,\n useCache: this.scanOptions.useCache ?? true,\n smartRefresh: false,\n writeCache:\n this.startupScanOptions.from != null || this.startupScanOptions.to != null\n ? false\n : undefined,\n includeSmartTags:\n this.startupScanOptions.from != null || this.startupScanOptions.to != null\n ? false\n : undefined,\n });\n this.applyScanResult(initialResult);\n appLogger.info(\"scan.initial.done\", {\n duration_ms: Math.round(performance.now() - startedAt),\n sessions: this.sessions.length,\n agents: Object.fromEntries(\n Object.entries(this.byAgent).map(([key, value]) => [key, value.length]),\n ),\n });\n if (this.watchEnabled) {\n this.startWatching();\n this.initialSearchIndexTimer = setTimeout(() => {\n this.initialSearchIndexTimer = null;\n this.startSearchIndexWorker(\"scan.initial.background\");\n }, 1000);\n }\n }\n\n getSnapshot(): ScanResult {\n return {\n sessions: this.sessions,\n byAgent: this.byAgent,\n agents: this.agents,\n };\n }\n\n subscribe(listener: StoreListener): () => void {\n this.listeners.add(listener);\n return () => {\n this.listeners.delete(listener);\n };\n }\n\n async shutdown(): Promise<void> {\n for (const timer of this.refreshTimers.values()) {\n clearTimeout(timer);\n }\n this.refreshTimers.clear();\n this.pendingRefreshPathCounts.clear();\n\n for (const state of this.stablePaths.values()) {\n if (state.timer) {\n clearTimeout(state.timer);\n }\n }\n this.stablePaths.clear();\n\n if (this.pendingEventTimer) {\n clearTimeout(this.pendingEventTimer);\n this.pendingEventTimer = null;\n }\n if (this.initialSearchIndexTimer) {\n clearTimeout(this.initialSearchIndexTimer);\n this.initialSearchIndexTimer = null;\n }\n if (this.searchIndexWorker) {\n await this.searchIndexWorker.terminate();\n this.searchIndexWorker = null;\n }\n this.pendingEvent = null;\n\n await Promise.all(this.watchers.map((watcher) => watcher.close()));\n this.watchers = [];\n this.fallbackWatchScopes.clear();\n }\n\n private emit(event: SessionsUpdatedEvent): void {\n if (this.pendingEvent || event.newSessions > 0) {\n this.queueEvent(event);\n return;\n }\n\n this.emitNow(event);\n }\n\n private emitNow(event: SessionsUpdatedEvent): void {\n for (const listener of this.listeners) {\n listener(event);\n }\n }\n\n private queueEvent(event: SessionsUpdatedEvent): void {\n this.pendingEvent = this.pendingEvent ? mergeEvents(this.pendingEvent, event) : event;\n if (this.pendingEventTimer) {\n return;\n }\n\n this.pendingEventTimer = setTimeout(() => {\n const pending = this.pendingEvent;\n this.pendingEvent = null;\n this.pendingEventTimer = null;\n if (pending) {\n this.emitNow(pending);\n }\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 hasStartupWindow(): boolean {\n return this.startupScanOptions.from != null || this.startupScanOptions.to != null;\n }\n\n private getSearchIndexWorkerUrl(): URL | null {\n const workerUrl = new URL(\"./search-index-worker.js\", import.meta.url);\n if (workerUrl.protocol === \"file:\" && !existsSync(fileURLToPath(workerUrl))) {\n return null;\n }\n return workerUrl;\n }\n\n private startSearchIndexWorker(context: string): void {\n if (this.searchIndexWorker) return;\n\n const workerUrl = this.getSearchIndexWorkerUrl();\n if (!workerUrl) {\n appLogger.warn(\"search_index.worker_missing\", { context });\n return;\n }\n\n const worker = new Worker(workerUrl, {\n workerData: {\n context,\n agentNames: this.agents.map((agent) => agent.name),\n sessionsByAgent: this.byAgent,\n metaByAgent: Object.fromEntries(\n this.agents.map((agent) => [agent.name, buildAgentCacheMeta(agent)]),\n ),\n },\n });\n worker.unref();\n this.searchIndexWorker = worker;\n\n worker.on(\"message\", (message: SearchIndexWorkerMessage) => {\n if (message.type === \"sync-result\") {\n logSearchIndexSync(message.context, message.result);\n } else if (message.type === \"done\") {\n appLogger.info(`${message.context}.done`, {\n duration_ms: Math.round(message.durationMs),\n sessions: message.sessions,\n });\n }\n });\n worker.on(\"error\", (error) => {\n appLogger.error(\"search_index.worker_error\", { context, error });\n });\n worker.on(\"exit\", (code) => {\n this.searchIndexWorker = null;\n if (code !== 0) {\n appLogger.warn(\"search_index.worker_exit\", { context, code });\n }\n });\n }\n\n private applyScanResult(result: ScanResult): void {\n const knownAgents = createRegisteredAgents();\n const agentMap = new Map<string, BaseAgent>();\n const allowedAgents = this.getAllowedAgents();\n\n for (const agent of result.agents) {\n agentMap.set(agent.name, agent);\n }\n for (const agent of knownAgents) {\n if (!agentMap.has(agent.name)) {\n agentMap.set(agent.name, agent);\n }\n }\n\n this.agents = [...agentMap.values()].filter((agent) => {\n if (!allowedAgents) {\n return true;\n }\n return allowedAgents.has(agent.name.toLowerCase());\n });\n\n this.byAgent = {};\n for (const agent of this.agents) {\n this.byAgent[agent.name] = sortSessions(result.byAgent[agent.name] ?? []);\n this.refreshTimestamps.set(agent.name, Date.now());\n }\n\n this.rebuildSessions();\n }\n\n private getAllowedAgents(): Set<string> | null {\n if (!this.scanOptions.agents?.length) {\n return null;\n }\n return new Set(this.scanOptions.agents.map((agent) => agent.toLowerCase()));\n }\n\n private applyFilters(sessions: SessionHead[]): SessionHead[] {\n return filterSessions(sessions, { ...this.scanOptions, ...this.startupScanOptions });\n }\n\n private startWatching(): void {\n const scopesByRoot = new Map<string, WatchScope[]>();\n\n for (const agent of this.agents) {\n const watchTargets = resolveAgentWatchTargets(agent.name);\n\n if (watchTargets.length === 0) {\n appLogger.debug(\"watch.skip\", { agent: agent.name });\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 === agent.name && scope.targetPath === targetPath)\n ) {\n scopes.push({ agentName: agent.name, targetPath });\n }\n scopesByRoot.set(rootPath, scopes);\n }\n }\n\n for (const [rootPath, scopes] of scopesByRoot.entries()) {\n const agents = Array.from(new Set(scopes.map((scope) => scope.agentName)));\n appLogger.info(\"watch.start\", {\n root: rootPath,\n agents,\n targets: scopes.map((scope) => ({\n agent: scope.agentName,\n path: scope.targetPath,\n })),\n });\n\n if (isRecursiveWatchSupported()) {\n const started = this.watchDirectory(rootPath, scopes, true);\n if (started) {\n continue;\n }\n }\n\n this.watchDirectoryTree(rootPath, scopes);\n }\n }\n\n 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.scheduleRefreshForAgents(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.scheduleRefreshForAgents(state.agentNames);\n return;\n }\n\n state.timer = setTimeout(() => this.pollStablePath(path), WRITE_STABILITY_POLL_MS);\n }\n\n private scheduleRefreshForAgents(agentNames: Set<string>): void {\n for (const agentName of agentNames) {\n this.pendingRefreshPathCounts.set(\n agentName,\n (this.pendingRefreshPathCounts.get(agentName) ?? 0) + 1,\n );\n const delayMs =\n (this.byAgent[agentName]?.length ?? 0) === 0\n ? EMPTY_AGENT_REFRESH_DEBOUNCE_MS\n : REFRESH_DEBOUNCE_MS;\n this.scheduleRefresh(agentName, delayMs);\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 private scheduleRefresh(agentName: string, delayMs = REFRESH_DEBOUNCE_MS): void {\n appLogger.debug(\"scan.refresh.schedule\", { agent: agentName, delay_ms: delayMs });\n const existing = this.refreshTimers.get(agentName);\n if (existing) {\n clearTimeout(existing);\n }\n\n const timer = setTimeout(() => {\n this.refreshTimers.delete(agentName);\n void this.refreshAgent(agentName);\n }, delayMs);\n\n this.refreshTimers.set(agentName, timer);\n }\n\n private async refreshAgent(agentName: string): Promise<void> {\n if (this.refreshInFlight.has(agentName)) {\n appLogger.debug(\"scan.refresh.pending\", { agent: agentName });\n this.pendingRefreshes.add(agentName);\n return;\n }\n\n this.refreshInFlight.add(agentName);\n\n try {\n 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 } finally {\n this.refreshInFlight.delete(agentName);\n\n if (this.pendingRefreshes.delete(agentName)) {\n this.scheduleRefresh(agentName, PENDING_REFRESH_DELAY_MS);\n }\n }\n }\n\n private async runRefresh(agentName: string): Promise<void> {\n const startedAt = performance.now();\n const pendingPathCount = this.pendingRefreshPathCounts.get(agentName) ?? 0;\n this.pendingRefreshPathCounts.delete(agentName);\n const agent = this.agents.find((item) => item.name === agentName);\n if (!agent) {\n appLogger.warn(\"scan.refresh.missing_agent\", { agent: agentName });\n return;\n }\n\n const previousSessions = this.byAgent[agentName] ?? [];\n let nextSessions = previousSessions;\n\n if (!agent.isAvailable()) {\n nextSessions = [];\n this.refreshTimestamps.set(agentName, Date.now());\n } else if (previousSessions.length > 0 && agent.checkForChanges && agent.incrementalScan) {\n const checkResult = await Promise.resolve(\n agent.checkForChanges(this.refreshTimestamps.get(agentName) ?? 0, previousSessions),\n );\n\n this.refreshTimestamps.set(agentName, checkResult.timestamp);\n if (!checkResult.hasChanges) {\n appLogger.debug(\"scan.refresh.unchanged\", {\n agent: agentName,\n duration_ms: Math.round(performance.now() - startedAt),\n });\n return;\n }\n\n nextSessions = await Promise.resolve(\n agent.incrementalScan(previousSessions, checkResult.changedIds ?? []),\n );\n } else {\n nextSessions = await Promise.resolve(agent.scan(this.startupScanOptions));\n this.refreshTimestamps.set(agentName, Date.now());\n }\n\n nextSessions = this.applyFilters(nextSessions);\n if (!this.hasStartupWindow()) {\n saveCachedSessions(agentName, nextSessions, buildAgentCacheMeta(agent));\n }\n const searchIndexOptions =\n pendingPathCount >= SEARCH_INDEX_BULK_PENDING_PATH_THRESHOLD ? { isBulk: true } : undefined;\n const syncResult = searchIndexOptions\n ? syncSessionSearchIndex(\n agentName,\n nextSessions,\n (sessionId) => agent.getSessionData(sessionId),\n searchIndexOptions,\n )\n : syncSessionSearchIndex(agentName, nextSessions, (sessionId) =>\n agent.getSessionData(sessionId),\n );\n logSearchIndexSync(\"scan.refresh\", syncResult, { pending_paths: pendingPathCount });\n\n const event = buildUpdateEvent(agentName, previousSessions, nextSessions);\n this.byAgent[agentName] = sortSessions(nextSessions);\n this.rebuildSessions();\n\n if (event) {\n event.totalSessions = this.sessions.length;\n this.emit(event);\n }\n appLogger.info(\"scan.refresh.done\", {\n agent: agentName,\n duration_ms: Math.round(performance.now() - startedAt),\n sessions: nextSessions.length,\n new_sessions: event?.newSessions ?? 0,\n updated_sessions: event?.updatedSessions ?? 0,\n removed_sessions: event?.removedSessions ?? 0,\n pending_paths: pendingPathCount,\n search_index_mode: syncResult?.mode,\n search_index_rebuild_duration_ms:\n syncResult?.rebuildDurationMs == null\n ? undefined\n : Math.round(syncResult.rebuildDurationMs),\n });\n }\n}\n","import { consola } from \"consola\";\nimport type { BaseAgent } from \"@codesesh/core\";\nimport type { ScanResult } from \"@codesesh/core\";\nimport { VERSION } from \"./version.js\";\n\nexport function printScanResults(agents: BaseAgent[], result: ScanResult): void {\n consola.log(\"\");\n consola.box({\n title: \"CodeSesh\",\n message: `v${VERSION} • ${result.sessions.length} sessions discovered`,\n style: {\n padding: 1,\n borderColor: \"cyan\",\n },\n });\n consola.log(\"\");\n\n const rows: string[] = [];\n let availableCount = 0;\n\n for (const agent of agents) {\n const sessions = result.byAgent[agent.name];\n const count = sessions?.length ?? 0;\n if (count > 0) {\n availableCount++;\n rows.push(` ${green(\"✔\")} ${pad(agent.displayName)} ${dim(`${count} sessions`)}`);\n } else {\n rows.push(` ${dim(\"✖\")} ${pad(agent.displayName)} ${dim(\"not found\")}`);\n }\n }\n\n consola.log(rows.join(\"\\n\"));\n consola.log(\"\");\n consola.info(`Active: ${availableCount}/${agents.length} agents`);\n consola.log(\"\");\n}\n\nfunction pad(text: string, length = 16): string {\n return text.padEnd(length);\n}\n\nfunction green(text: string): string {\n return `\\x1b[32m${text}\\x1b[0m`;\n}\n\nfunction dim(text: string): string {\n return `\\x1b[2m${text}\\x1b[0m`;\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"],"mappings":"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","names":["Hono","existsSync","__dirname","existsSync","resolve","Hono","url","existsSync","readdirSync","statSync","dirname","join","resolve","fileURLToPath","resolve","existsSync","dirname","statSync","join","fileURLToPath","readdirSync","resolve","dirname","fileURLToPath"]}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
createRegisteredAgents,
|
|
4
|
+
syncSessionSearchIndex
|
|
5
|
+
} from "./chunk-SQYHWMQV.js";
|
|
6
|
+
|
|
7
|
+
// src/search-index-worker.ts
|
|
8
|
+
import { parentPort, workerData } from "worker_threads";
|
|
9
|
+
var data = workerData;
|
|
10
|
+
var startedAt = performance.now();
|
|
11
|
+
var agents = createRegisteredAgents();
|
|
12
|
+
for (const agentName of data.agentNames) {
|
|
13
|
+
const agent = agents.find((item) => item.name === agentName);
|
|
14
|
+
if (!agent) continue;
|
|
15
|
+
const meta = data.metaByAgent[agentName];
|
|
16
|
+
if (meta && agent.setSessionMetaMap) {
|
|
17
|
+
agent.setSessionMetaMap(new Map(Object.entries(meta)));
|
|
18
|
+
}
|
|
19
|
+
const sessions = data.sessionsByAgent[agentName] ?? [];
|
|
20
|
+
const result = syncSessionSearchIndex(
|
|
21
|
+
agentName,
|
|
22
|
+
sessions,
|
|
23
|
+
(sessionId) => agent.getSessionData(sessionId)
|
|
24
|
+
);
|
|
25
|
+
parentPort?.postMessage({
|
|
26
|
+
type: "sync-result",
|
|
27
|
+
context: data.context,
|
|
28
|
+
result
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
parentPort?.postMessage({
|
|
32
|
+
type: "done",
|
|
33
|
+
context: data.context,
|
|
34
|
+
durationMs: performance.now() - startedAt,
|
|
35
|
+
sessions: Object.values(data.sessionsByAgent).reduce(
|
|
36
|
+
(total, sessions) => total + sessions.length,
|
|
37
|
+
0
|
|
38
|
+
)
|
|
39
|
+
});
|
|
40
|
+
//# sourceMappingURL=search-index-worker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/search-index-worker.ts"],"sourcesContent":["import { parentPort, workerData } from \"node:worker_threads\";\nimport {\n createRegisteredAgents,\n syncSessionSearchIndex,\n type SearchIndexSyncResult,\n type SessionCacheMeta,\n type SessionHead,\n} from \"@codesesh/core\";\n\nexport type SearchIndexWorkerMessage =\n | {\n type: \"sync-result\";\n context: string;\n result: SearchIndexSyncResult | null;\n }\n | {\n type: \"done\";\n context: string;\n durationMs: number;\n sessions: number;\n };\n\ninterface SearchIndexWorkerData {\n context: string;\n agentNames: string[];\n sessionsByAgent: Record<string, SessionHead[]>;\n metaByAgent: Record<string, Record<string, SessionCacheMeta>>;\n}\n\nconst data = workerData as SearchIndexWorkerData;\nconst startedAt = performance.now();\nconst agents = createRegisteredAgents();\n\nfor (const agentName of data.agentNames) {\n const agent = agents.find((item) => item.name === agentName);\n if (!agent) continue;\n\n const meta = data.metaByAgent[agentName];\n if (meta && agent.setSessionMetaMap) {\n agent.setSessionMetaMap(new Map(Object.entries(meta)));\n }\n\n const sessions = data.sessionsByAgent[agentName] ?? [];\n const result = syncSessionSearchIndex(agentName, sessions, (sessionId) =>\n agent.getSessionData(sessionId),\n );\n parentPort?.postMessage({\n type: \"sync-result\",\n context: data.context,\n result,\n } satisfies SearchIndexWorkerMessage);\n}\n\nparentPort?.postMessage({\n type: \"done\",\n context: data.context,\n durationMs: performance.now() - startedAt,\n sessions: Object.values(data.sessionsByAgent).reduce(\n (total, sessions) => total + sessions.length,\n 0,\n ),\n} satisfies SearchIndexWorkerMessage);\n"],"mappings":";;;;;;;AAAA,SAAS,YAAY,kBAAkB;AA6BvC,IAAM,OAAO;AACb,IAAM,YAAY,YAAY,IAAI;AAClC,IAAM,SAAS,uBAAuB;AAEtC,WAAW,aAAa,KAAK,YAAY;AACvC,QAAM,QAAQ,OAAO,KAAK,CAAC,SAAS,KAAK,SAAS,SAAS;AAC3D,MAAI,CAAC,MAAO;AAEZ,QAAM,OAAO,KAAK,YAAY,SAAS;AACvC,MAAI,QAAQ,MAAM,mBAAmB;AACnC,UAAM,kBAAkB,IAAI,IAAI,OAAO,QAAQ,IAAI,CAAC,CAAC;AAAA,EACvD;AAEA,QAAM,WAAW,KAAK,gBAAgB,SAAS,KAAK,CAAC;AACrD,QAAM,SAAS;AAAA,IAAuB;AAAA,IAAW;AAAA,IAAU,CAAC,cAC1D,MAAM,eAAe,SAAS;AAAA,EAChC;AACA,cAAY,YAAY;AAAA,IACtB,MAAM;AAAA,IACN,SAAS,KAAK;AAAA,IACd;AAAA,EACF,CAAoC;AACtC;AAEA,YAAY,YAAY;AAAA,EACtB,MAAM;AAAA,EACN,SAAS,KAAK;AAAA,EACd,YAAY,YAAY,IAAI,IAAI;AAAA,EAChC,UAAU,OAAO,OAAO,KAAK,eAAe,EAAE;AAAA,IAC5C,CAAC,OAAO,aAAa,QAAQ,SAAS;AAAA,IACtC;AAAA,EACF;AACF,CAAoC;","names":[]}
|