@grislabs/agentmeter 0.1.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/README.md +208 -0
- package/dist/auto-patch.d.ts +48 -0
- package/dist/auto-patch.d.ts.map +1 -0
- package/dist/auto-patch.js +129 -0
- package/dist/auto-patch.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +209 -0
- package/dist/cli.js.map +1 -0
- package/dist/event-buffer.d.ts +19 -0
- package/dist/event-buffer.d.ts.map +1 -0
- package/dist/event-buffer.js +54 -0
- package/dist/event-buffer.js.map +1 -0
- package/dist/extractors.d.ts +50 -0
- package/dist/extractors.d.ts.map +1 -0
- package/dist/extractors.js +46 -0
- package/dist/extractors.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +175 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp.d.ts +66 -0
- package/dist/mcp.d.ts.map +1 -0
- package/dist/mcp.js +90 -0
- package/dist/mcp.js.map +1 -0
- package/dist/pricing.d.ts +14 -0
- package/dist/pricing.d.ts.map +1 -0
- package/dist/pricing.js +61 -0
- package/dist/pricing.js.map +1 -0
- package/dist/trace-context.d.ts +86 -0
- package/dist/trace-context.d.ts.map +1 -0
- package/dist/trace-context.js +216 -0
- package/dist/trace-context.js.map +1 -0
- package/dist/types.d.ts +102 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/package.json +50 -0
package/README.md
ADDED
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
# agentmeter
|
|
2
|
+
|
|
3
|
+
Cost intelligence for AI agents. Track per-task, per-workflow, per-customer costs across LLM calls, MCP tools, and agent payments.
|
|
4
|
+
|
|
5
|
+
**The problem:** Your AI agents make 15+ LLM calls, 8 tool calls, and trigger payments per task. Existing tools track per-API-call costs. Nobody tells you "that support ticket cost $2.47 to resolve" or "customer X is costing you $500/mo in agent spend."
|
|
6
|
+
|
|
7
|
+
**agentmeter answers:** What does each agent task cost, broken down by LLM inference, tool usage, and payments — per workflow, per customer?
|
|
8
|
+
|
|
9
|
+
## Quick Start
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm install @grislabs/agentmeter
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
### Zero-config auto-tracking
|
|
16
|
+
|
|
17
|
+
Patch your LLM client once. Every call is tracked automatically.
|
|
18
|
+
|
|
19
|
+
```typescript
|
|
20
|
+
import Anthropic from "@anthropic-ai/sdk";
|
|
21
|
+
import { init, patchAnthropic } from "@grislabs/agentmeter";
|
|
22
|
+
|
|
23
|
+
init({ apiKey: "am_live_...", endpoint: "https://api.agentmeter.dev" });
|
|
24
|
+
|
|
25
|
+
const client = patchAnthropic(new Anthropic());
|
|
26
|
+
|
|
27
|
+
// All calls are now tracked — no other changes needed
|
|
28
|
+
const msg = await client.messages.create({
|
|
29
|
+
model: "claude-sonnet-4-20250514",
|
|
30
|
+
max_tokens: 1024,
|
|
31
|
+
messages: [{ role: "user", content: "Hello" }],
|
|
32
|
+
});
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Works with OpenAI too:
|
|
36
|
+
|
|
37
|
+
```typescript
|
|
38
|
+
import OpenAI from "openai";
|
|
39
|
+
import { init, patchOpenAI } from "@grislabs/agentmeter";
|
|
40
|
+
|
|
41
|
+
init({ apiKey: "am_live_..." });
|
|
42
|
+
const client = patchOpenAI(new OpenAI());
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Workflow tracing
|
|
46
|
+
|
|
47
|
+
For per-task cost attribution, wrap your agent logic in `trace()`:
|
|
48
|
+
|
|
49
|
+
```typescript
|
|
50
|
+
import { trace, extractors } from "@grislabs/agentmeter";
|
|
51
|
+
|
|
52
|
+
const result = await trace(
|
|
53
|
+
"resolve-ticket", // workflow name
|
|
54
|
+
{ customerId: "cust_123" }, // tags for attribution
|
|
55
|
+
async (ctx) => {
|
|
56
|
+
// LLM call — cost tracked automatically
|
|
57
|
+
const analysis = await ctx.llm(
|
|
58
|
+
anthropic.messages.create({
|
|
59
|
+
model: "claude-sonnet-4-20250514",
|
|
60
|
+
max_tokens: 1024,
|
|
61
|
+
messages: [{ role: "user", content: ticket.description }],
|
|
62
|
+
}),
|
|
63
|
+
extractors.anthropic,
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
// Tool call with cost (e.g., paid MCP server)
|
|
67
|
+
const results = await ctx.tool(
|
|
68
|
+
"search-kb",
|
|
69
|
+
searchKnowledgeBase(ticket.query),
|
|
70
|
+
{ cost: 0.01, costType: "mcp" },
|
|
71
|
+
);
|
|
72
|
+
|
|
73
|
+
// Agent payment (Stripe MPP, x402, etc.)
|
|
74
|
+
await ctx.payment(
|
|
75
|
+
{
|
|
76
|
+
provider: "stripe_mpp",
|
|
77
|
+
amount: 0.50,
|
|
78
|
+
description: "Premium data lookup",
|
|
79
|
+
},
|
|
80
|
+
callMPPEndpoint(query),
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
return { analysis, results };
|
|
84
|
+
},
|
|
85
|
+
);
|
|
86
|
+
// Trace recorded: $2.47 total (LLM: $0.03, Tools: $0.01, Payments: $0.50)
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Budget controls
|
|
90
|
+
|
|
91
|
+
Set cost limits per workflow. Kill runaway agents before they drain your budget.
|
|
92
|
+
|
|
93
|
+
```typescript
|
|
94
|
+
import { budget } from "@grislabs/agentmeter";
|
|
95
|
+
|
|
96
|
+
budget("resolve-ticket", {
|
|
97
|
+
perRun: 5.00, // kill if single run exceeds $5
|
|
98
|
+
daily: 500, // alert at $500/day
|
|
99
|
+
monthly: 10_000, // hard cap at $10K/month
|
|
100
|
+
onExceeded: "kill", // "kill" | "alert" | "downgrade-model"
|
|
101
|
+
});
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Budget checks cover **all cost types** — LLM, tools, and payments combined.
|
|
105
|
+
|
|
106
|
+
### MCP middleware
|
|
107
|
+
|
|
108
|
+
Auto-track all MCP tool calls without manual wrapping:
|
|
109
|
+
|
|
110
|
+
```typescript
|
|
111
|
+
import { createMCPMiddleware } from "agentmeter/mcp";
|
|
112
|
+
|
|
113
|
+
const mcpMeter = createMCPMiddleware(mcpClient, {
|
|
114
|
+
defaultCostPerCall: 0.01,
|
|
115
|
+
toolCosts: { "premium-search": 0.10 },
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
await trace("my-workflow", {}, async (ctx) => {
|
|
119
|
+
const client = mcpMeter.wrap(ctx);
|
|
120
|
+
// All callTool invocations are now tracked with costs
|
|
121
|
+
await client.callTool({ name: "search", arguments: { q: "test" } });
|
|
122
|
+
});
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## CLI
|
|
126
|
+
|
|
127
|
+
Check your agent costs from the terminal:
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
# Overview: total spend, top workflows, daily trend
|
|
131
|
+
npx agentmeter status
|
|
132
|
+
|
|
133
|
+
# Workflow breakdown with cost percentiles (p50/p95)
|
|
134
|
+
npx agentmeter workflows
|
|
135
|
+
|
|
136
|
+
# Cost per customer
|
|
137
|
+
npx agentmeter customers
|
|
138
|
+
|
|
139
|
+
# Date range filter
|
|
140
|
+
npx agentmeter status --from=2026-03-01 --to=2026-03-22
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
Configure via environment variable, `.env` file, or `agentmeter.config.json`:
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
export AGENTMETER_API_KEY=am_live_...
|
|
147
|
+
export AGENTMETER_ENDPOINT=https://api.agentmeter.dev
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
## What's tracked
|
|
151
|
+
|
|
152
|
+
| Cost type | How | Example |
|
|
153
|
+
|-----------|-----|---------|
|
|
154
|
+
| **LLM inference** | Auto (via extractors or auto-patch) | Anthropic, OpenAI, Google |
|
|
155
|
+
| **MCP tool calls** | Manual (`cost` param) or MCP middleware | Paid MCP servers, API calls |
|
|
156
|
+
| **Agent payments** | `ctx.payment()` wrapper | Stripe MPP, x402, AP2 |
|
|
157
|
+
| **Compute** | Manual (`costType: "compute"`) | E2B sandbox, GPU time |
|
|
158
|
+
|
|
159
|
+
All costs roll up into `totalCost` per trace, split into `llmCost`, `toolCost`, and `paymentCost`.
|
|
160
|
+
|
|
161
|
+
## Supported providers
|
|
162
|
+
|
|
163
|
+
Built-in extractors for token/cost calculation:
|
|
164
|
+
|
|
165
|
+
- `extractors.anthropic` — Claude (Opus, Sonnet, Haiku) with prompt caching support
|
|
166
|
+
- `extractors.openai` — GPT-4o, GPT-4o-mini, o1, o3-mini
|
|
167
|
+
- `extractors.google` — Gemini 2.0 Flash/Pro, Gemini 1.5
|
|
168
|
+
|
|
169
|
+
Custom models: use `setCustomPricing()` or pass cost directly.
|
|
170
|
+
|
|
171
|
+
## API
|
|
172
|
+
|
|
173
|
+
### `init(config)`
|
|
174
|
+
|
|
175
|
+
Initialize agentmeter. Call once at app startup.
|
|
176
|
+
|
|
177
|
+
```typescript
|
|
178
|
+
init({
|
|
179
|
+
apiKey: "am_live_...", // your API key
|
|
180
|
+
endpoint: "https://api.agentmeter.dev", // API endpoint
|
|
181
|
+
local: false, // true = console output only, no API
|
|
182
|
+
flushIntervalMs: 10_000, // batch flush interval (default: 10s)
|
|
183
|
+
flushSize: 100, // batch size trigger (default: 100)
|
|
184
|
+
pricing: { // custom model pricing (per 1M tokens)
|
|
185
|
+
"my-model": { input: 1, output: 2 },
|
|
186
|
+
},
|
|
187
|
+
});
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
### `trace(workflow, tags, fn)`
|
|
191
|
+
|
|
192
|
+
Wrap agent logic. Returns whatever `fn` returns.
|
|
193
|
+
|
|
194
|
+
### `budget(workflow, rule)`
|
|
195
|
+
|
|
196
|
+
Set cost limits. Checked on every LLM call, tool call, and payment.
|
|
197
|
+
|
|
198
|
+
### `patchAnthropic(client)` / `patchOpenAI(client)`
|
|
199
|
+
|
|
200
|
+
Auto-track all LLM calls on a client instance. Returns the same client (mutated).
|
|
201
|
+
|
|
202
|
+
### `flush()` / `shutdown()`
|
|
203
|
+
|
|
204
|
+
Flush pending events. Call `shutdown()` before process exit.
|
|
205
|
+
|
|
206
|
+
## License
|
|
207
|
+
|
|
208
|
+
MIT
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { LLMCallEvent, TraceTags } from "./types.js";
|
|
2
|
+
type EventEmitter = (event: LLMCallEvent) => void;
|
|
3
|
+
export declare function setAutoPatchEmitter(emitter: EventEmitter): void;
|
|
4
|
+
export declare function setDefaultTags(tags: TraceTags): void;
|
|
5
|
+
/**
|
|
6
|
+
* Patch an Anthropic client instance to auto-track all messages.create calls.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```ts
|
|
10
|
+
* import Anthropic from "@anthropic-ai/sdk";
|
|
11
|
+
* import { init, patchAnthropic } from "agentmeter";
|
|
12
|
+
*
|
|
13
|
+
* init({ apiKey: "am_..." });
|
|
14
|
+
* const client = patchAnthropic(new Anthropic());
|
|
15
|
+
*
|
|
16
|
+
* // All calls are now auto-tracked
|
|
17
|
+
* const msg = await client.messages.create({ model: "claude-sonnet-4", ... });
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export declare function patchAnthropic<T extends {
|
|
21
|
+
messages: {
|
|
22
|
+
create: (...args: unknown[]) => unknown;
|
|
23
|
+
};
|
|
24
|
+
}>(client: T): T;
|
|
25
|
+
/**
|
|
26
|
+
* Patch an OpenAI client instance to auto-track all chat.completions.create calls.
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```ts
|
|
30
|
+
* import OpenAI from "openai";
|
|
31
|
+
* import { init, patchOpenAI } from "agentmeter";
|
|
32
|
+
*
|
|
33
|
+
* init({ apiKey: "am_..." });
|
|
34
|
+
* const client = patchOpenAI(new OpenAI());
|
|
35
|
+
*
|
|
36
|
+
* // All calls are now auto-tracked
|
|
37
|
+
* const completion = await client.chat.completions.create({ model: "gpt-4o", ... });
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
export declare function patchOpenAI<T extends {
|
|
41
|
+
chat: {
|
|
42
|
+
completions: {
|
|
43
|
+
create: (...args: unknown[]) => unknown;
|
|
44
|
+
};
|
|
45
|
+
};
|
|
46
|
+
}>(client: T): T;
|
|
47
|
+
export {};
|
|
48
|
+
//# sourceMappingURL=auto-patch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auto-patch.d.ts","sourceRoot":"","sources":["../src/auto-patch.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE1D,KAAK,YAAY,GAAG,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC;AAKlD,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,YAAY,GAAG,IAAI,CAE/D;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,SAAS,GAAG,IAAI,CAEpD;AAqCD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,cAAc,CAAC,CAAC,SAAS;IAAE,QAAQ,EAAE;QAAE,MAAM,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAA;KAAE,CAAA;CAAE,EAChG,MAAM,EAAE,CAAC,GACR,CAAC,CA2CH;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,WAAW,CAAC,CAAC,SAAS;IAAE,IAAI,EAAE;QAAE,WAAW,EAAE;YAAE,MAAM,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAA;SAAE,CAAA;KAAE,CAAA;CAAE,EAC1G,MAAM,EAAE,CAAC,GACR,CAAC,CAwCH"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.setAutoPatchEmitter = setAutoPatchEmitter;
|
|
4
|
+
exports.setDefaultTags = setDefaultTags;
|
|
5
|
+
exports.patchAnthropic = patchAnthropic;
|
|
6
|
+
exports.patchOpenAI = patchOpenAI;
|
|
7
|
+
const pricing_js_1 = require("./pricing.js");
|
|
8
|
+
let _emitEvent = null;
|
|
9
|
+
let _defaultTags = {};
|
|
10
|
+
function setAutoPatchEmitter(emitter) {
|
|
11
|
+
_emitEvent = emitter;
|
|
12
|
+
}
|
|
13
|
+
function setDefaultTags(tags) {
|
|
14
|
+
_defaultTags = tags;
|
|
15
|
+
}
|
|
16
|
+
function emitLLMEvent(params) {
|
|
17
|
+
if (!_emitEvent)
|
|
18
|
+
return;
|
|
19
|
+
const cost = (0, pricing_js_1.calculateCost)(params.model, params.inputTokens, params.outputTokens, params.cachedInputTokens);
|
|
20
|
+
_emitEvent({
|
|
21
|
+
type: "llm",
|
|
22
|
+
traceId: "auto",
|
|
23
|
+
workflow: "auto",
|
|
24
|
+
tags: { ..._defaultTags },
|
|
25
|
+
model: params.model,
|
|
26
|
+
inputTokens: params.inputTokens,
|
|
27
|
+
outputTokens: params.outputTokens,
|
|
28
|
+
cachedInputTokens: params.cachedInputTokens,
|
|
29
|
+
cost,
|
|
30
|
+
durationMs: params.durationMs,
|
|
31
|
+
success: params.success,
|
|
32
|
+
error: params.error,
|
|
33
|
+
timestamp: Date.now(),
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Patch an Anthropic client instance to auto-track all messages.create calls.
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* ```ts
|
|
41
|
+
* import Anthropic from "@anthropic-ai/sdk";
|
|
42
|
+
* import { init, patchAnthropic } from "agentmeter";
|
|
43
|
+
*
|
|
44
|
+
* init({ apiKey: "am_..." });
|
|
45
|
+
* const client = patchAnthropic(new Anthropic());
|
|
46
|
+
*
|
|
47
|
+
* // All calls are now auto-tracked
|
|
48
|
+
* const msg = await client.messages.create({ model: "claude-sonnet-4", ... });
|
|
49
|
+
* ```
|
|
50
|
+
*/
|
|
51
|
+
function patchAnthropic(client) {
|
|
52
|
+
const original = client.messages.create.bind(client.messages);
|
|
53
|
+
client.messages.create = async function (...args) {
|
|
54
|
+
const start = Date.now();
|
|
55
|
+
try {
|
|
56
|
+
const response = await original(...args);
|
|
57
|
+
emitLLMEvent({
|
|
58
|
+
model: response.model,
|
|
59
|
+
inputTokens: response.usage.input_tokens,
|
|
60
|
+
outputTokens: response.usage.output_tokens,
|
|
61
|
+
cachedInputTokens: (response.usage.cache_read_input_tokens ?? 0) +
|
|
62
|
+
(response.usage.cache_creation_input_tokens ?? 0),
|
|
63
|
+
durationMs: Date.now() - start,
|
|
64
|
+
success: true,
|
|
65
|
+
});
|
|
66
|
+
return response;
|
|
67
|
+
}
|
|
68
|
+
catch (err) {
|
|
69
|
+
emitLLMEvent({
|
|
70
|
+
model: "unknown",
|
|
71
|
+
inputTokens: 0,
|
|
72
|
+
outputTokens: 0,
|
|
73
|
+
cachedInputTokens: 0,
|
|
74
|
+
durationMs: Date.now() - start,
|
|
75
|
+
success: false,
|
|
76
|
+
error: err instanceof Error ? err.message : String(err),
|
|
77
|
+
});
|
|
78
|
+
throw err;
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
return client;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Patch an OpenAI client instance to auto-track all chat.completions.create calls.
|
|
85
|
+
*
|
|
86
|
+
* @example
|
|
87
|
+
* ```ts
|
|
88
|
+
* import OpenAI from "openai";
|
|
89
|
+
* import { init, patchOpenAI } from "agentmeter";
|
|
90
|
+
*
|
|
91
|
+
* init({ apiKey: "am_..." });
|
|
92
|
+
* const client = patchOpenAI(new OpenAI());
|
|
93
|
+
*
|
|
94
|
+
* // All calls are now auto-tracked
|
|
95
|
+
* const completion = await client.chat.completions.create({ model: "gpt-4o", ... });
|
|
96
|
+
* ```
|
|
97
|
+
*/
|
|
98
|
+
function patchOpenAI(client) {
|
|
99
|
+
const original = client.chat.completions.create.bind(client.chat.completions);
|
|
100
|
+
client.chat.completions.create = async function (...args) {
|
|
101
|
+
const start = Date.now();
|
|
102
|
+
try {
|
|
103
|
+
const response = await original(...args);
|
|
104
|
+
emitLLMEvent({
|
|
105
|
+
model: response.model,
|
|
106
|
+
inputTokens: response.usage?.prompt_tokens ?? 0,
|
|
107
|
+
outputTokens: response.usage?.completion_tokens ?? 0,
|
|
108
|
+
cachedInputTokens: response.usage?.prompt_tokens_details?.cached_tokens ?? 0,
|
|
109
|
+
durationMs: Date.now() - start,
|
|
110
|
+
success: true,
|
|
111
|
+
});
|
|
112
|
+
return response;
|
|
113
|
+
}
|
|
114
|
+
catch (err) {
|
|
115
|
+
emitLLMEvent({
|
|
116
|
+
model: "unknown",
|
|
117
|
+
inputTokens: 0,
|
|
118
|
+
outputTokens: 0,
|
|
119
|
+
cachedInputTokens: 0,
|
|
120
|
+
durationMs: Date.now() - start,
|
|
121
|
+
success: false,
|
|
122
|
+
error: err instanceof Error ? err.message : String(err),
|
|
123
|
+
});
|
|
124
|
+
throw err;
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
return client;
|
|
128
|
+
}
|
|
129
|
+
//# sourceMappingURL=auto-patch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auto-patch.js","sourceRoot":"","sources":["../src/auto-patch.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
const node_fs_1 = require("node:fs");
|
|
5
|
+
const node_path_1 = require("node:path");
|
|
6
|
+
const DEFAULT_ENDPOINT = "http://localhost:3001";
|
|
7
|
+
function loadConfig() {
|
|
8
|
+
// 1. Check env vars
|
|
9
|
+
const envKey = process.env.AGENTMETER_API_KEY;
|
|
10
|
+
const envEndpoint = process.env.AGENTMETER_ENDPOINT;
|
|
11
|
+
// 2. Check config file
|
|
12
|
+
const configPath = (0, node_path_1.resolve)(process.cwd(), "agentmeter.config.json");
|
|
13
|
+
let fileConfig = {};
|
|
14
|
+
if ((0, node_fs_1.existsSync)(configPath)) {
|
|
15
|
+
try {
|
|
16
|
+
fileConfig = JSON.parse((0, node_fs_1.readFileSync)(configPath, "utf-8"));
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
// ignore malformed config
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
// 3. Check .env file for AGENTMETER_API_KEY
|
|
23
|
+
const envPath = (0, node_path_1.resolve)(process.cwd(), ".env");
|
|
24
|
+
if ((0, node_fs_1.existsSync)(envPath) && !envKey) {
|
|
25
|
+
const envContent = (0, node_fs_1.readFileSync)(envPath, "utf-8");
|
|
26
|
+
const match = envContent.match(/^AGENTMETER_API_KEY=(.+)$/m);
|
|
27
|
+
if (match)
|
|
28
|
+
fileConfig.apiKey = match[1].trim();
|
|
29
|
+
const endpointMatch = envContent.match(/^AGENTMETER_ENDPOINT=(.+)$/m);
|
|
30
|
+
if (endpointMatch)
|
|
31
|
+
fileConfig.endpoint = endpointMatch[1].trim();
|
|
32
|
+
}
|
|
33
|
+
return {
|
|
34
|
+
apiKey: envKey ?? fileConfig.apiKey,
|
|
35
|
+
endpoint: envEndpoint ?? fileConfig.endpoint ?? DEFAULT_ENDPOINT,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
async function apiCall(path, config) {
|
|
39
|
+
const url = `${config.endpoint}${path}`;
|
|
40
|
+
const res = await fetch(url, {
|
|
41
|
+
headers: { Authorization: `Bearer ${config.apiKey}` },
|
|
42
|
+
});
|
|
43
|
+
if (!res.ok) {
|
|
44
|
+
if (res.status === 401)
|
|
45
|
+
throw new Error("Invalid API key");
|
|
46
|
+
throw new Error(`API error: ${res.status}`);
|
|
47
|
+
}
|
|
48
|
+
return res.json();
|
|
49
|
+
}
|
|
50
|
+
function formatUSD(n) {
|
|
51
|
+
return `$${n.toFixed(4)}`;
|
|
52
|
+
}
|
|
53
|
+
function padRight(s, len) {
|
|
54
|
+
return s.length >= len ? s.slice(0, len) : s + " ".repeat(len - s.length);
|
|
55
|
+
}
|
|
56
|
+
function padLeft(s, len) {
|
|
57
|
+
return s.length >= len ? s : " ".repeat(len - s.length) + s;
|
|
58
|
+
}
|
|
59
|
+
function printTable(headers, rows, colWidths) {
|
|
60
|
+
const sep = colWidths.map((w) => "─".repeat(w + 2)).join("┼");
|
|
61
|
+
const headerLine = headers.map((h, i) => ` ${padRight(h, colWidths[i])} `).join("│");
|
|
62
|
+
console.log(`┌${"─".repeat(sep.length)}┐`);
|
|
63
|
+
console.log(`│${headerLine}│`);
|
|
64
|
+
console.log(`├${sep}┤`);
|
|
65
|
+
for (const row of rows) {
|
|
66
|
+
const line = row.map((cell, i) => {
|
|
67
|
+
const isNum = /^\$|^\d/.test(cell);
|
|
68
|
+
return isNum ? ` ${padLeft(cell, colWidths[i])} ` : ` ${padRight(cell, colWidths[i])} `;
|
|
69
|
+
}).join("│");
|
|
70
|
+
console.log(`│${line}│`);
|
|
71
|
+
}
|
|
72
|
+
console.log(`└${"─".repeat(sep.length)}┘`);
|
|
73
|
+
}
|
|
74
|
+
async function cmdStatus(config, args) {
|
|
75
|
+
const from = args.find((a) => a.startsWith("--from="))?.split("=")[1];
|
|
76
|
+
const to = args.find((a) => a.startsWith("--to="))?.split("=")[1];
|
|
77
|
+
const params = new URLSearchParams();
|
|
78
|
+
if (from)
|
|
79
|
+
params.set("from", from);
|
|
80
|
+
if (to)
|
|
81
|
+
params.set("to", to);
|
|
82
|
+
const data = await apiCall(`/v1/overview?${params}`, config);
|
|
83
|
+
console.log(`\n AgentMeter Overview (${data.from.slice(0, 10)} → ${data.to.slice(0, 10)})\n`);
|
|
84
|
+
console.log(` Total spend: ${formatUSD(data.totals.totalCost)}`);
|
|
85
|
+
console.log(` Total traces: ${data.totals.traceCount}`);
|
|
86
|
+
console.log(` Errors: ${data.totals.errorCount}\n`);
|
|
87
|
+
if (data.topWorkflows.length > 0) {
|
|
88
|
+
console.log(" Top workflows by cost:\n");
|
|
89
|
+
printTable(["Workflow", "Traces", "Total Cost"], data.topWorkflows.map((w) => [w.workflow, String(w.traceCount), formatUSD(w.totalCost)]), [30, 8, 12]);
|
|
90
|
+
}
|
|
91
|
+
if (data.dailySpend.length > 0) {
|
|
92
|
+
console.log("\n Daily spend:\n");
|
|
93
|
+
printTable(["Day", "Traces", "Cost"], data.dailySpend.slice(-7).map((d) => [d.day, String(d.traceCount), formatUSD(d.dailyCost)]), [12, 8, 12]);
|
|
94
|
+
}
|
|
95
|
+
console.log();
|
|
96
|
+
}
|
|
97
|
+
async function cmdWorkflows(config, args) {
|
|
98
|
+
const from = args.find((a) => a.startsWith("--from="))?.split("=")[1];
|
|
99
|
+
const to = args.find((a) => a.startsWith("--to="))?.split("=")[1];
|
|
100
|
+
const params = new URLSearchParams();
|
|
101
|
+
if (from)
|
|
102
|
+
params.set("from", from);
|
|
103
|
+
if (to)
|
|
104
|
+
params.set("to", to);
|
|
105
|
+
const data = await apiCall(`/v1/workflows?${params}`, config);
|
|
106
|
+
if (data.workflows.length === 0) {
|
|
107
|
+
console.log("\n No workflow data found.\n");
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
console.log("\n Workflows:\n");
|
|
111
|
+
printTable(["Workflow", "Traces", "Total $", "Avg $", "P50 $", "P95 $", "Errors"], data.workflows.map((w) => [
|
|
112
|
+
w.workflow,
|
|
113
|
+
String(w.traceCount),
|
|
114
|
+
formatUSD(w.totalCost),
|
|
115
|
+
formatUSD(w.avgCost),
|
|
116
|
+
formatUSD(w.p50Cost),
|
|
117
|
+
formatUSD(w.p95Cost),
|
|
118
|
+
String(w.errorCount),
|
|
119
|
+
]), [25, 8, 12, 10, 10, 10, 7]);
|
|
120
|
+
console.log();
|
|
121
|
+
}
|
|
122
|
+
async function cmdCustomers(config, args) {
|
|
123
|
+
const from = args.find((a) => a.startsWith("--from="))?.split("=")[1];
|
|
124
|
+
const to = args.find((a) => a.startsWith("--to="))?.split("=")[1];
|
|
125
|
+
const params = new URLSearchParams();
|
|
126
|
+
if (from)
|
|
127
|
+
params.set("from", from);
|
|
128
|
+
if (to)
|
|
129
|
+
params.set("to", to);
|
|
130
|
+
const data = await apiCall(`/v1/customers?${params}`, config);
|
|
131
|
+
if (data.customers.length === 0) {
|
|
132
|
+
console.log("\n No customer data found.\n");
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
console.log("\n Customer costs:\n");
|
|
136
|
+
printTable(["Customer", "Traces", "Total $", "Avg $/trace", "Workflows", "Errors"], data.customers.map((c) => [
|
|
137
|
+
c.customerId ?? "unknown",
|
|
138
|
+
String(c.traceCount),
|
|
139
|
+
formatUSD(c.totalCost),
|
|
140
|
+
formatUSD(c.avgCostPerTrace),
|
|
141
|
+
String(c.workflowCount),
|
|
142
|
+
String(c.errorCount),
|
|
143
|
+
]), [20, 8, 12, 12, 10, 7]);
|
|
144
|
+
console.log();
|
|
145
|
+
}
|
|
146
|
+
function printHelp() {
|
|
147
|
+
console.log(`
|
|
148
|
+
agentmeter - Cost intelligence for AI agents
|
|
149
|
+
|
|
150
|
+
Usage:
|
|
151
|
+
npx agentmeter <command> [options]
|
|
152
|
+
|
|
153
|
+
Commands:
|
|
154
|
+
status Overview: total spend, top workflows, daily trend
|
|
155
|
+
workflows List all workflows with cost percentiles (p50/p95)
|
|
156
|
+
customers Cost breakdown per customer
|
|
157
|
+
|
|
158
|
+
Options:
|
|
159
|
+
--from=DATE Start date (default: 30 days ago)
|
|
160
|
+
--to=DATE End date (default: now)
|
|
161
|
+
|
|
162
|
+
Configuration (checked in order):
|
|
163
|
+
1. AGENTMETER_API_KEY env var
|
|
164
|
+
2. agentmeter.config.json in project root
|
|
165
|
+
3. AGENTMETER_API_KEY in .env file
|
|
166
|
+
|
|
167
|
+
Examples:
|
|
168
|
+
npx agentmeter status
|
|
169
|
+
npx agentmeter workflows --from=2026-03-01
|
|
170
|
+
npx agentmeter customers --to=2026-03-22
|
|
171
|
+
`);
|
|
172
|
+
}
|
|
173
|
+
async function main() {
|
|
174
|
+
const args = process.argv.slice(2);
|
|
175
|
+
const command = args[0];
|
|
176
|
+
if (!command || command === "--help" || command === "-h") {
|
|
177
|
+
printHelp();
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
const config = loadConfig();
|
|
181
|
+
if (!config.apiKey) {
|
|
182
|
+
console.error("\n Error: No API key found.");
|
|
183
|
+
console.error(" Set AGENTMETER_API_KEY in env, .env, or agentmeter.config.json\n");
|
|
184
|
+
process.exit(1);
|
|
185
|
+
}
|
|
186
|
+
try {
|
|
187
|
+
switch (command) {
|
|
188
|
+
case "status":
|
|
189
|
+
await cmdStatus(config, args);
|
|
190
|
+
break;
|
|
191
|
+
case "workflows":
|
|
192
|
+
await cmdWorkflows(config, args);
|
|
193
|
+
break;
|
|
194
|
+
case "customers":
|
|
195
|
+
await cmdCustomers(config, args);
|
|
196
|
+
break;
|
|
197
|
+
default:
|
|
198
|
+
console.error(`\n Unknown command: ${command}\n`);
|
|
199
|
+
printHelp();
|
|
200
|
+
process.exit(1);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
catch (err) {
|
|
204
|
+
console.error(`\n Error: ${err instanceof Error ? err.message : err}\n`);
|
|
205
|
+
process.exit(1);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
main();
|
|
209
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { AgentMeterEvent } from "./types.js";
|
|
2
|
+
export declare class EventBuffer {
|
|
3
|
+
private _buffer;
|
|
4
|
+
private _flushTimer;
|
|
5
|
+
private _flushSize;
|
|
6
|
+
private _flushIntervalMs;
|
|
7
|
+
private _onFlush;
|
|
8
|
+
constructor(opts: {
|
|
9
|
+
flushSize: number;
|
|
10
|
+
flushIntervalMs: number;
|
|
11
|
+
onFlush: (events: AgentMeterEvent[]) => Promise<void>;
|
|
12
|
+
});
|
|
13
|
+
start(): void;
|
|
14
|
+
stop(): void;
|
|
15
|
+
push(event: AgentMeterEvent): void;
|
|
16
|
+
flush(): Promise<void>;
|
|
17
|
+
get pending(): number;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=event-buffer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"event-buffer.d.ts","sourceRoot":"","sources":["../src/event-buffer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD,qBAAa,WAAW;IACtB,OAAO,CAAC,OAAO,CAAyB;IACxC,OAAO,CAAC,WAAW,CAA+C;IAClE,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,gBAAgB,CAAS;IACjC,OAAO,CAAC,QAAQ,CAA+C;gBAEnD,IAAI,EAAE;QAChB,SAAS,EAAE,MAAM,CAAC;QAClB,eAAe,EAAE,MAAM,CAAC;QACxB,OAAO,EAAE,CAAC,MAAM,EAAE,eAAe,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;KACvD;IAMD,KAAK,IAAI,IAAI;IASb,IAAI,IAAI,IAAI;IAOZ,IAAI,CAAC,KAAK,EAAE,eAAe,GAAG,IAAI;IAO5B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAW5B,IAAI,OAAO,IAAI,MAAM,CAEpB;CACF"}
|