@costwise/sdk 0.0.1 → 0.0.3

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.
Files changed (52) hide show
  1. package/README.md +176 -0
  2. package/dist/cjs/cli.d.ts +3 -0
  3. package/dist/cjs/cli.d.ts.map +1 -0
  4. package/dist/cjs/cli.js +156 -0
  5. package/dist/cjs/cli.js.map +1 -0
  6. package/dist/cjs/index.d.ts +5 -0
  7. package/dist/cjs/index.d.ts.map +1 -0
  8. package/dist/cjs/index.js +12 -0
  9. package/dist/cjs/index.js.map +1 -0
  10. package/dist/cjs/package.json +1 -0
  11. package/dist/cjs/src/anthropic.d.ts +10 -0
  12. package/dist/cjs/src/anthropic.d.ts.map +1 -0
  13. package/dist/cjs/src/anthropic.js +55 -0
  14. package/dist/cjs/src/anthropic.js.map +1 -0
  15. package/dist/cjs/src/openai.d.ts +9 -0
  16. package/dist/cjs/src/openai.d.ts.map +1 -0
  17. package/dist/cjs/src/openai.js +51 -0
  18. package/dist/cjs/src/openai.js.map +1 -0
  19. package/dist/cjs/src/tracker.d.ts +23 -0
  20. package/dist/cjs/src/tracker.d.ts.map +1 -0
  21. package/dist/cjs/src/tracker.js +212 -0
  22. package/dist/cjs/src/tracker.js.map +1 -0
  23. package/dist/cjs/src/types.d.ts +56 -0
  24. package/dist/cjs/src/types.d.ts.map +1 -0
  25. package/dist/cjs/src/types.js +3 -0
  26. package/dist/cjs/src/types.js.map +1 -0
  27. package/dist/esm/cli.d.ts +3 -0
  28. package/dist/esm/cli.d.ts.map +1 -0
  29. package/dist/esm/cli.js +154 -0
  30. package/dist/esm/cli.js.map +1 -0
  31. package/dist/esm/index.d.ts +5 -0
  32. package/dist/esm/index.d.ts.map +1 -0
  33. package/dist/esm/index.js +4 -0
  34. package/dist/esm/index.js.map +1 -0
  35. package/dist/esm/src/anthropic.d.ts +10 -0
  36. package/dist/esm/src/anthropic.d.ts.map +1 -0
  37. package/dist/esm/src/anthropic.js +48 -0
  38. package/dist/esm/src/anthropic.js.map +1 -0
  39. package/dist/esm/src/openai.d.ts +9 -0
  40. package/dist/esm/src/openai.d.ts.map +1 -0
  41. package/dist/esm/src/openai.js +44 -0
  42. package/dist/esm/src/openai.js.map +1 -0
  43. package/dist/esm/src/tracker.d.ts +23 -0
  44. package/dist/esm/src/tracker.d.ts.map +1 -0
  45. package/dist/esm/src/tracker.js +207 -0
  46. package/dist/esm/src/tracker.js.map +1 -0
  47. package/dist/esm/src/types.d.ts +56 -0
  48. package/dist/esm/src/types.d.ts.map +1 -0
  49. package/dist/esm/src/types.js +2 -0
  50. package/dist/esm/src/types.js.map +1 -0
  51. package/package.json +36 -2
  52. package/index.js +0 -3
