@zhangferry-dev/tokendash 1.4.0 → 1.5.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 +32 -40
- package/dist/client/assets/{index-B4YgU_cb.js → index-BPWY9q0y.js} +45 -45
- package/dist/client/index.html +1 -1
- package/dist/client/popover.html +44 -17
- package/dist/electron-server.cjs +180 -53
- package/dist/electron-server.cjs.map +3 -3
- package/dist/server/analyticsParser.js +66 -2
- package/dist/server/claudeBlocksParser.js +48 -5
- package/dist/server/claudeJsonlParser.d.ts +6 -0
- package/dist/server/claudeJsonlParser.js +53 -4
- package/dist/server/codexParser.d.ts +10 -7
- package/dist/server/codexParser.js +83 -57
- package/dist/server/index.d.ts +4 -0
- package/dist/server/index.js +25 -9
- package/electron/main.cjs +67 -12
- package/electron/preload.cjs +3 -0
- package/electron/trayBadge.cjs +3 -1
- package/electron/trayHelper +0 -0
- package/electron/trayHelper.swift +38 -16
- package/electron-builder.yml +4 -1
- package/package.json +1 -1
- package/resources/icon.icns +0 -0
- package/resources/product_menu.png +0 -0
- package/resources/cache_diagram.html +0 -456
- package/resources/cache_diagram.png +0 -0
- package/resources/pr1_preview.png +0 -0
- package/resources/test_single_agent.png +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/server/index.ts", "../src/server/cache.ts", "../src/shared/schemas.ts", "../src/server/codexParser.ts", "../src/server/codexPricing.ts", "../src/server/openclawParser.ts", "../src/server/opencodeParser.ts", "../src/server/claudeJsonlParser.ts", "../src/server/routes/daily.ts", "../src/server/routes/monthly.ts", "../src/server/routes/session.ts", "../src/server/routes/projects.ts", "../src/server/routes/blocks.ts", "../src/server/analyticsParser.ts", "../src/server/routes/analytics.ts", "../src/server/agentDetection.ts", "../src/server/routes/api.ts"],
|
|
4
|
-
"sourcesContent": ["import express from 'express';\nimport type { Express } from 'express';\nimport { readFileSync } from 'node:fs';\nimport type { Server } from 'node:http';\nimport { fileURLToPath } from 'node:url';\nimport { dirname, join } from 'node:path';\nimport { registerApiRoutes } from './routes/api.js';\nimport { detectAvailableAgents } from './agentDetection.js';\nimport open from 'open';\n\ninterface CliArgs {\n port?: number;\n noOpen?: boolean;\n showVersion?: boolean;\n tray?: boolean;\n}\n\nconst CLI_USAGE = [\n 'Usage:',\n ' tokendash',\n ' tokendash --version',\n ' tokendash --port <number> [--no-open]',\n ' tokendash --tray [--port <number>]',\n].join('\\n');\n\nfunction getPackageVersion(): string {\n const __filename = fileURLToPath(import.meta.url);\n const __dirname = dirname(__filename);\n const packageJson = JSON.parse(readFileSync(join(__dirname, '..', '..', 'package.json'), 'utf8')) as { version?: string };\n return packageJson.version ?? 'unknown';\n}\n\nfunction exitWithCliError(message: string): never {\n console.error(message);\n console.error(`\\n${CLI_USAGE}`);\n process.exit(1);\n}\n\nfunction parseCliArgs(): CliArgs {\n const args = process.argv.slice(2);\n const result: CliArgs = {};\n\n if (args.length === 1 && (args[0] === '--version' || args[0] === '-v')) {\n result.showVersion = true;\n return result;\n }\n\n for (let i = 0; i < args.length; i++) {\n const arg = args[i];\n\n if (arg === '--version' || arg === '-v') {\n exitWithCliError('The --version flag must be used by itself.');\n }\n\n if (arg === '--port') {\n if (i + 1 >= args.length) {\n exitWithCliError('Missing value for --port.');\n }\n\n const value = parseInt(args[i + 1], 10);\n if (!Number.isInteger(value) || value <= 0) {\n exitWithCliError(`Invalid port value: ${args[i + 1]}`);\n }\n\n result.port = value;\n i++;\n } else if (arg === '--no-open') {\n result.noOpen = true;\n } else if (arg === '--tray') {\n result.tray = true;\n } else {\n exitWithCliError(`Unsupported argument: ${arg}`);\n }\n }\n\n return result;\n}\n\nasync function ensureUsageSupportAvailable(): Promise<boolean> {\n try {\n const agents = detectAvailableAgents();\n if (!agents.claude && !agents.codex) {\n console.error('Error: No AI coding assistant data found.');\n console.error('\\nDetails: Could not find Claude Code (~/.claude/projects/) or Codex (~/.codex/sessions/) data.');\n console.error('Please install at least one of: Claude Code or Codex CLI.');\n return false;\n }\n if (agents.claude) console.log(' \u2713 Claude Code detected');\n if (agents.codex) console.log(' \u2713 Codex detected');\n return true;\n } catch (error) {\n console.error('Error: failed to detect available AI coding assistants');\n console.error('\\nDetails:', error instanceof Error ? error.message : error);\n return false;\n }\n}\n\nfunction resolvePort(value?: number): number {\n return Number.isInteger(value) && value && value > 0 ? value : 3456;\n}\n\nfunction listen(app: Express, port: number): Promise<Server> {\n return new Promise((resolve, reject) => {\n const server = app.listen(port);\n\n const handleListening = () => {\n cleanup();\n resolve(server);\n };\n\n const handleError = (error: Error) => {\n cleanup();\n reject(error);\n };\n\n const cleanup = () => {\n server.off('listening', handleListening);\n server.off('error', handleError);\n };\n\n server.once('listening', handleListening);\n server.once('error', handleError);\n });\n}\n\nasync function listenWithPortFallback(app: Express, preferredPort: number): Promise<{ server: Server; port: number; usedFallback: boolean }> {\n let port = preferredPort;\n\n for (let attempt = 0; attempt < 20; attempt++, port++) {\n try {\n const server = await listen(app, port);\n return { server, port, usedFallback: port !== preferredPort };\n } catch (error) {\n const err = error as NodeJS.ErrnoException;\n if (err.code !== 'EADDRINUSE') {\n throw error;\n }\n }\n }\n\n throw new Error(`Could not find an available port starting from ${preferredPort}`);\n}\n\nexport function createApp(_port: number, baseDir?: string): Express {\n const app = express();\n const router = express.Router();\n\n // Register API routes\n registerApiRoutes(router);\n app.use('/api', router);\n\n // Resolve paths: use provided baseDir or compute from import.meta.url\n const _baseDir = baseDir ?? dirname(fileURLToPath(import.meta.url));\n const isProduction = baseDir\n ? true\n : import.meta.url.includes('dist/');\n const popoverPath = isProduction\n ? join(_baseDir, 'client', 'popover.html')\n : join(_baseDir, '..', '..', 'public', 'popover.html');\n\n app.get('/popover.html', (_req, res) => {\n res.sendFile(popoverPath);\n });\n\n // Check if running from dist (production build)\n if (isProduction) {\n // Serve static files from client build\n const clientPath = join(_baseDir, 'client');\n const clientIndexPath = join(clientPath, 'index.html');\n\n app.use(express.static(clientPath));\n\n // SPA fallback\n app.use('{*path}', (_req, res) => {\n res.sendFile(clientIndexPath);\n });\n }\n\n return app;\n}\n\nasync function main() {\n const args = parseCliArgs();\n if (args.showVersion) {\n console.log(getPackageVersion());\n return;\n }\n\n const version = getPackageVersion();\n const preferredPort = resolvePort(args.port ?? (process.env.PORT ? parseInt(process.env.PORT, 10) : undefined));\n\n // --tray mode: launch Electron\n if (args.tray) {\n if (process.platform !== 'darwin') {\n console.error('Error: --tray is only supported on macOS.');\n process.exit(1);\n }\n console.log(`Starting tokendash v${version} in tray mode...`);\n // @ts-ignore -- electron is installed separately for tray mode\n const { default: electronPath } = await import('electron');\n const { spawn } = await import('node:child_process');\n const child = spawn(electronPath as unknown as string, ['.'], {\n env: {\n ...process.env,\n TOKENDASH_PORT: String(preferredPort),\n TOKENDASH_TRAY: '1',\n },\n stdio: 'inherit',\n });\n child.on('close', (code) => process.exit(code ?? 0));\n process.on('SIGTERM', () => child.kill('SIGTERM'));\n return;\n }\n\n const shouldOpenBrowser = !args.noOpen;\n\n console.log(`Starting tokendash v${version}...`);\n console.log(`Checking local usage data sources...`);\n\n const isUsageSupportAvailable = await ensureUsageSupportAvailable();\n if (!isUsageSupportAvailable) {\n process.exit(1);\n }\n\n const app = createApp(preferredPort);\n const { server, port, usedFallback } = await listenWithPortFallback(app, preferredPort);\n\n if (usedFallback) {\n console.warn(`tokendash detected that port ${preferredPort} is already in use, switched to http://localhost:${port}`);\n }\n\n console.log(`tokendash running on http://localhost:${port}`);\n console.log(`API available at http://localhost:${port}/api`);\n const isProduction = import.meta.url.includes('dist/');\n if (isProduction) {\n console.log('Serving production build');\n } else {\n console.log('Development mode - use \"npm run dev\" for full dev experience');\n }\n\n // Open browser if requested\n if (shouldOpenBrowser) {\n // Small delay to ensure server is ready\n setTimeout(() => {\n console.log('Opening dashboard in your browser...');\n open(`http://localhost:${port}`).catch((err) => {\n console.warn('Could not open browser:', err.message);\n });\n }, 100);\n } else {\n console.log('Browser auto-open disabled (--no-open)');\n }\n\n // Graceful shutdown\n process.on('SIGTERM', () => {\n server.close(() => {\n console.log('Server closed');\n process.exit(0);\n });\n });\n}\n\nexport { main };\n", "import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { tmpdir } from 'node:os';\n\nconst DEFAULT_TTL = 5 * 60 * 1000; // 5 minutes (fresh)\nconst DISK_TTL = 60 * 60 * 1000; // 1 hour (stale but usable)\n\nconst CACHE_DIR = join(tmpdir(), 'tokendash-cache');\n\ninterface CacheEntry<T> {\n data: T;\n expiresAt: number;\n updatedAt: number;\n}\n\nfunction diskPath(key: string): string {\n const safe = key.replace(/[^a-zA-Z0-9_-]/g, '_');\n return join(CACHE_DIR, `${safe}.json`);\n}\n\nclass Cache {\n private store = new Map<string, CacheEntry<unknown>>();\n\n get<T>(key: string): T | null {\n const entry = this.store.get(key);\n if (entry && Date.now() <= entry.expiresAt) {\n return entry.data as T;\n }\n return null;\n }\n\n /** Get data even if stale (for stale-while-revalidate) */\n getStale<T>(key: string): T | null {\n // Try memory first\n const entry = this.store.get(key);\n if (entry) return entry.data as T;\n\n // Try disk\n return this.readFromDisk<T>(key);\n }\n\n set<T>(key: string, data: T, ttl: number = DEFAULT_TTL): void {\n const entry: CacheEntry<T> = {\n data,\n expiresAt: Date.now() + ttl,\n updatedAt: Date.now(),\n };\n this.store.set(key, entry as CacheEntry<unknown>);\n this.writeToDisk(key, entry);\n }\n\n clear(): void {\n this.store.clear();\n }\n\n delete(key: string): boolean {\n return this.store.delete(key);\n }\n\n has(key: string): boolean {\n const entry = this.store.get(key);\n if (!entry) return false;\n if (Date.now() > entry.expiresAt) {\n this.store.delete(key);\n return false;\n }\n return true;\n }\n\n private writeToDisk<T>(key: string, entry: CacheEntry<T>): void {\n try {\n if (!existsSync(CACHE_DIR)) mkdirSync(CACHE_DIR, { recursive: true });\n writeFileSync(diskPath(key), JSON.stringify(entry), 'utf-8');\n } catch {\n // Disk cache is best-effort\n }\n }\n\n private readFromDisk<T>(key: string): T | null {\n try {\n const path = diskPath(key);\n if (!existsSync(path)) return null;\n const raw = readFileSync(path, 'utf-8');\n const entry = JSON.parse(raw) as CacheEntry<T>;\n // Only use disk cache if less than DISK_TTL old\n if (Date.now() - entry.updatedAt < DISK_TTL) {\n // Promote to memory cache (with 0 TTL so it'll be treated as stale)\n this.store.set(key, { ...entry, expiresAt: 0 } as CacheEntry<unknown>);\n return entry.data;\n }\n } catch {\n // Disk cache is best-effort\n }\n return null;\n }\n}\n\nexport const cache = new Cache();\nexport type { CacheEntry };\n", "import { z } from 'zod';\n\nexport const ModelBreakdownSchema = z.object({\n modelName: z.string(),\n inputTokens: z.number().default(0),\n outputTokens: z.number().default(0),\n cacheCreationTokens: z.number().default(0),\n cacheReadTokens: z.number().default(0),\n cost: z.number().default(0),\n});\n\nexport const DailyEntrySchema = z.object({\n date: z.string(),\n inputTokens: z.number().default(0),\n outputTokens: z.number().default(0),\n cacheCreationTokens: z.number().default(0),\n cacheReadTokens: z.number().default(0),\n totalTokens: z.number().default(0),\n totalCost: z.number().default(0),\n modelsUsed: z.array(z.string()).default([]),\n modelBreakdowns: z.array(ModelBreakdownSchema).default([]),\n});\n\nexport const TotalsSchema = z.object({\n inputTokens: z.number().default(0),\n outputTokens: z.number().default(0),\n cacheCreationTokens: z.number().default(0),\n cacheReadTokens: z.number().default(0),\n totalTokens: z.number().default(0),\n totalCost: z.number().default(0),\n});\n\nexport const DailyResponseSchema = z.object({\n daily: z.array(DailyEntrySchema).default([]),\n totals: TotalsSchema,\n});\n\nexport const ProjectEntrySchema = z.object({\n projectPath: z.string(),\n instances: z.array(DailyEntrySchema).default([]),\n});\n\nexport const ProjectsResponseSchema = z.object({\n projects: z.record(z.array(DailyEntrySchema).default([])).default({}),\n});\n\nexport function validateDaily(data: unknown) {\n return DailyResponseSchema.parse(data);\n}\n\nexport function validateProjects(data: unknown) {\n return ProjectsResponseSchema.parse(data);\n}\n\nconst BlockEntrySchema = z.object({\n id: z.string(),\n startTime: z.string(),\n endTime: z.string(),\n actualEndTime: z.string().nullable().default(null),\n isActive: z.boolean().default(false),\n isGap: z.boolean().default(false),\n entries: z.number().default(0),\n tokenCounts: z.object({\n inputTokens: z.number().default(0),\n outputTokens: z.number().default(0),\n cacheCreationInputTokens: z.number().default(0),\n cacheReadInputTokens: z.number().default(0),\n }).default({ inputTokens: 0, outputTokens: 0, cacheCreationInputTokens: 0, cacheReadInputTokens: 0 }),\n totalTokens: z.number().default(0),\n costUSD: z.number().default(0),\n models: z.array(z.string()).default([]),\n});\n\nexport const BlocksResponseSchema = z.object({\n blocks: z.array(BlockEntrySchema).default([]),\n});\n\nexport function validateBlocks(data: unknown) {\n return BlocksResponseSchema.parse(data);\n}\n\n// --- Analytics schemas ---\n\nconst DailyCodeChangeSchema = z.object({\n date: z.string(),\n linesAdded: z.number().default(0),\n linesDeleted: z.number().default(0),\n netChange: z.number().default(0),\n filesModified: z.number().default(0),\n});\n\nconst ToolUsageEntrySchema = z.object({\n name: z.string(),\n count: z.number().default(0),\n});\n\nconst ProductivityKPIsSchema = z.object({\n avgLinesPerEdit: z.number().default(0),\n filesModifiedPerDay: z.number().default(0),\n addDeleteRatio: z.number().default(0),\n totalEdits: z.number().default(0),\n totalFilesModified: z.number().default(0),\n activeDaysWithEdits: z.number().default(0),\n});\n\nconst AnalyticsResponseSchema = z.object({\n codeChangeTrend: z.array(DailyCodeChangeSchema).default([]),\n toolUsageDistribution: z.array(ToolUsageEntrySchema).default([]),\n productivityKPIs: ProductivityKPIsSchema,\n toolCallTrend: z.array(z.record(z.union([z.string(), z.number()]))).default([]),\n});\n\nexport function validateAnalytics(data: unknown) {\n return AnalyticsResponseSchema.parse(data);\n}\n", "import { readFileSync, readdirSync, statSync, accessSync, constants } from 'node:fs';\nimport { join } from 'node:path';\nimport { homedir } from 'node:os';\nimport { z } from 'zod';\nimport type { DailyEntry, DailyResponse, ProjectsResponse, BlockEntry, BlocksResponse, Totals, ModelBreakdown } from '../shared/types.js';\nimport { calculateCost } from './codexPricing.js';\n\n// ---------------------------------------------------------------------------\n// Zod schemas for JSONL event validation (format change detector)\n// ---------------------------------------------------------------------------\n\nconst TokenUsageSchema = z.object({\n input_tokens: z.number().default(0),\n cached_input_tokens: z.number().default(0),\n output_tokens: z.number().default(0),\n reasoning_output_tokens: z.number().default(0),\n total_tokens: z.number().default(0),\n}).default({ input_tokens: 0, cached_input_tokens: 0, output_tokens: 0, reasoning_output_tokens: 0, total_tokens: 0 });\n\nconst TokenCountInfoSchema = z.object({\n total_token_usage: TokenUsageSchema,\n last_token_usage: TokenUsageSchema,\n}).nullable().default(null);\n\nconst TokenCountPayloadSchema = z.object({\n type: z.literal('token_count'),\n info: TokenCountInfoSchema,\n});\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ninterface ParsedTokenEvent {\n timestamp: string;\n inputTokens: number;\n cachedInputTokens: number;\n outputTokens: number;\n reasoningOutputTokens: number;\n totalTokens: number;\n}\n\nexport interface ParsedSession {\n id: string;\n cwd: string;\n model: string;\n createdAt: string;\n tokenEvents: ParsedTokenEvent[];\n}\n\nexport interface AggregateOptions {\n groupBy: 'day' | 'hour' | 'month' | 'session' | 'project';\n project?: string | null;\n since?: Date | null;\n until?: Date | null;\n timezone?: string;\n}\n\ninterface TokenAccumulator {\n inputTokens: number;\n cachedInputTokens: number;\n outputTokens: number;\n reasoningOutputTokens: number;\n totalTokens: number;\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction getSessionsDir(): string {\n return join(homedir(), '.codex', 'sessions');\n}\n\nexport function isSessionsDirAccessible(): boolean {\n try {\n accessSync(getSessionsDir(), constants.R_OK);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Recursively find all .jsonl files under ~/.codex/sessions/\n */\nexport function scanCodexSessions(): string[] {\n const sessionsDir = getSessionsDir();\n const results: string[] = [];\n\n function walk(dir: string): void {\n let entries;\n try {\n entries = readdirSync(dir);\n } catch {\n return;\n }\n for (const entry of entries) {\n const full = join(dir, entry);\n let st: ReturnType<typeof statSync>;\n try {\n st = statSync(full);\n } catch {\n continue;\n }\n if (st.isDirectory()) {\n walk(full);\n } else if (entry.endsWith('.jsonl')) {\n results.push(full);\n }\n }\n }\n\n walk(sessionsDir);\n return results.sort();\n}\n\n/**\n * Parse a single Codex session JSONL file.\n *\n * CRITICAL INVARIANT: Sum ALL token_count events without any deduplication.\n * Each Codex turn emits TWO token_count events with identical last_token_usage\n * values (~1-2s apart) \u2014 one for reasoning, one for output completion.\n * Both are distinct billable events. Deduplicating would produce the wrong\n * total (4.7M instead of the correct 9.2M).\n */\nexport function parseCodexSession(filepath: string): ParsedSession | null {\n let content: string;\n try {\n content = readFileSync(filepath, 'utf-8');\n } catch {\n return null;\n }\n\n const lines = content.split('\\n');\n let sessionId = '';\n let cwd = '';\n let model = '';\n let createdAt = '';\n const tokenEvents: ParsedTokenEvent[] = [];\n\n for (const line of lines) {\n const trimmed = line.trim();\n if (!trimmed) continue;\n\n let obj: Record<string, unknown>;\n try {\n obj = JSON.parse(trimmed) as Record<string, unknown>;\n } catch {\n continue;\n }\n\n const type = obj.type as string;\n\n if (type === 'session_meta') {\n const payload = (obj.payload as Record<string, unknown>) || {};\n sessionId = (payload.id as string) || '';\n cwd = (payload.cwd as string) || '';\n createdAt = (payload.timestamp as string) || '';\n }\n\n if (type === 'turn_context') {\n const payload = (obj.payload as Record<string, unknown>) || {};\n if (!model && payload.model) {\n model = payload.model as string;\n }\n }\n\n // Extract token counts from event_msg with nested token_count payload.\n // NEVER deduplicate \u2014 see invariant comment above.\n if (type === 'event_msg') {\n const payload = (obj.payload as Record<string, unknown>) || {};\n if (payload.type === 'token_count') {\n const timestamp = (obj.timestamp as string) || '';\n const parseResult = TokenCountPayloadSchema.safeParse(payload);\n if (!parseResult.success) {\n console.warn(`[codexParser] Schema validation failed in ${filepath}:`, parseResult.error.message);\n continue;\n }\n const info = parseResult.data.info;\n if (!info) continue;\n const last = info.last_token_usage;\n tokenEvents.push({\n timestamp,\n inputTokens: last.input_tokens,\n cachedInputTokens: last.cached_input_tokens,\n outputTokens: last.output_tokens,\n reasoningOutputTokens: last.reasoning_output_tokens,\n totalTokens: last.total_tokens,\n });\n }\n }\n }\n\n if (!sessionId) return null;\n\n return { id: sessionId, cwd, model, createdAt, tokenEvents };\n}\n\n/** Parse all Codex sessions. */\nexport function parseAllSessions(): ParsedSession[] {\n return scanCodexSessions()\n .map(parseCodexSession)\n .filter((s): s is ParsedSession => s !== null);\n}\n\n// ---------------------------------------------------------------------------\n// Date/timezone helpers\n// ---------------------------------------------------------------------------\n\nconst TZ_OFFSETS: Record<string, number> = {\n 'Asia/Shanghai': 8,\n 'Asia/Tokyo': 9,\n 'America/New_York': -5,\n 'America/Los_Angeles': -8,\n 'Europe/London': 0,\n 'UTC': 0,\n};\n\nfunction getTzOffsetHours(tz: string): number {\n return TZ_OFFSETS[tz] ?? 8; // Default Asia/Shanghai\n}\n\nfunction toLocalISO(ts: string, tz: string): Date {\n const d = new Date(ts);\n return new Date(d.getTime() + getTzOffsetHours(tz) * 3600_000);\n}\n\nfunction getDateKey(ts: string, tz: string): string {\n return toLocalISO(ts, tz).toISOString().slice(0, 10);\n}\n\nfunction getHourKey(ts: string, tz: string): string {\n const local = toLocalISO(ts, tz);\n return local.toISOString().slice(0, 13).replace('T', ' ') + ':00';\n}\n\nfunction getMonthKey(ts: string, tz: string): string {\n return getDateKey(ts, tz).slice(0, 7);\n}\n\nfunction extractProjectName(cwd: string): string {\n if (!cwd) return 'unknown';\n const parts = cwd.replace(/\\/+$/, '').split('/');\n return parts[parts.length - 1] || 'unknown';\n}\n\n// ---------------------------------------------------------------------------\n// Core aggregation\n// ---------------------------------------------------------------------------\n\nfunction emptyAcc(): TokenAccumulator {\n return { inputTokens: 0, cachedInputTokens: 0, outputTokens: 0, reasoningOutputTokens: 0, totalTokens: 0 };\n}\n\nfunction addAcc(a: TokenAccumulator, ev: ParsedTokenEvent): void {\n a.inputTokens += ev.inputTokens;\n a.cachedInputTokens += ev.cachedInputTokens;\n a.outputTokens += ev.outputTokens;\n a.reasoningOutputTokens += ev.reasoningOutputTokens;\n a.totalTokens += ev.totalTokens;\n}\n\nfunction mergeAcc(a: TokenAccumulator, b: TokenAccumulator): void {\n a.inputTokens += b.inputTokens;\n a.cachedInputTokens += b.cachedInputTokens;\n a.outputTokens += b.outputTokens;\n a.reasoningOutputTokens += b.reasoningOutputTokens;\n a.totalTokens += b.totalTokens;\n}\n\nfunction accToEntry(date: string, acc: TokenAccumulator, models: Set<string>): DailyEntry {\n const cost = calculateCost(acc, models);\n return {\n date,\n inputTokens: acc.inputTokens,\n outputTokens: acc.outputTokens,\n cacheCreationTokens: 0,\n cacheReadTokens: acc.cachedInputTokens,\n totalTokens: acc.totalTokens,\n totalCost: cost,\n modelsUsed: [...models],\n modelBreakdowns: buildModelBreakdowns(acc, models, cost),\n };\n}\n\nfunction buildModelBreakdowns(acc: TokenAccumulator, models: Set<string>, totalCost: number): ModelBreakdown[] {\n const modelList = [...models];\n if (modelList.length === 0) return [];\n const costPerModel = totalCost / modelList.length;\n return modelList.map(name => ({\n modelName: name,\n inputTokens: acc.inputTokens,\n outputTokens: acc.outputTokens,\n cacheCreationTokens: 0,\n cacheReadTokens: acc.cachedInputTokens,\n cost: costPerModel,\n }));\n}\n\ntype GroupKey = string;\n\nfunction groupSessions(\n sessions: ParsedSession[],\n options: AggregateOptions,\n): Map<GroupKey, { acc: TokenAccumulator; models: Set<string> }> {\n const tz = options.timezone || 'Asia/Shanghai';\n const grouped = new Map<GroupKey, { acc: TokenAccumulator; models: Set<string> }>();\n\n for (const session of sessions) {\n if (options.project && extractProjectName(session.cwd) !== options.project) continue;\n\n for (const ev of session.tokenEvents) {\n const evDate = new Date(ev.timestamp);\n if (options.since && evDate < options.since) continue;\n if (options.until && evDate > options.until) continue;\n\n let key: string;\n switch (options.groupBy) {\n case 'hour': key = getHourKey(ev.timestamp, tz); break;\n case 'month': key = getMonthKey(ev.timestamp, tz); break;\n case 'session': key = session.id; break;\n case 'project': key = extractProjectName(session.cwd); break;\n default: key = getDateKey(ev.timestamp, tz); break;\n }\n\n if (!grouped.has(key)) {\n grouped.set(key, { acc: emptyAcc(), models: new Set() });\n }\n const entry = grouped.get(key)!;\n addAcc(entry.acc, ev);\n if (session.model) entry.models.add(session.model);\n }\n }\n\n return grouped;\n}\n\n// ---------------------------------------------------------------------------\n// Public API \u2014 response builders for route handlers\n// ---------------------------------------------------------------------------\n\n/** Aggregate and return DailyResponse format (for /daily?agent=codex) */\nexport function getDailyResponse(options?: Partial<AggregateOptions>): DailyResponse {\n const sessions = parseAllSessions();\n const grouped = groupSessions(sessions, { groupBy: 'day', ...options });\n\n const daily: DailyEntry[] = [];\n const totalsAcc = emptyAcc();\n\n for (const [date, { acc, models }] of grouped) {\n daily.push(accToEntry(date, acc, models));\n mergeAcc(totalsAcc, acc);\n }\n\n // Sort by date ascending\n daily.sort((a, b) => a.date.localeCompare(b.date));\n\n const models = new Set<string>();\n for (const s of sessions) if (s.model) models.add(s.model);\n const totalCost = calculateCost(totalsAcc, models);\n\n return {\n daily,\n totals: {\n inputTokens: totalsAcc.inputTokens,\n outputTokens: totalsAcc.outputTokens,\n cacheCreationTokens: 0,\n cacheReadTokens: totalsAcc.cachedInputTokens,\n totalTokens: totalsAcc.totalTokens,\n totalCost,\n },\n };\n}\n\n/** Aggregate and return ProjectsResponse format (for /projects?agent=codex) */\nexport function getProjectsResponse(options?: Partial<AggregateOptions>): ProjectsResponse {\n const sessions = parseAllSessions();\n const tz = options?.timezone || 'Asia/Shanghai';\n const projects: Record<string, DailyEntry[]> = {};\n\n for (const session of sessions) {\n const projectName = extractProjectName(session.cwd);\n\n // Per-project daily grouping\n const dailyMap = new Map<string, { acc: TokenAccumulator; models: Set<string> }>();\n for (const ev of session.tokenEvents) {\n const evDate = new Date(ev.timestamp);\n if (options?.since && evDate < options.since) continue;\n if (options?.until && evDate > options.until) continue;\n\n const dayKey = getDateKey(ev.timestamp, tz);\n if (!dailyMap.has(dayKey)) {\n dailyMap.set(dayKey, { acc: emptyAcc(), models: new Set() });\n }\n addAcc(dailyMap.get(dayKey)!.acc, ev);\n if (session.model) dailyMap.get(dayKey)!.models.add(session.model);\n }\n\n if (!projects[projectName]) projects[projectName] = [];\n for (const [date, { acc, models }] of dailyMap) {\n projects[projectName].push(accToEntry(date, acc, models));\n }\n }\n\n // Sort each project's daily entries\n for (const key of Object.keys(projects)) {\n projects[key].sort((a, b) => a.date.localeCompare(b.date));\n }\n\n return { projects };\n}\n\n/** Aggregate and return BlocksResponse format (hourly, for /blocks?agent=codex) */\nexport function getBlocksResponse(options?: Partial<AggregateOptions>): BlocksResponse {\n const sessions = parseAllSessions();\n const grouped = groupSessions(sessions, { groupBy: 'hour', ...options });\n\n const blocks: BlockEntry[] = [];\n let idx = 0;\n\n for (const [hourKey, { acc, models }] of grouped) {\n const cost = calculateCost(acc, models);\n const [datePart, timePart] = hourKey.split(' ');\n const hour = timePart.split(':')[0];\n\n blocks.push({\n id: `codex-hour-${idx}`,\n startTime: `${datePart}T${hour}:00:00`,\n endTime: `${datePart}T${hour}:59:59`,\n actualEndTime: null,\n isActive: false,\n isGap: false,\n entries: acc.totalTokens > 0 ? 1 : 0,\n tokenCounts: {\n inputTokens: acc.inputTokens,\n outputTokens: acc.outputTokens,\n cacheCreationInputTokens: 0,\n cacheReadInputTokens: acc.cachedInputTokens,\n },\n totalTokens: acc.totalTokens,\n costUSD: cost,\n models: [...models],\n });\n idx++;\n }\n\n // Sort by startTime\n blocks.sort((a, b) => a.startTime.localeCompare(b.startTime));\n\n return { blocks };\n}\n", "/**\n * Codex token pricing configuration.\n *\n * Pricing formula (confirmed by reverse-engineering @ccusage/codex):\n * cost = (inputTokens - cachedInputTokens) * input_rate\n * + cachedInputTokens * cached_rate\n * + outputTokens * output_rate\n *\n * Reasoning tokens are NOT billed separately (included in outputTokens).\n *\n * Update rates from https://openai.com/api/pricing/ when models change.\n * All prices are USD per 1M tokens.\n */\n\ninterface ModelPricing {\n inputPer1M: number;\n cachedInputPer1M: number;\n outputPer1M: number;\n}\n\nconst MODEL_PRICING: Record<string, ModelPricing> = {\n 'gpt-5.4': {\n inputPer1M: 2.50,\n cachedInputPer1M: 0.25,\n outputPer1M: 15.00,\n },\n};\n\nconst DEFAULT_PRICING: ModelPricing = {\n inputPer1M: 2.50,\n cachedInputPer1M: 0.25,\n outputPer1M: 15.00,\n};\n\ninterface TokenCounts {\n inputTokens: number;\n cachedInputTokens: number;\n outputTokens: number;\n reasoningOutputTokens: number;\n totalTokens: number;\n}\n\n/**\n * Calculate cost in USD from token counts and model pricing.\n * Matches the @ccusage/codex calculateCostUSD function exactly.\n */\nexport function calculateCost(tokens: TokenCounts, models: Set<string>): number {\n const model = [...models][0] ?? '';\n const pricing = MODEL_PRICING[model] ?? DEFAULT_PRICING;\n\n const nonCachedInput = Math.max(tokens.inputTokens - tokens.cachedInputTokens, 0);\n const cachedInput = Math.min(tokens.cachedInputTokens, tokens.inputTokens);\n const outputTokens = tokens.outputTokens;\n\n const inputCost = (nonCachedInput / 1_000_000) * pricing.inputPer1M;\n const cachedCost = (cachedInput / 1_000_000) * pricing.cachedInputPer1M;\n const outputCost = (outputTokens / 1_000_000) * pricing.outputPer1M;\n\n return inputCost + cachedCost + outputCost;\n}\n\nexport function getModelPricing(model: string): ModelPricing {\n return MODEL_PRICING[model] ?? DEFAULT_PRICING;\n}\n", "import { readFileSync, readdirSync, statSync, accessSync, constants } from 'node:fs';\nimport { join } from 'node:path';\nimport { homedir } from 'node:os';\nimport type { DailyEntry, DailyResponse, ProjectsResponse, BlockEntry, BlocksResponse } from '../shared/types.js';\n\n// ---------------------------------------------------------------------------\n// OpenClaw JSONL format\n//\n// Each line in a session .jsonl file is one of:\n// { type: \"model_change\", provider: \"anthropic\", modelId: \"claude-opus-4-6\" }\n// { type: \"custom\", customType: \"model-snapshot\", data: { provider, modelId } }\n// { type: \"message\", message: { role, usage: { input, output, cacheRead, cacheWrite, cost: { total } }, timestamp (ms), model, provider } }\n//\n// sessions.json index:\n// { \"<key>\": { sessionId: \"...\", sessionFile?: \"...\" }, ... }\n// ---------------------------------------------------------------------------\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ninterface OpenClawTokenEvent {\n timestampMs: number;\n inputTokens: number;\n outputTokens: number;\n cacheReadTokens: number;\n cacheWriteTokens: number;\n totalTokens: number;\n cost: number;\n model: string;\n}\n\ninterface OpenClawSession {\n id: string;\n agentId: string;\n tokenEvents: OpenClawTokenEvent[];\n}\n\ninterface TokenAccumulator {\n inputTokens: number;\n outputTokens: number;\n cacheReadTokens: number;\n cacheWriteTokens: number;\n totalTokens: number;\n cost: number;\n}\n\n// ---------------------------------------------------------------------------\n// Directory helpers\n// ---------------------------------------------------------------------------\n\n/** All directories OpenClaw may have used (current + legacy names). */\nfunction getOpenClawDirs(): string[] {\n const home = homedir();\n return [\n join(home, '.openclaw'),\n join(home, '.clawdbot'), // legacy name 1\n join(home, '.moltbot'), // legacy name 2\n join(home, '.moldbot'), // legacy name 3\n ];\n}\n\nexport function isOpenClawAccessible(): boolean {\n for (const dir of getOpenClawDirs()) {\n try {\n accessSync(join(dir, 'agents'), constants.R_OK);\n return true;\n } catch {\n // try next\n }\n }\n return false;\n}\n\n// ---------------------------------------------------------------------------\n// Session scanning\n// ---------------------------------------------------------------------------\n\ninterface SessionRef {\n sessionId: string;\n sessionFile: string; // absolute path to .jsonl\n agentId: string;\n}\n\n/** Scan all OpenClaw agent dirs and collect session file references. */\nexport function scanOpenClawSessions(): SessionRef[] {\n const refs: SessionRef[] = [];\n\n for (const baseDir of getOpenClawDirs()) {\n const agentsDir = join(baseDir, 'agents');\n let agentEntries: string[];\n try {\n agentEntries = readdirSync(agentsDir);\n } catch {\n continue;\n }\n\n for (const agentEntry of agentEntries) {\n const sessionsDir = join(agentsDir, agentEntry, 'sessions');\n const indexedPaths = new Set<string>();\n\n // Try sessions.json index first\n const indexPath = join(sessionsDir, 'sessions.json');\n try {\n const raw = readFileSync(indexPath, 'utf-8');\n const index = JSON.parse(raw) as Record<string, { sessionId?: string; sessionFile?: string }>;\n for (const entry of Object.values(index)) {\n if (!entry.sessionId) continue;\n let sessionPath: string;\n if (entry.sessionFile) {\n const filePath = entry.sessionFile;\n if (filePath.startsWith('/')) {\n // Validate absolute path stays within an OpenClaw directory\n if (!getOpenClawDirs().some(dir => filePath.startsWith(dir))) continue;\n sessionPath = filePath;\n } else {\n sessionPath = join(sessionsDir, filePath);\n }\n } else {\n sessionPath = join(sessionsDir, `${entry.sessionId}.jsonl`);\n }\n indexedPaths.add(sessionPath);\n refs.push({ sessionId: entry.sessionId, sessionFile: sessionPath, agentId: agentEntry });\n }\n } catch {\n // No sessions.json \u2014 will scan .jsonl files below\n }\n\n // Scan for .jsonl files not already covered by the index\n let files: string[];\n try {\n files = readdirSync(sessionsDir);\n } catch {\n continue;\n }\n for (const f of files) {\n if (!f.endsWith('.jsonl')) continue;\n const fullPath = join(sessionsDir, f);\n if (indexedPaths.has(fullPath)) continue;\n const sessionId = f.replace(/\\.jsonl.*$/, '');\n refs.push({ sessionId, sessionFile: fullPath, agentId: agentEntry });\n }\n }\n }\n\n return refs;\n}\n\n// ---------------------------------------------------------------------------\n// Session-level cache (mtime-based invalidation)\n// ---------------------------------------------------------------------------\n\nconst sessionCache = new Map<string, { mtime: number; result: OpenClawSession | null }>();\n\n// ---------------------------------------------------------------------------\n// JSONL parser\n// ---------------------------------------------------------------------------\n\nexport function parseOpenClawSession(ref: SessionRef): OpenClawSession | null {\n let fileMtimeMs = 0;\n try {\n fileMtimeMs = statSync(ref.sessionFile).mtimeMs;\n } catch { /* ok */ }\n\n // Return cached result if file hasn't changed\n const cached = sessionCache.get(ref.sessionFile);\n if (cached && cached.mtime === fileMtimeMs) {\n return cached.result;\n }\n\n let content: string;\n try {\n content = readFileSync(ref.sessionFile, 'utf-8');\n } catch {\n return null;\n }\n\n const tokenEvents: OpenClawTokenEvent[] = [];\n let currentModel = '';\n let currentProvider = '';\n\n for (const line of content.split('\\n')) {\n const trimmed = line.trim();\n if (!trimmed) continue;\n\n let obj: Record<string, unknown>;\n try {\n obj = JSON.parse(trimmed) as Record<string, unknown>;\n } catch {\n continue;\n }\n\n const type = obj.type as string;\n\n if (type === 'model_change') {\n if (obj.modelId) currentModel = obj.modelId as string;\n if (obj.provider) currentProvider = obj.provider as string;\n continue;\n }\n\n if (type === 'custom' && (obj.customType as string) === 'model-snapshot') {\n const data = (obj.data as Record<string, unknown>) || {};\n if (data.modelId) currentModel = data.modelId as string;\n if (data.provider) currentProvider = data.provider as string;\n continue;\n }\n\n if (type === 'message') {\n const msg = (obj.message as Record<string, unknown>) || {};\n if ((msg.role as string) !== 'assistant') continue;\n\n const usage = (msg.usage as Record<string, unknown>) || {};\n if (!usage) continue;\n\n // Model: prefer embedded, fall back to tracked state\n const model = ((msg.model as string) || currentModel || '').trim();\n const provider = ((msg.provider as string) || currentProvider || '').trim();\n if (!model) continue; // can't attribute cost without a model\n\n // Update tracked state\n if (model) currentModel = model;\n if (provider) currentProvider = provider;\n\n const input = Number(usage.input ?? 0);\n const output = Number(usage.output ?? 0);\n const cacheRead = Number(usage.cacheRead ?? 0);\n const cacheWrite = Number(usage.cacheWrite ?? 0);\n const costObj = (usage.cost as Record<string, unknown>) || {};\n const cost = Number(costObj.total ?? 0);\n const timestampMs = Number(msg.timestamp ?? fileMtimeMs);\n\n tokenEvents.push({\n timestampMs,\n inputTokens: Math.max(0, input),\n outputTokens: Math.max(0, output),\n cacheReadTokens: Math.max(0, cacheRead),\n cacheWriteTokens: Math.max(0, cacheWrite),\n totalTokens: Math.max(0, input + output + cacheRead),\n cost: Math.max(0, cost),\n model: `${provider}/${model}`,\n });\n }\n }\n\n if (tokenEvents.length === 0) {\n sessionCache.set(ref.sessionFile, { mtime: fileMtimeMs, result: null });\n return null;\n }\n\n const result: OpenClawSession = { id: ref.sessionId, agentId: ref.agentId, tokenEvents };\n sessionCache.set(ref.sessionFile, { mtime: fileMtimeMs, result });\n return result;\n}\n\nexport function parseAllOpenClawSessions(): OpenClawSession[] {\n return scanOpenClawSessions()\n .map(parseOpenClawSession)\n .filter((s): s is OpenClawSession => s !== null);\n}\n\n// ---------------------------------------------------------------------------\n// Date / timezone helpers (same logic as codexParser)\n// ---------------------------------------------------------------------------\n\nconst TZ_OFFSETS: Record<string, number> = {\n 'Asia/Shanghai': 8,\n 'Asia/Tokyo': 9,\n 'America/New_York': -5,\n 'America/Los_Angeles': -8,\n 'Europe/London': 0,\n 'UTC': 0,\n};\n\nfunction getTzOffsetHours(tz: string): number {\n return TZ_OFFSETS[tz] ?? 8;\n}\n\nfunction msToLocalDate(ms: number, tz: string): Date {\n return new Date(ms + getTzOffsetHours(tz) * 3_600_000);\n}\n\nfunction getDateKey(ms: number, tz: string): string {\n return msToLocalDate(ms, tz).toISOString().slice(0, 10);\n}\n\nfunction getHourKey(ms: number, tz: string): string {\n const d = msToLocalDate(ms, tz);\n return d.toISOString().slice(0, 13).replace('T', ' ') + ':00';\n}\n\nfunction getMonthKey(ms: number, tz: string): string {\n return getDateKey(ms, tz).slice(0, 7);\n}\n\n// ---------------------------------------------------------------------------\n// Aggregation helpers\n// ---------------------------------------------------------------------------\n\nfunction emptyAcc(): TokenAccumulator {\n return { inputTokens: 0, outputTokens: 0, cacheReadTokens: 0, cacheWriteTokens: 0, totalTokens: 0, cost: 0 };\n}\n\nfunction addEvent(acc: TokenAccumulator, ev: OpenClawTokenEvent): void {\n acc.inputTokens += ev.inputTokens;\n acc.outputTokens += ev.outputTokens;\n acc.cacheReadTokens += ev.cacheReadTokens;\n acc.cacheWriteTokens += ev.cacheWriteTokens;\n acc.totalTokens += ev.totalTokens;\n acc.cost += ev.cost;\n}\n\nfunction mergeAcc(a: TokenAccumulator, b: TokenAccumulator): void {\n a.inputTokens += b.inputTokens;\n a.outputTokens += b.outputTokens;\n a.cacheReadTokens += b.cacheReadTokens;\n a.cacheWriteTokens += b.cacheWriteTokens;\n a.totalTokens += b.totalTokens;\n a.cost += b.cost;\n}\n\nfunction accToEntry(date: string, acc: TokenAccumulator, models: Set<string>): DailyEntry {\n const modelList = [...models];\n const costPerModel = modelList.length > 0 ? acc.cost / modelList.length : 0;\n return {\n date,\n inputTokens: acc.inputTokens,\n outputTokens: acc.outputTokens,\n cacheCreationTokens: acc.cacheWriteTokens,\n cacheReadTokens: acc.cacheReadTokens,\n totalTokens: acc.totalTokens,\n totalCost: acc.cost,\n modelsUsed: modelList,\n modelBreakdowns: modelList.map(name => ({\n modelName: name,\n inputTokens: acc.inputTokens,\n outputTokens: acc.outputTokens,\n cacheCreationTokens: acc.cacheWriteTokens,\n cacheReadTokens: acc.cacheReadTokens,\n cost: costPerModel,\n })),\n };\n}\n\n// ---------------------------------------------------------------------------\n// Public API \u2014 mirrors codexParser's response builders\n// ---------------------------------------------------------------------------\n\nexport interface OpenClawAggregateOptions {\n groupBy?: 'day' | 'hour' | 'month' | 'session';\n since?: Date | null;\n until?: Date | null;\n timezone?: string;\n project?: string | null; // maps to agentId\n}\n\nexport function getDailyResponse(options?: OpenClawAggregateOptions): DailyResponse {\n const sessions = parseAllOpenClawSessions();\n const tz = options?.timezone || 'Asia/Shanghai';\n\n const grouped = new Map<string, { acc: TokenAccumulator; models: Set<string> }>();\n const totalsAcc = emptyAcc();\n\n for (const session of sessions) {\n if (options?.project && session.agentId !== options.project) continue;\n\n for (const ev of session.tokenEvents) {\n if (options?.since && ev.timestampMs < options.since.getTime()) continue;\n if (options?.until && ev.timestampMs > options.until.getTime()) continue;\n\n const key = getDateKey(ev.timestampMs, tz);\n if (!grouped.has(key)) grouped.set(key, { acc: emptyAcc(), models: new Set() });\n const entry = grouped.get(key)!;\n addEvent(entry.acc, ev);\n entry.models.add(ev.model);\n }\n }\n\n const daily: DailyEntry[] = [];\n for (const [date, { acc, models }] of grouped) {\n daily.push(accToEntry(date, acc, models));\n mergeAcc(totalsAcc, acc);\n }\n daily.sort((a, b) => a.date.localeCompare(b.date));\n\n return {\n daily,\n totals: {\n inputTokens: totalsAcc.inputTokens,\n outputTokens: totalsAcc.outputTokens,\n cacheCreationTokens: totalsAcc.cacheWriteTokens,\n cacheReadTokens: totalsAcc.cacheReadTokens,\n totalTokens: totalsAcc.totalTokens,\n totalCost: totalsAcc.cost,\n },\n };\n}\n\nexport function getProjectsResponse(options?: OpenClawAggregateOptions): ProjectsResponse {\n const sessions = parseAllOpenClawSessions();\n const tz = options?.timezone || 'Asia/Shanghai';\n const projects: Record<string, DailyEntry[]> = {};\n\n for (const session of sessions) {\n const projectName = session.agentId;\n const dailyMap = new Map<string, { acc: TokenAccumulator; models: Set<string> }>();\n\n for (const ev of session.tokenEvents) {\n if (options?.since && ev.timestampMs < options.since.getTime()) continue;\n if (options?.until && ev.timestampMs > options.until.getTime()) continue;\n\n const dayKey = getDateKey(ev.timestampMs, tz);\n if (!dailyMap.has(dayKey)) dailyMap.set(dayKey, { acc: emptyAcc(), models: new Set() });\n addEvent(dailyMap.get(dayKey)!.acc, ev);\n dailyMap.get(dayKey)!.models.add(ev.model);\n }\n\n if (!projects[projectName]) projects[projectName] = [];\n for (const [date, { acc, models }] of dailyMap) {\n projects[projectName].push(accToEntry(date, acc, models));\n }\n }\n\n for (const key of Object.keys(projects)) {\n projects[key].sort((a, b) => a.date.localeCompare(b.date));\n }\n\n return { projects };\n}\n\nexport function getBlocksResponse(options?: OpenClawAggregateOptions): BlocksResponse {\n const sessions = parseAllOpenClawSessions();\n const tz = options?.timezone || 'Asia/Shanghai';\n\n const grouped = new Map<string, { acc: TokenAccumulator; models: Set<string> }>();\n\n for (const session of sessions) {\n if (options?.project && session.agentId !== options.project) continue;\n\n for (const ev of session.tokenEvents) {\n if (options?.since && ev.timestampMs < options.since.getTime()) continue;\n if (options?.until && ev.timestampMs > options.until.getTime()) continue;\n\n const key = getHourKey(ev.timestampMs, tz);\n if (!grouped.has(key)) grouped.set(key, { acc: emptyAcc(), models: new Set() });\n addEvent(grouped.get(key)!.acc, ev);\n grouped.get(key)!.models.add(ev.model);\n }\n }\n\n const blocks: BlockEntry[] = [];\n let idx = 0;\n\n for (const [hourKey, { acc, models }] of grouped) {\n const [datePart, timePart] = hourKey.split(' ');\n const hour = timePart.split(':')[0];\n blocks.push({\n id: `openclaw-hour-${idx}`,\n startTime: `${datePart}T${hour}:00:00`,\n endTime: `${datePart}T${hour}:59:59`,\n actualEndTime: null,\n isActive: false,\n isGap: false,\n entries: acc.totalTokens > 0 ? 1 : 0,\n tokenCounts: {\n inputTokens: acc.inputTokens,\n outputTokens: acc.outputTokens,\n cacheCreationInputTokens: acc.cacheWriteTokens,\n cacheReadInputTokens: acc.cacheReadTokens,\n },\n totalTokens: acc.totalTokens,\n costUSD: acc.cost,\n models: [...models],\n });\n idx++;\n }\n\n blocks.sort((a, b) => a.startTime.localeCompare(b.startTime));\n return { blocks };\n}\n", "import { existsSync } from 'node:fs';\nimport { execSync } from 'node:child_process';\nimport { join } from 'node:path';\nimport { homedir } from 'node:os';\nimport type { DailyEntry, DailyResponse, ProjectsResponse, BlockEntry, BlocksResponse } from '../shared/types.js';\n\n// ---------------------------------------------------------------------------\n// OpenCode SQLite format\n//\n// Database: ~/.local/share/opencode/opencode.db\n// Table: message\n// Column: data (JSON) with structure:\n// {\n// \"role\": \"assistant\",\n// \"time\": { \"created\": <ms>, \"completed\": <ms> },\n// \"modelID\": \"glm-4.7\",\n// \"providerID\": \"zhipuai-coding-plan\",\n// \"tokens\": { \"input\": N, \"output\": N, \"reasoning\": N, \"cache\": { \"read\": N, \"write\": N } },\n// \"cost\": N,\n// \"path\": { \"cwd\": \"/path/to/project\" }\n// }\n// ---------------------------------------------------------------------------\n\nconst OPENCODE_DB = join(homedir(), '.local', 'share', 'opencode', 'opencode.db');\n\n// ---------------------------------------------------------------------------\n// Detection\n// ---------------------------------------------------------------------------\n\nexport function isOpencodeAccessible(): boolean {\n return existsSync(OPENCODE_DB);\n}\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ninterface OpenCodeTokenEvent {\n timestampMs: number;\n inputTokens: number;\n outputTokens: number;\n cacheReadTokens: number;\n cacheWriteTokens: number;\n totalTokens: number;\n cost: number;\n model: string;\n project: string;\n}\n\ninterface TokenAccumulator {\n inputTokens: number;\n outputTokens: number;\n cacheReadTokens: number;\n cacheWriteTokens: number;\n totalTokens: number;\n cost: number;\n}\n\n// ---------------------------------------------------------------------------\n// SQLite query helper\n// ---------------------------------------------------------------------------\n\nfunction queryOpenCodeDB(sql: string): string {\n return execSync(`sqlite3 -json \"${OPENCODE_DB}\" \"${sql}\"`, {\n encoding: 'utf-8',\n maxBuffer: 50 * 1024 * 1024,\n timeout: 10000,\n });\n}\n\n// ---------------------------------------------------------------------------\n// Parse all token events from message table\n// ---------------------------------------------------------------------------\n\ninterface RawMessage {\n data: string;\n}\n\nexport function parseAllOpenCodeEvents(project?: string | null): OpenCodeTokenEvent[] {\n let sql = `SELECT data FROM message WHERE json_extract(data, '$.role') = 'assistant'`;\n if (project) {\n sql += ` AND json_extract(data, '$.path.cwd') = '${project.replace(/'/g, \"''\")}'`;\n }\n\n let raw: string;\n try {\n raw = queryOpenCodeDB(sql);\n } catch {\n return [];\n }\n\n let rows: RawMessage[];\n try {\n rows = JSON.parse(raw) as RawMessage[];\n } catch {\n return [];\n }\n\n const events: OpenCodeTokenEvent[] = [];\n\n for (const row of rows) {\n let data: Record<string, unknown>;\n try {\n data = JSON.parse(row.data) as Record<string, unknown>;\n } catch {\n continue;\n }\n\n const tokens = (data.tokens as Record<string, unknown>) || {};\n const cache = (tokens.cache as Record<string, unknown>) || {};\n const time = (data.time as Record<string, unknown>) || {};\n const path = (data.path as Record<string, unknown>) || {};\n\n const input = Number(tokens.input ?? 0);\n const output = Number(tokens.output ?? 0);\n const cacheRead = Number(cache.read ?? 0);\n const cacheWrite = Number(cache.write ?? 0);\n\n if (input === 0 && output === 0 && cacheRead === 0 && cacheWrite === 0) continue;\n\n events.push({\n timestampMs: Number(time.created ?? 0),\n inputTokens: Math.max(0, input),\n outputTokens: Math.max(0, output),\n cacheReadTokens: Math.max(0, cacheRead),\n cacheWriteTokens: Math.max(0, cacheWrite),\n totalTokens: Math.max(0, input + output + cacheRead),\n cost: Math.max(0, Number(data.cost ?? 0)),\n model: String(data.modelID ?? 'unknown'),\n project: String(path.cwd ?? ''),\n });\n }\n\n return events;\n}\n\n// ---------------------------------------------------------------------------\n// Date / timezone helpers (same logic as openclawParser)\n// ---------------------------------------------------------------------------\n\nconst TZ_OFFSETS: Record<string, number> = {\n 'Asia/Shanghai': 8,\n 'Asia/Tokyo': 9,\n 'America/New_York': -5,\n 'America/Los_Angeles': -8,\n 'Europe/London': 0,\n 'UTC': 0,\n};\n\nfunction getTzOffsetHours(tz: string): number {\n return TZ_OFFSETS[tz] ?? 8;\n}\n\nfunction msToLocalDate(ms: number, tz: string): Date {\n return new Date(ms + getTzOffsetHours(tz) * 3_600_000);\n}\n\nfunction getDateKey(ms: number, tz: string): string {\n return msToLocalDate(ms, tz).toISOString().slice(0, 10);\n}\n\nfunction getHourKey(ms: number, tz: string): string {\n const d = msToLocalDate(ms, tz);\n return d.toISOString().slice(0, 13).replace('T', ' ') + ':00';\n}\n\n// ---------------------------------------------------------------------------\n// Aggregation helpers\n// ---------------------------------------------------------------------------\n\nfunction emptyAcc(): TokenAccumulator {\n return { inputTokens: 0, outputTokens: 0, cacheReadTokens: 0, cacheWriteTokens: 0, totalTokens: 0, cost: 0 };\n}\n\nfunction addEvent(acc: TokenAccumulator, ev: OpenCodeTokenEvent): void {\n acc.inputTokens += ev.inputTokens;\n acc.outputTokens += ev.outputTokens;\n acc.cacheReadTokens += ev.cacheReadTokens;\n acc.cacheWriteTokens += ev.cacheWriteTokens;\n acc.totalTokens += ev.totalTokens;\n acc.cost += ev.cost;\n}\n\n// ---------------------------------------------------------------------------\n// Public API \u2014 mirrors openclawParser's response builders\n// ---------------------------------------------------------------------------\n\nexport interface OpenCodeAggregateOptions {\n project?: string | null;\n timezone?: string;\n}\n\nexport function getDailyResponse(options?: OpenCodeAggregateOptions): DailyResponse {\n const events = parseAllOpenCodeEvents(options?.project);\n const tz = options?.timezone || 'Asia/Shanghai';\n\n // Track per-day, per-model accumulators for correct breakdowns\n interface ModelAcc { inputTokens: number; outputTokens: number; cacheCreationTokens: number; cacheReadTokens: number; cost: number; }\n interface DayGroup { totals: TokenAccumulator; models: Map<string, ModelAcc>; }\n const grouped = new Map<string, DayGroup>();\n\n for (const ev of events) {\n const key = getDateKey(ev.timestampMs, tz);\n if (!grouped.has(key)) grouped.set(key, { totals: emptyAcc(), models: new Map() });\n const g = grouped.get(key)!;\n addEvent(g.totals, ev);\n\n if (!g.models.has(ev.model)) {\n g.models.set(ev.model, { inputTokens: 0, outputTokens: 0, cacheCreationTokens: 0, cacheReadTokens: 0, cost: 0 });\n }\n const m = g.models.get(ev.model)!;\n m.inputTokens += ev.inputTokens;\n m.outputTokens += ev.outputTokens;\n m.cacheCreationTokens += ev.cacheWriteTokens;\n m.cacheReadTokens += ev.cacheReadTokens;\n m.cost += ev.cost;\n }\n\n const totalsAcc = emptyAcc();\n const daily: DailyEntry[] = [];\n for (const [date, g] of grouped) {\n mergeAcc(totalsAcc, g.totals);\n const modelList = [...g.models.keys()];\n daily.push({\n date,\n inputTokens: g.totals.inputTokens,\n outputTokens: g.totals.outputTokens,\n cacheCreationTokens: g.totals.cacheWriteTokens,\n cacheReadTokens: g.totals.cacheReadTokens,\n totalTokens: g.totals.totalTokens,\n totalCost: g.totals.cost,\n modelsUsed: modelList,\n modelBreakdowns: modelList.map(name => {\n const m = g.models.get(name)!;\n return {\n modelName: name,\n inputTokens: m.inputTokens,\n outputTokens: m.outputTokens,\n cacheCreationTokens: m.cacheCreationTokens,\n cacheReadTokens: m.cacheReadTokens,\n cost: m.cost,\n };\n }),\n });\n }\n daily.sort((a, b) => a.date.localeCompare(b.date));\n\n return {\n daily,\n totals: {\n inputTokens: totalsAcc.inputTokens,\n outputTokens: totalsAcc.outputTokens,\n cacheCreationTokens: totalsAcc.cacheWriteTokens,\n cacheReadTokens: totalsAcc.cacheReadTokens,\n totalTokens: totalsAcc.totalTokens,\n totalCost: totalsAcc.cost,\n },\n };\n}\n\nfunction mergeAcc(a: TokenAccumulator, b: TokenAccumulator): void {\n a.inputTokens += b.inputTokens;\n a.outputTokens += b.outputTokens;\n a.cacheReadTokens += b.cacheReadTokens;\n a.cacheWriteTokens += b.cacheWriteTokens;\n a.totalTokens += b.totalTokens;\n a.cost += b.cost;\n}\n\nexport function getProjectsResponse(options?: OpenCodeAggregateOptions): ProjectsResponse {\n const events = parseAllOpenCodeEvents();\n const tz = options?.timezone || 'Asia/Shanghai';\n const projects: Record<string, DailyEntry[]> = {};\n\n for (const ev of events) {\n const projectName = ev.project || 'unknown';\n const dayKey = getDateKey(ev.timestampMs, tz);\n\n if (!projects[projectName]) projects[projectName] = [];\n\n // Find or create entry for this date in this project\n let dayEntry = projects[projectName].find(d => d.date === dayKey);\n if (!dayEntry) {\n dayEntry = {\n date: dayKey,\n inputTokens: 0,\n outputTokens: 0,\n cacheCreationTokens: 0,\n cacheReadTokens: 0,\n totalTokens: 0,\n totalCost: 0,\n modelsUsed: [],\n modelBreakdowns: [],\n };\n projects[projectName].push(dayEntry);\n }\n\n dayEntry.inputTokens += ev.inputTokens;\n dayEntry.outputTokens += ev.outputTokens;\n dayEntry.cacheCreationTokens += ev.cacheWriteTokens;\n dayEntry.cacheReadTokens += ev.cacheReadTokens;\n dayEntry.totalTokens += ev.totalTokens;\n dayEntry.totalCost += ev.cost;\n\n if (!dayEntry.modelsUsed.includes(ev.model)) {\n dayEntry.modelsUsed.push(ev.model);\n }\n\n // Update or add model breakdown\n let breakdown = dayEntry.modelBreakdowns.find(b => b.modelName === ev.model);\n if (!breakdown) {\n breakdown = {\n modelName: ev.model,\n inputTokens: 0,\n outputTokens: 0,\n cacheCreationTokens: 0,\n cacheReadTokens: 0,\n cost: 0,\n };\n dayEntry.modelBreakdowns.push(breakdown);\n }\n breakdown.inputTokens += ev.inputTokens;\n breakdown.outputTokens += ev.outputTokens;\n breakdown.cacheCreationTokens += ev.cacheWriteTokens;\n breakdown.cacheReadTokens += ev.cacheReadTokens;\n breakdown.cost += ev.cost;\n }\n\n for (const key of Object.keys(projects)) {\n projects[key].sort((a, b) => a.date.localeCompare(b.date));\n }\n\n return { projects };\n}\n\nexport function getBlocksResponse(options?: OpenCodeAggregateOptions): BlocksResponse {\n const events = parseAllOpenCodeEvents(options?.project);\n const tz = options?.timezone || 'Asia/Shanghai';\n\n const grouped = new Map<string, { acc: TokenAccumulator; models: Set<string> }>();\n\n for (const ev of events) {\n const key = getHourKey(ev.timestampMs, tz);\n if (!grouped.has(key)) grouped.set(key, { acc: emptyAcc(), models: new Set() });\n addEvent(grouped.get(key)!.acc, ev);\n grouped.get(key)!.models.add(ev.model);\n }\n\n const blocks: BlockEntry[] = [];\n let idx = 0;\n\n for (const [hourKey, { acc, models }] of grouped) {\n const [datePart, timePart] = hourKey.split(' ');\n const hour = timePart.split(':')[0];\n blocks.push({\n id: `opencode-hour-${idx}`,\n startTime: `${datePart}T${hour}:00:00`,\n endTime: `${datePart}T${hour}:59:59`,\n actualEndTime: null,\n isActive: false,\n isGap: false,\n entries: acc.totalTokens > 0 ? 1 : 0,\n tokenCounts: {\n inputTokens: acc.inputTokens,\n outputTokens: acc.outputTokens,\n cacheCreationInputTokens: acc.cacheWriteTokens,\n cacheReadInputTokens: acc.cacheReadTokens,\n },\n totalTokens: acc.totalTokens,\n costUSD: acc.cost,\n models: [...models],\n });\n idx++;\n }\n\n blocks.sort((a, b) => a.startTime.localeCompare(b.startTime));\n return { blocks };\n}\n", "import { readFileSync, readdirSync, statSync, existsSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { homedir } from 'node:os';\nimport type { DailyEntry, DailyResponse, ProjectsResponse, Totals, BlockEntry } from '../shared/types.js';\n\n// ---------------------------------------------------------------------------\n// Model pricing (USD per 1M tokens)\n// Update from https://docs.anthropic.com/en/docs/about-claude/models when needed\n// ---------------------------------------------------------------------------\n\ninterface ModelPricing {\n inputPer1M: number;\n cacheReadPer1M: number;\n outputPer1M: number;\n}\n\nconst MODEL_PRICING: Record<string, ModelPricing> = {\n // Claude 4.6\n 'claude-opus-4-6': { inputPer1M: 15, cacheReadPer1M: 1.50, outputPer1M: 75 },\n 'claude-sonnet-4-6': { inputPer1M: 3, cacheReadPer1M: 0.30, outputPer1M: 15 },\n // Claude 4.5\n 'claude-sonnet-4-5-20250514': { inputPer1M: 3, cacheReadPer1M: 0.30, outputPer1M: 15 },\n 'claude-haiku-4-5-20251001': { inputPer1M: 0.80, cacheReadPer1M: 0.08, outputPer1M: 4 },\n // Older Claude models\n 'claude-3-5-sonnet-20241022': { inputPer1M: 3, cacheReadPer1M: 0.30, outputPer1M: 15 },\n 'claude-3-5-haiku-20241022': { inputPer1M: 0.80, cacheReadPer1M: 0.08, outputPer1M: 4 },\n 'claude-3-opus-20240229': { inputPer1M: 15, cacheReadPer1M: 1.50, outputPer1M: 75 },\n 'claude-3-haiku-20240307': { inputPer1M: 0.25, cacheReadPer1M: 0.03, outputPer1M: 1.25 },\n};\n\nconst DEFAULT_PRICING: ModelPricing = { inputPer1M: 3, cacheReadPer1M: 0.30, outputPer1M: 15 };\n\nfunction getPricing(model: string): ModelPricing {\n // Try exact match first, then prefix match\n if (MODEL_PRICING[model]) return MODEL_PRICING[model];\n const lower = model.toLowerCase();\n for (const key of Object.keys(MODEL_PRICING)) {\n if (lower.startsWith(key) || lower.includes(key)) return MODEL_PRICING[key];\n }\n return DEFAULT_PRICING;\n}\n\nexport function calculateCost(inputTokens: number, cacheReadTokens: number, outputTokens: number, model: string): number {\n const p = getPricing(model);\n const nonCachedInput = Math.max(inputTokens - cacheReadTokens, 0);\n return (nonCachedInput / 1_000_000) * p.inputPer1M\n + (cacheReadTokens / 1_000_000) * p.cacheReadPer1M\n + (outputTokens / 1_000_000) * p.outputPer1M;\n}\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ninterface ParsedUsage {\n timestamp: string;\n model: string;\n inputTokens: number;\n outputTokens: number;\n cacheCreationTokens: number;\n cacheReadTokens: number;\n projectDir: string;\n}\n\n// ---------------------------------------------------------------------------\n// JSONL parsing with mtime cache\n// ---------------------------------------------------------------------------\n\nconst CLAUDE_PROJECTS_DIR = join(homedir(), '.claude', 'projects');\n\nconst fileCache = new Map<string, { mtime: number; entries: ParsedUsage[] }>();\n\nfunction extractProjectName(dirName: string): string {\n const parts = dirName.replace(/^-/, '').split('-');\n return parts[parts.length - 1] || dirName;\n}\n\nfunction matchesProject(dirName: string, filter: string): boolean {\n return extractProjectName(dirName) === extractProjectName(filter);\n}\n\nfunction findJsonlFiles(dir: string): string[] {\n const results: string[] = [];\n try {\n const entries = readdirSync(dir, { withFileTypes: true });\n for (const entry of entries) {\n if (entry.isDirectory()) {\n results.push(...findJsonlFiles(join(dir, entry.name)));\n } else if (entry.name.endsWith('.jsonl')) {\n results.push(join(dir, entry.name));\n }\n }\n } catch { /* skip unreadable dirs */ }\n return results;\n}\n\nfunction parseAllSessions(project?: string | null): ParsedUsage[] {\n if (!existsSync(CLAUDE_PROJECTS_DIR)) return [];\n\n const results: ParsedUsage[] = [];\n const projectDirs = readdirSync(CLAUDE_PROJECTS_DIR, { withFileTypes: true })\n .filter(d => d.isDirectory())\n .map(d => d.name);\n\n for (const dirName of projectDirs) {\n if (project && !matchesProject(dirName, project)) continue;\n\n const dirPath = join(CLAUDE_PROJECTS_DIR, dirName);\n const files = findJsonlFiles(dirPath);\n\n for (const filePath of files) {\n\n let mtime = 0;\n try { mtime = statSync(filePath).mtimeMs; } catch { /* ok */ }\n\n const cached = fileCache.get(filePath);\n if (cached && cached.mtime === mtime) {\n results.push(...cached.entries);\n continue;\n }\n\n const entries: ParsedUsage[] = [];\n let content: string;\n try {\n content = readFileSync(filePath, 'utf-8');\n } catch {\n continue;\n }\n\n for (const line of content.split('\\n')) {\n const trimmed = line.trim();\n if (!trimmed) continue;\n\n let obj: Record<string, unknown>;\n try { obj = JSON.parse(trimmed) as Record<string, unknown>; } catch { continue; }\n\n if (obj.type !== 'assistant' || !obj.message) continue;\n const msg = obj.message as Record<string, unknown>;\n const usage = (msg.usage as Record<string, number>) || {};\n\n const inputTokens = usage.input_tokens || 0;\n const outputTokens = usage.output_tokens || 0;\n const cacheCreationTokens = usage.cache_creation_input_tokens || 0;\n const cacheReadTokens = usage.cache_read_input_tokens || 0;\n const totalTokens = inputTokens + outputTokens + cacheReadTokens;\n\n if (totalTokens === 0) continue;\n\n entries.push({\n timestamp: obj.timestamp as string,\n model: (msg.model as string) || 'unknown',\n inputTokens,\n outputTokens,\n cacheCreationTokens,\n cacheReadTokens,\n projectDir: dirName,\n });\n }\n\n fileCache.set(filePath, { mtime, entries });\n results.push(...entries);\n }\n }\n\n return results;\n}\n\n// ---------------------------------------------------------------------------\n// Timezone helpers\n// ---------------------------------------------------------------------------\n\nconst TZ_OFFSETS: Record<string, number> = {\n 'Asia/Shanghai': 8,\n 'Asia/Tokyo': 9,\n 'America/New_York': -5,\n 'America/Los_Angeles': -8,\n 'Europe/London': 0,\n 'UTC': 0,\n};\n\nexport function getDateKey(timestamp: string, tz: string): string {\n const offset = (TZ_OFFSETS[tz] ?? 8) * 3_600_000;\n const d = new Date(new Date(timestamp).getTime() + offset);\n // Use UTC methods since we manually applied the timezone offset\n return `${d.getUTCFullYear()}-${String(d.getUTCMonth() + 1).padStart(2, '0')}-${String(d.getUTCDate()).padStart(2, '0')}`;\n}\n\nexport function getHourKey(timestamp: string, tz: string): string {\n const offset = (TZ_OFFSETS[tz] ?? 8) * 3_600_000;\n const d = new Date(new Date(timestamp).getTime() + offset);\n // Use UTC methods since we manually applied the timezone offset\n const yyyy = d.getUTCFullYear();\n const mm = String(d.getUTCMonth() + 1).padStart(2, '0');\n const dd = String(d.getUTCDate()).padStart(2, '0');\n const hh = String(d.getUTCHours()).padStart(2, '0');\n return `${yyyy}-${mm}-${dd}T${hh}`;\n}\n\n// ---------------------------------------------------------------------------\n// Aggregation helpers\n// ---------------------------------------------------------------------------\n\ninterface DayAgg {\n date: string;\n inputTokens: number;\n outputTokens: number;\n cacheCreationTokens: number;\n cacheReadTokens: number;\n totalTokens: number;\n totalCost: number;\n models: Map<string, { input: number; output: number; cacheCreation: number; cacheRead: number; cost: number }>;\n}\n\nfunction toDailyEntry(agg: DayAgg): DailyEntry {\n const modelBreakdowns = [...agg.models.entries()].map(([modelName, m]) => ({\n modelName,\n inputTokens: m.input,\n outputTokens: m.output,\n cacheCreationTokens: m.cacheCreation,\n cacheReadTokens: m.cacheRead,\n cost: m.cost,\n }));\n\n return {\n date: agg.date,\n inputTokens: agg.inputTokens,\n outputTokens: agg.outputTokens,\n cacheCreationTokens: agg.cacheCreationTokens,\n cacheReadTokens: agg.cacheReadTokens,\n totalTokens: agg.totalTokens,\n totalCost: Math.round(agg.totalCost * 10000) / 10000,\n modelsUsed: [...agg.models.keys()],\n modelBreakdowns,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\nconst DEFAULT_TZ = 'Asia/Shanghai';\n\nexport function getDailyResponse(project?: string | null, tz = DEFAULT_TZ): DailyResponse {\n const entries = parseAllSessions(project);\n const dayMap = new Map<string, DayAgg>();\n\n for (const e of entries) {\n const date = getDateKey(e.timestamp, tz);\n if (!dayMap.has(date)) {\n dayMap.set(date, {\n date, inputTokens: 0, outputTokens: 0, cacheCreationTokens: 0,\n cacheReadTokens: 0, totalTokens: 0, totalCost: 0,\n models: new Map(),\n });\n }\n const agg = dayMap.get(date)!;\n agg.inputTokens += e.inputTokens;\n agg.outputTokens += e.outputTokens;\n agg.cacheCreationTokens += e.cacheCreationTokens;\n agg.cacheReadTokens += e.cacheReadTokens;\n agg.totalTokens += e.inputTokens + e.outputTokens + e.cacheReadTokens;\n\n const cost = calculateCost(e.inputTokens, e.cacheReadTokens, e.outputTokens, e.model);\n agg.totalCost += cost;\n\n if (!agg.models.has(e.model)) {\n agg.models.set(e.model, { input: 0, output: 0, cacheCreation: 0, cacheRead: 0, cost: 0 });\n }\n const m = agg.models.get(e.model)!;\n m.input += e.inputTokens;\n m.output += e.outputTokens;\n m.cacheCreation += e.cacheCreationTokens;\n m.cacheRead += e.cacheReadTokens;\n m.cost += cost;\n }\n\n const daily = [...dayMap.values()].sort((a, b) => a.date.localeCompare(b.date)).map(toDailyEntry);\n const totals: Totals = daily.reduce((acc, d) => ({\n inputTokens: acc.inputTokens + d.inputTokens,\n outputTokens: acc.outputTokens + d.outputTokens,\n cacheCreationTokens: acc.cacheCreationTokens + d.cacheCreationTokens,\n cacheReadTokens: acc.cacheReadTokens + d.cacheReadTokens,\n totalTokens: acc.totalTokens + d.totalTokens,\n totalCost: acc.totalCost + d.totalCost,\n }), { inputTokens: 0, outputTokens: 0, cacheCreationTokens: 0, cacheReadTokens: 0, totalTokens: 0, totalCost: 0 });\n\n return { daily, totals };\n}\n\nexport function getProjectsResponse(tz = DEFAULT_TZ): ProjectsResponse {\n const entries = parseAllSessions();\n const projectMap = new Map<string, Map<string, DayAgg>>();\n\n for (const e of entries) {\n const date = getDateKey(e.timestamp, tz);\n const projectName = e.projectDir;\n\n if (!projectMap.has(projectName)) {\n projectMap.set(projectName, new Map());\n }\n const dayMap = projectMap.get(projectName)!;\n\n if (!dayMap.has(date)) {\n dayMap.set(date, {\n date, inputTokens: 0, outputTokens: 0, cacheCreationTokens: 0,\n cacheReadTokens: 0, totalTokens: 0, totalCost: 0,\n models: new Map(),\n });\n }\n const agg = dayMap.get(date)!;\n agg.inputTokens += e.inputTokens;\n agg.outputTokens += e.outputTokens;\n agg.cacheCreationTokens += e.cacheCreationTokens;\n agg.cacheReadTokens += e.cacheReadTokens;\n agg.totalTokens += e.inputTokens + e.outputTokens + e.cacheReadTokens;\n\n const cost = calculateCost(e.inputTokens, e.cacheReadTokens, e.outputTokens, e.model);\n agg.totalCost += cost;\n\n if (!agg.models.has(e.model)) {\n agg.models.set(e.model, { input: 0, output: 0, cacheCreation: 0, cacheRead: 0, cost: 0 });\n }\n const m = agg.models.get(e.model)!;\n m.input += e.inputTokens;\n m.output += e.outputTokens;\n m.cacheCreation += e.cacheCreationTokens;\n m.cacheRead += e.cacheReadTokens;\n m.cost += cost;\n }\n\n const projects: Record<string, DailyEntry[]> = {};\n for (const [projectName, dayMap] of projectMap) {\n projects[projectName] = [...dayMap.values()]\n .sort((a, b) => a.date.localeCompare(b.date))\n .map(toDailyEntry);\n }\n\n return { projects };\n}\n\nexport function getBlocksResponse(project?: string | null, tz = DEFAULT_TZ): { blocks: BlockEntry[] } {\n const entries = parseAllSessions(project);\n const hourMap = new Map<string, {\n inputTokens: number; outputTokens: number; cacheCreationTokens: number;\n cacheReadTokens: number; costUSD: number; models: Set<string>;\n }>();\n\n for (const e of entries) {\n const hourKey = getHourKey(e.timestamp, tz);\n if (!hourMap.has(hourKey)) {\n hourMap.set(hourKey, {\n inputTokens: 0, outputTokens: 0, cacheCreationTokens: 0,\n cacheReadTokens: 0, costUSD: 0, models: new Set(),\n });\n }\n const bucket = hourMap.get(hourKey)!;\n bucket.inputTokens += e.inputTokens;\n bucket.outputTokens += e.outputTokens;\n bucket.cacheCreationTokens += e.cacheCreationTokens;\n bucket.cacheReadTokens += e.cacheReadTokens;\n bucket.costUSD += calculateCost(e.inputTokens, e.cacheReadTokens, e.outputTokens, e.model);\n bucket.models.add(e.model);\n }\n\n const blocks: BlockEntry[] = [];\n let idx = 0;\n for (const [hourKey, bucket] of hourMap) {\n const totalTokens = bucket.inputTokens + bucket.outputTokens + bucket.cacheReadTokens;\n blocks.push({\n id: `claude-${idx}`,\n startTime: `${hourKey}:00:00`,\n endTime: `${hourKey}:59:59`,\n actualEndTime: null,\n isActive: false,\n isGap: false,\n entries: totalTokens > 0 ? 1 : 0,\n tokenCounts: {\n inputTokens: bucket.inputTokens,\n outputTokens: bucket.outputTokens,\n cacheCreationInputTokens: bucket.cacheCreationTokens,\n cacheReadInputTokens: bucket.cacheReadTokens,\n },\n totalTokens,\n costUSD: Math.round(bucket.costUSD * 10000) / 10000,\n models: [...bucket.models],\n });\n idx++;\n }\n\n blocks.sort((a, b) => a.startTime.localeCompare(b.startTime));\n return { blocks };\n}\n", "import { type Request, type Response } from 'express';\nimport { cache } from '../cache.js';\nimport { validateDaily } from '../../shared/schemas.js';\nimport { getDailyResponse as getCodexDailyResponse } from '../codexParser.js';\nimport { getDailyResponse as getOpenClawDailyResponse } from '../openclawParser.js';\nimport { getDailyResponse as getOpencodeDailyResponse } from '../opencodeParser.js';\nimport { getDailyResponse as getClaudeDailyResponse } from '../claudeJsonlParser.js';\n\nexport async function getDaily(req: Request, res: Response): Promise<void> {\n const agent = req.query.agent as string || 'claude';\n const cacheKey = `daily:${agent}`;\n try {\n const cached = cache.get(cacheKey);\n if (cached) {\n res.json(cached);\n return;\n }\n\n // Stale-while-revalidate: return stale data, refresh in background\n const stale = cache.getStale(cacheKey);\n if (stale) {\n refreshDailyCache(agent, cacheKey);\n res.json(stale);\n return;\n }\n\n const data = await fetchDailyData(agent);\n cache.set(cacheKey, data);\n res.json(data);\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Unknown error';\n console.error('Error fetching daily data:', error);\n res.status(502).json({\n error: `Failed to fetch daily data from ${agent}`,\n hint: message,\n });\n }\n}\n\nfunction fetchDailyData(agent: string) {\n if (agent === 'codex') {\n return Promise.resolve(getCodexDailyResponse());\n } else if (agent === 'openclaw') {\n return Promise.resolve(validateDaily(getOpenClawDailyResponse()));\n } else if (agent === 'opencode') {\n return Promise.resolve(validateDaily(getOpencodeDailyResponse()));\n } else {\n // Claude Code: parse JSONL directly (fast, no CLI)\n return Promise.resolve(validateDaily(getClaudeDailyResponse()));\n }\n}\n\nfunction refreshDailyCache(agent: string, cacheKey: string): void {\n fetchDailyData(agent)\n .then(data => cache.set(cacheKey, data))\n .catch(err => console.error('Background refresh failed (daily):', err));\n}\n", "import { type Request, type Response } from 'express';\nimport { cache } from '../cache.js';\nimport { validateDaily } from '../../shared/schemas.js';\nimport { getDailyResponse as getClaudeDailyResponse } from '../claudeJsonlParser.js';\nimport { getDailyResponse as getCodexDailyResponse } from '../codexParser.js';\nimport { getDailyResponse as getOpenClawDailyResponse } from '../openclawParser.js';\n\nexport async function getMonthly(req: Request, res: Response): Promise<void> {\n const agent = req.query.agent as string || 'claude';\n const cacheKey = `monthly:${agent}`;\n try {\n const cached = cache.get(cacheKey);\n if (cached) {\n res.json(cached);\n return;\n }\n\n const stale = cache.getStale(cacheKey);\n if (stale) {\n res.json(stale);\n return;\n }\n\n // Monthly is same as daily for our parser (aggregated by date already)\n let data;\n if (agent === 'codex') {\n data = validateDaily(getCodexDailyResponse());\n } else if (agent === 'openclaw') {\n data = validateDaily(getOpenClawDailyResponse());\n } else {\n data = validateDaily(getClaudeDailyResponse());\n }\n\n cache.set(cacheKey, data);\n res.json(data);\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Unknown error';\n console.error('Error fetching monthly data:', error);\n res.status(502).json({\n error: 'Failed to fetch monthly data',\n hint: message,\n });\n }\n}\n", "import { type Request, type Response } from 'express';\nimport { cache } from '../cache.js';\nimport { validateDaily } from '../../shared/schemas.js';\nimport { getDailyResponse as getClaudeDailyResponse } from '../claudeJsonlParser.js';\nimport { getDailyResponse as getCodexDailyResponse } from '../codexParser.js';\nimport { getDailyResponse as getOpenClawDailyResponse } from '../openclawParser.js';\n\nexport async function getSession(req: Request, res: Response): Promise<void> {\n const agent = req.query.agent as string || 'claude';\n const cacheKey = `session:${agent}`;\n try {\n const cached = cache.get(cacheKey);\n if (cached) {\n res.json(cached);\n return;\n }\n\n const stale = cache.getStale(cacheKey);\n if (stale) {\n res.json(stale);\n return;\n }\n\n // Session data uses same daily aggregation\n let data;\n if (agent === 'codex') {\n data = validateDaily(getCodexDailyResponse());\n } else if (agent === 'openclaw') {\n data = validateDaily(getOpenClawDailyResponse());\n } else {\n data = validateDaily(getClaudeDailyResponse());\n }\n\n cache.set(cacheKey, data);\n res.json(data);\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Unknown error';\n console.error('Error fetching session data:', error);\n res.status(502).json({\n error: 'Failed to fetch session data',\n hint: message,\n });\n }\n}\n", "import { type Request, type Response } from 'express';\nimport { cache } from '../cache.js';\nimport { validateProjects } from '../../shared/schemas.js';\nimport { getProjectsResponse as getCodexProjectsResponse } from '../codexParser.js';\nimport { getProjectsResponse as getOpenClawProjectsResponse } from '../openclawParser.js';\nimport { getProjectsResponse as getOpencodeProjectsResponse } from '../opencodeParser.js';\nimport { getProjectsResponse as getClaudeProjectsResponse } from '../claudeJsonlParser.js';\n\nexport async function getProjects(req: Request, res: Response): Promise<void> {\n const agent = req.query.agent as string || 'claude';\n const cacheKey = `projects:${agent}`;\n try {\n const cached = cache.get(cacheKey);\n if (cached) {\n res.json(cached);\n return;\n }\n\n // Stale-while-revalidate\n const stale = cache.getStale(cacheKey);\n if (stale) {\n refreshProjectsCache(agent, cacheKey);\n res.json(stale);\n return;\n }\n\n const data = fetchProjectsData(agent);\n cache.set(cacheKey, data);\n res.json(data);\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Unknown error';\n console.error('Error fetching projects data:', error);\n res.status(502).json({\n error: `Failed to fetch projects data from ${agent}`,\n hint: message,\n });\n }\n}\n\nfunction fetchProjectsData(agent: string) {\n if (agent === 'codex') {\n return getCodexProjectsResponse();\n } else if (agent === 'openclaw') {\n return validateProjects(getOpenClawProjectsResponse());\n } else if (agent === 'opencode') {\n return validateProjects(getOpencodeProjectsResponse());\n } else {\n // Claude Code: parse JSONL directly (fast, no CLI)\n return validateProjects(getClaudeProjectsResponse());\n }\n}\n\nfunction refreshProjectsCache(agent: string, cacheKey: string): void {\n Promise.resolve()\n .then(() => { const data = fetchProjectsData(agent); cache.set(cacheKey, data); })\n .catch(err => console.error('Background refresh failed (projects):', err));\n}\n", "import { type Request, type Response } from 'express';\nimport { cache } from '../cache.js';\nimport { validateBlocks } from '../../shared/schemas.js';\nimport { getBlocksResponse as getCodexBlocksResponse } from '../codexParser.js';\nimport { getBlocksResponse as getOpenClawBlocksResponse } from '../openclawParser.js';\nimport { getBlocksResponse as getOpencodeBlocksResponse } from '../opencodeParser.js';\nimport { getBlocksResponse as getClaudeBlocksResponse } from '../claudeJsonlParser.js';\n\nexport async function getBlocks(req: Request, res: Response): Promise<void> {\n const agent = req.query.agent as string || 'claude';\n const project = req.query.project as string || undefined;\n\n try {\n const cacheKey = `blocks:${agent}:${project || 'all'}`;\n const cached = cache.get(cacheKey);\n if (cached) {\n res.json(cached);\n return;\n }\n\n // Stale-while-revalidate\n const stale = cache.getStale(cacheKey);\n if (stale) {\n refreshBlocksCache(agent, project, cacheKey);\n res.json(stale);\n return;\n }\n\n const data = fetchBlocksData(agent, project);\n cache.set(cacheKey, data);\n res.json(data);\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Unknown error';\n console.error('Error fetching blocks data:', error);\n res.status(502).json({\n error: 'Failed to fetch blocks data',\n hint: message,\n });\n }\n}\n\nfunction fetchBlocksData(agent: string, project?: string) {\n if (agent === 'openclaw') {\n return validateBlocks(getOpenClawBlocksResponse({ project: project || null }));\n } else if (agent === 'opencode') {\n return validateBlocks(getOpencodeBlocksResponse({ project: project || null }));\n } else if (agent === 'codex') {\n return validateBlocks(getCodexBlocksResponse({ project: project || null }));\n } else {\n // Claude Code: parse JSONL directly (fast, no CLI)\n return validateBlocks(getClaudeBlocksResponse(project || null));\n }\n}\n\nfunction refreshBlocksCache(agent: string, project: string | undefined, cacheKey: string): void {\n Promise.resolve()\n .then(() => { const data = fetchBlocksData(agent, project); cache.set(cacheKey, data); })\n .catch(err => console.error('Background refresh failed (blocks):', err));\n}\n", "import { readFileSync, readdirSync, statSync, existsSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { homedir } from 'node:os';\nimport { scanOpenClawSessions } from './openclawParser.js';\nimport type { AnalyticsResponse, ToolUsageEntry, DailyCodeChange, DailyToolCall, ProductivityKPIs } from '../shared/types.js';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ninterface ToolCallRecord {\n toolName: string; // normalized name\n timestamp: number; // ms epoch\n filePath?: string;\n linesAdded: number;\n linesDeleted: number;\n}\n\n// ---------------------------------------------------------------------------\n// Timezone helpers (same as other parsers)\n// ---------------------------------------------------------------------------\n\nconst TZ_OFFSETS: Record<string, number> = {\n 'Asia/Shanghai': 8,\n 'Asia/Tokyo': 9,\n 'America/New_York': -5,\n 'America/Los_Angeles': -8,\n 'Europe/London': 0,\n 'UTC': 0,\n};\n\nfunction getDateKey(ms: number, tz: string): string {\n const offset = (TZ_OFFSETS[tz] ?? 8) * 3_600_000;\n const d = new Date(ms + offset);\n return `${d.getUTCFullYear()}-${String(d.getUTCMonth() + 1).padStart(2, '0')}-${String(d.getUTCDate()).padStart(2, '0')}`;\n}\n\n// ---------------------------------------------------------------------------\n// Tool name normalization\n// ---------------------------------------------------------------------------\n\nexport function normalizeToolName(name: string): string {\n const lower = name.toLowerCase();\n if (lower.startsWith('mcp__')) {\n const parts = name.split('__');\n const serverPart = parts.length >= 3 ? parts[2] : 'mcp';\n return `MCP:${serverPart}`;\n }\n const mapping: Record<string, string> = {\n 'exec': 'Bash',\n 'read': 'Read',\n 'edit': 'Edit',\n 'write': 'Write',\n };\n return mapping[lower] || name;\n}\n\n// ---------------------------------------------------------------------------\n// Line counting\n// ---------------------------------------------------------------------------\n\nfunction countLines(text: string): number {\n if (!text) return 0;\n return text.split('\\n').length;\n}\n\n// ---------------------------------------------------------------------------\n// Claude Code session scanning & tool extraction\n// ---------------------------------------------------------------------------\n\nconst CLAUDE_PROJECTS_DIR = join(homedir(), '.claude', 'projects');\n\nfunction extractProjectName(dirName: string): string {\n const parts = dirName.replace(/^-/, '').split('-');\n return parts[parts.length - 1] || dirName;\n}\n\nfunction matchesProject(dirName: string, filter: string): boolean {\n return extractProjectName(dirName) === extractProjectName(filter);\n}\n\n// Session-level cache (mtime-based)\nconst claudeSessionCache = new Map<string, { mtime: number; toolCalls: ToolCallRecord[] }>();\n\nexport function extractClaudeToolCalls(project?: string | null): ToolCallRecord[] {\n if (!existsSync(CLAUDE_PROJECTS_DIR)) return [];\n\n const results: ToolCallRecord[] = [];\n const projectDirs = readdirSync(CLAUDE_PROJECTS_DIR, { withFileTypes: true })\n .filter(d => d.isDirectory())\n .map(d => d.name);\n\n for (const dirName of projectDirs) {\n if (project && !matchesProject(dirName, project)) continue;\n\n const dirPath = join(CLAUDE_PROJECTS_DIR, dirName);\n let files: string[];\n try {\n files = readdirSync(dirPath).filter(f => f.endsWith('.jsonl'));\n } catch {\n continue;\n }\n\n for (const file of files) {\n const filePath = join(dirPath, file);\n\n let mtime = 0;\n try { mtime = statSync(filePath).mtimeMs; } catch { /* ok */ }\n\n const cached = claudeSessionCache.get(filePath);\n if (cached && cached.mtime === mtime) {\n results.push(...cached.toolCalls);\n continue;\n }\n\n const toolCalls: ToolCallRecord[] = [];\n let content: string;\n try {\n content = readFileSync(filePath, 'utf-8');\n } catch {\n continue;\n }\n\n for (const line of content.split('\\n')) {\n const trimmed = line.trim();\n if (!trimmed) continue;\n\n let obj: Record<string, unknown>;\n try { obj = JSON.parse(trimmed) as Record<string, unknown>; } catch { continue; }\n\n if (obj.type !== 'assistant' || !obj.message) continue;\n const msg = obj.message as Record<string, unknown>;\n const timestamp = new Date(obj.timestamp as string).getTime();\n const content_arr = msg.content as Array<Record<string, unknown>> | undefined;\n if (!content_arr) continue;\n\n for (const item of content_arr) {\n if (item.type !== 'tool_use') continue;\n\n const toolName = normalizeToolName(item.name as string);\n const input = (item.input as Record<string, unknown>) || {};\n\n let linesAdded = 0;\n let linesDeleted = 0;\n const filePath2 = (input.file_path as string) || undefined;\n\n if (toolName === 'Edit') {\n linesDeleted = countLines(input.old_string as string || '');\n linesAdded = countLines(input.new_string as string || '');\n } else if (toolName === 'Write') {\n linesAdded = countLines(input.content as string || '');\n }\n\n toolCalls.push({ toolName, timestamp, filePath: filePath2, linesAdded, linesDeleted });\n }\n }\n\n claudeSessionCache.set(filePath, { mtime, toolCalls });\n results.push(...toolCalls);\n }\n }\n\n return results;\n}\n\n// ---------------------------------------------------------------------------\n// OpenClaw tool extraction\n// ---------------------------------------------------------------------------\n\nconst openclawSessionCache = new Map<string, { mtime: number; toolCalls: ToolCallRecord[] }>();\n\nexport function extractOpenClawToolCalls(project?: string | null): ToolCallRecord[] {\n const results: ToolCallRecord[] = [];\n const refs = scanOpenClawSessions();\n\n for (const ref of refs) {\n if (project && ref.agentId !== project) continue;\n\n let mtime = 0;\n try { mtime = statSync(ref.sessionFile).mtimeMs; } catch { /* ok */ }\n\n const cached = openclawSessionCache.get(ref.sessionFile);\n if (cached && cached.mtime === mtime) {\n results.push(...cached.toolCalls);\n continue;\n }\n\n const toolCalls: ToolCallRecord[] = [];\n let content: string;\n try {\n content = readFileSync(ref.sessionFile, 'utf-8');\n } catch {\n continue;\n }\n\n for (const line of content.split('\\n')) {\n const trimmed = line.trim();\n if (!trimmed) continue;\n\n let obj: Record<string, unknown>;\n try { obj = JSON.parse(trimmed) as Record<string, unknown>; } catch { continue; }\n\n if (obj.type !== 'message') continue;\n const msg = obj.message as Record<string, unknown>;\n if (msg.role !== 'assistant') continue;\n\n const timestamp = Number(msg.timestamp ?? 0);\n const content_arr = msg.content as Array<Record<string, unknown>> | undefined;\n if (!content_arr) continue;\n\n for (const item of content_arr) {\n if (item.type !== 'toolCall') continue;\n\n const toolName = normalizeToolName(item.name as string);\n const args = (item.arguments as Record<string, unknown>) || {};\n\n let linesAdded = 0;\n let linesDeleted = 0;\n const filePath2 = (args.path as string) || undefined;\n\n if (toolName === 'Edit') {\n linesDeleted = countLines(args.oldText as string || '');\n linesAdded = countLines(args.newText as string || '');\n } else if (toolName === 'Write') {\n linesAdded = countLines(args.content as string || '');\n }\n\n toolCalls.push({ toolName, timestamp, filePath: filePath2, linesAdded, linesDeleted });\n }\n }\n\n openclawSessionCache.set(ref.sessionFile, { mtime, toolCalls });\n results.push(...toolCalls);\n }\n\n return results;\n}\n\n// ---------------------------------------------------------------------------\n// Analytics computation\n// ---------------------------------------------------------------------------\n\nexport function computeAnalytics(toolCalls: ToolCallRecord[], timezone = 'Asia/Shanghai'): AnalyticsResponse {\n // 1. Code Change Trend \u2014 group edit/write calls by date\n const changeMap = new Map<string, { added: number; deleted: number; files: Set<string> }>();\n for (const tc of toolCalls) {\n if (tc.linesAdded === 0 && tc.linesDeleted === 0) continue;\n const key = getDateKey(tc.timestamp, timezone);\n if (!changeMap.has(key)) changeMap.set(key, { added: 0, deleted: 0, files: new Set() });\n const entry = changeMap.get(key)!;\n entry.added += tc.linesAdded;\n entry.deleted += tc.linesDeleted;\n if (tc.filePath) entry.files.add(tc.filePath);\n }\n const codeChangeTrend: DailyCodeChange[] = [];\n for (const [date, { added, deleted, files }] of changeMap) {\n codeChangeTrend.push({ date, linesAdded: added, linesDeleted: deleted, netChange: added - deleted, filesModified: files.size });\n }\n codeChangeTrend.sort((a, b) => a.date.localeCompare(b.date));\n\n // 2. Tool Usage Distribution \u2014 count per tool\n const toolCountMap = new Map<string, number>();\n for (const tc of toolCalls) {\n toolCountMap.set(tc.toolName, (toolCountMap.get(tc.toolName) || 0) + 1);\n }\n const toolUsageDistribution: ToolUsageEntry[] = [...toolCountMap.entries()]\n .map(([name, count]) => ({ name, count }))\n .sort((a, b) => b.count - a.count);\n\n // 3. Productivity KPIs\n const editCalls = toolCalls.filter(tc => tc.toolName === 'Edit' || tc.toolName === 'Write');\n const totalEdits = editCalls.length;\n const totalLinesChanged = editCalls.reduce((s, tc) => s + tc.linesAdded + tc.linesDeleted, 0);\n const totalLinesAdded = editCalls.reduce((s, tc) => s + tc.linesAdded, 0);\n const totalLinesDeleted = editCalls.reduce((s, tc) => s + tc.linesDeleted, 0);\n const uniqueFiles = new Set(editCalls.filter(tc => tc.filePath).map(tc => tc.filePath!));\n const editDates = new Set(editCalls.map(tc => getDateKey(tc.timestamp, timezone)));\n\n const productivityKPIs: ProductivityKPIs = {\n avgLinesPerEdit: totalEdits > 0 ? Math.round(totalLinesChanged / totalEdits) : 0,\n filesModifiedPerDay: editDates.size > 0 ? Math.round(uniqueFiles.size / editDates.size) : 0,\n addDeleteRatio: totalLinesDeleted > 0 ? Math.round((totalLinesAdded / totalLinesDeleted) * 100) / 100 : totalLinesAdded > 0 ? 1 : 0,\n totalEdits,\n totalFilesModified: uniqueFiles.size,\n activeDaysWithEdits: editDates.size,\n };\n\n // 4. Tool Call Trend \u2014 group all calls by (date, toolName)\n const trendMap = new Map<string, Map<string, number>>();\n for (const tc of toolCalls) {\n const date = getDateKey(tc.timestamp, timezone);\n if (!trendMap.has(date)) trendMap.set(date, new Map());\n const dayMap = trendMap.get(date)!;\n dayMap.set(tc.toolName, (dayMap.get(tc.toolName) || 0) + 1);\n }\n const toolCallTrend: DailyToolCall[] = [];\n for (const [date, dayMap] of trendMap) {\n const entry: DailyToolCall = { date };\n for (const [tool, count] of dayMap) {\n entry[tool] = count;\n }\n toolCallTrend.push(entry);\n }\n toolCallTrend.sort((a, b) => a.date.localeCompare(b.date));\n\n return { codeChangeTrend, toolUsageDistribution, productivityKPIs, toolCallTrend };\n}\n", "import { type Request, type Response } from 'express';\nimport { cache } from '../cache.js';\nimport { validateAnalytics } from '../../shared/schemas.js';\nimport { extractClaudeToolCalls, extractOpenClawToolCalls, computeAnalytics } from '../analyticsParser.js';\n\nconst EMPTY_ANALYTICS = {\n codeChangeTrend: [],\n toolUsageDistribution: [],\n productivityKPIs: { avgLinesPerEdit: 0, filesModifiedPerDay: 0, addDeleteRatio: 0, totalEdits: 0, totalFilesModified: 0, activeDaysWithEdits: 0 },\n toolCallTrend: [],\n};\n\nexport async function getAnalytics(req: Request, res: Response): Promise<void> {\n const agent = req.query.agent as string || 'claude';\n const project = req.query.project as string || undefined;\n\n if (agent === 'codex' || agent === 'opencode') {\n res.json(EMPTY_ANALYTICS);\n return;\n }\n\n try {\n const cacheKey = `analytics:${agent}:${project || 'all'}`;\n const cached = cache.get(cacheKey);\n if (cached) {\n res.json(cached);\n return;\n }\n\n const toolCalls = agent === 'openclaw'\n ? extractOpenClawToolCalls(project || null)\n : extractClaudeToolCalls(project || null);\n\n const data = computeAnalytics(toolCalls);\n const validated = validateAnalytics(data);\n cache.set(cacheKey, validated);\n res.json(validated);\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Unknown error';\n console.error('Error fetching analytics:', error);\n res.status(502).json({\n error: `Failed to fetch analytics from ${agent}`,\n hint: message,\n });\n }\n}\n", "import { existsSync, readdirSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { homedir } from 'node:os';\n\nconst CLAUDE_PROJECTS_DIR = join(homedir(), '.claude', 'projects');\nconst CODEX_SESSIONS_DIR = join(homedir(), '.codex', 'sessions');\n\nexport function isClaudeCodeAvailable(): boolean {\n if (!existsSync(CLAUDE_PROJECTS_DIR)) return false;\n try {\n const dirs = readdirSync(CLAUDE_PROJECTS_DIR, { withFileTypes: true });\n return dirs.some(d => d.isDirectory());\n } catch {\n return false;\n }\n}\n\nexport function isCodexAvailable(): boolean {\n return existsSync(CODEX_SESSIONS_DIR);\n}\n\nexport function isOpencodeAvailable(): boolean {\n return existsSync(join(homedir(), '.local', 'share', 'opencode', 'opencode.db'));\n}\n\nexport function detectAvailableAgents(): { claude: boolean; codex: boolean; opencode: boolean } {\n return {\n claude: isClaudeCodeAvailable(),\n codex: isCodexAvailable(),\n opencode: isOpencodeAvailable(),\n };\n}\n", "import { type Router, type Request, type Response } from 'express';\nimport { getDaily } from './daily.js';\nimport { getMonthly } from './monthly.js';\nimport { getSession } from './session.js';\nimport { getProjects } from './projects.js';\nimport { getBlocks } from './blocks.js';\nimport { getAnalytics } from './analytics.js';\nimport { detectAvailableAgents } from '../agentDetection.js';\nimport { isOpenClawAccessible } from '../openclawParser.js';\nimport { isOpencodeAccessible } from '../opencodeParser.js';\n\nfunction getAgents(_req: Request, res: Response): void {\n try {\n const agents = detectAvailableAgents();\n const available: string[] = [];\n if (agents.claude) available.push('claude');\n if (agents.codex) available.push('codex');\n if (isOpenClawAccessible()) available.push('openclaw');\n if (isOpencodeAccessible()) available.push('opencode');\n res.json({ available, default: available[0] || null });\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Unknown error';\n res.status(500).json({ error: 'Failed to detect agents', hint: message });\n }\n}\n\nexport function registerApiRoutes(router: Router): void {\n router.get('/agents', getAgents);\n router.get('/daily', getDaily);\n router.get('/monthly', getMonthly);\n router.get('/session', getSession);\n router.get('/projects', getProjects);\n router.get('/blocks', getBlocks);\n router.get('/analytics', getAnalytics);\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": ["import_node_fs", "import_node_path", "import_node_fs", "import_node_path", "import_node_os", "import_zod", "
|
|
4
|
+
"sourcesContent": ["import express from 'express';\nimport type { Express } from 'express';\nimport { existsSync, readFileSync } from 'node:fs';\nimport type { Server } from 'node:http';\nimport { fileURLToPath } from 'node:url';\nimport { basename, dirname, join, resolve } from 'node:path';\nimport { registerApiRoutes } from './routes/api.js';\nimport { detectAvailableAgents } from './agentDetection.js';\nimport open from 'open';\n\ninterface CliArgs {\n port?: number;\n noOpen?: boolean;\n showVersion?: boolean;\n tray?: boolean;\n}\n\nconst CLI_USAGE = [\n 'Usage:',\n ' tokendash',\n ' tokendash --version',\n ' tokendash --port <number> [--no-open]',\n ' tokendash --tray [--port <number>]',\n].join('\\n');\n\nfunction getPackageVersion(): string {\n const __filename = fileURLToPath(import.meta.url);\n const __dirname = dirname(__filename);\n const packageJson = JSON.parse(readFileSync(join(__dirname, '..', '..', 'package.json'), 'utf8')) as { version?: string };\n return packageJson.version ?? 'unknown';\n}\n\nfunction exitWithCliError(message: string): never {\n console.error(message);\n console.error(`\\n${CLI_USAGE}`);\n process.exit(1);\n}\n\nfunction parseCliArgs(): CliArgs {\n const args = process.argv.slice(2);\n const result: CliArgs = {};\n\n if (args.length === 1 && (args[0] === '--version' || args[0] === '-v')) {\n result.showVersion = true;\n return result;\n }\n\n for (let i = 0; i < args.length; i++) {\n const arg = args[i];\n\n if (arg === '--version' || arg === '-v') {\n exitWithCliError('The --version flag must be used by itself.');\n }\n\n if (arg === '--port') {\n if (i + 1 >= args.length) {\n exitWithCliError('Missing value for --port.');\n }\n\n const value = parseInt(args[i + 1], 10);\n if (!Number.isInteger(value) || value <= 0) {\n exitWithCliError(`Invalid port value: ${args[i + 1]}`);\n }\n\n result.port = value;\n i++;\n } else if (arg === '--no-open') {\n result.noOpen = true;\n } else if (arg === '--tray') {\n result.tray = true;\n } else {\n exitWithCliError(`Unsupported argument: ${arg}`);\n }\n }\n\n return result;\n}\n\nasync function ensureUsageSupportAvailable(): Promise<boolean> {\n try {\n const agents = detectAvailableAgents();\n if (!agents.claude && !agents.codex) {\n console.error('Error: No AI coding assistant data found.');\n console.error('\\nDetails: Could not find Claude Code (~/.claude/projects/) or Codex (~/.codex/sessions/) data.');\n console.error('Please install at least one of: Claude Code or Codex CLI.');\n return false;\n }\n if (agents.claude) console.log(' \u2713 Claude Code detected');\n if (agents.codex) console.log(' \u2713 Codex detected');\n return true;\n } catch (error) {\n console.error('Error: failed to detect available AI coding assistants');\n console.error('\\nDetails:', error instanceof Error ? error.message : error);\n return false;\n }\n}\n\nfunction resolvePort(value?: number): number {\n return Number.isInteger(value) && value && value > 0 ? value : 3456;\n}\n\nfunction listen(app: Express, port: number): Promise<Server> {\n return new Promise((resolve, reject) => {\n const server = app.listen(port);\n\n const handleListening = () => {\n cleanup();\n resolve(server);\n };\n\n const handleError = (error: Error) => {\n cleanup();\n reject(error);\n };\n\n const cleanup = () => {\n server.off('listening', handleListening);\n server.off('error', handleError);\n };\n\n server.once('listening', handleListening);\n server.once('error', handleError);\n });\n}\n\nasync function listenWithPortFallback(app: Express, preferredPort: number): Promise<{ server: Server; port: number; usedFallback: boolean }> {\n let port = preferredPort;\n\n for (let attempt = 0; attempt < 20; attempt++, port++) {\n try {\n const server = await listen(app, port);\n return { server, port, usedFallback: port !== preferredPort };\n } catch (error) {\n const err = error as NodeJS.ErrnoException;\n if (err.code !== 'EADDRINUSE') {\n throw error;\n }\n }\n }\n\n throw new Error(`Could not find an available port starting from ${preferredPort}`);\n}\n\nexport function resolveStaticAssetBaseDir(moduleUrl = import.meta.url, baseDir?: string): { baseDir: string; isProduction: boolean } {\n if (baseDir) return { baseDir: resolve(baseDir), isProduction: true };\n\n const moduleDir = dirname(fileURLToPath(moduleUrl));\n const isProduction = moduleUrl.includes('/dist/');\n\n if (!isProduction) return { baseDir: resolve(moduleDir), isProduction: false };\n\n // The CLI entrypoint runs from dist/server/index.js while the Vite assets are\n // emitted to dist/client. Resolve the production asset base to dist instead\n // of dist/server so / resolves to dist/client/index.html in installed npm\n // packages. Electron passes dist explicitly and is unaffected by this branch.\n if (basename(moduleDir) === 'server') {\n return { baseDir: resolve(dirname(moduleDir)), isProduction: true };\n }\n\n return { baseDir: resolve(moduleDir), isProduction: true };\n}\n\nexport function createApp(_port: number, baseDir?: string): Express {\n const app = express();\n const router = express.Router();\n\n // Register API routes\n registerApiRoutes(router);\n app.use('/api', router);\n\n const { baseDir: _baseDir, isProduction } = resolveStaticAssetBaseDir(import.meta.url, baseDir);\n const popoverPath = isProduction\n ? join(_baseDir, 'client', 'popover.html')\n : join(_baseDir, '..', '..', 'public', 'popover.html');\n\n app.get('/popover.html', (_req, res, next) => {\n if (!existsSync(popoverPath)) {\n next();\n return;\n }\n res.type('html').send(readFileSync(popoverPath, 'utf8'));\n });\n\n // Check if running from dist (production build)\n if (isProduction) {\n // Serve static files from client build\n const clientPath = join(_baseDir, 'client');\n const clientIndexPath = join(clientPath, 'index.html');\n\n app.use(express.static(clientPath));\n\n // SPA fallback\n app.use('{*path}', (_req, res) => {\n res.sendFile(clientIndexPath);\n });\n }\n\n return app;\n}\n\nasync function main() {\n const args = parseCliArgs();\n if (args.showVersion) {\n console.log(getPackageVersion());\n return;\n }\n\n const version = getPackageVersion();\n const preferredPort = resolvePort(args.port ?? (process.env.PORT ? parseInt(process.env.PORT, 10) : undefined));\n\n // --tray mode: launch Electron\n if (args.tray) {\n if (process.platform !== 'darwin') {\n console.error('Error: --tray is only supported on macOS.');\n process.exit(1);\n }\n console.log(`Starting tokendash v${version} in tray mode...`);\n // @ts-ignore -- electron is installed separately for tray mode\n const { default: electronPath } = await import('electron');\n const { spawn } = await import('node:child_process');\n const child = spawn(electronPath as unknown as string, ['.'], {\n env: {\n ...process.env,\n TOKENDASH_PORT: String(preferredPort),\n TOKENDASH_TRAY: '1',\n },\n stdio: 'inherit',\n });\n child.on('close', (code) => process.exit(code ?? 0));\n process.on('SIGTERM', () => child.kill('SIGTERM'));\n return;\n }\n\n const shouldOpenBrowser = !args.noOpen;\n\n console.log(`Starting tokendash v${version}...`);\n console.log(`Checking local usage data sources...`);\n\n const isUsageSupportAvailable = await ensureUsageSupportAvailable();\n if (!isUsageSupportAvailable) {\n process.exit(1);\n }\n\n const app = createApp(preferredPort);\n const { server, port, usedFallback } = await listenWithPortFallback(app, preferredPort);\n\n if (usedFallback) {\n console.warn(`tokendash detected that port ${preferredPort} is already in use, switched to http://localhost:${port}`);\n }\n\n console.log(`tokendash running on http://localhost:${port}`);\n console.log(`API available at http://localhost:${port}/api`);\n const isProduction = import.meta.url.includes('dist/');\n if (isProduction) {\n console.log('Serving production build');\n } else {\n console.log('Development mode - use \"npm run dev\" for full dev experience');\n }\n\n // Open browser if requested\n if (shouldOpenBrowser) {\n // Small delay to ensure server is ready\n setTimeout(() => {\n console.log('Opening dashboard in your browser...');\n open(`http://localhost:${port}`).catch((err) => {\n console.warn('Could not open browser:', err.message);\n });\n }, 100);\n } else {\n console.log('Browser auto-open disabled (--no-open)');\n }\n\n // Graceful shutdown\n process.on('SIGTERM', () => {\n server.close(() => {\n console.log('Server closed');\n process.exit(0);\n });\n });\n}\n\nexport { main };\n", "import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { tmpdir } from 'node:os';\n\nconst DEFAULT_TTL = 5 * 60 * 1000; // 5 minutes (fresh)\nconst DISK_TTL = 60 * 60 * 1000; // 1 hour (stale but usable)\n\nconst CACHE_DIR = join(tmpdir(), 'tokendash-cache');\n\ninterface CacheEntry<T> {\n data: T;\n expiresAt: number;\n updatedAt: number;\n}\n\nfunction diskPath(key: string): string {\n const safe = key.replace(/[^a-zA-Z0-9_-]/g, '_');\n return join(CACHE_DIR, `${safe}.json`);\n}\n\nclass Cache {\n private store = new Map<string, CacheEntry<unknown>>();\n\n get<T>(key: string): T | null {\n const entry = this.store.get(key);\n if (entry && Date.now() <= entry.expiresAt) {\n return entry.data as T;\n }\n return null;\n }\n\n /** Get data even if stale (for stale-while-revalidate) */\n getStale<T>(key: string): T | null {\n // Try memory first\n const entry = this.store.get(key);\n if (entry) return entry.data as T;\n\n // Try disk\n return this.readFromDisk<T>(key);\n }\n\n set<T>(key: string, data: T, ttl: number = DEFAULT_TTL): void {\n const entry: CacheEntry<T> = {\n data,\n expiresAt: Date.now() + ttl,\n updatedAt: Date.now(),\n };\n this.store.set(key, entry as CacheEntry<unknown>);\n this.writeToDisk(key, entry);\n }\n\n clear(): void {\n this.store.clear();\n }\n\n delete(key: string): boolean {\n return this.store.delete(key);\n }\n\n has(key: string): boolean {\n const entry = this.store.get(key);\n if (!entry) return false;\n if (Date.now() > entry.expiresAt) {\n this.store.delete(key);\n return false;\n }\n return true;\n }\n\n private writeToDisk<T>(key: string, entry: CacheEntry<T>): void {\n try {\n if (!existsSync(CACHE_DIR)) mkdirSync(CACHE_DIR, { recursive: true });\n writeFileSync(diskPath(key), JSON.stringify(entry), 'utf-8');\n } catch {\n // Disk cache is best-effort\n }\n }\n\n private readFromDisk<T>(key: string): T | null {\n try {\n const path = diskPath(key);\n if (!existsSync(path)) return null;\n const raw = readFileSync(path, 'utf-8');\n const entry = JSON.parse(raw) as CacheEntry<T>;\n // Only use disk cache if less than DISK_TTL old\n if (Date.now() - entry.updatedAt < DISK_TTL) {\n // Promote to memory cache (with 0 TTL so it'll be treated as stale)\n this.store.set(key, { ...entry, expiresAt: 0 } as CacheEntry<unknown>);\n return entry.data;\n }\n } catch {\n // Disk cache is best-effort\n }\n return null;\n }\n}\n\nexport const cache = new Cache();\nexport type { CacheEntry };\n", "import { z } from 'zod';\n\nexport const ModelBreakdownSchema = z.object({\n modelName: z.string(),\n inputTokens: z.number().default(0),\n outputTokens: z.number().default(0),\n cacheCreationTokens: z.number().default(0),\n cacheReadTokens: z.number().default(0),\n cost: z.number().default(0),\n});\n\nexport const DailyEntrySchema = z.object({\n date: z.string(),\n inputTokens: z.number().default(0),\n outputTokens: z.number().default(0),\n cacheCreationTokens: z.number().default(0),\n cacheReadTokens: z.number().default(0),\n totalTokens: z.number().default(0),\n totalCost: z.number().default(0),\n modelsUsed: z.array(z.string()).default([]),\n modelBreakdowns: z.array(ModelBreakdownSchema).default([]),\n});\n\nexport const TotalsSchema = z.object({\n inputTokens: z.number().default(0),\n outputTokens: z.number().default(0),\n cacheCreationTokens: z.number().default(0),\n cacheReadTokens: z.number().default(0),\n totalTokens: z.number().default(0),\n totalCost: z.number().default(0),\n});\n\nexport const DailyResponseSchema = z.object({\n daily: z.array(DailyEntrySchema).default([]),\n totals: TotalsSchema,\n});\n\nexport const ProjectEntrySchema = z.object({\n projectPath: z.string(),\n instances: z.array(DailyEntrySchema).default([]),\n});\n\nexport const ProjectsResponseSchema = z.object({\n projects: z.record(z.array(DailyEntrySchema).default([])).default({}),\n});\n\nexport function validateDaily(data: unknown) {\n return DailyResponseSchema.parse(data);\n}\n\nexport function validateProjects(data: unknown) {\n return ProjectsResponseSchema.parse(data);\n}\n\nconst BlockEntrySchema = z.object({\n id: z.string(),\n startTime: z.string(),\n endTime: z.string(),\n actualEndTime: z.string().nullable().default(null),\n isActive: z.boolean().default(false),\n isGap: z.boolean().default(false),\n entries: z.number().default(0),\n tokenCounts: z.object({\n inputTokens: z.number().default(0),\n outputTokens: z.number().default(0),\n cacheCreationInputTokens: z.number().default(0),\n cacheReadInputTokens: z.number().default(0),\n }).default({ inputTokens: 0, outputTokens: 0, cacheCreationInputTokens: 0, cacheReadInputTokens: 0 }),\n totalTokens: z.number().default(0),\n costUSD: z.number().default(0),\n models: z.array(z.string()).default([]),\n});\n\nexport const BlocksResponseSchema = z.object({\n blocks: z.array(BlockEntrySchema).default([]),\n});\n\nexport function validateBlocks(data: unknown) {\n return BlocksResponseSchema.parse(data);\n}\n\n// --- Analytics schemas ---\n\nconst DailyCodeChangeSchema = z.object({\n date: z.string(),\n linesAdded: z.number().default(0),\n linesDeleted: z.number().default(0),\n netChange: z.number().default(0),\n filesModified: z.number().default(0),\n});\n\nconst ToolUsageEntrySchema = z.object({\n name: z.string(),\n count: z.number().default(0),\n});\n\nconst ProductivityKPIsSchema = z.object({\n avgLinesPerEdit: z.number().default(0),\n filesModifiedPerDay: z.number().default(0),\n addDeleteRatio: z.number().default(0),\n totalEdits: z.number().default(0),\n totalFilesModified: z.number().default(0),\n activeDaysWithEdits: z.number().default(0),\n});\n\nconst AnalyticsResponseSchema = z.object({\n codeChangeTrend: z.array(DailyCodeChangeSchema).default([]),\n toolUsageDistribution: z.array(ToolUsageEntrySchema).default([]),\n productivityKPIs: ProductivityKPIsSchema,\n toolCallTrend: z.array(z.record(z.union([z.string(), z.number()]))).default([]),\n});\n\nexport function validateAnalytics(data: unknown) {\n return AnalyticsResponseSchema.parse(data);\n}\n", "import { readFileSync, readdirSync, statSync, accessSync, constants } from 'node:fs';\nimport { join } from 'node:path';\nimport { homedir } from 'node:os';\nimport { z } from 'zod';\nimport type { DailyEntry, DailyResponse, ProjectsResponse, BlockEntry, BlocksResponse, ModelBreakdown } from '../shared/types.js';\nimport { calculateCost } from './codexPricing.js';\n\n// ---------------------------------------------------------------------------\n// Zod schemas for JSONL event validation (format change detector)\n// ---------------------------------------------------------------------------\n\nconst TokenUsageSchema = z.object({\n input_tokens: z.number().default(0),\n cached_input_tokens: z.number().default(0),\n output_tokens: z.number().default(0),\n reasoning_output_tokens: z.number().default(0),\n total_tokens: z.number().default(0),\n}).default({ input_tokens: 0, cached_input_tokens: 0, output_tokens: 0, reasoning_output_tokens: 0, total_tokens: 0 });\n\nconst TokenCountInfoSchema = z.object({\n total_token_usage: TokenUsageSchema,\n last_token_usage: TokenUsageSchema,\n}).nullable().default(null);\n\nconst TokenCountPayloadSchema = z.object({\n type: z.literal('token_count'),\n info: TokenCountInfoSchema,\n});\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface ParsedTokenEvent {\n timestamp: string;\n inputTokens: number;\n cachedInputTokens: number;\n outputTokens: number;\n reasoningOutputTokens: number;\n totalTokens: number;\n}\n\nexport interface ParsedSession {\n id: string;\n cwd: string;\n model: string;\n createdAt: string;\n tokenEvents: ParsedTokenEvent[];\n}\n\nexport interface AggregateOptions {\n groupBy: 'day' | 'hour' | 'month' | 'session' | 'project';\n project?: string | null;\n since?: Date | null;\n until?: Date | null;\n timezone?: string;\n}\n\ninterface TokenAccumulator {\n inputTokens: number;\n cachedInputTokens: number;\n outputTokens: number;\n reasoningOutputTokens: number;\n totalTokens: number;\n}\n\ninterface AggregateBucket {\n acc: TokenAccumulator;\n models: Map<string, TokenAccumulator>;\n}\n\nfunction tokenUsageKey(usage: z.infer<typeof TokenUsageSchema>): string {\n return [\n usage.input_tokens,\n usage.cached_input_tokens,\n usage.output_tokens,\n usage.reasoning_output_tokens,\n usage.total_tokens,\n ].join(':');\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction getSessionsDir(): string {\n return join(homedir(), '.codex', 'sessions');\n}\n\nexport function isSessionsDirAccessible(): boolean {\n try {\n accessSync(getSessionsDir(), constants.R_OK);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Recursively find all .jsonl files under ~/.codex/sessions/\n */\nexport function scanCodexSessions(): string[] {\n const sessionsDir = getSessionsDir();\n const results: string[] = [];\n\n function walk(dir: string): void {\n let entries;\n try {\n entries = readdirSync(dir);\n } catch {\n return;\n }\n for (const entry of entries) {\n const full = join(dir, entry);\n let st: ReturnType<typeof statSync>;\n try {\n st = statSync(full);\n } catch {\n continue;\n }\n if (st.isDirectory()) {\n walk(full);\n } else if (entry.endsWith('.jsonl')) {\n results.push(full);\n }\n }\n }\n\n walk(sessionsDir);\n return results.sort();\n}\n\n/**\n * Parse a single Codex session JSONL file.\n *\n * Codex can emit duplicate token_count events for the same turn, with identical\n * total_token_usage and last_token_usage snapshots a few seconds apart. These\n * are repeated status updates, not separate billable usage records, so only the\n * first occurrence of each cumulative total_token_usage snapshot should count.\n */\nexport function parseCodexSession(filepath: string): ParsedSession | null {\n let content: string;\n try {\n content = readFileSync(filepath, 'utf-8');\n } catch {\n return null;\n }\n\n const lines = content.split('\\n');\n let sessionId = '';\n let cwd = '';\n let model = '';\n let createdAt = '';\n const tokenEvents: ParsedTokenEvent[] = [];\n const seenTotalUsageSnapshots = new Set<string>();\n\n for (const line of lines) {\n const trimmed = line.trim();\n if (!trimmed) continue;\n\n let obj: Record<string, unknown>;\n try {\n obj = JSON.parse(trimmed) as Record<string, unknown>;\n } catch {\n continue;\n }\n\n const type = obj.type as string;\n\n if (type === 'session_meta') {\n const payload = (obj.payload as Record<string, unknown>) || {};\n sessionId = (payload.id as string) || '';\n cwd = (payload.cwd as string) || '';\n createdAt = (payload.timestamp as string) || '';\n }\n\n if (type === 'turn_context') {\n const payload = (obj.payload as Record<string, unknown>) || {};\n if (!model && payload.model) {\n model = payload.model as string;\n }\n }\n\n // Extract token counts from event_msg with nested token_count payload.\n if (type === 'event_msg') {\n const payload = (obj.payload as Record<string, unknown>) || {};\n if (payload.type === 'token_count') {\n const timestamp = (obj.timestamp as string) || '';\n const parseResult = TokenCountPayloadSchema.safeParse(payload);\n if (!parseResult.success) {\n console.warn(`[codexParser] Schema validation failed in ${filepath}:`, parseResult.error.message);\n continue;\n }\n const info = parseResult.data.info;\n if (!info) continue;\n const totalUsageKey = tokenUsageKey(info.total_token_usage);\n if (seenTotalUsageSnapshots.has(totalUsageKey)) continue;\n seenTotalUsageSnapshots.add(totalUsageKey);\n\n const last = info.last_token_usage;\n tokenEvents.push({\n timestamp,\n inputTokens: last.input_tokens,\n cachedInputTokens: last.cached_input_tokens,\n outputTokens: last.output_tokens,\n reasoningOutputTokens: last.reasoning_output_tokens,\n totalTokens: last.total_tokens,\n });\n }\n }\n }\n\n if (!sessionId) return null;\n\n return { id: sessionId, cwd, model, createdAt, tokenEvents };\n}\n\n/** Parse all Codex sessions. */\nexport function parseAllSessions(): ParsedSession[] {\n return scanCodexSessions()\n .map(parseCodexSession)\n .filter((s): s is ParsedSession => s !== null);\n}\n\n// ---------------------------------------------------------------------------\n// Date/timezone helpers\n// ---------------------------------------------------------------------------\n\nconst TZ_OFFSETS: Record<string, number> = {\n 'Asia/Shanghai': 8,\n 'Asia/Tokyo': 9,\n 'America/New_York': -5,\n 'America/Los_Angeles': -8,\n 'Europe/London': 0,\n 'UTC': 0,\n};\n\nfunction getTzOffsetHours(tz: string): number {\n return TZ_OFFSETS[tz] ?? 8; // Default Asia/Shanghai\n}\n\nfunction toLocalISO(ts: string, tz: string): Date {\n const d = new Date(ts);\n return new Date(d.getTime() + getTzOffsetHours(tz) * 3600_000);\n}\n\nfunction getDateKey(ts: string, tz: string): string {\n return toLocalISO(ts, tz).toISOString().slice(0, 10);\n}\n\nfunction getHourKey(ts: string, tz: string): string {\n const local = toLocalISO(ts, tz);\n return local.toISOString().slice(0, 13).replace('T', ' ') + ':00';\n}\n\nfunction getMonthKey(ts: string, tz: string): string {\n return getDateKey(ts, tz).slice(0, 7);\n}\n\nfunction extractProjectName(cwd: string): string {\n if (!cwd) return 'unknown';\n const parts = cwd.replace(/\\/+$/, '').split('/');\n return parts[parts.length - 1] || 'unknown';\n}\n\n// ---------------------------------------------------------------------------\n// Core aggregation\n// ---------------------------------------------------------------------------\n\nfunction emptyAcc(): TokenAccumulator {\n return { inputTokens: 0, cachedInputTokens: 0, outputTokens: 0, reasoningOutputTokens: 0, totalTokens: 0 };\n}\n\nfunction addAcc(a: TokenAccumulator, ev: ParsedTokenEvent): void {\n a.inputTokens += ev.inputTokens;\n a.cachedInputTokens += ev.cachedInputTokens;\n a.outputTokens += ev.outputTokens;\n a.reasoningOutputTokens += ev.reasoningOutputTokens;\n a.totalTokens += ev.totalTokens;\n}\n\nfunction mergeAcc(a: TokenAccumulator, b: TokenAccumulator): void {\n a.inputTokens += b.inputTokens;\n a.cachedInputTokens += b.cachedInputTokens;\n a.outputTokens += b.outputTokens;\n a.reasoningOutputTokens += b.reasoningOutputTokens;\n a.totalTokens += b.totalTokens;\n}\n\nfunction addAccToBucket(bucket: AggregateBucket, ev: ParsedTokenEvent, model: string): void {\n addAcc(bucket.acc, ev);\n if (!model) return;\n if (!bucket.models.has(model)) bucket.models.set(model, emptyAcc());\n addAcc(bucket.models.get(model)!, ev);\n}\n\nfunction accToEntry(date: string, acc: TokenAccumulator, modelAccs: Map<string, TokenAccumulator>): DailyEntry {\n const modelNames = [...modelAccs.keys()];\n const modelBreakdowns = buildModelBreakdowns(modelAccs);\n const totalCost = modelBreakdowns.reduce((sum, model) => sum + model.cost, 0);\n return {\n date,\n inputTokens: acc.inputTokens,\n outputTokens: acc.outputTokens,\n cacheCreationTokens: 0,\n cacheReadTokens: acc.cachedInputTokens,\n totalTokens: acc.totalTokens,\n totalCost,\n modelsUsed: modelNames,\n modelBreakdowns,\n };\n}\n\nfunction buildModelBreakdowns(modelAccs: Map<string, TokenAccumulator>): ModelBreakdown[] {\n return [...modelAccs.entries()].map(([modelName, acc]) => ({\n modelName,\n inputTokens: acc.inputTokens,\n outputTokens: acc.outputTokens,\n cacheCreationTokens: 0,\n cacheReadTokens: acc.cachedInputTokens,\n cost: calculateCost(acc, new Set([modelName])),\n }));\n}\n\ntype GroupKey = string;\n\nfunction groupSessions(\n sessions: ParsedSession[],\n options: AggregateOptions,\n): Map<GroupKey, AggregateBucket> {\n const tz = options.timezone || 'Asia/Shanghai';\n const grouped = new Map<GroupKey, AggregateBucket>();\n\n for (const session of sessions) {\n if (options.project && extractProjectName(session.cwd) !== options.project) continue;\n\n for (const ev of session.tokenEvents) {\n const evDate = new Date(ev.timestamp);\n if (options.since && evDate < options.since) continue;\n if (options.until && evDate > options.until) continue;\n\n let key: string;\n switch (options.groupBy) {\n case 'hour': key = getHourKey(ev.timestamp, tz); break;\n case 'month': key = getMonthKey(ev.timestamp, tz); break;\n case 'session': key = session.id; break;\n case 'project': key = extractProjectName(session.cwd); break;\n default: key = getDateKey(ev.timestamp, tz); break;\n }\n\n if (!grouped.has(key)) {\n grouped.set(key, { acc: emptyAcc(), models: new Map() });\n }\n addAccToBucket(grouped.get(key)!, ev, session.model);\n }\n }\n\n return grouped;\n}\n\n// ---------------------------------------------------------------------------\n// Public API \u2014 response builders for route handlers\n// ---------------------------------------------------------------------------\n\nexport function buildCodexResponsesFromSessions(\n sessions: ParsedSession[],\n options?: Partial<AggregateOptions>,\n): { daily: DailyResponse; projects: ProjectsResponse; blocks: BlocksResponse } {\n return {\n daily: buildDailyResponse(sessions, options),\n projects: buildProjectsResponse(sessions, options),\n blocks: buildBlocksResponse(sessions, options),\n };\n}\n\nfunction buildDailyResponse(sessions: ParsedSession[], options?: Partial<AggregateOptions>): DailyResponse {\n const grouped = groupSessions(sessions, { groupBy: 'day', ...options });\n\n const daily: DailyEntry[] = [];\n const totalsAcc = emptyAcc();\n\n const totalModels = new Map<string, TokenAccumulator>();\n for (const [date, { acc, models }] of grouped) {\n daily.push(accToEntry(date, acc, models));\n mergeAcc(totalsAcc, acc);\n for (const [model, modelAcc] of models) {\n if (!totalModels.has(model)) totalModels.set(model, emptyAcc());\n mergeAcc(totalModels.get(model)!, modelAcc);\n }\n }\n\n daily.sort((a, b) => a.date.localeCompare(b.date));\n\n const totalCost = buildModelBreakdowns(totalModels).reduce((sum, model) => sum + model.cost, 0);\n\n return {\n daily,\n totals: {\n inputTokens: totalsAcc.inputTokens,\n outputTokens: totalsAcc.outputTokens,\n cacheCreationTokens: 0,\n cacheReadTokens: totalsAcc.cachedInputTokens,\n totalTokens: totalsAcc.totalTokens,\n totalCost,\n },\n };\n}\n\nfunction buildProjectsResponse(sessions: ParsedSession[], options?: Partial<AggregateOptions>): ProjectsResponse {\n const tz = options?.timezone || 'Asia/Shanghai';\n const projectGroups = new Map<string, Map<string, AggregateBucket>>();\n\n for (const session of sessions) {\n const projectName = extractProjectName(session.cwd);\n if (options?.project && projectName !== options.project) continue;\n if (!projectGroups.has(projectName)) projectGroups.set(projectName, new Map());\n const dailyMap = projectGroups.get(projectName)!;\n\n for (const ev of session.tokenEvents) {\n const evDate = new Date(ev.timestamp);\n if (options?.since && evDate < options.since) continue;\n if (options?.until && evDate > options.until) continue;\n\n const dayKey = getDateKey(ev.timestamp, tz);\n if (!dailyMap.has(dayKey)) {\n dailyMap.set(dayKey, { acc: emptyAcc(), models: new Map() });\n }\n addAccToBucket(dailyMap.get(dayKey)!, ev, session.model);\n }\n }\n\n const projects: Record<string, DailyEntry[]> = {};\n for (const [projectName, dailyMap] of projectGroups) {\n projects[projectName] = [...dailyMap.entries()]\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([date, { acc, models }]) => accToEntry(date, acc, models));\n }\n\n return { projects };\n}\n\nfunction buildBlocksResponse(sessions: ParsedSession[], options?: Partial<AggregateOptions>): BlocksResponse {\n const grouped = groupSessions(sessions, { groupBy: 'hour', ...options });\n\n const blocks: BlockEntry[] = [];\n let idx = 0;\n\n for (const [hourKey, { acc, models }] of grouped) {\n const cost = buildModelBreakdowns(models).reduce((sum, model) => sum + model.cost, 0);\n const [datePart, timePart] = hourKey.split(' ');\n const hour = timePart.split(':')[0];\n\n blocks.push({\n id: `codex-hour-${idx}`,\n startTime: `${datePart}T${hour}:00:00`,\n endTime: `${datePart}T${hour}:59:59`,\n actualEndTime: null,\n isActive: false,\n isGap: false,\n entries: acc.totalTokens > 0 ? 1 : 0,\n tokenCounts: {\n inputTokens: acc.inputTokens,\n outputTokens: acc.outputTokens,\n cacheCreationInputTokens: 0,\n cacheReadInputTokens: acc.cachedInputTokens,\n },\n totalTokens: acc.totalTokens,\n costUSD: cost,\n models: [...models.keys()],\n });\n idx++;\n }\n\n blocks.sort((a, b) => a.startTime.localeCompare(b.startTime));\n\n return { blocks };\n}\n\n/** Aggregate and return DailyResponse format (for /daily?agent=codex) */\nexport function getDailyResponse(options?: Partial<AggregateOptions>): DailyResponse {\n return buildDailyResponse(parseAllSessions(), options);\n}\n\n/** Aggregate and return ProjectsResponse format (for /projects?agent=codex) */\nexport function getProjectsResponse(options?: Partial<AggregateOptions>): ProjectsResponse {\n return buildProjectsResponse(parseAllSessions(), options);\n}\n\n/** Aggregate and return BlocksResponse format (hourly, for /blocks?agent=codex) */\nexport function getBlocksResponse(options?: Partial<AggregateOptions>): BlocksResponse {\n return buildBlocksResponse(parseAllSessions(), options);\n}\n", "/**\n * Codex token pricing configuration.\n *\n * Pricing formula (confirmed by reverse-engineering @ccusage/codex):\n * cost = (inputTokens - cachedInputTokens) * input_rate\n * + cachedInputTokens * cached_rate\n * + outputTokens * output_rate\n *\n * Reasoning tokens are NOT billed separately (included in outputTokens).\n *\n * Update rates from https://openai.com/api/pricing/ when models change.\n * All prices are USD per 1M tokens.\n */\n\ninterface ModelPricing {\n inputPer1M: number;\n cachedInputPer1M: number;\n outputPer1M: number;\n}\n\nconst MODEL_PRICING: Record<string, ModelPricing> = {\n 'gpt-5.4': {\n inputPer1M: 2.50,\n cachedInputPer1M: 0.25,\n outputPer1M: 15.00,\n },\n};\n\nconst DEFAULT_PRICING: ModelPricing = {\n inputPer1M: 2.50,\n cachedInputPer1M: 0.25,\n outputPer1M: 15.00,\n};\n\ninterface TokenCounts {\n inputTokens: number;\n cachedInputTokens: number;\n outputTokens: number;\n reasoningOutputTokens: number;\n totalTokens: number;\n}\n\n/**\n * Calculate cost in USD from token counts and model pricing.\n * Matches the @ccusage/codex calculateCostUSD function exactly.\n */\nexport function calculateCost(tokens: TokenCounts, models: Set<string>): number {\n const model = [...models][0] ?? '';\n const pricing = MODEL_PRICING[model] ?? DEFAULT_PRICING;\n\n const nonCachedInput = Math.max(tokens.inputTokens - tokens.cachedInputTokens, 0);\n const cachedInput = Math.min(tokens.cachedInputTokens, tokens.inputTokens);\n const outputTokens = tokens.outputTokens;\n\n const inputCost = (nonCachedInput / 1_000_000) * pricing.inputPer1M;\n const cachedCost = (cachedInput / 1_000_000) * pricing.cachedInputPer1M;\n const outputCost = (outputTokens / 1_000_000) * pricing.outputPer1M;\n\n return inputCost + cachedCost + outputCost;\n}\n\nexport function getModelPricing(model: string): ModelPricing {\n return MODEL_PRICING[model] ?? DEFAULT_PRICING;\n}\n", "import { readFileSync, readdirSync, statSync, accessSync, constants } from 'node:fs';\nimport { join } from 'node:path';\nimport { homedir } from 'node:os';\nimport type { DailyEntry, DailyResponse, ProjectsResponse, BlockEntry, BlocksResponse } from '../shared/types.js';\n\n// ---------------------------------------------------------------------------\n// OpenClaw JSONL format\n//\n// Each line in a session .jsonl file is one of:\n// { type: \"model_change\", provider: \"anthropic\", modelId: \"claude-opus-4-6\" }\n// { type: \"custom\", customType: \"model-snapshot\", data: { provider, modelId } }\n// { type: \"message\", message: { role, usage: { input, output, cacheRead, cacheWrite, cost: { total } }, timestamp (ms), model, provider } }\n//\n// sessions.json index:\n// { \"<key>\": { sessionId: \"...\", sessionFile?: \"...\" }, ... }\n// ---------------------------------------------------------------------------\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ninterface OpenClawTokenEvent {\n timestampMs: number;\n inputTokens: number;\n outputTokens: number;\n cacheReadTokens: number;\n cacheWriteTokens: number;\n totalTokens: number;\n cost: number;\n model: string;\n}\n\ninterface OpenClawSession {\n id: string;\n agentId: string;\n tokenEvents: OpenClawTokenEvent[];\n}\n\ninterface TokenAccumulator {\n inputTokens: number;\n outputTokens: number;\n cacheReadTokens: number;\n cacheWriteTokens: number;\n totalTokens: number;\n cost: number;\n}\n\n// ---------------------------------------------------------------------------\n// Directory helpers\n// ---------------------------------------------------------------------------\n\n/** All directories OpenClaw may have used (current + legacy names). */\nfunction getOpenClawDirs(): string[] {\n const home = homedir();\n return [\n join(home, '.openclaw'),\n join(home, '.clawdbot'), // legacy name 1\n join(home, '.moltbot'), // legacy name 2\n join(home, '.moldbot'), // legacy name 3\n ];\n}\n\nexport function isOpenClawAccessible(): boolean {\n for (const dir of getOpenClawDirs()) {\n try {\n accessSync(join(dir, 'agents'), constants.R_OK);\n return true;\n } catch {\n // try next\n }\n }\n return false;\n}\n\n// ---------------------------------------------------------------------------\n// Session scanning\n// ---------------------------------------------------------------------------\n\ninterface SessionRef {\n sessionId: string;\n sessionFile: string; // absolute path to .jsonl\n agentId: string;\n}\n\n/** Scan all OpenClaw agent dirs and collect session file references. */\nexport function scanOpenClawSessions(): SessionRef[] {\n const refs: SessionRef[] = [];\n\n for (const baseDir of getOpenClawDirs()) {\n const agentsDir = join(baseDir, 'agents');\n let agentEntries: string[];\n try {\n agentEntries = readdirSync(agentsDir);\n } catch {\n continue;\n }\n\n for (const agentEntry of agentEntries) {\n const sessionsDir = join(agentsDir, agentEntry, 'sessions');\n const indexedPaths = new Set<string>();\n\n // Try sessions.json index first\n const indexPath = join(sessionsDir, 'sessions.json');\n try {\n const raw = readFileSync(indexPath, 'utf-8');\n const index = JSON.parse(raw) as Record<string, { sessionId?: string; sessionFile?: string }>;\n for (const entry of Object.values(index)) {\n if (!entry.sessionId) continue;\n let sessionPath: string;\n if (entry.sessionFile) {\n const filePath = entry.sessionFile;\n if (filePath.startsWith('/')) {\n // Validate absolute path stays within an OpenClaw directory\n if (!getOpenClawDirs().some(dir => filePath.startsWith(dir))) continue;\n sessionPath = filePath;\n } else {\n sessionPath = join(sessionsDir, filePath);\n }\n } else {\n sessionPath = join(sessionsDir, `${entry.sessionId}.jsonl`);\n }\n indexedPaths.add(sessionPath);\n refs.push({ sessionId: entry.sessionId, sessionFile: sessionPath, agentId: agentEntry });\n }\n } catch {\n // No sessions.json \u2014 will scan .jsonl files below\n }\n\n // Scan for .jsonl files not already covered by the index\n let files: string[];\n try {\n files = readdirSync(sessionsDir);\n } catch {\n continue;\n }\n for (const f of files) {\n if (!f.endsWith('.jsonl')) continue;\n const fullPath = join(sessionsDir, f);\n if (indexedPaths.has(fullPath)) continue;\n const sessionId = f.replace(/\\.jsonl.*$/, '');\n refs.push({ sessionId, sessionFile: fullPath, agentId: agentEntry });\n }\n }\n }\n\n return refs;\n}\n\n// ---------------------------------------------------------------------------\n// Session-level cache (mtime-based invalidation)\n// ---------------------------------------------------------------------------\n\nconst sessionCache = new Map<string, { mtime: number; result: OpenClawSession | null }>();\n\n// ---------------------------------------------------------------------------\n// JSONL parser\n// ---------------------------------------------------------------------------\n\nexport function parseOpenClawSession(ref: SessionRef): OpenClawSession | null {\n let fileMtimeMs = 0;\n try {\n fileMtimeMs = statSync(ref.sessionFile).mtimeMs;\n } catch { /* ok */ }\n\n // Return cached result if file hasn't changed\n const cached = sessionCache.get(ref.sessionFile);\n if (cached && cached.mtime === fileMtimeMs) {\n return cached.result;\n }\n\n let content: string;\n try {\n content = readFileSync(ref.sessionFile, 'utf-8');\n } catch {\n return null;\n }\n\n const tokenEvents: OpenClawTokenEvent[] = [];\n let currentModel = '';\n let currentProvider = '';\n\n for (const line of content.split('\\n')) {\n const trimmed = line.trim();\n if (!trimmed) continue;\n\n let obj: Record<string, unknown>;\n try {\n obj = JSON.parse(trimmed) as Record<string, unknown>;\n } catch {\n continue;\n }\n\n const type = obj.type as string;\n\n if (type === 'model_change') {\n if (obj.modelId) currentModel = obj.modelId as string;\n if (obj.provider) currentProvider = obj.provider as string;\n continue;\n }\n\n if (type === 'custom' && (obj.customType as string) === 'model-snapshot') {\n const data = (obj.data as Record<string, unknown>) || {};\n if (data.modelId) currentModel = data.modelId as string;\n if (data.provider) currentProvider = data.provider as string;\n continue;\n }\n\n if (type === 'message') {\n const msg = (obj.message as Record<string, unknown>) || {};\n if ((msg.role as string) !== 'assistant') continue;\n\n const usage = (msg.usage as Record<string, unknown>) || {};\n if (!usage) continue;\n\n // Model: prefer embedded, fall back to tracked state\n const model = ((msg.model as string) || currentModel || '').trim();\n const provider = ((msg.provider as string) || currentProvider || '').trim();\n if (!model) continue; // can't attribute cost without a model\n\n // Update tracked state\n if (model) currentModel = model;\n if (provider) currentProvider = provider;\n\n const input = Number(usage.input ?? 0);\n const output = Number(usage.output ?? 0);\n const cacheRead = Number(usage.cacheRead ?? 0);\n const cacheWrite = Number(usage.cacheWrite ?? 0);\n const costObj = (usage.cost as Record<string, unknown>) || {};\n const cost = Number(costObj.total ?? 0);\n const timestampMs = Number(msg.timestamp ?? fileMtimeMs);\n\n tokenEvents.push({\n timestampMs,\n inputTokens: Math.max(0, input),\n outputTokens: Math.max(0, output),\n cacheReadTokens: Math.max(0, cacheRead),\n cacheWriteTokens: Math.max(0, cacheWrite),\n totalTokens: Math.max(0, input + output + cacheRead),\n cost: Math.max(0, cost),\n model: `${provider}/${model}`,\n });\n }\n }\n\n if (tokenEvents.length === 0) {\n sessionCache.set(ref.sessionFile, { mtime: fileMtimeMs, result: null });\n return null;\n }\n\n const result: OpenClawSession = { id: ref.sessionId, agentId: ref.agentId, tokenEvents };\n sessionCache.set(ref.sessionFile, { mtime: fileMtimeMs, result });\n return result;\n}\n\nexport function parseAllOpenClawSessions(): OpenClawSession[] {\n return scanOpenClawSessions()\n .map(parseOpenClawSession)\n .filter((s): s is OpenClawSession => s !== null);\n}\n\n// ---------------------------------------------------------------------------\n// Date / timezone helpers (same logic as codexParser)\n// ---------------------------------------------------------------------------\n\nconst TZ_OFFSETS: Record<string, number> = {\n 'Asia/Shanghai': 8,\n 'Asia/Tokyo': 9,\n 'America/New_York': -5,\n 'America/Los_Angeles': -8,\n 'Europe/London': 0,\n 'UTC': 0,\n};\n\nfunction getTzOffsetHours(tz: string): number {\n return TZ_OFFSETS[tz] ?? 8;\n}\n\nfunction msToLocalDate(ms: number, tz: string): Date {\n return new Date(ms + getTzOffsetHours(tz) * 3_600_000);\n}\n\nfunction getDateKey(ms: number, tz: string): string {\n return msToLocalDate(ms, tz).toISOString().slice(0, 10);\n}\n\nfunction getHourKey(ms: number, tz: string): string {\n const d = msToLocalDate(ms, tz);\n return d.toISOString().slice(0, 13).replace('T', ' ') + ':00';\n}\n\nfunction getMonthKey(ms: number, tz: string): string {\n return getDateKey(ms, tz).slice(0, 7);\n}\n\n// ---------------------------------------------------------------------------\n// Aggregation helpers\n// ---------------------------------------------------------------------------\n\nfunction emptyAcc(): TokenAccumulator {\n return { inputTokens: 0, outputTokens: 0, cacheReadTokens: 0, cacheWriteTokens: 0, totalTokens: 0, cost: 0 };\n}\n\nfunction addEvent(acc: TokenAccumulator, ev: OpenClawTokenEvent): void {\n acc.inputTokens += ev.inputTokens;\n acc.outputTokens += ev.outputTokens;\n acc.cacheReadTokens += ev.cacheReadTokens;\n acc.cacheWriteTokens += ev.cacheWriteTokens;\n acc.totalTokens += ev.totalTokens;\n acc.cost += ev.cost;\n}\n\nfunction mergeAcc(a: TokenAccumulator, b: TokenAccumulator): void {\n a.inputTokens += b.inputTokens;\n a.outputTokens += b.outputTokens;\n a.cacheReadTokens += b.cacheReadTokens;\n a.cacheWriteTokens += b.cacheWriteTokens;\n a.totalTokens += b.totalTokens;\n a.cost += b.cost;\n}\n\nfunction accToEntry(date: string, acc: TokenAccumulator, models: Set<string>): DailyEntry {\n const modelList = [...models];\n const costPerModel = modelList.length > 0 ? acc.cost / modelList.length : 0;\n return {\n date,\n inputTokens: acc.inputTokens,\n outputTokens: acc.outputTokens,\n cacheCreationTokens: acc.cacheWriteTokens,\n cacheReadTokens: acc.cacheReadTokens,\n totalTokens: acc.totalTokens,\n totalCost: acc.cost,\n modelsUsed: modelList,\n modelBreakdowns: modelList.map(name => ({\n modelName: name,\n inputTokens: acc.inputTokens,\n outputTokens: acc.outputTokens,\n cacheCreationTokens: acc.cacheWriteTokens,\n cacheReadTokens: acc.cacheReadTokens,\n cost: costPerModel,\n })),\n };\n}\n\n// ---------------------------------------------------------------------------\n// Public API \u2014 mirrors codexParser's response builders\n// ---------------------------------------------------------------------------\n\nexport interface OpenClawAggregateOptions {\n groupBy?: 'day' | 'hour' | 'month' | 'session';\n since?: Date | null;\n until?: Date | null;\n timezone?: string;\n project?: string | null; // maps to agentId\n}\n\nexport function getDailyResponse(options?: OpenClawAggregateOptions): DailyResponse {\n const sessions = parseAllOpenClawSessions();\n const tz = options?.timezone || 'Asia/Shanghai';\n\n const grouped = new Map<string, { acc: TokenAccumulator; models: Set<string> }>();\n const totalsAcc = emptyAcc();\n\n for (const session of sessions) {\n if (options?.project && session.agentId !== options.project) continue;\n\n for (const ev of session.tokenEvents) {\n if (options?.since && ev.timestampMs < options.since.getTime()) continue;\n if (options?.until && ev.timestampMs > options.until.getTime()) continue;\n\n const key = getDateKey(ev.timestampMs, tz);\n if (!grouped.has(key)) grouped.set(key, { acc: emptyAcc(), models: new Set() });\n const entry = grouped.get(key)!;\n addEvent(entry.acc, ev);\n entry.models.add(ev.model);\n }\n }\n\n const daily: DailyEntry[] = [];\n for (const [date, { acc, models }] of grouped) {\n daily.push(accToEntry(date, acc, models));\n mergeAcc(totalsAcc, acc);\n }\n daily.sort((a, b) => a.date.localeCompare(b.date));\n\n return {\n daily,\n totals: {\n inputTokens: totalsAcc.inputTokens,\n outputTokens: totalsAcc.outputTokens,\n cacheCreationTokens: totalsAcc.cacheWriteTokens,\n cacheReadTokens: totalsAcc.cacheReadTokens,\n totalTokens: totalsAcc.totalTokens,\n totalCost: totalsAcc.cost,\n },\n };\n}\n\nexport function getProjectsResponse(options?: OpenClawAggregateOptions): ProjectsResponse {\n const sessions = parseAllOpenClawSessions();\n const tz = options?.timezone || 'Asia/Shanghai';\n const projects: Record<string, DailyEntry[]> = {};\n\n for (const session of sessions) {\n const projectName = session.agentId;\n const dailyMap = new Map<string, { acc: TokenAccumulator; models: Set<string> }>();\n\n for (const ev of session.tokenEvents) {\n if (options?.since && ev.timestampMs < options.since.getTime()) continue;\n if (options?.until && ev.timestampMs > options.until.getTime()) continue;\n\n const dayKey = getDateKey(ev.timestampMs, tz);\n if (!dailyMap.has(dayKey)) dailyMap.set(dayKey, { acc: emptyAcc(), models: new Set() });\n addEvent(dailyMap.get(dayKey)!.acc, ev);\n dailyMap.get(dayKey)!.models.add(ev.model);\n }\n\n if (!projects[projectName]) projects[projectName] = [];\n for (const [date, { acc, models }] of dailyMap) {\n projects[projectName].push(accToEntry(date, acc, models));\n }\n }\n\n for (const key of Object.keys(projects)) {\n projects[key].sort((a, b) => a.date.localeCompare(b.date));\n }\n\n return { projects };\n}\n\nexport function getBlocksResponse(options?: OpenClawAggregateOptions): BlocksResponse {\n const sessions = parseAllOpenClawSessions();\n const tz = options?.timezone || 'Asia/Shanghai';\n\n const grouped = new Map<string, { acc: TokenAccumulator; models: Set<string> }>();\n\n for (const session of sessions) {\n if (options?.project && session.agentId !== options.project) continue;\n\n for (const ev of session.tokenEvents) {\n if (options?.since && ev.timestampMs < options.since.getTime()) continue;\n if (options?.until && ev.timestampMs > options.until.getTime()) continue;\n\n const key = getHourKey(ev.timestampMs, tz);\n if (!grouped.has(key)) grouped.set(key, { acc: emptyAcc(), models: new Set() });\n addEvent(grouped.get(key)!.acc, ev);\n grouped.get(key)!.models.add(ev.model);\n }\n }\n\n const blocks: BlockEntry[] = [];\n let idx = 0;\n\n for (const [hourKey, { acc, models }] of grouped) {\n const [datePart, timePart] = hourKey.split(' ');\n const hour = timePart.split(':')[0];\n blocks.push({\n id: `openclaw-hour-${idx}`,\n startTime: `${datePart}T${hour}:00:00`,\n endTime: `${datePart}T${hour}:59:59`,\n actualEndTime: null,\n isActive: false,\n isGap: false,\n entries: acc.totalTokens > 0 ? 1 : 0,\n tokenCounts: {\n inputTokens: acc.inputTokens,\n outputTokens: acc.outputTokens,\n cacheCreationInputTokens: acc.cacheWriteTokens,\n cacheReadInputTokens: acc.cacheReadTokens,\n },\n totalTokens: acc.totalTokens,\n costUSD: acc.cost,\n models: [...models],\n });\n idx++;\n }\n\n blocks.sort((a, b) => a.startTime.localeCompare(b.startTime));\n return { blocks };\n}\n", "import { existsSync } from 'node:fs';\nimport { execSync } from 'node:child_process';\nimport { join } from 'node:path';\nimport { homedir } from 'node:os';\nimport type { DailyEntry, DailyResponse, ProjectsResponse, BlockEntry, BlocksResponse } from '../shared/types.js';\n\n// ---------------------------------------------------------------------------\n// OpenCode SQLite format\n//\n// Database: ~/.local/share/opencode/opencode.db\n// Table: message\n// Column: data (JSON) with structure:\n// {\n// \"role\": \"assistant\",\n// \"time\": { \"created\": <ms>, \"completed\": <ms> },\n// \"modelID\": \"glm-4.7\",\n// \"providerID\": \"zhipuai-coding-plan\",\n// \"tokens\": { \"input\": N, \"output\": N, \"reasoning\": N, \"cache\": { \"read\": N, \"write\": N } },\n// \"cost\": N,\n// \"path\": { \"cwd\": \"/path/to/project\" }\n// }\n// ---------------------------------------------------------------------------\n\nconst OPENCODE_DB = join(homedir(), '.local', 'share', 'opencode', 'opencode.db');\n\n// ---------------------------------------------------------------------------\n// Detection\n// ---------------------------------------------------------------------------\n\nexport function isOpencodeAccessible(): boolean {\n return existsSync(OPENCODE_DB);\n}\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ninterface OpenCodeTokenEvent {\n timestampMs: number;\n inputTokens: number;\n outputTokens: number;\n cacheReadTokens: number;\n cacheWriteTokens: number;\n totalTokens: number;\n cost: number;\n model: string;\n project: string;\n}\n\ninterface TokenAccumulator {\n inputTokens: number;\n outputTokens: number;\n cacheReadTokens: number;\n cacheWriteTokens: number;\n totalTokens: number;\n cost: number;\n}\n\n// ---------------------------------------------------------------------------\n// SQLite query helper\n// ---------------------------------------------------------------------------\n\nfunction queryOpenCodeDB(sql: string): string {\n return execSync(`sqlite3 -json \"${OPENCODE_DB}\" \"${sql}\"`, {\n encoding: 'utf-8',\n maxBuffer: 50 * 1024 * 1024,\n timeout: 10000,\n });\n}\n\n// ---------------------------------------------------------------------------\n// Parse all token events from message table\n// ---------------------------------------------------------------------------\n\ninterface RawMessage {\n data: string;\n}\n\nexport function parseAllOpenCodeEvents(project?: string | null): OpenCodeTokenEvent[] {\n let sql = `SELECT data FROM message WHERE json_extract(data, '$.role') = 'assistant'`;\n if (project) {\n sql += ` AND json_extract(data, '$.path.cwd') = '${project.replace(/'/g, \"''\")}'`;\n }\n\n let raw: string;\n try {\n raw = queryOpenCodeDB(sql);\n } catch {\n return [];\n }\n\n let rows: RawMessage[];\n try {\n rows = JSON.parse(raw) as RawMessage[];\n } catch {\n return [];\n }\n\n const events: OpenCodeTokenEvent[] = [];\n\n for (const row of rows) {\n let data: Record<string, unknown>;\n try {\n data = JSON.parse(row.data) as Record<string, unknown>;\n } catch {\n continue;\n }\n\n const tokens = (data.tokens as Record<string, unknown>) || {};\n const cache = (tokens.cache as Record<string, unknown>) || {};\n const time = (data.time as Record<string, unknown>) || {};\n const path = (data.path as Record<string, unknown>) || {};\n\n const input = Number(tokens.input ?? 0);\n const output = Number(tokens.output ?? 0);\n const cacheRead = Number(cache.read ?? 0);\n const cacheWrite = Number(cache.write ?? 0);\n\n if (input === 0 && output === 0 && cacheRead === 0 && cacheWrite === 0) continue;\n\n events.push({\n timestampMs: Number(time.created ?? 0),\n inputTokens: Math.max(0, input),\n outputTokens: Math.max(0, output),\n cacheReadTokens: Math.max(0, cacheRead),\n cacheWriteTokens: Math.max(0, cacheWrite),\n totalTokens: Math.max(0, input + output + cacheRead),\n cost: Math.max(0, Number(data.cost ?? 0)),\n model: String(data.modelID ?? 'unknown'),\n project: String(path.cwd ?? ''),\n });\n }\n\n return events;\n}\n\n// ---------------------------------------------------------------------------\n// Date / timezone helpers (same logic as openclawParser)\n// ---------------------------------------------------------------------------\n\nconst TZ_OFFSETS: Record<string, number> = {\n 'Asia/Shanghai': 8,\n 'Asia/Tokyo': 9,\n 'America/New_York': -5,\n 'America/Los_Angeles': -8,\n 'Europe/London': 0,\n 'UTC': 0,\n};\n\nfunction getTzOffsetHours(tz: string): number {\n return TZ_OFFSETS[tz] ?? 8;\n}\n\nfunction msToLocalDate(ms: number, tz: string): Date {\n return new Date(ms + getTzOffsetHours(tz) * 3_600_000);\n}\n\nfunction getDateKey(ms: number, tz: string): string {\n return msToLocalDate(ms, tz).toISOString().slice(0, 10);\n}\n\nfunction getHourKey(ms: number, tz: string): string {\n const d = msToLocalDate(ms, tz);\n return d.toISOString().slice(0, 13).replace('T', ' ') + ':00';\n}\n\n// ---------------------------------------------------------------------------\n// Aggregation helpers\n// ---------------------------------------------------------------------------\n\nfunction emptyAcc(): TokenAccumulator {\n return { inputTokens: 0, outputTokens: 0, cacheReadTokens: 0, cacheWriteTokens: 0, totalTokens: 0, cost: 0 };\n}\n\nfunction addEvent(acc: TokenAccumulator, ev: OpenCodeTokenEvent): void {\n acc.inputTokens += ev.inputTokens;\n acc.outputTokens += ev.outputTokens;\n acc.cacheReadTokens += ev.cacheReadTokens;\n acc.cacheWriteTokens += ev.cacheWriteTokens;\n acc.totalTokens += ev.totalTokens;\n acc.cost += ev.cost;\n}\n\n// ---------------------------------------------------------------------------\n// Public API \u2014 mirrors openclawParser's response builders\n// ---------------------------------------------------------------------------\n\nexport interface OpenCodeAggregateOptions {\n project?: string | null;\n timezone?: string;\n}\n\nexport function getDailyResponse(options?: OpenCodeAggregateOptions): DailyResponse {\n const events = parseAllOpenCodeEvents(options?.project);\n const tz = options?.timezone || 'Asia/Shanghai';\n\n // Track per-day, per-model accumulators for correct breakdowns\n interface ModelAcc { inputTokens: number; outputTokens: number; cacheCreationTokens: number; cacheReadTokens: number; cost: number; }\n interface DayGroup { totals: TokenAccumulator; models: Map<string, ModelAcc>; }\n const grouped = new Map<string, DayGroup>();\n\n for (const ev of events) {\n const key = getDateKey(ev.timestampMs, tz);\n if (!grouped.has(key)) grouped.set(key, { totals: emptyAcc(), models: new Map() });\n const g = grouped.get(key)!;\n addEvent(g.totals, ev);\n\n if (!g.models.has(ev.model)) {\n g.models.set(ev.model, { inputTokens: 0, outputTokens: 0, cacheCreationTokens: 0, cacheReadTokens: 0, cost: 0 });\n }\n const m = g.models.get(ev.model)!;\n m.inputTokens += ev.inputTokens;\n m.outputTokens += ev.outputTokens;\n m.cacheCreationTokens += ev.cacheWriteTokens;\n m.cacheReadTokens += ev.cacheReadTokens;\n m.cost += ev.cost;\n }\n\n const totalsAcc = emptyAcc();\n const daily: DailyEntry[] = [];\n for (const [date, g] of grouped) {\n mergeAcc(totalsAcc, g.totals);\n const modelList = [...g.models.keys()];\n daily.push({\n date,\n inputTokens: g.totals.inputTokens,\n outputTokens: g.totals.outputTokens,\n cacheCreationTokens: g.totals.cacheWriteTokens,\n cacheReadTokens: g.totals.cacheReadTokens,\n totalTokens: g.totals.totalTokens,\n totalCost: g.totals.cost,\n modelsUsed: modelList,\n modelBreakdowns: modelList.map(name => {\n const m = g.models.get(name)!;\n return {\n modelName: name,\n inputTokens: m.inputTokens,\n outputTokens: m.outputTokens,\n cacheCreationTokens: m.cacheCreationTokens,\n cacheReadTokens: m.cacheReadTokens,\n cost: m.cost,\n };\n }),\n });\n }\n daily.sort((a, b) => a.date.localeCompare(b.date));\n\n return {\n daily,\n totals: {\n inputTokens: totalsAcc.inputTokens,\n outputTokens: totalsAcc.outputTokens,\n cacheCreationTokens: totalsAcc.cacheWriteTokens,\n cacheReadTokens: totalsAcc.cacheReadTokens,\n totalTokens: totalsAcc.totalTokens,\n totalCost: totalsAcc.cost,\n },\n };\n}\n\nfunction mergeAcc(a: TokenAccumulator, b: TokenAccumulator): void {\n a.inputTokens += b.inputTokens;\n a.outputTokens += b.outputTokens;\n a.cacheReadTokens += b.cacheReadTokens;\n a.cacheWriteTokens += b.cacheWriteTokens;\n a.totalTokens += b.totalTokens;\n a.cost += b.cost;\n}\n\nexport function getProjectsResponse(options?: OpenCodeAggregateOptions): ProjectsResponse {\n const events = parseAllOpenCodeEvents();\n const tz = options?.timezone || 'Asia/Shanghai';\n const projects: Record<string, DailyEntry[]> = {};\n\n for (const ev of events) {\n const projectName = ev.project || 'unknown';\n const dayKey = getDateKey(ev.timestampMs, tz);\n\n if (!projects[projectName]) projects[projectName] = [];\n\n // Find or create entry for this date in this project\n let dayEntry = projects[projectName].find(d => d.date === dayKey);\n if (!dayEntry) {\n dayEntry = {\n date: dayKey,\n inputTokens: 0,\n outputTokens: 0,\n cacheCreationTokens: 0,\n cacheReadTokens: 0,\n totalTokens: 0,\n totalCost: 0,\n modelsUsed: [],\n modelBreakdowns: [],\n };\n projects[projectName].push(dayEntry);\n }\n\n dayEntry.inputTokens += ev.inputTokens;\n dayEntry.outputTokens += ev.outputTokens;\n dayEntry.cacheCreationTokens += ev.cacheWriteTokens;\n dayEntry.cacheReadTokens += ev.cacheReadTokens;\n dayEntry.totalTokens += ev.totalTokens;\n dayEntry.totalCost += ev.cost;\n\n if (!dayEntry.modelsUsed.includes(ev.model)) {\n dayEntry.modelsUsed.push(ev.model);\n }\n\n // Update or add model breakdown\n let breakdown = dayEntry.modelBreakdowns.find(b => b.modelName === ev.model);\n if (!breakdown) {\n breakdown = {\n modelName: ev.model,\n inputTokens: 0,\n outputTokens: 0,\n cacheCreationTokens: 0,\n cacheReadTokens: 0,\n cost: 0,\n };\n dayEntry.modelBreakdowns.push(breakdown);\n }\n breakdown.inputTokens += ev.inputTokens;\n breakdown.outputTokens += ev.outputTokens;\n breakdown.cacheCreationTokens += ev.cacheWriteTokens;\n breakdown.cacheReadTokens += ev.cacheReadTokens;\n breakdown.cost += ev.cost;\n }\n\n for (const key of Object.keys(projects)) {\n projects[key].sort((a, b) => a.date.localeCompare(b.date));\n }\n\n return { projects };\n}\n\nexport function getBlocksResponse(options?: OpenCodeAggregateOptions): BlocksResponse {\n const events = parseAllOpenCodeEvents(options?.project);\n const tz = options?.timezone || 'Asia/Shanghai';\n\n const grouped = new Map<string, { acc: TokenAccumulator; models: Set<string> }>();\n\n for (const ev of events) {\n const key = getHourKey(ev.timestampMs, tz);\n if (!grouped.has(key)) grouped.set(key, { acc: emptyAcc(), models: new Set() });\n addEvent(grouped.get(key)!.acc, ev);\n grouped.get(key)!.models.add(ev.model);\n }\n\n const blocks: BlockEntry[] = [];\n let idx = 0;\n\n for (const [hourKey, { acc, models }] of grouped) {\n const [datePart, timePart] = hourKey.split(' ');\n const hour = timePart.split(':')[0];\n blocks.push({\n id: `opencode-hour-${idx}`,\n startTime: `${datePart}T${hour}:00:00`,\n endTime: `${datePart}T${hour}:59:59`,\n actualEndTime: null,\n isActive: false,\n isGap: false,\n entries: acc.totalTokens > 0 ? 1 : 0,\n tokenCounts: {\n inputTokens: acc.inputTokens,\n outputTokens: acc.outputTokens,\n cacheCreationInputTokens: acc.cacheWriteTokens,\n cacheReadInputTokens: acc.cacheReadTokens,\n },\n totalTokens: acc.totalTokens,\n costUSD: acc.cost,\n models: [...models],\n });\n idx++;\n }\n\n blocks.sort((a, b) => a.startTime.localeCompare(b.startTime));\n return { blocks };\n}\n", "import { readFileSync, readdirSync, statSync, existsSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { homedir } from 'node:os';\nimport type { DailyEntry, DailyResponse, ProjectsResponse, Totals, BlockEntry } from '../shared/types.js';\n\n// ---------------------------------------------------------------------------\n// Model pricing (USD per 1M tokens)\n// Update from https://docs.anthropic.com/en/docs/about-claude/models when needed\n// ---------------------------------------------------------------------------\n\ninterface ModelPricing {\n inputPer1M: number;\n cacheReadPer1M: number;\n outputPer1M: number;\n}\n\nconst MODEL_PRICING: Record<string, ModelPricing> = {\n // Claude 4.6\n 'claude-opus-4-6': { inputPer1M: 15, cacheReadPer1M: 1.50, outputPer1M: 75 },\n 'claude-sonnet-4-6': { inputPer1M: 3, cacheReadPer1M: 0.30, outputPer1M: 15 },\n // Claude 4.5\n 'claude-sonnet-4-5-20250514': { inputPer1M: 3, cacheReadPer1M: 0.30, outputPer1M: 15 },\n 'claude-haiku-4-5-20251001': { inputPer1M: 0.80, cacheReadPer1M: 0.08, outputPer1M: 4 },\n // Older Claude models\n 'claude-3-5-sonnet-20241022': { inputPer1M: 3, cacheReadPer1M: 0.30, outputPer1M: 15 },\n 'claude-3-5-haiku-20241022': { inputPer1M: 0.80, cacheReadPer1M: 0.08, outputPer1M: 4 },\n 'claude-3-opus-20240229': { inputPer1M: 15, cacheReadPer1M: 1.50, outputPer1M: 75 },\n 'claude-3-haiku-20240307': { inputPer1M: 0.25, cacheReadPer1M: 0.03, outputPer1M: 1.25 },\n};\n\nconst DEFAULT_PRICING: ModelPricing = { inputPer1M: 3, cacheReadPer1M: 0.30, outputPer1M: 15 };\n\nfunction getPricing(model: string): ModelPricing {\n // Try exact match first, then prefix match\n if (MODEL_PRICING[model]) return MODEL_PRICING[model];\n const lower = model.toLowerCase();\n for (const key of Object.keys(MODEL_PRICING)) {\n if (lower.startsWith(key) || lower.includes(key)) return MODEL_PRICING[key];\n }\n return DEFAULT_PRICING;\n}\n\nexport function calculateCost(inputTokens: number, cacheReadTokens: number, outputTokens: number, model: string): number {\n const p = getPricing(model);\n const nonCachedInput = Math.max(inputTokens - cacheReadTokens, 0);\n return (nonCachedInput / 1_000_000) * p.inputPer1M\n + (cacheReadTokens / 1_000_000) * p.cacheReadPer1M\n + (outputTokens / 1_000_000) * p.outputPer1M;\n}\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ninterface ParsedUsage {\n timestamp: string;\n model: string;\n inputTokens: number;\n outputTokens: number;\n cacheCreationTokens: number;\n cacheReadTokens: number;\n projectDir: string;\n}\n\n// ---------------------------------------------------------------------------\n// JSONL parsing with mtime cache\n// ---------------------------------------------------------------------------\n\nconst CLAUDE_PROJECTS_DIR = join(homedir(), '.claude', 'projects');\n\nconst fileCache = new Map<string, { mtime: number; entries: ParsedUsage[] }>();\n\nconst projectNameCache = new Map<string, string>();\n\n/** Decode Claude's encoded project directory name.\n * Claude encodes paths: /Users/foo/bar \u2192 -Users-foo-bar\n * Since '-' replaces '/' and project names can contain '-',\n * we use filesystem checks to find the correct last segment.\n */\nexport function extractProjectName(dirName: string): string {\n if (!dirName.startsWith('-')) return dirName;\n\n const cached = projectNameCache.get(dirName);\n if (cached) return cached;\n\n const segments = dirName.replace(/^-/, '').split('-').filter(Boolean);\n if (segments.length === 0) { projectNameCache.set(dirName, dirName); return dirName; }\n if (segments.length === 1) { projectNameCache.set(dirName, segments[0]); return segments[0]; }\n\n let bestName = segments[segments.length - 1];\n\n // Try from right: find the longest last segment that forms a valid path\n for (let splitAt = segments.length - 1; splitAt >= 1; splitAt--) {\n const parentSegments = segments.slice(0, splitAt);\n const candidateName = segments.slice(splitAt).join('-');\n\n // Build parent path, handling hidden directories (dot prefix)\n let parentPath = '/';\n let valid = true;\n for (const seg of parentSegments) {\n const regular = join(parentPath, seg);\n const hidden = join(parentPath, '.' + seg);\n if (existsSync(regular)) {\n parentPath = regular;\n } else if (existsSync(hidden)) {\n parentPath = hidden;\n } else {\n valid = false;\n break;\n }\n }\n\n if (!valid) continue;\n\n if (existsSync(join(parentPath, candidateName)) || existsSync(join(parentPath, '.' + candidateName))) {\n bestName = candidateName;\n break;\n }\n }\n\n projectNameCache.set(dirName, bestName);\n return bestName;\n}\n\nfunction matchesProject(dirName: string, filter: string): boolean {\n return extractProjectName(dirName) === extractProjectName(filter);\n}\n\nfunction findJsonlFiles(dir: string): string[] {\n const results: string[] = [];\n try {\n const entries = readdirSync(dir, { withFileTypes: true });\n for (const entry of entries) {\n if (entry.isDirectory()) {\n results.push(...findJsonlFiles(join(dir, entry.name)));\n } else if (entry.name.endsWith('.jsonl')) {\n results.push(join(dir, entry.name));\n }\n }\n } catch { /* skip unreadable dirs */ }\n return results;\n}\n\nfunction parseAllSessions(project?: string | null): ParsedUsage[] {\n if (!existsSync(CLAUDE_PROJECTS_DIR)) return [];\n\n const results: ParsedUsage[] = [];\n const projectDirs = readdirSync(CLAUDE_PROJECTS_DIR, { withFileTypes: true })\n .filter(d => d.isDirectory())\n .map(d => d.name);\n\n for (const dirName of projectDirs) {\n if (project && !matchesProject(dirName, project)) continue;\n\n const dirPath = join(CLAUDE_PROJECTS_DIR, dirName);\n const files = findJsonlFiles(dirPath);\n\n for (const filePath of files) {\n\n let mtime = 0;\n try { mtime = statSync(filePath).mtimeMs; } catch { /* ok */ }\n\n const cached = fileCache.get(filePath);\n if (cached && cached.mtime === mtime) {\n results.push(...cached.entries);\n continue;\n }\n\n const entries: ParsedUsage[] = [];\n let content: string;\n try {\n content = readFileSync(filePath, 'utf-8');\n } catch {\n continue;\n }\n\n for (const line of content.split('\\n')) {\n const trimmed = line.trim();\n if (!trimmed) continue;\n\n let obj: Record<string, unknown>;\n try { obj = JSON.parse(trimmed) as Record<string, unknown>; } catch { continue; }\n\n if (obj.type !== 'assistant' || !obj.message) continue;\n const msg = obj.message as Record<string, unknown>;\n const usage = (msg.usage as Record<string, number>) || {};\n\n const inputTokens = usage.input_tokens || 0;\n const outputTokens = usage.output_tokens || 0;\n const cacheCreationTokens = usage.cache_creation_input_tokens || 0;\n const cacheReadTokens = usage.cache_read_input_tokens || 0;\n const totalTokens = inputTokens + outputTokens + cacheReadTokens;\n\n if (totalTokens === 0) continue;\n\n entries.push({\n timestamp: obj.timestamp as string,\n model: (msg.model as string) || 'unknown',\n inputTokens,\n outputTokens,\n cacheCreationTokens,\n cacheReadTokens,\n projectDir: dirName,\n });\n }\n\n fileCache.set(filePath, { mtime, entries });\n results.push(...entries);\n }\n }\n\n return results;\n}\n\n// ---------------------------------------------------------------------------\n// Timezone helpers\n// ---------------------------------------------------------------------------\n\nconst TZ_OFFSETS: Record<string, number> = {\n 'Asia/Shanghai': 8,\n 'Asia/Tokyo': 9,\n 'America/New_York': -5,\n 'America/Los_Angeles': -8,\n 'Europe/London': 0,\n 'UTC': 0,\n};\n\nexport function getDateKey(timestamp: string, tz: string): string {\n const offset = (TZ_OFFSETS[tz] ?? 8) * 3_600_000;\n const d = new Date(new Date(timestamp).getTime() + offset);\n // Use UTC methods since we manually applied the timezone offset\n return `${d.getUTCFullYear()}-${String(d.getUTCMonth() + 1).padStart(2, '0')}-${String(d.getUTCDate()).padStart(2, '0')}`;\n}\n\nexport function getHourKey(timestamp: string, tz: string): string {\n const offset = (TZ_OFFSETS[tz] ?? 8) * 3_600_000;\n const d = new Date(new Date(timestamp).getTime() + offset);\n // Use UTC methods since we manually applied the timezone offset\n const yyyy = d.getUTCFullYear();\n const mm = String(d.getUTCMonth() + 1).padStart(2, '0');\n const dd = String(d.getUTCDate()).padStart(2, '0');\n const hh = String(d.getUTCHours()).padStart(2, '0');\n return `${yyyy}-${mm}-${dd}T${hh}`;\n}\n\n// ---------------------------------------------------------------------------\n// Aggregation helpers\n// ---------------------------------------------------------------------------\n\ninterface DayAgg {\n date: string;\n inputTokens: number;\n outputTokens: number;\n cacheCreationTokens: number;\n cacheReadTokens: number;\n totalTokens: number;\n totalCost: number;\n models: Map<string, { input: number; output: number; cacheCreation: number; cacheRead: number; cost: number }>;\n}\n\nfunction toDailyEntry(agg: DayAgg): DailyEntry {\n const modelBreakdowns = [...agg.models.entries()].map(([modelName, m]) => ({\n modelName,\n inputTokens: m.input,\n outputTokens: m.output,\n cacheCreationTokens: m.cacheCreation,\n cacheReadTokens: m.cacheRead,\n cost: m.cost,\n }));\n\n return {\n date: agg.date,\n inputTokens: agg.inputTokens,\n outputTokens: agg.outputTokens,\n cacheCreationTokens: agg.cacheCreationTokens,\n cacheReadTokens: agg.cacheReadTokens,\n totalTokens: agg.totalTokens,\n totalCost: Math.round(agg.totalCost * 10000) / 10000,\n modelsUsed: [...agg.models.keys()],\n modelBreakdowns,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\nconst DEFAULT_TZ = 'Asia/Shanghai';\n\nexport function getDailyResponse(project?: string | null, tz = DEFAULT_TZ): DailyResponse {\n const entries = parseAllSessions(project);\n const dayMap = new Map<string, DayAgg>();\n\n for (const e of entries) {\n const date = getDateKey(e.timestamp, tz);\n if (!dayMap.has(date)) {\n dayMap.set(date, {\n date, inputTokens: 0, outputTokens: 0, cacheCreationTokens: 0,\n cacheReadTokens: 0, totalTokens: 0, totalCost: 0,\n models: new Map(),\n });\n }\n const agg = dayMap.get(date)!;\n agg.inputTokens += e.inputTokens;\n agg.outputTokens += e.outputTokens;\n agg.cacheCreationTokens += e.cacheCreationTokens;\n agg.cacheReadTokens += e.cacheReadTokens;\n agg.totalTokens += e.inputTokens + e.outputTokens + e.cacheReadTokens;\n\n const cost = calculateCost(e.inputTokens, e.cacheReadTokens, e.outputTokens, e.model);\n agg.totalCost += cost;\n\n if (!agg.models.has(e.model)) {\n agg.models.set(e.model, { input: 0, output: 0, cacheCreation: 0, cacheRead: 0, cost: 0 });\n }\n const m = agg.models.get(e.model)!;\n m.input += e.inputTokens;\n m.output += e.outputTokens;\n m.cacheCreation += e.cacheCreationTokens;\n m.cacheRead += e.cacheReadTokens;\n m.cost += cost;\n }\n\n const daily = [...dayMap.values()].sort((a, b) => a.date.localeCompare(b.date)).map(toDailyEntry);\n const totals: Totals = daily.reduce((acc, d) => ({\n inputTokens: acc.inputTokens + d.inputTokens,\n outputTokens: acc.outputTokens + d.outputTokens,\n cacheCreationTokens: acc.cacheCreationTokens + d.cacheCreationTokens,\n cacheReadTokens: acc.cacheReadTokens + d.cacheReadTokens,\n totalTokens: acc.totalTokens + d.totalTokens,\n totalCost: acc.totalCost + d.totalCost,\n }), { inputTokens: 0, outputTokens: 0, cacheCreationTokens: 0, cacheReadTokens: 0, totalTokens: 0, totalCost: 0 });\n\n return { daily, totals };\n}\n\nexport function getProjectsResponse(tz = DEFAULT_TZ): ProjectsResponse {\n const entries = parseAllSessions();\n const projectMap = new Map<string, Map<string, DayAgg>>();\n\n for (const e of entries) {\n const date = getDateKey(e.timestamp, tz);\n const projectName = extractProjectName(e.projectDir);\n\n if (!projectMap.has(projectName)) {\n projectMap.set(projectName, new Map());\n }\n const dayMap = projectMap.get(projectName)!;\n\n if (!dayMap.has(date)) {\n dayMap.set(date, {\n date, inputTokens: 0, outputTokens: 0, cacheCreationTokens: 0,\n cacheReadTokens: 0, totalTokens: 0, totalCost: 0,\n models: new Map(),\n });\n }\n const agg = dayMap.get(date)!;\n agg.inputTokens += e.inputTokens;\n agg.outputTokens += e.outputTokens;\n agg.cacheCreationTokens += e.cacheCreationTokens;\n agg.cacheReadTokens += e.cacheReadTokens;\n agg.totalTokens += e.inputTokens + e.outputTokens + e.cacheReadTokens;\n\n const cost = calculateCost(e.inputTokens, e.cacheReadTokens, e.outputTokens, e.model);\n agg.totalCost += cost;\n\n if (!agg.models.has(e.model)) {\n agg.models.set(e.model, { input: 0, output: 0, cacheCreation: 0, cacheRead: 0, cost: 0 });\n }\n const m = agg.models.get(e.model)!;\n m.input += e.inputTokens;\n m.output += e.outputTokens;\n m.cacheCreation += e.cacheCreationTokens;\n m.cacheRead += e.cacheReadTokens;\n m.cost += cost;\n }\n\n const projects: Record<string, DailyEntry[]> = {};\n for (const [projectName, dayMap] of projectMap) {\n projects[projectName] = [...dayMap.values()]\n .sort((a, b) => a.date.localeCompare(b.date))\n .map(toDailyEntry);\n }\n\n return { projects };\n}\n\nexport function getBlocksResponse(project?: string | null, tz = DEFAULT_TZ): { blocks: BlockEntry[] } {\n const entries = parseAllSessions(project);\n const hourMap = new Map<string, {\n inputTokens: number; outputTokens: number; cacheCreationTokens: number;\n cacheReadTokens: number; costUSD: number; models: Set<string>;\n }>();\n\n for (const e of entries) {\n const hourKey = getHourKey(e.timestamp, tz);\n if (!hourMap.has(hourKey)) {\n hourMap.set(hourKey, {\n inputTokens: 0, outputTokens: 0, cacheCreationTokens: 0,\n cacheReadTokens: 0, costUSD: 0, models: new Set(),\n });\n }\n const bucket = hourMap.get(hourKey)!;\n bucket.inputTokens += e.inputTokens;\n bucket.outputTokens += e.outputTokens;\n bucket.cacheCreationTokens += e.cacheCreationTokens;\n bucket.cacheReadTokens += e.cacheReadTokens;\n bucket.costUSD += calculateCost(e.inputTokens, e.cacheReadTokens, e.outputTokens, e.model);\n bucket.models.add(e.model);\n }\n\n const blocks: BlockEntry[] = [];\n let idx = 0;\n for (const [hourKey, bucket] of hourMap) {\n const totalTokens = bucket.inputTokens + bucket.outputTokens + bucket.cacheReadTokens;\n blocks.push({\n id: `claude-${idx}`,\n startTime: `${hourKey}:00:00`,\n endTime: `${hourKey}:59:59`,\n actualEndTime: null,\n isActive: false,\n isGap: false,\n entries: totalTokens > 0 ? 1 : 0,\n tokenCounts: {\n inputTokens: bucket.inputTokens,\n outputTokens: bucket.outputTokens,\n cacheCreationInputTokens: bucket.cacheCreationTokens,\n cacheReadInputTokens: bucket.cacheReadTokens,\n },\n totalTokens,\n costUSD: Math.round(bucket.costUSD * 10000) / 10000,\n models: [...bucket.models],\n });\n idx++;\n }\n\n blocks.sort((a, b) => a.startTime.localeCompare(b.startTime));\n return { blocks };\n}\n", "import { type Request, type Response } from 'express';\nimport { cache } from '../cache.js';\nimport { validateDaily } from '../../shared/schemas.js';\nimport { getDailyResponse as getCodexDailyResponse } from '../codexParser.js';\nimport { getDailyResponse as getOpenClawDailyResponse } from '../openclawParser.js';\nimport { getDailyResponse as getOpencodeDailyResponse } from '../opencodeParser.js';\nimport { getDailyResponse as getClaudeDailyResponse } from '../claudeJsonlParser.js';\n\nexport async function getDaily(req: Request, res: Response): Promise<void> {\n const agent = req.query.agent as string || 'claude';\n const cacheKey = `daily:${agent}`;\n try {\n const cached = cache.get(cacheKey);\n if (cached) {\n res.json(cached);\n return;\n }\n\n // Stale-while-revalidate: return stale data, refresh in background\n const stale = cache.getStale(cacheKey);\n if (stale) {\n refreshDailyCache(agent, cacheKey);\n res.json(stale);\n return;\n }\n\n const data = await fetchDailyData(agent);\n cache.set(cacheKey, data);\n res.json(data);\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Unknown error';\n console.error('Error fetching daily data:', error);\n res.status(502).json({\n error: `Failed to fetch daily data from ${agent}`,\n hint: message,\n });\n }\n}\n\nfunction fetchDailyData(agent: string) {\n if (agent === 'codex') {\n return Promise.resolve(getCodexDailyResponse());\n } else if (agent === 'openclaw') {\n return Promise.resolve(validateDaily(getOpenClawDailyResponse()));\n } else if (agent === 'opencode') {\n return Promise.resolve(validateDaily(getOpencodeDailyResponse()));\n } else {\n // Claude Code: parse JSONL directly (fast, no CLI)\n return Promise.resolve(validateDaily(getClaudeDailyResponse()));\n }\n}\n\nfunction refreshDailyCache(agent: string, cacheKey: string): void {\n fetchDailyData(agent)\n .then(data => cache.set(cacheKey, data))\n .catch(err => console.error('Background refresh failed (daily):', err));\n}\n", "import { type Request, type Response } from 'express';\nimport { cache } from '../cache.js';\nimport { validateDaily } from '../../shared/schemas.js';\nimport { getDailyResponse as getClaudeDailyResponse } from '../claudeJsonlParser.js';\nimport { getDailyResponse as getCodexDailyResponse } from '../codexParser.js';\nimport { getDailyResponse as getOpenClawDailyResponse } from '../openclawParser.js';\n\nexport async function getMonthly(req: Request, res: Response): Promise<void> {\n const agent = req.query.agent as string || 'claude';\n const cacheKey = `monthly:${agent}`;\n try {\n const cached = cache.get(cacheKey);\n if (cached) {\n res.json(cached);\n return;\n }\n\n const stale = cache.getStale(cacheKey);\n if (stale) {\n res.json(stale);\n return;\n }\n\n // Monthly is same as daily for our parser (aggregated by date already)\n let data;\n if (agent === 'codex') {\n data = validateDaily(getCodexDailyResponse());\n } else if (agent === 'openclaw') {\n data = validateDaily(getOpenClawDailyResponse());\n } else {\n data = validateDaily(getClaudeDailyResponse());\n }\n\n cache.set(cacheKey, data);\n res.json(data);\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Unknown error';\n console.error('Error fetching monthly data:', error);\n res.status(502).json({\n error: 'Failed to fetch monthly data',\n hint: message,\n });\n }\n}\n", "import { type Request, type Response } from 'express';\nimport { cache } from '../cache.js';\nimport { validateDaily } from '../../shared/schemas.js';\nimport { getDailyResponse as getClaudeDailyResponse } from '../claudeJsonlParser.js';\nimport { getDailyResponse as getCodexDailyResponse } from '../codexParser.js';\nimport { getDailyResponse as getOpenClawDailyResponse } from '../openclawParser.js';\n\nexport async function getSession(req: Request, res: Response): Promise<void> {\n const agent = req.query.agent as string || 'claude';\n const cacheKey = `session:${agent}`;\n try {\n const cached = cache.get(cacheKey);\n if (cached) {\n res.json(cached);\n return;\n }\n\n const stale = cache.getStale(cacheKey);\n if (stale) {\n res.json(stale);\n return;\n }\n\n // Session data uses same daily aggregation\n let data;\n if (agent === 'codex') {\n data = validateDaily(getCodexDailyResponse());\n } else if (agent === 'openclaw') {\n data = validateDaily(getOpenClawDailyResponse());\n } else {\n data = validateDaily(getClaudeDailyResponse());\n }\n\n cache.set(cacheKey, data);\n res.json(data);\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Unknown error';\n console.error('Error fetching session data:', error);\n res.status(502).json({\n error: 'Failed to fetch session data',\n hint: message,\n });\n }\n}\n", "import { type Request, type Response } from 'express';\nimport { cache } from '../cache.js';\nimport { validateProjects } from '../../shared/schemas.js';\nimport { getProjectsResponse as getCodexProjectsResponse } from '../codexParser.js';\nimport { getProjectsResponse as getOpenClawProjectsResponse } from '../openclawParser.js';\nimport { getProjectsResponse as getOpencodeProjectsResponse } from '../opencodeParser.js';\nimport { getProjectsResponse as getClaudeProjectsResponse } from '../claudeJsonlParser.js';\n\nexport async function getProjects(req: Request, res: Response): Promise<void> {\n const agent = req.query.agent as string || 'claude';\n const cacheKey = `projects:${agent}`;\n try {\n const cached = cache.get(cacheKey);\n if (cached) {\n res.json(cached);\n return;\n }\n\n // Stale-while-revalidate\n const stale = cache.getStale(cacheKey);\n if (stale) {\n refreshProjectsCache(agent, cacheKey);\n res.json(stale);\n return;\n }\n\n const data = fetchProjectsData(agent);\n cache.set(cacheKey, data);\n res.json(data);\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Unknown error';\n console.error('Error fetching projects data:', error);\n res.status(502).json({\n error: `Failed to fetch projects data from ${agent}`,\n hint: message,\n });\n }\n}\n\nfunction fetchProjectsData(agent: string) {\n if (agent === 'codex') {\n return getCodexProjectsResponse();\n } else if (agent === 'openclaw') {\n return validateProjects(getOpenClawProjectsResponse());\n } else if (agent === 'opencode') {\n return validateProjects(getOpencodeProjectsResponse());\n } else {\n // Claude Code: parse JSONL directly (fast, no CLI)\n return validateProjects(getClaudeProjectsResponse());\n }\n}\n\nfunction refreshProjectsCache(agent: string, cacheKey: string): void {\n Promise.resolve()\n .then(() => { const data = fetchProjectsData(agent); cache.set(cacheKey, data); })\n .catch(err => console.error('Background refresh failed (projects):', err));\n}\n", "import { type Request, type Response } from 'express';\nimport { cache } from '../cache.js';\nimport { validateBlocks } from '../../shared/schemas.js';\nimport { getBlocksResponse as getCodexBlocksResponse } from '../codexParser.js';\nimport { getBlocksResponse as getOpenClawBlocksResponse } from '../openclawParser.js';\nimport { getBlocksResponse as getOpencodeBlocksResponse } from '../opencodeParser.js';\nimport { getBlocksResponse as getClaudeBlocksResponse } from '../claudeJsonlParser.js';\n\nexport async function getBlocks(req: Request, res: Response): Promise<void> {\n const agent = req.query.agent as string || 'claude';\n const project = req.query.project as string || undefined;\n\n try {\n const cacheKey = `blocks:${agent}:${project || 'all'}`;\n const cached = cache.get(cacheKey);\n if (cached) {\n res.json(cached);\n return;\n }\n\n // Stale-while-revalidate\n const stale = cache.getStale(cacheKey);\n if (stale) {\n refreshBlocksCache(agent, project, cacheKey);\n res.json(stale);\n return;\n }\n\n const data = fetchBlocksData(agent, project);\n cache.set(cacheKey, data);\n res.json(data);\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Unknown error';\n console.error('Error fetching blocks data:', error);\n res.status(502).json({\n error: 'Failed to fetch blocks data',\n hint: message,\n });\n }\n}\n\nfunction fetchBlocksData(agent: string, project?: string) {\n if (agent === 'openclaw') {\n return validateBlocks(getOpenClawBlocksResponse({ project: project || null }));\n } else if (agent === 'opencode') {\n return validateBlocks(getOpencodeBlocksResponse({ project: project || null }));\n } else if (agent === 'codex') {\n return validateBlocks(getCodexBlocksResponse({ project: project || null }));\n } else {\n // Claude Code: parse JSONL directly (fast, no CLI)\n return validateBlocks(getClaudeBlocksResponse(project || null));\n }\n}\n\nfunction refreshBlocksCache(agent: string, project: string | undefined, cacheKey: string): void {\n Promise.resolve()\n .then(() => { const data = fetchBlocksData(agent, project); cache.set(cacheKey, data); })\n .catch(err => console.error('Background refresh failed (blocks):', err));\n}\n", "import { readFileSync, readdirSync, statSync, existsSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { homedir } from 'node:os';\nimport { scanOpenClawSessions } from './openclawParser.js';\nimport type { AnalyticsResponse, ToolUsageEntry, DailyCodeChange, DailyToolCall, ProductivityKPIs } from '../shared/types.js';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ninterface ToolCallRecord {\n toolName: string; // normalized name\n timestamp: number; // ms epoch\n filePath?: string;\n linesAdded: number;\n linesDeleted: number;\n}\n\n// ---------------------------------------------------------------------------\n// Timezone helpers (same as other parsers)\n// ---------------------------------------------------------------------------\n\nconst TZ_OFFSETS: Record<string, number> = {\n 'Asia/Shanghai': 8,\n 'Asia/Tokyo': 9,\n 'America/New_York': -5,\n 'America/Los_Angeles': -8,\n 'Europe/London': 0,\n 'UTC': 0,\n};\n\nfunction getDateKey(ms: number, tz: string): string {\n const offset = (TZ_OFFSETS[tz] ?? 8) * 3_600_000;\n const d = new Date(ms + offset);\n return `${d.getUTCFullYear()}-${String(d.getUTCMonth() + 1).padStart(2, '0')}-${String(d.getUTCDate()).padStart(2, '0')}`;\n}\n\n// ---------------------------------------------------------------------------\n// Tool name normalization\n// ---------------------------------------------------------------------------\n\nexport function normalizeToolName(name: string): string {\n const lower = name.toLowerCase();\n if (lower.startsWith('mcp__')) {\n const parts = name.split('__');\n const serverPart = parts.length >= 3 ? parts[2] : 'mcp';\n return `MCP:${serverPart}`;\n }\n const mapping: Record<string, string> = {\n 'exec': 'Bash',\n 'read': 'Read',\n 'edit': 'Edit',\n 'write': 'Write',\n };\n return mapping[lower] || name;\n}\n\n// ---------------------------------------------------------------------------\n// Line counting\n// ---------------------------------------------------------------------------\n\nfunction countLines(text: string): number {\n if (!text) return 0;\n return text.split('\\n').length;\n}\n\n// ---------------------------------------------------------------------------\n// Claude Code session scanning & tool extraction\n// ---------------------------------------------------------------------------\n\nconst CLAUDE_PROJECTS_DIR = join(homedir(), '.claude', 'projects');\n\nconst projectNameCache = new Map<string, string>();\n\n/** Decode Claude's encoded project directory name.\n * Claude encodes paths: /Users/foo/bar \u2192 -Users-foo-bar\n * Since '-' replaces '/' and project names can contain '-',\n * we use filesystem checks to find the correct last segment.\n */\nfunction extractProjectName(dirName: string): string {\n if (!dirName.startsWith('-')) return dirName;\n\n const cached = projectNameCache.get(dirName);\n if (cached) return cached;\n\n const segments = dirName.replace(/^-/, '').split('-').filter(Boolean);\n if (segments.length === 0) { projectNameCache.set(dirName, dirName); return dirName; }\n if (segments.length === 1) { projectNameCache.set(dirName, segments[0]); return segments[0]; }\n\n let bestName = segments[segments.length - 1];\n\n for (let splitAt = segments.length - 1; splitAt >= 1; splitAt--) {\n const parentSegments = segments.slice(0, splitAt);\n const candidateName = segments.slice(splitAt).join('-');\n\n let parentPath = '/';\n let valid = true;\n for (const seg of parentSegments) {\n const regular = join(parentPath, seg);\n const hidden = join(parentPath, '.' + seg);\n if (existsSync(regular)) {\n parentPath = regular;\n } else if (existsSync(hidden)) {\n parentPath = hidden;\n } else {\n valid = false;\n break;\n }\n }\n\n if (!valid) continue;\n\n if (existsSync(join(parentPath, candidateName)) || existsSync(join(parentPath, '.' + candidateName))) {\n bestName = candidateName;\n break;\n }\n }\n\n projectNameCache.set(dirName, bestName);\n return bestName;\n}\n\nfunction matchesProject(dirName: string, filter: string): boolean {\n return extractProjectName(dirName) === extractProjectName(filter);\n}\n\n// Session-level cache (mtime-based)\nconst claudeSessionCache = new Map<string, { mtime: number; toolCalls: ToolCallRecord[] }>();\n\nexport function extractClaudeToolCalls(project?: string | null): ToolCallRecord[] {\n if (!existsSync(CLAUDE_PROJECTS_DIR)) return [];\n\n const results: ToolCallRecord[] = [];\n const projectDirs = readdirSync(CLAUDE_PROJECTS_DIR, { withFileTypes: true })\n .filter(d => d.isDirectory())\n .map(d => d.name);\n\n for (const dirName of projectDirs) {\n if (project && !matchesProject(dirName, project)) continue;\n\n const dirPath = join(CLAUDE_PROJECTS_DIR, dirName);\n let files: string[];\n try {\n files = readdirSync(dirPath).filter(f => f.endsWith('.jsonl'));\n } catch {\n continue;\n }\n\n for (const file of files) {\n const filePath = join(dirPath, file);\n\n let mtime = 0;\n try { mtime = statSync(filePath).mtimeMs; } catch { /* ok */ }\n\n const cached = claudeSessionCache.get(filePath);\n if (cached && cached.mtime === mtime) {\n results.push(...cached.toolCalls);\n continue;\n }\n\n const toolCalls: ToolCallRecord[] = [];\n let content: string;\n try {\n content = readFileSync(filePath, 'utf-8');\n } catch {\n continue;\n }\n\n for (const line of content.split('\\n')) {\n const trimmed = line.trim();\n if (!trimmed) continue;\n\n let obj: Record<string, unknown>;\n try { obj = JSON.parse(trimmed) as Record<string, unknown>; } catch { continue; }\n\n if (obj.type !== 'assistant' || !obj.message) continue;\n const msg = obj.message as Record<string, unknown>;\n const timestamp = new Date(obj.timestamp as string).getTime();\n const content_arr = msg.content as Array<Record<string, unknown>> | undefined;\n if (!content_arr) continue;\n\n for (const item of content_arr) {\n if (item.type !== 'tool_use') continue;\n\n const toolName = normalizeToolName(item.name as string);\n const input = (item.input as Record<string, unknown>) || {};\n\n let linesAdded = 0;\n let linesDeleted = 0;\n const filePath2 = (input.file_path as string) || undefined;\n\n if (toolName === 'Edit') {\n linesDeleted = countLines(input.old_string as string || '');\n linesAdded = countLines(input.new_string as string || '');\n } else if (toolName === 'Write') {\n linesAdded = countLines(input.content as string || '');\n }\n\n toolCalls.push({ toolName, timestamp, filePath: filePath2, linesAdded, linesDeleted });\n }\n }\n\n claudeSessionCache.set(filePath, { mtime, toolCalls });\n results.push(...toolCalls);\n }\n }\n\n return results;\n}\n\n// ---------------------------------------------------------------------------\n// OpenClaw tool extraction\n// ---------------------------------------------------------------------------\n\nconst openclawSessionCache = new Map<string, { mtime: number; toolCalls: ToolCallRecord[] }>();\n\nexport function extractOpenClawToolCalls(project?: string | null): ToolCallRecord[] {\n const results: ToolCallRecord[] = [];\n const refs = scanOpenClawSessions();\n\n for (const ref of refs) {\n if (project && ref.agentId !== project) continue;\n\n let mtime = 0;\n try { mtime = statSync(ref.sessionFile).mtimeMs; } catch { /* ok */ }\n\n const cached = openclawSessionCache.get(ref.sessionFile);\n if (cached && cached.mtime === mtime) {\n results.push(...cached.toolCalls);\n continue;\n }\n\n const toolCalls: ToolCallRecord[] = [];\n let content: string;\n try {\n content = readFileSync(ref.sessionFile, 'utf-8');\n } catch {\n continue;\n }\n\n for (const line of content.split('\\n')) {\n const trimmed = line.trim();\n if (!trimmed) continue;\n\n let obj: Record<string, unknown>;\n try { obj = JSON.parse(trimmed) as Record<string, unknown>; } catch { continue; }\n\n if (obj.type !== 'message') continue;\n const msg = obj.message as Record<string, unknown>;\n if (msg.role !== 'assistant') continue;\n\n const timestamp = Number(msg.timestamp ?? 0);\n const content_arr = msg.content as Array<Record<string, unknown>> | undefined;\n if (!content_arr) continue;\n\n for (const item of content_arr) {\n if (item.type !== 'toolCall') continue;\n\n const toolName = normalizeToolName(item.name as string);\n const args = (item.arguments as Record<string, unknown>) || {};\n\n let linesAdded = 0;\n let linesDeleted = 0;\n const filePath2 = (args.path as string) || undefined;\n\n if (toolName === 'Edit') {\n linesDeleted = countLines(args.oldText as string || '');\n linesAdded = countLines(args.newText as string || '');\n } else if (toolName === 'Write') {\n linesAdded = countLines(args.content as string || '');\n }\n\n toolCalls.push({ toolName, timestamp, filePath: filePath2, linesAdded, linesDeleted });\n }\n }\n\n openclawSessionCache.set(ref.sessionFile, { mtime, toolCalls });\n results.push(...toolCalls);\n }\n\n return results;\n}\n\n// ---------------------------------------------------------------------------\n// Analytics computation\n// ---------------------------------------------------------------------------\n\nexport function computeAnalytics(toolCalls: ToolCallRecord[], timezone = 'Asia/Shanghai'): AnalyticsResponse {\n // 1. Code Change Trend \u2014 group edit/write calls by date\n const changeMap = new Map<string, { added: number; deleted: number; files: Set<string> }>();\n for (const tc of toolCalls) {\n if (tc.linesAdded === 0 && tc.linesDeleted === 0) continue;\n const key = getDateKey(tc.timestamp, timezone);\n if (!changeMap.has(key)) changeMap.set(key, { added: 0, deleted: 0, files: new Set() });\n const entry = changeMap.get(key)!;\n entry.added += tc.linesAdded;\n entry.deleted += tc.linesDeleted;\n if (tc.filePath) entry.files.add(tc.filePath);\n }\n const codeChangeTrend: DailyCodeChange[] = [];\n for (const [date, { added, deleted, files }] of changeMap) {\n codeChangeTrend.push({ date, linesAdded: added, linesDeleted: deleted, netChange: added - deleted, filesModified: files.size });\n }\n codeChangeTrend.sort((a, b) => a.date.localeCompare(b.date));\n\n // 2. Tool Usage Distribution \u2014 count per tool\n const toolCountMap = new Map<string, number>();\n for (const tc of toolCalls) {\n toolCountMap.set(tc.toolName, (toolCountMap.get(tc.toolName) || 0) + 1);\n }\n const toolUsageDistribution: ToolUsageEntry[] = [...toolCountMap.entries()]\n .map(([name, count]) => ({ name, count }))\n .sort((a, b) => b.count - a.count);\n\n // 3. Productivity KPIs\n const editCalls = toolCalls.filter(tc => tc.toolName === 'Edit' || tc.toolName === 'Write');\n const totalEdits = editCalls.length;\n const totalLinesChanged = editCalls.reduce((s, tc) => s + tc.linesAdded + tc.linesDeleted, 0);\n const totalLinesAdded = editCalls.reduce((s, tc) => s + tc.linesAdded, 0);\n const totalLinesDeleted = editCalls.reduce((s, tc) => s + tc.linesDeleted, 0);\n const uniqueFiles = new Set(editCalls.filter(tc => tc.filePath).map(tc => tc.filePath!));\n const editDates = new Set(editCalls.map(tc => getDateKey(tc.timestamp, timezone)));\n\n const productivityKPIs: ProductivityKPIs = {\n avgLinesPerEdit: totalEdits > 0 ? Math.round(totalLinesChanged / totalEdits) : 0,\n filesModifiedPerDay: editDates.size > 0 ? Math.round(uniqueFiles.size / editDates.size) : 0,\n addDeleteRatio: totalLinesDeleted > 0 ? Math.round((totalLinesAdded / totalLinesDeleted) * 100) / 100 : totalLinesAdded > 0 ? 1 : 0,\n totalEdits,\n totalFilesModified: uniqueFiles.size,\n activeDaysWithEdits: editDates.size,\n };\n\n // 4. Tool Call Trend \u2014 group all calls by (date, toolName)\n const trendMap = new Map<string, Map<string, number>>();\n for (const tc of toolCalls) {\n const date = getDateKey(tc.timestamp, timezone);\n if (!trendMap.has(date)) trendMap.set(date, new Map());\n const dayMap = trendMap.get(date)!;\n dayMap.set(tc.toolName, (dayMap.get(tc.toolName) || 0) + 1);\n }\n const toolCallTrend: DailyToolCall[] = [];\n for (const [date, dayMap] of trendMap) {\n const entry: DailyToolCall = { date };\n for (const [tool, count] of dayMap) {\n entry[tool] = count;\n }\n toolCallTrend.push(entry);\n }\n toolCallTrend.sort((a, b) => a.date.localeCompare(b.date));\n\n // Fill missing tool values with 0 so chart lines don't break\n if (toolCallTrend.length > 0) {\n const allTools = new Set<string>();\n for (const entry of toolCallTrend) {\n for (const key of Object.keys(entry)) {\n if (key !== 'date') allTools.add(key);\n }\n }\n for (const entry of toolCallTrend) {\n for (const tool of allTools) {\n if (entry[tool] === undefined) {\n entry[tool] = 0;\n }\n }\n }\n }\n\n return { codeChangeTrend, toolUsageDistribution, productivityKPIs, toolCallTrend };\n}\n", "import { type Request, type Response } from 'express';\nimport { cache } from '../cache.js';\nimport { validateAnalytics } from '../../shared/schemas.js';\nimport { extractClaudeToolCalls, extractOpenClawToolCalls, computeAnalytics } from '../analyticsParser.js';\n\nconst EMPTY_ANALYTICS = {\n codeChangeTrend: [],\n toolUsageDistribution: [],\n productivityKPIs: { avgLinesPerEdit: 0, filesModifiedPerDay: 0, addDeleteRatio: 0, totalEdits: 0, totalFilesModified: 0, activeDaysWithEdits: 0 },\n toolCallTrend: [],\n};\n\nexport async function getAnalytics(req: Request, res: Response): Promise<void> {\n const agent = req.query.agent as string || 'claude';\n const project = req.query.project as string || undefined;\n\n if (agent === 'codex' || agent === 'opencode') {\n res.json(EMPTY_ANALYTICS);\n return;\n }\n\n try {\n const cacheKey = `analytics:${agent}:${project || 'all'}`;\n const cached = cache.get(cacheKey);\n if (cached) {\n res.json(cached);\n return;\n }\n\n const toolCalls = agent === 'openclaw'\n ? extractOpenClawToolCalls(project || null)\n : extractClaudeToolCalls(project || null);\n\n const data = computeAnalytics(toolCalls);\n const validated = validateAnalytics(data);\n cache.set(cacheKey, validated);\n res.json(validated);\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Unknown error';\n console.error('Error fetching analytics:', error);\n res.status(502).json({\n error: `Failed to fetch analytics from ${agent}`,\n hint: message,\n });\n }\n}\n", "import { existsSync, readdirSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { homedir } from 'node:os';\n\nconst CLAUDE_PROJECTS_DIR = join(homedir(), '.claude', 'projects');\nconst CODEX_SESSIONS_DIR = join(homedir(), '.codex', 'sessions');\n\nexport function isClaudeCodeAvailable(): boolean {\n if (!existsSync(CLAUDE_PROJECTS_DIR)) return false;\n try {\n const dirs = readdirSync(CLAUDE_PROJECTS_DIR, { withFileTypes: true });\n return dirs.some(d => d.isDirectory());\n } catch {\n return false;\n }\n}\n\nexport function isCodexAvailable(): boolean {\n return existsSync(CODEX_SESSIONS_DIR);\n}\n\nexport function isOpencodeAvailable(): boolean {\n return existsSync(join(homedir(), '.local', 'share', 'opencode', 'opencode.db'));\n}\n\nexport function detectAvailableAgents(): { claude: boolean; codex: boolean; opencode: boolean } {\n return {\n claude: isClaudeCodeAvailable(),\n codex: isCodexAvailable(),\n opencode: isOpencodeAvailable(),\n };\n}\n", "import { type Router, type Request, type Response } from 'express';\nimport { getDaily } from './daily.js';\nimport { getMonthly } from './monthly.js';\nimport { getSession } from './session.js';\nimport { getProjects } from './projects.js';\nimport { getBlocks } from './blocks.js';\nimport { getAnalytics } from './analytics.js';\nimport { detectAvailableAgents } from '../agentDetection.js';\nimport { isOpenClawAccessible } from '../openclawParser.js';\nimport { isOpencodeAccessible } from '../opencodeParser.js';\n\nfunction getAgents(_req: Request, res: Response): void {\n try {\n const agents = detectAvailableAgents();\n const available: string[] = [];\n if (agents.claude) available.push('claude');\n if (agents.codex) available.push('codex');\n if (isOpenClawAccessible()) available.push('openclaw');\n if (isOpencodeAccessible()) available.push('opencode');\n res.json({ available, default: available[0] || null });\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Unknown error';\n res.status(500).json({ error: 'Failed to detect agents', hint: message });\n }\n}\n\nexport function registerApiRoutes(router: Router): void {\n router.get('/agents', getAgents);\n router.get('/daily', getDaily);\n router.get('/monthly', getMonthly);\n router.get('/session', getSession);\n router.get('/projects', getProjects);\n router.get('/blocks', getBlocks);\n router.get('/analytics', getAnalytics);\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["import_node_fs", "import_node_path", "import_node_fs", "import_node_path", "import_node_os", "import_zod", "import_node_fs", "import_node_path", "import_node_os", "TZ_OFFSETS", "getTzOffsetHours", "getDateKey", "getHourKey", "emptyAcc", "mergeAcc", "accToEntry", "getDailyResponse", "getDateKey", "getProjectsResponse", "getBlocksResponse", "getHourKey", "import_node_fs", "import_node_path", "import_node_os", "cache", "TZ_OFFSETS", "getTzOffsetHours", "msToLocalDate", "getDateKey", "getHourKey", "emptyAcc", "addEvent", "getDailyResponse", "mergeAcc", "getProjectsResponse", "getBlocksResponse", "import_node_fs", "import_node_path", "import_node_os", "MODEL_PRICING", "DEFAULT_PRICING", "calculateCost", "extractProjectName", "parseAllSessions", "TZ_OFFSETS", "getDateKey", "getHourKey", "getDailyResponse", "getProjectsResponse", "getBlocksResponse", "getDailyResponse", "getDailyResponse", "getDailyResponse", "getProjectsResponse", "getBlocksResponse", "import_node_fs", "import_node_path", "import_node_os", "TZ_OFFSETS", "getDateKey", "CLAUDE_PROJECTS_DIR", "projectNameCache", "extractProjectName", "matchesProject", "import_node_fs", "import_node_path", "import_node_os", "CLAUDE_PROJECTS_DIR", "resolve", "express", "open"]
|
|
7
7
|
}
|