1. 项目概述与核心价值

最近在折腾各种AI助手,从OpenAI的ChatGPT API到Anthropic的Claude,再到Cursor、GitHub Copilot这类集成在IDE里的智能编程伙伴,用起来是真爽,但月底一看账单,心里就有点发毛了。尤其是当你把API调用写进脚本、或者让Cursor在后台持续分析代码时,那个token消耗就像开了闸的水龙头,悄无声息地流走。你可能会想,每个请求不就几分钱吗?但架不住量多啊,项目一复杂,迭代一频繁,积少成多,成本管控立刻就变成了一个实实在在的痛点。

这就是 agentcost-cli 这个工具诞生的背景。它不是什么庞大的商业监控平台,而是一个轻量级的命令行工具,专门为我们这些日常与多个AI服务打交道的开发者设计。它的核心目标非常明确:帮你实时追踪、分析和预测你在使用OpenAI、Claude等大模型API,以及Cursor、Copilot这类工具时的token消耗与费用。你可以把它想象成你AI消费的“个人财务管家”,通过简单的命令,就能清晰地知道钱花在了哪里,哪个模型最“烧钱”,以及接下来的项目大概还需要多少预算。

这个工具适合所有正在或计划深度使用AI辅助编程、内容创作、数据分析的开发者、团队负责人甚至独立创作者。无论你是想优化个人工作流的效率成本比,还是需要为团队项目制定清晰的AI资源预算, agentcost-cli 提供的透明化数据都能成为你决策的有力依据。它把原本分散在各个平台后台、格式不一的用量数据,统一收集并呈现出来,让“黑盒”消费变得一目了然。

2. 核心设计思路与技术选型

2.1 为什么选择CLI(命令行界面)?

首先得聊聊为什么做成CLI而不是一个带界面的桌面应用或Web仪表盘。对于开发者工具而言,CLI有着不可替代的优势。第一是 极致的轻量与高效 。它不需要渲染复杂的UI,资源占用极小,启动速度极快,可以无缝集成到任何自动化脚本、CI/CD流水线或者你的终端工作流中。想象一下,你可以在每次运行完一批AI生成任务后,直接通过一条管道命令 your_ai_script | agentcost log 来记录花费,或者将其设置为定时任务,每天早晨给你推送一份前日的消费摘要。

第二是 强大的可集成性与自动化潜力 。CLI的输出是结构化的文本(通常是JSON),这让它能轻松地与 jq grep awk 等Unix经典工具配合,进行二次处理和分析。你也可以将它的数据轻松导入到Grafana、Prometheus等监控系统,或者你自己的数据库里,构建更复杂的监控看板。这种“只做一件事,并做好它”的Unix哲学,使得 agentcost-cli 能够作为一个坚实的基石,嵌入到你更庞大的工具链生态里。

第三是 对开发者心智模型的契合 。我们的目标用户是开发者,他们大部分时间生活在终端里。一个不需要切换上下文、直接在熟悉的终端中运行的命令,其使用门槛和心智负担远低于打开一个独立的应用程序。用 npm install -g agentcost-cli 全局安装后,一个 agentcost --help 就能开始,这种体验非常顺畅。

2.2 技术栈解析:Node.js与TypeScript

项目选择了Node.js和TypeScript作为主要技术栈,这是一个非常务实且高效的选择。

Node.js 的异步非阻塞I/O模型非常适合处理这类涉及网络请求(抓取用量数据)、文件I/O(读写本地配置和日志)和流式处理(实时监控)的任务。其庞大的生态系统(npm)提供了无数高质量的包,例如用于处理命令行参数的 commander yargs ,用于发起HTTP请求的 axios got ,用于颜色化输出的 chalk ,以及用于单元测试的 jest 等,这能极大加速开发进程,避免重复造轮子。

