@burn0/burn0 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -465,13 +465,16 @@ function createDispatcher(mode2, deps) {
465
465
  break;
466
466
  case "dev-cloud":
467
467
  deps.logEvent?.(event);
468
+ deps.writeLedger?.(event);
468
469
  deps.addToBatch?.(event);
469
470
  break;
470
471
  case "prod-cloud":
472
+ deps.logEvent?.(event);
473
+ deps.writeLedger?.(event);
471
474
  deps.addToBatch?.(event);
472
475
  break;
473
476
  case "prod-local":
474
- deps.accumulate?.(event);
477
+ deps.logEvent?.(event);
475
478
  break;
476
479
  case "test-enabled":
477
480
  deps.logEvent?.(event);
@@ -702,114 +705,114 @@ function estimateLocalCost(event) {
702
705
  }
703
706
 
704
707
  // src/transport/logger.ts
705
- var DIM = "\x1B[2m";
706
708
  var RESET = "\x1B[0m";
707
- var CYAN = "\x1B[36m";
708
709
  var GREEN = "\x1B[32m";
709
- var YELLOW = "\x1B[33m";
710
- var WHITE = "\x1B[37m";
711
710
  var BOLD = "\x1B[1m";
712
711
  var ORANGE = "\x1B[38;2;250;93;25m";
713
712
  var GRAY = "\x1B[90m";
714
- var headerPrinted = false;
715
- var sessionTotal = 0;
716
- var eventCount = 0;
717
- function formatTokens(count) {
718
- if (count >= 1e6) return `${(count / 1e6).toFixed(1)}M`;
719
- if (count >= 1e3) return `${(count / 1e3).toFixed(1)}K`;
720
- return count.toString();
721
- }
722
713
  function formatCost(cost) {
723
714
  if (cost >= 1) return `$${cost.toFixed(2)}`;
724
715
  if (cost >= 0.01) return `$${cost.toFixed(4)}`;
725
716
  return `$${cost.toFixed(6)}`;
726
717
  }
727
- function formatCostEstimate(estimate) {
728
- switch (estimate.type) {
729
- case "priced":
730
- return `${GREEN}${formatCost(estimate.cost)}${RESET}`;
731
- case "free":
732
- return `${GRAY}free${RESET}`;
733
- case "no-tokens":
734
- return `${YELLOW}no usage${RESET}`;
735
- case "fixed-tier":
736
- return `${YELLOW}plan?${RESET}`;
737
- case "unknown":
738
- return `${GRAY}untracked${RESET}`;
739
- case "loading":
740
- return `${GRAY}...${RESET}`;
741
- }
742
- }
743
- function printHeader() {
744
- if (headerPrinted) return;
745
- headerPrinted = true;
746
- process.stdout.write(`
747
- `);
748
- process.stdout.write(` ${ORANGE}${BOLD} burn0 ${RESET} ${DIM}live cost tracking${RESET}
749
- `);
750
- process.stdout.write(`
751
- `);
752
- process.stdout.write(` ${GRAY}SERVICE ENDPOINT / MODEL USAGE COST${RESET}
753
- `);
754
- process.stdout.write(` ${GRAY}${"\u2500".repeat(68)}${RESET}
755
- `);
756
- }
757
- function printSessionTotal() {
758
- process.stdout.write(` ${GRAY}${"\u2500".repeat(68)}${RESET}
759
- `);
760
- if (sessionTotal > 0) {
761
- process.stdout.write(` ${GRAY}${eventCount} calls${RESET} ${ORANGE}${BOLD}${formatCost(sessionTotal)}${RESET}
762
- `);
763
- } else {
764
- process.stdout.write(` ${GRAY}${eventCount} calls${RESET} ${GRAY}$0${RESET}
765
- `);
766
- }
767
- process.stdout.write(` ${GRAY}${"\u2500".repeat(68)}${RESET}
768
- `);
769
- }
770
- function formatEventLine(event) {
771
- const service = event.service.length > 15 ? event.service.substring(0, 14) + "." : event.service;
772
- const modelOrEndpoint = event.model ? event.model.length > 29 ? event.model.substring(0, 28) + "." : event.model : event.endpoint.length > 29 ? event.endpoint.substring(0, 28) + "." : event.endpoint;
773
- let usage = "";
774
- if (event.tokens_in !== void 0 && event.tokens_out !== void 0) {
775
- usage = `${formatTokens(event.tokens_in)} \u2192 ${formatTokens(event.tokens_out)}`;
776
- }
777
- const estimate = estimateLocalCost(event);
778
- const costStr = formatCostEstimate(estimate);
779
- return ` ${CYAN}${service.padEnd(16)}${RESET} ${WHITE}${modelOrEndpoint.padEnd(30)}${RESET}${GRAY}${usage.padEnd(15)}${RESET}${costStr}`;
780
- }
781
- function formatProcessSummary(events, uptimeSeconds) {
782
- const services = {};
783
- for (const event of events) {
784
- if (!services[event.service]) services[event.service] = { calls: 0 };
785
- services[event.service].calls++;
786
- if (event.tokens_in !== void 0) services[event.service].tokens_in = (services[event.service].tokens_in ?? 0) + event.tokens_in;
787
- if (event.tokens_out !== void 0) services[event.service].tokens_out = (services[event.service].tokens_out ?? 0) + event.tokens_out;
788
- }
789
- for (const svc of Object.values(services)) {
790
- if (svc.tokens_in === void 0) delete svc.tokens_in;
791
- if (svc.tokens_out === void 0) delete svc.tokens_out;
792
- }
793
- return JSON.stringify({
794
- burn0: "process-summary",
795
- uptime_hours: +(uptimeSeconds / 3600).toFixed(1),
796
- total_calls: events.length,
797
- services,
798
- message: "Add BURN0_API_KEY to see cost breakdowns \u2192 burn0.dev"
799
- });
800
- }
801
- function logEvent(event) {
802
- printHeader();
803
- const estimate = estimateLocalCost(event);
804
- if (estimate.type === "priced" && estimate.cost > 0) {
805
- sessionTotal += estimate.cost;
806
- }
807
- eventCount++;
808
- process.stdout.write(`${formatEventLine(event)}
809
- `);
810
- if (eventCount % 5 === 0) {
811
- printSessionTotal();
718
+ function formatDuration(ms) {
719
+ const seconds = Math.floor(ms / 1e3);
720
+ if (seconds < 60) return `${seconds}s`;
721
+ const minutes = Math.floor(seconds / 60);
722
+ const remainingSeconds = seconds % 60;
723
+ if (minutes < 60) return `${minutes}m ${remainingSeconds}s`;
724
+ const hours = Math.floor(minutes / 60);
725
+ const remainingMinutes = minutes % 60;
726
+ return `${hours}h ${remainingMinutes}m`;
727
+ }
728
+ function formatServiceBreakdown(perServiceCosts2, maxWidth) {
729
+ const sorted = Object.entries(perServiceCosts2).filter(([, cost]) => cost > 0).sort((a, b) => b[1] - a[1]);
730
+ if (sorted.length === 0) return "";
731
+ const parts = [];
732
+ let currentWidth = 0;
733
+ let shown = 0;
734
+ for (let i = 0; i < sorted.length && shown < 3; i++) {
735
+ const [name, cost] = sorted[i];
736
+ const part = `${name}: ${formatCost(cost)}`;
737
+ if (currentWidth + part.length + 3 > maxWidth && shown > 0) {
738
+ break;
739
+ }
740
+ parts.push(part);
741
+ currentWidth += part.length + 3;
742
+ shown++;
743
+ }
744
+ const remaining = sorted.length - shown;
745
+ if (remaining > 0) {
746
+ parts.push(`+${remaining} more`);
747
+ }
748
+ return parts.join(" \xB7 ");
749
+ }
750
+ function createTicker(init) {
751
+ let sessionCost = 0;
752
+ let sessionCalls = 0;
753
+ const sessionStartTime = Date.now();
754
+ let todayCost2 = init.todayCost;
755
+ let todayCalls2 = init.todayCalls;
756
+ const perServiceCosts2 = { ...init.perServiceCosts };
757
+ let exitPrinted = false;
758
+ let pricedCalls = 0;
759
+ let lastLineLen = 0;
760
+ function render() {
761
+ if (!process.stderr.isTTY) return;
762
+ if (todayCalls2 === 0) return;
763
+ let content;
764
+ if (pricedCalls === 0 && todayCost2 === 0) {
765
+ content = ` burn0 \u25B8 ${todayCalls2} calls today`;
766
+ } else {
767
+ const breakdown = formatServiceBreakdown(perServiceCosts2, 40);
768
+ const breakdownPart = breakdown ? ` \u2500\u2500 ${breakdown}` : "";
769
+ content = ` burn0 \u25B8 ${formatCost(todayCost2)} today (${todayCalls2} calls)${breakdownPart}`;
770
+ }
771
+ const pad = lastLineLen > content.length ? " ".repeat(lastLineLen - content.length) : "";
772
+ lastLineLen = content.length;
773
+ let colored;
774
+ if (pricedCalls === 0 && todayCost2 === 0) {
775
+ colored = ` ${ORANGE}${BOLD}burn0 \u25B8${RESET} ${GRAY}${todayCalls2} calls today${RESET}`;
776
+ } else {
777
+ const breakdown = formatServiceBreakdown(perServiceCosts2, 40);
778
+ const breakdownPart = breakdown ? ` ${GRAY}\u2500\u2500${RESET} ${breakdown}` : "";
779
+ colored = ` ${ORANGE}${BOLD}burn0 \u25B8${RESET} ${GREEN}${formatCost(todayCost2)}${RESET} ${GRAY}today (${todayCalls2} calls)${RESET}${breakdownPart}`;
780
+ }
781
+ process.stderr.write(`\r${colored}${pad}`);
782
+ }
783
+ function tick(event) {
784
+ const estimate = estimateLocalCost(event);
785
+ todayCalls2++;
786
+ sessionCalls++;
787
+ if (estimate.type === "priced" && estimate.cost > 0) {
788
+ todayCost2 += estimate.cost;
789
+ sessionCost += estimate.cost;
790
+ pricedCalls++;
791
+ perServiceCosts2[event.service] = (perServiceCosts2[event.service] ?? 0) + estimate.cost;
792
+ }
793
+ render();
794
+ }
795
+ function printExitSummary() {
796
+ if (!process.stderr.isTTY) return;
797
+ if (sessionCalls === 0) return;
798
+ if (exitPrinted) return;
799
+ exitPrinted = true;
800
+ const duration = formatDuration(Date.now() - sessionStartTime);
801
+ let line;
802
+ if (pricedCalls === 0 && sessionCost === 0) {
803
+ line = `
804
+ ${ORANGE}${BOLD}burn0 \u25B8${RESET} ${GRAY}session: ${sessionCalls} calls (${duration})${RESET} ${GRAY}\u2500\u2500${RESET} ${GRAY}today: ${todayCalls2} calls${RESET}
805
+ `;
806
+ } else {
807
+ const monthlyEst = todayCost2 > 0 ? formatCost(todayCost2 * 30) : null;
808
+ const projPart = monthlyEst ? ` ${GRAY}\u2500\u2500${RESET} ${GRAY}~${GREEN}${monthlyEst}${RESET}${GRAY}/mo${RESET}` : "";
809
+ line = `
810
+ ${ORANGE}${BOLD}burn0 \u25B8${RESET} ${GRAY}session:${RESET} ${GREEN}${formatCost(sessionCost)}${RESET} ${GRAY}(${sessionCalls} calls, ${duration})${RESET} ${GRAY}\u2500\u2500${RESET} ${GRAY}today:${RESET} ${GREEN}${formatCost(todayCost2)}${RESET}${projPart}
811
+ `;
812
+ }
813
+ process.stderr.write(line);
812
814
  }
815
+ return { tick, printExitSummary };
813
816
  }
814
817
 
815
818
  // src/index.ts
@@ -818,12 +821,36 @@ var apiKey = getApiKey();
818
821
  var mode = detectMode({ isTTY: isTTY(), apiKey });
819
822
  var { track, startSpan, enrichEvent } = createTracker();
820
823
  var originalFetch2 = globalThis.fetch;
821
- if (mode !== "test-disabled") {
824
+ if (mode !== "test-disabled" && mode !== "prod-local") {
822
825
  fetchPricing(BURN0_API_URL, originalFetch2).catch(() => {
823
826
  });
824
827
  }
825
- var accumulatedEvents = [];
826
- var ledger = mode === "dev-local" || mode === "test-enabled" ? new LocalLedger(process.cwd()) : null;
828
+ var ledger = new LocalLedger(process.cwd());
829
+ function getTodayDateStr() {
830
+ const d = /* @__PURE__ */ new Date();
831
+ return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}-${String(d.getDate()).padStart(2, "0")}`;
832
+ }
833
+ var todayCost = 0;
834
+ var todayCalls = 0;
835
+ var perServiceCosts = {};
836
+ try {
837
+ const todayStr = getTodayDateStr();
838
+ const allEvents = ledger.read();
839
+ for (const event of allEvents) {
840
+ const eventDate = new Date(event.timestamp);
841
+ const eventDateStr = `${eventDate.getFullYear()}-${String(eventDate.getMonth() + 1).padStart(2, "0")}-${String(eventDate.getDate()).padStart(2, "0")}`;
842
+ if (eventDateStr === todayStr) {
843
+ todayCalls++;
844
+ const estimate = estimateLocalCost(event);
845
+ if (estimate.type === "priced" && estimate.cost > 0) {
846
+ todayCost += estimate.cost;
847
+ perServiceCosts[event.service] = (perServiceCosts[event.service] ?? 0) + estimate.cost;
848
+ }
849
+ }
850
+ }
851
+ } catch {
852
+ }
853
+ var ticker = createTicker({ todayCost, todayCalls, perServiceCosts });
827
854
  var batch = null;
828
855
  if ((mode === "dev-cloud" || mode === "prod-cloud") && apiKey) {
829
856
  batch = new BatchBuffer({
@@ -836,17 +863,20 @@ if ((mode === "dev-cloud" || mode === "prod-cloud") && apiKey) {
836
863
  }
837
864
  });
838
865
  }
866
+ var shouldWriteLedger = mode !== "test-disabled" && mode !== "prod-local";
839
867
  var dispatch = createDispatcher(mode, {
840
- logEvent,
841
- writeLedger: ledger ? (e) => ledger.write(e) : void 0,
842
- addToBatch: batch ? (e) => batch.add(e) : void 0,
843
- accumulate: (e) => accumulatedEvents.push(e)
868
+ logEvent: (e) => ticker.tick(e),
869
+ writeLedger: shouldWriteLedger ? (e) => ledger.write(e) : void 0,
870
+ addToBatch: batch ? (e) => batch.add(e) : void 0
844
871
  });
845
872
  var preloaded = checkImportOrder();
846
873
  if (preloaded.length > 0) {
847
- console.warn(`[burn0] Warning: These SDKs were imported before burn0 and may not be tracked: ${preloaded.join(", ")}. Move \`import 'burn0'\` to the top of your entry file.`);
874
+ console.warn(`[burn0] Warning: These SDKs were imported before burn0 and may not be tracked: ${preloaded.join(", ")}. Move \`import '@burn0/burn0'\` to the top of your entry file.`);
848
875
  }
849
- if (canPatch() && mode !== "test-disabled") {
876
+ if (mode === "prod-local") {
877
+ console.warn("[burn0] No API key \u2014 costs not tracked. Get one free at burn0.dev/api");
878
+ }
879
+ if (canPatch() && mode !== "test-disabled" && mode !== "prod-local") {
850
880
  const onEvent = (event) => {
851
881
  const enriched = enrichEvent(event);
852
882
  dispatch(enriched);
@@ -855,25 +885,16 @@ if (canPatch() && mode !== "test-disabled") {
855
885
  patchHttp(onEvent);
856
886
  markPatched();
857
887
  }
858
- if (mode === "prod-local") {
859
- const startTime = Date.now();
860
- process.on("beforeExit", () => {
861
- if (accumulatedEvents.length > 0) {
862
- const uptimeSeconds = (Date.now() - startTime) / 1e3;
863
- console.log(formatProcessSummary(accumulatedEvents, uptimeSeconds));
864
- }
865
- });
866
- }
867
- if (batch) {
868
- const exitFlush = () => {
888
+ var exitHandled = false;
889
+ process.on("exit", () => {
890
+ if (exitHandled) return;
891
+ exitHandled = true;
892
+ if (batch) {
869
893
  batch.flush();
870
894
  batch.destroy();
871
- };
872
- process.on("beforeExit", exitFlush);
873
- process.on("SIGTERM", exitFlush);
874
- process.on("SIGINT", exitFlush);
875
- process.on("SIGHUP", exitFlush);
876
- }
895
+ }
896
+ ticker.printExitSummary();
897
+ });
877
898
  var restore = createRestorer({ unpatchFetch, unpatchHttp, resetGuard });
878
899
  // Annotate the CommonJS export names for ESM import in node:
879
900
  0 && (module.exports = {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/config/env.ts","../src/interceptor/guard.ts","../src/services/map.ts","../src/types.ts","../src/interceptor/stream.ts","../src/interceptor/fetch.ts","../src/interceptor/http.ts","../src/track.ts","../src/restore.ts","../src/transport/dispatcher.ts","../src/transport/batch.ts","../src/transport/local.ts","../src/transport/api.ts","../src/transport/local-pricing.ts","../src/transport/logger.ts"],"sourcesContent":["import { getApiKey, detectMode, isTTY } from './config/env'\nimport { canPatch, markPatched, resetGuard, checkImportOrder } from './interceptor/guard'\nimport { patchFetch, unpatchFetch } from './interceptor/fetch'\nimport { patchHttp, unpatchHttp } from './interceptor/http'\nimport { createTracker } from './track'\nimport { createRestorer } from './restore'\nimport { createDispatcher } from './transport/dispatcher'\nimport { BatchBuffer } from './transport/batch'\nimport { LocalLedger } from './transport/local'\nimport { shipEvents } from './transport/api'\nimport { logEvent, formatProcessSummary } from './transport/logger'\nimport { fetchPricing } from './transport/local-pricing'\nimport type { Burn0Event } from './types'\n\nconst BURN0_API_URL = process.env.BURN0_API_URL ?? 'https://api.burn0.dev'\n\nconst apiKey = getApiKey()\nconst mode = detectMode({ isTTY: isTTY(), apiKey })\n\nconst { track, startSpan, enrichEvent } = createTracker()\n\n// Store original fetch before patching (for API shipper and pricing fetch)\nconst originalFetch = globalThis.fetch\n\n// Fetch pricing data from backend (non-blocking, uses original fetch)\nif (mode !== 'test-disabled') {\n fetchPricing(BURN0_API_URL, originalFetch).catch(() => {})\n}\n\nconst accumulatedEvents: Burn0Event[] = []\n\nconst ledger = (mode === 'dev-local' || mode === 'test-enabled')\n ? new LocalLedger(process.cwd())\n : null\n\nlet batch: BatchBuffer | null = null\nif ((mode === 'dev-cloud' || mode === 'prod-cloud') && apiKey) {\n batch = new BatchBuffer({\n sizeThreshold: 50,\n timeThresholdMs: 10000,\n maxSize: 500,\n onFlush: (events) => {\n shipEvents(events, apiKey, BURN0_API_URL, originalFetch).catch(() => {})\n },\n })\n}\n\nconst dispatch = createDispatcher(mode, {\n logEvent,\n writeLedger: ledger ? (e) => ledger.write(e) : undefined,\n addToBatch: batch ? (e) => batch!.add(e) : undefined,\n accumulate: (e) => accumulatedEvents.push(e),\n})\n\nconst preloaded = checkImportOrder()\nif (preloaded.length > 0) {\n console.warn(`[burn0] Warning: These SDKs were imported before burn0 and may not be tracked: ${preloaded.join(', ')}. Move \\`import 'burn0'\\` to the top of your entry file.`)\n}\n\nif (canPatch() && mode !== 'test-disabled') {\n const onEvent = (event: Burn0Event) => {\n const enriched = enrichEvent(event)\n dispatch(enriched)\n }\n patchFetch(onEvent)\n patchHttp(onEvent)\n markPatched()\n}\n\nif (mode === 'prod-local') {\n const startTime = Date.now()\n process.on('beforeExit', () => {\n if (accumulatedEvents.length > 0) {\n const uptimeSeconds = (Date.now() - startTime) / 1000\n console.log(formatProcessSummary(accumulatedEvents, uptimeSeconds))\n }\n })\n}\n\nif (batch) {\n const exitFlush = () => {\n batch!.flush()\n batch!.destroy()\n }\n process.on('beforeExit', exitFlush)\n process.on('SIGTERM', exitFlush)\n process.on('SIGINT', exitFlush)\n process.on('SIGHUP', exitFlush)\n}\n\nconst restore = createRestorer({ unpatchFetch, unpatchHttp, resetGuard })\n\nexport { track, startSpan, restore }\n","import type { RuntimeMode } from '../types'\n\nexport function getApiKey(): string | undefined {\n const key = process.env.BURN0_API_KEY\n return key && key.length > 0 ? key : undefined\n}\n\nexport function detectMode(opts: { isTTY: boolean; apiKey: string | undefined }): RuntimeMode {\n const isTest = process.env.NODE_ENV === 'test'\n if (isTest) {\n return process.env.BURN0_ENABLE_TEST === '1' ? 'test-enabled' : 'test-disabled'\n }\n if (opts.apiKey) {\n return opts.isTTY ? 'dev-cloud' : 'prod-cloud'\n }\n return opts.isTTY ? 'dev-local' : 'prod-local'\n}\n\nexport function isTTY(): boolean {\n return Boolean(process.stdout.isTTY)\n}\n\nexport function isDebug(): boolean {\n return process.env.BURN0_DEBUG === '1' || process.env.BURN0_DEBUG === 'true'\n}\n","let patched = false\n\nexport function canPatch(): boolean {\n return !patched\n}\n\nexport function markPatched(): void {\n patched = true\n}\n\nexport function resetGuard(): void {\n patched = false\n}\n\nconst KNOWN_SDK_MODULES = [\n 'openai', '@anthropic-ai/sdk', '@google/generative-ai',\n '@mistralai/mistralai', 'cohere-ai', 'stripe',\n '@sendgrid/mail', 'twilio', 'resend', '@supabase/supabase-js',\n]\n\nexport function checkImportOrder(): string[] {\n const preloaded: string[] = []\n if (typeof require !== 'undefined' && require.cache) {\n for (const sdk of KNOWN_SDK_MODULES) {\n if (Object.keys(require.cache).some(k => k.includes(`/node_modules/${sdk}/`))) {\n preloaded.push(sdk)\n }\n }\n }\n return preloaded\n}\n","const BUILT_IN_MAP: Record<string, string> = {\n // LLMs\n 'api.openai.com': 'openai',\n 'api.anthropic.com': 'anthropic',\n 'generativelanguage.googleapis.com': 'google-gemini',\n 'api.mistral.ai': 'mistral',\n 'api.cohere.com': 'cohere',\n 'api.groq.com': 'groq',\n 'api.together.xyz': 'together-ai',\n 'api.perplexity.ai': 'perplexity',\n 'api.fireworks.ai': 'fireworks-ai',\n 'api.deepseek.com': 'deepseek',\n 'api.replicate.com': 'replicate',\n 'api.ai21.com': 'ai21',\n // APIs\n 'api.stripe.com': 'stripe',\n 'api.paypal.com': 'paypal',\n 'api.sendgrid.com': 'sendgrid',\n 'api.resend.com': 'resend',\n 'api.postmarkapp.com': 'postmark',\n 'api.mailgun.net': 'mailgun',\n 'api.twilio.com': 'twilio',\n 'api.vonage.com': 'vonage',\n 'api.clerk.com': 'clerk',\n 'api.cloudinary.com': 'cloudinary',\n 'upload.uploadcare.com': 'uploadcare',\n 'maps.googleapis.com': 'google-maps',\n 'api.mapbox.com': 'mapbox',\n 'api.segment.io': 'segment',\n 'api.mixpanel.com': 'mixpanel',\n 'api.github.com': 'github-api',\n 'api.plaid.com': 'plaid',\n 'api.pinecone.io': 'pinecone',\n 'supabase.co': 'supabase',\n}\n\nconst IGNORED_PATTERNS = ['localhost', '127.0.0.1', '0.0.0.0', '[::1]']\n\nlet serviceMap: Record<string, string> = { ...BUILT_IN_MAP }\n\nexport function identifyService(hostname: string): string | null {\n if (IGNORED_PATTERNS.includes(hostname) || hostname.startsWith('localhost:')) {\n return null\n }\n\n // Exact match\n if (serviceMap[hostname]) return serviceMap[hostname]\n\n // Try suffix matching for subdomains (e.g., myproject.supabase.co → supabase.co)\n for (const [mapHost, service] of Object.entries(serviceMap)) {\n if (hostname.endsWith('.' + mapHost)) return service\n }\n\n return `unknown:${hostname}`\n}\n\nexport function mergeServiceMap(remote: Record<string, string>): void {\n serviceMap = { ...serviceMap, ...remote }\n}\n\nexport function resetServiceMap(): void {\n serviceMap = { ...BUILT_IN_MAP }\n}\n","export interface Burn0Event {\n schema_version: number\n service: string\n endpoint: string\n model?: string\n tokens_in?: number\n tokens_out?: number\n status_code: number\n timestamp: string\n duration_ms: number\n estimated: boolean\n feature?: string\n metadata?: Record<string, string | number | boolean>\n}\n\nexport type RuntimeMode =\n | 'dev-cloud'\n | 'dev-local'\n | 'prod-cloud'\n | 'prod-local'\n | 'test-disabled'\n | 'test-enabled'\n\nexport interface Burn0Config {\n projectName?: string\n services?: ServiceConfig[]\n}\n\nexport interface ServiceConfig {\n name: string\n pricingModel: 'auto' | 'fixed-tier'\n plan?: string\n monthlyCost?: number\n}\n\nexport interface Span {\n end: () => void\n}\n\nexport const SCHEMA_VERSION = 1\n","export function teeReadableStream(\n stream: ReadableStream<Uint8Array>\n): [ReadableStream<Uint8Array>, ReadableStream<Uint8Array>] {\n return stream.tee() as [ReadableStream<Uint8Array>, ReadableStream<Uint8Array>]\n}\n\ninterface Usage {\n prompt_tokens?: number\n completion_tokens?: number\n input_tokens?: number\n output_tokens?: number\n}\n\nexport function extractUsageFromSSE(raw: string): Usage | null {\n const lines = raw.split('\\n')\n for (let i = lines.length - 1; i >= 0; i--) {\n const line = lines[i]\n if (!line.startsWith('data: ') || line === 'data: [DONE]') continue\n try {\n const parsed = JSON.parse(line.slice(6))\n if (parsed.usage) return parsed.usage\n } catch {}\n }\n return null\n}\n\nexport async function collectStream(stream: ReadableStream<Uint8Array>, timeoutMs = 30000): Promise<string> {\n const reader = stream.getReader()\n const chunks: string[] = []\n const decoder = new TextDecoder()\n\n const timeout = new Promise<never>((_, reject) => {\n setTimeout(() => reject(new Error('stream timeout')), timeoutMs)\n })\n\n try {\n while (true) {\n const result = await Promise.race([reader.read(), timeout]) as ReadableStreamReadResult<Uint8Array>\n if (result.done) break\n chunks.push(decoder.decode(result.value, { stream: true }))\n }\n } catch {\n // Timeout or error — return what we have\n } finally {\n try { reader.releaseLock() } catch {}\n }\n\n return chunks.join('')\n}\n","import { identifyService } from '../services/map'\nimport type { Burn0Event } from '../types'\nimport { SCHEMA_VERSION } from '../types'\nimport { teeReadableStream, collectStream, extractUsageFromSSE } from './stream'\n\ntype EventCallback = (event: Burn0Event) => void\nlet originalFetch: typeof globalThis.fetch | null = null\n\nexport function patchFetch(onEvent: EventCallback): void {\n originalFetch = globalThis.fetch\n\n globalThis.fetch = async function burn0Fetch(\n input: RequestInfo | URL,\n init?: RequestInit\n ): Promise<Response> {\n const startTime = Date.now()\n const url = new URL(typeof input === 'string' ? input : input instanceof URL ? input.href : input.url)\n const hostname = url.hostname\n const service = identifyService(hostname)\n\n if (!service) {\n return originalFetch!(input, init)\n }\n\n let model: string | undefined\n\n // Extract model from request body (OpenAI, Anthropic, etc.)\n if (init?.body && typeof init.body === 'string') {\n try {\n const parsed = JSON.parse(init.body)\n if (parsed.model) model = parsed.model\n } catch {}\n }\n\n // Extract model from URL path (Gemini-style: /v1beta/models/gemini-2.0-flash:generateContent)\n if (!model) {\n const modelMatch = url.pathname.match(/\\/models\\/([^/:]+)/)\n if (modelMatch) model = modelMatch[1]\n }\n\n const response = await originalFetch!(input, init)\n const duration = Date.now() - startTime\n\n let tokensIn: number | undefined\n let tokensOut: number | undefined\n\n // Check for SSE streaming response\n if (response.headers.get('content-type')?.includes('text/event-stream') && response.body) {\n const [forCaller, forBurn0] = teeReadableStream(response.body)\n\n collectStream(forBurn0).then((raw) => {\n const usage = extractUsageFromSSE(raw)\n let sseTokensIn = usage?.prompt_tokens ?? usage?.input_tokens\n let sseTokensOut = usage?.completion_tokens ?? usage?.output_tokens\n if (sseTokensIn !== undefined && sseTokensIn < 0) sseTokensIn = undefined\n if (sseTokensOut !== undefined && sseTokensOut < 0) sseTokensOut = undefined\n const sseEvent: Burn0Event = {\n schema_version: SCHEMA_VERSION,\n service,\n endpoint: url.pathname,\n model,\n tokens_in: sseTokensIn,\n tokens_out: sseTokensOut,\n status_code: response.status,\n timestamp: new Date().toISOString(),\n duration_ms: duration,\n estimated: !usage,\n }\n try { onEvent(sseEvent) } catch {}\n }).catch(() => {\n const sseEvent: Burn0Event = {\n schema_version: SCHEMA_VERSION,\n service,\n endpoint: url.pathname,\n model,\n status_code: response.status,\n timestamp: new Date().toISOString(),\n duration_ms: duration,\n estimated: true,\n }\n try { onEvent(sseEvent) } catch {}\n })\n\n return new Response(forCaller, {\n status: response.status,\n statusText: response.statusText,\n headers: response.headers,\n })\n }\n\n if (response.headers.get('content-type')?.includes('application/json')) {\n try {\n const cloned = response.clone()\n const body = await cloned.json()\n // Standard format (OpenAI, Anthropic, Perplexity)\n if (body.usage) {\n tokensIn = body.usage.prompt_tokens ?? body.usage.input_tokens\n tokensOut = body.usage.completion_tokens ?? body.usage.output_tokens\n }\n // Gemini format\n if (body.usageMetadata) {\n tokensIn = body.usageMetadata.promptTokenCount\n tokensOut = body.usageMetadata.candidatesTokenCount\n }\n if (body.model) model = body.model\n } catch {}\n }\n\n if (tokensIn !== undefined && tokensIn < 0) tokensIn = undefined\n if (tokensOut !== undefined && tokensOut < 0) tokensOut = undefined\n\n const event: Burn0Event = {\n schema_version: SCHEMA_VERSION,\n service,\n endpoint: url.pathname,\n model,\n tokens_in: tokensIn,\n tokens_out: tokensOut,\n status_code: response.status,\n timestamp: new Date().toISOString(),\n duration_ms: duration,\n estimated: false,\n }\n\n try { onEvent(event) } catch {}\n return response\n }\n}\n\nexport function unpatchFetch(): void {\n if (originalFetch) {\n globalThis.fetch = originalFetch\n originalFetch = null\n }\n}\n","import http from 'node:http'\nimport https from 'node:https'\nimport { identifyService } from '../services/map'\nimport type { Burn0Event } from '../types'\nimport { SCHEMA_VERSION } from '../types'\n\ntype EventCallback = (event: Burn0Event) => void\n\nlet originalHttpRequest: typeof http.request | null = null\nlet originalHttpsRequest: typeof https.request | null = null\nlet originalHttpGet: typeof http.get | null = null\nlet originalHttpsGet: typeof https.get | null = null\n\nfunction wrapRequest(original: typeof http.request, onEvent: EventCallback): typeof http.request {\n return function burn0Request(this: unknown, ...args: Parameters<typeof http.request>): http.ClientRequest {\n const req = original.apply(this, args)\n const startTime = Date.now()\n\n const firstArg = args[0]\n let hostname = ''\n let endpoint = '/'\n\n if (typeof firstArg === 'string') {\n try {\n const parsed = new URL(firstArg)\n hostname = parsed.hostname\n endpoint = parsed.pathname\n } catch {}\n } else if (firstArg instanceof URL) {\n hostname = firstArg.hostname\n endpoint = firstArg.pathname\n } else if (firstArg && typeof firstArg === 'object') {\n hostname = (firstArg as http.RequestOptions).hostname ?? (firstArg as http.RequestOptions).host ?? ''\n endpoint = (firstArg as http.RequestOptions).path ?? '/'\n }\n\n const cleanHostname = hostname.replace(/:\\d+$/, '')\n const service = identifyService(cleanHostname)\n\n if (!service) return req\n\n req.on('response', (res: http.IncomingMessage) => {\n const isJson = res.headers['content-type']?.includes('application/json')\n const chunks: Buffer[] = []\n const MAX_RESPONSE_SIZE = 5 * 1024 * 1024 // 5MB\n let totalSize = 0\n let tooLarge = false\n\n if (isJson) {\n res.on('data', (chunk: Buffer) => {\n totalSize += chunk.length\n if (totalSize > MAX_RESPONSE_SIZE) {\n tooLarge = true\n return\n }\n chunks.push(chunk)\n })\n }\n res.on('end', () => {\n const duration = Date.now() - startTime\n let tokensIn: number | undefined\n let tokensOut: number | undefined\n let model: string | undefined\n\n if (isJson && chunks.length > 0 && !tooLarge) {\n try {\n const body = JSON.parse(Buffer.concat(chunks).toString())\n if (body.usage) {\n tokensIn = body.usage.prompt_tokens ?? body.usage.input_tokens\n tokensOut = body.usage.completion_tokens ?? body.usage.output_tokens\n }\n if (body.model) model = body.model\n } catch {}\n }\n\n if (tokensIn !== undefined && tokensIn < 0) tokensIn = undefined\n if (tokensOut !== undefined && tokensOut < 0) tokensOut = undefined\n\n const event: Burn0Event = {\n schema_version: SCHEMA_VERSION,\n service,\n endpoint: endpoint.toString(),\n model,\n tokens_in: tokensIn,\n tokens_out: tokensOut,\n status_code: res.statusCode ?? 0,\n timestamp: new Date().toISOString(),\n duration_ms: duration,\n estimated: false,\n }\n try { onEvent(event) } catch {}\n })\n })\n return req\n } as typeof http.request\n}\n\nexport function patchHttp(onEvent: EventCallback): void {\n originalHttpRequest = http.request\n originalHttpsRequest = https.request\n originalHttpGet = http.get\n originalHttpsGet = https.get\n http.request = wrapRequest(originalHttpRequest, onEvent)\n https.request = wrapRequest(originalHttpsRequest as unknown as typeof http.request, onEvent) as unknown as typeof https.request\n http.get = wrapRequest(originalHttpGet as typeof http.request, onEvent) as typeof http.get\n https.get = wrapRequest(originalHttpsGet as unknown as typeof http.request, onEvent) as unknown as typeof https.get\n}\n\nexport function unpatchHttp(): void {\n if (originalHttpRequest) { http.request = originalHttpRequest; originalHttpRequest = null }\n if (originalHttpsRequest) { https.request = originalHttpsRequest; originalHttpsRequest = null }\n if (originalHttpGet) { http.get = originalHttpGet; originalHttpGet = null }\n if (originalHttpsGet) { https.get = originalHttpsGet; originalHttpsGet = null }\n}\n","import { AsyncLocalStorage } from 'node:async_hooks'\nimport type { Burn0Event, Span } from './types'\n\ninterface TrackContext {\n feature: string\n metadata?: Record<string, string | number | boolean>\n}\n\nconst storage = new AsyncLocalStorage<TrackContext>()\nlet activeSpan: TrackContext | null = null\n\nexport function createTracker() {\n async function track(\n feature: string,\n metadata: Record<string, string | number | boolean>,\n fn: () => Promise<void>\n ): Promise<void> {\n await storage.run({ feature, metadata }, fn)\n }\n\n function startSpan(\n feature: string,\n metadata?: Record<string, string | number | boolean>\n ): Span {\n activeSpan = { feature, metadata }\n return {\n end() { activeSpan = null },\n }\n }\n\n function enrichEvent(event: Burn0Event): Burn0Event {\n const ctx = storage.getStore() ?? activeSpan\n if (!ctx) return event\n return {\n ...event,\n feature: ctx.feature,\n metadata: ctx.metadata && Object.keys(ctx.metadata).length > 0 ? ctx.metadata : undefined,\n }\n }\n\n return { track, startSpan, enrichEvent }\n}\n","interface RestoreDeps {\n unpatchFetch: () => void\n unpatchHttp: () => void\n resetGuard: () => void\n}\n\nexport function createRestorer(deps: RestoreDeps): () => void {\n return () => {\n deps.unpatchFetch()\n deps.unpatchHttp()\n deps.resetGuard()\n }\n}\n","import type { Burn0Event, RuntimeMode } from '../types'\n\ninterface DispatcherDeps {\n logEvent?: (event: Burn0Event) => void\n writeLedger?: (event: Burn0Event) => void\n addToBatch?: (event: Burn0Event) => void\n accumulate?: (event: Burn0Event) => void\n}\n\nexport function createDispatcher(mode: RuntimeMode, deps: DispatcherDeps): (event: Burn0Event) => void {\n return (event: Burn0Event) => {\n switch (mode) {\n case 'dev-local':\n deps.logEvent?.(event); deps.writeLedger?.(event); break\n case 'dev-cloud':\n deps.logEvent?.(event); deps.addToBatch?.(event); break\n case 'prod-cloud':\n deps.addToBatch?.(event); break\n case 'prod-local':\n deps.accumulate?.(event); break\n case 'test-enabled':\n deps.logEvent?.(event); deps.writeLedger?.(event); deps.addToBatch?.(event); break\n case 'test-disabled':\n break\n }\n }\n}\n","import type { Burn0Event } from '../types'\n\nexport interface BatchBufferOptions {\n sizeThreshold: number\n timeThresholdMs: number\n maxSize: number\n onFlush: (events: Burn0Event[]) => void\n}\n\nexport class BatchBuffer {\n private events: Burn0Event[] = []\n private timer: ReturnType<typeof setInterval> | null = null\n private options: BatchBufferOptions\n\n constructor(options: BatchBufferOptions) {\n this.options = options\n this.timer = setInterval(() => {\n if (this.events.length > 0) this.flush()\n }, options.timeThresholdMs)\n if (this.timer && typeof this.timer === 'object' && 'unref' in this.timer) {\n this.timer.unref()\n }\n }\n\n add(event: Burn0Event): void {\n this.events.push(event)\n if (this.events.length > this.options.maxSize) {\n this.events = this.events.slice(-this.options.maxSize)\n }\n if (this.events.length >= this.options.sizeThreshold) {\n this.flush()\n }\n }\n\n flush(): void {\n if (this.events.length === 0) return\n const batch = [...this.events]\n this.events = []\n this.options.onFlush(batch)\n }\n\n destroy(): void {\n if (this.timer) { clearInterval(this.timer); this.timer = null }\n }\n}\n","import fs from 'node:fs'\nimport path from 'node:path'\nimport type { Burn0Event } from '../types'\n\nconst BURN0_DIR = '.burn0'\nconst LEDGER_FILE = 'costs.jsonl'\nconst MAX_FILE_SIZE = 10 * 1024 * 1024\nconst MAX_AGE_MS = 7 * 24 * 60 * 60 * 1000\n\nexport class LocalLedger {\n private filePath: string\n private dirPath: string\n\n constructor(projectRoot: string) {\n this.dirPath = path.join(projectRoot, BURN0_DIR)\n this.filePath = path.join(this.dirPath, LEDGER_FILE)\n }\n\n write(event: Burn0Event): void {\n this.ensureDir()\n this.rotateIfNeeded()\n fs.appendFileSync(this.filePath, JSON.stringify(event) + '\\n')\n }\n\n read(): Burn0Event[] {\n try {\n const content = fs.readFileSync(this.filePath, 'utf-8').trim()\n if (!content) return []\n return content.split('\\n').map((line) => JSON.parse(line) as Burn0Event)\n } catch { return [] }\n }\n\n private ensureDir(): void {\n if (!fs.existsSync(this.dirPath)) fs.mkdirSync(this.dirPath, { recursive: true })\n }\n\n private rotateIfNeeded(): void {\n try {\n const stat = fs.statSync(this.filePath)\n if (stat.size > MAX_FILE_SIZE) { this.pruneOldEntries(); return }\n } catch { return }\n const events = this.read()\n if (events.length > 0) {\n const oldest = new Date(events[0].timestamp).getTime()\n if (Date.now() - oldest > MAX_AGE_MS) this.pruneOldEntries()\n }\n }\n\n private pruneOldEntries(): void {\n const cutoff = Date.now() - MAX_AGE_MS\n const events = this.read().filter(e => new Date(e.timestamp).getTime() > cutoff)\n const content = events.map(e => JSON.stringify(e)).join('\\n') + (events.length ? '\\n' : '')\n fs.writeFileSync(this.filePath, content)\n }\n}\n","import type { Burn0Event } from '../types'\nimport { isDebug } from '../config/env'\n\nconst SDK_VERSION = '0.1.0'\n\nexport async function shipEvents(\n events: Burn0Event[],\n apiKey: string,\n baseUrl: string,\n fetchFn: typeof globalThis.fetch = globalThis.fetch\n): Promise<boolean> {\n const maxAttempts = 3\n const baseDelayMs = 1000\n const maxDelayMs = 5000\n\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\n try {\n const response = await fetchFn(`${baseUrl}/v1/events`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${apiKey}`,\n 'X-Burn0-SDK-Version': SDK_VERSION,\n },\n body: JSON.stringify({ events, sdk_version: SDK_VERSION }),\n })\n if (response.ok) return true\n } catch (err) {\n if (isDebug()) {\n console.warn('[burn0] Event shipping failed:', (err as Error).message)\n }\n }\n\n if (attempt < maxAttempts - 1) {\n const delay = Math.min(baseDelayMs * Math.pow(2, attempt), maxDelayMs)\n await new Promise((resolve) => setTimeout(resolve, delay))\n }\n }\n\n return false\n}\n","/**\n * Pricing data for terminal display.\n * Fetched from the burn0 backend on startup, cached locally.\n * Falls back to \"no cost display\" if backend is unreachable.\n */\nimport fs from 'node:fs'\nimport path from 'node:path'\n\ninterface PricingData {\n version: number\n updated_at: string\n services: Record<string, any>\n}\n\nlet pricingData: PricingData | null = null\nconst CACHE_FILE = '.burn0/pricing-cache.json'\nconst CACHE_TTL_MS = 24 * 60 * 60 * 1000 // 24 hours\n\n// Free services — no API call cost\nconst FREE_SERVICES = new Set([\n 'github-api', 'slack-api', 'discord-api',\n])\n\nexport type CostEstimate =\n | { type: 'priced'; cost: number }\n | { type: 'free' }\n | { type: 'no-tokens' }\n | { type: 'fixed-tier' }\n | { type: 'unknown' }\n | { type: 'loading' } // pricing not fetched yet\n\n/**\n * Fetch pricing from backend and cache locally.\n * Non-blocking — called on init, doesn't delay the app.\n */\nexport async function fetchPricing(\n apiUrl: string,\n fetchFn: typeof globalThis.fetch\n): Promise<void> {\n // Try cache first\n try {\n const cachePath = path.join(process.cwd(), CACHE_FILE)\n if (fs.existsSync(cachePath)) {\n const raw = fs.readFileSync(cachePath, 'utf-8')\n const cached = JSON.parse(raw) as PricingData & { cached_at: number }\n if (Date.now() - cached.cached_at < CACHE_TTL_MS) {\n pricingData = cached\n return\n }\n }\n } catch {}\n\n // Fetch from backend\n try {\n const response = await fetchFn(`${apiUrl}/v1/pricing`, {\n headers: { 'Accept': 'application/json' },\n })\n if (response.ok) {\n const data = await response.json() as PricingData\n pricingData = data\n\n // Cache to disk\n try {\n const dir = path.join(process.cwd(), '.burn0')\n if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true })\n fs.writeFileSync(\n path.join(process.cwd(), CACHE_FILE),\n JSON.stringify({ ...data, cached_at: Date.now() }, null, 2)\n )\n } catch {}\n }\n } catch {}\n}\n\nexport function estimateLocalCost(event: {\n service: string\n model?: string\n tokens_in?: number\n tokens_out?: number\n endpoint?: string\n status_code?: number\n}): CostEstimate {\n // Free services\n if (FREE_SERVICES.has(event.service)) {\n return { type: 'free' }\n }\n\n // Unknown services\n if (event.service.startsWith('unknown:')) {\n return { type: 'unknown' }\n }\n\n // No pricing data loaded yet\n if (!pricingData) {\n return { type: 'loading' }\n }\n\n const svc = pricingData.services[event.service]\n if (!svc) {\n return { type: 'unknown' }\n }\n\n // LLM pricing\n if (svc.type === 'llm') {\n if (!event.model) return { type: 'unknown' }\n if (event.tokens_in === undefined || event.tokens_out === undefined) {\n return { type: 'no-tokens' }\n }\n\n // Try exact match, then prefix match\n let prices: [number, number] | undefined = svc.models[event.model]\n if (!prices) {\n const match = Object.keys(svc.models).find((m: string) => event.model!.startsWith(m))\n if (match) prices = svc.models[match]\n }\n if (prices) {\n const inputCost = (event.tokens_in / 1_000_000) * prices[0]\n const outputCost = (event.tokens_out / 1_000_000) * prices[1]\n return { type: 'priced', cost: inputCost + outputCost }\n }\n return { type: 'unknown' }\n }\n\n // API pricing with endpoint matching\n if (svc.type === 'api') {\n const endpoint = event.endpoint ?? ''\n // Try prefix match\n for (const [prefix, cost] of Object.entries(svc.endpoints)) {\n if (prefix !== '*' && endpoint.startsWith(prefix)) {\n return (cost as number) === 0 ? { type: 'free' } : { type: 'priced', cost: cost as number }\n }\n }\n // Fall back to default\n const defaultCost = svc.endpoints['*'] as number | undefined\n if (defaultCost !== undefined) {\n return defaultCost === 0 ? { type: 'free' } : { type: 'priced', cost: defaultCost }\n }\n return { type: 'unknown' }\n }\n\n // Fixed-tier services\n if (svc.type === 'fixed') {\n return { type: 'fixed-tier' }\n }\n\n return { type: 'unknown' }\n}\n","import type { Burn0Event } from '../types'\nimport { estimateLocalCost, type CostEstimate } from './local-pricing'\n\nconst DIM = '\\x1b[2m'\nconst RESET = '\\x1b[0m'\nconst CYAN = '\\x1b[36m'\nconst GREEN = '\\x1b[32m'\nconst YELLOW = '\\x1b[33m'\nconst WHITE = '\\x1b[37m'\nconst BOLD = '\\x1b[1m'\nconst ORANGE = '\\x1b[38;2;250;93;25m'\nconst BG_DARK = '\\x1b[48;2;30;30;30m'\nconst GRAY = '\\x1b[90m'\n\nlet headerPrinted = false\nlet sessionTotal = 0\nlet eventCount = 0\n\nfunction formatTokens(count: number): string {\n if (count >= 1_000_000) return `${(count / 1_000_000).toFixed(1)}M`\n if (count >= 1000) return `${(count / 1000).toFixed(1)}K`\n return count.toString()\n}\n\nfunction formatCost(cost: number): string {\n if (cost >= 1) return `$${cost.toFixed(2)}`\n if (cost >= 0.01) return `$${cost.toFixed(4)}`\n return `$${cost.toFixed(6)}`\n}\n\nfunction formatCostEstimate(estimate: CostEstimate): string {\n switch (estimate.type) {\n case 'priced':\n return `${GREEN}${formatCost(estimate.cost)}${RESET}`\n case 'free':\n return `${GRAY}free${RESET}`\n case 'no-tokens':\n return `${YELLOW}no usage${RESET}`\n case 'fixed-tier':\n return `${YELLOW}plan?${RESET}`\n case 'unknown':\n return `${GRAY}untracked${RESET}`\n case 'loading':\n return `${GRAY}...${RESET}`\n }\n}\n\nfunction printHeader(): void {\n if (headerPrinted) return\n headerPrinted = true\n process.stdout.write(`\\n`)\n process.stdout.write(` ${ORANGE}${BOLD} burn0 ${RESET} ${DIM}live cost tracking${RESET}\\n`)\n process.stdout.write(`\\n`)\n process.stdout.write(` ${GRAY}SERVICE ENDPOINT / MODEL USAGE COST${RESET}\\n`)\n process.stdout.write(` ${GRAY}${'─'.repeat(68)}${RESET}\\n`)\n}\n\nfunction printSessionTotal(): void {\n process.stdout.write(` ${GRAY}${'─'.repeat(68)}${RESET}\\n`)\n if (sessionTotal > 0) {\n process.stdout.write(` ${GRAY}${eventCount} calls${RESET} ${ORANGE}${BOLD}${formatCost(sessionTotal)}${RESET}\\n`)\n } else {\n process.stdout.write(` ${GRAY}${eventCount} calls${RESET} ${GRAY}$0${RESET}\\n`)\n }\n process.stdout.write(` ${GRAY}${'─'.repeat(68)}${RESET}\\n`)\n}\n\nexport function formatEventLine(event: Burn0Event): string {\n const service = event.service.length > 15\n ? event.service.substring(0, 14) + '.'\n : event.service\n\n const modelOrEndpoint = event.model\n ? (event.model.length > 29 ? event.model.substring(0, 28) + '.' : event.model)\n : (event.endpoint.length > 29 ? event.endpoint.substring(0, 28) + '.' : event.endpoint)\n\n let usage = ''\n if (event.tokens_in !== undefined && event.tokens_out !== undefined) {\n usage = `${formatTokens(event.tokens_in)} → ${formatTokens(event.tokens_out)}`\n }\n\n const estimate = estimateLocalCost(event)\n const costStr = formatCostEstimate(estimate)\n\n return ` ${CYAN}${service.padEnd(16)}${RESET} ${WHITE}${modelOrEndpoint.padEnd(30)}${RESET}${GRAY}${usage.padEnd(15)}${RESET}${costStr}`\n}\n\nexport function formatProcessSummary(events: Burn0Event[], uptimeSeconds: number): string {\n const services: Record<string, { calls: number; tokens_in?: number; tokens_out?: number }> = {}\n for (const event of events) {\n if (!services[event.service]) services[event.service] = { calls: 0 }\n services[event.service].calls++\n if (event.tokens_in !== undefined) services[event.service].tokens_in = (services[event.service].tokens_in ?? 0) + event.tokens_in\n if (event.tokens_out !== undefined) services[event.service].tokens_out = (services[event.service].tokens_out ?? 0) + event.tokens_out\n }\n for (const svc of Object.values(services)) {\n if (svc.tokens_in === undefined) delete svc.tokens_in\n if (svc.tokens_out === undefined) delete svc.tokens_out\n }\n return JSON.stringify({\n burn0: 'process-summary',\n uptime_hours: +(uptimeSeconds / 3600).toFixed(1),\n total_calls: events.length,\n services,\n message: 'Add BURN0_API_KEY to see cost breakdowns → burn0.dev',\n })\n}\n\nexport function logEvent(event: Burn0Event): void {\n printHeader()\n\n const estimate = estimateLocalCost(event)\n if (estimate.type === 'priced' && estimate.cost > 0) {\n sessionTotal += estimate.cost\n }\n eventCount++\n\n process.stdout.write(`${formatEventLine(event)}\\n`)\n\n // Show running total every 5 events\n if (eventCount % 5 === 0) {\n printSessionTotal()\n }\n}\n"],"mappings":"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","names":["preloaded","http","https","track","startSpan","enrichEvent","mode","batch","path","fs","apiKey","import_node_fs","import_node_path","path","fs","originalFetch"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/config/env.ts","../src/interceptor/guard.ts","../src/services/map.ts","../src/types.ts","../src/interceptor/stream.ts","../src/interceptor/fetch.ts","../src/interceptor/http.ts","../src/track.ts","../src/restore.ts","../src/transport/dispatcher.ts","../src/transport/batch.ts","../src/transport/local.ts","../src/transport/api.ts","../src/transport/local-pricing.ts","../src/transport/logger.ts"],"sourcesContent":["import { getApiKey, detectMode, isTTY } from './config/env'\nimport { canPatch, markPatched, resetGuard, checkImportOrder } from './interceptor/guard'\nimport { patchFetch, unpatchFetch } from './interceptor/fetch'\nimport { patchHttp, unpatchHttp } from './interceptor/http'\nimport { createTracker } from './track'\nimport { createRestorer } from './restore'\nimport { createDispatcher } from './transport/dispatcher'\nimport { BatchBuffer } from './transport/batch'\nimport { LocalLedger } from './transport/local'\nimport { shipEvents } from './transport/api'\nimport { createTicker } from './transport/logger'\nimport { fetchPricing, estimateLocalCost } from './transport/local-pricing'\nimport type { Burn0Event } from './types'\n\nconst BURN0_API_URL = process.env.BURN0_API_URL ?? 'https://api.burn0.dev'\n\nconst apiKey = getApiKey()\nconst mode = detectMode({ isTTY: isTTY(), apiKey })\n\nconst { track, startSpan, enrichEvent } = createTracker()\n\n// Store original fetch before patching (for API shipper and pricing fetch)\nconst originalFetch = globalThis.fetch\n\n// Fetch pricing data from backend (non-blocking, uses original fetch)\nif (mode !== 'test-disabled' && mode !== 'prod-local') {\n fetchPricing(BURN0_API_URL, originalFetch).catch(() => {})\n}\n\n// Always create ledger — used to seed today's cost for the ticker\nconst ledger = new LocalLedger(process.cwd())\n\n// Seed ticker with today's prior costs from ledger\nfunction getTodayDateStr(): string {\n const d = new Date()\n return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`\n}\n\nlet todayCost = 0\nlet todayCalls = 0\nconst perServiceCosts: Record<string, number> = {}\n\ntry {\n const todayStr = getTodayDateStr()\n const allEvents = ledger.read()\n for (const event of allEvents) {\n const eventDate = new Date(event.timestamp)\n const eventDateStr = `${eventDate.getFullYear()}-${String(eventDate.getMonth() + 1).padStart(2, '0')}-${String(eventDate.getDate()).padStart(2, '0')}`\n if (eventDateStr === todayStr) {\n todayCalls++\n const estimate = estimateLocalCost(event)\n if (estimate.type === 'priced' && estimate.cost > 0) {\n todayCost += estimate.cost\n perServiceCosts[event.service] = (perServiceCosts[event.service] ?? 0) + estimate.cost\n }\n }\n }\n} catch {}\n\nconst ticker = createTicker({ todayCost, todayCalls, perServiceCosts })\n\nlet batch: BatchBuffer | null = null\nif ((mode === 'dev-cloud' || mode === 'prod-cloud') && apiKey) {\n batch = new BatchBuffer({\n sizeThreshold: 50,\n timeThresholdMs: 10000,\n maxSize: 500,\n onFlush: (events) => {\n shipEvents(events, apiKey, BURN0_API_URL, originalFetch).catch(() => {})\n },\n })\n}\n\n// Always write to ledger — powers the ticker, report, and local cost tracking\nconst shouldWriteLedger = mode !== 'test-disabled' && mode !== 'prod-local'\n\nconst dispatch = createDispatcher(mode, {\n logEvent: (e) => ticker.tick(e),\n writeLedger: shouldWriteLedger ? (e) => ledger.write(e) : undefined,\n addToBatch: batch ? (e) => batch!.add(e) : undefined,\n})\n\nconst preloaded = checkImportOrder()\nif (preloaded.length > 0) {\n console.warn(`[burn0] Warning: These SDKs were imported before burn0 and may not be tracked: ${preloaded.join(', ')}. Move \\`import '@burn0/burn0'\\` to the top of your entry file.`)\n}\n\nif (mode === 'prod-local') {\n console.warn('[burn0] No API key — costs not tracked. Get one free at burn0.dev/api')\n}\n\nif (canPatch() && mode !== 'test-disabled' && mode !== 'prod-local') {\n const onEvent = (event: Burn0Event) => {\n const enriched = enrichEvent(event)\n dispatch(enriched)\n }\n patchFetch(onEvent)\n patchHttp(onEvent)\n markPatched()\n}\n\n// Cleanup on exit — flush batch and print summary\n// Only use 'exit' event — fires when process is already terminating\n// Never register SIGINT/SIGTERM handlers — that interferes with the app's lifecycle\nlet exitHandled = false\nprocess.on('exit', () => {\n if (exitHandled) return\n exitHandled = true\n if (batch) {\n batch.flush()\n batch.destroy()\n }\n ticker.printExitSummary()\n})\n\nconst restore = createRestorer({ unpatchFetch, unpatchHttp, resetGuard })\n\nexport { track, startSpan, restore }\n","import type { RuntimeMode } from '../types'\n\nexport function getApiKey(): string | undefined {\n const key = process.env.BURN0_API_KEY\n return key && key.length > 0 ? key : undefined\n}\n\nexport function detectMode(opts: { isTTY: boolean; apiKey: string | undefined }): RuntimeMode {\n const isTest = process.env.NODE_ENV === 'test'\n if (isTest) {\n return process.env.BURN0_ENABLE_TEST === '1' ? 'test-enabled' : 'test-disabled'\n }\n if (opts.apiKey) {\n return opts.isTTY ? 'dev-cloud' : 'prod-cloud'\n }\n return opts.isTTY ? 'dev-local' : 'prod-local'\n}\n\nexport function isTTY(): boolean {\n return Boolean(process.stdout.isTTY)\n}\n\nexport function isDebug(): boolean {\n return process.env.BURN0_DEBUG === '1' || process.env.BURN0_DEBUG === 'true'\n}\n","let patched = false\n\nexport function canPatch(): boolean {\n return !patched\n}\n\nexport function markPatched(): void {\n patched = true\n}\n\nexport function resetGuard(): void {\n patched = false\n}\n\nconst KNOWN_SDK_MODULES = [\n 'openai', '@anthropic-ai/sdk', '@google/generative-ai',\n '@mistralai/mistralai', 'cohere-ai', 'stripe',\n '@sendgrid/mail', 'twilio', 'resend', '@supabase/supabase-js',\n]\n\nexport function checkImportOrder(): string[] {\n const preloaded: string[] = []\n if (typeof require !== 'undefined' && require.cache) {\n for (const sdk of KNOWN_SDK_MODULES) {\n if (Object.keys(require.cache).some(k => k.includes(`/node_modules/${sdk}/`))) {\n preloaded.push(sdk)\n }\n }\n }\n return preloaded\n}\n","const BUILT_IN_MAP: Record<string, string> = {\n // LLMs\n 'api.openai.com': 'openai',\n 'api.anthropic.com': 'anthropic',\n 'generativelanguage.googleapis.com': 'google-gemini',\n 'api.mistral.ai': 'mistral',\n 'api.cohere.com': 'cohere',\n 'api.groq.com': 'groq',\n 'api.together.xyz': 'together-ai',\n 'api.perplexity.ai': 'perplexity',\n 'api.fireworks.ai': 'fireworks-ai',\n 'api.deepseek.com': 'deepseek',\n 'api.replicate.com': 'replicate',\n 'api.ai21.com': 'ai21',\n // APIs\n 'api.stripe.com': 'stripe',\n 'api.paypal.com': 'paypal',\n 'api.sendgrid.com': 'sendgrid',\n 'api.resend.com': 'resend',\n 'api.postmarkapp.com': 'postmark',\n 'api.mailgun.net': 'mailgun',\n 'api.twilio.com': 'twilio',\n 'api.vonage.com': 'vonage',\n 'api.clerk.com': 'clerk',\n 'api.cloudinary.com': 'cloudinary',\n 'upload.uploadcare.com': 'uploadcare',\n 'maps.googleapis.com': 'google-maps',\n 'api.mapbox.com': 'mapbox',\n 'api.segment.io': 'segment',\n 'api.mixpanel.com': 'mixpanel',\n 'api.github.com': 'github-api',\n 'api.plaid.com': 'plaid',\n 'api.pinecone.io': 'pinecone',\n 'supabase.co': 'supabase',\n}\n\nconst IGNORED_PATTERNS = ['localhost', '127.0.0.1', '0.0.0.0', '[::1]']\n\nlet serviceMap: Record<string, string> = { ...BUILT_IN_MAP }\n\nexport function identifyService(hostname: string): string | null {\n if (IGNORED_PATTERNS.includes(hostname) || hostname.startsWith('localhost:')) {\n return null\n }\n\n // Exact match\n if (serviceMap[hostname]) return serviceMap[hostname]\n\n // Try suffix matching for subdomains (e.g., myproject.supabase.co → supabase.co)\n for (const [mapHost, service] of Object.entries(serviceMap)) {\n if (hostname.endsWith('.' + mapHost)) return service\n }\n\n return `unknown:${hostname}`\n}\n\nexport function mergeServiceMap(remote: Record<string, string>): void {\n serviceMap = { ...serviceMap, ...remote }\n}\n\nexport function resetServiceMap(): void {\n serviceMap = { ...BUILT_IN_MAP }\n}\n","export interface Burn0Event {\n schema_version: number\n service: string\n endpoint: string\n model?: string\n tokens_in?: number\n tokens_out?: number\n status_code: number\n timestamp: string\n duration_ms: number\n estimated: boolean\n feature?: string\n metadata?: Record<string, string | number | boolean>\n}\n\nexport type RuntimeMode =\n | 'dev-cloud'\n | 'dev-local'\n | 'prod-cloud'\n | 'prod-local'\n | 'test-disabled'\n | 'test-enabled'\n\nexport interface Burn0Config {\n projectName?: string\n services?: ServiceConfig[]\n}\n\nexport interface ServiceConfig {\n name: string\n pricingModel: 'auto' | 'fixed-tier'\n plan?: string\n monthlyCost?: number\n}\n\nexport interface Span {\n end: () => void\n}\n\nexport const SCHEMA_VERSION = 1\n","export function teeReadableStream(\n stream: ReadableStream<Uint8Array>\n): [ReadableStream<Uint8Array>, ReadableStream<Uint8Array>] {\n return stream.tee() as [ReadableStream<Uint8Array>, ReadableStream<Uint8Array>]\n}\n\ninterface Usage {\n prompt_tokens?: number\n completion_tokens?: number\n input_tokens?: number\n output_tokens?: number\n}\n\nexport function extractUsageFromSSE(raw: string): Usage | null {\n const lines = raw.split('\\n')\n for (let i = lines.length - 1; i >= 0; i--) {\n const line = lines[i]\n if (!line.startsWith('data: ') || line === 'data: [DONE]') continue\n try {\n const parsed = JSON.parse(line.slice(6))\n if (parsed.usage) return parsed.usage\n } catch {}\n }\n return null\n}\n\nexport async function collectStream(stream: ReadableStream<Uint8Array>, timeoutMs = 30000): Promise<string> {\n const reader = stream.getReader()\n const chunks: string[] = []\n const decoder = new TextDecoder()\n\n const timeout = new Promise<never>((_, reject) => {\n setTimeout(() => reject(new Error('stream timeout')), timeoutMs)\n })\n\n try {\n while (true) {\n const result = await Promise.race([reader.read(), timeout]) as ReadableStreamReadResult<Uint8Array>\n if (result.done) break\n chunks.push(decoder.decode(result.value, { stream: true }))\n }\n } catch {\n // Timeout or error — return what we have\n } finally {\n try { reader.releaseLock() } catch {}\n }\n\n return chunks.join('')\n}\n","import { identifyService } from '../services/map'\nimport type { Burn0Event } from '../types'\nimport { SCHEMA_VERSION } from '../types'\nimport { teeReadableStream, collectStream, extractUsageFromSSE } from './stream'\n\ntype EventCallback = (event: Burn0Event) => void\nlet originalFetch: typeof globalThis.fetch | null = null\n\nexport function patchFetch(onEvent: EventCallback): void {\n originalFetch = globalThis.fetch\n\n globalThis.fetch = async function burn0Fetch(\n input: RequestInfo | URL,\n init?: RequestInit\n ): Promise<Response> {\n const startTime = Date.now()\n const url = new URL(typeof input === 'string' ? input : input instanceof URL ? input.href : input.url)\n const hostname = url.hostname\n const service = identifyService(hostname)\n\n if (!service) {\n return originalFetch!(input, init)\n }\n\n let model: string | undefined\n\n // Extract model from request body (OpenAI, Anthropic, etc.)\n if (init?.body && typeof init.body === 'string') {\n try {\n const parsed = JSON.parse(init.body)\n if (parsed.model) model = parsed.model\n } catch {}\n }\n\n // Extract model from URL path (Gemini-style: /v1beta/models/gemini-2.0-flash:generateContent)\n if (!model) {\n const modelMatch = url.pathname.match(/\\/models\\/([^/:]+)/)\n if (modelMatch) model = modelMatch[1]\n }\n\n const response = await originalFetch!(input, init)\n const duration = Date.now() - startTime\n\n let tokensIn: number | undefined\n let tokensOut: number | undefined\n\n // Check for SSE streaming response\n if (response.headers.get('content-type')?.includes('text/event-stream') && response.body) {\n const [forCaller, forBurn0] = teeReadableStream(response.body)\n\n collectStream(forBurn0).then((raw) => {\n const usage = extractUsageFromSSE(raw)\n let sseTokensIn = usage?.prompt_tokens ?? usage?.input_tokens\n let sseTokensOut = usage?.completion_tokens ?? usage?.output_tokens\n if (sseTokensIn !== undefined && sseTokensIn < 0) sseTokensIn = undefined\n if (sseTokensOut !== undefined && sseTokensOut < 0) sseTokensOut = undefined\n const sseEvent: Burn0Event = {\n schema_version: SCHEMA_VERSION,\n service,\n endpoint: url.pathname,\n model,\n tokens_in: sseTokensIn,\n tokens_out: sseTokensOut,\n status_code: response.status,\n timestamp: new Date().toISOString(),\n duration_ms: duration,\n estimated: !usage,\n }\n try { onEvent(sseEvent) } catch {}\n }).catch(() => {\n const sseEvent: Burn0Event = {\n schema_version: SCHEMA_VERSION,\n service,\n endpoint: url.pathname,\n model,\n status_code: response.status,\n timestamp: new Date().toISOString(),\n duration_ms: duration,\n estimated: true,\n }\n try { onEvent(sseEvent) } catch {}\n })\n\n return new Response(forCaller, {\n status: response.status,\n statusText: response.statusText,\n headers: response.headers,\n })\n }\n\n if (response.headers.get('content-type')?.includes('application/json')) {\n try {\n const cloned = response.clone()\n const body = await cloned.json()\n // Standard format (OpenAI, Anthropic, Perplexity)\n if (body.usage) {\n tokensIn = body.usage.prompt_tokens ?? body.usage.input_tokens\n tokensOut = body.usage.completion_tokens ?? body.usage.output_tokens\n }\n // Gemini format\n if (body.usageMetadata) {\n tokensIn = body.usageMetadata.promptTokenCount\n tokensOut = body.usageMetadata.candidatesTokenCount\n }\n if (body.model) model = body.model\n } catch {}\n }\n\n if (tokensIn !== undefined && tokensIn < 0) tokensIn = undefined\n if (tokensOut !== undefined && tokensOut < 0) tokensOut = undefined\n\n const event: Burn0Event = {\n schema_version: SCHEMA_VERSION,\n service,\n endpoint: url.pathname,\n model,\n tokens_in: tokensIn,\n tokens_out: tokensOut,\n status_code: response.status,\n timestamp: new Date().toISOString(),\n duration_ms: duration,\n estimated: false,\n }\n\n try { onEvent(event) } catch {}\n return response\n }\n}\n\nexport function unpatchFetch(): void {\n if (originalFetch) {\n globalThis.fetch = originalFetch\n originalFetch = null\n }\n}\n","import http from 'node:http'\nimport https from 'node:https'\nimport { identifyService } from '../services/map'\nimport type { Burn0Event } from '../types'\nimport { SCHEMA_VERSION } from '../types'\n\ntype EventCallback = (event: Burn0Event) => void\n\nlet originalHttpRequest: typeof http.request | null = null\nlet originalHttpsRequest: typeof https.request | null = null\nlet originalHttpGet: typeof http.get | null = null\nlet originalHttpsGet: typeof https.get | null = null\n\nfunction wrapRequest(original: typeof http.request, onEvent: EventCallback): typeof http.request {\n return function burn0Request(this: unknown, ...args: Parameters<typeof http.request>): http.ClientRequest {\n const req = original.apply(this, args)\n const startTime = Date.now()\n\n const firstArg = args[0]\n let hostname = ''\n let endpoint = '/'\n\n if (typeof firstArg === 'string') {\n try {\n const parsed = new URL(firstArg)\n hostname = parsed.hostname\n endpoint = parsed.pathname\n } catch {}\n } else if (firstArg instanceof URL) {\n hostname = firstArg.hostname\n endpoint = firstArg.pathname\n } else if (firstArg && typeof firstArg === 'object') {\n hostname = (firstArg as http.RequestOptions).hostname ?? (firstArg as http.RequestOptions).host ?? ''\n endpoint = (firstArg as http.RequestOptions).path ?? '/'\n }\n\n const cleanHostname = hostname.replace(/:\\d+$/, '')\n const service = identifyService(cleanHostname)\n\n if (!service) return req\n\n req.on('response', (res: http.IncomingMessage) => {\n const isJson = res.headers['content-type']?.includes('application/json')\n const chunks: Buffer[] = []\n const MAX_RESPONSE_SIZE = 5 * 1024 * 1024 // 5MB\n let totalSize = 0\n let tooLarge = false\n\n if (isJson) {\n res.on('data', (chunk: Buffer) => {\n totalSize += chunk.length\n if (totalSize > MAX_RESPONSE_SIZE) {\n tooLarge = true\n return\n }\n chunks.push(chunk)\n })\n }\n res.on('end', () => {\n const duration = Date.now() - startTime\n let tokensIn: number | undefined\n let tokensOut: number | undefined\n let model: string | undefined\n\n if (isJson && chunks.length > 0 && !tooLarge) {\n try {\n const body = JSON.parse(Buffer.concat(chunks).toString())\n if (body.usage) {\n tokensIn = body.usage.prompt_tokens ?? body.usage.input_tokens\n tokensOut = body.usage.completion_tokens ?? body.usage.output_tokens\n }\n if (body.model) model = body.model\n } catch {}\n }\n\n if (tokensIn !== undefined && tokensIn < 0) tokensIn = undefined\n if (tokensOut !== undefined && tokensOut < 0) tokensOut = undefined\n\n const event: Burn0Event = {\n schema_version: SCHEMA_VERSION,\n service,\n endpoint: endpoint.toString(),\n model,\n tokens_in: tokensIn,\n tokens_out: tokensOut,\n status_code: res.statusCode ?? 0,\n timestamp: new Date().toISOString(),\n duration_ms: duration,\n estimated: false,\n }\n try { onEvent(event) } catch {}\n })\n })\n return req\n } as typeof http.request\n}\n\nexport function patchHttp(onEvent: EventCallback): void {\n originalHttpRequest = http.request\n originalHttpsRequest = https.request\n originalHttpGet = http.get\n originalHttpsGet = https.get\n http.request = wrapRequest(originalHttpRequest, onEvent)\n https.request = wrapRequest(originalHttpsRequest as unknown as typeof http.request, onEvent) as unknown as typeof https.request\n http.get = wrapRequest(originalHttpGet as typeof http.request, onEvent) as typeof http.get\n https.get = wrapRequest(originalHttpsGet as unknown as typeof http.request, onEvent) as unknown as typeof https.get\n}\n\nexport function unpatchHttp(): void {\n if (originalHttpRequest) { http.request = originalHttpRequest; originalHttpRequest = null }\n if (originalHttpsRequest) { https.request = originalHttpsRequest; originalHttpsRequest = null }\n if (originalHttpGet) { http.get = originalHttpGet; originalHttpGet = null }\n if (originalHttpsGet) { https.get = originalHttpsGet; originalHttpsGet = null }\n}\n","import { AsyncLocalStorage } from 'node:async_hooks'\nimport type { Burn0Event, Span } from './types'\n\ninterface TrackContext {\n feature: string\n metadata?: Record<string, string | number | boolean>\n}\n\nconst storage = new AsyncLocalStorage<TrackContext>()\nlet activeSpan: TrackContext | null = null\n\nexport function createTracker() {\n async function track(\n feature: string,\n metadata: Record<string, string | number | boolean>,\n fn: () => Promise<void>\n ): Promise<void> {\n await storage.run({ feature, metadata }, fn)\n }\n\n function startSpan(\n feature: string,\n metadata?: Record<string, string | number | boolean>\n ): Span {\n activeSpan = { feature, metadata }\n return {\n end() { activeSpan = null },\n }\n }\n\n function enrichEvent(event: Burn0Event): Burn0Event {\n const ctx = storage.getStore() ?? activeSpan\n if (!ctx) return event\n return {\n ...event,\n feature: ctx.feature,\n metadata: ctx.metadata && Object.keys(ctx.metadata).length > 0 ? ctx.metadata : undefined,\n }\n }\n\n return { track, startSpan, enrichEvent }\n}\n","interface RestoreDeps {\n unpatchFetch: () => void\n unpatchHttp: () => void\n resetGuard: () => void\n}\n\nexport function createRestorer(deps: RestoreDeps): () => void {\n return () => {\n deps.unpatchFetch()\n deps.unpatchHttp()\n deps.resetGuard()\n }\n}\n","import type { Burn0Event, RuntimeMode } from '../types'\n\ninterface DispatcherDeps {\n logEvent?: (event: Burn0Event) => void\n writeLedger?: (event: Burn0Event) => void\n addToBatch?: (event: Burn0Event) => void\n}\n\nexport function createDispatcher(mode: RuntimeMode, deps: DispatcherDeps): (event: Burn0Event) => void {\n return (event: Burn0Event) => {\n switch (mode) {\n case 'dev-local':\n deps.logEvent?.(event); deps.writeLedger?.(event); break\n case 'dev-cloud':\n deps.logEvent?.(event); deps.writeLedger?.(event); deps.addToBatch?.(event); break\n case 'prod-cloud':\n deps.logEvent?.(event); deps.writeLedger?.(event); deps.addToBatch?.(event); break\n case 'prod-local':\n deps.logEvent?.(event); break\n case 'test-enabled':\n deps.logEvent?.(event); deps.writeLedger?.(event); deps.addToBatch?.(event); break\n case 'test-disabled':\n break\n }\n }\n}\n","import type { Burn0Event } from '../types'\n\nexport interface BatchBufferOptions {\n sizeThreshold: number\n timeThresholdMs: number\n maxSize: number\n onFlush: (events: Burn0Event[]) => void\n}\n\nexport class BatchBuffer {\n private events: Burn0Event[] = []\n private timer: ReturnType<typeof setInterval> | null = null\n private options: BatchBufferOptions\n\n constructor(options: BatchBufferOptions) {\n this.options = options\n this.timer = setInterval(() => {\n if (this.events.length > 0) this.flush()\n }, options.timeThresholdMs)\n if (this.timer && typeof this.timer === 'object' && 'unref' in this.timer) {\n this.timer.unref()\n }\n }\n\n add(event: Burn0Event): void {\n this.events.push(event)\n if (this.events.length > this.options.maxSize) {\n this.events = this.events.slice(-this.options.maxSize)\n }\n if (this.events.length >= this.options.sizeThreshold) {\n this.flush()\n }\n }\n\n flush(): void {\n if (this.events.length === 0) return\n const batch = [...this.events]\n this.events = []\n this.options.onFlush(batch)\n }\n\n destroy(): void {\n if (this.timer) { clearInterval(this.timer); this.timer = null }\n }\n}\n","import fs from 'node:fs'\nimport path from 'node:path'\nimport type { Burn0Event } from '../types'\n\nconst BURN0_DIR = '.burn0'\nconst LEDGER_FILE = 'costs.jsonl'\nconst MAX_FILE_SIZE = 10 * 1024 * 1024\nconst MAX_AGE_MS = 7 * 24 * 60 * 60 * 1000\n\nexport class LocalLedger {\n private filePath: string\n private dirPath: string\n\n constructor(projectRoot: string) {\n this.dirPath = path.join(projectRoot, BURN0_DIR)\n this.filePath = path.join(this.dirPath, LEDGER_FILE)\n }\n\n write(event: Burn0Event): void {\n this.ensureDir()\n this.rotateIfNeeded()\n fs.appendFileSync(this.filePath, JSON.stringify(event) + '\\n')\n }\n\n read(): Burn0Event[] {\n try {\n const content = fs.readFileSync(this.filePath, 'utf-8').trim()\n if (!content) return []\n return content.split('\\n').map((line) => JSON.parse(line) as Burn0Event)\n } catch { return [] }\n }\n\n private ensureDir(): void {\n if (!fs.existsSync(this.dirPath)) fs.mkdirSync(this.dirPath, { recursive: true })\n }\n\n private rotateIfNeeded(): void {\n try {\n const stat = fs.statSync(this.filePath)\n if (stat.size > MAX_FILE_SIZE) { this.pruneOldEntries(); return }\n } catch { return }\n const events = this.read()\n if (events.length > 0) {\n const oldest = new Date(events[0].timestamp).getTime()\n if (Date.now() - oldest > MAX_AGE_MS) this.pruneOldEntries()\n }\n }\n\n private pruneOldEntries(): void {\n const cutoff = Date.now() - MAX_AGE_MS\n const events = this.read().filter(e => new Date(e.timestamp).getTime() > cutoff)\n const content = events.map(e => JSON.stringify(e)).join('\\n') + (events.length ? '\\n' : '')\n fs.writeFileSync(this.filePath, content)\n }\n}\n","import type { Burn0Event } from '../types'\nimport { isDebug } from '../config/env'\n\nconst SDK_VERSION = '0.1.0'\n\nexport async function shipEvents(\n events: Burn0Event[],\n apiKey: string,\n baseUrl: string,\n fetchFn: typeof globalThis.fetch = globalThis.fetch\n): Promise<boolean> {\n const maxAttempts = 3\n const baseDelayMs = 1000\n const maxDelayMs = 5000\n\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\n try {\n const response = await fetchFn(`${baseUrl}/v1/events`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${apiKey}`,\n 'X-Burn0-SDK-Version': SDK_VERSION,\n },\n body: JSON.stringify({ events, sdk_version: SDK_VERSION }),\n })\n if (response.ok) return true\n } catch (err) {\n if (isDebug()) {\n console.warn('[burn0] Event shipping failed:', (err as Error).message)\n }\n }\n\n if (attempt < maxAttempts - 1) {\n const delay = Math.min(baseDelayMs * Math.pow(2, attempt), maxDelayMs)\n await new Promise((resolve) => setTimeout(resolve, delay))\n }\n }\n\n return false\n}\n","/**\n * Pricing data for terminal display.\n * Fetched from the burn0 backend on startup, cached locally.\n * Falls back to \"no cost display\" if backend is unreachable.\n */\nimport fs from 'node:fs'\nimport path from 'node:path'\n\ninterface PricingData {\n version: number\n updated_at: string\n services: Record<string, any>\n}\n\nlet pricingData: PricingData | null = null\nconst CACHE_FILE = '.burn0/pricing-cache.json'\nconst CACHE_TTL_MS = 24 * 60 * 60 * 1000 // 24 hours\n\n// Free services — no API call cost\nconst FREE_SERVICES = new Set([\n 'github-api', 'slack-api', 'discord-api',\n])\n\nexport type CostEstimate =\n | { type: 'priced'; cost: number }\n | { type: 'free' }\n | { type: 'no-tokens' }\n | { type: 'fixed-tier' }\n | { type: 'unknown' }\n | { type: 'loading' } // pricing not fetched yet\n\n/**\n * Fetch pricing from backend and cache locally.\n * Non-blocking — called on init, doesn't delay the app.\n */\nexport async function fetchPricing(\n apiUrl: string,\n fetchFn: typeof globalThis.fetch\n): Promise<void> {\n // Try cache first\n try {\n const cachePath = path.join(process.cwd(), CACHE_FILE)\n if (fs.existsSync(cachePath)) {\n const raw = fs.readFileSync(cachePath, 'utf-8')\n const cached = JSON.parse(raw) as PricingData & { cached_at: number }\n if (Date.now() - cached.cached_at < CACHE_TTL_MS) {\n pricingData = cached\n return\n }\n }\n } catch {}\n\n // Fetch from backend\n try {\n const response = await fetchFn(`${apiUrl}/v1/pricing`, {\n headers: { 'Accept': 'application/json' },\n })\n if (response.ok) {\n const data = await response.json() as PricingData\n pricingData = data\n\n // Cache to disk\n try {\n const dir = path.join(process.cwd(), '.burn0')\n if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true })\n fs.writeFileSync(\n path.join(process.cwd(), CACHE_FILE),\n JSON.stringify({ ...data, cached_at: Date.now() }, null, 2)\n )\n } catch {}\n }\n } catch {}\n}\n\nexport function estimateLocalCost(event: {\n service: string\n model?: string\n tokens_in?: number\n tokens_out?: number\n endpoint?: string\n status_code?: number\n}): CostEstimate {\n // Free services\n if (FREE_SERVICES.has(event.service)) {\n return { type: 'free' }\n }\n\n // Unknown services\n if (event.service.startsWith('unknown:')) {\n return { type: 'unknown' }\n }\n\n // No pricing data loaded yet\n if (!pricingData) {\n return { type: 'loading' }\n }\n\n const svc = pricingData.services[event.service]\n if (!svc) {\n return { type: 'unknown' }\n }\n\n // LLM pricing\n if (svc.type === 'llm') {\n if (!event.model) return { type: 'unknown' }\n if (event.tokens_in === undefined || event.tokens_out === undefined) {\n return { type: 'no-tokens' }\n }\n\n // Try exact match, then prefix match\n let prices: [number, number] | undefined = svc.models[event.model]\n if (!prices) {\n const match = Object.keys(svc.models).find((m: string) => event.model!.startsWith(m))\n if (match) prices = svc.models[match]\n }\n if (prices) {\n const inputCost = (event.tokens_in / 1_000_000) * prices[0]\n const outputCost = (event.tokens_out / 1_000_000) * prices[1]\n return { type: 'priced', cost: inputCost + outputCost }\n }\n return { type: 'unknown' }\n }\n\n // API pricing with endpoint matching\n if (svc.type === 'api') {\n const endpoint = event.endpoint ?? ''\n // Try prefix match\n for (const [prefix, cost] of Object.entries(svc.endpoints)) {\n if (prefix !== '*' && endpoint.startsWith(prefix)) {\n return (cost as number) === 0 ? { type: 'free' } : { type: 'priced', cost: cost as number }\n }\n }\n // Fall back to default\n const defaultCost = svc.endpoints['*'] as number | undefined\n if (defaultCost !== undefined) {\n return defaultCost === 0 ? { type: 'free' } : { type: 'priced', cost: defaultCost }\n }\n return { type: 'unknown' }\n }\n\n // Fixed-tier services\n if (svc.type === 'fixed') {\n return { type: 'fixed-tier' }\n }\n\n return { type: 'unknown' }\n}\n","import type { Burn0Event } from '../types'\nimport { estimateLocalCost } from './local-pricing'\n\nconst RESET = '\\x1b[0m'\nconst GREEN = '\\x1b[32m'\nconst BOLD = '\\x1b[1m'\nconst ORANGE = '\\x1b[38;2;250;93;25m'\nconst GRAY = '\\x1b[90m'\nconst CLEAR_LINE = '\\x1b[2K\\r'\n\nexport interface TickerInit {\n todayCost: number\n todayCalls: number\n perServiceCosts: Record<string, number>\n}\n\nexport interface Ticker {\n tick: (event: Burn0Event) => void\n printExitSummary: () => void\n}\n\nfunction formatCost(cost: number): string {\n if (cost >= 1) return `$${cost.toFixed(2)}`\n if (cost >= 0.01) return `$${cost.toFixed(4)}`\n return `$${cost.toFixed(6)}`\n}\n\nfunction formatDuration(ms: number): string {\n const seconds = Math.floor(ms / 1000)\n if (seconds < 60) return `${seconds}s`\n const minutes = Math.floor(seconds / 60)\n const remainingSeconds = seconds % 60\n if (minutes < 60) return `${minutes}m ${remainingSeconds}s`\n const hours = Math.floor(minutes / 60)\n const remainingMinutes = minutes % 60\n return `${hours}h ${remainingMinutes}m`\n}\n\nfunction formatServiceBreakdown(perServiceCosts: Record<string, number>, maxWidth: number): string {\n const sorted = Object.entries(perServiceCosts)\n .filter(([, cost]) => cost > 0)\n .sort((a, b) => b[1] - a[1])\n\n if (sorted.length === 0) return ''\n\n const parts: string[] = []\n let currentWidth = 0\n\n let shown = 0\n for (let i = 0; i < sorted.length && shown < 3; i++) {\n const [name, cost] = sorted[i]\n const part = `${name}: ${formatCost(cost)}`\n if (currentWidth + part.length + 3 > maxWidth && shown > 0) {\n break\n }\n parts.push(part)\n currentWidth += part.length + 3\n shown++\n }\n\n const remaining = sorted.length - shown\n if (remaining > 0) {\n parts.push(`+${remaining} more`)\n }\n\n return parts.join(' · ')\n}\n\nexport function createTicker(init: TickerInit): Ticker {\n let sessionCost = 0\n let sessionCalls = 0\n const sessionStartTime = Date.now()\n\n let todayCost = init.todayCost\n let todayCalls = init.todayCalls\n const perServiceCosts = { ...init.perServiceCosts }\n\n let exitPrinted = false\n\n let pricedCalls = 0\n let lastLineLen = 0\n\n function render(): void {\n if (!process.stderr.isTTY) return\n if (todayCalls === 0) return\n\n let content: string\n if (pricedCalls === 0 && todayCost === 0) {\n content = ` burn0 ▸ ${todayCalls} calls today`\n } else {\n const breakdown = formatServiceBreakdown(perServiceCosts, 40)\n const breakdownPart = breakdown ? ` ── ${breakdown}` : ''\n content = ` burn0 ▸ ${formatCost(todayCost)} today (${todayCalls} calls)${breakdownPart}`\n }\n\n // Pad with spaces to clear any leftover characters from the previous render\n const pad = lastLineLen > content.length ? ' '.repeat(lastLineLen - content.length) : ''\n lastLineLen = content.length\n\n // Apply colors after measuring length (ANSI codes don't take terminal width)\n let colored: string\n if (pricedCalls === 0 && todayCost === 0) {\n colored = ` ${ORANGE}${BOLD}burn0 ▸${RESET} ${GRAY}${todayCalls} calls today${RESET}`\n } else {\n const breakdown = formatServiceBreakdown(perServiceCosts, 40)\n const breakdownPart = breakdown ? ` ${GRAY}──${RESET} ${breakdown}` : ''\n colored = ` ${ORANGE}${BOLD}burn0 ▸${RESET} ${GREEN}${formatCost(todayCost)}${RESET} ${GRAY}today (${todayCalls} calls)${RESET}${breakdownPart}`\n }\n\n process.stderr.write(`\\r${colored}${pad}`)\n }\n\n function tick(event: Burn0Event): void {\n const estimate = estimateLocalCost(event)\n\n todayCalls++\n sessionCalls++\n\n if (estimate.type === 'priced' && estimate.cost > 0) {\n todayCost += estimate.cost\n sessionCost += estimate.cost\n pricedCalls++\n perServiceCosts[event.service] = (perServiceCosts[event.service] ?? 0) + estimate.cost\n }\n\n render()\n }\n\n function printExitSummary(): void {\n if (!process.stderr.isTTY) return\n if (sessionCalls === 0) return\n if (exitPrinted) return\n exitPrinted = true\n\n const duration = formatDuration(Date.now() - sessionStartTime)\n let line: string\n if (pricedCalls === 0 && sessionCost === 0) {\n line = `\\n ${ORANGE}${BOLD}burn0 ▸${RESET} ${GRAY}session: ${sessionCalls} calls (${duration})${RESET} ${GRAY}──${RESET} ${GRAY}today: ${todayCalls} calls${RESET}\\n`\n } else {\n const monthlyEst = todayCost > 0 ? formatCost(todayCost * 30) : null\n const projPart = monthlyEst ? ` ${GRAY}──${RESET} ${GRAY}~${GREEN}${monthlyEst}${RESET}${GRAY}/mo${RESET}` : ''\n line = `\\n ${ORANGE}${BOLD}burn0 ▸${RESET} ${GRAY}session:${RESET} ${GREEN}${formatCost(sessionCost)}${RESET} ${GRAY}(${sessionCalls} calls, ${duration})${RESET} ${GRAY}──${RESET} ${GRAY}today:${RESET} ${GREEN}${formatCost(todayCost)}${RESET}${projPart}\\n`\n }\n\n process.stderr.write(line)\n }\n\n return { tick, printExitSummary }\n}\n"],"mappings":"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","names":["preloaded","http","https","track","startSpan","enrichEvent","mode","batch","path","fs","apiKey","import_node_fs","import_node_path","path","fs","perServiceCosts","todayCost","todayCalls","originalFetch"]}
package/dist/index.mjs CHANGED
@@ -2,7 +2,7 @@ import {
2
2
  restore,
3
3
  startSpan,
4
4
  track
5
- } from "./chunk-ZHAS7BCI.mjs";
5
+ } from "./chunk-KKYHE4ZV.mjs";
6
6
  import "./chunk-DJ72YN4C.mjs";
7
7
  export {
8
8
  restore,