devrage 0.5.5 → 0.5.6

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/dist/cli.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../src/commands/scan.ts", "../src/adapters/amp.ts", "../src/adapters/claude.ts", "../src/adapters/cline.ts", "../src/adapters/codex.ts", "../src/adapters/cursor.ts", "../src/adapters/opencode.ts", "../src/adapters/pi.ts", "../src/adapters/zed.ts", "../src/adapters/index.ts", "../src/detector/index.ts", "../src/pricing/index.ts", "../src/cli.ts"],
4
- "sourcesContent": ["import { mkdir, writeFile } from \"node:fs/promises\";\nimport { dirname, join } from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\nimport {\n allAdapters,\n createAdapter,\n type CostModelSummary,\n type CostSummary,\n type PricingSource,\n} from \"../adapters/index\";\nimport { detect } from \"../detector/index\";\nimport { getPricingCachePath, loadPricingCatalog, summarizeUsage } from \"../pricing/index\";\n\n// ANSI color helpers \u2014 no dependencies needed\nconst c = {\n reset: \"\\x1b[0m\",\n bold: \"\\x1b[1m\",\n dim: \"\\x1b[2m\",\n red: \"\\x1b[31m\",\n green: \"\\x1b[32m\",\n yellow: \"\\x1b[33m\",\n blue: \"\\x1b[34m\",\n magenta: \"\\x1b[35m\",\n cyan: \"\\x1b[36m\",\n white: \"\\x1b[37m\",\n gray: \"\\x1b[90m\",\n};\n\nconst MAX_TERMINAL_MODELS = 10;\n\nconst SPINNER_MESSAGES = [\n \"Tallying the damage\",\n \"Reviewing your outbursts\",\n \"Judging your vocabulary\",\n \"Computing your shame\",\n \"Cataloging the profanity\",\n \"Measuring your frustration\",\n \"Assessing the verbal carnage\",\n \"Quantifying your displeasure\",\n \"Auditing your language\",\n \"Tabulating regrets\",\n];\n\nconst COST_SPINNER_MESSAGES = [\n \"Loading price catalog\",\n \"Reading local usage\",\n \"Scanning transcript stores\",\n \"Crunching token counts\",\n \"Still working through local history\",\n];\n\nconst DAY_MS = 24 * 60 * 60 * 1000;\n\nfunction createSpinner(messages = SPINNER_MESSAGES) {\n let messageIdx = 0;\n let dotCount = 0;\n let timer: ReturnType<typeof setInterval> | null = null;\n let messageOverride: string | null = null;\n\n function render() {\n dotCount = (dotCount + 1) % 4;\n const msg = messageOverride ?? messages[messageIdx % messages.length];\n const dots = \".\".repeat(dotCount || 1);\n process.stdout.write(`\\r ${c.dim}${msg}${dots}${c.reset} `);\n }\n\n return {\n start(message?: string) {\n messageIdx = Math.floor(Math.random() * messages.length);\n messageOverride = message ?? null;\n render();\n timer = setInterval(() => {\n render();\n }, 300);\n },\n update(message?: string) {\n if (message) {\n messageOverride = message;\n } else {\n messageOverride = null;\n messageIdx++;\n }\n render();\n },\n stop() {\n if (timer) {\n clearInterval(timer);\n timer = null;\n }\n process.stdout.write(\"\\r\" + \" \".repeat(80) + \"\\r\");\n },\n };\n}\n\ninterface ScanOptions {\n agent?: string;\n refreshPrices?: boolean;\n since?: Date;\n rangeLabel?: string;\n}\n\ninterface CostTotals {\n entries: [string, CostSummary][];\n totalCost: number;\n totalRequests: number;\n pricedRequests: number;\n unpricedRequests: number;\n}\n\ninterface CostReportModel {\n model: string;\n provider?: string;\n estimatedCost: number;\n requests: number;\n inputTokens: number;\n outputTokens: number;\n reasoningTokens: number;\n cacheReadTokens: number;\n cacheWriteTokens: number;\n}\n\ninterface CostReportDay {\n day: string;\n estimatedCost: number;\n requests: number;\n models: CostReportModel[];\n}\n\ninterface CostReportAgent {\n name: string;\n estimatedCost: number;\n requests: number;\n models: CostReportModel[];\n days: CostReportDay[];\n}\n\ninterface CostReportData {\n generatedAt: string;\n scope: string;\n totalCost: number;\n pricedRequests: number;\n unpricedRequests: number;\n agents: CostReportAgent[];\n}\n\nfunction parseArgs(args: string[]): ScanOptions {\n const options: ScanOptions = {};\n\n for (let i = 0; i < args.length; i++) {\n const arg = args[i];\n if (arg === \"--agent\" || arg === \"-a\") {\n options.agent = args[++i];\n } else if (arg === \"--since\" || arg === \"-s\") {\n const val = args[++i];\n if (val) {\n setAbsoluteSince(options, val);\n }\n } else if (arg === \"--day\" || arg === \"--days\") {\n const parsed = readOptionalDaysArg(args, i);\n setRelativeRange(options, parsed.days);\n if (parsed.consumed) {\n i++;\n }\n } else if (arg === \"--week\") {\n setRelativeRange(options, 7);\n } else if (arg === \"--month\") {\n setRelativeRange(options, 30);\n } else if (arg === \"--help\" || arg === \"-h\") {\n console.log(`devrage scan \u2014 scan sessions for profanity\n\nOptions:\n --agent, -a <name> Scan only a specific agent (claude, codex, cursor, opencode, amp, cline, pi, zed)\n --since, -s <date> Only scan messages after this date (ISO 8601)\n --day, --days [n] Only scan the last n days (default: 1)\n --week Only scan the last 7 days\n --month Only scan the last 30 days\n --help, -h Show this help`);\n process.exit(0);\n }\n }\n\n return options;\n}\n\nfunction parseCostArgs(args: string[]): ScanOptions {\n const options: ScanOptions = {};\n\n for (let i = 0; i < args.length; i++) {\n const arg = args[i];\n if (arg === \"--agent\" || arg === \"-a\") {\n options.agent = args[++i];\n } else if (arg === \"--refresh-prices\") {\n options.refreshPrices = true;\n } else if (arg === \"--since\" || arg === \"-s\") {\n const val = args[++i];\n if (val) {\n setAbsoluteSince(options, val);\n }\n } else if (arg === \"--day\" || arg === \"--days\") {\n const parsed = readOptionalDaysArg(args, i);\n setRelativeRange(options, parsed.days);\n if (parsed.consumed) {\n i++;\n }\n } else if (arg === \"--week\") {\n setRelativeRange(options, 7);\n } else if (arg === \"--month\") {\n setRelativeRange(options, 30);\n } else if (arg === \"--help\" || arg === \"-h\") {\n console.log(`devrage cost \u2014 show API-equivalent coding agent cost\n\nUsage:\n devrage cost [options]\n\nOptions:\n --agent, -a <name> Show only a specific agent (claude, codex, cursor, opencode, amp, pi)\n --refresh-prices Refresh models.dev pricing before estimating cost\n --since, -s <date> Only include usage after this date (ISO 8601)\n --day, --days [n] Only include the last n days (default: 1)\n --week Only include the last 7 days\n --month Only include the last 30 days\n --help, -h Show this help`);\n process.exit(0);\n }\n }\n\n return options;\n}\n\nfunction setAbsoluteSince(options: ScanOptions, value: string): void {\n options.since = parseDateArg(value);\n options.rangeLabel = undefined;\n}\n\nfunction setRelativeRange(options: ScanOptions, days: number): void {\n options.since = new Date(Date.now() - days * DAY_MS);\n options.rangeLabel = `last ${days} ${days === 1 ? \"day\" : \"days\"}`;\n}\n\nfunction readOptionalDaysArg(args: string[], index: number): { days: number; consumed: boolean } {\n const value = args[index + 1];\n if (!value || (value.startsWith(\"-\") && !/^-\\d+$/.test(value))) {\n return { days: 1, consumed: false };\n }\n\n return { days: parseDaysArg(value), consumed: true };\n}\n\nfunction parseDaysArg(value: string | undefined): number {\n const days = Number(value);\n if (!Number.isInteger(days) || days < 1) {\n console.error(`invalid days: ${value ?? \"\"}`);\n process.exit(1);\n }\n\n return days;\n}\n\nfunction parseDateArg(value: string): Date {\n const date = new Date(value);\n if (isNaN(date.getTime())) {\n console.error(`invalid date: ${value}`);\n process.exit(1);\n }\n\n return date;\n}\n\nexport async function scan(args: string[]): Promise<void> {\n const options = parseArgs(args);\n\n const adapters = options.agent ? [createAdapter(options.agent)] : allAdapters();\n\n const spinner = createSpinner();\n spinner.start();\n\n const groupTally: Record<string, number> = {};\n const variantTally: Record<string, Record<string, number>> = {};\n\n let totalMessages = 0;\n let totalSwears = 0;\n const perAgent: Record<string, { messages: number; swears: number }> = {};\n\n for (const adapter of adapters) {\n let agentMessages = 0;\n let agentSwears = 0;\n spinner.update();\n\n for await (const message of adapter.messages({ since: options.since })) {\n totalMessages++;\n agentMessages++;\n\n const result = detect(message.text);\n if (result.count > 0) {\n totalSwears += result.count;\n agentSwears += result.count;\n\n for (const match of result.matches) {\n groupTally[match.group] = (groupTally[match.group] ?? 0) + 1;\n\n const variants = (variantTally[match.group] ??= {});\n variants[match.word] = (variants[match.word] ?? 0) + 1;\n }\n }\n }\n\n if (agentMessages > 0) {\n perAgent[adapter.name] = { messages: agentMessages, swears: agentSwears };\n }\n }\n\n spinner.stop();\n\n const activeAgents = Object.entries(perAgent);\n\n console.log(\"\");\n printReportHeader(options);\n printBasicOverview(totalMessages, totalSwears);\n\n if (activeAgents.length > 1) {\n console.log(\"\");\n console.log(` ${sectionTitle(\"agent language\")}`);\n for (const [name, stats] of activeAgents) {\n const rate = ((stats.swears / stats.messages) * 100).toFixed(1);\n console.log(\n ` ${colorText(name.padEnd(10), agentColor(name))} ${c.bold}${String(stats.swears).padStart(4)}${c.reset} ${c.dim}in ${stats.messages} messages (${rate}%)${c.reset}`,\n );\n }\n }\n\n if (totalSwears > 0) {\n const sorted = Object.entries(groupTally).sort(([, a], [, b]) => b - a);\n console.log(\"\");\n console.log(` ${sectionTitle(\"top words\")}`);\n for (const [group, count] of sorted.slice(0, 10)) {\n const variants = variantTally[group] ?? {};\n const variantList = Object.entries(variants)\n .sort(([, a], [, b]) => b - a)\n .filter(([v]) => v !== group)\n .slice(0, 15)\n .map(([v, cnt]) => `${c.dim}${v}${c.reset} ${cnt}`)\n .join(`${c.dim},${c.reset} `);\n const suffix = variantList ? ` ${c.dim}(${c.reset}${variantList}${c.dim})${c.reset}` : \"\";\n console.log(\n ` ${c.yellow}${group.padEnd(12)}${c.reset} ${c.bold}${String(count).padStart(4)}${c.reset}${suffix}`,\n );\n }\n }\n\n console.log(\"\");\n if (totalSwears === 0) {\n console.log(` ${c.green}squeaky clean! not a single swear found.${c.reset}`);\n console.log(\"\");\n }\n}\n\nexport async function cost(args: string[]): Promise<void> {\n const options = parseCostArgs(args);\n const adapters = options.agent ? [createAdapter(options.agent)] : allAdapters();\n const costByAgent: Record<string, CostSummary> = {};\n const spinner = createSpinner(COST_SPINNER_MESSAGES);\n let totals: CostTotals | null = null;\n\n spinner.start(\"Loading price catalog\");\n try {\n const pricing = await loadPricingCatalog({ refresh: options.refreshPrices });\n for (const adapter of adapters) {\n if (!adapter.usage) {\n continue;\n }\n\n spinner.update(`Reading ${adapter.name} usage`);\n const summary = await summarizeUsage(adapter.usage({ since: options.since }), pricing);\n if (summary.requests > 0) {\n costByAgent[adapter.name] = summary;\n }\n }\n\n totals = getCostTotals(costByAgent);\n } finally {\n spinner.stop();\n }\n\n if (!totals || totals.entries.length === 0) {\n console.log(\"\");\n printCostCommandUnavailable(options);\n return;\n }\n\n spinner.start(\"Writing cost report\");\n let reportUrl: string;\n try {\n reportUrl = await writeCostHtmlReport(totals, options);\n } finally {\n spinner.stop();\n }\n\n console.log(\"\");\n printCostCommand(totals, options, reportUrl);\n}\n\nfunction printCostCommand(totals: CostTotals, options: ScanOptions, reportUrl: string): void {\n const modelTotals = aggregateModelCosts(totals.entries);\n\n printCompactHeader(options);\n printCompactTotal(totals);\n printCompactAgents(totals.entries);\n printCompactModels(modelTotals, totals.totalCost);\n console.log(\"\");\n console.log(` ${c.dim}Report:${c.reset} ${reportUrl}`);\n console.log(\"\");\n}\n\nfunction printCompactHeader(options: ScanOptions): void {\n const filters = [\n options.agent,\n options.rangeLabel ?? (options.since ? `since ${formatDate(options.since)}` : null),\n ].filter(Boolean);\n const suffix = filters.length > 0 ? ` ${c.dim}${filters.join(\" \u00B7 \")}${c.reset}` : \"\";\n console.log(` ${c.bold}${c.red}devrage${c.reset} ${c.dim}cost${c.reset}${suffix}`);\n console.log(\"\");\n}\n\nfunction compactMeta(totals: CostTotals): string {\n const parts = [formatRequests(totals.pricedRequests)];\n if (totals.unpricedRequests > 0) {\n parts.push(`${formatNumber(totals.unpricedRequests)} unpriced`);\n }\n\n return `${c.dim}${parts.join(\" \u00B7 \")}${c.reset}`;\n}\n\nfunction printCompactTotal(totals: CostTotals): void {\n console.log(` ${c.bold}total${c.reset}`);\n console.log(\n ` ${c.bold}${c.green}${formatCurrency(totals.totalCost)}${c.reset} ${compactMeta(totals)}`,\n );\n}\n\nfunction printCompactModels(models: CostModelSummary[], totalCost: number): void {\n if (models.length === 0) {\n return;\n }\n\n const visibleModels = models.slice(0, MAX_TERMINAL_MODELS);\n const maxCost = visibleModels[0]?.estimatedCost ?? 0;\n console.log(\"\");\n console.log(` ${c.bold}models${c.reset}`);\n for (const model of visibleModels) {\n const share = totalCost > 0 ? model.estimatedCost / totalCost : 0;\n const color = modelColor(model);\n console.log(\n ` ${colorText(clip(model.model, 27).padEnd(27), color)} ${formatCurrency(model.estimatedCost).padStart(9)} ${c.dim}${formatPercent(share).padStart(6)}${c.reset} ${renderBar(model.estimatedCost, maxCost, 16, color)}`,\n );\n }\n}\n\nfunction printCompactAgents(entries: [string, CostSummary][]): void {\n console.log(\"\");\n console.log(` ${c.bold}agents${c.reset}`);\n for (const [name, stats] of entries.sort(\n ([, left], [, right]) => right.estimatedCost - left.estimatedCost,\n )) {\n const color = agentColor(name);\n console.log(\n ` ${colorText(name.padEnd(10), color)} ${colorText(formatCurrency(stats.estimatedCost).padStart(9), color)} ${c.dim}${formatRequests(stats.requests).padStart(12)}${c.reset}`,\n );\n }\n}\n\nfunction printCostCommandUnavailable(options: ScanOptions): void {\n printCompactHeader(options);\n console.log(` ${c.gray}no local usage found${c.reset}`);\n console.log(\"\");\n}\n\nasync function writeCostHtmlReport(totals: CostTotals, options: ScanOptions): Promise<string> {\n const generatedAt = new Date().toISOString();\n const reportPath = join(\n dirname(getPricingCachePath()),\n `cost-report-${safeTimestamp(generatedAt)}.html`,\n );\n await mkdir(dirname(reportPath), { recursive: true });\n await writeFile(\n reportPath,\n renderCostHtmlReport(costReportData(totals, options, generatedAt)),\n \"utf-8\",\n );\n return pathToFileURL(reportPath).href;\n}\n\nfunction safeTimestamp(value: string): string {\n return value.replace(/[:.]/g, \"-\");\n}\n\nfunction costReportData(\n totals: CostTotals,\n options: ScanOptions,\n generatedAt: string,\n): CostReportData {\n return {\n generatedAt,\n scope:\n options.rangeLabel ??\n (options.since ? `since ${formatDate(options.since)}` : \"all local history\"),\n totalCost: totals.totalCost,\n pricedRequests: totals.pricedRequests,\n unpricedRequests: totals.unpricedRequests,\n agents: totals.entries\n .map(([name, summary]) => ({\n name,\n estimatedCost: summary.estimatedCost,\n requests: summary.requests - summary.unpricedRequests,\n models: summary.models.map(costReportModel),\n days: summary.days.map((day) => ({\n day: day.day,\n estimatedCost: day.estimatedCost,\n requests: day.requests - day.unpricedRequests,\n models: day.models.map(costReportModel),\n })),\n }))\n .sort((left, right) => right.estimatedCost - left.estimatedCost),\n };\n}\n\nfunction costReportModel(model: CostModelSummary): CostReportModel {\n return {\n model: model.model,\n provider: model.provider,\n estimatedCost: model.estimatedCost,\n requests: model.requests - model.unpricedRequests,\n inputTokens: model.inputTokens,\n outputTokens: model.outputTokens,\n reasoningTokens: model.reasoningTokens,\n cacheReadTokens: model.cacheReadTokens,\n cacheWriteTokens: model.cacheWriteTokens,\n };\n}\n\nfunction renderCostHtmlReport(data: CostReportData): string {\n return `<!doctype html>\n<html lang=\"en\">\n<head>\n <meta charset=\"utf-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n <title>devrage cost report</title>\n <style>\n :root {\n color-scheme: dark;\n --bg: #0f1117;\n --panel: #151923;\n --panel-2: #10141c;\n --border: #283040;\n --text: #edf1f7;\n --muted: #99a3b5;\n --faint: #677184;\n --green: #55c98f;\n --purple: #b18cff;\n --blue: #75a7ff;\n --yellow: #e5b75f;\n --cyan: #62c7df;\n }\n * { box-sizing: border-box; }\n body {\n margin: 0;\n background: var(--bg);\n color: var(--text);\n font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif;\n line-height: 1.45;\n }\n main { width: min(1180px, calc(100vw - 32px)); margin: 0 auto; padding: 28px 0 48px; }\n header { display: flex; justify-content: space-between; gap: 20px; align-items: end; margin-bottom: 22px; }\n h1 { margin: 0; font-size: 22px; letter-spacing: -0.02em; }\n .scope { color: var(--muted); font-size: 13px; margin-top: 4px; }\n .generated { color: var(--faint); font-size: 12px; text-align: right; }\n .summary { display: grid; grid-template-columns: 1.4fr repeat(3, 1fr); gap: 12px; margin-bottom: 18px; }\n .card, .panel { border: 1px solid var(--border); background: var(--panel); }\n .card { padding: 16px; min-height: 92px; }\n .label { color: var(--muted); font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.1em; }\n .value { margin-top: 8px; font-size: 26px; font-weight: 800; letter-spacing: -0.03em; font-variant-numeric: tabular-nums; }\n .primary .value { color: var(--green); font-size: 42px; }\n .controls { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; margin: 18px 0; }\n label { display: grid; gap: 6px; color: var(--muted); font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.08em; }\n select { width: 100%; border: 1px solid var(--border); background: var(--panel-2); color: var(--text); padding: 10px 12px; font: inherit; border-radius: 0; }\n .grid { display: grid; grid-template-columns: 1fr; gap: 14px; align-items: start; }\n .panel { min-width: 0; }\n .panel h2 { margin: 0; padding: 13px 14px; border-bottom: 1px solid var(--border); font-size: 13px; text-transform: uppercase; letter-spacing: 0.1em; color: var(--muted); }\n .panel-body { padding: 14px; }\n table { width: 100%; border-collapse: collapse; font-variant-numeric: tabular-nums; }\n th, td { padding: 9px 8px; border-bottom: 1px solid #202838; text-align: left; white-space: nowrap; }\n th { color: var(--faint); font-size: 11px; text-transform: uppercase; letter-spacing: 0.08em; }\n td:not(:first-child), th:not(:first-child) { text-align: right; }\n tr:last-child td { border-bottom: 0; }\n .name { color: var(--text); font-weight: 650; }\n .muted { color: var(--muted); }\n .chart-wrap { min-width: 0; }\n .chart { width: 100%; min-width: 0; height: 190px; display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); gap: clamp(1px, 0.55vw, 8px); align-items: end; overflow: hidden; }\n .bar-column { display: flex; align-items: end; min-width: 0; height: 190px; overflow: hidden; font-variant-numeric: tabular-nums; }\n .chart-empty { align-self: center; }\n .axis { position: relative; height: 24px; margin-top: 8px; border-top: 1px solid #202838; color: var(--muted); font-size: 10px; font-variant-numeric: tabular-nums; overflow: hidden; }\n .axis-tick { position: absolute; top: 6px; transform: translateX(-50%); white-space: nowrap; }\n .axis-tick.edge-start { transform: translateX(0); }\n .axis-tick.edge-end { transform: translateX(-100%); }\n .column-track { width: 100%; min-width: 0; height: 190px; display: flex; align-items: end; background: #202838; overflow: hidden; }\n .column-fill { width: 100%; min-height: 2px; background: var(--cyan); }\n .legend { display: flex; flex-wrap: wrap; gap: 10px 14px; color: var(--muted); font-size: 12px; margin-top: 12px; }\n .dot { display: inline-block; width: 9px; height: 9px; margin-right: 5px; background: var(--cyan); }\n .tooltip { position: fixed; z-index: 20; display: none; pointer-events: none; border: 1px solid var(--border); background: #0b0e14; color: var(--text); padding: 7px 9px; font-size: 12px; font-variant-numeric: tabular-nums; box-shadow: 0 8px 20px rgba(0, 0, 0, 0.35); }\n .tooltip .sub { color: var(--muted); margin-top: 2px; }\n .green { color: var(--green); } .purple { color: var(--purple); } .blue { color: var(--blue); } .yellow { color: var(--yellow); } .cyan { color: var(--cyan); }\n .bg-green { background: var(--green); } .bg-purple { background: var(--purple); } .bg-blue { background: var(--blue); } .bg-yellow { background: var(--yellow); } .bg-cyan { background: var(--cyan); }\n @media (max-width: 900px) { header, .grid { display: block; } .summary, .controls { grid-template-columns: 1fr; } .panel { margin-top: 14px; } .generated { text-align: left; margin-top: 8px; } }\n </style>\n</head>\n<body>\n <main>\n <header>\n <div>\n <h1>devrage cost report</h1>\n <div class=\"scope\" id=\"scope\"></div>\n </div>\n <div class=\"generated\" id=\"generated\"></div>\n </header>\n <section class=\"summary\">\n <div class=\"card primary\"><div class=\"label\">total</div><div class=\"value\" id=\"totalCost\"></div></div>\n <div class=\"card\"><div class=\"label\">requests</div><div class=\"value\" id=\"requestCount\"></div></div>\n <div class=\"card\"><div class=\"label\">models</div><div class=\"value\" id=\"modelCount\"></div></div>\n <div class=\"card\"><div class=\"label\">agents</div><div class=\"value\" id=\"agentCount\"></div></div>\n </section>\n <section class=\"controls\">\n <label>Agent<select id=\"agentFilter\"></select></label>\n <label>Model<select id=\"modelFilter\"></select></label>\n <label>Range<select id=\"rangeFilter\"><option value=\"all\">All included data</option><option value=\"7\">Last 7 days</option><option value=\"30\">Last 30 days</option><option value=\"90\">Last 90 days</option></select></label>\n </section>\n <section class=\"grid\">\n <div class=\"panel\"><h2>Agents</h2><div class=\"panel-body\"><table><thead><tr><th>Agent</th><th>Cost</th><th>Reqs</th></tr></thead><tbody id=\"agentRows\"></tbody></table></div></div>\n <div class=\"panel\"><h2>Models</h2><div class=\"panel-body\"><table><thead><tr><th>Model</th><th>Cost</th><th>Share</th><th>Reqs</th><th>Input</th><th>Output</th><th>Cache</th></tr></thead><tbody id=\"modelRows\"></tbody></table><div class=\"legend\"><span><i class=\"dot bg-purple\"></i>Claude/Anthropic</span><span><i class=\"dot bg-green\"></i>OpenAI</span><span><i class=\"dot bg-blue\"></i>Google</span><span><i class=\"dot bg-yellow\"></i>Kimi/GLM</span></div></div></div>\n <div class=\"panel\"><h2>Daily</h2><div class=\"panel-body\"><div class=\"chart-wrap\"><div class=\"chart\" id=\"dailyChart\"></div><div class=\"axis\" id=\"dailyAxis\"></div></div></div></div>\n </section>\n <div class=\"tooltip\" id=\"tooltip\"></div>\n </main>\n <script>\n const DATA = ${jsonForScript(data)};\n const $ = (id) => document.getElementById(id);\n const money = (value) => '$' + (Math.floor(Math.max(0, value) * 100 + 1e-9) / 100).toFixed(2);\n const number = (value) => Math.round(value).toLocaleString('en-US');\n const pct = (value) => (value * 100).toFixed(1) + '%';\n const esc = (value) => String(value).replace(/[&<>\"']/g, (ch) => ({'&':'&amp;','<':'&lt;','>':'&gt;','\"':'&quot;',\"'\":'&#39;'}[ch]));\n const modelClass = (name, provider) => {\n const model = String(name || '').toLowerCase();\n const p = String(provider || '').toLowerCase();\n if (p === 'anthropic' || model.startsWith('claude-')) return 'purple';\n if (p === 'openai' || model.startsWith('gpt-') || /^o\\\\d/.test(model)) return 'green';\n if (p === 'google' || model.startsWith('gemini-')) return 'blue';\n if (model.startsWith('kimi-') || model.startsWith('glm-')) return 'yellow';\n return 'cyan';\n };\n const shortDate = (day) => new Date(day + 'T00:00:00.000Z').toLocaleDateString('en-US', {month:'short', day:'numeric', timeZone:'UTC'});\n function dailyTicks(days) {\n const count = days.length;\n if (count === 0) return [];\n const maxTicks = count <= 7 ? count : count <= 31 ? 6 : count <= 90 ? 7 : 9;\n if (maxTicks <= 1) return [{index: 0, day: days[0].day}];\n const ticks = [];\n const seen = new Set();\n for (let tick = 0; tick < maxTicks; tick++) {\n const index = Math.round(((count - 1) * tick) / (maxTicks - 1));\n if (seen.has(index)) continue;\n seen.add(index);\n ticks.push({index, day: days[index].day});\n }\n return ticks;\n }\n function addModel(map, incoming) {\n const key = incoming.model;\n const row = map.get(key) || {model: incoming.model, provider: incoming.provider, estimatedCost: 0, requests: 0, inputTokens: 0, outputTokens: 0, reasoningTokens: 0, cacheReadTokens: 0, cacheWriteTokens: 0};\n row.estimatedCost += incoming.estimatedCost; row.requests += incoming.requests;\n row.inputTokens += incoming.inputTokens; row.outputTokens += incoming.outputTokens; row.reasoningTokens += incoming.reasoningTokens;\n row.cacheReadTokens += incoming.cacheReadTokens; row.cacheWriteTokens += incoming.cacheWriteTokens;\n map.set(key, row);\n }\n function filteredAgents() {\n const selected = $('agentFilter').value;\n return DATA.agents.filter((agent) => selected === 'all' || agent.name === selected);\n }\n function dayAllowed(day) {\n const range = $('rangeFilter').value;\n if (range === 'all') return true;\n const cutoff = new Date(DATA.generatedAt).getTime() - Number(range) * 24 * 60 * 60 * 1000;\n return new Date(day + 'T23:59:59.999Z').getTime() >= cutoff;\n }\n function selectedModelRows(models) {\n const selected = $('modelFilter').value;\n return models.filter((model) => selected === 'all' || model.model === selected);\n }\n function compute() {\n const agents = filteredAgents();\n const modelMap = new Map();\n const dayMap = new Map();\n let totalCost = 0, requests = 0;\n for (const agent of agents) {\n const models = selectedModelRows(agent.models);\n for (const model of models) { addModel(modelMap, model); totalCost += model.estimatedCost; requests += model.requests; }\n for (const day of agent.days) {\n if (!dayAllowed(day.day)) continue;\n const dayModels = selectedModelRows(day.models);\n const cost = dayModels.reduce((sum, model) => sum + model.estimatedCost, 0);\n const reqs = dayModels.reduce((sum, model) => sum + model.requests, 0);\n if (cost <= 0 && reqs <= 0) continue;\n const row = dayMap.get(day.day) || {day: day.day, estimatedCost: 0, requests: 0};\n row.estimatedCost += cost; row.requests += reqs; dayMap.set(day.day, row);\n }\n }\n return {agents, models: Array.from(modelMap.values()).sort((a,b) => b.estimatedCost - a.estimatedCost), days: Array.from(dayMap.values()).sort((a,b) => a.day.localeCompare(b.day)), totalCost, requests};\n }\n function render() {\n const view = compute();\n $('totalCost').textContent = money(view.totalCost);\n $('requestCount').textContent = number(view.requests);\n $('modelCount').textContent = number(view.models.length);\n $('agentCount').textContent = number(view.agents.length);\n const agentRows = view.agents.map((agent) => '<tr><td class=\"name\">' + esc(agent.name) + '</td><td>' + money(agent.estimatedCost) + '</td><td>' + number(agent.requests) + '</td></tr>').join('');\n $('agentRows').innerHTML = agentRows || '<tr><td colspan=\"3\" class=\"muted\">No data</td></tr>';\n const maxModel = Math.max(1, ...view.models.map((model) => model.estimatedCost));\n $('modelRows').innerHTML = view.models.map((model) => {\n const klass = modelClass(model.model, model.provider);\n const cache = model.cacheReadTokens + model.cacheWriteTokens;\n return '<tr><td class=\"name ' + klass + '\">' + esc(model.model) + '</td><td>' + money(model.estimatedCost) + '</td><td>' + pct(view.totalCost > 0 ? model.estimatedCost / view.totalCost : 0) + '</td><td>' + number(model.requests) + '</td><td>' + number(model.inputTokens) + '</td><td>' + number(model.outputTokens + model.reasoningTokens) + '</td><td>' + number(cache) + '</td></tr>';\n }).join('') || '<tr><td colspan=\"7\" class=\"muted\">No data</td></tr>';\n const maxDay = Math.max(1, ...view.days.map((day) => day.estimatedCost));\n $('dailyChart').innerHTML = view.days.length ? view.days.map((day) => {\n const tooltip = esc(shortDate(day.day) + '|' + money(day.estimatedCost) + '|' + number(day.requests) + ' reqs');\n return '<div class=\"bar-column\" data-tooltip=\"' + tooltip + '\"><div class=\"column-track\"><div class=\"column-fill\" style=\"height:' + Math.max(1, (day.estimatedCost / maxDay) * 100) + '%\"></div></div></div>';\n }).join('') : '<div class=\"muted chart-empty\">No data</div>';\n $('dailyAxis').innerHTML = dailyTicks(view.days).map((tick) => {\n const left = view.days.length === 1 ? 50 : ((tick.index + 0.5) / view.days.length) * 100;\n const edge = view.days.length === 1 ? '' : tick.index === 0 ? ' edge-start' : tick.index === view.days.length - 1 ? ' edge-end' : '';\n return '<span class=\"axis-tick' + edge + '\" style=\"left:' + left.toFixed(4) + '%\">' + esc(shortDate(tick.day)) + '</span>';\n }).join('');\n }\n function showTooltip(event) {\n const target = event.target.closest('[data-tooltip]');\n const tooltip = $('tooltip');\n if (!target) { tooltip.style.display = 'none'; return; }\n const [date, amount, requests] = target.dataset.tooltip.split('|');\n tooltip.innerHTML = '<div>' + esc(date) + '</div><div class=\"sub\">' + esc(amount) + ' \u00B7 ' + esc(requests) + '</div>';\n tooltip.style.display = 'block';\n moveTooltip(event);\n }\n function moveTooltip(event) {\n const tooltip = $('tooltip');\n if (tooltip.style.display !== 'block') return;\n const offset = 12;\n const nextLeft = Math.min(window.innerWidth - tooltip.offsetWidth - 8, event.clientX + offset);\n const nextTop = Math.min(window.innerHeight - tooltip.offsetHeight - 8, event.clientY + offset);\n tooltip.style.left = Math.max(8, nextLeft) + 'px';\n tooltip.style.top = Math.max(8, nextTop) + 'px';\n }\n function init() {\n $('scope').textContent = DATA.scope;\n $('generated').textContent = 'Generated ' + new Date(DATA.generatedAt).toLocaleString();\n $('agentFilter').innerHTML = '<option value=\"all\">All agents</option>' + DATA.agents.map((agent) => '<option value=\"' + esc(agent.name) + '\">' + esc(agent.name) + '</option>').join('');\n const models = Array.from(new Set(DATA.agents.flatMap((agent) => agent.models.map((model) => model.model)))).sort();\n $('modelFilter').innerHTML = '<option value=\"all\">All models</option>' + models.map((model) => '<option value=\"' + esc(model) + '\">' + esc(model) + '</option>').join('');\n ['agentFilter', 'modelFilter', 'rangeFilter'].forEach((id) => $(id).addEventListener('change', render));\n $('dailyChart').addEventListener('mouseover', showTooltip);\n $('dailyChart').addEventListener('mousemove', moveTooltip);\n $('dailyChart').addEventListener('mouseleave', () => { $('tooltip').style.display = 'none'; });\n render();\n }\n init();\n </script>\n</body>\n</html>`;\n}\n\nfunction jsonForScript(value: unknown): string {\n return JSON.stringify(value).replace(/</g, \"\\\\u003c\");\n}\n\nfunction printReportHeader(options: ScanOptions): void {\n const scope =\n options.rangeLabel ??\n (options.since ? `since ${formatDate(options.since)}` : \"all local history\");\n const agent = options.agent ? ` \u00B7 ${options.agent}` : \"\";\n console.log(` ${c.bold}${c.red}devrage${c.reset} ${c.dim}report${c.reset}`);\n console.log(` ${c.dim}${scope}${agent}${c.reset}`);\n console.log(` ${c.dim}${\"\u2500\".repeat(54)}${c.reset}`);\n}\n\nfunction printBasicOverview(totalMessages: number, totalSwears: number): void {\n console.log(\n ` ${c.dim}messages scanned${c.reset} ${c.bold}${formatNumber(totalMessages)}${c.reset}`,\n );\n console.log(\n ` ${c.dim}total swears${c.reset} ${c.bold}${c.red}${formatNumber(totalSwears)}${c.reset}`,\n );\n}\n\nfunction getCostTotals(costByAgent: Record<string, CostSummary>): CostTotals {\n const entries = Object.entries(costByAgent);\n const totalCost = entries.reduce((sum, [, stats]) => sum + stats.estimatedCost, 0);\n const totalRequests = entries.reduce((sum, [, stats]) => sum + stats.requests, 0);\n const unpricedRequests = entries.reduce((sum, [, stats]) => sum + stats.unpricedRequests, 0);\n\n return {\n entries,\n totalCost,\n totalRequests,\n pricedRequests: totalRequests - unpricedRequests,\n unpricedRequests,\n };\n}\n\nfunction aggregateModelCosts(entries: [string, CostSummary][]): CostModelSummary[] {\n const models = new Map<string, CostModelSummary>();\n\n for (const [, stats] of entries) {\n for (const model of stats.models) {\n mergeModelSummary(models, model);\n }\n }\n\n return sortedCostModels(models);\n}\n\nfunction mergeModelSummary(\n models: Map<string, CostModelSummary>,\n incoming: CostModelSummary,\n): void {\n const key = incoming.model;\n let model = models.get(key);\n\n if (!model) {\n models.set(key, { ...incoming });\n return;\n }\n\n model.requests += incoming.requests;\n model.estimatedCost += incoming.estimatedCost;\n model.billedCost += incoming.billedCost;\n model.pricingSource = mergeDisplayPricingSource(model.pricingSource, incoming.pricingSource);\n model.unpricedRequests += incoming.unpricedRequests;\n model.inputTokens += incoming.inputTokens;\n model.outputTokens += incoming.outputTokens;\n model.reasoningTokens += incoming.reasoningTokens;\n model.cacheReadTokens += incoming.cacheReadTokens;\n model.cacheWriteTokens += incoming.cacheWriteTokens;\n}\n\nfunction sortedCostModels(models: Map<string, CostModelSummary>): CostModelSummary[] {\n return Array.from(models.values()).sort(\n (left, right) => right.estimatedCost - left.estimatedCost || right.requests - left.requests,\n );\n}\n\nfunction mergeDisplayPricingSource(left: PricingSource, right: PricingSource): PricingSource {\n return left === right ? left : \"mixed\";\n}\n\nfunction sectionTitle(label: string): string {\n const width = 54;\n const lineLength = Math.max(4, width - label.length - 1);\n return `${c.bold}${label}${c.reset} ${c.dim}${\"\u2500\".repeat(lineLength)}${c.reset}`;\n}\n\nfunction colorText(value: string, color: string): string {\n return `${color}${value}${c.reset}`;\n}\n\nfunction agentColor(agent: string): string {\n switch (agent) {\n case \"claude\":\n return c.magenta;\n case \"codex\":\n return c.green;\n case \"opencode\":\n return c.cyan;\n case \"amp\":\n return c.yellow;\n case \"pi\":\n return c.blue;\n case \"cursor\":\n return c.blue;\n default:\n return c.white;\n }\n}\n\nfunction modelColor(model: CostModelSummary): string {\n const provider = model.provider?.toLowerCase();\n const modelName = model.model.toLowerCase();\n\n if (provider === \"anthropic\" || modelName.startsWith(\"claude-\")) {\n return c.magenta;\n }\n if (provider === \"openai\" || modelName.startsWith(\"gpt-\") || /^o\\d/.test(modelName)) {\n return c.green;\n }\n if (provider === \"google\" || modelName.startsWith(\"gemini-\")) {\n return c.blue;\n }\n if (modelName.startsWith(\"kimi-\") || modelName.startsWith(\"glm-\")) {\n return c.yellow;\n }\n\n return c.cyan;\n}\n\nfunction renderBar(value: number, max: number, width: number, color = c.cyan): string {\n const filled = max > 0 && value > 0 ? Math.max(1, Math.round((value / max) * width)) : 0;\n const empty = width - filled;\n return `${color}${\"\u2501\".repeat(filled)}${c.gray}${\"\u2500\".repeat(empty)}${c.reset}`;\n}\n\nfunction clip(value: string, maxLength: number): string {\n return value.length <= maxLength ? value : `${value.slice(0, maxLength - 1)}\u2026`;\n}\n\nfunction formatCurrency(value: number): string {\n const cents = Math.floor(Math.max(0, value) * 100 + 1e-9);\n return `$${(cents / 100).toFixed(2)}`;\n}\n\nfunction formatNumber(value: number): string {\n return value.toLocaleString(\"en-US\");\n}\n\nfunction formatRequests(value: number): string {\n return `${formatNumber(value)} ${value === 1 ? \"req\" : \"reqs\"}`;\n}\n\nfunction formatPercent(value: number): string {\n return `${(value * 100).toFixed(1)}%`;\n}\n\nfunction formatDate(value: Date): string {\n return value.toISOString().slice(0, 10);\n}\n", "import { readdir, readFile } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport type { Adapter, AdapterOptions, Message, UsageRecord } from \"./index\";\n\n/**\n * Amp (Sourcegraph) stores threads as JSON files at:\n * ~/.local/share/amp/threads/<thread-id>.json\n *\n * Each file is a JSON object with a `messages` array:\n * { \"messages\": [{ \"role\": \"user\"|\"assistant\", \"content\": \"...\", ... }], \"usageLedger\": {...}, ... }\n *\n * Messages have `role`, `content` (string or array), and optionally a timestamp.\n */\n\nfunction getAmpThreadsDir(): string {\n return join(process.env[\"XDG_DATA_HOME\"] ?? join(homedir(), \".local\", \"share\"), \"amp\", \"threads\");\n}\n\nexport function ampAdapter(): Adapter {\n return {\n name: \"amp\",\n async *messages(options?: AdapterOptions): AsyncGenerator<Message> {\n const threadsDir = getAmpThreadsDir();\n\n let files: string[];\n try {\n files = await readdir(threadsDir);\n } catch {\n return; // Amp not installed or no threads\n }\n\n const jsonFiles = files.filter((f) => f.endsWith(\".json\"));\n\n for (const file of jsonFiles) {\n const filePath = join(threadsDir, file);\n const threadId = file.replace(\".json\", \"\");\n\n try {\n const thread = await readAmpThread(filePath);\n if (!thread) {\n continue;\n }\n\n if (!thread.messages || !Array.isArray(thread.messages)) {\n continue;\n }\n\n for (const msg of thread.messages) {\n if (msg.role !== \"user\") {\n continue;\n }\n\n const text = extractText(msg.content);\n if (!text) {\n continue;\n }\n\n const timestamp = msg.timestamp ?? msg.createdAt ?? undefined;\n if (options?.since && timestamp) {\n const ts = new Date(timestamp);\n if (ts < options.since) {\n continue;\n }\n }\n\n yield {\n text,\n timestamp,\n session: threadId,\n };\n }\n } catch {\n // Skip malformed files\n }\n }\n },\n async *usage(options?: AdapterOptions): AsyncGenerator<UsageRecord> {\n const threadsDir = getAmpThreadsDir();\n\n let files: string[];\n try {\n files = await readdir(threadsDir);\n } catch {\n return;\n }\n\n for (const file of files.filter((f) => f.endsWith(\".json\"))) {\n const filePath = join(threadsDir, file);\n const threadId = file.replace(\".json\", \"\");\n\n try {\n const thread = await readAmpThread(filePath);\n if (!thread?.usageLedger) {\n continue;\n }\n\n for (const record of extractAmpUsageRecords(thread.usageLedger, threadId)) {\n if (options?.since && record.timestamp) {\n const ts = new Date(record.timestamp);\n if (ts < options.since) {\n continue;\n }\n }\n\n yield record;\n }\n } catch {\n // Skip malformed files\n }\n }\n },\n };\n}\n\nasync function readAmpThread(filePath: string): Promise<AmpThread | null> {\n const raw = await readFile(filePath, \"utf-8\");\n const parsed = JSON.parse(raw) as unknown;\n return asRecord(parsed) ? (parsed as AmpThread) : null;\n}\n\nfunction extractText(content: unknown): string | null {\n if (typeof content === \"string\") {\n return content;\n }\n if (Array.isArray(content)) {\n const parts = content\n .filter(\n (p): p is { type: string; text: string } =>\n typeof p === \"object\" && p !== null && typeof p.text === \"string\",\n )\n .map((p) => p.text);\n return parts.length > 0 ? parts.join(\" \") : null;\n }\n return null;\n}\n\ninterface AmpMessage {\n role?: string;\n content?: unknown;\n timestamp?: string;\n createdAt?: string;\n}\n\ninterface AmpThread {\n messages?: AmpMessage[];\n usageLedger?: unknown;\n}\n\ninterface AmpUsageContext {\n provider?: string;\n model?: string;\n timestamp?: string;\n}\n\nfunction extractAmpUsageRecords(usageLedger: unknown, threadId: string): UsageRecord[] {\n const records: UsageRecord[] = [];\n collectAmpUsage(usageLedger, threadId, records, {});\n return records;\n}\n\nfunction collectAmpUsage(\n value: unknown,\n threadId: string,\n records: UsageRecord[],\n context: AmpUsageContext,\n depth = 0,\n): void {\n if (depth > 12) {\n return;\n }\n\n if (Array.isArray(value)) {\n for (const item of value) {\n collectAmpUsage(item, threadId, records, context, depth + 1);\n }\n return;\n }\n\n const record = asRecord(value);\n if (!record) {\n return;\n }\n\n const nextContext = {\n provider: stringField(record, [\"provider\", \"providerID\", \"providerId\"]) ?? context.provider,\n model: stringField(record, [\"model\", \"modelID\", \"modelId\"]) ?? context.model,\n timestamp: timestampField(record) ?? context.timestamp,\n };\n const usageSource = firstRecordField(record, [\"usage\", \"tokens\", \"tokenUsage\"]) ?? record;\n const rawInputTokens = tokenField(usageSource, [\"inputTokens\", \"input_tokens\", \"promptTokens\"]);\n const outputTokens = tokenField(usageSource, [\n \"outputTokens\",\n \"output_tokens\",\n \"completionTokens\",\n ]);\n const reasoningTokens = tokenField(usageSource, [\"reasoningTokens\", \"reasoning_output_tokens\"]);\n const cachedInputSubset = tokenField(usageSource, [\"cachedInputTokens\", \"cached_input_tokens\"]);\n const cacheReadTokens = tokenField(usageSource, [\n \"cacheReadTokens\",\n \"cache_read_tokens\",\n \"cacheReadInputTokens\",\n \"cache_read_input_tokens\",\n \"cachedInputTokens\",\n \"cached_input_tokens\",\n ]);\n const inputTokens = Math.max(rawInputTokens - cachedInputSubset, 0);\n const cacheWriteTokens = tokenField(usageSource, [\n \"cacheWriteTokens\",\n \"cache_write_tokens\",\n \"cacheCreationInputTokens\",\n \"cache_creation_input_tokens\",\n \"cacheWriteInputTokens\",\n \"cache_write_input_tokens\",\n ]);\n const billedCost = tokenField(record, [\n \"cost\",\n \"totalCost\",\n \"total_cost\",\n \"billedCost\",\n \"billed_cost\",\n ]);\n\n if (\n inputTokens + outputTokens + reasoningTokens + cacheReadTokens + cacheWriteTokens + billedCost >\n 0\n ) {\n records.push({\n agent: \"amp\",\n provider: nextContext.provider,\n model: nextContext.model,\n timestamp: nextContext.timestamp,\n session: threadId,\n billedCost,\n inputTokens,\n outputTokens,\n reasoningTokens,\n cacheReadTokens,\n cacheWriteTokens,\n });\n }\n\n for (const child of Object.values(record)) {\n if (child !== usageSource && typeof child === \"object\" && child !== null) {\n collectAmpUsage(child, threadId, records, nextContext, depth + 1);\n }\n }\n}\n\nfunction firstRecordField(\n record: Record<string, unknown>,\n fields: string[],\n): Record<string, unknown> | null {\n for (const field of fields) {\n const value = asRecord(record[field]);\n if (value) {\n return value;\n }\n }\n\n return null;\n}\n\nfunction stringField(record: Record<string, unknown>, fields: string[]): string | undefined {\n for (const field of fields) {\n const value = record[field];\n if (typeof value === \"string\" && value.trim()) {\n return value;\n }\n }\n\n return undefined;\n}\n\nfunction timestampField(record: Record<string, unknown>): string | undefined {\n const value = stringField(record, [\"timestamp\", \"createdAt\", \"time\", \"date\"]);\n if (value) {\n const date = new Date(value);\n return Number.isFinite(date.getTime()) ? date.toISOString() : undefined;\n }\n\n return undefined;\n}\n\nfunction tokenField(record: Record<string, unknown>, fields: string[]): number {\n for (const field of fields) {\n const value = record[field];\n if (typeof value === \"number\" && Number.isFinite(value)) {\n return value;\n }\n }\n\n return 0;\n}\n\nfunction asRecord(value: unknown): Record<string, unknown> | null {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n return null;\n }\n\n return value as Record<string, unknown>;\n}\n", "import { createReadStream } from \"node:fs\";\nimport { readdir, stat } from \"node:fs/promises\";\nimport { createInterface } from \"node:readline\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport type { Adapter, AdapterOptions, Message, UsageRecord } from \"./index\";\n\n/**\n * Claude Code stores sessions as JSONL files at:\n * ~/.claude/projects/<project-path>/<session-uuid>.jsonl\n *\n * Each line is a JSON object. User messages have:\n * { \"type\": \"human\", \"message\": { \"content\": [...] } }\n * or sometimes:\n * { \"role\": \"user\", \"content\": \"...\" }\n */\n\nconst CLAUDE_DIR = join(homedir(), \".claude\", \"projects\");\n\nexport function claudeAdapter(): Adapter {\n return {\n name: \"claude\",\n async *messages(options?: AdapterOptions): AsyncGenerator<Message> {\n for await (const file of discoverClaudeJsonlFiles()) {\n yield* parseClaudeJsonl(file.filePath, { ...file, since: options?.since });\n }\n },\n async *usage(options?: AdapterOptions): AsyncGenerator<UsageRecord> {\n for await (const file of discoverClaudeJsonlFiles()) {\n yield* parseClaudeUsageJsonl(file.filePath, { ...file, since: options?.since });\n }\n },\n };\n}\n\nasync function* discoverClaudeJsonlFiles(): AsyncGenerator<{\n filePath: string;\n session: string;\n project: string;\n}> {\n let projectDirs: string[];\n try {\n projectDirs = await readdir(CLAUDE_DIR);\n } catch {\n return;\n }\n\n for (const projectDir of projectDirs) {\n const projectPath = join(CLAUDE_DIR, projectDir);\n const projectStat = await stat(projectPath);\n if (!projectStat.isDirectory()) {\n continue;\n }\n\n const entries = await readdir(projectPath);\n const jsonlFiles = entries.filter((f) => f.endsWith(\".jsonl\"));\n\n for (const file of jsonlFiles) {\n yield {\n filePath: join(projectPath, file),\n session: file.replace(\".jsonl\", \"\"),\n project: projectDir,\n };\n }\n\n // Also check for subagent JSONL files in session subdirectories\n const subdirs = entries.filter((f) => !f.includes(\".\"));\n for (const subdir of subdirs) {\n const subagentsDir = join(projectPath, subdir, \"subagents\");\n try {\n const subFiles = await readdir(subagentsDir);\n const subJsonl = subFiles.filter((f) => f.endsWith(\".jsonl\"));\n for (const file of subJsonl) {\n yield {\n filePath: join(subagentsDir, file),\n session: `${subdir}/${file.replace(\".jsonl\", \"\")}`,\n project: projectDir,\n };\n }\n } catch {\n // No subagents directory, skip\n }\n }\n }\n}\n\nasync function* parseClaudeJsonl(\n filePath: string,\n context: { session: string; project: string; since?: Date },\n): AsyncGenerator<Message> {\n const rl = createInterface({\n input: createReadStream(filePath, { encoding: \"utf-8\" }),\n crlfDelay: Infinity,\n });\n\n for await (const line of rl) {\n if (!line.trim()) {\n continue;\n }\n\n try {\n const entry = JSON.parse(line) as Record<string, unknown>;\n const text = extractUserText(entry);\n if (!text) {\n continue;\n }\n\n const timestamp = extractTimestamp(entry);\n if (context.since && timestamp) {\n const ts = new Date(timestamp);\n if (ts < context.since) {\n continue;\n }\n }\n\n yield {\n text,\n timestamp: timestamp ?? undefined,\n session: context.session,\n project: context.project,\n };\n } catch {\n // Skip malformed lines\n }\n }\n}\n\nfunction extractUserText(entry: Record<string, unknown>): string | null {\n // Format: { \"type\": \"user\", \"message\": { \"role\": \"user\", \"content\": \"...\" } }\n if (entry[\"type\"] === \"user\") {\n const message = entry[\"message\"] as Record<string, unknown> | undefined;\n if (!message) {\n return null;\n }\n return contentToString(message[\"content\"]);\n }\n\n // Legacy format: { \"type\": \"human\", \"message\": { \"content\": [...] } }\n if (entry[\"type\"] === \"human\") {\n const message = entry[\"message\"] as Record<string, unknown> | undefined;\n if (!message) {\n return null;\n }\n return contentToString(message[\"content\"]);\n }\n\n // Flat format: { \"role\": \"user\", \"content\": \"...\" }\n if (entry[\"role\"] === \"user\") {\n return contentToString(entry[\"content\"]);\n }\n\n return null;\n}\n\nfunction contentToString(content: unknown): string | null {\n if (typeof content === \"string\") {\n return content;\n }\n if (Array.isArray(content)) {\n const parts = content\n .filter(\n (p): p is { type: string; text: string } =>\n typeof p === \"object\" && p !== null && p.type === \"text\",\n )\n .map((p) => p.text);\n return parts.length > 0 ? parts.join(\" \") : null;\n }\n return null;\n}\n\nfunction extractTimestamp(entry: Record<string, unknown>): string | null {\n if (typeof entry[\"timestamp\"] === \"string\") {\n return entry[\"timestamp\"];\n }\n if (typeof entry[\"createdAt\"] === \"string\") {\n return entry[\"createdAt\"];\n }\n return null;\n}\n\n/** Claude Code repeats assistant rows while streaming, so request/message IDs are deduped. */\nasync function* parseClaudeUsageJsonl(\n filePath: string,\n context: { session: string; project: string; since?: Date },\n): AsyncGenerator<UsageRecord> {\n const rl = createInterface({\n input: createReadStream(filePath, { encoding: \"utf-8\" }),\n crlfDelay: Infinity,\n });\n const seen = new Set<string>();\n\n for await (const line of rl) {\n if (!line.trim()) {\n continue;\n }\n\n try {\n const entry = JSON.parse(line) as Record<string, unknown>;\n const message = asRecord(entry[\"message\"]);\n if (!message || entry[\"type\"] !== \"assistant\" || message[\"role\"] !== \"assistant\") {\n continue;\n }\n\n const usage = asRecord(message[\"usage\"]);\n if (!usage) {\n continue;\n }\n\n const model = stringValue(message[\"model\"]);\n const timestamp = extractTimestamp(entry) ?? undefined;\n if (context.since && timestamp) {\n const ts = new Date(timestamp);\n if (ts < context.since) {\n continue;\n }\n }\n\n const inputTokens = numberValue(usage[\"input_tokens\"]);\n const outputTokens = numberValue(usage[\"output_tokens\"]);\n const cacheReadTokens = numberValue(usage[\"cache_read_input_tokens\"]);\n const cacheWriteTokens = cacheCreationTokens(usage);\n if (inputTokens + outputTokens + cacheReadTokens + cacheWriteTokens === 0) {\n continue;\n }\n\n const dedupeKey =\n stringValue(entry[\"requestId\"]) ??\n stringValue(message[\"id\"]) ??\n `${context.session}:${timestamp ?? \"\"}:${model ?? \"unknown\"}:${inputTokens}:${outputTokens}`;\n if (seen.has(dedupeKey)) {\n continue;\n }\n seen.add(dedupeKey);\n\n yield {\n agent: \"claude\",\n provider: \"anthropic\",\n model,\n timestamp,\n session: context.session,\n inputTokens,\n outputTokens,\n reasoningTokens: 0,\n cacheReadTokens,\n cacheWriteTokens,\n };\n } catch {\n // Skip malformed lines\n }\n }\n}\n\nfunction cacheCreationTokens(usage: Record<string, unknown>): number {\n const explicit = numberValue(usage[\"cache_creation_input_tokens\"]);\n if (explicit > 0) {\n return explicit;\n }\n\n const cacheCreation = asRecord(usage[\"cache_creation\"]);\n return (\n numberValue(cacheCreation?.[\"ephemeral_1h_input_tokens\"]) +\n numberValue(cacheCreation?.[\"ephemeral_5m_input_tokens\"])\n );\n}\n\nfunction numberValue(value: unknown): number {\n return typeof value === \"number\" && Number.isFinite(value) ? value : 0;\n}\n\nfunction stringValue(value: unknown): string | undefined {\n return typeof value === \"string\" && value.trim() ? value : undefined;\n}\n\nfunction asRecord(value: unknown): Record<string, unknown> | null {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n return null;\n }\n\n return value as Record<string, unknown>;\n}\n", "import { readdir, readFile, stat } from \"node:fs/promises\";\nimport { existsSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport type { Adapter, AdapterOptions, Message } from \"./index\";\n\n/**\n * Cline (formerly Claude Dev) stores task history at:\n *\n * VS Code extension:\n * macOS: ~/Library/Application Support/Code/User/globalStorage/saoudrizwan.claude-dev/tasks/<task-id>/api_conversation_history.json\n * Linux: ~/.config/Code/User/globalStorage/saoudrizwan.claude-dev/tasks/<task-id>/api_conversation_history.json\n * Windows: %APPDATA%/Code/User/globalStorage/saoudrizwan.claude-dev/tasks/<task-id>/api_conversation_history.json\n *\n * Standalone CLI / JetBrains (newer):\n * ~/.cline/data/tasks/<task-id>/api_conversation_history.json\n *\n * Roo Code (fork) uses the same format at:\n * globalStorage/rooveterinaryinc.roo-cline/tasks/<task-id>/api_conversation_history.json\n *\n * Each api_conversation_history.json is a JSON array of messages:\n * [{ \"role\": \"user\"|\"assistant\", \"content\": \"...\" | [{type: \"text\", text: \"...\"}] }]\n */\n\nfunction getClineTaskDirs(): string[] {\n const dirs: string[] = [];\n\n // VS Code extension paths\n const vscodePaths = getVSCodeGlobalStoragePaths();\n const extensionIds = [\"saoudrizwan.claude-dev\", \"rooveterinaryinc.roo-cline\"];\n\n for (const basePath of vscodePaths) {\n for (const extId of extensionIds) {\n const tasksDir = join(basePath, extId, \"tasks\");\n if (existsSync(tasksDir)) {\n dirs.push(tasksDir);\n }\n }\n }\n\n // Standalone CLI path\n const clineStandalone = join(homedir(), \".cline\", \"data\", \"tasks\");\n if (existsSync(clineStandalone)) {\n dirs.push(clineStandalone);\n }\n\n return dirs;\n}\n\nfunction getVSCodeGlobalStoragePaths(): string[] {\n const paths: string[] = [];\n\n if (process.platform === \"darwin\") {\n paths.push(\n join(homedir(), \"Library\", \"Application Support\", \"Code\", \"User\", \"globalStorage\"),\n join(homedir(), \"Library\", \"Application Support\", \"Code - Insiders\", \"User\", \"globalStorage\"),\n join(homedir(), \"Library\", \"Application Support\", \"Cursor\", \"User\", \"globalStorage\"),\n );\n } else if (process.platform === \"linux\") {\n const configBase = process.env[\"XDG_CONFIG_HOME\"] ?? join(homedir(), \".config\");\n paths.push(\n join(configBase, \"Code\", \"User\", \"globalStorage\"),\n join(configBase, \"Code - Insiders\", \"User\", \"globalStorage\"),\n join(configBase, \"Cursor\", \"User\", \"globalStorage\"),\n );\n } else {\n // Windows\n const appData = process.env[\"APPDATA\"] ?? join(homedir(), \"AppData\", \"Roaming\");\n paths.push(\n join(appData, \"Code\", \"User\", \"globalStorage\"),\n join(appData, \"Code - Insiders\", \"User\", \"globalStorage\"),\n join(appData, \"Cursor\", \"User\", \"globalStorage\"),\n );\n }\n\n return paths;\n}\n\nexport function clineAdapter(): Adapter {\n return {\n name: \"cline\",\n async *messages(options?: AdapterOptions): AsyncGenerator<Message> {\n const taskDirs = getClineTaskDirs();\n\n for (const tasksDir of taskDirs) {\n let taskIds: string[];\n try {\n taskIds = await readdir(tasksDir);\n } catch {\n continue;\n }\n\n for (const taskId of taskIds) {\n const taskDir = join(tasksDir, taskId);\n const taskStat = await stat(taskDir).catch(() => null);\n if (!taskStat?.isDirectory()) {\n continue;\n }\n\n const historyFile = join(taskDir, \"api_conversation_history.json\");\n\n try {\n const raw = await readFile(historyFile, \"utf-8\");\n const messages = JSON.parse(raw) as ClineMessage[];\n\n if (!Array.isArray(messages)) {\n continue;\n }\n\n for (const msg of messages) {\n if (msg.role !== \"user\") {\n continue;\n }\n\n const text = extractText(msg.content);\n if (!text) {\n continue;\n }\n\n // Cline doesn't store per-message timestamps in the conversation file\n // Use the task metadata file for approximate timing\n const timestamp = msg.ts ?? undefined;\n if (options?.since && timestamp) {\n const ts = new Date(timestamp);\n if (ts < options.since) {\n continue;\n }\n }\n\n yield {\n text,\n session: taskId,\n };\n }\n } catch {\n // Skip tasks without history or malformed files\n }\n }\n }\n },\n };\n}\n\nfunction extractText(content: unknown): string | null {\n if (typeof content === \"string\") {\n return content;\n }\n if (Array.isArray(content)) {\n const parts = content\n .filter(\n (p): p is { type: string; text: string } =>\n typeof p === \"object\" && p !== null && p.type === \"text\" && typeof p.text === \"string\",\n )\n .map((p) => p.text);\n return parts.length > 0 ? parts.join(\" \") : null;\n }\n return null;\n}\n\ninterface ClineMessage {\n role?: string;\n content?: unknown;\n ts?: string;\n}\n", "import { createReadStream } from \"node:fs\";\nimport { readdir, stat } from \"node:fs/promises\";\nimport { createInterface } from \"node:readline\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport type { Adapter, AdapterOptions, Message, UsageRecord } from \"./index\";\n\n/**\n * Codex stores sessions as JSONL files at:\n * ~/.codex/sessions/YYYY/MM/DD/rollout-*.jsonl\n *\n * Each line is JSON with structure:\n * { \"timestamp\": \"...\", \"type\": \"response_item\", \"payload\": { \"type\": \"message\", \"role\": \"user\", \"content\": [...] } }\n *\n * User messages have payload.role === \"user\" and content is an array of\n * { \"type\": \"input_text\", \"text\": \"...\" }\n *\n * We skip messages that are just environment context injections.\n */\n\nconst CODEX_SESSIONS_DIR = join(homedir(), \".codex\", \"sessions\");\n\nexport function codexAdapter(): Adapter {\n return {\n name: \"codex\",\n async *messages(options?: AdapterOptions): AsyncGenerator<Message> {\n for await (const file of discoverCodexSessionFiles(CODEX_SESSIONS_DIR)) {\n yield* parseCodexJsonl(file.filePath, { session: file.session, since: options?.since });\n }\n },\n async *usage(options?: AdapterOptions): AsyncGenerator<UsageRecord> {\n const seenUsage = new Set<string>();\n for await (const file of discoverCodexSessionFiles(CODEX_SESSIONS_DIR)) {\n for await (const record of parseCodexUsageJsonl(file.filePath, {\n session: file.session,\n since: options?.since,\n })) {\n const key = codexUsageRecordKey(record);\n if (seenUsage.has(key)) {\n continue;\n }\n seenUsage.add(key);\n yield record;\n }\n }\n },\n };\n}\n\nasync function* discoverCodexSessionFiles(\n dir: string,\n): AsyncGenerator<{ filePath: string; session: string }> {\n let entries: string[];\n try {\n entries = await readdir(dir);\n } catch {\n return;\n }\n\n for (const entry of entries) {\n const fullPath = join(dir, entry);\n const entryStat = await stat(fullPath);\n\n if (entryStat.isDirectory()) {\n yield* discoverCodexSessionFiles(fullPath);\n } else if (entry.endsWith(\".jsonl\")) {\n yield { filePath: fullPath, session: sessionFromRolloutFileName(entry) };\n }\n }\n}\n\nfunction sessionFromRolloutFileName(fileName: string): string {\n return (\n fileName.match(\n /([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\\.jsonl$/i,\n )?.[1] ?? fileName.replace(\".jsonl\", \"\")\n );\n}\n\nasync function* parseCodexJsonl(\n filePath: string,\n context: { session: string; since?: Date },\n): AsyncGenerator<Message> {\n const rl = createInterface({\n input: createReadStream(filePath, { encoding: \"utf-8\" }),\n crlfDelay: Infinity,\n });\n\n for await (const line of rl) {\n if (!line.trim()) {\n continue;\n }\n\n try {\n const entry = JSON.parse(line) as CodexEntry;\n\n // Only care about response_item entries with user messages\n if (entry.type !== \"response_item\") {\n continue;\n }\n\n const payload = entry.payload;\n if (!payload || payload.role !== \"user\") {\n continue;\n }\n\n const text = extractText(payload.content);\n if (!text) {\n continue;\n }\n\n // Skip environment context injections (they start with <environment_context>)\n if (text.startsWith(\"<environment_context>\")) {\n continue;\n }\n // Skip permission/sandbox instructions\n if (text.startsWith(\"<permissions instructions>\")) {\n continue;\n }\n\n if (context.since && entry.timestamp) {\n const ts = new Date(entry.timestamp);\n if (ts < context.since) {\n continue;\n }\n }\n\n yield {\n text,\n timestamp: entry.timestamp,\n session: context.session,\n };\n } catch {\n // Skip malformed lines\n }\n }\n}\n\nfunction extractText(content: unknown): string | null {\n if (!Array.isArray(content)) {\n return null;\n }\n\n const parts = content\n .filter(\n (p): p is { type: string; text: string } =>\n typeof p === \"object\" &&\n p !== null &&\n p.type === \"input_text\" &&\n typeof p.text === \"string\",\n )\n .map((p) => p.text);\n\n return parts.length > 0 ? parts.join(\" \") : null;\n}\n\ninterface CodexEntry {\n timestamp?: string;\n type: string;\n payload?: {\n type?: string;\n role?: string;\n content?: unknown;\n };\n}\n\ninterface CodexTokenUsage {\n inputTokens: number;\n cachedInputTokens: number;\n outputTokens: number;\n reasoningOutputTokens: number;\n totalTokens: number;\n}\n\n/** Codex token_count events include both cumulative totals and the last completed response. */\nasync function* parseCodexUsageJsonl(\n filePath: string,\n context: { session: string; since?: Date },\n): AsyncGenerator<UsageRecord> {\n const rl = createInterface({\n input: createReadStream(filePath, { encoding: \"utf-8\" }),\n crlfDelay: Infinity,\n });\n let model: string | undefined;\n let previousTotal: CodexTokenUsage | null = null;\n let previousUsageSignature: string | null = null;\n let session = context.session;\n let sawSessionMeta = false;\n\n for await (const line of rl) {\n if (!line.trim()) {\n continue;\n }\n\n try {\n const entry = JSON.parse(line) as Record<string, unknown>;\n const payload = asRecord(entry[\"payload\"]);\n\n if (entry[\"type\"] === \"session_meta\") {\n const metaSession = stringValue(payload?.[\"id\"]) ?? stringValue(entry[\"id\"]);\n if (metaSession && !sawSessionMeta) {\n session = metaSession;\n sawSessionMeta = true;\n }\n continue;\n }\n\n if (entry[\"type\"] === \"turn_context\") {\n model = stringValue(payload?.[\"model\"]) ?? model;\n continue;\n }\n\n if (entry[\"type\"] !== \"event_msg\" || payload?.[\"type\"] !== \"token_count\") {\n continue;\n }\n\n const info = asRecord(payload[\"info\"]);\n if (!info) {\n continue;\n }\n\n const lastUsageValue = info[\"last_token_usage\"];\n const lastUsage = parseCodexTokenUsage(lastUsageValue);\n const total = parseCodexTokenUsage(info[\"total_token_usage\"]);\n let usage: CodexTokenUsage | null = null;\n\n if (lastUsageValue !== undefined) {\n if (lastUsage && hasBillableUsage(lastUsage)) {\n const signature = codexUsageSignature(lastUsage, total);\n if (signature !== previousUsageSignature) {\n usage = lastUsage;\n }\n previousUsageSignature = signature;\n }\n } else if (total) {\n const delta = previousTotal ? subtractCodexUsage(total, previousTotal) : total;\n if (hasBillableUsage(delta)) {\n usage = delta;\n }\n }\n if (total && hasBillableUsage(total)) {\n previousTotal = total;\n }\n if (!usage) {\n continue;\n }\n\n const timestamp = stringValue(entry[\"timestamp\"]);\n if (context.since && timestamp) {\n const ts = new Date(timestamp);\n if (ts < context.since) {\n continue;\n }\n }\n\n const reasoningTokens = Math.min(usage.reasoningOutputTokens, usage.outputTokens);\n yield {\n agent: \"codex\",\n provider: \"openai\",\n model,\n timestamp,\n session,\n inputTokens: Math.max(usage.inputTokens - usage.cachedInputTokens, 0),\n outputTokens: Math.max(usage.outputTokens - reasoningTokens, 0),\n reasoningTokens,\n cacheReadTokens: usage.cachedInputTokens,\n cacheWriteTokens: 0,\n };\n } catch {\n // Skip malformed lines\n }\n }\n}\n\nfunction codexUsageRecordKey(record: UsageRecord): string {\n return JSON.stringify([\n record.session ?? \"\",\n record.timestamp ?? \"\",\n record.provider ?? \"\",\n record.model ?? \"\",\n record.inputTokens,\n record.outputTokens,\n record.reasoningTokens,\n record.cacheReadTokens,\n record.cacheWriteTokens,\n ]);\n}\n\nfunction parseCodexTokenUsage(value: unknown): CodexTokenUsage | null {\n const usage = asRecord(value);\n if (!usage) {\n return null;\n }\n\n const hasUsageField = [\n \"input_tokens\",\n \"cached_input_tokens\",\n \"output_tokens\",\n \"reasoning_output_tokens\",\n \"total_tokens\",\n ].some((key) => typeof usage[key] === \"number\" && Number.isFinite(usage[key]));\n if (!hasUsageField) {\n return null;\n }\n\n return {\n inputTokens: numberValue(usage[\"input_tokens\"]),\n cachedInputTokens: numberValue(usage[\"cached_input_tokens\"]),\n outputTokens: numberValue(usage[\"output_tokens\"]),\n reasoningOutputTokens: numberValue(usage[\"reasoning_output_tokens\"]),\n totalTokens: numberValue(usage[\"total_tokens\"]),\n };\n}\n\nfunction subtractCodexUsage(current: CodexTokenUsage, previous: CodexTokenUsage): CodexTokenUsage {\n return {\n inputTokens: Math.max(current.inputTokens - previous.inputTokens, 0),\n cachedInputTokens: Math.max(current.cachedInputTokens - previous.cachedInputTokens, 0),\n outputTokens: Math.max(current.outputTokens - previous.outputTokens, 0),\n reasoningOutputTokens: Math.max(\n current.reasoningOutputTokens - previous.reasoningOutputTokens,\n 0,\n ),\n totalTokens: Math.max(current.totalTokens - previous.totalTokens, 0),\n };\n}\n\nfunction hasBillableUsage(usage: CodexTokenUsage): boolean {\n return (\n usage.inputTokens + usage.cachedInputTokens + usage.outputTokens + usage.reasoningOutputTokens >\n 0\n );\n}\n\nfunction codexUsageSignature(usage: CodexTokenUsage, total: CodexTokenUsage | null): string {\n return [\n usage.inputTokens,\n usage.cachedInputTokens,\n usage.outputTokens,\n usage.reasoningOutputTokens,\n total?.inputTokens ?? \"\",\n total?.cachedInputTokens ?? \"\",\n total?.outputTokens ?? \"\",\n total?.reasoningOutputTokens ?? \"\",\n ].join(\":\");\n}\n\nfunction numberValue(value: unknown): number {\n return typeof value === \"number\" && Number.isFinite(value) ? value : 0;\n}\n\nfunction stringValue(value: unknown): string | undefined {\n return typeof value === \"string\" && value.trim() ? value : undefined;\n}\n\nfunction asRecord(value: unknown): Record<string, unknown> | null {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n return null;\n }\n\n return value as Record<string, unknown>;\n}\n", "import { existsSync } from \"node:fs\";\nimport { readdir } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport type { Adapter, AdapterOptions, Message, UsageRecord } from \"./index\";\n\n/**\n * Reads Cursor's VS Code-style state stores read-only. Extraction is limited to\n * known AI keys and confident user-authored message shapes; unreadable DBs skip.\n */\n\nconst CANDIDATE_KEY_PREFIXES = [\n \"bubbleId:\",\n \"composerData:\",\n \"composer.composerData\",\n \"aiService.prompts\",\n \"aiService.generations\",\n \"workbench.panel.composerChatViewPane.\",\n];\n\nconst STATE_TABLES = [\"ItemTable\", \"cursorDiskKV\"];\n\ninterface CursorStateStore {\n path: string;\n scope: string;\n project?: string;\n}\n\ninterface StateRow {\n key: string;\n value: unknown;\n}\n\ninterface ExtractedMessage {\n text: string;\n timestamp?: string;\n session?: string;\n}\n\nexport function cursorAdapter(): Adapter {\n return {\n name: \"cursor\",\n async *messages(options?: AdapterOptions): AsyncGenerator<Message> {\n const stores = await discoverCursorStateStores();\n\n for (const store of stores) {\n yield* parseCursorStore(store, options);\n }\n },\n async *usage(options?: AdapterOptions): AsyncGenerator<UsageRecord> {\n const stores = await discoverCursorStateStores();\n\n for (const store of stores) {\n yield* parseCursorUsageStore(store, options);\n }\n },\n };\n}\n\nasync function discoverCursorStateStores(): Promise<CursorStateStore[]> {\n const stores: CursorStateStore[] = [];\n const seen = new Set<string>();\n\n for (const userDir of getCursorUserDirs()) {\n if (!existsSync(userDir)) {\n continue;\n }\n\n const globalState = join(userDir, \"globalStorage\", \"state.vscdb\");\n if (existsSync(globalState) && !seen.has(globalState)) {\n seen.add(globalState);\n stores.push({ path: globalState, scope: \"global\" });\n }\n\n const workspaceRoot = join(userDir, \"workspaceStorage\");\n let workspaceIds: string[] = [];\n try {\n workspaceIds = await readdir(workspaceRoot);\n } catch {\n continue;\n }\n\n for (const workspaceId of workspaceIds) {\n const statePath = join(workspaceRoot, workspaceId, \"state.vscdb\");\n if (existsSync(statePath) && !seen.has(statePath)) {\n seen.add(statePath);\n stores.push({ path: statePath, scope: \"workspace\", project: workspaceId });\n }\n }\n }\n\n return stores;\n}\n\nfunction getCursorUserDirs(): string[] {\n const configHome = envOrDefault(\"XDG_CONFIG_HOME\", join(homedir(), \".config\"));\n const appData = envOrDefault(\"APPDATA\", join(homedir(), \"AppData\", \"Roaming\"));\n\n return uniqueStrings([\n join(homedir(), \"Library\", \"Application Support\", \"Cursor\", \"User\"),\n join(configHome, \"Cursor\", \"User\"),\n join(appData, \"Cursor\", \"User\"),\n ]);\n}\n\nasync function* parseCursorStore(\n store: CursorStateStore,\n options?: AdapterOptions,\n): AsyncGenerator<Message> {\n const db = await openCursorDb(store.path);\n if (!db) {\n return;\n }\n\n try {\n const rows = readStateRows(db);\n const seen = new Set<string>();\n\n for (const row of rows) {\n try {\n if (!isCandidateKey(row.key)) {\n continue;\n }\n\n const parsed = parseJsonValue(row.value);\n if (parsed === undefined) {\n continue;\n }\n\n for (const message of extractCursorMessages(parsed, row.key)) {\n const text = message.text.trim();\n if (!isLikelyMessageText(text)) {\n continue;\n }\n\n if (options?.since && message.timestamp) {\n const timestamp = new Date(message.timestamp);\n if (Number.isFinite(timestamp.getTime()) && timestamp < options.since) {\n continue;\n }\n }\n\n const session = message.session ?? `${store.scope}:${row.key}`;\n const dedupeKey = `${session}\\u0000${message.timestamp ?? \"\"}\\u0000${text}`;\n if (seen.has(dedupeKey)) {\n continue;\n }\n seen.add(dedupeKey);\n\n yield {\n text,\n timestamp: message.timestamp,\n session,\n project: store.project,\n };\n }\n } catch {\n continue;\n }\n }\n } finally {\n db.close();\n }\n}\n\nasync function* parseCursorUsageStore(\n store: CursorStateStore,\n options?: AdapterOptions,\n): AsyncGenerator<UsageRecord> {\n const db = await openCursorDb(store.path);\n if (!db) {\n return;\n }\n\n try {\n const rows = readStateRows(db);\n const composerModels = collectComposerModels(rows);\n const seen = new Set<string>();\n\n for (const row of rows) {\n try {\n if (!row.key.startsWith(\"bubbleId:\")) {\n continue;\n }\n\n const parsed = parseJsonValue(row.value);\n const usage = extractCursorBubbleUsage(parsed, row.key, composerModels);\n if (!usage) {\n continue;\n }\n\n if (options?.since && usage.timestamp) {\n const timestamp = new Date(usage.timestamp);\n if (Number.isFinite(timestamp.getTime()) && timestamp < options.since) {\n continue;\n }\n }\n\n const dedupeKey = `${usage.session ?? \"\"}\\u0000${usage.timestamp ?? \"\"}\\u0000${usage.model ?? \"\"}\\u0000${usage.inputTokens}\\u0000${usage.outputTokens}`;\n if (seen.has(dedupeKey)) {\n continue;\n }\n seen.add(dedupeKey);\n\n yield usage;\n } catch {\n continue;\n }\n }\n } finally {\n db.close();\n }\n}\n\nasync function openCursorDb(dbPath: string): Promise<import(\"better-sqlite3\").Database | null> {\n try {\n const BetterSqlite3 = await import(\"better-sqlite3\");\n const Ctor = BetterSqlite3.default ?? BetterSqlite3;\n return new (Ctor as unknown as new (...args: unknown[]) => import(\"better-sqlite3\").Database)(\n dbPath,\n { readonly: true },\n );\n } catch {\n return null;\n }\n}\n\nfunction readStateRows(db: import(\"better-sqlite3\").Database): StateRow[] {\n const rows: StateRow[] = [];\n\n try {\n const tables = db.prepare(\"SELECT name FROM sqlite_master WHERE type = 'table'\").all() as {\n name: unknown;\n }[];\n const availableTables = new Set(tables.flatMap((table) => stringValue(table.name) ?? []));\n\n for (const table of STATE_TABLES) {\n if (!availableTables.has(table)) {\n continue;\n }\n\n const columns = db.prepare(`PRAGMA table_info(\"${table}\")`).all() as { name: unknown }[];\n const columnNames = new Set(columns.flatMap((column) => stringValue(column.name) ?? []));\n if (!columnNames.has(\"key\") || !columnNames.has(\"value\")) {\n continue;\n }\n\n const tableRows = db.prepare(`SELECT key, value FROM \"${table}\"`).all() as {\n key: unknown;\n value: unknown;\n }[];\n rows.push(\n ...tableRows.flatMap((row) =>\n typeof row.key === \"string\" ? [{ key: row.key, value: row.value }] : [],\n ),\n );\n }\n } catch {\n return rows;\n }\n\n return rows;\n}\n\nfunction isCandidateKey(key: string): boolean {\n return CANDIDATE_KEY_PREFIXES.some((prefix) => key === prefix || key.startsWith(prefix));\n}\n\nfunction parseJsonValue(value: unknown): unknown | undefined {\n const raw = decodeStateValue(value);\n if (!raw) {\n return undefined;\n }\n\n try {\n const parsed = JSON.parse(raw) as unknown;\n if (typeof parsed !== \"string\") {\n return parsed;\n }\n\n const trimmed = parsed.trim();\n if (!trimmed.startsWith(\"{\") && !trimmed.startsWith(\"[\")) {\n return parsed;\n }\n\n try {\n return JSON.parse(trimmed) as unknown;\n } catch {\n return parsed;\n }\n } catch {\n return undefined;\n }\n}\n\nfunction decodeStateValue(value: unknown): string | null {\n if (typeof value === \"string\") {\n return value;\n }\n\n if (Buffer.isBuffer(value)) {\n return value.toString(\"utf-8\");\n }\n\n return null;\n}\n\nfunction extractCursorMessages(root: unknown, rowKey: string): ExtractedMessage[] {\n if (rowKey.startsWith(\"bubbleId:\")) {\n const message = extractCursorBubbleMessage(root, rowKey);\n return message ? [message] : [];\n }\n\n const messages: ExtractedMessage[] = [];\n collectRoleMessages(root, messages);\n\n if (rowKey.startsWith(\"aiService.prompts\") || rowKey.startsWith(\"aiService.generations\")) {\n collectPromptMessages(root, messages);\n }\n\n return uniqueMessages(messages);\n}\n\nfunction extractCursorBubbleMessage(root: unknown, rowKey: string): ExtractedMessage | null {\n const record = asRecord(root);\n if (!record || numberValue(record[\"type\"]) !== 1) {\n return null;\n }\n\n const text = firstTextField(record, [\"text\", \"richText\"]);\n if (!text) {\n return null;\n }\n\n return {\n text,\n timestamp: extractTimestamp(record),\n session: cursorBubbleSession(rowKey) ?? extractSession(record),\n };\n}\n\nfunction collectComposerModels(rows: StateRow[]): Map<string, string> {\n const models = new Map<string, string>();\n\n for (const row of rows) {\n if (!row.key.startsWith(\"composerData:\")) {\n continue;\n }\n\n const parsed = parseJsonValue(row.value);\n const record = asRecord(parsed);\n if (!record) {\n continue;\n }\n\n const composerId = stringValue(record[\"composerId\"]) ?? row.key.slice(\"composerData:\".length);\n const model = extractCursorModel(record);\n if (composerId && model) {\n models.set(composerId, model);\n }\n }\n\n return models;\n}\n\nfunction extractCursorBubbleUsage(\n root: unknown,\n rowKey: string,\n composerModels: Map<string, string>,\n): UsageRecord | null {\n const record = asRecord(root);\n if (!record || numberValue(record[\"type\"]) !== 2) {\n return null;\n }\n\n const tokenCount = asRecord(record[\"tokenCount\"]);\n if (!tokenCount) {\n return null;\n }\n\n const inputTokens = numberValue(tokenCount[\"inputTokens\"] ?? tokenCount[\"input\"]);\n const outputTokens = numberValue(tokenCount[\"outputTokens\"] ?? tokenCount[\"output\"]);\n const cacheReadTokens = numberValue(tokenCount[\"cacheReadTokens\"] ?? tokenCount[\"cacheRead\"]);\n const cacheWriteTokens = numberValue(tokenCount[\"cacheWriteTokens\"] ?? tokenCount[\"cacheWrite\"]);\n if (inputTokens + outputTokens + cacheReadTokens + cacheWriteTokens === 0) {\n return null;\n }\n\n const composerId = cursorBubbleSession(rowKey);\n const model =\n extractCursorModel(record) ?? (composerId ? composerModels.get(composerId) : undefined);\n\n return {\n agent: \"cursor\",\n model,\n timestamp: extractTimestamp(record),\n session: composerId ?? extractSession(record),\n inputTokens,\n outputTokens,\n reasoningTokens: numberValue(tokenCount[\"reasoningTokens\"] ?? tokenCount[\"reasoning\"]),\n cacheReadTokens,\n cacheWriteTokens,\n };\n}\n\nfunction extractCursorModel(record: Record<string, unknown>): string | undefined {\n const direct = firstStringField(record, [\"model\", \"modelName\", \"modelId\"]);\n if (direct) {\n return direct;\n }\n\n for (const field of [\"modelInfo\", \"modelConfig\"]) {\n const modelRecord = asRecord(record[field]);\n if (!modelRecord) {\n continue;\n }\n\n const nested = firstStringField(modelRecord, [\"modelName\", \"modelId\", \"id\", \"name\"]);\n if (nested && nested !== \"default\") {\n return nested;\n }\n\n const selected = modelRecord[\"selectedModels\"];\n if (Array.isArray(selected)) {\n for (const item of selected) {\n const itemRecord = asRecord(item);\n const selectedModel = itemRecord\n ? firstStringField(itemRecord, [\"modelId\", \"modelName\", \"id\", \"name\"])\n : undefined;\n if (selectedModel && selectedModel !== \"default\") {\n return selectedModel;\n }\n }\n }\n\n if (nested) {\n return nested;\n }\n }\n\n return undefined;\n}\n\nfunction cursorBubbleSession(rowKey: string): string | undefined {\n const [, composerId] = rowKey.split(\":\");\n return composerId?.trim() || undefined;\n}\n\nfunction collectRoleMessages(\n value: unknown,\n messages: ExtractedMessage[],\n inheritedSession?: string,\n depth = 0,\n): void {\n if (depth > 12) {\n return;\n }\n\n if (Array.isArray(value)) {\n for (const item of value) {\n collectRoleMessages(item, messages, inheritedSession, depth + 1);\n }\n return;\n }\n\n const record = asRecord(value);\n if (!record) {\n return;\n }\n\n const session = extractSession(record) ?? inheritedSession;\n if (isUserAuthored(record)) {\n const text = extractMessageText(record);\n if (text) {\n messages.push({ text, timestamp: extractTimestamp(record), session });\n }\n }\n\n for (const child of Object.values(record)) {\n if (typeof child === \"object\" && child !== null) {\n collectRoleMessages(child, messages, session, depth + 1);\n }\n }\n}\n\nfunction collectPromptMessages(\n value: unknown,\n messages: ExtractedMessage[],\n inheritedSession?: string,\n depth = 0,\n): void {\n if (depth > 12) {\n return;\n }\n\n if (typeof value === \"string\") {\n messages.push({ text: value, session: inheritedSession });\n return;\n }\n\n if (Array.isArray(value)) {\n for (const item of value) {\n collectPromptMessages(item, messages, inheritedSession, depth + 1);\n }\n return;\n }\n\n const record = asRecord(value);\n if (!record) {\n return;\n }\n\n const session = extractSession(record) ?? inheritedSession;\n const prompt = firstTextField(record, [\n \"prompt\",\n \"userPrompt\",\n \"originalPrompt\",\n \"currentPrompt\",\n \"query\",\n \"input\",\n ]);\n\n if (prompt && !isAssistantAuthored(record)) {\n messages.push({ text: prompt, timestamp: extractTimestamp(record), session });\n }\n\n for (const child of Object.values(record)) {\n if (typeof child === \"object\" && child !== null) {\n collectPromptMessages(child, messages, session, depth + 1);\n }\n }\n}\n\nfunction isUserAuthored(record: Record<string, unknown>): boolean {\n return [\"role\", \"speaker\", \"sender\", \"author\", \"source\", \"from\", \"type\", \"kind\"].some((field) =>\n actorIsUser(record[field]),\n );\n}\n\nfunction isAssistantAuthored(record: Record<string, unknown>): boolean {\n return [\"role\", \"speaker\", \"sender\", \"author\", \"source\", \"from\", \"type\", \"kind\"].some((field) =>\n actorIsAssistant(record[field]),\n );\n}\n\nfunction actorIsUser(value: unknown): boolean {\n const actor = actorString(value);\n return actor === \"user\" || actor === \"human\" || actor === \"usermessage\";\n}\n\nfunction actorIsAssistant(value: unknown): boolean {\n const actor = actorString(value);\n return actor === \"assistant\" || actor === \"ai\" || actor === \"assistantmessage\";\n}\n\nfunction actorString(value: unknown): string | null {\n if (typeof value === \"string\") {\n return value.toLowerCase().replace(/[^a-z]/g, \"\");\n }\n\n const record = asRecord(value);\n if (!record) {\n return null;\n }\n\n for (const field of [\"role\", \"type\", \"name\"]) {\n if (typeof record[field] === \"string\") {\n return record[field].toLowerCase().replace(/[^a-z]/g, \"\");\n }\n }\n\n return null;\n}\n\nfunction extractMessageText(record: Record<string, unknown>): string | null {\n return firstTextField(record, [\"text\", \"content\", \"message\", \"prompt\", \"query\", \"input\"]);\n}\n\nfunction firstTextField(record: Record<string, unknown>, fields: string[]): string | null {\n for (const field of fields) {\n const text = contentToText(record[field]);\n if (text) {\n return text;\n }\n }\n\n return null;\n}\n\nfunction firstStringField(record: Record<string, unknown>, fields: string[]): string | undefined {\n for (const field of fields) {\n const value = stringValue(record[field]);\n if (value) {\n return value;\n }\n }\n\n return undefined;\n}\n\nfunction contentToText(value: unknown): string | null {\n if (typeof value === \"string\") {\n return value;\n }\n\n if (Array.isArray(value)) {\n const parts = value.map(contentToText).filter((part): part is string => Boolean(part));\n return parts.length > 0 ? parts.join(\" \") : null;\n }\n\n const record = asRecord(value);\n if (!record) {\n return null;\n }\n\n return firstTextField(record, [\"text\", \"content\", \"message\", \"value\"]);\n}\n\nfunction extractTimestamp(record: Record<string, unknown>): string | undefined {\n for (const field of [\"timestamp\", \"createdAt\", \"updatedAt\", \"time\", \"created\", \"date\", \"ts\"]) {\n const timestamp = normalizeTimestamp(record[field]);\n if (timestamp) {\n return timestamp;\n }\n }\n\n return undefined;\n}\n\nfunction normalizeTimestamp(value: unknown): string | undefined {\n if (typeof value === \"string\") {\n const date = new Date(value);\n return Number.isFinite(date.getTime()) ? date.toISOString() : undefined;\n }\n\n if (typeof value === \"number\" && Number.isFinite(value)) {\n const milliseconds = value > 1_000_000_000_000 ? value : value * 1000;\n const date = new Date(milliseconds);\n return Number.isFinite(date.getTime()) ? date.toISOString() : undefined;\n }\n\n return undefined;\n}\n\nfunction extractSession(record: Record<string, unknown>): string | undefined {\n for (const field of [\"conversationId\", \"composerId\", \"sessionId\", \"chatId\", \"threadId\", \"id\"]) {\n const value = record[field];\n if (typeof value === \"string\" && value.trim()) {\n return value;\n }\n }\n\n return undefined;\n}\n\nfunction isLikelyMessageText(text: string): boolean {\n return text.length > 0 && !text.startsWith(\"<environment_context>\");\n}\n\nfunction uniqueMessages(messages: ExtractedMessage[]): ExtractedMessage[] {\n const seen = new Set<string>();\n const unique: ExtractedMessage[] = [];\n\n for (const message of messages) {\n const key = `${message.session ?? \"\"}\\u0000${message.timestamp ?? \"\"}\\u0000${message.text}`;\n if (seen.has(key)) {\n continue;\n }\n\n seen.add(key);\n unique.push(message);\n }\n\n return unique;\n}\n\nfunction uniqueStrings(values: string[]): string[] {\n return Array.from(new Set(values));\n}\n\nfunction envOrDefault(name: string, fallback: string): string {\n const value = process.env[name];\n return value && value.trim() ? value : fallback;\n}\n\nfunction numberValue(value: unknown): number {\n return typeof value === \"number\" && Number.isFinite(value) ? value : 0;\n}\n\nfunction stringValue(value: unknown): string | undefined {\n return typeof value === \"string\" && value.trim() ? value : undefined;\n}\n\nfunction asRecord(value: unknown): Record<string, unknown> | null {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n return null;\n }\n\n return value as Record<string, unknown>;\n}\n", "import { existsSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport type { Adapter, AdapterOptions, Message, UsageRecord } from \"./index\";\n\n/**\n * OpenCode stores sessions in a SQLite database at:\n * ~/.local/share/opencode/opencode.db\n *\n * Schema:\n * message: { id, session_id, time_created (epoch ms), time_updated, data (JSON) }\n * part: { id, message_id, session_id, time_created, time_updated, data (JSON) }\n *\n * message.data: { \"role\": \"user\"|\"assistant\", \"time\": {...}, \"agent\": \"...\", ... }\n * part.data: { \"type\": \"text\", \"text\": \"the user's message\" }\n *\n * User messages have role=\"user\" in message.data. The actual text content is in\n * the associated part rows where part.data.type === \"text\".\n */\n\nfunction getOpencodeDatabasePath(): string | null {\n // macOS: ~/.local/share/opencode/opencode.db (despite XDG, this is where it actually lives)\n const xdgPath = join(\n process.env[\"XDG_DATA_HOME\"] ?? join(homedir(), \".local\", \"share\"),\n \"opencode\",\n \"opencode.db\",\n );\n if (existsSync(xdgPath)) {\n return xdgPath;\n }\n\n // macOS Application Support fallback\n if (process.platform === \"darwin\") {\n const macPath = join(homedir(), \"Library\", \"Application Support\", \"opencode\", \"opencode.db\");\n if (existsSync(macPath)) {\n return macPath;\n }\n }\n\n return null;\n}\n\nexport function opencodeAdapter(): Adapter {\n return {\n name: \"opencode\",\n async *messages(options?: AdapterOptions): AsyncGenerator<Message> {\n const db = await openOpencodeDb();\n if (!db) {\n return;\n }\n\n try {\n yield* queryUserMessages(db, options);\n } finally {\n db.close();\n }\n },\n async *usage(options?: AdapterOptions): AsyncGenerator<UsageRecord> {\n const db = await openOpencodeDb();\n if (!db) {\n return;\n }\n\n try {\n yield* queryUsageRecords(db, options);\n } finally {\n db.close();\n }\n },\n };\n}\n\nasync function openOpencodeDb(): Promise<import(\"better-sqlite3\").Database | null> {\n const dbPath = getOpencodeDatabasePath();\n if (!dbPath) {\n return null;\n }\n\n // Dynamic import so the CLI doesn't crash if better-sqlite3 isn't available\n try {\n const BetterSqlite3 = await import(\"better-sqlite3\");\n const Ctor = BetterSqlite3.default ?? BetterSqlite3;\n return new (Ctor as unknown as new (...args: unknown[]) => import(\"better-sqlite3\").Database)(\n dbPath,\n { readonly: true },\n );\n } catch {\n console.warn(\"devrage: better-sqlite3 not available, skipping OpenCode sessions\");\n return null;\n }\n}\n\nfunction* queryUserMessages(\n db: import(\"better-sqlite3\").Database,\n options?: AdapterOptions,\n): Generator<Message> {\n // Query: join message + part, filter to user role and text parts\n let query = `\n SELECT\n m.session_id,\n m.time_created,\n json_extract(p.data, '$.text') as text\n FROM message m\n JOIN part p ON p.message_id = m.id\n WHERE json_extract(m.data, '$.role') = 'user'\n AND json_extract(p.data, '$.type') = 'text'\n `;\n\n const params: unknown[] = [];\n if (options?.since) {\n query += ` AND m.time_created >= ?`;\n params.push(options.since.getTime());\n }\n\n query += ` ORDER BY m.time_created ASC`;\n\n const rows = db.prepare(query).all(...params) as {\n session_id: string;\n time_created: number;\n text: string;\n }[];\n\n for (const row of rows) {\n if (!row.text || !row.text.trim()) {\n continue;\n }\n\n yield {\n text: row.text,\n timestamp: new Date(row.time_created).toISOString(),\n session: row.session_id,\n };\n }\n}\n\n/** OpenCode assistant messages store provider/model, billed cost, and token usage in message.data. */\nfunction* queryUsageRecords(\n db: import(\"better-sqlite3\").Database,\n options?: AdapterOptions,\n): Generator<UsageRecord> {\n let where = `WHERE json_type(data, '$.tokens') = 'object'`;\n const params: unknown[] = [];\n\n if (options?.since) {\n where += ` AND time_created >= ?`;\n params.push(options.since.getTime());\n }\n\n const rows = db\n .prepare(`\n SELECT\n session_id,\n time_created,\n COALESCE(json_extract(data, '$.providerID'), json_extract(data, '$.model.providerID')) AS provider,\n COALESCE(json_extract(data, '$.modelID'), json_extract(data, '$.model.modelID')) AS model,\n json_extract(data, '$.cost') AS billed_cost,\n json_extract(data, '$.tokens.input') AS input_tokens,\n json_extract(data, '$.tokens.output') AS output_tokens,\n json_extract(data, '$.tokens.reasoning') AS reasoning_tokens,\n json_extract(data, '$.tokens.cache.read') AS cache_read_tokens,\n json_extract(data, '$.tokens.cache.write') AS cache_write_tokens\n FROM message\n ${where}\n ORDER BY time_created ASC\n `)\n .all(...params) as {\n session_id: string | null;\n time_created: number | null;\n provider: string | null;\n model: string | null;\n billed_cost: number | null;\n input_tokens: number | null;\n output_tokens: number | null;\n reasoning_tokens: number | null;\n cache_read_tokens: number | null;\n cache_write_tokens: number | null;\n }[];\n\n for (const row of rows) {\n const inputTokens = numberValue(row.input_tokens);\n const outputTokens = numberValue(row.output_tokens);\n const reasoningTokens = numberValue(row.reasoning_tokens);\n const cacheReadTokens = numberValue(row.cache_read_tokens);\n const cacheWriteTokens = numberValue(row.cache_write_tokens);\n const billedCost = numberValue(row.billed_cost);\n\n if (\n inputTokens + outputTokens + reasoningTokens + cacheReadTokens + cacheWriteTokens === 0 &&\n billedCost === 0\n ) {\n continue;\n }\n\n yield {\n agent: \"opencode\",\n provider: stringValue(row.provider),\n model: stringValue(row.model),\n timestamp: row.time_created ? new Date(row.time_created).toISOString() : undefined,\n session: stringValue(row.session_id),\n billedCost,\n inputTokens,\n outputTokens,\n reasoningTokens,\n cacheReadTokens,\n cacheWriteTokens,\n };\n }\n}\n\nfunction numberValue(value: unknown): number {\n return typeof value === \"number\" && Number.isFinite(value) ? value : 0;\n}\n\nfunction stringValue(value: unknown): string | undefined {\n return typeof value === \"string\" && value.trim() ? value : undefined;\n}\n", "import { createReadStream } from \"node:fs\";\nimport { readdir, stat } from \"node:fs/promises\";\nimport { createInterface } from \"node:readline\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport type { Adapter, AdapterOptions, Message, UsageRecord } from \"./index\";\n\n/**\n * Pi Agent stores sessions as JSONL files at:\n * ~/.pi/agent/sessions/<project>/<session-id>.jsonl\n *\n * Each line is a JSON object:\n * { \"type\": \"session\", \"cwd\": \"/path/to/project\" } \u2014 session metadata\n * { \"type\": \"message\", \"timestamp\": \"...\", \"message\": { \"role\": \"user\", \"content\": \"...\" } }\n *\n * Content can be a string or array of { type: \"text\", text: \"...\" } parts.\n */\n\nconst PI_SESSIONS_DIR = join(homedir(), \".pi\", \"agent\", \"sessions\");\n\nexport function piAdapter(): Adapter {\n return {\n name: \"pi\",\n async *messages(options?: AdapterOptions): AsyncGenerator<Message> {\n yield* walkPiSessions(PI_SESSIONS_DIR, options);\n },\n async *usage(options?: AdapterOptions): AsyncGenerator<UsageRecord> {\n yield* walkPiUsageSessions(PI_SESSIONS_DIR, options);\n },\n };\n}\n\nasync function* walkPiSessions(\n dir: string,\n options?: AdapterOptions,\n project?: string,\n): AsyncGenerator<Message> {\n let entries: string[];\n try {\n entries = await readdir(dir);\n } catch {\n return;\n }\n\n for (const entry of entries) {\n const fullPath = join(dir, entry);\n const entryStat = await stat(fullPath).catch(() => null);\n if (!entryStat) {\n continue;\n }\n\n if (entryStat.isDirectory()) {\n yield* walkPiSessions(fullPath, options, project ?? entry);\n } else if (entry.endsWith(\".jsonl\")) {\n const session = entry.replace(\".jsonl\", \"\");\n yield* parsePiJsonl(fullPath, { session, project, since: options?.since });\n }\n }\n}\n\nasync function* walkPiUsageSessions(\n dir: string,\n options?: AdapterOptions,\n project?: string,\n): AsyncGenerator<UsageRecord> {\n let entries: string[];\n try {\n entries = await readdir(dir);\n } catch {\n return;\n }\n\n for (const entry of entries) {\n const fullPath = join(dir, entry);\n const entryStat = await stat(fullPath).catch(() => null);\n if (!entryStat) {\n continue;\n }\n\n if (entryStat.isDirectory()) {\n yield* walkPiUsageSessions(fullPath, options, project ?? entry);\n } else if (entry.endsWith(\".jsonl\")) {\n const session = entry.replace(\".jsonl\", \"\");\n yield* parsePiUsageJsonl(fullPath, { session, project, since: options?.since });\n }\n }\n}\n\nasync function* parsePiJsonl(\n filePath: string,\n context: { session: string; project?: string; since?: Date },\n): AsyncGenerator<Message> {\n const rl = createInterface({\n input: createReadStream(filePath, { encoding: \"utf-8\" }),\n crlfDelay: Infinity,\n });\n\n let project = context.project;\n\n for await (const line of rl) {\n if (!line.trim()) {\n continue;\n }\n\n try {\n const entry = JSON.parse(line) as PiEntry;\n\n // Session metadata line carries cwd\n if (entry.type === \"session\") {\n project = entry.cwd ?? project;\n continue;\n }\n\n if (entry.type !== \"message\") {\n continue;\n }\n\n const message = entry.message;\n if (!message || message.role !== \"user\") {\n continue;\n }\n\n const text = contentToString(message.content);\n if (!text) {\n continue;\n }\n\n const timestamp =\n typeof entry.timestamp === \"string\"\n ? entry.timestamp\n : typeof message.timestamp === \"number\"\n ? new Date(message.timestamp).toISOString()\n : undefined;\n\n if (context.since && timestamp) {\n const ts = new Date(timestamp);\n if (ts < context.since) {\n continue;\n }\n }\n\n yield {\n text,\n timestamp,\n session: context.session,\n project,\n };\n } catch {\n // Skip malformed lines\n }\n }\n}\n\nasync function* parsePiUsageJsonl(\n filePath: string,\n context: { session: string; project?: string; since?: Date },\n): AsyncGenerator<UsageRecord> {\n const rl = createInterface({\n input: createReadStream(filePath, { encoding: \"utf-8\" }),\n crlfDelay: Infinity,\n });\n\n for await (const line of rl) {\n if (!line.trim()) {\n continue;\n }\n\n try {\n const entry = JSON.parse(line) as PiEntry;\n if (entry.type !== \"message\") {\n continue;\n }\n\n const message = entry.message;\n if (!message || message.role !== \"assistant\") {\n continue;\n }\n\n const usage = asRecord(message.usage);\n if (!usage) {\n continue;\n }\n\n const inputTokens = numberValue(usage[\"input\"]);\n const outputTokens = numberValue(usage[\"output\"]);\n const cacheReadTokens = numberValue(usage[\"cacheRead\"]);\n const cacheWriteTokens = numberValue(usage[\"cacheWrite\"]);\n if (inputTokens + outputTokens + cacheReadTokens + cacheWriteTokens === 0) {\n continue;\n }\n\n const timestamp =\n typeof entry.timestamp === \"string\"\n ? entry.timestamp\n : typeof message.timestamp === \"number\"\n ? new Date(message.timestamp).toISOString()\n : undefined;\n if (context.since && timestamp) {\n const ts = new Date(timestamp);\n if (ts < context.since) {\n continue;\n }\n }\n\n const responseModel = stringValue(message.responseModel);\n const model = responseModel ?? stringValue(message.model);\n\n yield {\n agent: \"pi\",\n provider: responseModel?.includes(\"/\") ? undefined : stringValue(message.provider),\n model,\n timestamp,\n session: context.session,\n inputTokens,\n outputTokens,\n reasoningTokens: 0,\n cacheReadTokens,\n cacheWriteTokens,\n };\n } catch {\n // Skip malformed lines\n }\n }\n}\n\nfunction contentToString(content: unknown): string | null {\n if (typeof content === \"string\") {\n return content;\n }\n if (Array.isArray(content)) {\n const parts = content\n .filter(\n (p): p is { type: string; text: string } =>\n typeof p === \"object\" && p !== null && p.type === \"text\" && typeof p.text === \"string\",\n )\n .map((p) => p.text);\n return parts.length > 0 ? parts.join(\" \") : null;\n }\n return null;\n}\n\ninterface PiEntry {\n type?: string;\n timestamp?: string;\n cwd?: string;\n message?: {\n role?: string;\n content?: unknown;\n timestamp?: number;\n provider?: unknown;\n model?: unknown;\n responseModel?: unknown;\n usage?: unknown;\n };\n}\n\nfunction numberValue(value: unknown): number {\n return typeof value === \"number\" && Number.isFinite(value) ? value : 0;\n}\n\nfunction stringValue(value: unknown): string | undefined {\n return typeof value === \"string\" && value.trim() ? value : undefined;\n}\n\nfunction asRecord(value: unknown): Record<string, unknown> | null {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n return null;\n }\n\n return value as Record<string, unknown>;\n}\n", "import { readdir, readFile } from \"node:fs/promises\";\nimport { existsSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport type { Adapter, AdapterOptions, Message } from \"./index\";\n\n/**\n * Zed stores AI conversations in two places:\n *\n * 1. Text threads (older assistant panel):\n * ~/.local/share/zed/conversations/*.json (Linux)\n * ~/Library/Application Support/Zed/conversations/*.json (macOS)\n * These are markdown-like JSON with messages.\n *\n * 2. Agent threads (newer):\n * Stored in SQLite at ~/.local/share/zed/db (Linux)\n * or ~/Library/Application Support/Zed/db (macOS)\n * We'd need to query this, but the schema isn't well documented.\n *\n * We support the text thread JSON files for now, and the SQLite agent\n * threads when better-sqlite3 is available.\n */\n\nfunction getZedPaths(): { conversations: string; db: string } {\n if (process.platform === \"darwin\") {\n const base = join(homedir(), \"Library\", \"Application Support\", \"Zed\");\n return {\n conversations: join(base, \"conversations\"),\n db: join(base, \"db\"),\n };\n }\n // Linux / others\n const base = join(process.env[\"XDG_DATA_HOME\"] ?? join(homedir(), \".local\", \"share\"), \"zed\");\n return {\n conversations: join(base, \"conversations\"),\n db: join(base, \"db\"),\n };\n}\n\nexport function zedAdapter(): Adapter {\n return {\n name: \"zed\",\n async *messages(options?: AdapterOptions): AsyncGenerator<Message> {\n const paths = getZedPaths();\n\n // 1. Parse text thread JSON conversations\n yield* parseTextThreads(paths.conversations, options);\n\n // 2. Try SQLite agent threads\n yield* parseAgentThreads(paths.db, options);\n },\n };\n}\n\nasync function* parseTextThreads(dir: string, _options?: AdapterOptions): AsyncGenerator<Message> {\n if (!existsSync(dir)) {\n return;\n }\n\n let files: string[];\n try {\n files = await readdir(dir);\n } catch {\n return;\n }\n\n const jsonFiles = files.filter((f) => f.endsWith(\".json\"));\n\n for (const file of jsonFiles) {\n const filePath = join(dir, file);\n const session = file.replace(\".json\", \"\");\n\n try {\n const raw = await readFile(filePath, \"utf-8\");\n const conversation = JSON.parse(raw) as ZedConversation;\n\n if (!conversation.messages || !Array.isArray(conversation.messages)) {\n continue;\n }\n\n for (const msg of conversation.messages) {\n if (msg.role !== \"user\") {\n continue;\n }\n\n const text = typeof msg.content === \"string\" ? msg.content : null;\n if (!text) {\n continue;\n }\n\n yield {\n text,\n session,\n };\n }\n } catch {\n // Skip malformed files\n }\n }\n}\n\nasync function* parseAgentThreads(\n dbDir: string,\n _options?: AdapterOptions,\n): AsyncGenerator<Message> {\n // Zed uses a directory of SQLite databases. The main one is typically\n // a file like 0-dev.db or similar inside the db/ directory.\n if (!existsSync(dbDir)) {\n return;\n }\n\n let dbFiles: string[];\n try {\n const entries = await readdir(dbDir);\n dbFiles = entries.filter((f) => f.endsWith(\".db\"));\n } catch {\n return;\n }\n\n if (dbFiles.length === 0) {\n return;\n }\n\n let Database: unknown;\n try {\n const mod = await import(\"better-sqlite3\");\n Database = mod.default ?? mod;\n } catch {\n return; // better-sqlite3 not available\n }\n\n for (const dbFile of dbFiles) {\n const dbPath = join(dbDir, dbFile);\n let db: import(\"better-sqlite3\").Database;\n\n try {\n db = new (Database as new (...args: unknown[]) => import(\"better-sqlite3\").Database)(dbPath, {\n readonly: true,\n });\n } catch {\n continue; // Can't open this DB\n }\n\n try {\n // Check if this DB has a threads/messages table\n const tables = db.prepare(\"SELECT name FROM sqlite_master WHERE type='table'\").all() as {\n name: string;\n }[];\n const tableNames = tables.map((t) => t.name);\n\n // Look for message-like tables (Zed's schema may vary by version)\n const msgTable = tableNames.find(\n (t) => t === \"messages\" || t === \"thread_messages\" || t.includes(\"message\"),\n );\n\n if (!msgTable) {\n db.close();\n continue;\n }\n\n const columns = db.prepare(`PRAGMA table_info(\"${msgTable}\")`).all() as {\n name: string;\n }[];\n const colNames = columns.map((c) => c.name);\n\n const hasRole = colNames.includes(\"role\");\n\n if (!hasRole) {\n db.close();\n continue;\n }\n\n const contentCol = colNames.includes(\"content\")\n ? \"content\"\n : colNames.includes(\"body\")\n ? \"body\"\n : \"text\";\n\n let query = `SELECT \"${contentCol}\" as text FROM \"${msgTable}\" WHERE role = 'user'`;\n\n const rows = db.prepare(query).all() as { text: string }[];\n for (const row of rows) {\n if (!row.text?.trim()) {\n continue;\n }\n yield { text: row.text };\n }\n } catch {\n // Schema mismatch or other error\n } finally {\n db.close();\n }\n }\n}\n\ninterface ZedConversation {\n messages?: { role?: string; content?: unknown }[];\n}\n", "import { ampAdapter } from \"./amp\";\nimport { claudeAdapter } from \"./claude\";\nimport { clineAdapter } from \"./cline\";\nimport { codexAdapter } from \"./codex\";\nimport { cursorAdapter } from \"./cursor\";\nimport { opencodeAdapter } from \"./opencode\";\nimport { piAdapter } from \"./pi\";\nimport { zedAdapter } from \"./zed\";\n\nexport interface Message {\n text: string;\n timestamp?: string;\n session?: string;\n project?: string;\n}\n\nexport interface CostModelSummary {\n model: string;\n provider?: string;\n requests: number;\n estimatedCost: number;\n billedCost: number;\n pricingSource: PricingSource;\n unpricedRequests: number;\n inputTokens: number;\n outputTokens: number;\n reasoningTokens: number;\n cacheReadTokens: number;\n cacheWriteTokens: number;\n}\n\nexport interface CostDaySummary {\n day: string;\n requests: number;\n estimatedCost: number;\n billedCost: number;\n unpricedRequests: number;\n inputTokens: number;\n outputTokens: number;\n reasoningTokens: number;\n cacheReadTokens: number;\n cacheWriteTokens: number;\n models: CostModelSummary[];\n}\n\nexport type PricingSource =\n | \"catalog\"\n | \"stale-catalog\"\n | \"fallback\"\n | \"stored\"\n | \"unknown\"\n | \"mixed\";\n\nexport interface PricingMetadata {\n source: \"catalog\" | \"stale-catalog\" | \"fallback\";\n fetchedAt?: string;\n}\n\nexport interface CostSummary {\n requests: number;\n estimatedCost: number;\n billedCost: number;\n unpricedRequests: number;\n inputTokens: number;\n outputTokens: number;\n reasoningTokens: number;\n cacheReadTokens: number;\n cacheWriteTokens: number;\n models: CostModelSummary[];\n days: CostDaySummary[];\n pricing: PricingMetadata;\n}\n\nexport interface UsageRecord {\n agent: string;\n provider?: string;\n model?: string;\n timestamp?: string;\n session?: string;\n billedCost?: number;\n inputTokens: number;\n outputTokens: number;\n reasoningTokens: number;\n cacheReadTokens: number;\n cacheWriteTokens: number;\n}\n\nexport interface Adapter {\n name: string;\n /** Discover and yield all user messages from local session storage */\n messages(options?: AdapterOptions): AsyncGenerator<Message>;\n /** Discover and yield token/cost accounting rows when the agent exposes them */\n usage?(options?: AdapterOptions): AsyncGenerator<UsageRecord>;\n}\n\nexport interface AdapterOptions {\n since?: Date;\n}\n\nconst ADAPTERS: Record<string, () => Adapter> = {\n claude: claudeAdapter,\n codex: codexAdapter,\n cursor: cursorAdapter,\n opencode: opencodeAdapter,\n amp: ampAdapter,\n cline: clineAdapter,\n pi: piAdapter,\n zed: zedAdapter,\n};\n\nexport function createAdapter(name: string): Adapter {\n const factory = ADAPTERS[name];\n if (!factory) {\n throw new Error(`unknown adapter: ${name} (available: ${Object.keys(ADAPTERS).join(\", \")})`);\n }\n return factory();\n}\n\nexport function allAdapters(): Adapter[] {\n return Object.values(ADAPTERS).map((f) => f());\n}\n", "export interface DetectionResult {\n /** Total swear words found in the text */\n count: number;\n /** Individual matches */\n matches: Match[];\n}\n\nexport interface Match {\n word: string;\n index: number;\n severity: Severity;\n group: string;\n}\n\nexport type Severity = \"mild\" | \"moderate\" | \"strong\";\n\ninterface WordDef {\n word: string;\n severity: Severity;\n group: string;\n}\n\n/**\n * Core wordlist: canonical forms, conjugations, compound words, and common typos.\n * Grouped by root word for reporting rollup.\n *\n * Sources:\n * - swearjar npm (en_US.json) for compound words\n * - Manual typo variants based on common keyboard transpositions\n */\nconst WORDLIST: WordDef[] = [\n // === FUCK family (strong) ===\n // Canonical forms\n { word: \"fuck\", severity: \"strong\", group: \"fuck\" },\n { word: \"fucking\", severity: \"strong\", group: \"fuck\" },\n { word: \"fucked\", severity: \"strong\", group: \"fuck\" },\n { word: \"fucker\", severity: \"strong\", group: \"fuck\" },\n { word: \"fuckin\", severity: \"strong\", group: \"fuck\" },\n { word: \"fucks\", severity: \"strong\", group: \"fuck\" },\n // Compound words\n { word: \"motherfucker\", severity: \"strong\", group: \"fuck\" },\n { word: \"motherfucking\", severity: \"strong\", group: \"fuck\" },\n { word: \"mothafucka\", severity: \"strong\", group: \"fuck\" },\n { word: \"fuckup\", severity: \"strong\", group: \"fuck\" },\n { word: \"fuckoff\", severity: \"strong\", group: \"fuck\" },\n { word: \"clusterfuck\", severity: \"strong\", group: \"fuck\" },\n { word: \"fuckwit\", severity: \"strong\", group: \"fuck\" },\n { word: \"fucktard\", severity: \"strong\", group: \"fuck\" },\n { word: \"fuckface\", severity: \"strong\", group: \"fuck\" },\n { word: \"fuckhead\", severity: \"strong\", group: \"fuck\" },\n // Typos \u2014 transpositions\n { word: \"fukc\", severity: \"strong\", group: \"fuck\" },\n { word: \"fukcing\", severity: \"strong\", group: \"fuck\" },\n { word: \"fukced\", severity: \"strong\", group: \"fuck\" },\n { word: \"fukcer\", severity: \"strong\", group: \"fuck\" },\n { word: \"fcuk\", severity: \"strong\", group: \"fuck\" },\n { word: \"fcuking\", severity: \"strong\", group: \"fuck\" },\n { word: \"fcuked\", severity: \"strong\", group: \"fuck\" },\n { word: \"fuk\", severity: \"strong\", group: \"fuck\" },\n { word: \"fuking\", severity: \"strong\", group: \"fuck\" },\n { word: \"fuked\", severity: \"strong\", group: \"fuck\" },\n { word: \"fuker\", severity: \"strong\", group: \"fuck\" },\n { word: \"fuxk\", severity: \"strong\", group: \"fuck\" },\n { word: \"fuxking\", severity: \"strong\", group: \"fuck\" },\n\n // === SHIT family (strong) ===\n { word: \"shit\", severity: \"strong\", group: \"shit\" },\n { word: \"shitty\", severity: \"strong\", group: \"shit\" },\n { word: \"shitting\", severity: \"strong\", group: \"shit\" },\n { word: \"shits\", severity: \"strong\", group: \"shit\" },\n { word: \"shitted\", severity: \"strong\", group: \"shit\" },\n // Compound words\n { word: \"bullshit\", severity: \"strong\", group: \"shit\" },\n { word: \"horseshit\", severity: \"strong\", group: \"shit\" },\n { word: \"dipshit\", severity: \"strong\", group: \"shit\" },\n { word: \"shitshow\", severity: \"strong\", group: \"shit\" },\n { word: \"shithead\", severity: \"strong\", group: \"shit\" },\n { word: \"shithole\", severity: \"strong\", group: \"shit\" },\n { word: \"shitface\", severity: \"strong\", group: \"shit\" },\n { word: \"shitfaced\", severity: \"strong\", group: \"shit\" },\n { word: \"shitstain\", severity: \"strong\", group: \"shit\" },\n { word: \"shitbag\", severity: \"strong\", group: \"shit\" },\n // Typos\n { word: \"hsit\", severity: \"strong\", group: \"shit\" },\n { word: \"siht\", severity: \"strong\", group: \"shit\" },\n { word: \"shti\", severity: \"strong\", group: \"shit\" },\n { word: \"sjit\", severity: \"strong\", group: \"shit\" },\n { word: \"shjt\", severity: \"strong\", group: \"shit\" },\n { word: \"bulshit\", severity: \"strong\", group: \"shit\" },\n { word: \"bullsht\", severity: \"strong\", group: \"shit\" },\n\n // === ASS family (moderate) ===\n { word: \"ass\", severity: \"moderate\", group: \"ass\" },\n { word: \"asses\", severity: \"moderate\", group: \"ass\" },\n // Compound words (these are strong)\n { word: \"asshole\", severity: \"strong\", group: \"ass\" },\n { word: \"assholes\", severity: \"strong\", group: \"ass\" },\n { word: \"jackass\", severity: \"strong\", group: \"ass\" },\n { word: \"dumbass\", severity: \"strong\", group: \"ass\" },\n { word: \"fatass\", severity: \"moderate\", group: \"ass\" },\n { word: \"asshat\", severity: \"strong\", group: \"ass\" },\n { word: \"asswipe\", severity: \"strong\", group: \"ass\" },\n { word: \"badass\", severity: \"mild\", group: \"ass\" },\n\n // === DAMN family (moderate) ===\n { word: \"damn\", severity: \"moderate\", group: \"damn\" },\n { word: \"damned\", severity: \"moderate\", group: \"damn\" },\n { word: \"damnit\", severity: \"moderate\", group: \"damn\" },\n { word: \"dammit\", severity: \"moderate\", group: \"damn\" },\n { word: \"goddamn\", severity: \"moderate\", group: \"damn\" },\n { word: \"goddamnit\", severity: \"moderate\", group: \"damn\" },\n { word: \"goddammit\", severity: \"moderate\", group: \"damn\" },\n\n // === BITCH family (strong) ===\n { word: \"bitch\", severity: \"strong\", group: \"bitch\" },\n { word: \"bitches\", severity: \"strong\", group: \"bitch\" },\n { word: \"bitching\", severity: \"strong\", group: \"bitch\" },\n { word: \"bitchy\", severity: \"strong\", group: \"bitch\" },\n { word: \"bitchass\", severity: \"strong\", group: \"bitch\" },\n\n // === BASTARD (strong) ===\n { word: \"bastard\", severity: \"strong\", group: \"bastard\" },\n { word: \"bastards\", severity: \"strong\", group: \"bastard\" },\n\n // === PISS family (moderate) ===\n { word: \"piss\", severity: \"moderate\", group: \"piss\" },\n { word: \"pissed\", severity: \"moderate\", group: \"piss\" },\n { word: \"pissing\", severity: \"moderate\", group: \"piss\" },\n { word: \"pissoff\", severity: \"moderate\", group: \"piss\" },\n\n // === DICK (moderate) ===\n { word: \"dick\", severity: \"moderate\", group: \"dick\" },\n { word: \"dickhead\", severity: \"strong\", group: \"dick\" },\n\n // === CRAP (moderate) ===\n { word: \"crap\", severity: \"moderate\", group: \"crap\" },\n { word: \"crappy\", severity: \"moderate\", group: \"crap\" },\n { word: \"crapping\", severity: \"moderate\", group: \"crap\" },\n\n // === HELL (mild) ===\n { word: \"hell\", severity: \"mild\", group: \"hell\" },\n\n // === Abbreviations (mild) ===\n { word: \"wtf\", severity: \"mild\", group: \"wtf\" },\n { word: \"stfu\", severity: \"mild\", group: \"stfu\" },\n { word: \"lmfao\", severity: \"mild\", group: \"lmfao\" },\n { word: \"lmao\", severity: \"mild\", group: \"lmao\" },\n\n // === CUNT (strong) ===\n { word: \"cunt\", severity: \"strong\", group: \"cunt\" },\n { word: \"cunts\", severity: \"strong\", group: \"cunt\" },\n];\n\n/**\n * Normalize text before matching:\n * 1. Collapse repeated characters (3+ of the same char \u2192 2)\n * e.g. \"fuuuuck\" \u2192 \"fuuck\", \"shiiiiit\" \u2192 \"shiit\"\n * This lets \"fuuuuck\" match against \"fuck\" after the regex runs,\n * because the pattern also includes \"fuuck\" style intermediates.\n *\n * Actually \u2014 better approach: collapse ALL runs of 2+ to 1 for matching\n * purposes, while keeping the original text for position tracking.\n * e.g. \"fuuuuck\" \u2192 \"fuck\", \"shiiiit\" \u2192 \"shit\"\n * This directly normalizes to the root word.\n */\nfunction collapseRepeats(text: string): string {\n return text.replace(/(.)\\1+/g, \"$1\");\n}\n\n/**\n * Build the detection regex from the wordlist.\n * Sort longer words first so \"motherfucker\" matches before \"fuck\".\n */\nfunction buildPattern(words: WordDef[]): RegExp {\n const sorted = [...words].sort((a, b) => b.word.length - a.word.length);\n const pattern = sorted.map((w) => w.word).join(\"|\");\n return new RegExp(`\\\\b(${pattern})\\\\b`, \"gi\");\n}\n\nconst DEFAULT_PATTERN = buildPattern(WORDLIST);\nconst WORD_MAP = new Map(WORDLIST.map((w) => [w.word.toLowerCase(), w]));\n\n/**\n * Detect profanity in a string.\n *\n * Runs detection in two passes:\n * 1. Direct match on original text (preserves positions)\n * 2. Match on repeat-collapsed text (catches fuuuuck, shiiiiit, etc.)\n */\nexport function detect(text: string): DetectionResult {\n const matches: Match[] = [];\n const seen = new Set<number>(); // track original-text positions we've already matched\n\n // Pass 1: direct match on original (lowercase) text\n runPattern(text, text.toLowerCase(), matches, seen);\n\n // Pass 2: match on collapsed text to catch repeated chars\n const collapsed = collapseRepeats(text.toLowerCase());\n if (collapsed !== text.toLowerCase()) {\n runPattern(text, collapsed, matches, seen);\n }\n\n return { count: matches.length, matches };\n}\n\nfunction runPattern(\n _originalText: string,\n searchText: string,\n matches: Match[],\n seen: Set<number>,\n): void {\n DEFAULT_PATTERN.lastIndex = 0;\n\n let match: RegExpExecArray | null;\n while ((match = DEFAULT_PATTERN.exec(searchText)) !== null) {\n if (seen.has(match.index)) {\n continue;\n }\n\n const word = match[0].toLowerCase();\n const entry = WORD_MAP.get(word);\n if (!entry) {\n continue;\n }\n\n seen.add(match.index);\n matches.push({\n word,\n index: match.index,\n severity: entry.severity,\n group: entry.group,\n });\n }\n}\n\n/**\n * Create a custom detector with additional words.\n */\nexport function createDetector(extraWords?: WordDef[]): (text: string) => DetectionResult {\n const allWords = extraWords ? [...WORDLIST, ...extraWords] : WORDLIST;\n const pattern = buildPattern(allWords);\n const wordMap = new Map(allWords.map((w) => [w.word.toLowerCase(), w]));\n\n return (text: string): DetectionResult => {\n const matches: Match[] = [];\n const seen = new Set<number>();\n\n const lower = text.toLowerCase();\n pattern.lastIndex = 0;\n let match: RegExpExecArray | null;\n while ((match = pattern.exec(lower)) !== null) {\n if (seen.has(match.index)) {\n continue;\n }\n const word = match[0].toLowerCase();\n const entry = wordMap.get(word);\n if (!entry) {\n continue;\n }\n seen.add(match.index);\n matches.push({ word, index: match.index, severity: entry.severity, group: entry.group });\n }\n\n const collapsed = collapseRepeats(lower);\n if (collapsed !== lower) {\n pattern.lastIndex = 0;\n while ((match = pattern.exec(collapsed)) !== null) {\n if (seen.has(match.index)) {\n continue;\n }\n const word = match[0].toLowerCase();\n const entry = wordMap.get(word);\n if (!entry) {\n continue;\n }\n seen.add(match.index);\n matches.push({ word, index: match.index, severity: entry.severity, group: entry.group });\n }\n }\n\n return { count: matches.length, matches };\n };\n}\n\nexport type { WordDef as WordEntry };\n", "import { mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\nimport type {\n CostDaySummary,\n CostModelSummary,\n CostSummary,\n PricingMetadata,\n PricingSource,\n UsageRecord,\n} from \"../adapters/index\";\n\n/**\n * Owns API-equivalent token pricing. The models.dev cache is local-only, and\n * adapter-reported billed cost stays separate from estimated token-price cost.\n */\n\nconst MODELS_DEV_URL = \"https://models.dev/api.json\";\nconst CACHE_TTL_MS = 7 * 24 * 60 * 60 * 1000;\nconst FETCH_TIMEOUT_MS = 2_000;\n\ninterface PricingOptions {\n refresh?: boolean;\n cacheTtlMs?: number;\n fetchTimeoutMs?: number;\n}\n\ninterface PricingCatalog extends PricingMetadata {\n cachePath: string;\n catalog?: unknown;\n}\n\ninterface PricingCacheFile {\n source: \"models.dev\";\n fetchedAt: string;\n schemaVersion: 1;\n catalog: unknown;\n}\n\ninterface RateTable {\n input?: number;\n output?: number;\n cache_read?: number;\n cache_write?: number;\n tiers?: unknown[];\n context_over_200k?: RateTable;\n}\n\ninterface ResolvedRates {\n provider?: string;\n model: string;\n rates: RateTable;\n source: Exclude<PricingSource, \"stored\" | \"unknown\" | \"mixed\">;\n}\n\ninterface PricedUsage {\n provider?: string;\n model: string;\n estimatedCost: number;\n source: PricingSource;\n}\n\ninterface CostAccumulator {\n requests: number;\n estimatedCost: number;\n billedCost: number;\n unpricedRequests: number;\n inputTokens: number;\n outputTokens: number;\n reasoningTokens: number;\n cacheReadTokens: number;\n cacheWriteTokens: number;\n byModel: Map<string, CostModelSummary>;\n}\n\nconst FALLBACK_COSTS: Record<string, Record<string, RateTable>> = {\n openai: {\n \"gpt-5.5\": {\n input: 5,\n output: 30,\n cache_read: 0.5,\n context_over_200k: { input: 10, output: 45, cache_read: 1 },\n },\n \"gpt-5.5-pro\": { input: 30, output: 180 },\n \"gpt-5.4\": { input: 2.5, output: 15, cache_read: 0.25 },\n \"gpt-5.4-mini\": { input: 0.75, output: 4.5, cache_read: 0.075 },\n \"gpt-5.4-nano\": { input: 0.2, output: 1.25, cache_read: 0.02 },\n \"gpt-5.4-pro\": { input: 30, output: 180 },\n \"gpt-5.3-codex\": { input: 1.75, output: 14, cache_read: 0.175 },\n },\n anthropic: {\n \"claude-opus-4-7\": { input: 5, output: 25, cache_read: 0.5, cache_write: 6.25 },\n },\n};\n\nconst PROVIDER_ALIASES: Record<string, string> = {\n anthropic: \"anthropic\",\n claude: \"anthropic\",\n openai: \"openai\",\n};\n\n/** Load models.dev pricing from cache, refresh, stale cache, or embedded fallbacks. */\nexport async function loadPricingCatalog(options: PricingOptions = {}): Promise<PricingCatalog> {\n const cachePath = getPricingCachePath();\n const cache = await readPricingCache(cachePath);\n const ttlMs = options.cacheTtlMs ?? CACHE_TTL_MS;\n\n if (!options.refresh && cache && isFresh(cache.fetchedAt, ttlMs)) {\n return {\n source: \"catalog\",\n fetchedAt: cache.fetchedAt,\n cachePath,\n catalog: cache.catalog,\n };\n }\n\n try {\n const catalog = await fetchModelsDevCatalog(options.fetchTimeoutMs ?? FETCH_TIMEOUT_MS);\n const fetchedAt = new Date().toISOString();\n await writePricingCache(cachePath, {\n source: \"models.dev\",\n fetchedAt,\n schemaVersion: 1,\n catalog,\n });\n\n return { source: \"catalog\", fetchedAt, cachePath, catalog };\n } catch {\n if (cache) {\n return {\n source: \"stale-catalog\",\n fetchedAt: cache.fetchedAt,\n cachePath,\n catalog: cache.catalog,\n };\n }\n\n return { source: \"fallback\", cachePath };\n }\n}\n\n/** Price usage rows individually, then aggregate by model for report output. */\nexport async function summarizeUsage(\n records: AsyncIterable<UsageRecord>,\n pricing: PricingCatalog,\n): Promise<CostSummary> {\n const total = createCostAccumulator();\n const byDay = new Map<string, CostAccumulator>();\n\n for await (const record of records) {\n const priced = priceUsageRecord(record, pricing);\n const billedCost = record.billedCost ?? 0;\n const isUnpriced = priced.source === \"stored\" || priced.source === \"unknown\";\n addUsageToAccumulator(total, record, priced, billedCost, isUnpriced);\n\n const day = timestampDay(record.timestamp);\n if (day) {\n let dayAccumulator = byDay.get(day);\n if (!dayAccumulator) {\n dayAccumulator = createCostAccumulator();\n byDay.set(day, dayAccumulator);\n }\n addUsageToAccumulator(dayAccumulator, record, priced, billedCost, isUnpriced);\n }\n }\n\n return {\n requests: total.requests,\n estimatedCost: total.estimatedCost,\n billedCost: total.billedCost,\n unpricedRequests: total.unpricedRequests,\n inputTokens: total.inputTokens,\n outputTokens: total.outputTokens,\n reasoningTokens: total.reasoningTokens,\n cacheReadTokens: total.cacheReadTokens,\n cacheWriteTokens: total.cacheWriteTokens,\n models: sortedModels(total.byModel),\n days: Array.from(byDay.entries())\n .sort(([left], [right]) => left.localeCompare(right))\n .map(([day, bucket]) => costDaySummary(day, bucket)),\n pricing: {\n source: pricing.source,\n fetchedAt: pricing.fetchedAt,\n },\n };\n}\n\n/** Resolve the devrage-owned cache path for the models.dev catalog. */\nexport function getPricingCachePath(): string {\n if (process.env[\"XDG_CACHE_HOME\"]) {\n return join(process.env[\"XDG_CACHE_HOME\"], \"devrage\", \"models.dev.json\");\n }\n\n if (process.platform === \"darwin\") {\n return join(homedir(), \"Library\", \"Caches\", \"devrage\", \"models.dev.json\");\n }\n\n if (process.platform === \"win32\") {\n const localAppData = process.env[\"LOCALAPPDATA\"] ?? join(homedir(), \"AppData\", \"Local\");\n return join(localAppData, \"devrage\", \"models.dev.json\");\n }\n\n return join(homedir(), \".cache\", \"devrage\", \"models.dev.json\");\n}\n\nfunction createCostAccumulator(): CostAccumulator {\n return {\n requests: 0,\n estimatedCost: 0,\n billedCost: 0,\n unpricedRequests: 0,\n inputTokens: 0,\n outputTokens: 0,\n reasoningTokens: 0,\n cacheReadTokens: 0,\n cacheWriteTokens: 0,\n byModel: new Map(),\n };\n}\n\nfunction addUsageToAccumulator(\n bucket: CostAccumulator,\n record: UsageRecord,\n priced: PricedUsage,\n billedCost: number,\n isUnpriced: boolean,\n): void {\n const key = `${priced.provider ?? \"\"}:${priced.model}`;\n let model = bucket.byModel.get(key);\n\n if (!model) {\n model = {\n model: priced.model,\n provider: priced.provider,\n requests: 0,\n estimatedCost: 0,\n billedCost: 0,\n pricingSource: priced.source,\n unpricedRequests: 0,\n inputTokens: 0,\n outputTokens: 0,\n reasoningTokens: 0,\n cacheReadTokens: 0,\n cacheWriteTokens: 0,\n };\n bucket.byModel.set(key, model);\n }\n\n model.requests += 1;\n model.estimatedCost += priced.estimatedCost;\n model.billedCost += billedCost;\n model.pricingSource = mergePricingSource(model.pricingSource, priced.source);\n model.inputTokens += record.inputTokens;\n model.outputTokens += record.outputTokens;\n model.reasoningTokens += record.reasoningTokens;\n model.cacheReadTokens += record.cacheReadTokens;\n model.cacheWriteTokens += record.cacheWriteTokens;\n\n bucket.requests += 1;\n bucket.estimatedCost += priced.estimatedCost;\n bucket.billedCost += billedCost;\n bucket.inputTokens += record.inputTokens;\n bucket.outputTokens += record.outputTokens;\n bucket.reasoningTokens += record.reasoningTokens;\n bucket.cacheReadTokens += record.cacheReadTokens;\n bucket.cacheWriteTokens += record.cacheWriteTokens;\n\n if (isUnpriced) {\n model.unpricedRequests += 1;\n bucket.unpricedRequests += 1;\n }\n}\n\nfunction costDaySummary(day: string, bucket: CostAccumulator): CostDaySummary {\n return {\n day,\n requests: bucket.requests,\n estimatedCost: bucket.estimatedCost,\n billedCost: bucket.billedCost,\n unpricedRequests: bucket.unpricedRequests,\n inputTokens: bucket.inputTokens,\n outputTokens: bucket.outputTokens,\n reasoningTokens: bucket.reasoningTokens,\n cacheReadTokens: bucket.cacheReadTokens,\n cacheWriteTokens: bucket.cacheWriteTokens,\n models: sortedModels(bucket.byModel),\n };\n}\n\nfunction sortedModels(byModel: Map<string, CostModelSummary>): CostModelSummary[] {\n return Array.from(byModel.values()).sort(\n (a, b) => b.estimatedCost - a.estimatedCost || b.requests - a.requests,\n );\n}\n\nfunction timestampDay(timestamp: string | undefined): string | null {\n if (!timestamp) {\n return null;\n }\n\n const time = new Date(timestamp).getTime();\n if (!Number.isFinite(time)) {\n return null;\n }\n\n return new Date(time).toISOString().slice(0, 10);\n}\n\nasync function fetchModelsDevCatalog(timeoutMs: number): Promise<unknown> {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), timeoutMs);\n\n try {\n const response = await fetch(MODELS_DEV_URL, { signal: controller.signal });\n if (!response.ok) {\n throw new Error(`models.dev returned ${response.status}`);\n }\n\n const catalog = await response.json();\n if (!isModelsDevCatalog(catalog)) {\n throw new Error(\"models.dev response did not match expected shape\");\n }\n\n return catalog;\n } finally {\n clearTimeout(timeout);\n }\n}\n\nasync function readPricingCache(cachePath: string): Promise<PricingCacheFile | null> {\n try {\n const raw = await readFile(cachePath, \"utf-8\");\n const parsed = JSON.parse(raw) as unknown;\n const cache = asRecord(parsed);\n\n if (\n cache?.[\"source\"] !== \"models.dev\" ||\n cache[\"schemaVersion\"] !== 1 ||\n typeof cache[\"fetchedAt\"] !== \"string\" ||\n !isModelsDevCatalog(cache[\"catalog\"])\n ) {\n return null;\n }\n\n return {\n source: \"models.dev\",\n fetchedAt: cache[\"fetchedAt\"],\n schemaVersion: 1,\n catalog: cache[\"catalog\"],\n };\n } catch {\n return null;\n }\n}\n\nasync function writePricingCache(cachePath: string, cache: PricingCacheFile): Promise<void> {\n try {\n await mkdir(dirname(cachePath), { recursive: true });\n await writeFile(cachePath, `${JSON.stringify(cache)}\\n`, \"utf-8\");\n } catch {\n // Cost estimation can still use the freshly fetched catalog when cache writes fail.\n }\n}\n\nfunction priceUsageRecord(record: UsageRecord, catalog: PricingCatalog): PricedUsage {\n const resolved = resolveRates(record, catalog);\n if (!resolved) {\n return {\n provider: normalizeProvider(record.provider),\n model: normalizeModel(record.model) ?? \"unknown\",\n estimatedCost: 0,\n source: (record.billedCost ?? 0) > 0 ? \"stored\" : \"unknown\",\n };\n }\n\n const rates = selectContextRates(resolved.rates, record);\n const inputRate = rates.input ?? 0;\n const outputRate = rates.output ?? 0;\n const cacheReadRate = rates.cache_read ?? inputRate;\n const cacheWriteRate = rates.cache_write ?? inputRate;\n const outputTokens = record.outputTokens + record.reasoningTokens;\n\n return {\n provider: resolved.provider,\n model: resolved.model,\n estimatedCost:\n (record.inputTokens * inputRate +\n record.cacheReadTokens * cacheReadRate +\n record.cacheWriteTokens * cacheWriteRate +\n outputTokens * outputRate) /\n 1_000_000,\n source: resolved.source,\n };\n}\n\nfunction resolveRates(record: UsageRecord, pricing: PricingCatalog): ResolvedRates | null {\n const candidates = modelCandidates(record.provider, record.model);\n\n for (const candidate of candidates) {\n if (!candidate.provider || !pricing.catalog) {\n continue;\n }\n\n const rates = getCatalogRates(pricing.catalog, candidate.provider, candidate.model);\n if (rates) {\n return {\n provider: candidate.provider,\n model: candidate.model,\n rates,\n source: pricing.source === \"stale-catalog\" ? \"stale-catalog\" : \"catalog\",\n };\n }\n }\n\n for (const candidate of candidates) {\n if (!candidate.provider) {\n continue;\n }\n\n const providerRates = FALLBACK_COSTS[candidate.provider];\n const rates = providerRates?.[candidate.model];\n if (rates) {\n return { provider: candidate.provider, model: candidate.model, rates, source: \"fallback\" };\n }\n }\n\n return null;\n}\n\nfunction modelCandidates(\n providerInput: string | undefined,\n modelInput: string | undefined,\n): { provider?: string; model: string }[] {\n const candidates: { provider?: string; model: string }[] = [];\n let provider = normalizeProvider(providerInput);\n let model = normalizeModel(modelInput);\n\n if (!model) {\n return candidates;\n }\n\n const prefixed = splitProviderModel(model);\n if (prefixed) {\n provider = provider ?? prefixed.provider;\n model = prefixed.model;\n }\n\n addCandidate(candidates, provider, model);\n addCandidate(candidates, provider, MODEL_ALIASES[model]);\n\n const inferred = provider ?? inferProvider(model);\n addCandidate(candidates, inferred, model);\n addCandidate(candidates, inferred, MODEL_ALIASES[model]);\n\n for (const fallbackProvider of Object.keys(FALLBACK_COSTS)) {\n addCandidate(candidates, fallbackProvider, model);\n addCandidate(candidates, fallbackProvider, MODEL_ALIASES[model]);\n }\n\n return candidates;\n}\n\nconst MODEL_ALIASES: Record<string, string> = {\n \"gpt-5.5-chat-latest\": \"gpt-5.5\",\n};\n\nfunction addCandidate(\n candidates: { provider?: string; model: string }[],\n provider: string | undefined,\n model: string | undefined,\n): void {\n if (!model) {\n return;\n }\n\n if (\n candidates.some((candidate) => candidate.provider === provider && candidate.model === model)\n ) {\n return;\n }\n\n candidates.push({ provider, model });\n}\n\nfunction splitProviderModel(model: string): { provider: string; model: string } | null {\n const slash = model.indexOf(\"/\");\n if (slash <= 0 || slash === model.length - 1) {\n return null;\n }\n\n const provider = normalizeProvider(model.slice(0, slash));\n const bareModel = normalizeModel(model.slice(slash + 1));\n if (!provider || !bareModel) {\n return null;\n }\n\n return { provider, model: bareModel };\n}\n\nfunction normalizeProvider(provider: string | undefined): string | undefined {\n if (!provider) {\n return undefined;\n }\n\n const normalized = provider.trim().toLowerCase();\n return PROVIDER_ALIASES[normalized] ?? normalized;\n}\n\nfunction normalizeModel(model: string | undefined): string | undefined {\n const normalized = model?.trim().toLowerCase();\n return normalized || undefined;\n}\n\nfunction inferProvider(model: string): string | undefined {\n if (model.startsWith(\"gpt-\") || /^o\\d/.test(model)) {\n return \"openai\";\n }\n\n if (model.startsWith(\"claude-\")) {\n return \"anthropic\";\n }\n\n return undefined;\n}\n\nfunction getCatalogRates(catalog: unknown, provider: string, model: string): RateTable | null {\n const root = asRecord(catalog);\n const providerEntry = asRecord(root?.[provider]);\n const models = asRecord(providerEntry?.[\"models\"]);\n const modelEntry = asRecord(models?.[model]);\n return toRateTable(modelEntry?.[\"cost\"]);\n}\n\nfunction selectContextRates(rates: RateTable, record: UsageRecord): RateTable {\n const contextTokens = record.inputTokens + record.cacheReadTokens + record.cacheWriteTokens;\n let selected = rates;\n let selectedSize = 0;\n\n for (const tier of rates.tiers ?? []) {\n const tierRecord = asRecord(tier);\n const tierInfo = asRecord(tierRecord?.[\"tier\"]);\n const size = typeof tierInfo?.[\"size\"] === \"number\" ? tierInfo[\"size\"] : 0;\n if (tierInfo?.[\"type\"] !== \"context\" || contextTokens < size || size < selectedSize) {\n continue;\n }\n\n const tierRates = toRateTable(tierRecord);\n if (tierRates) {\n selected = { ...rates, ...tierRates };\n selectedSize = size;\n }\n }\n\n if (selected === rates && rates.context_over_200k && contextTokens > 200_000) {\n selected = { ...rates, ...rates.context_over_200k };\n }\n\n return selected;\n}\n\nfunction toRateTable(value: unknown): RateTable | null {\n const record = asRecord(value);\n if (!record) {\n return null;\n }\n\n const rates: RateTable = {};\n const input = numberValue(record[\"input\"]);\n const output = numberValue(record[\"output\"]);\n const cacheRead = numberValue(record[\"cache_read\"]);\n const cacheWrite = numberValue(record[\"cache_write\"]);\n const contextOver200k = toRateTable(record[\"context_over_200k\"]);\n\n if (input !== undefined) {\n rates.input = input;\n }\n if (output !== undefined) {\n rates.output = output;\n }\n if (cacheRead !== undefined) {\n rates.cache_read = cacheRead;\n }\n if (cacheWrite !== undefined) {\n rates.cache_write = cacheWrite;\n }\n if (Array.isArray(record[\"tiers\"])) {\n rates.tiers = record[\"tiers\"];\n }\n if (contextOver200k) {\n rates.context_over_200k = contextOver200k;\n }\n\n return rates.input !== undefined || rates.output !== undefined ? rates : null;\n}\n\nfunction numberValue(value: unknown): number | undefined {\n return typeof value === \"number\" && Number.isFinite(value) ? value : undefined;\n}\n\nfunction isModelsDevCatalog(value: unknown): boolean {\n const catalog = asRecord(value);\n const openai = asRecord(catalog?.[\"openai\"]);\n const anthropic = asRecord(catalog?.[\"anthropic\"]);\n return Boolean(asRecord(openai?.[\"models\"]) || asRecord(anthropic?.[\"models\"]));\n}\n\nfunction isFresh(fetchedAt: string, ttlMs: number): boolean {\n const fetchedTime = new Date(fetchedAt).getTime();\n return Number.isFinite(fetchedTime) && Date.now() - fetchedTime <= ttlMs;\n}\n\nfunction mergePricingSource(left: PricingSource, right: PricingSource): PricingSource {\n return left === right ? left : \"mixed\";\n}\n\nfunction asRecord(value: unknown): Record<string, unknown> | null {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n return null;\n }\n\n return value as Record<string, unknown>;\n}\n", "import { cost, scan } from \"./commands/scan\";\n\nconst COMMANDS: Record<string, (args: string[]) => Promise<void>> = {\n cost,\n scan,\n};\n\nconst OPTIONS_WITH_VALUES = new Set([\"--agent\", \"-a\", \"--since\", \"-s\"]);\n\ninterface ParsedCommand {\n handler: (args: string[]) => Promise<void>;\n args: string[];\n}\n\nfunction usage(): void {\n console.log(`devrage \u2014 count how many times you swear at your coding agents\n\nUsage:\n devrage <command> [options]\n\nCommands:\n cost Show API-equivalent coding agent cost\n scan Scan sessions for profanity\n\nOptions:\n --help, -h Show this help message\n --version Show version\n\nExamples:\n devrage cost\n devrage scan\n devrage scan --agent claude\n devrage scan --since 2025-01-01`);\n}\n\nasync function main(): Promise<void> {\n const args = process.argv.slice(2);\n const command = args[0];\n\n if (command === \"--help\" || command === \"-h\") {\n usage();\n process.exit(0);\n }\n\n if (command === \"--version\") {\n console.log(\"0.5.5\");\n process.exit(0);\n }\n\n // If no command is present, default to scan for the original no-subcommand UX.\n const parsed = parseCommand(args);\n if (parsed) {\n await parsed.handler(parsed.args);\n } else {\n // Pass all args through to scan (covers both no-arg and unknown-arg cases)\n await scan(args);\n }\n}\n\nfunction parseCommand(args: string[]): ParsedCommand | null {\n for (let index = 0; index < args.length; index++) {\n const arg = args[index];\n if (!arg) {\n continue;\n }\n\n const handler = COMMANDS[arg];\n if (handler) {\n return {\n handler,\n args: [...args.slice(0, index), ...args.slice(index + 1)],\n };\n }\n\n if (OPTIONS_WITH_VALUES.has(arg) && index + 1 < args.length) {\n index++;\n }\n }\n\n return null;\n}\n\nmain().catch((err: unknown) => {\n console.error(err);\n process.exit(1);\n});\n"],
5
- "mappings": "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",
6
- "names": ["mkdir", "writeFile", "dirname", "join", "readdir", "homedir", "join", "asRecord", "usage", "readdir", "readFile", "stat", "homedir", "join", "extractText", "createReadStream", "readdir", "stat", "createInterface", "homedir", "join", "extractText", "asRecord", "stringValue", "usage", "numberValue", "existsSync", "readdir", "homedir", "join", "usage", "stringValue", "asRecord", "numberValue", "extractTimestamp", "existsSync", "homedir", "join", "numberValue", "stringValue", "createReadStream", "readdir", "stat", "createInterface", "homedir", "join", "contentToString", "usage", "asRecord", "numberValue", "stringValue", "readdir", "readFile", "existsSync", "homedir", "join", "base", "c", "readFile", "homedir", "join", "asRecord", "numberValue", "join", "dirname", "mkdir", "writeFile"]
3
+ "sources": ["../src/commands/scan.ts", "../src/adapters/amp.ts", "../src/adapters/claude.ts", "../src/adapters/cline.ts", "../src/adapters/codex.ts", "../src/adapters/cursor.ts", "../src/adapters/opencode.ts", "../src/adapters/pi.ts", "../src/adapters/t3code.ts", "../src/adapters/zed.ts", "../src/adapters/index.ts", "../src/detector/index.ts", "../src/pricing/index.ts", "../src/cli.ts"],
4
+ "sourcesContent": ["import { mkdir, writeFile } from \"node:fs/promises\";\nimport { dirname, join } from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\nimport {\n allAdapters,\n createAdapter,\n type CostModelSummary,\n type CostSummary,\n type PricingSource,\n} from \"../adapters/index\";\nimport { detect } from \"../detector/index\";\nimport { getPricingCachePath, loadPricingCatalog, summarizeUsage } from \"../pricing/index\";\n\n// ANSI color helpers \u2014 no dependencies needed\nconst c = {\n reset: \"\\x1b[0m\",\n bold: \"\\x1b[1m\",\n dim: \"\\x1b[2m\",\n red: \"\\x1b[31m\",\n green: \"\\x1b[32m\",\n yellow: \"\\x1b[33m\",\n blue: \"\\x1b[34m\",\n magenta: \"\\x1b[35m\",\n cyan: \"\\x1b[36m\",\n white: \"\\x1b[37m\",\n gray: \"\\x1b[90m\",\n};\n\nconst MAX_TERMINAL_MODELS = 10;\n\nconst SPINNER_MESSAGES = [\n \"Tallying the damage\",\n \"Reviewing your outbursts\",\n \"Judging your vocabulary\",\n \"Computing your shame\",\n \"Cataloging the profanity\",\n \"Measuring your frustration\",\n \"Assessing the verbal carnage\",\n \"Quantifying your displeasure\",\n \"Auditing your language\",\n \"Tabulating regrets\",\n];\n\nconst COST_SPINNER_MESSAGES = [\n \"Loading price catalog\",\n \"Reading local usage\",\n \"Scanning transcript stores\",\n \"Crunching token counts\",\n \"Still working through local history\",\n];\n\nconst DAY_MS = 24 * 60 * 60 * 1000;\n\nfunction createSpinner(messages = SPINNER_MESSAGES) {\n let messageIdx = 0;\n let dotCount = 0;\n let timer: ReturnType<typeof setInterval> | null = null;\n let messageOverride: string | null = null;\n\n function render() {\n dotCount = (dotCount + 1) % 4;\n const msg = messageOverride ?? messages[messageIdx % messages.length];\n const dots = \".\".repeat(dotCount || 1);\n process.stdout.write(`\\r ${c.dim}${msg}${dots}${c.reset} `);\n }\n\n return {\n start(message?: string) {\n messageIdx = Math.floor(Math.random() * messages.length);\n messageOverride = message ?? null;\n render();\n timer = setInterval(() => {\n render();\n }, 300);\n },\n update(message?: string) {\n if (message) {\n messageOverride = message;\n } else {\n messageOverride = null;\n messageIdx++;\n }\n render();\n },\n stop() {\n if (timer) {\n clearInterval(timer);\n timer = null;\n }\n process.stdout.write(\"\\r\" + \" \".repeat(80) + \"\\r\");\n },\n };\n}\n\ninterface ScanOptions {\n agent?: string;\n refreshPrices?: boolean;\n since?: Date;\n rangeLabel?: string;\n}\n\ninterface CostTotals {\n entries: [string, CostSummary][];\n totalCost: number;\n totalRequests: number;\n pricedRequests: number;\n unpricedRequests: number;\n}\n\ninterface CostReportModel {\n model: string;\n provider?: string;\n estimatedCost: number;\n requests: number;\n inputTokens: number;\n outputTokens: number;\n reasoningTokens: number;\n cacheReadTokens: number;\n cacheWriteTokens: number;\n}\n\ninterface CostReportDay {\n day: string;\n estimatedCost: number;\n requests: number;\n models: CostReportModel[];\n}\n\ninterface CostReportAgent {\n name: string;\n estimatedCost: number;\n requests: number;\n models: CostReportModel[];\n days: CostReportDay[];\n}\n\ninterface CostReportData {\n generatedAt: string;\n scope: string;\n totalCost: number;\n pricedRequests: number;\n unpricedRequests: number;\n agents: CostReportAgent[];\n}\n\nfunction parseArgs(args: string[]): ScanOptions {\n const options: ScanOptions = {};\n\n for (let i = 0; i < args.length; i++) {\n const arg = args[i];\n if (arg === \"--agent\" || arg === \"-a\") {\n options.agent = args[++i];\n } else if (arg === \"--since\" || arg === \"-s\") {\n const val = args[++i];\n if (val) {\n setAbsoluteSince(options, val);\n }\n } else if (arg === \"--day\" || arg === \"--days\") {\n const parsed = readOptionalDaysArg(args, i);\n setRelativeRange(options, parsed.days);\n if (parsed.consumed) {\n i++;\n }\n } else if (arg === \"--week\") {\n setRelativeRange(options, 7);\n } else if (arg === \"--month\") {\n setRelativeRange(options, 30);\n } else if (arg === \"--help\" || arg === \"-h\") {\n console.log(`devrage scan \u2014 scan sessions for profanity\n\nOptions:\n --agent, -a <name> Scan only a specific agent (claude, codex, cursor, opencode, amp, cline, pi, t3code, zed)\n --since, -s <date> Only scan messages after this date (ISO 8601)\n --day, --days [n] Only scan the last n days (default: 1)\n --week Only scan the last 7 days\n --month Only scan the last 30 days\n --help, -h Show this help`);\n process.exit(0);\n }\n }\n\n return options;\n}\n\nfunction parseCostArgs(args: string[]): ScanOptions {\n const options: ScanOptions = {};\n\n for (let i = 0; i < args.length; i++) {\n const arg = args[i];\n if (arg === \"--agent\" || arg === \"-a\") {\n options.agent = args[++i];\n } else if (arg === \"--refresh-prices\") {\n options.refreshPrices = true;\n } else if (arg === \"--since\" || arg === \"-s\") {\n const val = args[++i];\n if (val) {\n setAbsoluteSince(options, val);\n }\n } else if (arg === \"--day\" || arg === \"--days\") {\n const parsed = readOptionalDaysArg(args, i);\n setRelativeRange(options, parsed.days);\n if (parsed.consumed) {\n i++;\n }\n } else if (arg === \"--week\") {\n setRelativeRange(options, 7);\n } else if (arg === \"--month\") {\n setRelativeRange(options, 30);\n } else if (arg === \"--help\" || arg === \"-h\") {\n console.log(`devrage cost \u2014 show API-equivalent coding agent cost\n\nUsage:\n devrage cost [options]\n\nOptions:\n --agent, -a <name> Show only a specific agent (claude, codex, cursor, opencode, amp, pi, t3code)\n --refresh-prices Refresh models.dev pricing before estimating cost\n --since, -s <date> Only include usage after this date (ISO 8601)\n --day, --days [n] Only include the last n days (default: 1)\n --week Only include the last 7 days\n --month Only include the last 30 days\n --help, -h Show this help`);\n process.exit(0);\n }\n }\n\n return options;\n}\n\nfunction setAbsoluteSince(options: ScanOptions, value: string): void {\n options.since = parseDateArg(value);\n options.rangeLabel = undefined;\n}\n\nfunction setRelativeRange(options: ScanOptions, days: number): void {\n options.since = new Date(Date.now() - days * DAY_MS);\n options.rangeLabel = `last ${days} ${days === 1 ? \"day\" : \"days\"}`;\n}\n\nfunction readOptionalDaysArg(args: string[], index: number): { days: number; consumed: boolean } {\n const value = args[index + 1];\n if (!value || (value.startsWith(\"-\") && !/^-\\d+$/.test(value))) {\n return { days: 1, consumed: false };\n }\n\n return { days: parseDaysArg(value), consumed: true };\n}\n\nfunction parseDaysArg(value: string | undefined): number {\n const days = Number(value);\n if (!Number.isInteger(days) || days < 1) {\n console.error(`invalid days: ${value ?? \"\"}`);\n process.exit(1);\n }\n\n return days;\n}\n\nfunction parseDateArg(value: string): Date {\n const date = new Date(value);\n if (isNaN(date.getTime())) {\n console.error(`invalid date: ${value}`);\n process.exit(1);\n }\n\n return date;\n}\n\nexport async function scan(args: string[]): Promise<void> {\n const options = parseArgs(args);\n\n const adapters = options.agent ? [createAdapter(options.agent)] : allAdapters();\n\n const spinner = createSpinner();\n spinner.start();\n\n const groupTally: Record<string, number> = {};\n const variantTally: Record<string, Record<string, number>> = {};\n\n let totalMessages = 0;\n let totalSwears = 0;\n const perAgent: Record<string, { messages: number; swears: number }> = {};\n\n for (const adapter of adapters) {\n let agentMessages = 0;\n let agentSwears = 0;\n spinner.update();\n\n for await (const message of adapter.messages({ since: options.since })) {\n totalMessages++;\n agentMessages++;\n\n const result = detect(message.text);\n if (result.count > 0) {\n totalSwears += result.count;\n agentSwears += result.count;\n\n for (const match of result.matches) {\n groupTally[match.group] = (groupTally[match.group] ?? 0) + 1;\n\n const variants = (variantTally[match.group] ??= {});\n variants[match.word] = (variants[match.word] ?? 0) + 1;\n }\n }\n }\n\n if (agentMessages > 0) {\n perAgent[adapter.name] = { messages: agentMessages, swears: agentSwears };\n }\n }\n\n spinner.stop();\n\n const activeAgents = Object.entries(perAgent);\n\n console.log(\"\");\n printReportHeader(options);\n printBasicOverview(totalMessages, totalSwears);\n\n if (activeAgents.length > 1) {\n console.log(\"\");\n console.log(` ${sectionTitle(\"agent language\")}`);\n for (const [name, stats] of activeAgents) {\n const rate = ((stats.swears / stats.messages) * 100).toFixed(1);\n console.log(\n ` ${colorText(name.padEnd(10), agentColor(name))} ${c.bold}${String(stats.swears).padStart(4)}${c.reset} ${c.dim}in ${stats.messages} messages (${rate}%)${c.reset}`,\n );\n }\n }\n\n if (totalSwears > 0) {\n const sorted = Object.entries(groupTally).sort(([, a], [, b]) => b - a);\n console.log(\"\");\n console.log(` ${sectionTitle(\"top words\")}`);\n for (const [group, count] of sorted.slice(0, 10)) {\n const variants = variantTally[group] ?? {};\n const variantList = Object.entries(variants)\n .sort(([, a], [, b]) => b - a)\n .filter(([v]) => v !== group)\n .slice(0, 15)\n .map(([v, cnt]) => `${c.dim}${v}${c.reset} ${cnt}`)\n .join(`${c.dim},${c.reset} `);\n const suffix = variantList ? ` ${c.dim}(${c.reset}${variantList}${c.dim})${c.reset}` : \"\";\n console.log(\n ` ${c.yellow}${group.padEnd(12)}${c.reset} ${c.bold}${String(count).padStart(4)}${c.reset}${suffix}`,\n );\n }\n }\n\n console.log(\"\");\n if (totalSwears === 0) {\n console.log(` ${c.green}squeaky clean! not a single swear found.${c.reset}`);\n console.log(\"\");\n }\n}\n\nexport async function cost(args: string[]): Promise<void> {\n const options = parseCostArgs(args);\n const adapters = options.agent ? [createAdapter(options.agent)] : allAdapters();\n const costByAgent: Record<string, CostSummary> = {};\n const spinner = createSpinner(COST_SPINNER_MESSAGES);\n let totals: CostTotals | null = null;\n\n spinner.start(\"Loading price catalog\");\n try {\n const pricing = await loadPricingCatalog({ refresh: options.refreshPrices });\n for (const adapter of adapters) {\n if (!adapter.usage) {\n continue;\n }\n\n spinner.update(`Reading ${adapter.name} usage`);\n const summary = await summarizeUsage(adapter.usage({ since: options.since }), pricing);\n if (summary.requests > 0) {\n costByAgent[adapter.name] = summary;\n }\n }\n\n totals = getCostTotals(costByAgent);\n } finally {\n spinner.stop();\n }\n\n if (!totals || totals.entries.length === 0) {\n console.log(\"\");\n printCostCommandUnavailable(options);\n return;\n }\n\n spinner.start(\"Writing cost report\");\n let reportUrl: string;\n try {\n reportUrl = await writeCostHtmlReport(totals, options);\n } finally {\n spinner.stop();\n }\n\n console.log(\"\");\n printCostCommand(totals, options, reportUrl);\n}\n\nfunction printCostCommand(totals: CostTotals, options: ScanOptions, reportUrl: string): void {\n const modelTotals = aggregateModelCosts(totals.entries);\n\n printCompactHeader(options);\n printCompactTotal(totals);\n printCompactAgents(totals.entries);\n printCompactModels(modelTotals, totals.totalCost);\n console.log(\"\");\n console.log(` ${c.dim}Report:${c.reset} ${reportUrl}`);\n console.log(\"\");\n}\n\nfunction printCompactHeader(options: ScanOptions): void {\n const filters = [\n options.agent,\n options.rangeLabel ?? (options.since ? `since ${formatDate(options.since)}` : null),\n ].filter(Boolean);\n const suffix = filters.length > 0 ? ` ${c.dim}${filters.join(\" \u00B7 \")}${c.reset}` : \"\";\n console.log(` ${c.bold}${c.red}devrage${c.reset} ${c.dim}cost${c.reset}${suffix}`);\n console.log(\"\");\n}\n\nfunction compactMeta(totals: CostTotals): string {\n const parts = [formatRequests(totals.pricedRequests)];\n if (totals.unpricedRequests > 0) {\n parts.push(`${formatNumber(totals.unpricedRequests)} unpriced`);\n }\n\n return `${c.dim}${parts.join(\" \u00B7 \")}${c.reset}`;\n}\n\nfunction printCompactTotal(totals: CostTotals): void {\n console.log(` ${c.bold}total${c.reset}`);\n console.log(\n ` ${c.bold}${c.green}${formatCurrency(totals.totalCost)}${c.reset} ${compactMeta(totals)}`,\n );\n}\n\nfunction printCompactModels(models: CostModelSummary[], totalCost: number): void {\n if (models.length === 0) {\n return;\n }\n\n const visibleModels = models.slice(0, MAX_TERMINAL_MODELS);\n const maxCost = visibleModels[0]?.estimatedCost ?? 0;\n console.log(\"\");\n console.log(` ${c.bold}models${c.reset}`);\n for (const model of visibleModels) {\n const share = totalCost > 0 ? model.estimatedCost / totalCost : 0;\n const color = modelColor(model);\n console.log(\n ` ${colorText(clip(model.model, 27).padEnd(27), color)} ${formatCurrency(model.estimatedCost).padStart(9)} ${c.dim}${formatPercent(share).padStart(6)}${c.reset} ${renderBar(model.estimatedCost, maxCost, 16, color)}`,\n );\n }\n}\n\nfunction printCompactAgents(entries: [string, CostSummary][]): void {\n console.log(\"\");\n console.log(` ${c.bold}agents${c.reset}`);\n for (const [name, stats] of entries.sort(\n ([, left], [, right]) => right.estimatedCost - left.estimatedCost,\n )) {\n const color = agentColor(name);\n console.log(\n ` ${colorText(name.padEnd(10), color)} ${colorText(formatCurrency(stats.estimatedCost).padStart(9), color)} ${c.dim}${formatRequests(stats.requests).padStart(12)}${c.reset}`,\n );\n }\n}\n\nfunction printCostCommandUnavailable(options: ScanOptions): void {\n printCompactHeader(options);\n console.log(` ${c.gray}no local usage found${c.reset}`);\n console.log(\"\");\n}\n\nasync function writeCostHtmlReport(totals: CostTotals, options: ScanOptions): Promise<string> {\n const generatedAt = new Date().toISOString();\n const reportPath = join(\n dirname(getPricingCachePath()),\n `cost-report-${safeTimestamp(generatedAt)}.html`,\n );\n await mkdir(dirname(reportPath), { recursive: true });\n await writeFile(\n reportPath,\n renderCostHtmlReport(costReportData(totals, options, generatedAt)),\n \"utf-8\",\n );\n return pathToFileURL(reportPath).href;\n}\n\nfunction safeTimestamp(value: string): string {\n return value.replace(/[:.]/g, \"-\");\n}\n\nfunction costReportData(\n totals: CostTotals,\n options: ScanOptions,\n generatedAt: string,\n): CostReportData {\n return {\n generatedAt,\n scope:\n options.rangeLabel ??\n (options.since ? `since ${formatDate(options.since)}` : \"all local history\"),\n totalCost: totals.totalCost,\n pricedRequests: totals.pricedRequests,\n unpricedRequests: totals.unpricedRequests,\n agents: totals.entries\n .map(([name, summary]) => ({\n name,\n estimatedCost: summary.estimatedCost,\n requests: summary.requests - summary.unpricedRequests,\n models: summary.models.map(costReportModel),\n days: summary.days.map((day) => ({\n day: day.day,\n estimatedCost: day.estimatedCost,\n requests: day.requests - day.unpricedRequests,\n models: day.models.map(costReportModel),\n })),\n }))\n .sort((left, right) => right.estimatedCost - left.estimatedCost),\n };\n}\n\nfunction costReportModel(model: CostModelSummary): CostReportModel {\n return {\n model: model.model,\n provider: model.provider,\n estimatedCost: model.estimatedCost,\n requests: model.requests - model.unpricedRequests,\n inputTokens: model.inputTokens,\n outputTokens: model.outputTokens,\n reasoningTokens: model.reasoningTokens,\n cacheReadTokens: model.cacheReadTokens,\n cacheWriteTokens: model.cacheWriteTokens,\n };\n}\n\nfunction renderCostHtmlReport(data: CostReportData): string {\n return `<!doctype html>\n<html lang=\"en\">\n<head>\n <meta charset=\"utf-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n <title>devrage cost report</title>\n <style>\n :root {\n color-scheme: dark;\n --bg: #0f1117;\n --panel: #151923;\n --panel-2: #10141c;\n --border: #283040;\n --text: #edf1f7;\n --muted: #99a3b5;\n --faint: #677184;\n --green: #55c98f;\n --purple: #b18cff;\n --blue: #75a7ff;\n --yellow: #e5b75f;\n --cyan: #62c7df;\n }\n * { box-sizing: border-box; }\n body {\n margin: 0;\n background: var(--bg);\n color: var(--text);\n font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif;\n line-height: 1.45;\n }\n main { width: min(1180px, calc(100vw - 32px)); margin: 0 auto; padding: 28px 0 48px; }\n header { display: flex; justify-content: space-between; gap: 20px; align-items: end; margin-bottom: 22px; }\n h1 { margin: 0; font-size: 22px; letter-spacing: -0.02em; }\n .scope { color: var(--muted); font-size: 13px; margin-top: 4px; }\n .generated { color: var(--faint); font-size: 12px; text-align: right; }\n .summary { display: grid; grid-template-columns: 1.4fr repeat(3, 1fr); gap: 12px; margin-bottom: 18px; }\n .card, .panel { border: 1px solid var(--border); background: var(--panel); }\n .card { padding: 16px; min-height: 92px; }\n .label { color: var(--muted); font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.1em; }\n .value { margin-top: 8px; font-size: 26px; font-weight: 800; letter-spacing: -0.03em; font-variant-numeric: tabular-nums; }\n .primary .value { color: var(--green); font-size: 42px; }\n .controls { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; margin: 18px 0; }\n label { display: grid; gap: 6px; color: var(--muted); font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.08em; }\n select { width: 100%; border: 1px solid var(--border); background: var(--panel-2); color: var(--text); padding: 10px 12px; font: inherit; border-radius: 0; }\n .grid { display: grid; grid-template-columns: 1fr; gap: 14px; align-items: start; }\n .panel { min-width: 0; }\n .panel h2 { margin: 0; padding: 13px 14px; border-bottom: 1px solid var(--border); font-size: 13px; text-transform: uppercase; letter-spacing: 0.1em; color: var(--muted); }\n .panel-body { padding: 14px; }\n table { width: 100%; border-collapse: collapse; font-variant-numeric: tabular-nums; }\n th, td { padding: 9px 8px; border-bottom: 1px solid #202838; text-align: left; white-space: nowrap; }\n th { color: var(--faint); font-size: 11px; text-transform: uppercase; letter-spacing: 0.08em; }\n td:not(:first-child), th:not(:first-child) { text-align: right; }\n tr:last-child td { border-bottom: 0; }\n .name { color: var(--text); font-weight: 650; }\n .muted { color: var(--muted); }\n .chart-wrap { min-width: 0; }\n .chart { width: 100%; min-width: 0; height: 190px; display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); gap: clamp(1px, 0.55vw, 8px); align-items: end; overflow: hidden; }\n .bar-column { display: flex; align-items: end; min-width: 0; height: 190px; overflow: hidden; font-variant-numeric: tabular-nums; }\n .chart-empty { align-self: center; }\n .axis { position: relative; height: 24px; margin-top: 8px; border-top: 1px solid #202838; color: var(--muted); font-size: 10px; font-variant-numeric: tabular-nums; overflow: hidden; }\n .axis-tick { position: absolute; top: 6px; transform: translateX(-50%); white-space: nowrap; }\n .axis-tick.edge-start { transform: translateX(0); }\n .axis-tick.edge-end { transform: translateX(-100%); }\n .column-track { width: 100%; min-width: 0; height: 190px; display: flex; align-items: end; background: #202838; overflow: hidden; }\n .column-fill { width: 100%; min-height: 2px; background: var(--cyan); }\n .legend { display: flex; flex-wrap: wrap; gap: 10px 14px; color: var(--muted); font-size: 12px; margin-top: 12px; }\n .dot { display: inline-block; width: 9px; height: 9px; margin-right: 5px; background: var(--cyan); }\n .tooltip { position: fixed; z-index: 20; display: none; pointer-events: none; border: 1px solid var(--border); background: #0b0e14; color: var(--text); padding: 7px 9px; font-size: 12px; font-variant-numeric: tabular-nums; box-shadow: 0 8px 20px rgba(0, 0, 0, 0.35); }\n .tooltip .sub { color: var(--muted); margin-top: 2px; }\n .green { color: var(--green); } .purple { color: var(--purple); } .blue { color: var(--blue); } .yellow { color: var(--yellow); } .cyan { color: var(--cyan); }\n .bg-green { background: var(--green); } .bg-purple { background: var(--purple); } .bg-blue { background: var(--blue); } .bg-yellow { background: var(--yellow); } .bg-cyan { background: var(--cyan); }\n @media (max-width: 900px) { header, .grid { display: block; } .summary, .controls { grid-template-columns: 1fr; } .panel { margin-top: 14px; } .generated { text-align: left; margin-top: 8px; } }\n </style>\n</head>\n<body>\n <main>\n <header>\n <div>\n <h1>devrage cost report</h1>\n <div class=\"scope\" id=\"scope\"></div>\n </div>\n <div class=\"generated\" id=\"generated\"></div>\n </header>\n <section class=\"summary\">\n <div class=\"card primary\"><div class=\"label\">total</div><div class=\"value\" id=\"totalCost\"></div></div>\n <div class=\"card\"><div class=\"label\">requests</div><div class=\"value\" id=\"requestCount\"></div></div>\n <div class=\"card\"><div class=\"label\">models</div><div class=\"value\" id=\"modelCount\"></div></div>\n <div class=\"card\"><div class=\"label\">agents</div><div class=\"value\" id=\"agentCount\"></div></div>\n </section>\n <section class=\"controls\">\n <label>Agent<select id=\"agentFilter\"></select></label>\n <label>Model<select id=\"modelFilter\"></select></label>\n <label>Range<select id=\"rangeFilter\"><option value=\"all\">All included data</option><option value=\"7\">Last 7 days</option><option value=\"30\">Last 30 days</option><option value=\"90\">Last 90 days</option></select></label>\n </section>\n <section class=\"grid\">\n <div class=\"panel\"><h2>Agents</h2><div class=\"panel-body\"><table><thead><tr><th>Agent</th><th>Cost</th><th>Reqs</th></tr></thead><tbody id=\"agentRows\"></tbody></table></div></div>\n <div class=\"panel\"><h2>Models</h2><div class=\"panel-body\"><table><thead><tr><th>Model</th><th>Cost</th><th>Share</th><th>Reqs</th><th>Input</th><th>Output</th><th>Cache</th></tr></thead><tbody id=\"modelRows\"></tbody></table><div class=\"legend\"><span><i class=\"dot bg-purple\"></i>Claude/Anthropic</span><span><i class=\"dot bg-green\"></i>OpenAI</span><span><i class=\"dot bg-blue\"></i>Google</span><span><i class=\"dot bg-yellow\"></i>Kimi/GLM</span></div></div></div>\n <div class=\"panel\"><h2>Daily</h2><div class=\"panel-body\"><div class=\"chart-wrap\"><div class=\"chart\" id=\"dailyChart\"></div><div class=\"axis\" id=\"dailyAxis\"></div></div></div></div>\n </section>\n <div class=\"tooltip\" id=\"tooltip\"></div>\n </main>\n <script>\n const DATA = ${jsonForScript(data)};\n const $ = (id) => document.getElementById(id);\n const money = (value) => '$' + (Math.floor(Math.max(0, value) * 100 + 1e-9) / 100).toFixed(2);\n const number = (value) => Math.round(value).toLocaleString('en-US');\n const pct = (value) => (value * 100).toFixed(1) + '%';\n const esc = (value) => String(value).replace(/[&<>\"']/g, (ch) => ({'&':'&amp;','<':'&lt;','>':'&gt;','\"':'&quot;',\"'\":'&#39;'}[ch]));\n const modelClass = (name, provider) => {\n const model = String(name || '').toLowerCase();\n const p = String(provider || '').toLowerCase();\n if (p === 'anthropic' || model.startsWith('claude-')) return 'purple';\n if (p === 'openai' || model.startsWith('gpt-') || /^o\\\\d/.test(model)) return 'green';\n if (p === 'google' || model.startsWith('gemini-')) return 'blue';\n if (model.startsWith('kimi-') || model.startsWith('glm-')) return 'yellow';\n return 'cyan';\n };\n const shortDate = (day) => new Date(day + 'T00:00:00.000Z').toLocaleDateString('en-US', {month:'short', day:'numeric', timeZone:'UTC'});\n function dailyTicks(days) {\n const count = days.length;\n if (count === 0) return [];\n const maxTicks = count <= 7 ? count : count <= 31 ? 6 : count <= 90 ? 7 : 9;\n if (maxTicks <= 1) return [{index: 0, day: days[0].day}];\n const ticks = [];\n const seen = new Set();\n for (let tick = 0; tick < maxTicks; tick++) {\n const index = Math.round(((count - 1) * tick) / (maxTicks - 1));\n if (seen.has(index)) continue;\n seen.add(index);\n ticks.push({index, day: days[index].day});\n }\n return ticks;\n }\n function addModel(map, incoming) {\n const key = incoming.model;\n const row = map.get(key) || {model: incoming.model, provider: incoming.provider, estimatedCost: 0, requests: 0, inputTokens: 0, outputTokens: 0, reasoningTokens: 0, cacheReadTokens: 0, cacheWriteTokens: 0};\n row.estimatedCost += incoming.estimatedCost; row.requests += incoming.requests;\n row.inputTokens += incoming.inputTokens; row.outputTokens += incoming.outputTokens; row.reasoningTokens += incoming.reasoningTokens;\n row.cacheReadTokens += incoming.cacheReadTokens; row.cacheWriteTokens += incoming.cacheWriteTokens;\n map.set(key, row);\n }\n function filteredAgents() {\n const selected = $('agentFilter').value;\n return DATA.agents.filter((agent) => selected === 'all' || agent.name === selected);\n }\n function dayAllowed(day) {\n const range = $('rangeFilter').value;\n if (range === 'all') return true;\n const cutoff = new Date(DATA.generatedAt).getTime() - Number(range) * 24 * 60 * 60 * 1000;\n return new Date(day + 'T23:59:59.999Z').getTime() >= cutoff;\n }\n function selectedModelRows(models) {\n const selected = $('modelFilter').value;\n return models.filter((model) => selected === 'all' || model.model === selected);\n }\n function compute() {\n const agents = filteredAgents();\n const modelMap = new Map();\n const dayMap = new Map();\n let totalCost = 0, requests = 0;\n for (const agent of agents) {\n const models = selectedModelRows(agent.models);\n for (const model of models) { addModel(modelMap, model); totalCost += model.estimatedCost; requests += model.requests; }\n for (const day of agent.days) {\n if (!dayAllowed(day.day)) continue;\n const dayModels = selectedModelRows(day.models);\n const cost = dayModels.reduce((sum, model) => sum + model.estimatedCost, 0);\n const reqs = dayModels.reduce((sum, model) => sum + model.requests, 0);\n if (cost <= 0 && reqs <= 0) continue;\n const row = dayMap.get(day.day) || {day: day.day, estimatedCost: 0, requests: 0};\n row.estimatedCost += cost; row.requests += reqs; dayMap.set(day.day, row);\n }\n }\n return {agents, models: Array.from(modelMap.values()).sort((a,b) => b.estimatedCost - a.estimatedCost), days: Array.from(dayMap.values()).sort((a,b) => a.day.localeCompare(b.day)), totalCost, requests};\n }\n function render() {\n const view = compute();\n $('totalCost').textContent = money(view.totalCost);\n $('requestCount').textContent = number(view.requests);\n $('modelCount').textContent = number(view.models.length);\n $('agentCount').textContent = number(view.agents.length);\n const agentRows = view.agents.map((agent) => '<tr><td class=\"name\">' + esc(agent.name) + '</td><td>' + money(agent.estimatedCost) + '</td><td>' + number(agent.requests) + '</td></tr>').join('');\n $('agentRows').innerHTML = agentRows || '<tr><td colspan=\"3\" class=\"muted\">No data</td></tr>';\n const maxModel = Math.max(1, ...view.models.map((model) => model.estimatedCost));\n $('modelRows').innerHTML = view.models.map((model) => {\n const klass = modelClass(model.model, model.provider);\n const cache = model.cacheReadTokens + model.cacheWriteTokens;\n return '<tr><td class=\"name ' + klass + '\">' + esc(model.model) + '</td><td>' + money(model.estimatedCost) + '</td><td>' + pct(view.totalCost > 0 ? model.estimatedCost / view.totalCost : 0) + '</td><td>' + number(model.requests) + '</td><td>' + number(model.inputTokens) + '</td><td>' + number(model.outputTokens + model.reasoningTokens) + '</td><td>' + number(cache) + '</td></tr>';\n }).join('') || '<tr><td colspan=\"7\" class=\"muted\">No data</td></tr>';\n const maxDay = Math.max(1, ...view.days.map((day) => day.estimatedCost));\n $('dailyChart').innerHTML = view.days.length ? view.days.map((day) => {\n const tooltip = esc(shortDate(day.day) + '|' + money(day.estimatedCost) + '|' + number(day.requests) + ' reqs');\n return '<div class=\"bar-column\" data-tooltip=\"' + tooltip + '\"><div class=\"column-track\"><div class=\"column-fill\" style=\"height:' + Math.max(1, (day.estimatedCost / maxDay) * 100) + '%\"></div></div></div>';\n }).join('') : '<div class=\"muted chart-empty\">No data</div>';\n $('dailyAxis').innerHTML = dailyTicks(view.days).map((tick) => {\n const left = view.days.length === 1 ? 50 : ((tick.index + 0.5) / view.days.length) * 100;\n const edge = view.days.length === 1 ? '' : tick.index === 0 ? ' edge-start' : tick.index === view.days.length - 1 ? ' edge-end' : '';\n return '<span class=\"axis-tick' + edge + '\" style=\"left:' + left.toFixed(4) + '%\">' + esc(shortDate(tick.day)) + '</span>';\n }).join('');\n }\n function showTooltip(event) {\n const target = event.target.closest('[data-tooltip]');\n const tooltip = $('tooltip');\n if (!target) { tooltip.style.display = 'none'; return; }\n const [date, amount, requests] = target.dataset.tooltip.split('|');\n tooltip.innerHTML = '<div>' + esc(date) + '</div><div class=\"sub\">' + esc(amount) + ' \u00B7 ' + esc(requests) + '</div>';\n tooltip.style.display = 'block';\n moveTooltip(event);\n }\n function moveTooltip(event) {\n const tooltip = $('tooltip');\n if (tooltip.style.display !== 'block') return;\n const offset = 12;\n const nextLeft = Math.min(window.innerWidth - tooltip.offsetWidth - 8, event.clientX + offset);\n const nextTop = Math.min(window.innerHeight - tooltip.offsetHeight - 8, event.clientY + offset);\n tooltip.style.left = Math.max(8, nextLeft) + 'px';\n tooltip.style.top = Math.max(8, nextTop) + 'px';\n }\n function init() {\n $('scope').textContent = DATA.scope;\n $('generated').textContent = 'Generated ' + new Date(DATA.generatedAt).toLocaleString();\n $('agentFilter').innerHTML = '<option value=\"all\">All agents</option>' + DATA.agents.map((agent) => '<option value=\"' + esc(agent.name) + '\">' + esc(agent.name) + '</option>').join('');\n const models = Array.from(new Set(DATA.agents.flatMap((agent) => agent.models.map((model) => model.model)))).sort();\n $('modelFilter').innerHTML = '<option value=\"all\">All models</option>' + models.map((model) => '<option value=\"' + esc(model) + '\">' + esc(model) + '</option>').join('');\n ['agentFilter', 'modelFilter', 'rangeFilter'].forEach((id) => $(id).addEventListener('change', render));\n $('dailyChart').addEventListener('mouseover', showTooltip);\n $('dailyChart').addEventListener('mousemove', moveTooltip);\n $('dailyChart').addEventListener('mouseleave', () => { $('tooltip').style.display = 'none'; });\n render();\n }\n init();\n </script>\n</body>\n</html>`;\n}\n\nfunction jsonForScript(value: unknown): string {\n return JSON.stringify(value).replace(/</g, \"\\\\u003c\");\n}\n\nfunction printReportHeader(options: ScanOptions): void {\n const scope =\n options.rangeLabel ??\n (options.since ? `since ${formatDate(options.since)}` : \"all local history\");\n const agent = options.agent ? ` \u00B7 ${options.agent}` : \"\";\n console.log(` ${c.bold}${c.red}devrage${c.reset} ${c.dim}report${c.reset}`);\n console.log(` ${c.dim}${scope}${agent}${c.reset}`);\n console.log(` ${c.dim}${\"\u2500\".repeat(54)}${c.reset}`);\n}\n\nfunction printBasicOverview(totalMessages: number, totalSwears: number): void {\n console.log(\n ` ${c.dim}messages scanned${c.reset} ${c.bold}${formatNumber(totalMessages)}${c.reset}`,\n );\n console.log(\n ` ${c.dim}total swears${c.reset} ${c.bold}${c.red}${formatNumber(totalSwears)}${c.reset}`,\n );\n}\n\nfunction getCostTotals(costByAgent: Record<string, CostSummary>): CostTotals {\n const entries = Object.entries(costByAgent);\n const totalCost = entries.reduce((sum, [, stats]) => sum + stats.estimatedCost, 0);\n const totalRequests = entries.reduce((sum, [, stats]) => sum + stats.requests, 0);\n const unpricedRequests = entries.reduce((sum, [, stats]) => sum + stats.unpricedRequests, 0);\n\n return {\n entries,\n totalCost,\n totalRequests,\n pricedRequests: totalRequests - unpricedRequests,\n unpricedRequests,\n };\n}\n\nfunction aggregateModelCosts(entries: [string, CostSummary][]): CostModelSummary[] {\n const models = new Map<string, CostModelSummary>();\n\n for (const [, stats] of entries) {\n for (const model of stats.models) {\n mergeModelSummary(models, model);\n }\n }\n\n return sortedCostModels(models);\n}\n\nfunction mergeModelSummary(\n models: Map<string, CostModelSummary>,\n incoming: CostModelSummary,\n): void {\n const key = incoming.model;\n let model = models.get(key);\n\n if (!model) {\n models.set(key, { ...incoming });\n return;\n }\n\n model.requests += incoming.requests;\n model.estimatedCost += incoming.estimatedCost;\n model.billedCost += incoming.billedCost;\n model.pricingSource = mergeDisplayPricingSource(model.pricingSource, incoming.pricingSource);\n model.unpricedRequests += incoming.unpricedRequests;\n model.inputTokens += incoming.inputTokens;\n model.outputTokens += incoming.outputTokens;\n model.reasoningTokens += incoming.reasoningTokens;\n model.cacheReadTokens += incoming.cacheReadTokens;\n model.cacheWriteTokens += incoming.cacheWriteTokens;\n}\n\nfunction sortedCostModels(models: Map<string, CostModelSummary>): CostModelSummary[] {\n return Array.from(models.values()).sort(\n (left, right) => right.estimatedCost - left.estimatedCost || right.requests - left.requests,\n );\n}\n\nfunction mergeDisplayPricingSource(left: PricingSource, right: PricingSource): PricingSource {\n return left === right ? left : \"mixed\";\n}\n\nfunction sectionTitle(label: string): string {\n const width = 54;\n const lineLength = Math.max(4, width - label.length - 1);\n return `${c.bold}${label}${c.reset} ${c.dim}${\"\u2500\".repeat(lineLength)}${c.reset}`;\n}\n\nfunction colorText(value: string, color: string): string {\n return `${color}${value}${c.reset}`;\n}\n\nfunction agentColor(agent: string): string {\n switch (agent) {\n case \"claude\":\n return c.magenta;\n case \"codex\":\n return c.green;\n case \"opencode\":\n return c.cyan;\n case \"amp\":\n return c.yellow;\n case \"pi\":\n return c.blue;\n case \"cursor\":\n return c.blue;\n default:\n return c.white;\n }\n}\n\nfunction modelColor(model: CostModelSummary): string {\n const provider = model.provider?.toLowerCase();\n const modelName = model.model.toLowerCase();\n\n if (provider === \"anthropic\" || modelName.startsWith(\"claude-\")) {\n return c.magenta;\n }\n if (provider === \"openai\" || modelName.startsWith(\"gpt-\") || /^o\\d/.test(modelName)) {\n return c.green;\n }\n if (provider === \"google\" || modelName.startsWith(\"gemini-\")) {\n return c.blue;\n }\n if (modelName.startsWith(\"kimi-\") || modelName.startsWith(\"glm-\")) {\n return c.yellow;\n }\n\n return c.cyan;\n}\n\nfunction renderBar(value: number, max: number, width: number, color = c.cyan): string {\n const filled = max > 0 && value > 0 ? Math.max(1, Math.round((value / max) * width)) : 0;\n const empty = width - filled;\n return `${color}${\"\u2501\".repeat(filled)}${c.gray}${\"\u2500\".repeat(empty)}${c.reset}`;\n}\n\nfunction clip(value: string, maxLength: number): string {\n return value.length <= maxLength ? value : `${value.slice(0, maxLength - 1)}\u2026`;\n}\n\nfunction formatCurrency(value: number): string {\n const cents = Math.floor(Math.max(0, value) * 100 + 1e-9);\n return `$${(cents / 100).toFixed(2)}`;\n}\n\nfunction formatNumber(value: number): string {\n return value.toLocaleString(\"en-US\");\n}\n\nfunction formatRequests(value: number): string {\n return `${formatNumber(value)} ${value === 1 ? \"req\" : \"reqs\"}`;\n}\n\nfunction formatPercent(value: number): string {\n return `${(value * 100).toFixed(1)}%`;\n}\n\nfunction formatDate(value: Date): string {\n return value.toISOString().slice(0, 10);\n}\n", "import { readdir, readFile } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport type { Adapter, AdapterOptions, Message, UsageRecord } from \"./index\";\n\n/**\n * Amp (Sourcegraph) stores threads as JSON files at:\n * ~/.local/share/amp/threads/<thread-id>.json\n *\n * Each file is a JSON object with a `messages` array:\n * { \"messages\": [{ \"role\": \"user\"|\"assistant\", \"content\": \"...\", ... }], \"usageLedger\": {...}, ... }\n *\n * Messages have `role`, `content` (string or array), and optionally a timestamp.\n */\n\nfunction getAmpThreadsDir(): string {\n return join(process.env[\"XDG_DATA_HOME\"] ?? join(homedir(), \".local\", \"share\"), \"amp\", \"threads\");\n}\n\nexport function ampAdapter(): Adapter {\n return {\n name: \"amp\",\n async *messages(options?: AdapterOptions): AsyncGenerator<Message> {\n const threadsDir = getAmpThreadsDir();\n\n let files: string[];\n try {\n files = await readdir(threadsDir);\n } catch {\n return; // Amp not installed or no threads\n }\n\n const jsonFiles = files.filter((f) => f.endsWith(\".json\"));\n\n for (const file of jsonFiles) {\n const filePath = join(threadsDir, file);\n const threadId = file.replace(\".json\", \"\");\n\n try {\n const thread = await readAmpThread(filePath);\n if (!thread) {\n continue;\n }\n\n if (!thread.messages || !Array.isArray(thread.messages)) {\n continue;\n }\n\n for (const msg of thread.messages) {\n if (msg.role !== \"user\") {\n continue;\n }\n\n const text = extractText(msg.content);\n if (!text) {\n continue;\n }\n\n const timestamp = msg.timestamp ?? msg.createdAt ?? undefined;\n if (options?.since && timestamp) {\n const ts = new Date(timestamp);\n if (ts < options.since) {\n continue;\n }\n }\n\n yield {\n text,\n timestamp,\n session: threadId,\n };\n }\n } catch {\n // Skip malformed files\n }\n }\n },\n async *usage(options?: AdapterOptions): AsyncGenerator<UsageRecord> {\n const threadsDir = getAmpThreadsDir();\n\n let files: string[];\n try {\n files = await readdir(threadsDir);\n } catch {\n return;\n }\n\n for (const file of files.filter((f) => f.endsWith(\".json\"))) {\n const filePath = join(threadsDir, file);\n const threadId = file.replace(\".json\", \"\");\n\n try {\n const thread = await readAmpThread(filePath);\n if (!thread?.usageLedger) {\n continue;\n }\n\n for (const record of extractAmpUsageRecords(thread.usageLedger, threadId)) {\n if (options?.since && record.timestamp) {\n const ts = new Date(record.timestamp);\n if (ts < options.since) {\n continue;\n }\n }\n\n yield record;\n }\n } catch {\n // Skip malformed files\n }\n }\n },\n };\n}\n\nasync function readAmpThread(filePath: string): Promise<AmpThread | null> {\n const raw = await readFile(filePath, \"utf-8\");\n const parsed = JSON.parse(raw) as unknown;\n return asRecord(parsed) ? (parsed as AmpThread) : null;\n}\n\nfunction extractText(content: unknown): string | null {\n if (typeof content === \"string\") {\n return content;\n }\n if (Array.isArray(content)) {\n const parts = content\n .filter(\n (p): p is { type: string; text: string } =>\n typeof p === \"object\" && p !== null && typeof p.text === \"string\",\n )\n .map((p) => p.text);\n return parts.length > 0 ? parts.join(\" \") : null;\n }\n return null;\n}\n\ninterface AmpMessage {\n role?: string;\n content?: unknown;\n timestamp?: string;\n createdAt?: string;\n}\n\ninterface AmpThread {\n messages?: AmpMessage[];\n usageLedger?: unknown;\n}\n\ninterface AmpUsageContext {\n provider?: string;\n model?: string;\n timestamp?: string;\n}\n\nfunction extractAmpUsageRecords(usageLedger: unknown, threadId: string): UsageRecord[] {\n const records: UsageRecord[] = [];\n collectAmpUsage(usageLedger, threadId, records, {});\n return records;\n}\n\nfunction collectAmpUsage(\n value: unknown,\n threadId: string,\n records: UsageRecord[],\n context: AmpUsageContext,\n depth = 0,\n): void {\n if (depth > 12) {\n return;\n }\n\n if (Array.isArray(value)) {\n for (const item of value) {\n collectAmpUsage(item, threadId, records, context, depth + 1);\n }\n return;\n }\n\n const record = asRecord(value);\n if (!record) {\n return;\n }\n\n const nextContext = {\n provider: stringField(record, [\"provider\", \"providerID\", \"providerId\"]) ?? context.provider,\n model: stringField(record, [\"model\", \"modelID\", \"modelId\"]) ?? context.model,\n timestamp: timestampField(record) ?? context.timestamp,\n };\n const usageSource = firstRecordField(record, [\"usage\", \"tokens\", \"tokenUsage\"]) ?? record;\n const rawInputTokens = tokenField(usageSource, [\"inputTokens\", \"input_tokens\", \"promptTokens\"]);\n const outputTokens = tokenField(usageSource, [\n \"outputTokens\",\n \"output_tokens\",\n \"completionTokens\",\n ]);\n const reasoningTokens = tokenField(usageSource, [\"reasoningTokens\", \"reasoning_output_tokens\"]);\n const cachedInputSubset = tokenField(usageSource, [\"cachedInputTokens\", \"cached_input_tokens\"]);\n const cacheReadTokens = tokenField(usageSource, [\n \"cacheReadTokens\",\n \"cache_read_tokens\",\n \"cacheReadInputTokens\",\n \"cache_read_input_tokens\",\n \"cachedInputTokens\",\n \"cached_input_tokens\",\n ]);\n const inputTokens = Math.max(rawInputTokens - cachedInputSubset, 0);\n const cacheWriteTokens = tokenField(usageSource, [\n \"cacheWriteTokens\",\n \"cache_write_tokens\",\n \"cacheCreationInputTokens\",\n \"cache_creation_input_tokens\",\n \"cacheWriteInputTokens\",\n \"cache_write_input_tokens\",\n ]);\n const billedCost = tokenField(record, [\n \"cost\",\n \"totalCost\",\n \"total_cost\",\n \"billedCost\",\n \"billed_cost\",\n ]);\n\n if (\n inputTokens + outputTokens + reasoningTokens + cacheReadTokens + cacheWriteTokens + billedCost >\n 0\n ) {\n records.push({\n agent: \"amp\",\n provider: nextContext.provider,\n model: nextContext.model,\n timestamp: nextContext.timestamp,\n session: threadId,\n billedCost,\n inputTokens,\n outputTokens,\n reasoningTokens,\n cacheReadTokens,\n cacheWriteTokens,\n });\n }\n\n for (const child of Object.values(record)) {\n if (child !== usageSource && typeof child === \"object\" && child !== null) {\n collectAmpUsage(child, threadId, records, nextContext, depth + 1);\n }\n }\n}\n\nfunction firstRecordField(\n record: Record<string, unknown>,\n fields: string[],\n): Record<string, unknown> | null {\n for (const field of fields) {\n const value = asRecord(record[field]);\n if (value) {\n return value;\n }\n }\n\n return null;\n}\n\nfunction stringField(record: Record<string, unknown>, fields: string[]): string | undefined {\n for (const field of fields) {\n const value = record[field];\n if (typeof value === \"string\" && value.trim()) {\n return value;\n }\n }\n\n return undefined;\n}\n\nfunction timestampField(record: Record<string, unknown>): string | undefined {\n const value = stringField(record, [\"timestamp\", \"createdAt\", \"time\", \"date\"]);\n if (value) {\n const date = new Date(value);\n return Number.isFinite(date.getTime()) ? date.toISOString() : undefined;\n }\n\n return undefined;\n}\n\nfunction tokenField(record: Record<string, unknown>, fields: string[]): number {\n for (const field of fields) {\n const value = record[field];\n if (typeof value === \"number\" && Number.isFinite(value)) {\n return value;\n }\n }\n\n return 0;\n}\n\nfunction asRecord(value: unknown): Record<string, unknown> | null {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n return null;\n }\n\n return value as Record<string, unknown>;\n}\n", "import { createReadStream } from \"node:fs\";\nimport { readdir, stat } from \"node:fs/promises\";\nimport { createInterface } from \"node:readline\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport type { Adapter, AdapterOptions, Message, UsageRecord } from \"./index\";\n\n/**\n * Claude Code stores sessions as JSONL files at:\n * ~/.claude/projects/<project-path>/<session-uuid>.jsonl\n *\n * Each line is a JSON object. User messages have:\n * { \"type\": \"human\", \"message\": { \"content\": [...] } }\n * or sometimes:\n * { \"role\": \"user\", \"content\": \"...\" }\n */\n\nconst CLAUDE_DIR = join(homedir(), \".claude\", \"projects\");\n\nexport function claudeAdapter(): Adapter {\n return {\n name: \"claude\",\n async *messages(options?: AdapterOptions): AsyncGenerator<Message> {\n for await (const file of discoverClaudeJsonlFiles()) {\n yield* parseClaudeJsonl(file.filePath, { ...file, since: options?.since });\n }\n },\n async *usage(options?: AdapterOptions): AsyncGenerator<UsageRecord> {\n for await (const file of discoverClaudeJsonlFiles()) {\n yield* parseClaudeUsageJsonl(file.filePath, { ...file, since: options?.since });\n }\n },\n };\n}\n\nasync function* discoverClaudeJsonlFiles(): AsyncGenerator<{\n filePath: string;\n session: string;\n project: string;\n}> {\n let projectDirs: string[];\n try {\n projectDirs = await readdir(CLAUDE_DIR);\n } catch {\n return;\n }\n\n for (const projectDir of projectDirs) {\n const projectPath = join(CLAUDE_DIR, projectDir);\n const projectStat = await stat(projectPath);\n if (!projectStat.isDirectory()) {\n continue;\n }\n\n const entries = await readdir(projectPath);\n const jsonlFiles = entries.filter((f) => f.endsWith(\".jsonl\"));\n\n for (const file of jsonlFiles) {\n yield {\n filePath: join(projectPath, file),\n session: file.replace(\".jsonl\", \"\"),\n project: projectDir,\n };\n }\n\n // Also check for subagent JSONL files in session subdirectories\n const subdirs = entries.filter((f) => !f.includes(\".\"));\n for (const subdir of subdirs) {\n const subagentsDir = join(projectPath, subdir, \"subagents\");\n try {\n const subFiles = await readdir(subagentsDir);\n const subJsonl = subFiles.filter((f) => f.endsWith(\".jsonl\"));\n for (const file of subJsonl) {\n yield {\n filePath: join(subagentsDir, file),\n session: `${subdir}/${file.replace(\".jsonl\", \"\")}`,\n project: projectDir,\n };\n }\n } catch {\n // No subagents directory, skip\n }\n }\n }\n}\n\nasync function* parseClaudeJsonl(\n filePath: string,\n context: { session: string; project: string; since?: Date },\n): AsyncGenerator<Message> {\n const rl = createInterface({\n input: createReadStream(filePath, { encoding: \"utf-8\" }),\n crlfDelay: Infinity,\n });\n\n for await (const line of rl) {\n if (!line.trim()) {\n continue;\n }\n\n try {\n const entry = JSON.parse(line) as Record<string, unknown>;\n const text = extractUserText(entry);\n if (!text) {\n continue;\n }\n\n const timestamp = extractTimestamp(entry);\n if (context.since && timestamp) {\n const ts = new Date(timestamp);\n if (ts < context.since) {\n continue;\n }\n }\n\n yield {\n text,\n timestamp: timestamp ?? undefined,\n session: context.session,\n project: context.project,\n };\n } catch {\n // Skip malformed lines\n }\n }\n}\n\nfunction extractUserText(entry: Record<string, unknown>): string | null {\n // Format: { \"type\": \"user\", \"message\": { \"role\": \"user\", \"content\": \"...\" } }\n if (entry[\"type\"] === \"user\") {\n const message = entry[\"message\"] as Record<string, unknown> | undefined;\n if (!message) {\n return null;\n }\n return contentToString(message[\"content\"]);\n }\n\n // Legacy format: { \"type\": \"human\", \"message\": { \"content\": [...] } }\n if (entry[\"type\"] === \"human\") {\n const message = entry[\"message\"] as Record<string, unknown> | undefined;\n if (!message) {\n return null;\n }\n return contentToString(message[\"content\"]);\n }\n\n // Flat format: { \"role\": \"user\", \"content\": \"...\" }\n if (entry[\"role\"] === \"user\") {\n return contentToString(entry[\"content\"]);\n }\n\n return null;\n}\n\nfunction contentToString(content: unknown): string | null {\n if (typeof content === \"string\") {\n return content;\n }\n if (Array.isArray(content)) {\n const parts = content\n .filter(\n (p): p is { type: string; text: string } =>\n typeof p === \"object\" && p !== null && p.type === \"text\",\n )\n .map((p) => p.text);\n return parts.length > 0 ? parts.join(\" \") : null;\n }\n return null;\n}\n\nfunction extractTimestamp(entry: Record<string, unknown>): string | null {\n if (typeof entry[\"timestamp\"] === \"string\") {\n return entry[\"timestamp\"];\n }\n if (typeof entry[\"createdAt\"] === \"string\") {\n return entry[\"createdAt\"];\n }\n return null;\n}\n\n/** Claude Code repeats assistant rows while streaming, so request/message IDs are deduped. */\nasync function* parseClaudeUsageJsonl(\n filePath: string,\n context: { session: string; project: string; since?: Date },\n): AsyncGenerator<UsageRecord> {\n const rl = createInterface({\n input: createReadStream(filePath, { encoding: \"utf-8\" }),\n crlfDelay: Infinity,\n });\n const seen = new Set<string>();\n\n for await (const line of rl) {\n if (!line.trim()) {\n continue;\n }\n\n try {\n const entry = JSON.parse(line) as Record<string, unknown>;\n const message = asRecord(entry[\"message\"]);\n if (!message || entry[\"type\"] !== \"assistant\" || message[\"role\"] !== \"assistant\") {\n continue;\n }\n\n const usage = asRecord(message[\"usage\"]);\n if (!usage) {\n continue;\n }\n\n const model = stringValue(message[\"model\"]);\n const timestamp = extractTimestamp(entry) ?? undefined;\n if (context.since && timestamp) {\n const ts = new Date(timestamp);\n if (ts < context.since) {\n continue;\n }\n }\n\n const inputTokens = numberValue(usage[\"input_tokens\"]);\n const outputTokens = numberValue(usage[\"output_tokens\"]);\n const cacheReadTokens = numberValue(usage[\"cache_read_input_tokens\"]);\n const cacheWriteTokens = cacheCreationTokens(usage);\n if (inputTokens + outputTokens + cacheReadTokens + cacheWriteTokens === 0) {\n continue;\n }\n\n const dedupeKey =\n stringValue(entry[\"requestId\"]) ??\n stringValue(message[\"id\"]) ??\n `${context.session}:${timestamp ?? \"\"}:${model ?? \"unknown\"}:${inputTokens}:${outputTokens}`;\n if (seen.has(dedupeKey)) {\n continue;\n }\n seen.add(dedupeKey);\n\n yield {\n agent: \"claude\",\n provider: \"anthropic\",\n model,\n timestamp,\n session: context.session,\n inputTokens,\n outputTokens,\n reasoningTokens: 0,\n cacheReadTokens,\n cacheWriteTokens,\n };\n } catch {\n // Skip malformed lines\n }\n }\n}\n\nfunction cacheCreationTokens(usage: Record<string, unknown>): number {\n const explicit = numberValue(usage[\"cache_creation_input_tokens\"]);\n if (explicit > 0) {\n return explicit;\n }\n\n const cacheCreation = asRecord(usage[\"cache_creation\"]);\n return (\n numberValue(cacheCreation?.[\"ephemeral_1h_input_tokens\"]) +\n numberValue(cacheCreation?.[\"ephemeral_5m_input_tokens\"])\n );\n}\n\nfunction numberValue(value: unknown): number {\n return typeof value === \"number\" && Number.isFinite(value) ? value : 0;\n}\n\nfunction stringValue(value: unknown): string | undefined {\n return typeof value === \"string\" && value.trim() ? value : undefined;\n}\n\nfunction asRecord(value: unknown): Record<string, unknown> | null {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n return null;\n }\n\n return value as Record<string, unknown>;\n}\n", "import { readdir, readFile, stat } from \"node:fs/promises\";\nimport { existsSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport type { Adapter, AdapterOptions, Message } from \"./index\";\n\n/**\n * Cline (formerly Claude Dev) stores task history at:\n *\n * VS Code extension:\n * macOS: ~/Library/Application Support/Code/User/globalStorage/saoudrizwan.claude-dev/tasks/<task-id>/api_conversation_history.json\n * Linux: ~/.config/Code/User/globalStorage/saoudrizwan.claude-dev/tasks/<task-id>/api_conversation_history.json\n * Windows: %APPDATA%/Code/User/globalStorage/saoudrizwan.claude-dev/tasks/<task-id>/api_conversation_history.json\n *\n * Standalone CLI / JetBrains (newer):\n * ~/.cline/data/tasks/<task-id>/api_conversation_history.json\n *\n * Roo Code (fork) uses the same format at:\n * globalStorage/rooveterinaryinc.roo-cline/tasks/<task-id>/api_conversation_history.json\n *\n * Each api_conversation_history.json is a JSON array of messages:\n * [{ \"role\": \"user\"|\"assistant\", \"content\": \"...\" | [{type: \"text\", text: \"...\"}] }]\n */\n\nfunction getClineTaskDirs(): string[] {\n const dirs: string[] = [];\n\n // VS Code extension paths\n const vscodePaths = getVSCodeGlobalStoragePaths();\n const extensionIds = [\"saoudrizwan.claude-dev\", \"rooveterinaryinc.roo-cline\"];\n\n for (const basePath of vscodePaths) {\n for (const extId of extensionIds) {\n const tasksDir = join(basePath, extId, \"tasks\");\n if (existsSync(tasksDir)) {\n dirs.push(tasksDir);\n }\n }\n }\n\n // Standalone CLI path\n const clineStandalone = join(homedir(), \".cline\", \"data\", \"tasks\");\n if (existsSync(clineStandalone)) {\n dirs.push(clineStandalone);\n }\n\n return dirs;\n}\n\nfunction getVSCodeGlobalStoragePaths(): string[] {\n const paths: string[] = [];\n\n if (process.platform === \"darwin\") {\n paths.push(\n join(homedir(), \"Library\", \"Application Support\", \"Code\", \"User\", \"globalStorage\"),\n join(homedir(), \"Library\", \"Application Support\", \"Code - Insiders\", \"User\", \"globalStorage\"),\n join(homedir(), \"Library\", \"Application Support\", \"Cursor\", \"User\", \"globalStorage\"),\n );\n } else if (process.platform === \"linux\") {\n const configBase = process.env[\"XDG_CONFIG_HOME\"] ?? join(homedir(), \".config\");\n paths.push(\n join(configBase, \"Code\", \"User\", \"globalStorage\"),\n join(configBase, \"Code - Insiders\", \"User\", \"globalStorage\"),\n join(configBase, \"Cursor\", \"User\", \"globalStorage\"),\n );\n } else {\n // Windows\n const appData = process.env[\"APPDATA\"] ?? join(homedir(), \"AppData\", \"Roaming\");\n paths.push(\n join(appData, \"Code\", \"User\", \"globalStorage\"),\n join(appData, \"Code - Insiders\", \"User\", \"globalStorage\"),\n join(appData, \"Cursor\", \"User\", \"globalStorage\"),\n );\n }\n\n return paths;\n}\n\nexport function clineAdapter(): Adapter {\n return {\n name: \"cline\",\n async *messages(options?: AdapterOptions): AsyncGenerator<Message> {\n const taskDirs = getClineTaskDirs();\n\n for (const tasksDir of taskDirs) {\n let taskIds: string[];\n try {\n taskIds = await readdir(tasksDir);\n } catch {\n continue;\n }\n\n for (const taskId of taskIds) {\n const taskDir = join(tasksDir, taskId);\n const taskStat = await stat(taskDir).catch(() => null);\n if (!taskStat?.isDirectory()) {\n continue;\n }\n\n const historyFile = join(taskDir, \"api_conversation_history.json\");\n\n try {\n const raw = await readFile(historyFile, \"utf-8\");\n const messages = JSON.parse(raw) as ClineMessage[];\n\n if (!Array.isArray(messages)) {\n continue;\n }\n\n for (const msg of messages) {\n if (msg.role !== \"user\") {\n continue;\n }\n\n const text = extractText(msg.content);\n if (!text) {\n continue;\n }\n\n // Cline doesn't store per-message timestamps in the conversation file\n // Use the task metadata file for approximate timing\n const timestamp = msg.ts ?? undefined;\n if (options?.since && timestamp) {\n const ts = new Date(timestamp);\n if (ts < options.since) {\n continue;\n }\n }\n\n yield {\n text,\n session: taskId,\n };\n }\n } catch {\n // Skip tasks without history or malformed files\n }\n }\n }\n },\n };\n}\n\nfunction extractText(content: unknown): string | null {\n if (typeof content === \"string\") {\n return content;\n }\n if (Array.isArray(content)) {\n const parts = content\n .filter(\n (p): p is { type: string; text: string } =>\n typeof p === \"object\" && p !== null && p.type === \"text\" && typeof p.text === \"string\",\n )\n .map((p) => p.text);\n return parts.length > 0 ? parts.join(\" \") : null;\n }\n return null;\n}\n\ninterface ClineMessage {\n role?: string;\n content?: unknown;\n ts?: string;\n}\n", "import { createReadStream } from \"node:fs\";\nimport { readdir, stat } from \"node:fs/promises\";\nimport { createInterface } from \"node:readline\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport type { Adapter, AdapterOptions, Message, UsageRecord } from \"./index\";\n\n/**\n * Codex stores sessions as JSONL files at:\n * ~/.codex/sessions/YYYY/MM/DD/rollout-*.jsonl\n *\n * Each line is JSON with structure:\n * { \"timestamp\": \"...\", \"type\": \"response_item\", \"payload\": { \"type\": \"message\", \"role\": \"user\", \"content\": [...] } }\n *\n * User messages have payload.role === \"user\" and content is an array of\n * { \"type\": \"input_text\", \"text\": \"...\" }\n *\n * We skip messages that are just environment context injections.\n */\n\nconst CODEX_SESSIONS_DIR = join(homedir(), \".codex\", \"sessions\");\n\nexport function codexAdapter(): Adapter {\n return {\n name: \"codex\",\n async *messages(options?: AdapterOptions): AsyncGenerator<Message> {\n for await (const file of discoverCodexSessionFiles(CODEX_SESSIONS_DIR)) {\n yield* parseCodexJsonl(file.filePath, { session: file.session, since: options?.since });\n }\n },\n async *usage(options?: AdapterOptions): AsyncGenerator<UsageRecord> {\n const seenUsage = new Set<string>();\n for await (const file of discoverCodexSessionFiles(CODEX_SESSIONS_DIR)) {\n for await (const record of parseCodexUsageJsonl(file.filePath, {\n session: file.session,\n since: options?.since,\n })) {\n const key = codexUsageRecordKey(record);\n if (seenUsage.has(key)) {\n continue;\n }\n seenUsage.add(key);\n yield record;\n }\n }\n },\n };\n}\n\nasync function* discoverCodexSessionFiles(\n dir: string,\n): AsyncGenerator<{ filePath: string; session: string }> {\n let entries: string[];\n try {\n entries = await readdir(dir);\n } catch {\n return;\n }\n\n for (const entry of entries) {\n const fullPath = join(dir, entry);\n const entryStat = await stat(fullPath);\n\n if (entryStat.isDirectory()) {\n yield* discoverCodexSessionFiles(fullPath);\n } else if (entry.endsWith(\".jsonl\")) {\n yield { filePath: fullPath, session: sessionFromRolloutFileName(entry) };\n }\n }\n}\n\nfunction sessionFromRolloutFileName(fileName: string): string {\n return (\n fileName.match(\n /([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\\.jsonl$/i,\n )?.[1] ?? fileName.replace(\".jsonl\", \"\")\n );\n}\n\nasync function* parseCodexJsonl(\n filePath: string,\n context: { session: string; since?: Date },\n): AsyncGenerator<Message> {\n const rl = createInterface({\n input: createReadStream(filePath, { encoding: \"utf-8\" }),\n crlfDelay: Infinity,\n });\n\n for await (const line of rl) {\n if (!line.trim()) {\n continue;\n }\n\n try {\n const entry = JSON.parse(line) as CodexEntry;\n\n // Only care about response_item entries with user messages\n if (entry.type !== \"response_item\") {\n continue;\n }\n\n const payload = entry.payload;\n if (!payload || payload.role !== \"user\") {\n continue;\n }\n\n const text = extractText(payload.content);\n if (!text) {\n continue;\n }\n\n // Skip environment context injections (they start with <environment_context>)\n if (text.startsWith(\"<environment_context>\")) {\n continue;\n }\n // Skip permission/sandbox instructions\n if (text.startsWith(\"<permissions instructions>\")) {\n continue;\n }\n\n if (context.since && entry.timestamp) {\n const ts = new Date(entry.timestamp);\n if (ts < context.since) {\n continue;\n }\n }\n\n yield {\n text,\n timestamp: entry.timestamp,\n session: context.session,\n };\n } catch {\n // Skip malformed lines\n }\n }\n}\n\nfunction extractText(content: unknown): string | null {\n if (!Array.isArray(content)) {\n return null;\n }\n\n const parts = content\n .filter(\n (p): p is { type: string; text: string } =>\n typeof p === \"object\" &&\n p !== null &&\n p.type === \"input_text\" &&\n typeof p.text === \"string\",\n )\n .map((p) => p.text);\n\n return parts.length > 0 ? parts.join(\" \") : null;\n}\n\ninterface CodexEntry {\n timestamp?: string;\n type: string;\n payload?: {\n type?: string;\n role?: string;\n content?: unknown;\n };\n}\n\ninterface CodexTokenUsage {\n inputTokens: number;\n cachedInputTokens: number;\n outputTokens: number;\n reasoningOutputTokens: number;\n totalTokens: number;\n}\n\n/** Codex token_count events include both cumulative totals and the last completed response. */\nasync function* parseCodexUsageJsonl(\n filePath: string,\n context: { session: string; since?: Date },\n): AsyncGenerator<UsageRecord> {\n const rl = createInterface({\n input: createReadStream(filePath, { encoding: \"utf-8\" }),\n crlfDelay: Infinity,\n });\n let model: string | undefined;\n let previousTotal: CodexTokenUsage | null = null;\n let previousUsageSignature: string | null = null;\n let session = context.session;\n let sawSessionMeta = false;\n\n for await (const line of rl) {\n if (!line.trim()) {\n continue;\n }\n\n try {\n const entry = JSON.parse(line) as Record<string, unknown>;\n const payload = asRecord(entry[\"payload\"]);\n\n if (entry[\"type\"] === \"session_meta\") {\n const metaSession = stringValue(payload?.[\"id\"]) ?? stringValue(entry[\"id\"]);\n if (metaSession && !sawSessionMeta) {\n session = metaSession;\n sawSessionMeta = true;\n }\n continue;\n }\n\n if (entry[\"type\"] === \"turn_context\") {\n model = stringValue(payload?.[\"model\"]) ?? model;\n continue;\n }\n\n if (entry[\"type\"] !== \"event_msg\" || payload?.[\"type\"] !== \"token_count\") {\n continue;\n }\n\n const info = asRecord(payload[\"info\"]);\n if (!info) {\n continue;\n }\n\n const lastUsageValue = info[\"last_token_usage\"];\n const lastUsage = parseCodexTokenUsage(lastUsageValue);\n const total = parseCodexTokenUsage(info[\"total_token_usage\"]);\n let usage: CodexTokenUsage | null = null;\n\n if (lastUsageValue !== undefined) {\n if (lastUsage && hasBillableUsage(lastUsage)) {\n const signature = codexUsageSignature(lastUsage, total);\n if (signature !== previousUsageSignature) {\n usage = lastUsage;\n }\n previousUsageSignature = signature;\n }\n } else if (total) {\n const delta = previousTotal ? subtractCodexUsage(total, previousTotal) : total;\n if (hasBillableUsage(delta)) {\n usage = delta;\n }\n }\n if (total && hasBillableUsage(total)) {\n previousTotal = total;\n }\n if (!usage) {\n continue;\n }\n\n const timestamp = stringValue(entry[\"timestamp\"]);\n if (context.since && timestamp) {\n const ts = new Date(timestamp);\n if (ts < context.since) {\n continue;\n }\n }\n\n const reasoningTokens = Math.min(usage.reasoningOutputTokens, usage.outputTokens);\n yield {\n agent: \"codex\",\n provider: \"openai\",\n model,\n timestamp,\n session,\n inputTokens: Math.max(usage.inputTokens - usage.cachedInputTokens, 0),\n outputTokens: Math.max(usage.outputTokens - reasoningTokens, 0),\n reasoningTokens,\n cacheReadTokens: usage.cachedInputTokens,\n cacheWriteTokens: 0,\n };\n } catch {\n // Skip malformed lines\n }\n }\n}\n\nfunction codexUsageRecordKey(record: UsageRecord): string {\n return JSON.stringify([\n record.session ?? \"\",\n record.timestamp ?? \"\",\n record.provider ?? \"\",\n record.model ?? \"\",\n record.inputTokens,\n record.outputTokens,\n record.reasoningTokens,\n record.cacheReadTokens,\n record.cacheWriteTokens,\n ]);\n}\n\nfunction parseCodexTokenUsage(value: unknown): CodexTokenUsage | null {\n const usage = asRecord(value);\n if (!usage) {\n return null;\n }\n\n const hasUsageField = [\n \"input_tokens\",\n \"cached_input_tokens\",\n \"output_tokens\",\n \"reasoning_output_tokens\",\n \"total_tokens\",\n ].some((key) => typeof usage[key] === \"number\" && Number.isFinite(usage[key]));\n if (!hasUsageField) {\n return null;\n }\n\n return {\n inputTokens: numberValue(usage[\"input_tokens\"]),\n cachedInputTokens: numberValue(usage[\"cached_input_tokens\"]),\n outputTokens: numberValue(usage[\"output_tokens\"]),\n reasoningOutputTokens: numberValue(usage[\"reasoning_output_tokens\"]),\n totalTokens: numberValue(usage[\"total_tokens\"]),\n };\n}\n\nfunction subtractCodexUsage(current: CodexTokenUsage, previous: CodexTokenUsage): CodexTokenUsage {\n return {\n inputTokens: Math.max(current.inputTokens - previous.inputTokens, 0),\n cachedInputTokens: Math.max(current.cachedInputTokens - previous.cachedInputTokens, 0),\n outputTokens: Math.max(current.outputTokens - previous.outputTokens, 0),\n reasoningOutputTokens: Math.max(\n current.reasoningOutputTokens - previous.reasoningOutputTokens,\n 0,\n ),\n totalTokens: Math.max(current.totalTokens - previous.totalTokens, 0),\n };\n}\n\nfunction hasBillableUsage(usage: CodexTokenUsage): boolean {\n return (\n usage.inputTokens + usage.cachedInputTokens + usage.outputTokens + usage.reasoningOutputTokens >\n 0\n );\n}\n\nfunction codexUsageSignature(usage: CodexTokenUsage, total: CodexTokenUsage | null): string {\n return [\n usage.inputTokens,\n usage.cachedInputTokens,\n usage.outputTokens,\n usage.reasoningOutputTokens,\n total?.inputTokens ?? \"\",\n total?.cachedInputTokens ?? \"\",\n total?.outputTokens ?? \"\",\n total?.reasoningOutputTokens ?? \"\",\n ].join(\":\");\n}\n\nfunction numberValue(value: unknown): number {\n return typeof value === \"number\" && Number.isFinite(value) ? value : 0;\n}\n\nfunction stringValue(value: unknown): string | undefined {\n return typeof value === \"string\" && value.trim() ? value : undefined;\n}\n\nfunction asRecord(value: unknown): Record<string, unknown> | null {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n return null;\n }\n\n return value as Record<string, unknown>;\n}\n", "import { existsSync } from \"node:fs\";\nimport { readdir } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport type { Adapter, AdapterOptions, Message, UsageRecord } from \"./index\";\n\n/**\n * Reads Cursor's VS Code-style state stores read-only. Extraction is limited to\n * known AI keys and confident user-authored message shapes; unreadable DBs skip.\n */\n\nconst CANDIDATE_KEY_PREFIXES = [\n \"bubbleId:\",\n \"composerData:\",\n \"composer.composerData\",\n \"aiService.prompts\",\n \"aiService.generations\",\n \"workbench.panel.composerChatViewPane.\",\n];\n\nconst STATE_TABLES = [\"ItemTable\", \"cursorDiskKV\"];\n\ninterface CursorStateStore {\n path: string;\n scope: string;\n project?: string;\n}\n\ninterface StateRow {\n key: string;\n value: unknown;\n}\n\ninterface ExtractedMessage {\n text: string;\n timestamp?: string;\n session?: string;\n}\n\nexport function cursorAdapter(): Adapter {\n return {\n name: \"cursor\",\n async *messages(options?: AdapterOptions): AsyncGenerator<Message> {\n const stores = await discoverCursorStateStores();\n\n for (const store of stores) {\n yield* parseCursorStore(store, options);\n }\n },\n async *usage(options?: AdapterOptions): AsyncGenerator<UsageRecord> {\n const stores = await discoverCursorStateStores();\n\n for (const store of stores) {\n yield* parseCursorUsageStore(store, options);\n }\n },\n };\n}\n\nasync function discoverCursorStateStores(): Promise<CursorStateStore[]> {\n const stores: CursorStateStore[] = [];\n const seen = new Set<string>();\n\n for (const userDir of getCursorUserDirs()) {\n if (!existsSync(userDir)) {\n continue;\n }\n\n const globalState = join(userDir, \"globalStorage\", \"state.vscdb\");\n if (existsSync(globalState) && !seen.has(globalState)) {\n seen.add(globalState);\n stores.push({ path: globalState, scope: \"global\" });\n }\n\n const workspaceRoot = join(userDir, \"workspaceStorage\");\n let workspaceIds: string[] = [];\n try {\n workspaceIds = await readdir(workspaceRoot);\n } catch {\n continue;\n }\n\n for (const workspaceId of workspaceIds) {\n const statePath = join(workspaceRoot, workspaceId, \"state.vscdb\");\n if (existsSync(statePath) && !seen.has(statePath)) {\n seen.add(statePath);\n stores.push({ path: statePath, scope: \"workspace\", project: workspaceId });\n }\n }\n }\n\n return stores;\n}\n\nfunction getCursorUserDirs(): string[] {\n const configHome = envOrDefault(\"XDG_CONFIG_HOME\", join(homedir(), \".config\"));\n const appData = envOrDefault(\"APPDATA\", join(homedir(), \"AppData\", \"Roaming\"));\n\n return uniqueStrings([\n join(homedir(), \"Library\", \"Application Support\", \"Cursor\", \"User\"),\n join(configHome, \"Cursor\", \"User\"),\n join(appData, \"Cursor\", \"User\"),\n ]);\n}\n\nasync function* parseCursorStore(\n store: CursorStateStore,\n options?: AdapterOptions,\n): AsyncGenerator<Message> {\n const db = await openCursorDb(store.path);\n if (!db) {\n return;\n }\n\n try {\n const rows = readStateRows(db);\n const seen = new Set<string>();\n\n for (const row of rows) {\n try {\n if (!isCandidateKey(row.key)) {\n continue;\n }\n\n const parsed = parseJsonValue(row.value);\n if (parsed === undefined) {\n continue;\n }\n\n for (const message of extractCursorMessages(parsed, row.key)) {\n const text = message.text.trim();\n if (!isLikelyMessageText(text)) {\n continue;\n }\n\n if (options?.since && message.timestamp) {\n const timestamp = new Date(message.timestamp);\n if (Number.isFinite(timestamp.getTime()) && timestamp < options.since) {\n continue;\n }\n }\n\n const session = message.session ?? `${store.scope}:${row.key}`;\n const dedupeKey = `${session}\\u0000${message.timestamp ?? \"\"}\\u0000${text}`;\n if (seen.has(dedupeKey)) {\n continue;\n }\n seen.add(dedupeKey);\n\n yield {\n text,\n timestamp: message.timestamp,\n session,\n project: store.project,\n };\n }\n } catch {\n continue;\n }\n }\n } finally {\n db.close();\n }\n}\n\nasync function* parseCursorUsageStore(\n store: CursorStateStore,\n options?: AdapterOptions,\n): AsyncGenerator<UsageRecord> {\n const db = await openCursorDb(store.path);\n if (!db) {\n return;\n }\n\n try {\n const rows = readStateRows(db);\n const composerModels = collectComposerModels(rows);\n const seen = new Set<string>();\n\n for (const row of rows) {\n try {\n if (!row.key.startsWith(\"bubbleId:\")) {\n continue;\n }\n\n const parsed = parseJsonValue(row.value);\n const usage = extractCursorBubbleUsage(parsed, row.key, composerModels);\n if (!usage) {\n continue;\n }\n\n if (options?.since && usage.timestamp) {\n const timestamp = new Date(usage.timestamp);\n if (Number.isFinite(timestamp.getTime()) && timestamp < options.since) {\n continue;\n }\n }\n\n const dedupeKey = `${usage.session ?? \"\"}\\u0000${usage.timestamp ?? \"\"}\\u0000${usage.model ?? \"\"}\\u0000${usage.inputTokens}\\u0000${usage.outputTokens}`;\n if (seen.has(dedupeKey)) {\n continue;\n }\n seen.add(dedupeKey);\n\n yield usage;\n } catch {\n continue;\n }\n }\n } finally {\n db.close();\n }\n}\n\nasync function openCursorDb(dbPath: string): Promise<import(\"better-sqlite3\").Database | null> {\n try {\n const BetterSqlite3 = await import(\"better-sqlite3\");\n const Ctor = BetterSqlite3.default ?? BetterSqlite3;\n return new (Ctor as unknown as new (...args: unknown[]) => import(\"better-sqlite3\").Database)(\n dbPath,\n { readonly: true },\n );\n } catch {\n return null;\n }\n}\n\nfunction readStateRows(db: import(\"better-sqlite3\").Database): StateRow[] {\n const rows: StateRow[] = [];\n\n try {\n const tables = db.prepare(\"SELECT name FROM sqlite_master WHERE type = 'table'\").all() as {\n name: unknown;\n }[];\n const availableTables = new Set(tables.flatMap((table) => stringValue(table.name) ?? []));\n\n for (const table of STATE_TABLES) {\n if (!availableTables.has(table)) {\n continue;\n }\n\n const columns = db.prepare(`PRAGMA table_info(\"${table}\")`).all() as { name: unknown }[];\n const columnNames = new Set(columns.flatMap((column) => stringValue(column.name) ?? []));\n if (!columnNames.has(\"key\") || !columnNames.has(\"value\")) {\n continue;\n }\n\n const tableRows = db.prepare(`SELECT key, value FROM \"${table}\"`).all() as {\n key: unknown;\n value: unknown;\n }[];\n rows.push(\n ...tableRows.flatMap((row) =>\n typeof row.key === \"string\" ? [{ key: row.key, value: row.value }] : [],\n ),\n );\n }\n } catch {\n return rows;\n }\n\n return rows;\n}\n\nfunction isCandidateKey(key: string): boolean {\n return CANDIDATE_KEY_PREFIXES.some((prefix) => key === prefix || key.startsWith(prefix));\n}\n\nfunction parseJsonValue(value: unknown): unknown | undefined {\n const raw = decodeStateValue(value);\n if (!raw) {\n return undefined;\n }\n\n try {\n const parsed = JSON.parse(raw) as unknown;\n if (typeof parsed !== \"string\") {\n return parsed;\n }\n\n const trimmed = parsed.trim();\n if (!trimmed.startsWith(\"{\") && !trimmed.startsWith(\"[\")) {\n return parsed;\n }\n\n try {\n return JSON.parse(trimmed) as unknown;\n } catch {\n return parsed;\n }\n } catch {\n return undefined;\n }\n}\n\nfunction decodeStateValue(value: unknown): string | null {\n if (typeof value === \"string\") {\n return value;\n }\n\n if (Buffer.isBuffer(value)) {\n return value.toString(\"utf-8\");\n }\n\n return null;\n}\n\nfunction extractCursorMessages(root: unknown, rowKey: string): ExtractedMessage[] {\n if (rowKey.startsWith(\"bubbleId:\")) {\n const message = extractCursorBubbleMessage(root, rowKey);\n return message ? [message] : [];\n }\n\n const messages: ExtractedMessage[] = [];\n collectRoleMessages(root, messages);\n\n if (rowKey.startsWith(\"aiService.prompts\") || rowKey.startsWith(\"aiService.generations\")) {\n collectPromptMessages(root, messages);\n }\n\n return uniqueMessages(messages);\n}\n\nfunction extractCursorBubbleMessage(root: unknown, rowKey: string): ExtractedMessage | null {\n const record = asRecord(root);\n if (!record || numberValue(record[\"type\"]) !== 1) {\n return null;\n }\n\n const text = firstTextField(record, [\"text\", \"richText\"]);\n if (!text) {\n return null;\n }\n\n return {\n text,\n timestamp: extractTimestamp(record),\n session: cursorBubbleSession(rowKey) ?? extractSession(record),\n };\n}\n\nfunction collectComposerModels(rows: StateRow[]): Map<string, string> {\n const models = new Map<string, string>();\n\n for (const row of rows) {\n if (!row.key.startsWith(\"composerData:\")) {\n continue;\n }\n\n const parsed = parseJsonValue(row.value);\n const record = asRecord(parsed);\n if (!record) {\n continue;\n }\n\n const composerId = stringValue(record[\"composerId\"]) ?? row.key.slice(\"composerData:\".length);\n const model = extractCursorModel(record);\n if (composerId && model) {\n models.set(composerId, model);\n }\n }\n\n return models;\n}\n\nfunction extractCursorBubbleUsage(\n root: unknown,\n rowKey: string,\n composerModels: Map<string, string>,\n): UsageRecord | null {\n const record = asRecord(root);\n if (!record || numberValue(record[\"type\"]) !== 2) {\n return null;\n }\n\n const tokenCount = asRecord(record[\"tokenCount\"]);\n if (!tokenCount) {\n return null;\n }\n\n const inputTokens = numberValue(tokenCount[\"inputTokens\"] ?? tokenCount[\"input\"]);\n const outputTokens = numberValue(tokenCount[\"outputTokens\"] ?? tokenCount[\"output\"]);\n const cacheReadTokens = numberValue(tokenCount[\"cacheReadTokens\"] ?? tokenCount[\"cacheRead\"]);\n const cacheWriteTokens = numberValue(tokenCount[\"cacheWriteTokens\"] ?? tokenCount[\"cacheWrite\"]);\n if (inputTokens + outputTokens + cacheReadTokens + cacheWriteTokens === 0) {\n return null;\n }\n\n const composerId = cursorBubbleSession(rowKey);\n const model =\n extractCursorModel(record) ?? (composerId ? composerModels.get(composerId) : undefined);\n\n return {\n agent: \"cursor\",\n model,\n timestamp: extractTimestamp(record),\n session: composerId ?? extractSession(record),\n inputTokens,\n outputTokens,\n reasoningTokens: numberValue(tokenCount[\"reasoningTokens\"] ?? tokenCount[\"reasoning\"]),\n cacheReadTokens,\n cacheWriteTokens,\n };\n}\n\nfunction extractCursorModel(record: Record<string, unknown>): string | undefined {\n const direct = firstStringField(record, [\"model\", \"modelName\", \"modelId\"]);\n if (direct) {\n return direct;\n }\n\n for (const field of [\"modelInfo\", \"modelConfig\"]) {\n const modelRecord = asRecord(record[field]);\n if (!modelRecord) {\n continue;\n }\n\n const nested = firstStringField(modelRecord, [\"modelName\", \"modelId\", \"id\", \"name\"]);\n if (nested && nested !== \"default\") {\n return nested;\n }\n\n const selected = modelRecord[\"selectedModels\"];\n if (Array.isArray(selected)) {\n for (const item of selected) {\n const itemRecord = asRecord(item);\n const selectedModel = itemRecord\n ? firstStringField(itemRecord, [\"modelId\", \"modelName\", \"id\", \"name\"])\n : undefined;\n if (selectedModel && selectedModel !== \"default\") {\n return selectedModel;\n }\n }\n }\n\n if (nested) {\n return nested;\n }\n }\n\n return undefined;\n}\n\nfunction cursorBubbleSession(rowKey: string): string | undefined {\n const [, composerId] = rowKey.split(\":\");\n return composerId?.trim() || undefined;\n}\n\nfunction collectRoleMessages(\n value: unknown,\n messages: ExtractedMessage[],\n inheritedSession?: string,\n depth = 0,\n): void {\n if (depth > 12) {\n return;\n }\n\n if (Array.isArray(value)) {\n for (const item of value) {\n collectRoleMessages(item, messages, inheritedSession, depth + 1);\n }\n return;\n }\n\n const record = asRecord(value);\n if (!record) {\n return;\n }\n\n const session = extractSession(record) ?? inheritedSession;\n if (isUserAuthored(record)) {\n const text = extractMessageText(record);\n if (text) {\n messages.push({ text, timestamp: extractTimestamp(record), session });\n }\n }\n\n for (const child of Object.values(record)) {\n if (typeof child === \"object\" && child !== null) {\n collectRoleMessages(child, messages, session, depth + 1);\n }\n }\n}\n\nfunction collectPromptMessages(\n value: unknown,\n messages: ExtractedMessage[],\n inheritedSession?: string,\n depth = 0,\n): void {\n if (depth > 12) {\n return;\n }\n\n if (typeof value === \"string\") {\n messages.push({ text: value, session: inheritedSession });\n return;\n }\n\n if (Array.isArray(value)) {\n for (const item of value) {\n collectPromptMessages(item, messages, inheritedSession, depth + 1);\n }\n return;\n }\n\n const record = asRecord(value);\n if (!record) {\n return;\n }\n\n const session = extractSession(record) ?? inheritedSession;\n const prompt = firstTextField(record, [\n \"prompt\",\n \"userPrompt\",\n \"originalPrompt\",\n \"currentPrompt\",\n \"query\",\n \"input\",\n ]);\n\n if (prompt && !isAssistantAuthored(record)) {\n messages.push({ text: prompt, timestamp: extractTimestamp(record), session });\n }\n\n for (const child of Object.values(record)) {\n if (typeof child === \"object\" && child !== null) {\n collectPromptMessages(child, messages, session, depth + 1);\n }\n }\n}\n\nfunction isUserAuthored(record: Record<string, unknown>): boolean {\n return [\"role\", \"speaker\", \"sender\", \"author\", \"source\", \"from\", \"type\", \"kind\"].some((field) =>\n actorIsUser(record[field]),\n );\n}\n\nfunction isAssistantAuthored(record: Record<string, unknown>): boolean {\n return [\"role\", \"speaker\", \"sender\", \"author\", \"source\", \"from\", \"type\", \"kind\"].some((field) =>\n actorIsAssistant(record[field]),\n );\n}\n\nfunction actorIsUser(value: unknown): boolean {\n const actor = actorString(value);\n return actor === \"user\" || actor === \"human\" || actor === \"usermessage\";\n}\n\nfunction actorIsAssistant(value: unknown): boolean {\n const actor = actorString(value);\n return actor === \"assistant\" || actor === \"ai\" || actor === \"assistantmessage\";\n}\n\nfunction actorString(value: unknown): string | null {\n if (typeof value === \"string\") {\n return value.toLowerCase().replace(/[^a-z]/g, \"\");\n }\n\n const record = asRecord(value);\n if (!record) {\n return null;\n }\n\n for (const field of [\"role\", \"type\", \"name\"]) {\n if (typeof record[field] === \"string\") {\n return record[field].toLowerCase().replace(/[^a-z]/g, \"\");\n }\n }\n\n return null;\n}\n\nfunction extractMessageText(record: Record<string, unknown>): string | null {\n return firstTextField(record, [\"text\", \"content\", \"message\", \"prompt\", \"query\", \"input\"]);\n}\n\nfunction firstTextField(record: Record<string, unknown>, fields: string[]): string | null {\n for (const field of fields) {\n const text = contentToText(record[field]);\n if (text) {\n return text;\n }\n }\n\n return null;\n}\n\nfunction firstStringField(record: Record<string, unknown>, fields: string[]): string | undefined {\n for (const field of fields) {\n const value = stringValue(record[field]);\n if (value) {\n return value;\n }\n }\n\n return undefined;\n}\n\nfunction contentToText(value: unknown): string | null {\n if (typeof value === \"string\") {\n return value;\n }\n\n if (Array.isArray(value)) {\n const parts = value.map(contentToText).filter((part): part is string => Boolean(part));\n return parts.length > 0 ? parts.join(\" \") : null;\n }\n\n const record = asRecord(value);\n if (!record) {\n return null;\n }\n\n return firstTextField(record, [\"text\", \"content\", \"message\", \"value\"]);\n}\n\nfunction extractTimestamp(record: Record<string, unknown>): string | undefined {\n for (const field of [\"timestamp\", \"createdAt\", \"updatedAt\", \"time\", \"created\", \"date\", \"ts\"]) {\n const timestamp = normalizeTimestamp(record[field]);\n if (timestamp) {\n return timestamp;\n }\n }\n\n return undefined;\n}\n\nfunction normalizeTimestamp(value: unknown): string | undefined {\n if (typeof value === \"string\") {\n const date = new Date(value);\n return Number.isFinite(date.getTime()) ? date.toISOString() : undefined;\n }\n\n if (typeof value === \"number\" && Number.isFinite(value)) {\n const milliseconds = value > 1_000_000_000_000 ? value : value * 1000;\n const date = new Date(milliseconds);\n return Number.isFinite(date.getTime()) ? date.toISOString() : undefined;\n }\n\n return undefined;\n}\n\nfunction extractSession(record: Record<string, unknown>): string | undefined {\n for (const field of [\"conversationId\", \"composerId\", \"sessionId\", \"chatId\", \"threadId\", \"id\"]) {\n const value = record[field];\n if (typeof value === \"string\" && value.trim()) {\n return value;\n }\n }\n\n return undefined;\n}\n\nfunction isLikelyMessageText(text: string): boolean {\n return text.length > 0 && !text.startsWith(\"<environment_context>\");\n}\n\nfunction uniqueMessages(messages: ExtractedMessage[]): ExtractedMessage[] {\n const seen = new Set<string>();\n const unique: ExtractedMessage[] = [];\n\n for (const message of messages) {\n const key = `${message.session ?? \"\"}\\u0000${message.timestamp ?? \"\"}\\u0000${message.text}`;\n if (seen.has(key)) {\n continue;\n }\n\n seen.add(key);\n unique.push(message);\n }\n\n return unique;\n}\n\nfunction uniqueStrings(values: string[]): string[] {\n return Array.from(new Set(values));\n}\n\nfunction envOrDefault(name: string, fallback: string): string {\n const value = process.env[name];\n return value && value.trim() ? value : fallback;\n}\n\nfunction numberValue(value: unknown): number {\n return typeof value === \"number\" && Number.isFinite(value) ? value : 0;\n}\n\nfunction stringValue(value: unknown): string | undefined {\n return typeof value === \"string\" && value.trim() ? value : undefined;\n}\n\nfunction asRecord(value: unknown): Record<string, unknown> | null {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n return null;\n }\n\n return value as Record<string, unknown>;\n}\n", "import { existsSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport type { Adapter, AdapterOptions, Message, UsageRecord } from \"./index\";\n\n/**\n * OpenCode stores sessions in a SQLite database at:\n * ~/.local/share/opencode/opencode.db\n *\n * Schema:\n * message: { id, session_id, time_created (epoch ms), time_updated, data (JSON) }\n * part: { id, message_id, session_id, time_created, time_updated, data (JSON) }\n *\n * message.data: { \"role\": \"user\"|\"assistant\", \"time\": {...}, \"agent\": \"...\", ... }\n * part.data: { \"type\": \"text\", \"text\": \"the user's message\" }\n *\n * User messages have role=\"user\" in message.data. The actual text content is in\n * the associated part rows where part.data.type === \"text\".\n */\n\nfunction getOpencodeDatabasePath(): string | null {\n // macOS: ~/.local/share/opencode/opencode.db (despite XDG, this is where it actually lives)\n const xdgPath = join(\n process.env[\"XDG_DATA_HOME\"] ?? join(homedir(), \".local\", \"share\"),\n \"opencode\",\n \"opencode.db\",\n );\n if (existsSync(xdgPath)) {\n return xdgPath;\n }\n\n // macOS Application Support fallback\n if (process.platform === \"darwin\") {\n const macPath = join(homedir(), \"Library\", \"Application Support\", \"opencode\", \"opencode.db\");\n if (existsSync(macPath)) {\n return macPath;\n }\n }\n\n return null;\n}\n\nexport function opencodeAdapter(): Adapter {\n return {\n name: \"opencode\",\n async *messages(options?: AdapterOptions): AsyncGenerator<Message> {\n const db = await openOpencodeDb();\n if (!db) {\n return;\n }\n\n try {\n yield* queryUserMessages(db, options);\n } finally {\n db.close();\n }\n },\n async *usage(options?: AdapterOptions): AsyncGenerator<UsageRecord> {\n const db = await openOpencodeDb();\n if (!db) {\n return;\n }\n\n try {\n yield* queryUsageRecords(db, options);\n } finally {\n db.close();\n }\n },\n };\n}\n\nasync function openOpencodeDb(): Promise<import(\"better-sqlite3\").Database | null> {\n const dbPath = getOpencodeDatabasePath();\n if (!dbPath) {\n return null;\n }\n\n // Dynamic import so the CLI doesn't crash if better-sqlite3 isn't available\n try {\n const BetterSqlite3 = await import(\"better-sqlite3\");\n const Ctor = BetterSqlite3.default ?? BetterSqlite3;\n return new (Ctor as unknown as new (...args: unknown[]) => import(\"better-sqlite3\").Database)(\n dbPath,\n { readonly: true },\n );\n } catch {\n console.warn(\"devrage: better-sqlite3 not available, skipping OpenCode sessions\");\n return null;\n }\n}\n\nfunction* queryUserMessages(\n db: import(\"better-sqlite3\").Database,\n options?: AdapterOptions,\n): Generator<Message> {\n // Query: join message + part, filter to user role and text parts\n let query = `\n SELECT\n m.session_id,\n m.time_created,\n json_extract(p.data, '$.text') as text\n FROM message m\n JOIN part p ON p.message_id = m.id\n WHERE json_extract(m.data, '$.role') = 'user'\n AND json_extract(p.data, '$.type') = 'text'\n `;\n\n const params: unknown[] = [];\n if (options?.since) {\n query += ` AND m.time_created >= ?`;\n params.push(options.since.getTime());\n }\n\n query += ` ORDER BY m.time_created ASC`;\n\n const rows = db.prepare(query).all(...params) as {\n session_id: string;\n time_created: number;\n text: string;\n }[];\n\n for (const row of rows) {\n if (!row.text || !row.text.trim()) {\n continue;\n }\n\n yield {\n text: row.text,\n timestamp: new Date(row.time_created).toISOString(),\n session: row.session_id,\n };\n }\n}\n\n/** OpenCode assistant messages store provider/model, billed cost, and token usage in message.data. */\nfunction* queryUsageRecords(\n db: import(\"better-sqlite3\").Database,\n options?: AdapterOptions,\n): Generator<UsageRecord> {\n let where = `WHERE json_type(data, '$.tokens') = 'object'`;\n const params: unknown[] = [];\n\n if (options?.since) {\n where += ` AND time_created >= ?`;\n params.push(options.since.getTime());\n }\n\n const rows = db\n .prepare(`\n SELECT\n session_id,\n time_created,\n COALESCE(json_extract(data, '$.providerID'), json_extract(data, '$.model.providerID')) AS provider,\n COALESCE(json_extract(data, '$.modelID'), json_extract(data, '$.model.modelID')) AS model,\n json_extract(data, '$.cost') AS billed_cost,\n json_extract(data, '$.tokens.input') AS input_tokens,\n json_extract(data, '$.tokens.output') AS output_tokens,\n json_extract(data, '$.tokens.reasoning') AS reasoning_tokens,\n json_extract(data, '$.tokens.cache.read') AS cache_read_tokens,\n json_extract(data, '$.tokens.cache.write') AS cache_write_tokens\n FROM message\n ${where}\n ORDER BY time_created ASC\n `)\n .all(...params) as {\n session_id: string | null;\n time_created: number | null;\n provider: string | null;\n model: string | null;\n billed_cost: number | null;\n input_tokens: number | null;\n output_tokens: number | null;\n reasoning_tokens: number | null;\n cache_read_tokens: number | null;\n cache_write_tokens: number | null;\n }[];\n\n for (const row of rows) {\n const inputTokens = numberValue(row.input_tokens);\n const outputTokens = numberValue(row.output_tokens);\n const reasoningTokens = numberValue(row.reasoning_tokens);\n const cacheReadTokens = numberValue(row.cache_read_tokens);\n const cacheWriteTokens = numberValue(row.cache_write_tokens);\n const billedCost = numberValue(row.billed_cost);\n\n if (\n inputTokens + outputTokens + reasoningTokens + cacheReadTokens + cacheWriteTokens === 0 &&\n billedCost === 0\n ) {\n continue;\n }\n\n yield {\n agent: \"opencode\",\n provider: stringValue(row.provider),\n model: stringValue(row.model),\n timestamp: row.time_created ? new Date(row.time_created).toISOString() : undefined,\n session: stringValue(row.session_id),\n billedCost,\n inputTokens,\n outputTokens,\n reasoningTokens,\n cacheReadTokens,\n cacheWriteTokens,\n };\n }\n}\n\nfunction numberValue(value: unknown): number {\n return typeof value === \"number\" && Number.isFinite(value) ? value : 0;\n}\n\nfunction stringValue(value: unknown): string | undefined {\n return typeof value === \"string\" && value.trim() ? value : undefined;\n}\n", "import { createReadStream } from \"node:fs\";\nimport { readdir, stat } from \"node:fs/promises\";\nimport { createInterface } from \"node:readline\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport type { Adapter, AdapterOptions, Message, UsageRecord } from \"./index\";\n\n/**\n * Pi Agent stores sessions as JSONL files at:\n * ~/.pi/agent/sessions/<project>/<session-id>.jsonl\n *\n * Each line is a JSON object:\n * { \"type\": \"session\", \"cwd\": \"/path/to/project\" } \u2014 session metadata\n * { \"type\": \"message\", \"timestamp\": \"...\", \"message\": { \"role\": \"user\", \"content\": \"...\" } }\n *\n * Content can be a string or array of { type: \"text\", text: \"...\" } parts.\n */\n\nconst PI_SESSIONS_DIR = join(homedir(), \".pi\", \"agent\", \"sessions\");\n\nexport function piAdapter(): Adapter {\n return {\n name: \"pi\",\n async *messages(options?: AdapterOptions): AsyncGenerator<Message> {\n yield* walkPiSessions(PI_SESSIONS_DIR, options);\n },\n async *usage(options?: AdapterOptions): AsyncGenerator<UsageRecord> {\n yield* walkPiUsageSessions(PI_SESSIONS_DIR, options);\n },\n };\n}\n\nasync function* walkPiSessions(\n dir: string,\n options?: AdapterOptions,\n project?: string,\n): AsyncGenerator<Message> {\n let entries: string[];\n try {\n entries = await readdir(dir);\n } catch {\n return;\n }\n\n for (const entry of entries) {\n const fullPath = join(dir, entry);\n const entryStat = await stat(fullPath).catch(() => null);\n if (!entryStat) {\n continue;\n }\n\n if (entryStat.isDirectory()) {\n yield* walkPiSessions(fullPath, options, project ?? entry);\n } else if (entry.endsWith(\".jsonl\")) {\n const session = entry.replace(\".jsonl\", \"\");\n yield* parsePiJsonl(fullPath, { session, project, since: options?.since });\n }\n }\n}\n\nasync function* walkPiUsageSessions(\n dir: string,\n options?: AdapterOptions,\n project?: string,\n): AsyncGenerator<UsageRecord> {\n let entries: string[];\n try {\n entries = await readdir(dir);\n } catch {\n return;\n }\n\n for (const entry of entries) {\n const fullPath = join(dir, entry);\n const entryStat = await stat(fullPath).catch(() => null);\n if (!entryStat) {\n continue;\n }\n\n if (entryStat.isDirectory()) {\n yield* walkPiUsageSessions(fullPath, options, project ?? entry);\n } else if (entry.endsWith(\".jsonl\")) {\n const session = entry.replace(\".jsonl\", \"\");\n yield* parsePiUsageJsonl(fullPath, { session, project, since: options?.since });\n }\n }\n}\n\nasync function* parsePiJsonl(\n filePath: string,\n context: { session: string; project?: string; since?: Date },\n): AsyncGenerator<Message> {\n const rl = createInterface({\n input: createReadStream(filePath, { encoding: \"utf-8\" }),\n crlfDelay: Infinity,\n });\n\n let project = context.project;\n\n for await (const line of rl) {\n if (!line.trim()) {\n continue;\n }\n\n try {\n const entry = JSON.parse(line) as PiEntry;\n\n // Session metadata line carries cwd\n if (entry.type === \"session\") {\n project = entry.cwd ?? project;\n continue;\n }\n\n if (entry.type !== \"message\") {\n continue;\n }\n\n const message = entry.message;\n if (!message || message.role !== \"user\") {\n continue;\n }\n\n const text = contentToString(message.content);\n if (!text) {\n continue;\n }\n\n const timestamp =\n typeof entry.timestamp === \"string\"\n ? entry.timestamp\n : typeof message.timestamp === \"number\"\n ? new Date(message.timestamp).toISOString()\n : undefined;\n\n if (context.since && timestamp) {\n const ts = new Date(timestamp);\n if (ts < context.since) {\n continue;\n }\n }\n\n yield {\n text,\n timestamp,\n session: context.session,\n project,\n };\n } catch {\n // Skip malformed lines\n }\n }\n}\n\nasync function* parsePiUsageJsonl(\n filePath: string,\n context: { session: string; project?: string; since?: Date },\n): AsyncGenerator<UsageRecord> {\n const rl = createInterface({\n input: createReadStream(filePath, { encoding: \"utf-8\" }),\n crlfDelay: Infinity,\n });\n\n for await (const line of rl) {\n if (!line.trim()) {\n continue;\n }\n\n try {\n const entry = JSON.parse(line) as PiEntry;\n if (entry.type !== \"message\") {\n continue;\n }\n\n const message = entry.message;\n if (!message || message.role !== \"assistant\") {\n continue;\n }\n\n const usage = asRecord(message.usage);\n if (!usage) {\n continue;\n }\n\n const inputTokens = numberValue(usage[\"input\"]);\n const outputTokens = numberValue(usage[\"output\"]);\n const cacheReadTokens = numberValue(usage[\"cacheRead\"]);\n const cacheWriteTokens = numberValue(usage[\"cacheWrite\"]);\n if (inputTokens + outputTokens + cacheReadTokens + cacheWriteTokens === 0) {\n continue;\n }\n\n const timestamp =\n typeof entry.timestamp === \"string\"\n ? entry.timestamp\n : typeof message.timestamp === \"number\"\n ? new Date(message.timestamp).toISOString()\n : undefined;\n if (context.since && timestamp) {\n const ts = new Date(timestamp);\n if (ts < context.since) {\n continue;\n }\n }\n\n const responseModel = stringValue(message.responseModel);\n const model = responseModel ?? stringValue(message.model);\n\n yield {\n agent: \"pi\",\n provider: responseModel?.includes(\"/\") ? undefined : stringValue(message.provider),\n model,\n timestamp,\n session: context.session,\n inputTokens,\n outputTokens,\n reasoningTokens: 0,\n cacheReadTokens,\n cacheWriteTokens,\n };\n } catch {\n // Skip malformed lines\n }\n }\n}\n\nfunction contentToString(content: unknown): string | null {\n if (typeof content === \"string\") {\n return content;\n }\n if (Array.isArray(content)) {\n const parts = content\n .filter(\n (p): p is { type: string; text: string } =>\n typeof p === \"object\" && p !== null && p.type === \"text\" && typeof p.text === \"string\",\n )\n .map((p) => p.text);\n return parts.length > 0 ? parts.join(\" \") : null;\n }\n return null;\n}\n\ninterface PiEntry {\n type?: string;\n timestamp?: string;\n cwd?: string;\n message?: {\n role?: string;\n content?: unknown;\n timestamp?: number;\n provider?: unknown;\n model?: unknown;\n responseModel?: unknown;\n usage?: unknown;\n };\n}\n\nfunction numberValue(value: unknown): number {\n return typeof value === \"number\" && Number.isFinite(value) ? value : 0;\n}\n\nfunction stringValue(value: unknown): string | undefined {\n return typeof value === \"string\" && value.trim() ? value : undefined;\n}\n\nfunction asRecord(value: unknown): Record<string, unknown> | null {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n return null;\n }\n\n return value as Record<string, unknown>;\n}\n", "import { existsSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { isAbsolute, join, resolve } from \"node:path\";\nimport type { Adapter, AdapterOptions, Message, UsageRecord } from \"./index\";\n\n/**\n * T3 Code stores server state in SQLite under:\n * ~/.t3/userdata/state.sqlite\n * ~/.t3/dev/state.sqlite\n *\n * User text is projected into projection_thread_messages. Token usage arrives\n * in provider runtime as thread.token-usage.updated, then is persisted as a\n * thread.activity-appended event with activity.kind === \"context-window.updated\".\n */\n\ninterface T3DatabaseLocation {\n path: string;\n scope: string;\n}\n\ninterface ThreadInfo {\n provider?: string;\n model?: string;\n}\n\ninterface ParsedUsage {\n inputTokens: number;\n outputTokens: number;\n reasoningTokens: number;\n cacheReadTokens: number;\n cacheWriteTokens: number;\n}\n\ninterface T3MessageRow {\n thread_id: unknown;\n created_at: unknown;\n text: unknown;\n}\n\ninterface T3UsageEventRow {\n stream_id: unknown;\n occurred_at: unknown;\n payload_json: unknown;\n}\n\ninterface T3ThreadModelSelectionRow {\n thread_id: unknown;\n model_selection_json: unknown;\n}\n\ninterface T3ThreadModelRow {\n thread_id: unknown;\n model: unknown;\n}\n\ninterface T3ThreadSessionRow {\n thread_id: unknown;\n provider_name: unknown;\n}\n\nexport function t3codeAdapter(): Adapter {\n return {\n name: \"t3code\",\n async *messages(options?: AdapterOptions): AsyncGenerator<Message> {\n for (const location of discoverT3Databases()) {\n const db = await openT3Db(location.path);\n if (!db) {\n continue;\n }\n\n try {\n yield* queryUserMessages(db, location, options);\n } finally {\n db.close();\n }\n }\n },\n async *usage(options?: AdapterOptions): AsyncGenerator<UsageRecord> {\n const seen = new Set<string>();\n\n for (const location of discoverT3Databases()) {\n const db = await openT3Db(location.path);\n if (!db) {\n continue;\n }\n\n try {\n yield* queryUsageRecords(db, location, seen, options);\n } finally {\n db.close();\n }\n }\n },\n };\n}\n\nfunction discoverT3Databases(): T3DatabaseLocation[] {\n const locations: T3DatabaseLocation[] = [];\n const seen = new Set<string>();\n const stateDir = stringValue(process.env[\"T3CODE_STATE_DIR\"]);\n\n if (stateDir) {\n addLocation(locations, seen, join(resolveHomePath(stateDir), \"state.sqlite\"), \"state\");\n }\n\n for (const baseDir of uniqueStrings([\n stringValue(process.env[\"T3CODE_HOME\"]),\n join(homedir(), \".t3\"),\n ])) {\n addLocation(\n locations,\n seen,\n join(resolveHomePath(baseDir), \"userdata\", \"state.sqlite\"),\n \"userdata\",\n );\n addLocation(locations, seen, join(resolveHomePath(baseDir), \"dev\", \"state.sqlite\"), \"dev\");\n }\n\n return locations;\n}\n\nfunction addLocation(\n locations: T3DatabaseLocation[],\n seen: Set<string>,\n dbPath: string,\n scope: string,\n): void {\n if (seen.has(dbPath) || !existsSync(dbPath)) {\n return;\n }\n\n seen.add(dbPath);\n locations.push({ path: dbPath, scope });\n}\n\nfunction resolveHomePath(value: string): string {\n if (value === \"~\") {\n return homedir();\n }\n if (value.startsWith(\"~/\") || value.startsWith(\"~\\\\\")) {\n return join(homedir(), value.slice(2));\n }\n return isAbsolute(value) ? value : resolve(value);\n}\n\nasync function openT3Db(dbPath: string): Promise<import(\"better-sqlite3\").Database | null> {\n try {\n const BetterSqlite3 = await import(\"better-sqlite3\");\n const Ctor = BetterSqlite3.default ?? BetterSqlite3;\n return new (Ctor as unknown as new (...args: unknown[]) => import(\"better-sqlite3\").Database)(\n dbPath,\n { readonly: true, fileMustExist: true },\n );\n } catch {\n return null;\n }\n}\n\nfunction* queryUserMessages(\n db: import(\"better-sqlite3\").Database,\n location: T3DatabaseLocation,\n options?: AdapterOptions,\n): Generator<Message> {\n if (!hasColumns(db, \"projection_thread_messages\", [\"thread_id\", \"role\", \"text\", \"created_at\"])) {\n return;\n }\n\n const orderColumn = hasColumns(db, \"projection_thread_messages\", [\"message_id\"])\n ? \"message_id\"\n : \"created_at\";\n let query = `\n SELECT thread_id, created_at, text\n FROM projection_thread_messages\n WHERE role = 'user'\n `;\n const params: unknown[] = [];\n if (options?.since) {\n query += ` AND created_at >= ?`;\n params.push(options.since.toISOString());\n }\n query += ` ORDER BY created_at ASC, ${orderColumn} ASC`;\n\n let rows: T3MessageRow[];\n try {\n rows = db.prepare(query).all(...params) as T3MessageRow[];\n } catch {\n return;\n }\n\n for (const row of rows) {\n const text = stringValue(row.text);\n if (!text) {\n continue;\n }\n\n yield {\n text,\n timestamp: stringValue(row.created_at),\n session: stringValue(row.thread_id),\n project: location.scope,\n };\n }\n}\n\nfunction* queryUsageRecords(\n db: import(\"better-sqlite3\").Database,\n location: T3DatabaseLocation,\n seen: Set<string>,\n options?: AdapterOptions,\n): Generator<UsageRecord> {\n if (\n !hasColumns(db, \"orchestration_events\", [\n \"event_id\",\n \"stream_id\",\n \"event_type\",\n \"occurred_at\",\n \"payload_json\",\n ])\n ) {\n return;\n }\n\n const threadInfo = readThreadInfo(db);\n const orderColumn = hasColumns(db, \"orchestration_events\", [\"sequence\"])\n ? \"sequence\"\n : \"event_id\";\n let query = `\n SELECT event_id, stream_id, occurred_at, payload_json\n FROM orchestration_events\n WHERE event_type = 'thread.activity-appended'\n `;\n const params: unknown[] = [];\n if (options?.since) {\n query += ` AND occurred_at >= ?`;\n params.push(options.since.toISOString());\n }\n query += ` ORDER BY occurred_at ASC, ${orderColumn} ASC`;\n\n let rows: T3UsageEventRow[];\n try {\n rows = db.prepare(query).all(...params) as T3UsageEventRow[];\n } catch {\n return;\n }\n\n for (const row of rows) {\n const payload = asRecord(parseJson(row.payload_json));\n const activity = asRecord(payload?.[\"activity\"]);\n if (activity?.[\"kind\"] !== \"context-window.updated\") {\n continue;\n }\n\n const usage = parseUsageSnapshot(activity[\"payload\"]);\n if (!usage || !hasBillableUsage(usage)) {\n continue;\n }\n\n const threadId = stringValue(payload?.[\"threadId\"]) ?? stringValue(row.stream_id);\n const timestamp = stringValue(activity[\"createdAt\"]) ?? stringValue(row.occurred_at);\n const turnId = stringValue(activity[\"turnId\"]);\n const info = threadId ? threadInfo.get(threadId) : undefined;\n const provider = normalizeT3Provider(info?.provider, info?.model);\n const dedupeKey = t3UsageDedupeKey({\n scope: location.scope,\n threadId,\n turnId,\n provider,\n model: info?.model,\n usage,\n });\n if (seen.has(dedupeKey)) {\n continue;\n }\n seen.add(dedupeKey);\n\n yield {\n agent: \"t3code\",\n provider,\n model: info?.model,\n timestamp,\n session: threadId,\n inputTokens: usage.inputTokens,\n outputTokens: usage.outputTokens,\n reasoningTokens: usage.reasoningTokens,\n cacheReadTokens: usage.cacheReadTokens,\n cacheWriteTokens: usage.cacheWriteTokens,\n };\n }\n}\n\nfunction normalizeT3Provider(\n provider: string | undefined,\n model: string | undefined,\n): string | undefined {\n const normalized = provider?.trim().toLowerCase();\n const key = normalized?.replace(/[^a-z0-9]/g, \"\");\n switch (key) {\n case \"codex\":\n return \"openai\";\n case \"claudeagent\":\n case \"claudecode\":\n return \"anthropic\";\n case \"cursor\":\n case \"opencode\":\n return undefined;\n default:\n if (key?.includes(\"codex\")) {\n return \"openai\";\n }\n if (key?.includes(\"claude\")) {\n return \"anthropic\";\n }\n if (normalized === \"openai\" || normalized === \"anthropic\") {\n return normalized;\n }\n return providerFromModel(model);\n }\n}\n\nfunction providerFromModel(model: string | undefined): string | undefined {\n const slash = model?.indexOf(\"/\") ?? -1;\n if (!model || slash <= 0) {\n return undefined;\n }\n\n return model.slice(0, slash);\n}\n\nfunction readThreadInfo(db: import(\"better-sqlite3\").Database): Map<string, ThreadInfo> {\n const info = new Map<string, ThreadInfo>();\n\n readProjectionThreadModels(db, info);\n readProjectionThreadProviders(db, info);\n\n return info;\n}\n\nfunction readProjectionThreadModels(\n db: import(\"better-sqlite3\").Database,\n info: Map<string, ThreadInfo>,\n): void {\n if (!tableExists(db, \"projection_threads\")) {\n return;\n }\n\n const columns = tableColumns(db, \"projection_threads\");\n if (!columns.has(\"thread_id\")) {\n return;\n }\n\n try {\n if (columns.has(\"model_selection_json\")) {\n const rows = db\n .prepare(\"SELECT thread_id, model_selection_json FROM projection_threads\")\n .all() as T3ThreadModelSelectionRow[];\n for (const row of rows) {\n const threadId = stringValue(row.thread_id);\n const modelSelection = asRecord(parseJson(row.model_selection_json));\n if (!threadId || !modelSelection) {\n continue;\n }\n const entry = info.get(threadId) ?? {};\n entry.model = stringValue(modelSelection[\"model\"]) ?? entry.model;\n entry.provider =\n stringValue(modelSelection[\"provider\"]) ??\n stringValue(modelSelection[\"instanceId\"]) ??\n entry.provider;\n info.set(threadId, entry);\n }\n return;\n }\n\n if (columns.has(\"model\")) {\n const rows = db\n .prepare(\"SELECT thread_id, model FROM projection_threads\")\n .all() as T3ThreadModelRow[];\n for (const row of rows) {\n const threadId = stringValue(row.thread_id);\n const model = stringValue(row.model);\n if (threadId && model) {\n info.set(threadId, { ...info.get(threadId), model });\n }\n }\n }\n } catch {\n return;\n }\n}\n\nfunction readProjectionThreadProviders(\n db: import(\"better-sqlite3\").Database,\n info: Map<string, ThreadInfo>,\n): void {\n if (!hasColumns(db, \"projection_thread_sessions\", [\"thread_id\", \"provider_name\"])) {\n return;\n }\n\n try {\n const rows = db\n .prepare(\"SELECT thread_id, provider_name FROM projection_thread_sessions\")\n .all() as T3ThreadSessionRow[];\n for (const row of rows) {\n const threadId = stringValue(row.thread_id);\n const provider = stringValue(row.provider_name);\n if (!threadId || !provider) {\n continue;\n }\n info.set(threadId, { ...info.get(threadId), provider });\n }\n } catch {\n return;\n }\n}\n\nfunction parseUsageSnapshot(value: unknown): ParsedUsage | null {\n const usage = asRecord(value);\n if (!usage) {\n return null;\n }\n\n const lastInputTokens = tokenValue(usage[\"lastInputTokens\"] ?? usage[\"last_input_tokens\"]);\n const lastCachedInputTokens = tokenValue(\n usage[\"lastCachedInputTokens\"] ?? usage[\"last_cached_input_tokens\"],\n );\n const lastOutputTokens = tokenValue(usage[\"lastOutputTokens\"] ?? usage[\"last_output_tokens\"]);\n const lastReasoningOutputTokens = tokenValue(\n usage[\"lastReasoningOutputTokens\"] ?? usage[\"last_reasoning_output_tokens\"],\n );\n const hasLastDetails = [\n lastInputTokens,\n lastCachedInputTokens,\n lastOutputTokens,\n lastReasoningOutputTokens,\n ].some((token) => token !== undefined);\n\n if (hasLastDetails) {\n return splitTokenUsage({\n inputTokens: lastInputTokens ?? 0,\n cachedInputTokens: lastCachedInputTokens ?? 0,\n outputTokens: lastOutputTokens ?? 0,\n reasoningOutputTokens: lastReasoningOutputTokens ?? 0,\n });\n }\n\n const inputTokens = tokenValue(usage[\"inputTokens\"] ?? usage[\"input_tokens\"]);\n const cachedInputTokens = tokenValue(usage[\"cachedInputTokens\"] ?? usage[\"cached_input_tokens\"]);\n const outputTokens = tokenValue(usage[\"outputTokens\"] ?? usage[\"output_tokens\"]);\n const reasoningOutputTokens = tokenValue(\n usage[\"reasoningOutputTokens\"] ?? usage[\"reasoning_output_tokens\"],\n );\n const hasSnapshotDetails = [\n inputTokens,\n cachedInputTokens,\n outputTokens,\n reasoningOutputTokens,\n ].some((token) => token !== undefined);\n\n if (!hasSnapshotDetails) {\n return null;\n }\n\n return splitTokenUsage({\n inputTokens: inputTokens ?? 0,\n cachedInputTokens: cachedInputTokens ?? 0,\n outputTokens: outputTokens ?? 0,\n reasoningOutputTokens: reasoningOutputTokens ?? 0,\n });\n}\n\nfunction splitTokenUsage(input: {\n inputTokens: number;\n cachedInputTokens: number;\n outputTokens: number;\n reasoningOutputTokens: number;\n}): ParsedUsage {\n const reasoningTokens = Math.min(input.reasoningOutputTokens, input.outputTokens);\n return {\n inputTokens: Math.max(input.inputTokens - input.cachedInputTokens, 0),\n outputTokens: Math.max(input.outputTokens - reasoningTokens, 0),\n reasoningTokens,\n cacheReadTokens: input.cachedInputTokens,\n cacheWriteTokens: 0,\n };\n}\n\nfunction hasBillableUsage(usage: ParsedUsage): boolean {\n return (\n usage.inputTokens +\n usage.outputTokens +\n usage.reasoningTokens +\n usage.cacheReadTokens +\n usage.cacheWriteTokens >\n 0\n );\n}\n\nfunction t3UsageDedupeKey(input: {\n scope: string;\n threadId?: string;\n turnId?: string;\n provider?: string;\n model?: string;\n usage: ParsedUsage;\n}): string {\n return JSON.stringify([\n input.scope,\n input.threadId ?? \"\",\n input.turnId ?? \"\",\n input.provider ?? \"\",\n input.model ?? \"\",\n input.usage.inputTokens,\n input.usage.outputTokens,\n input.usage.reasoningTokens,\n input.usage.cacheReadTokens,\n input.usage.cacheWriteTokens,\n ]);\n}\n\nfunction hasColumns(\n db: import(\"better-sqlite3\").Database,\n table: string,\n requiredColumns: string[],\n): boolean {\n const columns = tableColumns(db, table);\n return requiredColumns.every((column) => columns.has(column));\n}\n\nfunction tableExists(db: import(\"better-sqlite3\").Database, table: string): boolean {\n try {\n const row = db\n .prepare(\"SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = ? LIMIT 1\")\n .get(table);\n return Boolean(row);\n } catch {\n return false;\n }\n}\n\nfunction tableColumns(db: import(\"better-sqlite3\").Database, table: string): Set<string> {\n if (!tableExists(db, table)) {\n return new Set();\n }\n\n try {\n const rows = db.prepare(`PRAGMA table_info(\"${table}\")`).all() as { name: unknown }[];\n return new Set(rows.flatMap((row) => stringValue(row.name) ?? []));\n } catch {\n return new Set();\n }\n}\n\nfunction parseJson(value: unknown): unknown | null {\n if (typeof value !== \"string\") {\n return null;\n }\n\n try {\n return JSON.parse(value) as unknown;\n } catch {\n return null;\n }\n}\n\nfunction tokenValue(value: unknown): number | undefined {\n if (typeof value !== \"number\" || !Number.isFinite(value)) {\n return undefined;\n }\n\n return Math.max(Math.round(value), 0);\n}\n\nfunction uniqueStrings(values: (string | undefined)[]): string[] {\n const seen = new Set<string>();\n const unique: string[] = [];\n\n for (const value of values) {\n if (!value || seen.has(value)) {\n continue;\n }\n seen.add(value);\n unique.push(value);\n }\n\n return unique;\n}\n\nfunction stringValue(value: unknown): string | undefined {\n return typeof value === \"string\" && value.trim() ? value : undefined;\n}\n\nfunction asRecord(value: unknown): Record<string, unknown> | null {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n return null;\n }\n\n return value as Record<string, unknown>;\n}\n", "import { readdir, readFile } from \"node:fs/promises\";\nimport { existsSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport type { Adapter, AdapterOptions, Message } from \"./index\";\n\n/**\n * Zed stores AI conversations in two places:\n *\n * 1. Text threads (older assistant panel):\n * ~/.local/share/zed/conversations/*.json (Linux)\n * ~/Library/Application Support/Zed/conversations/*.json (macOS)\n * These are markdown-like JSON with messages.\n *\n * 2. Agent threads (newer):\n * Stored in SQLite at ~/.local/share/zed/db (Linux)\n * or ~/Library/Application Support/Zed/db (macOS)\n * We'd need to query this, but the schema isn't well documented.\n *\n * We support the text thread JSON files for now, and the SQLite agent\n * threads when better-sqlite3 is available.\n */\n\nfunction getZedPaths(): { conversations: string; db: string } {\n if (process.platform === \"darwin\") {\n const base = join(homedir(), \"Library\", \"Application Support\", \"Zed\");\n return {\n conversations: join(base, \"conversations\"),\n db: join(base, \"db\"),\n };\n }\n // Linux / others\n const base = join(process.env[\"XDG_DATA_HOME\"] ?? join(homedir(), \".local\", \"share\"), \"zed\");\n return {\n conversations: join(base, \"conversations\"),\n db: join(base, \"db\"),\n };\n}\n\nexport function zedAdapter(): Adapter {\n return {\n name: \"zed\",\n async *messages(options?: AdapterOptions): AsyncGenerator<Message> {\n const paths = getZedPaths();\n\n // 1. Parse text thread JSON conversations\n yield* parseTextThreads(paths.conversations, options);\n\n // 2. Try SQLite agent threads\n yield* parseAgentThreads(paths.db, options);\n },\n };\n}\n\nasync function* parseTextThreads(dir: string, _options?: AdapterOptions): AsyncGenerator<Message> {\n if (!existsSync(dir)) {\n return;\n }\n\n let files: string[];\n try {\n files = await readdir(dir);\n } catch {\n return;\n }\n\n const jsonFiles = files.filter((f) => f.endsWith(\".json\"));\n\n for (const file of jsonFiles) {\n const filePath = join(dir, file);\n const session = file.replace(\".json\", \"\");\n\n try {\n const raw = await readFile(filePath, \"utf-8\");\n const conversation = JSON.parse(raw) as ZedConversation;\n\n if (!conversation.messages || !Array.isArray(conversation.messages)) {\n continue;\n }\n\n for (const msg of conversation.messages) {\n if (msg.role !== \"user\") {\n continue;\n }\n\n const text = typeof msg.content === \"string\" ? msg.content : null;\n if (!text) {\n continue;\n }\n\n yield {\n text,\n session,\n };\n }\n } catch {\n // Skip malformed files\n }\n }\n}\n\nasync function* parseAgentThreads(\n dbDir: string,\n _options?: AdapterOptions,\n): AsyncGenerator<Message> {\n // Zed uses a directory of SQLite databases. The main one is typically\n // a file like 0-dev.db or similar inside the db/ directory.\n if (!existsSync(dbDir)) {\n return;\n }\n\n let dbFiles: string[];\n try {\n const entries = await readdir(dbDir);\n dbFiles = entries.filter((f) => f.endsWith(\".db\"));\n } catch {\n return;\n }\n\n if (dbFiles.length === 0) {\n return;\n }\n\n let Database: unknown;\n try {\n const mod = await import(\"better-sqlite3\");\n Database = mod.default ?? mod;\n } catch {\n return; // better-sqlite3 not available\n }\n\n for (const dbFile of dbFiles) {\n const dbPath = join(dbDir, dbFile);\n let db: import(\"better-sqlite3\").Database;\n\n try {\n db = new (Database as new (...args: unknown[]) => import(\"better-sqlite3\").Database)(dbPath, {\n readonly: true,\n });\n } catch {\n continue; // Can't open this DB\n }\n\n try {\n // Check if this DB has a threads/messages table\n const tables = db.prepare(\"SELECT name FROM sqlite_master WHERE type='table'\").all() as {\n name: string;\n }[];\n const tableNames = tables.map((t) => t.name);\n\n // Look for message-like tables (Zed's schema may vary by version)\n const msgTable = tableNames.find(\n (t) => t === \"messages\" || t === \"thread_messages\" || t.includes(\"message\"),\n );\n\n if (!msgTable) {\n db.close();\n continue;\n }\n\n const columns = db.prepare(`PRAGMA table_info(\"${msgTable}\")`).all() as {\n name: string;\n }[];\n const colNames = columns.map((c) => c.name);\n\n const hasRole = colNames.includes(\"role\");\n\n if (!hasRole) {\n db.close();\n continue;\n }\n\n const contentCol = colNames.includes(\"content\")\n ? \"content\"\n : colNames.includes(\"body\")\n ? \"body\"\n : \"text\";\n\n let query = `SELECT \"${contentCol}\" as text FROM \"${msgTable}\" WHERE role = 'user'`;\n\n const rows = db.prepare(query).all() as { text: string }[];\n for (const row of rows) {\n if (!row.text?.trim()) {\n continue;\n }\n yield { text: row.text };\n }\n } catch {\n // Schema mismatch or other error\n } finally {\n db.close();\n }\n }\n}\n\ninterface ZedConversation {\n messages?: { role?: string; content?: unknown }[];\n}\n", "import { ampAdapter } from \"./amp\";\nimport { claudeAdapter } from \"./claude\";\nimport { clineAdapter } from \"./cline\";\nimport { codexAdapter } from \"./codex\";\nimport { cursorAdapter } from \"./cursor\";\nimport { opencodeAdapter } from \"./opencode\";\nimport { piAdapter } from \"./pi\";\nimport { t3codeAdapter } from \"./t3code\";\nimport { zedAdapter } from \"./zed\";\n\nexport interface Message {\n text: string;\n timestamp?: string;\n session?: string;\n project?: string;\n}\n\nexport interface CostModelSummary {\n model: string;\n provider?: string;\n requests: number;\n estimatedCost: number;\n billedCost: number;\n pricingSource: PricingSource;\n unpricedRequests: number;\n inputTokens: number;\n outputTokens: number;\n reasoningTokens: number;\n cacheReadTokens: number;\n cacheWriteTokens: number;\n}\n\nexport interface CostDaySummary {\n day: string;\n requests: number;\n estimatedCost: number;\n billedCost: number;\n unpricedRequests: number;\n inputTokens: number;\n outputTokens: number;\n reasoningTokens: number;\n cacheReadTokens: number;\n cacheWriteTokens: number;\n models: CostModelSummary[];\n}\n\nexport type PricingSource =\n | \"catalog\"\n | \"stale-catalog\"\n | \"fallback\"\n | \"stored\"\n | \"unknown\"\n | \"mixed\";\n\nexport interface PricingMetadata {\n source: \"catalog\" | \"stale-catalog\" | \"fallback\";\n fetchedAt?: string;\n}\n\nexport interface CostSummary {\n requests: number;\n estimatedCost: number;\n billedCost: number;\n unpricedRequests: number;\n inputTokens: number;\n outputTokens: number;\n reasoningTokens: number;\n cacheReadTokens: number;\n cacheWriteTokens: number;\n models: CostModelSummary[];\n days: CostDaySummary[];\n pricing: PricingMetadata;\n}\n\nexport interface UsageRecord {\n agent: string;\n provider?: string;\n model?: string;\n timestamp?: string;\n session?: string;\n billedCost?: number;\n inputTokens: number;\n outputTokens: number;\n reasoningTokens: number;\n cacheReadTokens: number;\n cacheWriteTokens: number;\n}\n\nexport interface Adapter {\n name: string;\n /** Discover and yield all user messages from local session storage */\n messages(options?: AdapterOptions): AsyncGenerator<Message>;\n /** Discover and yield token/cost accounting rows when the agent exposes them */\n usage?(options?: AdapterOptions): AsyncGenerator<UsageRecord>;\n}\n\nexport interface AdapterOptions {\n since?: Date;\n}\n\nconst ADAPTERS: Record<string, () => Adapter> = {\n claude: claudeAdapter,\n codex: codexAdapter,\n cursor: cursorAdapter,\n opencode: opencodeAdapter,\n amp: ampAdapter,\n cline: clineAdapter,\n pi: piAdapter,\n t3code: t3codeAdapter,\n zed: zedAdapter,\n};\n\nexport function createAdapter(name: string): Adapter {\n const factory = ADAPTERS[name];\n if (!factory) {\n throw new Error(`unknown adapter: ${name} (available: ${Object.keys(ADAPTERS).join(\", \")})`);\n }\n return factory();\n}\n\nexport function allAdapters(): Adapter[] {\n return Object.values(ADAPTERS).map((f) => f());\n}\n", "export interface DetectionResult {\n /** Total swear words found in the text */\n count: number;\n /** Individual matches */\n matches: Match[];\n}\n\nexport interface Match {\n word: string;\n index: number;\n severity: Severity;\n group: string;\n}\n\nexport type Severity = \"mild\" | \"moderate\" | \"strong\";\n\ninterface WordDef {\n word: string;\n severity: Severity;\n group: string;\n}\n\n/**\n * Core wordlist: canonical forms, conjugations, compound words, and common typos.\n * Grouped by root word for reporting rollup.\n *\n * Sources:\n * - swearjar npm (en_US.json) for compound words\n * - Manual typo variants based on common keyboard transpositions\n */\nconst WORDLIST: WordDef[] = [\n // === FUCK family (strong) ===\n // Canonical forms\n { word: \"fuck\", severity: \"strong\", group: \"fuck\" },\n { word: \"fucking\", severity: \"strong\", group: \"fuck\" },\n { word: \"fucked\", severity: \"strong\", group: \"fuck\" },\n { word: \"fucker\", severity: \"strong\", group: \"fuck\" },\n { word: \"fuckin\", severity: \"strong\", group: \"fuck\" },\n { word: \"fucks\", severity: \"strong\", group: \"fuck\" },\n // Compound words\n { word: \"motherfucker\", severity: \"strong\", group: \"fuck\" },\n { word: \"motherfucking\", severity: \"strong\", group: \"fuck\" },\n { word: \"mothafucka\", severity: \"strong\", group: \"fuck\" },\n { word: \"fuckup\", severity: \"strong\", group: \"fuck\" },\n { word: \"fuckoff\", severity: \"strong\", group: \"fuck\" },\n { word: \"clusterfuck\", severity: \"strong\", group: \"fuck\" },\n { word: \"fuckwit\", severity: \"strong\", group: \"fuck\" },\n { word: \"fucktard\", severity: \"strong\", group: \"fuck\" },\n { word: \"fuckface\", severity: \"strong\", group: \"fuck\" },\n { word: \"fuckhead\", severity: \"strong\", group: \"fuck\" },\n // Typos \u2014 transpositions\n { word: \"fukc\", severity: \"strong\", group: \"fuck\" },\n { word: \"fukcing\", severity: \"strong\", group: \"fuck\" },\n { word: \"fukced\", severity: \"strong\", group: \"fuck\" },\n { word: \"fukcer\", severity: \"strong\", group: \"fuck\" },\n { word: \"fcuk\", severity: \"strong\", group: \"fuck\" },\n { word: \"fcuking\", severity: \"strong\", group: \"fuck\" },\n { word: \"fcuked\", severity: \"strong\", group: \"fuck\" },\n { word: \"fuk\", severity: \"strong\", group: \"fuck\" },\n { word: \"fuking\", severity: \"strong\", group: \"fuck\" },\n { word: \"fuked\", severity: \"strong\", group: \"fuck\" },\n { word: \"fuker\", severity: \"strong\", group: \"fuck\" },\n { word: \"fuxk\", severity: \"strong\", group: \"fuck\" },\n { word: \"fuxking\", severity: \"strong\", group: \"fuck\" },\n\n // === SHIT family (strong) ===\n { word: \"shit\", severity: \"strong\", group: \"shit\" },\n { word: \"shitty\", severity: \"strong\", group: \"shit\" },\n { word: \"shitting\", severity: \"strong\", group: \"shit\" },\n { word: \"shits\", severity: \"strong\", group: \"shit\" },\n { word: \"shitted\", severity: \"strong\", group: \"shit\" },\n // Compound words\n { word: \"bullshit\", severity: \"strong\", group: \"shit\" },\n { word: \"horseshit\", severity: \"strong\", group: \"shit\" },\n { word: \"dipshit\", severity: \"strong\", group: \"shit\" },\n { word: \"shitshow\", severity: \"strong\", group: \"shit\" },\n { word: \"shithead\", severity: \"strong\", group: \"shit\" },\n { word: \"shithole\", severity: \"strong\", group: \"shit\" },\n { word: \"shitface\", severity: \"strong\", group: \"shit\" },\n { word: \"shitfaced\", severity: \"strong\", group: \"shit\" },\n { word: \"shitstain\", severity: \"strong\", group: \"shit\" },\n { word: \"shitbag\", severity: \"strong\", group: \"shit\" },\n // Typos\n { word: \"hsit\", severity: \"strong\", group: \"shit\" },\n { word: \"siht\", severity: \"strong\", group: \"shit\" },\n { word: \"shti\", severity: \"strong\", group: \"shit\" },\n { word: \"sjit\", severity: \"strong\", group: \"shit\" },\n { word: \"shjt\", severity: \"strong\", group: \"shit\" },\n { word: \"bulshit\", severity: \"strong\", group: \"shit\" },\n { word: \"bullsht\", severity: \"strong\", group: \"shit\" },\n\n // === ASS family (moderate) ===\n { word: \"ass\", severity: \"moderate\", group: \"ass\" },\n { word: \"asses\", severity: \"moderate\", group: \"ass\" },\n // Compound words (these are strong)\n { word: \"asshole\", severity: \"strong\", group: \"ass\" },\n { word: \"assholes\", severity: \"strong\", group: \"ass\" },\n { word: \"jackass\", severity: \"strong\", group: \"ass\" },\n { word: \"dumbass\", severity: \"strong\", group: \"ass\" },\n { word: \"fatass\", severity: \"moderate\", group: \"ass\" },\n { word: \"asshat\", severity: \"strong\", group: \"ass\" },\n { word: \"asswipe\", severity: \"strong\", group: \"ass\" },\n { word: \"badass\", severity: \"mild\", group: \"ass\" },\n\n // === DAMN family (moderate) ===\n { word: \"damn\", severity: \"moderate\", group: \"damn\" },\n { word: \"damned\", severity: \"moderate\", group: \"damn\" },\n { word: \"damnit\", severity: \"moderate\", group: \"damn\" },\n { word: \"dammit\", severity: \"moderate\", group: \"damn\" },\n { word: \"goddamn\", severity: \"moderate\", group: \"damn\" },\n { word: \"goddamnit\", severity: \"moderate\", group: \"damn\" },\n { word: \"goddammit\", severity: \"moderate\", group: \"damn\" },\n\n // === BITCH family (strong) ===\n { word: \"bitch\", severity: \"strong\", group: \"bitch\" },\n { word: \"bitches\", severity: \"strong\", group: \"bitch\" },\n { word: \"bitching\", severity: \"strong\", group: \"bitch\" },\n { word: \"bitchy\", severity: \"strong\", group: \"bitch\" },\n { word: \"bitchass\", severity: \"strong\", group: \"bitch\" },\n\n // === BASTARD (strong) ===\n { word: \"bastard\", severity: \"strong\", group: \"bastard\" },\n { word: \"bastards\", severity: \"strong\", group: \"bastard\" },\n\n // === PISS family (moderate) ===\n { word: \"piss\", severity: \"moderate\", group: \"piss\" },\n { word: \"pissed\", severity: \"moderate\", group: \"piss\" },\n { word: \"pissing\", severity: \"moderate\", group: \"piss\" },\n { word: \"pissoff\", severity: \"moderate\", group: \"piss\" },\n\n // === DICK (moderate) ===\n { word: \"dick\", severity: \"moderate\", group: \"dick\" },\n { word: \"dickhead\", severity: \"strong\", group: \"dick\" },\n\n // === CRAP (moderate) ===\n { word: \"crap\", severity: \"moderate\", group: \"crap\" },\n { word: \"crappy\", severity: \"moderate\", group: \"crap\" },\n { word: \"crapping\", severity: \"moderate\", group: \"crap\" },\n\n // === HELL (mild) ===\n { word: \"hell\", severity: \"mild\", group: \"hell\" },\n\n // === Abbreviations (mild) ===\n { word: \"wtf\", severity: \"mild\", group: \"wtf\" },\n { word: \"stfu\", severity: \"mild\", group: \"stfu\" },\n { word: \"lmfao\", severity: \"mild\", group: \"lmfao\" },\n { word: \"lmao\", severity: \"mild\", group: \"lmao\" },\n\n // === CUNT (strong) ===\n { word: \"cunt\", severity: \"strong\", group: \"cunt\" },\n { word: \"cunts\", severity: \"strong\", group: \"cunt\" },\n];\n\n/**\n * Normalize text before matching:\n * 1. Collapse repeated characters (3+ of the same char \u2192 2)\n * e.g. \"fuuuuck\" \u2192 \"fuuck\", \"shiiiiit\" \u2192 \"shiit\"\n * This lets \"fuuuuck\" match against \"fuck\" after the regex runs,\n * because the pattern also includes \"fuuck\" style intermediates.\n *\n * Actually \u2014 better approach: collapse ALL runs of 2+ to 1 for matching\n * purposes, while keeping the original text for position tracking.\n * e.g. \"fuuuuck\" \u2192 \"fuck\", \"shiiiit\" \u2192 \"shit\"\n * This directly normalizes to the root word.\n */\nfunction collapseRepeats(text: string): string {\n return text.replace(/(.)\\1+/g, \"$1\");\n}\n\n/**\n * Build the detection regex from the wordlist.\n * Sort longer words first so \"motherfucker\" matches before \"fuck\".\n */\nfunction buildPattern(words: WordDef[]): RegExp {\n const sorted = [...words].sort((a, b) => b.word.length - a.word.length);\n const pattern = sorted.map((w) => w.word).join(\"|\");\n return new RegExp(`\\\\b(${pattern})\\\\b`, \"gi\");\n}\n\nconst DEFAULT_PATTERN = buildPattern(WORDLIST);\nconst WORD_MAP = new Map(WORDLIST.map((w) => [w.word.toLowerCase(), w]));\n\n/**\n * Detect profanity in a string.\n *\n * Runs detection in two passes:\n * 1. Direct match on original text (preserves positions)\n * 2. Match on repeat-collapsed text (catches fuuuuck, shiiiiit, etc.)\n */\nexport function detect(text: string): DetectionResult {\n const matches: Match[] = [];\n const seen = new Set<number>(); // track original-text positions we've already matched\n\n // Pass 1: direct match on original (lowercase) text\n runPattern(text, text.toLowerCase(), matches, seen);\n\n // Pass 2: match on collapsed text to catch repeated chars\n const collapsed = collapseRepeats(text.toLowerCase());\n if (collapsed !== text.toLowerCase()) {\n runPattern(text, collapsed, matches, seen);\n }\n\n return { count: matches.length, matches };\n}\n\nfunction runPattern(\n _originalText: string,\n searchText: string,\n matches: Match[],\n seen: Set<number>,\n): void {\n DEFAULT_PATTERN.lastIndex = 0;\n\n let match: RegExpExecArray | null;\n while ((match = DEFAULT_PATTERN.exec(searchText)) !== null) {\n if (seen.has(match.index)) {\n continue;\n }\n\n const word = match[0].toLowerCase();\n const entry = WORD_MAP.get(word);\n if (!entry) {\n continue;\n }\n\n seen.add(match.index);\n matches.push({\n word,\n index: match.index,\n severity: entry.severity,\n group: entry.group,\n });\n }\n}\n\n/**\n * Create a custom detector with additional words.\n */\nexport function createDetector(extraWords?: WordDef[]): (text: string) => DetectionResult {\n const allWords = extraWords ? [...WORDLIST, ...extraWords] : WORDLIST;\n const pattern = buildPattern(allWords);\n const wordMap = new Map(allWords.map((w) => [w.word.toLowerCase(), w]));\n\n return (text: string): DetectionResult => {\n const matches: Match[] = [];\n const seen = new Set<number>();\n\n const lower = text.toLowerCase();\n pattern.lastIndex = 0;\n let match: RegExpExecArray | null;\n while ((match = pattern.exec(lower)) !== null) {\n if (seen.has(match.index)) {\n continue;\n }\n const word = match[0].toLowerCase();\n const entry = wordMap.get(word);\n if (!entry) {\n continue;\n }\n seen.add(match.index);\n matches.push({ word, index: match.index, severity: entry.severity, group: entry.group });\n }\n\n const collapsed = collapseRepeats(lower);\n if (collapsed !== lower) {\n pattern.lastIndex = 0;\n while ((match = pattern.exec(collapsed)) !== null) {\n if (seen.has(match.index)) {\n continue;\n }\n const word = match[0].toLowerCase();\n const entry = wordMap.get(word);\n if (!entry) {\n continue;\n }\n seen.add(match.index);\n matches.push({ word, index: match.index, severity: entry.severity, group: entry.group });\n }\n }\n\n return { count: matches.length, matches };\n };\n}\n\nexport type { WordDef as WordEntry };\n", "import { mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\nimport type {\n CostDaySummary,\n CostModelSummary,\n CostSummary,\n PricingMetadata,\n PricingSource,\n UsageRecord,\n} from \"../adapters/index\";\n\n/**\n * Owns API-equivalent token pricing. The models.dev cache is local-only, and\n * adapter-reported billed cost stays separate from estimated token-price cost.\n */\n\nconst MODELS_DEV_URL = \"https://models.dev/api.json\";\nconst CACHE_TTL_MS = 7 * 24 * 60 * 60 * 1000;\nconst FETCH_TIMEOUT_MS = 2_000;\n\ninterface PricingOptions {\n refresh?: boolean;\n cacheTtlMs?: number;\n fetchTimeoutMs?: number;\n}\n\ninterface PricingCatalog extends PricingMetadata {\n cachePath: string;\n catalog?: unknown;\n}\n\ninterface PricingCacheFile {\n source: \"models.dev\";\n fetchedAt: string;\n schemaVersion: 1;\n catalog: unknown;\n}\n\ninterface RateTable {\n input?: number;\n output?: number;\n cache_read?: number;\n cache_write?: number;\n tiers?: unknown[];\n context_over_200k?: RateTable;\n}\n\ninterface ResolvedRates {\n provider?: string;\n model: string;\n rates: RateTable;\n source: Exclude<PricingSource, \"stored\" | \"unknown\" | \"mixed\">;\n}\n\ninterface PricedUsage {\n provider?: string;\n model: string;\n estimatedCost: number;\n source: PricingSource;\n}\n\ninterface CostAccumulator {\n requests: number;\n estimatedCost: number;\n billedCost: number;\n unpricedRequests: number;\n inputTokens: number;\n outputTokens: number;\n reasoningTokens: number;\n cacheReadTokens: number;\n cacheWriteTokens: number;\n byModel: Map<string, CostModelSummary>;\n}\n\nconst FALLBACK_COSTS: Record<string, Record<string, RateTable>> = {\n openai: {\n \"gpt-5.5\": {\n input: 5,\n output: 30,\n cache_read: 0.5,\n context_over_200k: { input: 10, output: 45, cache_read: 1 },\n },\n \"gpt-5.5-pro\": { input: 30, output: 180 },\n \"gpt-5.4\": { input: 2.5, output: 15, cache_read: 0.25 },\n \"gpt-5.4-mini\": { input: 0.75, output: 4.5, cache_read: 0.075 },\n \"gpt-5.4-nano\": { input: 0.2, output: 1.25, cache_read: 0.02 },\n \"gpt-5.4-pro\": { input: 30, output: 180 },\n \"gpt-5.3-codex\": { input: 1.75, output: 14, cache_read: 0.175 },\n },\n anthropic: {\n \"claude-opus-4-7\": { input: 5, output: 25, cache_read: 0.5, cache_write: 6.25 },\n },\n};\n\nconst PROVIDER_ALIASES: Record<string, string> = {\n anthropic: \"anthropic\",\n claude: \"anthropic\",\n openai: \"openai\",\n};\n\n/** Load models.dev pricing from cache, refresh, stale cache, or embedded fallbacks. */\nexport async function loadPricingCatalog(options: PricingOptions = {}): Promise<PricingCatalog> {\n const cachePath = getPricingCachePath();\n const cache = await readPricingCache(cachePath);\n const ttlMs = options.cacheTtlMs ?? CACHE_TTL_MS;\n\n if (!options.refresh && cache && isFresh(cache.fetchedAt, ttlMs)) {\n return {\n source: \"catalog\",\n fetchedAt: cache.fetchedAt,\n cachePath,\n catalog: cache.catalog,\n };\n }\n\n try {\n const catalog = await fetchModelsDevCatalog(options.fetchTimeoutMs ?? FETCH_TIMEOUT_MS);\n const fetchedAt = new Date().toISOString();\n await writePricingCache(cachePath, {\n source: \"models.dev\",\n fetchedAt,\n schemaVersion: 1,\n catalog,\n });\n\n return { source: \"catalog\", fetchedAt, cachePath, catalog };\n } catch {\n if (cache) {\n return {\n source: \"stale-catalog\",\n fetchedAt: cache.fetchedAt,\n cachePath,\n catalog: cache.catalog,\n };\n }\n\n return { source: \"fallback\", cachePath };\n }\n}\n\n/** Price usage rows individually, then aggregate by model for report output. */\nexport async function summarizeUsage(\n records: AsyncIterable<UsageRecord>,\n pricing: PricingCatalog,\n): Promise<CostSummary> {\n const total = createCostAccumulator();\n const byDay = new Map<string, CostAccumulator>();\n\n for await (const record of records) {\n const priced = priceUsageRecord(record, pricing);\n const billedCost = record.billedCost ?? 0;\n const isUnpriced = priced.source === \"stored\" || priced.source === \"unknown\";\n addUsageToAccumulator(total, record, priced, billedCost, isUnpriced);\n\n const day = timestampDay(record.timestamp);\n if (day) {\n let dayAccumulator = byDay.get(day);\n if (!dayAccumulator) {\n dayAccumulator = createCostAccumulator();\n byDay.set(day, dayAccumulator);\n }\n addUsageToAccumulator(dayAccumulator, record, priced, billedCost, isUnpriced);\n }\n }\n\n return {\n requests: total.requests,\n estimatedCost: total.estimatedCost,\n billedCost: total.billedCost,\n unpricedRequests: total.unpricedRequests,\n inputTokens: total.inputTokens,\n outputTokens: total.outputTokens,\n reasoningTokens: total.reasoningTokens,\n cacheReadTokens: total.cacheReadTokens,\n cacheWriteTokens: total.cacheWriteTokens,\n models: sortedModels(total.byModel),\n days: Array.from(byDay.entries())\n .sort(([left], [right]) => left.localeCompare(right))\n .map(([day, bucket]) => costDaySummary(day, bucket)),\n pricing: {\n source: pricing.source,\n fetchedAt: pricing.fetchedAt,\n },\n };\n}\n\n/** Resolve the devrage-owned cache path for the models.dev catalog. */\nexport function getPricingCachePath(): string {\n if (process.env[\"XDG_CACHE_HOME\"]) {\n return join(process.env[\"XDG_CACHE_HOME\"], \"devrage\", \"models.dev.json\");\n }\n\n if (process.platform === \"darwin\") {\n return join(homedir(), \"Library\", \"Caches\", \"devrage\", \"models.dev.json\");\n }\n\n if (process.platform === \"win32\") {\n const localAppData = process.env[\"LOCALAPPDATA\"] ?? join(homedir(), \"AppData\", \"Local\");\n return join(localAppData, \"devrage\", \"models.dev.json\");\n }\n\n return join(homedir(), \".cache\", \"devrage\", \"models.dev.json\");\n}\n\nfunction createCostAccumulator(): CostAccumulator {\n return {\n requests: 0,\n estimatedCost: 0,\n billedCost: 0,\n unpricedRequests: 0,\n inputTokens: 0,\n outputTokens: 0,\n reasoningTokens: 0,\n cacheReadTokens: 0,\n cacheWriteTokens: 0,\n byModel: new Map(),\n };\n}\n\nfunction addUsageToAccumulator(\n bucket: CostAccumulator,\n record: UsageRecord,\n priced: PricedUsage,\n billedCost: number,\n isUnpriced: boolean,\n): void {\n const key = `${priced.provider ?? \"\"}:${priced.model}`;\n let model = bucket.byModel.get(key);\n\n if (!model) {\n model = {\n model: priced.model,\n provider: priced.provider,\n requests: 0,\n estimatedCost: 0,\n billedCost: 0,\n pricingSource: priced.source,\n unpricedRequests: 0,\n inputTokens: 0,\n outputTokens: 0,\n reasoningTokens: 0,\n cacheReadTokens: 0,\n cacheWriteTokens: 0,\n };\n bucket.byModel.set(key, model);\n }\n\n model.requests += 1;\n model.estimatedCost += priced.estimatedCost;\n model.billedCost += billedCost;\n model.pricingSource = mergePricingSource(model.pricingSource, priced.source);\n model.inputTokens += record.inputTokens;\n model.outputTokens += record.outputTokens;\n model.reasoningTokens += record.reasoningTokens;\n model.cacheReadTokens += record.cacheReadTokens;\n model.cacheWriteTokens += record.cacheWriteTokens;\n\n bucket.requests += 1;\n bucket.estimatedCost += priced.estimatedCost;\n bucket.billedCost += billedCost;\n bucket.inputTokens += record.inputTokens;\n bucket.outputTokens += record.outputTokens;\n bucket.reasoningTokens += record.reasoningTokens;\n bucket.cacheReadTokens += record.cacheReadTokens;\n bucket.cacheWriteTokens += record.cacheWriteTokens;\n\n if (isUnpriced) {\n model.unpricedRequests += 1;\n bucket.unpricedRequests += 1;\n }\n}\n\nfunction costDaySummary(day: string, bucket: CostAccumulator): CostDaySummary {\n return {\n day,\n requests: bucket.requests,\n estimatedCost: bucket.estimatedCost,\n billedCost: bucket.billedCost,\n unpricedRequests: bucket.unpricedRequests,\n inputTokens: bucket.inputTokens,\n outputTokens: bucket.outputTokens,\n reasoningTokens: bucket.reasoningTokens,\n cacheReadTokens: bucket.cacheReadTokens,\n cacheWriteTokens: bucket.cacheWriteTokens,\n models: sortedModels(bucket.byModel),\n };\n}\n\nfunction sortedModels(byModel: Map<string, CostModelSummary>): CostModelSummary[] {\n return Array.from(byModel.values()).sort(\n (a, b) => b.estimatedCost - a.estimatedCost || b.requests - a.requests,\n );\n}\n\nfunction timestampDay(timestamp: string | undefined): string | null {\n if (!timestamp) {\n return null;\n }\n\n const time = new Date(timestamp).getTime();\n if (!Number.isFinite(time)) {\n return null;\n }\n\n return new Date(time).toISOString().slice(0, 10);\n}\n\nasync function fetchModelsDevCatalog(timeoutMs: number): Promise<unknown> {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), timeoutMs);\n\n try {\n const response = await fetch(MODELS_DEV_URL, { signal: controller.signal });\n if (!response.ok) {\n throw new Error(`models.dev returned ${response.status}`);\n }\n\n const catalog = await response.json();\n if (!isModelsDevCatalog(catalog)) {\n throw new Error(\"models.dev response did not match expected shape\");\n }\n\n return catalog;\n } finally {\n clearTimeout(timeout);\n }\n}\n\nasync function readPricingCache(cachePath: string): Promise<PricingCacheFile | null> {\n try {\n const raw = await readFile(cachePath, \"utf-8\");\n const parsed = JSON.parse(raw) as unknown;\n const cache = asRecord(parsed);\n\n if (\n cache?.[\"source\"] !== \"models.dev\" ||\n cache[\"schemaVersion\"] !== 1 ||\n typeof cache[\"fetchedAt\"] !== \"string\" ||\n !isModelsDevCatalog(cache[\"catalog\"])\n ) {\n return null;\n }\n\n return {\n source: \"models.dev\",\n fetchedAt: cache[\"fetchedAt\"],\n schemaVersion: 1,\n catalog: cache[\"catalog\"],\n };\n } catch {\n return null;\n }\n}\n\nasync function writePricingCache(cachePath: string, cache: PricingCacheFile): Promise<void> {\n try {\n await mkdir(dirname(cachePath), { recursive: true });\n await writeFile(cachePath, `${JSON.stringify(cache)}\\n`, \"utf-8\");\n } catch {\n // Cost estimation can still use the freshly fetched catalog when cache writes fail.\n }\n}\n\nfunction priceUsageRecord(record: UsageRecord, catalog: PricingCatalog): PricedUsage {\n const resolved = resolveRates(record, catalog);\n if (!resolved) {\n return {\n provider: normalizeProvider(record.provider),\n model: normalizeModel(record.model) ?? \"unknown\",\n estimatedCost: 0,\n source: (record.billedCost ?? 0) > 0 ? \"stored\" : \"unknown\",\n };\n }\n\n const rates = selectContextRates(resolved.rates, record);\n const inputRate = rates.input ?? 0;\n const outputRate = rates.output ?? 0;\n const cacheReadRate = rates.cache_read ?? inputRate;\n const cacheWriteRate = rates.cache_write ?? inputRate;\n const outputTokens = record.outputTokens + record.reasoningTokens;\n\n return {\n provider: resolved.provider,\n model: resolved.model,\n estimatedCost:\n (record.inputTokens * inputRate +\n record.cacheReadTokens * cacheReadRate +\n record.cacheWriteTokens * cacheWriteRate +\n outputTokens * outputRate) /\n 1_000_000,\n source: resolved.source,\n };\n}\n\nfunction resolveRates(record: UsageRecord, pricing: PricingCatalog): ResolvedRates | null {\n const candidates = modelCandidates(record.provider, record.model);\n\n for (const candidate of candidates) {\n if (!candidate.provider || !pricing.catalog) {\n continue;\n }\n\n const rates = getCatalogRates(pricing.catalog, candidate.provider, candidate.model);\n if (rates) {\n return {\n provider: candidate.provider,\n model: candidate.model,\n rates,\n source: pricing.source === \"stale-catalog\" ? \"stale-catalog\" : \"catalog\",\n };\n }\n }\n\n for (const candidate of candidates) {\n if (!candidate.provider) {\n continue;\n }\n\n const providerRates = FALLBACK_COSTS[candidate.provider];\n const rates = providerRates?.[candidate.model];\n if (rates) {\n return { provider: candidate.provider, model: candidate.model, rates, source: \"fallback\" };\n }\n }\n\n return null;\n}\n\nfunction modelCandidates(\n providerInput: string | undefined,\n modelInput: string | undefined,\n): { provider?: string; model: string }[] {\n const candidates: { provider?: string; model: string }[] = [];\n let provider = normalizeProvider(providerInput);\n let model = normalizeModel(modelInput);\n\n if (!model) {\n return candidates;\n }\n\n const prefixed = splitProviderModel(model);\n if (prefixed) {\n provider = provider ?? prefixed.provider;\n model = prefixed.model;\n }\n\n addCandidate(candidates, provider, model);\n addCandidate(candidates, provider, MODEL_ALIASES[model]);\n\n const inferred = provider ?? inferProvider(model);\n addCandidate(candidates, inferred, model);\n addCandidate(candidates, inferred, MODEL_ALIASES[model]);\n\n for (const fallbackProvider of Object.keys(FALLBACK_COSTS)) {\n addCandidate(candidates, fallbackProvider, model);\n addCandidate(candidates, fallbackProvider, MODEL_ALIASES[model]);\n }\n\n return candidates;\n}\n\nconst MODEL_ALIASES: Record<string, string> = {\n \"gpt-5.5-chat-latest\": \"gpt-5.5\",\n};\n\nfunction addCandidate(\n candidates: { provider?: string; model: string }[],\n provider: string | undefined,\n model: string | undefined,\n): void {\n if (!model) {\n return;\n }\n\n if (\n candidates.some((candidate) => candidate.provider === provider && candidate.model === model)\n ) {\n return;\n }\n\n candidates.push({ provider, model });\n}\n\nfunction splitProviderModel(model: string): { provider: string; model: string } | null {\n const slash = model.indexOf(\"/\");\n if (slash <= 0 || slash === model.length - 1) {\n return null;\n }\n\n const provider = normalizeProvider(model.slice(0, slash));\n const bareModel = normalizeModel(model.slice(slash + 1));\n if (!provider || !bareModel) {\n return null;\n }\n\n return { provider, model: bareModel };\n}\n\nfunction normalizeProvider(provider: string | undefined): string | undefined {\n if (!provider) {\n return undefined;\n }\n\n const normalized = provider.trim().toLowerCase();\n return PROVIDER_ALIASES[normalized] ?? normalized;\n}\n\nfunction normalizeModel(model: string | undefined): string | undefined {\n const normalized = model?.trim().toLowerCase();\n return normalized || undefined;\n}\n\nfunction inferProvider(model: string): string | undefined {\n if (model.startsWith(\"gpt-\") || /^o\\d/.test(model)) {\n return \"openai\";\n }\n\n if (model.startsWith(\"claude-\")) {\n return \"anthropic\";\n }\n\n return undefined;\n}\n\nfunction getCatalogRates(catalog: unknown, provider: string, model: string): RateTable | null {\n const root = asRecord(catalog);\n const providerEntry = asRecord(root?.[provider]);\n const models = asRecord(providerEntry?.[\"models\"]);\n const modelEntry = asRecord(models?.[model]);\n return toRateTable(modelEntry?.[\"cost\"]);\n}\n\nfunction selectContextRates(rates: RateTable, record: UsageRecord): RateTable {\n const contextTokens = record.inputTokens + record.cacheReadTokens + record.cacheWriteTokens;\n let selected = rates;\n let selectedSize = 0;\n\n for (const tier of rates.tiers ?? []) {\n const tierRecord = asRecord(tier);\n const tierInfo = asRecord(tierRecord?.[\"tier\"]);\n const size = typeof tierInfo?.[\"size\"] === \"number\" ? tierInfo[\"size\"] : 0;\n if (tierInfo?.[\"type\"] !== \"context\" || contextTokens < size || size < selectedSize) {\n continue;\n }\n\n const tierRates = toRateTable(tierRecord);\n if (tierRates) {\n selected = { ...rates, ...tierRates };\n selectedSize = size;\n }\n }\n\n if (selected === rates && rates.context_over_200k && contextTokens > 200_000) {\n selected = { ...rates, ...rates.context_over_200k };\n }\n\n return selected;\n}\n\nfunction toRateTable(value: unknown): RateTable | null {\n const record = asRecord(value);\n if (!record) {\n return null;\n }\n\n const rates: RateTable = {};\n const input = numberValue(record[\"input\"]);\n const output = numberValue(record[\"output\"]);\n const cacheRead = numberValue(record[\"cache_read\"]);\n const cacheWrite = numberValue(record[\"cache_write\"]);\n const contextOver200k = toRateTable(record[\"context_over_200k\"]);\n\n if (input !== undefined) {\n rates.input = input;\n }\n if (output !== undefined) {\n rates.output = output;\n }\n if (cacheRead !== undefined) {\n rates.cache_read = cacheRead;\n }\n if (cacheWrite !== undefined) {\n rates.cache_write = cacheWrite;\n }\n if (Array.isArray(record[\"tiers\"])) {\n rates.tiers = record[\"tiers\"];\n }\n if (contextOver200k) {\n rates.context_over_200k = contextOver200k;\n }\n\n return rates.input !== undefined || rates.output !== undefined ? rates : null;\n}\n\nfunction numberValue(value: unknown): number | undefined {\n return typeof value === \"number\" && Number.isFinite(value) ? value : undefined;\n}\n\nfunction isModelsDevCatalog(value: unknown): boolean {\n const catalog = asRecord(value);\n const openai = asRecord(catalog?.[\"openai\"]);\n const anthropic = asRecord(catalog?.[\"anthropic\"]);\n return Boolean(asRecord(openai?.[\"models\"]) || asRecord(anthropic?.[\"models\"]));\n}\n\nfunction isFresh(fetchedAt: string, ttlMs: number): boolean {\n const fetchedTime = new Date(fetchedAt).getTime();\n return Number.isFinite(fetchedTime) && Date.now() - fetchedTime <= ttlMs;\n}\n\nfunction mergePricingSource(left: PricingSource, right: PricingSource): PricingSource {\n return left === right ? left : \"mixed\";\n}\n\nfunction asRecord(value: unknown): Record<string, unknown> | null {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n return null;\n }\n\n return value as Record<string, unknown>;\n}\n", "import { cost, scan } from \"./commands/scan\";\n\nconst COMMANDS: Record<string, (args: string[]) => Promise<void>> = {\n cost,\n scan,\n};\n\nconst OPTIONS_WITH_VALUES = new Set([\"--agent\", \"-a\", \"--since\", \"-s\"]);\n\ninterface ParsedCommand {\n handler: (args: string[]) => Promise<void>;\n args: string[];\n}\n\nfunction usage(): void {\n console.log(`devrage \u2014 count how many times you swear at your coding agents\n\nUsage:\n devrage <command> [options]\n\nCommands:\n cost Show API-equivalent coding agent cost\n scan Scan sessions for profanity\n\nOptions:\n --help, -h Show this help message\n --version Show version\n\nExamples:\n devrage cost\n devrage scan\n devrage scan --agent claude\n devrage scan --since 2025-01-01`);\n}\n\nasync function main(): Promise<void> {\n const args = process.argv.slice(2);\n const command = args[0];\n\n if (command === \"--help\" || command === \"-h\") {\n usage();\n process.exit(0);\n }\n\n if (command === \"--version\") {\n console.log(\"0.5.6\");\n process.exit(0);\n }\n\n // If no command is present, default to scan for the original no-subcommand UX.\n const parsed = parseCommand(args);\n if (parsed) {\n await parsed.handler(parsed.args);\n } else {\n // Pass all args through to scan (covers both no-arg and unknown-arg cases)\n await scan(args);\n }\n}\n\nfunction parseCommand(args: string[]): ParsedCommand | null {\n for (let index = 0; index < args.length; index++) {\n const arg = args[index];\n if (!arg) {\n continue;\n }\n\n const handler = COMMANDS[arg];\n if (handler) {\n return {\n handler,\n args: [...args.slice(0, index), ...args.slice(index + 1)],\n };\n }\n\n if (OPTIONS_WITH_VALUES.has(arg) && index + 1 < args.length) {\n index++;\n }\n }\n\n return null;\n}\n\nmain().catch((err: unknown) => {\n console.error(err);\n process.exit(1);\n});\n"],
5
+ "mappings": "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",
6
+ "names": ["mkdir", "writeFile", "dirname", "join", "readdir", "homedir", "join", "asRecord", "usage", "readdir", "readFile", "stat", "homedir", "join", "extractText", "createReadStream", "readdir", "stat", "createInterface", "homedir", "join", "extractText", "asRecord", "stringValue", "usage", "numberValue", "existsSync", "readdir", "homedir", "join", "usage", "stringValue", "asRecord", "numberValue", "extractTimestamp", "existsSync", "homedir", "join", "numberValue", "stringValue", "createReadStream", "readdir", "stat", "createInterface", "homedir", "join", "contentToString", "usage", "asRecord", "numberValue", "stringValue", "existsSync", "homedir", "join", "queryUserMessages", "queryUsageRecords", "stringValue", "uniqueStrings", "asRecord", "usage", "hasBillableUsage", "readdir", "readFile", "existsSync", "homedir", "join", "base", "c", "readFile", "homedir", "join", "asRecord", "numberValue", "join", "dirname", "mkdir", "writeFile"]
7
7
  }