TypeScript 的加入则是为了项目的长期可维护性和开发体验。AI服务的API模型、用量数据结构往往比较复杂且可能频繁变动。TypeScript的静态类型系统可以在编码阶段就捕获大量的潜在错误,比如拼写错误的属性名、类型不匹配的参数传递等。同时,它提供了卓越的代码智能提示(IntelliSense),当你编写代码去处理一个“OpenAI Usage Response”对象时,编辑器能直接告诉你这个对象有哪些字段,每个字段是什么类型,这大大降低了查阅外部文档的频率,提升了开发效率。对于可能由多人协作或未来需要增加复杂功能(如支持更多AI服务商)的项目来说,TypeScript带来的类型安全性和清晰的接口定义是至关重要的。

2.3 数据源与采集策略设计

工具的核心是数据。 agentcost-cli 需要从多个源头采集数据:

  1. 官方API :对于OpenAI、Anthropic这类提供了详细用量查询接口的服务商,这是最准确、最权威的数据源。通常需要用户配置相应的API Key,工具代表用户去查询指定时间范围内的token消耗和费用。这里的挑战在于不同服务商的API设计、认证方式、数据格式和费率表都不尽相同,需要为每个服务商实现一个独立的“适配器”(Adapter)。

  2. 本地日志与缓存 :对于Cursor、Copilot这类IDE插件或桌面应用,它们可能不提供官方的用量API,或者其用量与你的本地操作强相关。这时,策略就变成了 本地嗅探与推断 。例如,Cursor可能会在本地 ~/.cursor ~/.cursor/logs 目录下留下日志文件,记录每次AI交互的模型、提示(prompt)和补全(completion)的token数。 agentcost-cli 可以定期解析这些日志文件,从中提取出用量信息。这是一种“事后分析”模式。

  3. 代理拦截(高级模式) :更实时和全面的方式是通过一个本地代理。你可以配置你的AI应用(通过环境变量或设置)将所有的API请求发送到 agentcost-cli 启动的一个本地代理服务器(比如 localhost:8080 ),这个代理服务器会记录下每一个请求和响应的详细信息(包括请求头中的模型信息、请求体中的token数、响应体中的使用量),然后再将请求转发给真正的AI服务商。这种方式能捕获到100%的流量,精度最高,但实现也最复杂,且需要用户修改其应用的网络配置。

注意 :代理拦截模式涉及中间人处理网络请求,需要妥善处理安全性(如不记录敏感信息)、稳定性(代理崩溃不能影响主流程)和性能开销。对于大多数用户,基于官方API和本地日志的分析已经足够。

初始版本的 agentcost-cli 很可能会优先实现基于官方API(OpenAI, Anthropic)和本地日志(Cursor)的采集,因为这两者的可行性和用户接受度最高。

3. 核心功能模块拆解与实现

3.1 配置管理模块

任何需要对接外部服务的工具,配置管理都是第一步。 agentcost-cli 需要一个安全、灵活的方式来让用户配置他们的API密钥、偏好设置和监控目标。

实现方式 : 我们通常会选择一个固定的配置文件路径,例如 ~/.agentcost/config.json (Linux/macOS)或 %USERPROFILE%\.agentcost\config.json (Windows)。使用Node.js的 fs 模块来读写这个文件。

// ~/.agentcost/config.json 示例
{
  "openai": {
    "apiKey": "sk-...", // 实际存储时建议加密或使用环境变量引用
    "defaultModel": "gpt-4-turbo-preview",
    "organization": "org-..." // 可选
  },
  "anthropic": {
    "apiKey": "sk-ant-...",
    "defaultModel": "claude-3-opus-20240229"
  },
  "cursor": {
    "logPath": "~/.cursor/logs/app.log" // 指定Cursor日志路径
  },
  "general": {
    "currency": "USD",
    "outputFormat": "table", // 可选 table, json, csv
    "updateFrequency": "daily" // 数据更新频率
  }
}

安全考量 : 直接在配置文件中明文存储API Key是高风险行为。更好的做法是:

  1. 环境变量优先 :工具首先检查环境变量(如 OPENAI_API_KEY , ANTHROPIC_API_KEY ),如果存在则使用,配置文件中的对应字段可留空或作为备用。
  2. 加密存储 :如果必须存储在文件,应对敏感字段进行加密。可以引导用户在首次设置时提供一个主密码,用该密码派生密钥对API Key进行加密。但这增加了复杂度。
  3. 清晰的提示 :在文档和CLI输出中明确告知用户保护API Key的重要性,建议他们使用环境变量。

