From 929abc4e343d595cd146ab46aecaeb076e3fb97f Mon Sep 17 00:00:00 2001 From: Rob Bos Date: Sat, 18 Apr 2026 11:01:06 +0200 Subject: [PATCH] feat: display CO2 in kg when >= 1000g for readability Switch CO2 emissions display from always-grams to adaptive kg/g notation: values >= 1 000 g are shown as X.XX kg. - vscode-extension webview environmental panel: add formatCo2Grams() helper that wraps smartFixed(); use it for the 4 period cards - cli environmental command: add formatCo2() helper; use it for the per-period CO2 row and the methodology tree-absorption line; remove unused mt import Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- cli/src/commands/environmental.ts | 14 +++++++++++--- .../src/webview/environmental/main.ts | 16 ++++++++++++---- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/cli/src/commands/environmental.ts b/cli/src/commands/environmental.ts index 1730e591..63f826b7 100644 --- a/cli/src/commands/environmental.ts +++ b/cli/src/commands/environmental.ts @@ -3,7 +3,7 @@ */ import { Command } from 'commander'; import chalk from 'chalk'; -import { discoverSessionFiles, calculateDetailedStats, fmt, formatTokens, ENVIRONMENTAL } from '../helpers'; +import { discoverSessionFiles, calculateDetailedStats, formatTokens, ENVIRONMENTAL } from '../helpers'; import type { PeriodStats } from '../../../vscode-extension/src/types'; export const environmentalCommand = new Command('environmental') @@ -38,7 +38,7 @@ export const environmentalCommand = new Command('environmental') console.log(chalk.dim('Methodology: Estimates based on industry averages for AI inference')); console.log(chalk.dim(` CO₂: ${ENVIRONMENTAL.CO2_PER_1K_TOKENS} gCO₂e per 1K tokens`)); console.log(chalk.dim(` Water: ${ENVIRONMENTAL.WATER_USAGE_PER_1K_TOKENS} L per 1K tokens`)); - console.log(chalk.dim(` Tree absorption: ${fmt(ENVIRONMENTAL.CO2_ABSORPTION_PER_TREE_PER_YEAR)} g CO₂/year\n`)); + console.log(chalk.dim(` Tree absorption: ${formatCo2(ENVIRONMENTAL.CO2_ABSORPTION_PER_TREE_PER_YEAR)} CO₂/year\n`)); for (const period of periods) { printEnvironmentalStats(period.label, period.emoji, period.stats); @@ -75,6 +75,14 @@ export const environmentalCommand = new Command('environmental') console.log(chalk.dim(`Last updated: ${stats.lastUpdated.toLocaleString()}\n`)); }); +/** Format CO₂ in grams, switching to kg notation when ≥ 1 000 g */ +function formatCo2(grams: number): string { + if (grams >= 1000) { + return `${(grams / 1000).toFixed(2)} kgCO₂e`; + } + return `${grams.toFixed(3)} gCO₂e`; +} + function printEnvironmentalStats(label: string, emoji: string, stats: PeriodStats): void { console.log(chalk.bold(`${emoji} ${label}`)); console.log(chalk.dim('─'.repeat(55))); @@ -86,7 +94,7 @@ function printEnvironmentalStats(label: string, emoji: string, stats: PeriodStat } console.log(` Tokens used: ${chalk.bold.yellow(formatTokens(stats.tokens))}`); - console.log(` CO₂ emissions: ${chalk.bold(stats.co2.toFixed(3))} gCO₂e`); + console.log(` CO₂ emissions: ${chalk.bold(formatCo2(stats.co2))}`); console.log(` Water usage: ${chalk.bold(stats.waterUsage.toFixed(3))} liters`); if (stats.treesEquivalent > 0) { diff --git a/vscode-extension/src/webview/environmental/main.ts b/vscode-extension/src/webview/environmental/main.ts index d44fcdc3..91641848 100644 --- a/vscode-extension/src/webview/environmental/main.ts +++ b/vscode-extension/src/webview/environmental/main.ts @@ -79,6 +79,14 @@ function smartFixed(value: number): string { return formatFixed(Math.round(value), 0); } +/** Format CO₂ in grams, switching to kg notation when ≥ 1 000 g */ +function formatCo2Grams(grams: number): string { + if (grams >= 1000) { + return `${smartFixed(grams / 1000)} kg`; + } + return `${smartFixed(grams)} g`; +} + type AnalogyItem = { icon: string; text: string }; const co2AnalogyItems = (grams: number): AnalogyItem[] => [ @@ -188,10 +196,10 @@ function buildImpactCards( ], // CO₂ card [ - ['📅 Today', `${smartFixed(stats.today.co2)} g`, co2AnalogyItems(stats.today.co2)], - ['📈 Last 30 Days', `${smartFixed(stats.last30Days.co2)} g`, co2AnalogyItems(stats.last30Days.co2)], - ['📆 Previous Month', `${smartFixed(stats.lastMonth.co2)} g`, co2AnalogyItems(stats.lastMonth.co2)], - ['🌍 Projected Year', `${smartFixed(projectedCo2)} g`, co2AnalogyItems(projectedCo2)], + ['📅 Today', formatCo2Grams(stats.today.co2), co2AnalogyItems(stats.today.co2)], + ['📈 Last 30 Days', formatCo2Grams(stats.last30Days.co2), co2AnalogyItems(stats.last30Days.co2)], + ['📆 Previous Month', formatCo2Grams(stats.lastMonth.co2), co2AnalogyItems(stats.lastMonth.co2)], + ['🌍 Projected Year', formatCo2Grams(projectedCo2), co2AnalogyItems(projectedCo2)], ], // Water card [