package/README.md ADDED
@@ -0,0 +1,176 @@
1
+ # @costwise/sdk
2
+
3
+ Track Anthropic and OpenAI API usage costs with a drop-in SDK wrapper.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install @costwise/sdk
9
+ ```
10
+
11
+ ## Quick start
12
+
13
+ Replace:
14
+
15
+ ```ts
16
+ import OpenAI from "openai";
17
+ ```
18
+
19
+ with:
20
+
21
+ ```ts
22
+ import { CostwiseOpenAI } from "@costwise/sdk";
23
+ ```
24
+
25
+ Then initialize as usual:
26
+
27
+ ```ts
28
+ import { CostwiseOpenAI, CostwiseAnthropic } from "@costwise/sdk";
29
+
30
+ const openai = new CostwiseOpenAI({
31
+ apiKey: process.env.OPENAI_API_KEY,
32
+ costwiseKey: process.env.COSTWISE_API_KEY,
33
+ tag: "my-app"
34
+ });
35
+
36
+ const anthropic = new CostwiseAnthropic({
37
+ apiKey: process.env.ANTHROPIC_API_KEY,
38
+ costwiseKey: process.env.COSTWISE_API_KEY,
39
+ tag: "my-app"
40
+ });
41
+ ```
42
+
43
+ After each response, Costwise sends a non-blocking ingest event to:
44
+
45
+ `https://api.costwise.dev/ingest`
46
+
47
+ Tracking is fire-and-forget and never awaited, so request latency is not impacted. If ingest is unreachable, it fails silently.
48
+
49
+ ## Environment variables
50
+
51
+ - `COSTWISE_API_KEY` (optional if `costwiseKey` is provided in constructor)
52
+ - Constructor key aliases supported: `costwiseKey` (canonical) and `costswiseKey` (compatibility alias)
53
+ - `COSTWISE_LOCAL_USAGE_PATH` (optional JSONL file path for local usage history used by CLI)
54
+
55
+ ## Ingest payload
56
+
57
+ The SDK emits:
58
+
59
+ - `model`
60
+ - `input_tokens`
61
+ - `output_tokens`
62
+ - `cost` and `estimated_cost`
63
+ - `tag` and `endpoint_tag` (optional)
64
+ - `ts` and `timestamp`
65
+
66
+ ## Compare model costs and capacity
67
+
68
+ Use tracker utilities to estimate what other models would have cost for the same token usage:
69
+
70
+ ```ts
71
+ import { CostwiseTracker } from "@costwise/sdk";
72
+
73
+ const tracker = new CostwiseTracker({
74
+ costwiseKey: process.env.COSTWISE_API_KEY
75
+ });
76
+
77
+ const comparisons = tracker.compareCosts({
78
+ model: "gpt-4o",
79
+ inputTokens: 12000,
80
+ outputTokens: 2500
81
+ });
82
+
83
+ const summary = tracker.summarizeComparison({
84
+ model: "gpt-4o",
85
+ inputTokens: 12000,
86
+ outputTokens: 2500
87
+ });
88
+ ```
89
+
90
+ `compareCosts()` returns each model's estimated cost and capacity metadata (context window and capacity class), sorted cheapest-first.
91
+
92
+ Group by capacity tier and read the cheapest model per tier:
93
+
94
+ ```ts
95
+ const { byClass, cheapestPerClass } = tracker.compareCostsByCapacity({
96
+ model: "gpt-4o",
97
+ inputTokens: 12000,
98
+ outputTokens: 2500
99
+ });
100
+
101
+ // e.g. cheapestPerClass.mini?.model, cheapestPerClass.high?.estimatedCost
102
+ ```
103
+
104
+ `byClass` maps `nano` | `mini` | `standard` | `high` | `frontier` to full lists (cheapest-first within each class). `cheapestPerClass` is the single best-priced model in each class that has at least one priced model.
105
+
106
+ Format a ready-to-print CLI summary (without logging inside the SDK):
107
+
108
+ ```ts
109
+ const cli = tracker.formatComparisonForCli({
110
+ model: "gpt-4o",
111
+ inputTokens: 12000,
112
+ outputTokens: 2500
113
+ });
114
+
115
+ // App decides if/where to print:
116
+ // console.log(cli.text)
117
+ ```
118
+
119
+ ## Smoke test
120
+
121
+ Run a local end-to-end smoke test (build + mocked ingest + comparison output):
122
+
123
+ ```bash
124
+ npm run smoke
125
+ ```
126
+
127
+ ## CLI for actual usage
128
+
129
+ The CLI reads **real usage events** from a local JSONL file written by the SDK at runtime.
130
+
131
+ 1) Set a usage file path in your app environment:
132
+
133
+ ```bash
134
+ export COSTWISE_LOCAL_USAGE_PATH=.costwise-usage.jsonl
135
+ ```
136
+
137
+ 2) Run your app so events are recorded.
138
+
139
+ 3) Query usage and compare alternatives:
140
+
141
+ ```bash
142
+ costwise usage
143
+ costwise compare-actual
144
+ ```
145
+
146
+ Optional:
147
+
148
+ ```bash
149
+ costwise usage --file .costwise-usage.jsonl --json
150
+ costwise compare-actual --file .costwise-usage.jsonl --json
151
+ ```
152
+
153
+ ## Automated tests
154
+
155
+ Run the Node test suite (build + unit tests):
156
+
157
+ ```bash
158
+ npm test
159
+ ```
160
+
161
+ Current test coverage includes:
162
+
163
+ - Tracker cost math correctness for known models
164
+ - Unknown model handling (no ingest + empty comparison)
165
+ - Fire-and-forget tracking behavior (`fetch` not awaited)
166
+ - Silent ingest failure handling (`.catch(() => {})`)
167
+ - `compareCostsByCapacity()` output shape
168
+ - `formatComparisonForCli()` output shape
169
+ - OpenAI wrapper behavior:
170
+ - non-stream response returned untouched
171
+ - stream response returned untouched
172
+ - stream tracking via `finalChatCompletion()`
173
+ - Anthropic wrapper behavior:
174
+ - non-stream response returned untouched
175
+ - stream response returned untouched
176
+ - stream tracking via `finalMessage()`
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../cli.ts"],"names":[],"mappings":""}
@@ -0,0 +1,156 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ const promises_1 = require("node:fs/promises");
5
+ const tracker_js_1 = require("./src/tracker.js");
6
+ function help(exitCode) {
7
+ process.stdout.write([
8
+ "Costwise CLI (actual usage only)",
9
+ "",
10
+ "Usage:",
11
+ " costwise usage [--file <path>] [--json]",
12
+ " costwise compare-actual [--file <path>] [--json]",
13
+ "",
14
+ "Notes:",
15
+ " - Reads usage events from JSONL recorded by SDK (`COSTWISE_LOCAL_USAGE_PATH`).",
16
+ " - No manual token input flags are supported."
17
+ ].join("\n") + "\n");
18
+ process.exit(exitCode);
19
+ }
20
+ function parse(argv) {
21
+ if (argv.length === 0 || argv.includes("--help") || argv.includes("-h")) {
22
+ help(0);
23
+ }
24
+ const options = { json: false };
25
+ const first = argv[0];
26
+ if (first === "usage" || first === "compare-actual") {
27
+ options.command = first;
28
+ }
29
+ else {
30
+ help(1);
31
+ }
32
+ for (let i = 1; i < argv.length; i += 1) {
33
+ const arg = argv[i];
34
+ const next = argv[i + 1];
35
+ if (arg === "--file" && next) {
36
+ options.filePath = next;
37
+ i += 1;
38
+ continue;
39
+ }
40
+ if (arg === "--json") {
41
+ options.json = true;
42
+ continue;
43
+ }
44
+ help(1);
45
+ }
46
+ return options;
47
+ }
48
+ async function loadEvents(path) {
49
+ const content = await (0, promises_1.readFile)(path, "utf8");
50
+ const lines = content.split("\n").map((line) => line.trim()).filter(Boolean);
51
+ return lines.map((line) => JSON.parse(line));
52
+ }
53
+ function runUsage(events, asJson) {
54
+ const totals = events.reduce((acc, event) => {
55
+ acc.input += event.input_tokens;
56
+ acc.output += event.output_tokens;
57
+ acc.cost += event.estimated_cost;
58
+ acc.byModel[event.model] = (acc.byModel[event.model] ?? 0) + event.estimated_cost;
59
+ return acc;
60
+ }, { input: 0, output: 0, cost: 0, byModel: {} });
61
+ const topModels = Object.entries(totals.byModel)
62
+ .map(([model, cost]) => ({ model, cost }))
63
+ .sort((a, b) => b.cost - a.cost)
64
+ .slice(0, 5);
65
+ if (asJson) {
66
+ process.stdout.write(`${JSON.stringify({
67
+ events: events.length,
68
+ input_tokens: totals.input,
69
+ output_tokens: totals.output,
70
+ estimated_cost: totals.cost,
71
+ top_models: topModels
72
+ }, null, 2)}\n`);
73
+ return;
74
+ }
75
+ const lines = [
76
+ `Events: ${events.length}`,
77
+ `Input tokens: ${totals.input}`,
78
+ `Output tokens: ${totals.output}`,
79
+ `Estimated cost: $${totals.cost.toFixed(6)}`,
80
+ "Top models by spend:"
81
+ ];
82
+ for (const model of topModels) {
83
+ lines.push(` - ${model.model}: $${model.cost.toFixed(6)}`);
84
+ }
85
+ process.stdout.write(`${lines.join("\n")}\n`);
86
+ }
87
+ function runCompareActual(events, asJson) {
88
+ const totalInput = events.reduce((sum, event) => sum + event.input_tokens, 0);
89
+ const totalOutput = events.reduce((sum, event) => sum + event.output_tokens, 0);
90
+ const actualCost = events.reduce((sum, event) => sum + event.estimated_cost, 0);
91
+ const alternatives = Object.entries(tracker_js_1.PRICING)
92
+ .map(([model, rates]) => {
93
+ const estimated_cost = (totalInput / 1_000_000) * rates.input + (totalOutput / 1_000_000) * rates.output;
94
+ return {
95
+ model,
96
+ estimated_cost,
97
+ delta_vs_actual: estimated_cost - actualCost
98
+ };
99
+ })
100
+ .sort((a, b) => a.estimated_cost - b.estimated_cost);
101
+ const tracker = new tracker_js_1.CostwiseTracker();
102
+ const formatted = tracker.formatComparisonForCli({
103
+ model: alternatives[0]?.model ?? "unknown",
104
+ inputTokens: totalInput,
105
+ outputTokens: totalOutput
106
+ });
107
+ if (asJson) {
108
+ process.stdout.write(`${JSON.stringify({
109
+ actual: {
110
+ events: events.length,
111
+ input_tokens: totalInput,
112
+ output_tokens: totalOutput,
113
+ estimated_cost: actualCost
114
+ },
115
+ alternatives: alternatives.slice(0, 10)
116
+ }, null, 2)}\n`);
117
+ return;
118
+ }
119
+ const lines = [
120
+ `Actual usage events: ${events.length}`,
121
+ `Actual estimated cost: $${actualCost.toFixed(6)}`,
122
+ "Top alternative models (same total tokens):",
123
+ ...alternatives.slice(0, 5).map((alt) => ` - ${alt.model}: $${alt.estimated_cost.toFixed(6)} (delta ${alt.delta_vs_actual >= 0 ? "+" : ""}${alt.delta_vs_actual.toFixed(6)})`),
124
+ "",
125
+ "Cheapest-model summary:",
126
+ formatted.text
127
+ ];
128
+ process.stdout.write(`${lines.join("\n")}\n`);
129
+ }
130
+ async function main() {
131
+ const options = parse(process.argv.slice(2));
132
+ const usagePath = options.filePath ?? process.env.COSTWISE_LOCAL_USAGE_PATH;
133
+ if (!usagePath) {
134
+ process.stderr.write("Missing usage file. Set COSTWISE_LOCAL_USAGE_PATH or pass --file.\n");
135
+ process.exit(1);
136
+ }
137
+ let events = [];
138
+ try {
139
+ events = await loadEvents(usagePath);
140
+ }
141
+ catch {
142
+ process.stderr.write(`Unable to read usage file: ${usagePath}\n`);
143
+ process.exit(1);
144
+ }
145
+ if (events.length === 0) {
146
+ process.stdout.write("No usage events found.\n");
147
+ return;
148
+ }
149
+ if (options.command === "usage") {
150
+ runUsage(events, options.json);
151
+ return;
152
+ }
153
+ runCompareActual(events, options.json);
154
+ }
155
+ void main();
156
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../../cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export { CostwiseAnthropic } from "./src/anthropic.js";
2
+ export { CostwiseOpenAI } from "./src/openai.js";
3
+ export { CostwiseTracker, MODEL_CAPACITIES, PRICING } from "./src/tracker.js";
4
+ export type { CostwiseOptions, IngestPayload, CliComparisonFormat, LocalUsageEvent, ModelCapacity, ModelCapacityClass, ModelComparison, ModelComparisonByCapacity } from "./src/types.js";
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAC9E,YAAY,EACV,eAAe,EACf,aAAa,EACb,mBAAmB,EACnB,eAAe,EACf,aAAa,EACb,kBAAkB,EAClB,eAAe,EACf,yBAAyB,EAC1B,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PRICING = exports.MODEL_CAPACITIES = exports.CostwiseTracker = exports.CostwiseOpenAI = exports.CostwiseAnthropic = void 0;
4
+ var anthropic_js_1 = require("./src/anthropic.js");
5
+ Object.defineProperty(exports, "CostwiseAnthropic", { enumerable: true, get: function () { return anthropic_js_1.CostwiseAnthropic; } });
6
+ var openai_js_1 = require("./src/openai.js");
7
+ Object.defineProperty(exports, "CostwiseOpenAI", { enumerable: true, get: function () { return openai_js_1.CostwiseOpenAI; } });
8
+ var tracker_js_1 = require("./src/tracker.js");
9
+ Object.defineProperty(exports, "CostwiseTracker", { enumerable: true, get: function () { return tracker_js_1.CostwiseTracker; } });
10
+ Object.defineProperty(exports, "MODEL_CAPACITIES", { enumerable: true, get: function () { return tracker_js_1.MODEL_CAPACITIES; } });
11
+ Object.defineProperty(exports, "PRICING", { enumerable: true, get: function () { return tracker_js_1.PRICING; } });
12
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../index.ts"],"names":[],"mappings":";;;AAAA,mDAAuD;AAA9C,iHAAA,iBAAiB,OAAA;AAC1B,6CAAiD;AAAxC,2GAAA,cAAc,OAAA;AACvB,+CAA8E;AAArE,6GAAA,eAAe,OAAA;AAAE,8GAAA,gBAAgB,OAAA;AAAE,qGAAA,OAAO,OAAA"}
@@ -0,0 +1 @@
1
+ {"type":"commonjs"}
@@ -0,0 +1,10 @@
1
+ import Anthropic from "@anthropic-ai/sdk";
2
+ import { CostwiseOptions } from "./types.js";
3
+ export declare class CostwiseAnthropic extends Anthropic {
4
+ private readonly tracker;
5
+ private readonly tag?;
6
+ constructor(options?: ConstructorParameters<typeof Anthropic>[0] & CostwiseOptions);
7
+ private wrapMessagesCreate;
8
+ private hasFinalMessage;
9
+ }
10
+ //# sourceMappingURL=anthropic.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"anthropic.d.ts","sourceRoot":"","sources":["../../../src/anthropic.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,mBAAmB,CAAC;AAC1C,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AA0B7C,qBAAa,iBAAkB,SAAQ,SAAS;IAC9C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAkB;IAC1C,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAS;gBAElB,OAAO,GAAE,qBAAqB,CAAC,OAAO,SAAS,CAAC,CAAC,CAAC,CAAC,GAAG,eAAoB;IAOtF,OAAO,CAAC,kBAAkB;IAoC1B,OAAO,CAAC,eAAe;CAQxB"}
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.CostwiseAnthropic = void 0;
7
+ const sdk_1 = __importDefault(require("@anthropic-ai/sdk"));
8
+ const tracker_js_1 = require("./tracker.js");
9
+ class CostwiseAnthropic extends sdk_1.default {
10
+ tracker;
11
+ tag;
12
+ constructor(options = {}) {
13
+ super(options);
14
+ this.tracker = new tracker_js_1.CostwiseTracker(options);
15
+ this.tag = options.tag;
16
+ this.wrapMessagesCreate();
17
+ }
18
+ wrapMessagesCreate() {
19
+ const originalCreate = this.messages.create.bind(this.messages);
20
+ this.messages.create = (async (...args) => {
21
+ const response = await originalCreate(...args);
22
+ if (this.hasFinalMessage(response)) {
23
+ void response
24
+ .finalMessage()
25
+ .then((message) => {
26
+ this.tracker.trackUsage({
27
+ model: message.model,
28
+ inputTokens: message.usage?.input_tokens ?? 0,
29
+ outputTokens: message.usage?.output_tokens ?? 0,
30
+ tag: this.tag
31
+ });
32
+ })
33
+ .catch(() => { });
34
+ }
35
+ else {
36
+ const message = response;
37
+ this.tracker.trackUsage({
38
+ model: message.model,
39
+ inputTokens: message.usage?.input_tokens ?? 0,
40
+ outputTokens: message.usage?.output_tokens ?? 0,
41
+ tag: this.tag
42
+ });
43
+ }
44
+ return response;
45
+ });
46
+ }
47
+ hasFinalMessage(value) {
48
+ return (typeof value === "object" &&
49
+ value !== null &&
50
+ "finalMessage" in value &&
51
+ typeof value.finalMessage === "function");
52
+ }
53
+ }
54
+ exports.CostwiseAnthropic = CostwiseAnthropic;
55
+ //# sourceMappingURL=anthropic.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"anthropic.js","sourceRoot":"","sources":["../../../src/anthropic.ts"],"names":[],"mappings":";;;;;;AAAA,4DAA0C;AAE1C,6CAA+C;AAyB/C,MAAa,iBAAkB,SAAQ,aAAS;IAC7B,OAAO,CAAkB;IACzB,GAAG,CAAU;IAE9B,YAAY,UAAwE,EAAE;QACpF,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,OAAO,GAAG,IAAI,4BAAe,CAAC,OAAO,CAAC,CAAC;QAC5C,IAAI,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;QACvB,IAAI,CAAC,kBAAkB,EAAE,CAAC;IAC5B,CAAC;IAEO,kBAAkB;QACxB,MAAM,cAAc,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAoB,CAAC;QAEnF,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,KAAK,EAAE,GAAG,IAAiC,EAAE,EAAE;YACrE,MAAM,QAAQ,GAAG,MAAM,cAAc,CAAC,GAAG,IAAI,CAAC,CAAC;YAE/C,IAAI,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACnC,KAAK,QAAQ;qBACV,YAAY,EAAE;qBACd,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE;oBAChB,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC;wBACtB,KAAK,EAAE,OAAO,CAAC,KAAK;wBACpB,WAAW,EAAE,OAAO,CAAC,KAAK,EAAE,YAAY,IAAI,CAAC;wBAC7C,YAAY,EAAE,OAAO,CAAC,KAAK,EAAE,aAAa,IAAI,CAAC;wBAC/C,GAAG,EAAE,IAAI,CAAC,GAAG;qBACd,CAAC,CAAC;gBACL,CAAC,CAAC;qBACD,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;YACrB,CAAC;iBAAM,CAAC;gBACN,MAAM,OAAO,GAAG,QAGf,CAAC;gBAEF,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC;oBACtB,KAAK,EAAE,OAAO,CAAC,KAAK;oBACpB,WAAW,EAAE,OAAO,CAAC,KAAK,EAAE,YAAY,IAAI,CAAC;oBAC7C,YAAY,EAAE,OAAO,CAAC,KAAK,EAAE,aAAa,IAAI,CAAC;oBAC/C,GAAG,EAAE,IAAI,CAAC,GAAG;iBACd,CAAC,CAAC;YACL,CAAC;YAED,OAAO,QAAQ,CAAC;QAClB,CAAC,CAAoB,CAAC;IACxB,CAAC;IAEO,eAAe,CAAC,KAAc;QACpC,OAAO,CACL,OAAO,KAAK,KAAK,QAAQ;YACzB,KAAK,KAAK,IAAI;YACd,cAAc,IAAI,KAAK;YACvB,OAAQ,KAA6B,CAAC,YAAY,KAAK,UAAU,CAClE,CAAC;IACJ,CAAC;CACF;AAvDD,8CAuDC"}
@@ -0,0 +1,9 @@
1
+ import OpenAI from "openai";
2
+ import { CostwiseOptions } from "./types.js";
3
+ export declare class CostwiseOpenAI extends OpenAI {
4
+ private readonly tracker;
5
+ constructor(options?: ConstructorParameters<typeof OpenAI>[0] & CostwiseOptions);
6
+ private wrapChatCompletionsCreate;
7
+ private hasFinalChatCompletion;
8
+ }
9
+ //# sourceMappingURL=openai.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai.d.ts","sourceRoot":"","sources":["../../../src/openai.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAiB7C,qBAAa,cAAe,SAAQ,MAAM;IACxC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAkB;gBAE9B,OAAO,GAAE,qBAAqB,CAAC,OAAO,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,eAAoB;IAMnF,OAAO,CAAC,yBAAyB;IA6BjC,OAAO,CAAC,sBAAsB;CAQ/B"}
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.CostwiseOpenAI = void 0;
7
+ const openai_1 = __importDefault(require("openai"));
8
+ const tracker_js_1 = require("./tracker.js");
9
+ class CostwiseOpenAI extends openai_1.default {
10
+ tracker;
11
+ constructor(options = {}) {
12
+ super(options);
13
+ this.tracker = new tracker_js_1.CostwiseTracker(options);
14
+ this.wrapChatCompletionsCreate();
15
+ }
16
+ wrapChatCompletionsCreate() {
17
+ const originalCreate = this.chat.completions.create.bind(this.chat.completions);
18
+ this.chat.completions.create = (async (...args) => {
19
+ const response = await originalCreate(...args);
20
+ if (this.hasFinalChatCompletion(response)) {
21
+ void response
22
+ .finalChatCompletion()
23
+ .then((completion) => {
24
+ this.tracker.trackUsage({
25
+ model: completion.model,
26
+ inputTokens: completion.usage?.prompt_tokens ?? 0,
27
+ outputTokens: completion.usage?.completion_tokens ?? 0
28
+ });
29
+ })
30
+ .catch(() => { });
31
+ }
32
+ else {
33
+ const completion = response;
34
+ this.tracker.trackUsage({
35
+ model: completion.model,
36
+ inputTokens: completion.usage?.prompt_tokens ?? 0,
37
+ outputTokens: completion.usage?.completion_tokens ?? 0
38
+ });
39
+ }
40
+ return response;
41
+ });
42
+ }
43
+ hasFinalChatCompletion(value) {
44
+ return (typeof value === "object" &&
45
+ value !== null &&
46
+ "finalChatCompletion" in value &&
47
+ typeof value.finalChatCompletion === "function");
48
+ }
49
+ }
50
+ exports.CostwiseOpenAI = CostwiseOpenAI;
51
+ //# sourceMappingURL=openai.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai.js","sourceRoot":"","sources":["../../../src/openai.ts"],"names":[],"mappings":";;;;;;AAAA,oDAA4B;AAE5B,6CAA+C;AAgB/C,MAAa,cAAe,SAAQ,gBAAM;IACvB,OAAO,CAAkB;IAE1C,YAAY,UAAqE,EAAE;QACjF,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,OAAO,GAAG,IAAI,4BAAe,CAAC,OAAO,CAAC,CAAC;QAC5C,IAAI,CAAC,yBAAyB,EAAE,CAAC;IACnC,CAAC;IAEO,yBAAyB;QAC/B,MAAM,cAAc,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAqB,CAAC;QAEpG,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,KAAK,EAAE,GAAG,IAAkC,EAAE,EAAE;YAC9E,MAAM,QAAQ,GAAG,MAAM,cAAc,CAAC,GAAG,IAAI,CAAC,CAAC;YAE/C,IAAI,IAAI,CAAC,sBAAsB,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAC1C,KAAK,QAAQ;qBACV,mBAAmB,EAAE;qBACrB,IAAI,CAAC,CAAC,UAAU,EAAE,EAAE;oBACnB,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC;wBACtB,KAAK,EAAE,UAAU,CAAC,KAAK;wBACvB,WAAW,EAAE,UAAU,CAAC,KAAK,EAAE,aAAa,IAAI,CAAC;wBACjD,YAAY,EAAE,UAAU,CAAC,KAAK,EAAE,iBAAiB,IAAI,CAAC;qBACvD,CAAC,CAAC;gBACL,CAAC,CAAC;qBACD,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;YACrB,CAAC;iBAAM,CAAC;gBACN,MAAM,UAAU,GAAG,QAA4B,CAAC;gBAChD,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC;oBACtB,KAAK,EAAE,UAAU,CAAC,KAAK;oBACvB,WAAW,EAAE,UAAU,CAAC,KAAK,EAAE,aAAa,IAAI,CAAC;oBACjD,YAAY,EAAE,UAAU,CAAC,KAAK,EAAE,iBAAiB,IAAI,CAAC;iBACvD,CAAC,CAAC;YACL,CAAC;YACD,OAAO,QAAQ,CAAC;QAClB,CAAC,CAAqB,CAAC;IACzB,CAAC;IAEO,sBAAsB,CAAC,KAAc;QAC3C,OAAO,CACL,OAAO,KAAK,KAAK,QAAQ;YACzB,KAAK,KAAK,IAAI;YACd,qBAAqB,IAAI,KAAK;YAC9B,OAAQ,KAA0B,CAAC,mBAAmB,KAAK,UAAU,CACtE,CAAC;IACJ,CAAC;CACF;AA9CD,wCA8CC"}
@@ -0,0 +1,23 @@
1
+ import { CostwiseOptions, ModelCapacity, CliComparisonFormat, ModelComparison, ModelComparisonByCapacity, UsageSnapshot } from "./types.js";
2
+ type ModelRates = {
3
+ input: number;
4
+ output: number;
5
+ };
6
+ declare const PRICING: Record<string, ModelRates>;
7
+ declare const MODEL_CAPACITIES: Record<string, ModelCapacity>;
8
+ export declare class CostwiseTracker {
9
+ private readonly apiKey?;
10
+ private readonly tag?;
11
+ private readonly localUsagePath?;
12
+ constructor(options?: CostwiseOptions);
13
+ trackUsage(snapshot: UsageSnapshot): void;
14
+ compareCosts(snapshot: UsageSnapshot): ModelComparison[];
15
+ compareCostsByCapacity(snapshot: UsageSnapshot): ModelComparisonByCapacity;
16
+ summarizeComparison(snapshot: UsageSnapshot): string;
17
+ formatComparisonForCli(snapshot: UsageSnapshot): CliComparisonFormat;
18
+ private createPayload;
19
+ private estimateCost;
20
+ private calculateCost;
21
+ }
22
+ export { MODEL_CAPACITIES, PRICING };
23
+ //# sourceMappingURL=tracker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tracker.d.ts","sourceRoot":"","sources":["../../../src/tracker.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EAGf,aAAa,EAEb,mBAAmB,EACnB,eAAe,EACf,yBAAyB,EACzB,aAAa,EACd,MAAM,YAAY,CAAC;AAGpB,KAAK,UAAU,GAAG;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AA6BF,QAAA,MAAM,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAGvC,CAAC;AAEF,QAAA,MAAM,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAsBnD,CAAC;AAIF,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAS;IAC9B,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAS;gBAE7B,OAAO,GAAE,eAAoB;IAMzC,UAAU,CAAC,QAAQ,EAAE,aAAa,GAAG,IAAI;IA8BzC,YAAY,CAAC,QAAQ,EAAE,aAAa,GAAG,eAAe,EAAE;IAqBxD,sBAAsB,CAAC,QAAQ,EAAE,aAAa,GAAG,yBAAyB;IAgC1E,mBAAmB,CAAC,QAAQ,EAAE,aAAa,GAAG,MAAM;IAWpD,sBAAsB,CAAC,QAAQ,EAAE,aAAa,GAAG,mBAAmB;IA+BpE,OAAO,CAAC,aAAa;IAyBrB,OAAO,CAAC,YAAY;IAQpB,OAAO,CAAC,aAAa;CAKtB;AAED,OAAO,EAAE,gBAAgB,EAAE,OAAO,EAAE,CAAC"}