CLI初始化命令 : 我们会提供一个 agentcost config setup 的交互式命令,通过命令行问答(使用 inquirer 库)引导用户一步步输入必要信息,并生成或更新配置文件。

3.2 数据采集器(Collectors)

这是工具的核心引擎。我们需要为每个支持的服务实现一个独立的采集器类。所有采集器应遵循统一的接口(Interface),例如:

interface UsageCollector {
  name: string;
  // 采集指定日期范围内的用量数据
  collectUsage(startDate: Date, endDate: Date): Promise<UsageData[]>;
  // 测试连接/配置是否有效
  testConnection(): Promise<boolean>;
}

interface UsageData {
  service: string; // e.g., "openai", "cursor"
  model: string; // e.g., "gpt-4", "claude-3-sonnet"
  timestamp: Date;
  inputTokens: number;
  outputTokens: number;
  totalTokens: number;
  estimatedCost: number; // 根据官方费率计算
  metadata?: Record<string, any>; // 原始请求ID、项目标签等
}

OpenAI采集器实现要点 : OpenAI提供了 /usage 端点(需要组织级API Key)和通过 /v1/chat/completions 等端点返回的 usage 字段。对于历史数据,主要依赖 /usage 端点。

  1. 构造请求:使用配置中的API Key和Organization ID(如果有)。
  2. 处理分页: /usage 接口返回的数据可能是分页的,需要循环请求直到获取所有数据。
  3. 数据转换:将API返回的原始数据(通常按天聚合)转换为工具内部统一的 UsageData 格式,并根据 model date 匹配官方公布的费率表计算预估费用。费率表可以硬编码在工具内,并提供一个更新机制。

Cursor日志采集器实现要点

  1. 日志定位:根据配置或尝试常见的默认路径( ~/.cursor/logs )找到日志文件。
  2. 实时监控( tail -f 模式)或历史分析:使用 fs.createReadStream 配合 readline 模块逐行读取大日志文件,或者使用 tail 库实现实时跟踪。
  3. 日志解析:Cursor的日志格式可能随时间变化。需要编写一个解析函数,使用正则表达式或JSON解析(如果日志行是JSON字符串)来提取出 model prompt_tokens completion_tokens 等关键信息。这是一个需要持续维护的部分。
  4. 成本估算:Cursor本身不直接收费,但它调用的是背后的AI模型(如GPT-4)。我们需要建立一个映射关系: Cursor使用的模型名称 -> 对应的OpenAI/Anthropic官方模型及费率 ,从而估算出等效成本。

3.3 成本计算与费率管理

成本计算是另一个关键且易出错的模块。难点在于:

  1. 费率多变 :AI服务商的定价模型可能很复杂,区分输入(Input/ Prompt)Token和输出(Output/ Completion)Token,且不同模型价格不同。价格还可能随时调整。
  2. 单位换算 :费率通常是每1000个Token多少美元(如 $0.01 / 1K tokens )。计算时需要将Token数除以1000再乘以单价。
  3. 货币与精度 :需要支持多种货币显示,并处理好浮点数计算带来的精度问题(建议使用 decimal.js 这类库处理金融计算)。

实现方案 : 在项目内维护一个 pricing.json 文件,结构化地存储所有支持模型的费率。

// pricing.json
{
  "openai": {
    "gpt-4-turbo-preview": {
      "input": 0.01, // 美元/1K tokens
      "output": 0.03,
      "currency": "USD",
      "lastUpdated": "2024-04-01"
    },
    "gpt-3.5-turbo-0125": {
      "input": 0.0005,
      "output": 0.0015,
      "currency": "USD",
      "lastUpdated": "2024-04-01"
    }
  },
  "anthropic": {
    "claude-3-opus-20240229": {
      "input": 0.015,
      "output": 0.075,
      "currency": "USD"
    }
  }
}

