clawmoney 0.10.18 → 0.10.19

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.
@@ -100,24 +100,23 @@ export function parseClaudeOutput(raw) {
100
100
  // modelUsage is a dict: { "model-name": { inputTokens, outputTokens, cacheReadInputTokens, ... } }
101
101
  let inputTokens = 0;
102
102
  let outputTokens = 0;
103
- let cachedTokens = 0;
103
+ let cacheCreationTokens = 0;
104
+ let cacheReadTokens = 0;
104
105
  let model = "";
105
106
  const modelUsage = obj.modelUsage;
106
107
  if (modelUsage) {
107
108
  for (const [modelName, usage] of Object.entries(modelUsage)) {
108
109
  model = modelName;
109
- // Total input = base + cache_creation + cache_read
110
- inputTokens += (usage.inputTokens ?? 0)
111
- + (usage.cacheCreationInputTokens ?? 0)
112
- + (usage.cacheReadInputTokens ?? 0);
110
+ inputTokens += usage.inputTokens ?? 0;
113
111
  outputTokens += usage.outputTokens ?? 0;
114
- cachedTokens += usage.cacheReadInputTokens ?? 0;
112
+ cacheCreationTokens += usage.cacheCreationInputTokens ?? 0;
113
+ cacheReadTokens += usage.cacheReadInputTokens ?? 0;
115
114
  }
116
115
  }
117
116
  return {
118
117
  text,
119
118
  sessionId,
120
- usage: { input_tokens: inputTokens, output_tokens: outputTokens, cached_tokens: cachedTokens || undefined },
119
+ usage: { input_tokens: inputTokens, output_tokens: outputTokens, cache_creation_tokens: cacheCreationTokens, cache_read_tokens: cacheReadTokens },
121
120
  model,
122
121
  costUsd,
123
122
  };
@@ -126,7 +125,7 @@ export function parseClaudeOutput(raw) {
126
125
  return {
127
126
  text: raw.trim().slice(0, 5000),
128
127
  sessionId: "",
129
- usage: { input_tokens: 0, output_tokens: 0 },
128
+ usage: { input_tokens: 0, output_tokens: 0, cache_creation_tokens: 0, cache_read_tokens: 0 },
130
129
  model: "",
131
130
  costUsd: 0,
132
131
  };
@@ -173,7 +172,7 @@ export function parseCodexOutput(raw) {
173
172
  return {
174
173
  text: text || raw.trim().slice(0, 5000),
175
174
  sessionId: threadId,
176
- usage: { input_tokens: inputTokens, output_tokens: outputTokens },
175
+ usage: { input_tokens: inputTokens, output_tokens: outputTokens, cache_creation_tokens: 0, cache_read_tokens: 0 },
177
176
  model,
178
177
  costUsd: 0,
179
178
  };
@@ -193,6 +192,7 @@ export function parseGeminiOutput(raw) {
193
192
  const sessionId = obj.session_id ?? "";
194
193
  let inputTokens = 0;
195
194
  let outputTokens = 0;
195
+ let cachedTokens = 0;
196
196
  let model = "";
197
197
  const stats = obj.stats;
198
198
  const models = stats?.models;
@@ -203,13 +203,14 @@ export function parseGeminiOutput(raw) {
203
203
  if (tokens) {
204
204
  inputTokens += tokens.input ?? tokens.prompt ?? 0;
205
205
  outputTokens += tokens.candidates ?? tokens.output ?? 0;
206
+ cachedTokens += tokens.cached ?? 0;
206
207
  }
207
208
  }
208
209
  }
209
210
  return {
210
211
  text,
211
212
  sessionId,
212
- usage: { input_tokens: inputTokens, output_tokens: outputTokens },
213
+ usage: { input_tokens: inputTokens - cachedTokens, output_tokens: outputTokens, cache_creation_tokens: 0, cache_read_tokens: cachedTokens },
213
214
  model,
214
215
  costUsd: 0,
215
216
  };
@@ -218,7 +219,7 @@ export function parseGeminiOutput(raw) {
218
219
  return {
219
220
  text: raw.trim().slice(0, 5000),
220
221
  sessionId: "",
221
- usage: { input_tokens: 0, output_tokens: 0 },
222
+ usage: { input_tokens: 0, output_tokens: 0, cache_creation_tokens: 0, cache_read_tokens: 0 },
222
223
  model: "",
223
224
  costUsd: 0,
224
225
  };
@@ -13,8 +13,13 @@ export declare const API_PRICES: Record<string, ModelPricing>;
13
13
  export declare const RELAY_DISCOUNT = 0.3;
14
14
  export declare const PLATFORM_FEE = 0.05;
15
15
  export declare function getModelPricing(model: string): ModelPricing;
16
- export declare function calculateCost(model: string, inputTokens: number, outputTokens: number): {
16
+ export interface CostBreakdown {
17
+ inputCost: number;
18
+ cacheCreationCost: number;
19
+ cacheReadCost: number;
20
+ outputCost: number;
17
21
  apiCost: number;
18
22
  relayCost: number;
19
23
  providerEarn: number;
20
- };
24
+ }
25
+ export declare function calculateCost(model: string, inputTokens: number, outputTokens: number, cacheCreationTokens?: number, cacheReadTokens?: number): CostBreakdown;
@@ -36,10 +36,18 @@ export const PLATFORM_FEE = 0.05; // 5%
36
36
  export function getModelPricing(model) {
37
37
  return API_PRICES[model] ?? DEFAULT_PRICING;
38
38
  }
39
- export function calculateCost(model, inputTokens, outputTokens) {
39
+ // Cache pricing multipliers (relative to base input price)
40
+ const CACHE_WRITE_MULTIPLIER = 1.25; // 5-minute cache write
41
+ const CACHE_READ_MULTIPLIER = 0.10; // cache hit
42
+ export function calculateCost(model, inputTokens, outputTokens, cacheCreationTokens = 0, cacheReadTokens = 0) {
40
43
  const p = getModelPricing(model);
41
- const apiCost = (inputTokens * p.input + outputTokens * p.output) / 1_000_000;
44
+ const M = 1_000_000;
45
+ const inputCost = (inputTokens * p.input) / M;
46
+ const cacheCreationCost = (cacheCreationTokens * p.input * CACHE_WRITE_MULTIPLIER) / M;
47
+ const cacheReadCost = (cacheReadTokens * p.input * CACHE_READ_MULTIPLIER) / M;
48
+ const outputCost = (outputTokens * p.output) / M;
49
+ const apiCost = inputCost + cacheCreationCost + cacheReadCost + outputCost;
42
50
  const relayCost = apiCost * RELAY_DISCOUNT;
43
51
  const providerEarn = relayCost * (1 - PLATFORM_FEE);
44
- return { apiCost, relayCost, providerEarn };
52
+ return { inputCost, cacheCreationCost, cacheReadCost, outputCost, apiCost, relayCost, providerEarn };
45
53
  }
@@ -119,15 +119,14 @@ async function executeRelayRequest(request, config) {
119
119
  const elapsedMs = Date.now() - startMs;
120
120
  const parsed = parseCliOutput(cliType, raw);
121
121
  const answer = parsed.text.replace(/\n/g, " ").slice(0, 80);
122
- const inT = parsed.usage.input_tokens;
123
- const outT = parsed.usage.output_tokens;
124
- const cachedT = parsed.usage.cached_tokens ?? 0;
125
- const { apiCost, relayCost, providerEarn } = calculateCost(model, inT, outT);
122
+ const { input_tokens: inT, output_tokens: outT, cache_creation_tokens: cacheWriteT, cache_read_tokens: cacheReadT } = parsed.usage;
123
+ const cost = calculateCost(model, inT, outT, cacheWriteT, cacheReadT);
126
124
  const elapsedSec = (elapsedMs / 1000).toFixed(1);
127
125
  logger.info(` │ Answer: ${answer}`);
128
- logger.info(` │ Tokens: ${inT} in (${cachedT} cached) / ${outT} out`);
126
+ logger.info(` │ Tokens: input=${inT} cache_write=${cacheWriteT} cache_read=${cacheReadT} output=${outT}`);
129
127
  logger.info(` │ Time: ${elapsedSec}s`);
130
- logger.info(` │ Cost: API $${apiCost.toFixed(4)} → Relay $${relayCost.toFixed(4)} → Earn $${providerEarn.toFixed(4)}`);
128
+ logger.info(` │ Cost: input=$${cost.inputCost.toFixed(4)} cache_w=$${cost.cacheCreationCost.toFixed(4)} cache_r=$${cost.cacheReadCost.toFixed(4)} output=$${cost.outputCost.toFixed(4)}`);
129
+ logger.info(` │ Total: API $${cost.apiCost.toFixed(4)} → Relay $${cost.relayCost.toFixed(4)} → Earn $${cost.providerEarn.toFixed(4)}`);
131
130
  logger.info(` └─ Done`);
132
131
  return {
133
132
  event: "relay_response",
@@ -43,7 +43,8 @@ export interface ParsedOutput {
43
43
  usage: {
44
44
  input_tokens: number;
45
45
  output_tokens: number;
46
- cached_tokens?: number;
46
+ cache_creation_tokens: number;
47
+ cache_read_tokens: number;
47
48
  };
48
49
  model: string;
49
50
  costUsd: number;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clawmoney",
3
- "version": "0.10.18",
3
+ "version": "0.10.19",
4
4
  "description": "ClawMoney CLI -- Earn rewards with your AI agent",
5
5
  "type": "module",
6
6
  "bin": {