JSPM

@open-billing/sdk

0.1.0
  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 7
  • Score
    100M100P100Q80325F
  • License MIT

Neutral SDK for the agent-billing protocol — agent meter + business client

Package Exports

  • @open-billing/sdk

Readme

@open-billing/sdk

agent-billing 协议的中立 SDK。 一包两味,按你的角色选:

  • createAgentMeter —— AI Agent 作者用。返回一个 IOMetricsProvider, 挂到 @multi-agent/a2a Agent Server 即可,每次 IO 自动带 HMAC 签名上报。
  • createBillingClient —— 业务方后端用。查事件、用量、余额、流水、价格。

本包从不发明价格、也不假设租户模型 —— 它严格说 docs/spec.md 定义的那个协议。换言之你完全可以自己写一个 SDK 替代它,协议本身才是契约。

安装

bun add @open-billing/sdk
# 或: npm i @open-billing/sdk

@multi-agent/a2a >= 0.3.10peer dep —— 只在用 createAgentMeter 时才需要, 纯业务端 client 不需要。

Agent 侧 —— 一行接入计量

import { createAgentServer, defineSkill } from '@multi-agent/a2a'
import { createAgentMeter } from '@open-billing/sdk'

createAgentServer({
  agentId: 'image-agent',
  address: 'a2a://0.0.0.0:9090',

  // a2a 协议层接管 HMAC / token 计数 / 流拦截;SDK 只做 4 个 HTTP 调用。
  metricsProvider: createAgentMeter({
    baseUrl: process.env.BILLING_URL!,
    auth: { type: 'bearer', token: process.env.BILLING_AGENT_TOKEN! },
  }),

  skills: [
    defineSkill('generate', async (params, ctx) => {
      // 业务代码不写一行计费逻辑
      return { url: `https://example.com/${Date.now()}.png` }
    }),
  ],
})

每次 skill 调用幕后发生:

  1. a2a 启动时调 verifyIntegrity → 后端返 signingKey
  2. 每次调用前 preCallCheck → 后端按余额 / 规则决定 allow
  3. handler 跑 → 输入 / 输出 token 由 a2a 统计 + 算 contentHash + HMAC 签名
  4. reportMetrics POST /events 落库

verifyIntegrity / preCallCheck 错误走严格模式(不能预检的事不应该扣费)。 reportMetrics 错误会抛出 —— a2a 内置 plugin 会 log。

"skill 失败也扣费"注意事项: a2a 的 afterHandler 不区分业务成功 / 失败, 只要 stream 有过输出就上报 IO 事件。如果 skill 报错并往 stream 写了 error 消息, 这些字节会算作 output token 扣费。三种补法见 docs/design-rationale.md §7

业务侧 —— 五指 client

import { createBillingClient } from '@open-billing/sdk'

const billing = createBillingClient({
  baseUrl: process.env.BILLING_URL!,
  auth: { type: 'bearer', token: process.env.BUSINESS_TOKEN! },
})

// 1. 用户总消费
const usage = await billing.usage.byUser('user_42')
// → { totalCalls, totalInputTokens, totalOutputTokens, totalCost? }

// 2. 按 trace 拿事件(call graph)
const events = await billing.events.byTrace(traceId)

// 3. 时间范围 + Agent 过滤
const page = await billing.events.list({
  agentId: 'image-agent',
  from: new Date(Date.now() - 24 * 3600_000),
  limit: 50,
})

// 4. 余额(Billing Module 启用时)
const balance = await billing.accounts.balance('user_42')

// 5. 流水
const ledger = await billing.accounts.ledger('user_42', { op: 'charge' })

Admin 专用操作

需要 admin token(独立的角色,见 spec §3):

await billing.accounts.topup('user_42', 10_000, 'monthly grant')
await billing.accounts.adjust('user_42', -50, 'manual refund')
await billing.pricing.create({
  skill: 'generate',
  inputTokenPrice: 1,
  outputTokenPrice: 3,
})
await billing.pricing.expire(42)

鉴权 —— 三种姿势

// 1. Bearer(默认推荐)
auth: { type: 'bearer', token: 'xxx' }

// 2. 任意 header(对接非标准后端)
auth: { type: 'header', name: 'X-Service-Token', value: 'xxx' }

// 3. 完全自定义(签 JWT / mTLS 加证书 / 注入 trace header)
auth: { type: 'fn', apply: async (init) => {
  init.headers = { ...init.headers, Authorization: await signJWT() }
  return init
}}

Transport 调优

createBillingClient({
  baseUrl: '...',
  auth: { ... },
  timeout: 5_000,                          // 默认 10000ms
  retry: { attempts: 3, backoff: 'expo' }, // 默认 1(不重试);'expo' 或 'linear'
  fetcher: customFetch,                    // 完全替换 fetch(测试 / IPC / mock)
})

重试只针对 429 + 5xx —— 4xx 错误立刻抛。

错误处理

所有 HTTP 失败都抛 BillingError:

import type { BillingError } from '@open-billing/sdk'

try {
  await billing.accounts.balance('user_42')
} catch (e) {
  const err = e as BillingError
  err.status   // HTTP 状态码,如 404
  err.code     // 服务端给的错误码,如 'account_not_found'
  err.message  // 人类可读说明
  err.details  // 可选的结构化详情
}

API 一览

导出 角色 返回
createAgentMeter Agent IOMetricsProvider(a2a)
createBillingClient 业务方 { usage, events, accounts, pricing }
分组 方法 spec 所需 token
usage byUser(userId, query?) §6.6 business
usage byAgent(agentId, query?) §6.7 business
events list(filter?) §6.5 business
events byTrace(traceId) §6.4 business
accounts list(filter?) §6.7.5 business
accounts balance(userId) §6.8 business
accounts ledger(userId, filter?) §6.9 business
accounts topup(userId, amount, note?) §6.10 admin
accounts adjust(userId, amount, note?) §6.11 admin
pricing list(filter?) §6.12 business
pricing create(entry) §6.13 admin
pricing expire(id) §6.14 admin

完整类型定义看 src/types.ts,完整 wire format 看 docs/openapi.yaml

验证你的后端是否符合本协议

不管你 fork 参考服务端还是自己撸,跑 @open-billing/testkit 一次 —— 17 个 case 覆盖 鉴权 / HMAC / 幂等 / Billing Module 合规性。

License

MIT