提供一个 agentcost pricing update 命令,允许用户从某个可信源(如工具维护者提供的URL)更新费率表。计算函数则根据 UsageData 中的 service , model , inputTokens , outputTokens 查找费率并计算: cost = (inputTokens / 1000 * inputPrice) + (outputTokens / 1000 * outputPrice)

3.4 数据存储与聚合

采集到的数据需要持久化,以便生成历史报告和趋势分析。简单的方案是使用本地文件数据库,如SQLite(通过 better-sqlite3 sql.js )或直接存储为JSON文件。

SQLite方案示例 : 创建一个 schema.sql 文件定义表结构:

CREATE TABLE IF NOT EXISTS usage_records (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    service TEXT NOT NULL,
    model TEXT NOT NULL,
    timestamp DATETIME NOT NULL,
    input_tokens INTEGER DEFAULT 0,
    output_tokens INTEGER DEFAULT 0,
    total_tokens INTEGER NOT NULL,
    estimated_cost REAL NOT NULL,
    metadata TEXT, -- JSON字符串
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX idx_service_timestamp ON usage_records(service, timestamp);

每次采集器获取到新数据后,就将其插入数据库。聚合查询(如按日、按周、按模型统计)就可以通过高效的SQL语句完成,例如:

SELECT 
    date(timestamp) as day,
    service,
    model,
    SUM(estimated_cost) as daily_cost,
    SUM(total_tokens) as daily_tokens
FROM usage_records
WHERE timestamp BETWEEN ? AND ?
GROUP BY date(timestamp), service, model
ORDER BY day DESC;

3.5 CLI命令与输出展示

最后,我们需要设计一套直观易用的命令。使用 commander.js 库可以很好地构建CLI结构。

核心命令设计

  1. agentcost config :子命令管理配置,如 setup , show , edit
  2. agentcost sync [service] :手动触发数据同步,从指定服务或所有服务拉取最新用量数据并存入本地数据库。
  3. agentcost report [period] :生成报告。 period 可以是 today , yesterday , last-week , last-month , 或自定义日期范围 2024-01-01:2024-01-31
    • 默认以彩色表格形式在终端输出,使用 cli-table3 console.table
    • 支持 --format json --format csv 输出,便于脚本处理。
    • 支持 --output file.csv 将报告写入文件。
  4. agentcost monitor :进入实时监控模式,持续显示当前会话的Token消耗(类似于 top htop 命令),这对于调试和即时成本感知非常有用。
  5. agentcost budget set <amount> :设置月度预算,并在使用量接近或超出时给出警告。

输出展示示例 : 运行 agentcost report last-week 可能会输出如下表格:

┌─────────┬──────────────────────┬──────────────┬─────────────┬──────────────┬──────────────┐
│ Service │ Model                │ Input Tokens │ Output Tokens │ Total Tokens │ Estimated Cost │
├─────────┼──────────────────────┼──────────────┼─────────────┼──────────────┼──────────────┤
│ openai  │ gpt-4-turbo-preview  │ 125,430      │ 89,560      │ 214,990      │ $3.24        │
│ openai  │ gpt-3.5-turbo       │ 542,100      │ 210,300     │ 752,400      │ $0.53        │
│ cursor  │ gpt-4 (via cursor)   │ 78,900       │ 45,600      │ 124,500      │ $1.87        │
│ anthropic│ claude-3-sonnet     │ 65,800       │ 32,100      │ 97,900       │ $2.15        │
└─────────┴──────────────────────┴──────────────┴─────────────┴──────────────┴──────────────┘
                                     TOTAL COST LAST WEEK: $7.79

清晰、直观的表格能让用户快速把握消费全貌。

4. 高级功能与扩展性设计

4.1 项目/标签级成本归集

对于团队或复杂个人项目,我们不仅想知道总花费,还想知道“项目A”和“项目B”各自花了多少钱。这可以通过“标签”系统来实现。

实现思路

  1. 配置项目/标签映射 :在配置文件中,用户可以定义一组规则,将某些特征(如API请求中的特定 project 字段、访问的特定域名、代码仓库的路径)映射到一个标签。
    "taggingRules": [
      {
        "condition": { "service": "openai", "metadata.project": "nextjs-blog" },
        "tag": "project-blog"
      },
      {
        "condition": { "logPathContains": "/src/components" },
        "tag": "frontend-refactor"
      }
    ]
    
  2. 数据打标 :在数据采集或存储阶段,根据这些规则为每条用量记录附加一个或多个标签。
  3. 按标签报告 agentcost report 命令支持 --tag project-blog 参数,只显示该标签下的花费。也可以生成一个按标签聚合的总结报告。

这个功能将工具从简单的消费记录仪升级为初步的项目成本管理工具。

4.2 预算告警与通知

成本控制的关键是预警。我们可以实现一个简单的预算告警系统。

  1. 设置预算 :用户通过 agentcost budget set 100 设置月度预算为100美元。
  2. 周期性检查 :工具在每次同步数据后,或通过一个后台守护进程(daemon),计算本周期(本月)至今的累计花费。
  3. 触发告警 :当花费达到预算的50%、80%、90%、100%和110%时,触发不同级别的告警。
  4. 通知渠道
    • 终端输出 :最直接,在运行相关命令时显示醒目警告。
    • 桌面通知 :使用 node-notifier 库发送本地桌面通知。
    • Webhook :将告警事件发送到一个指定的URL,用户可以借此集成到Slack、钉钉、Discord等团队协作工具,或自己的告警系统中。

4.3 数据导出与可视化集成

虽然CLI表格很直观,但复杂的趋势分析还是需要图表。工具可以提供数据导出功能,让用户用更专业的工具进行分析。

  1. 导出格式 :支持导出为JSON、CSV格式,这是最通用的格式。
  2. 预置Grafana仪表盘 :可以提供一个Grafana的仪表盘JSON配置文件。用户将 agentcost-cli 的数据导入到支持SQLite或Prometheus的数据库中后,直接导入这个JSON文件,就能获得一个开箱即用的、包含月度趋势、模型分布、项目占比等图表的专业监控看板。
  3. 简单内置图表(可选) :对于不想搭建外部系统的用户,可以考虑使用 asciichart 之类的库在终端内生成简单的字符趋势图,虽然简陋但能提供最快速的趋势感知。

5. 实战部署与运维考量

5.1 安装与初始化

为了让用户能快速上手,安装和初始化流程必须尽可能简单。

安装

# 通过npm全局安装(推荐)
npm install -g agentcost-cli

# 或直接使用npx运行(免安装)
npx agentcost-cli config setup

初始化 : 首次运行 agentcost agentcost config setup 会启动一个交互式向导:

  1. 询问是否配置OpenAI、Anthropic等每个支持的服务。
  2. 对于每个服务,引导用户输入API Key(并提示可从环境变量读取)。
  3. 询问Cursor等本地工具的安装路径,以便自动发现日志。
  4. 设置默认货币、输出格式等偏好。
  5. 测试每个配置的连接是否成功。
  6. 将配置保存到 ~/.agentcost/config.json

5.2 作为后台服务运行

对于希望持续监控的用户,可以将 agentcost-cli 配置为一个后台服务(如systemd服务或LaunchAgent)。

Systemd服务文件示例 ( /etc/systemd/system/agentcost.service ):

[Unit]
Description=AgentCost CLI Daemon
After=network.target

[Service]
Type=simple
User=your-username
Environment="OPENAI_API_KEY=sk-..."
Environment="ANTHROPIC_API_KEY=sk-ant-..."
ExecStart=/usr/bin/agentcost monitor --daemon
Restart=on-failure
RestartSec=10

[Install]
WantedBy=multi-user.target

daemon 模式运行的 monitor 命令会持续运行,定期(如每5分钟)同步数据,并在后台检查预算告警条件,触发通知。

5.3 数据备份与迁移

本地数据库文件(如 ~/.agentcost/data.db )包含了所有的历史消费记录,非常重要。工具应提供简单的备份和恢复命令。

  • agentcost db backup --output ./backup-20240401.db :创建数据库备份。
  • agentcost db restore --input ./backup-20240401.db :从备份恢复数据库。

同时,在文档中应提醒用户定期备份此文件,特别是在进行重大版本升级之前。

6. 常见问题与故障排查

在实际使用中,你可能会遇到以下问题:

1. 数据同步失败,提示“Authentication Error”

  • 原因 :API Key已失效、配置错误或被撤销。
  • 排查
    1. 运行 agentcost config show 检查配置的Key是否正确,注意开头结尾是否有空格。
    2. 使用 agentcost config test 命令测试每个服务的连接。
    3. 手动到对应服务商的后台检查API Key的状态和剩余额度。
    4. 考虑是否配置了代理网络导致连接不通。

2. Cursor日志解析不到数据,或者数据为零

  • 原因 :Cursor更新了日志格式,或者日志路径不正确。
  • 排查
    1. 运行 agentcost config show 确认配置的Cursor日志路径。
    2. 使用 tail -f ~/.cursor/logs/app.log (请替换为你的路径)手动查看日志是否有新内容产生,并观察其格式。
    3. 检查 agentcost-cli 的版本,查看官方文档或GitHub Issues,确认是否支持你当前使用的Cursor版本。可能需要升级工具。

3. 预估成本与实际账单有细微出入

  • 原因 :这是最常见的情况,有多个可能。
  • 排查
    1. 费率表过期 :运行 agentcost pricing update 更新内置费率表。AI服务商可能已调整价格。
    2. 计算模型差异 :有些服务商可能对“上下文长度”或“缓存”的Token有特殊计费规则,而工具未考虑。需要查阅服务商最新的计费文档。
    3. 数据延迟 :官方API的用量数据可能有几小时到一天的延迟。工具同步的是截至上次拉取时的数据,并非实时。
    4. 免费额度或抵扣 :你的账单可能使用了免费额度、优惠券或积分抵扣,而工具只计算了原始消耗。

4. monitor 模式CPU或内存占用过高

  • 原因 :实时日志解析或高频API轮询可能导致资源占用上升。
  • 排查与优化
    1. 检查监控频率。通过 agentcost config edit 降低 syncFrequency (如同步间隔从1分钟改为5分钟)。
    2. 确认是否在监控非常大的日志文件。可以尝试配置日志轮转(log rotation),让Cursor只保留最近一段时间的日志。
    3. 如果只是偶尔查看,建议使用 agentcost report 命令按需查询,而不是长期开启 monitor 守护进程。

5. 工具命令执行缓慢

  • 原因 :首次同步大量历史数据、数据库未优化、网络延迟。
  • 排查
    1. 首次使用 agentcost sync --all 时,如果拉取数月的数据,速度慢是正常的。后续增量同步会很快。
    2. 可以尝试为SQLite数据库添加索引(工具应已内置)。如果数据量极大(超过10万条),考虑使用 agentcost db vacuum 命令清理和优化数据库。
    3. 对于API查询慢,工具应实现合理的超时设置和重试机制,并在命令中给出进度提示。

开发这样一个工具,最大的体会是“平衡”。在功能的丰富性、数据的准确性、使用的便捷性以及性能开销之间需要不断权衡。从最核心的“能看到花费”开始,逐步迭代,加入预算、标签、告警等高级功能,是一个更可持续的路径。另一个关键是 透明 ,要清楚地告诉用户数据的来源、计算的方式以及可能的误差范围,建立信任比追求绝对的精确度更重要。毕竟,它的首要目标是提供洞察和预警,而不是替代官方的计费系统。

Logo

码道开发者社区,聚焦华为云码道 CodeArts 代码智能体,沉淀 Agent、Skill、鸿蒙开发实战内容,供开发者查阅资料、交流技术、分享工程实践

更多推荐