@costwise/sdk 0.0.1 → 0.0.2

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 (44) hide show
  1. package/README.md +149 -0
  2. package/dist/cjs/index.d.ts +5 -0
  3. package/dist/cjs/index.d.ts.map +1 -0
  4. package/dist/cjs/index.js +12 -0
  5. package/dist/cjs/index.js.map +1 -0
  6. package/dist/cjs/package.json +1 -0
  7. package/dist/cjs/src/anthropic.d.ts +10 -0
  8. package/dist/cjs/src/anthropic.d.ts.map +1 -0
  9. package/dist/cjs/src/anthropic.js +55 -0
  10. package/dist/cjs/src/anthropic.js.map +1 -0
  11. package/dist/cjs/src/openai.d.ts +9 -0
  12. package/dist/cjs/src/openai.d.ts.map +1 -0
  13. package/dist/cjs/src/openai.js +51 -0
  14. package/dist/cjs/src/openai.js.map +1 -0
  15. package/dist/cjs/src/tracker.d.ts +22 -0
  16. package/dist/cjs/src/tracker.d.ts.map +1 -0
  17. package/dist/cjs/src/tracker.js +196 -0
  18. package/dist/cjs/src/tracker.js.map +1 -0
  19. package/dist/cjs/src/types.d.ts +47 -0
  20. package/dist/cjs/src/types.d.ts.map +1 -0
  21. package/dist/cjs/src/types.js +3 -0
  22. package/dist/cjs/src/types.js.map +1 -0
  23. package/dist/esm/index.d.ts +5 -0
  24. package/dist/esm/index.d.ts.map +1 -0
  25. package/dist/esm/index.js +4 -0
  26. package/dist/esm/index.js.map +1 -0
  27. package/dist/esm/src/anthropic.d.ts +10 -0
  28. package/dist/esm/src/anthropic.d.ts.map +1 -0
  29. package/dist/esm/src/anthropic.js +48 -0
  30. package/dist/esm/src/anthropic.js.map +1 -0
  31. package/dist/esm/src/openai.d.ts +9 -0
  32. package/dist/esm/src/openai.d.ts.map +1 -0
  33. package/dist/esm/src/openai.js +44 -0
  34. package/dist/esm/src/openai.js.map +1 -0
  35. package/dist/esm/src/tracker.d.ts +22 -0
  36. package/dist/esm/src/tracker.d.ts.map +1 -0
  37. package/dist/esm/src/tracker.js +191 -0
  38. package/dist/esm/src/tracker.js.map +1 -0
  39. package/dist/esm/src/types.d.ts +47 -0
  40. package/dist/esm/src/types.d.ts.map +1 -0
  41. package/dist/esm/src/types.js +2 -0
  42. package/dist/esm/src/types.js.map +1 -0
  43. package/package.json +31 -2
  44. package/index.js +0 -3
package/README.md ADDED
@@ -0,0 +1,149 @@
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
+
54
+ ## Ingest payload
55
+
56
+ The SDK emits:
57
+
58
+ - `model`
59
+ - `input_tokens`
60
+ - `output_tokens`
61
+ - `cost` and `estimated_cost`
62
+ - `tag` and `endpoint_tag` (optional)
63
+ - `ts` and `timestamp`
64
+
65
+ ## Compare model costs and capacity
66
+
67
+ Use tracker utilities to estimate what other models would have cost for the same token usage:
68
+
69
+ ```ts
70
+ import { CostwiseTracker } from "@costwise/sdk";
71
+
72
+ const tracker = new CostwiseTracker({
73
+ costwiseKey: process.env.COSTWISE_API_KEY
74
+ });
75
+
76
+ const comparisons = tracker.compareCosts({
77
+ model: "gpt-4o",
78
+ inputTokens: 12000,
79
+ outputTokens: 2500
80
+ });
81
+
82
+ const summary = tracker.summarizeComparison({
83
+ model: "gpt-4o",
84
+ inputTokens: 12000,
85
+ outputTokens: 2500
86
+ });
87
+ ```
88
+
89
+ `compareCosts()` returns each model's estimated cost and capacity metadata (context window and capacity class), sorted cheapest-first.
90
+
91
+ Group by capacity tier and read the cheapest model per tier:
92
+
93
+ ```ts
94
+ const { byClass, cheapestPerClass } = tracker.compareCostsByCapacity({
95
+ model: "gpt-4o",
96
+ inputTokens: 12000,
97
+ outputTokens: 2500
98
+ });
99
+
100
+ // e.g. cheapestPerClass.mini?.model, cheapestPerClass.high?.estimatedCost
101
+ ```
102
+
103
+ `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.
104
+
105
+ Format a ready-to-print CLI summary (without logging inside the SDK):
106
+
107
+ ```ts
108
+ const cli = tracker.formatComparisonForCli({
109
+ model: "gpt-4o",
110
+ inputTokens: 12000,
111
+ outputTokens: 2500
112
+ });
113
+
114
+ // App decides if/where to print:
115
+ // console.log(cli.text)
116
+ ```
117
+
118
+ ## Smoke test
119
+
120
+ Run a local end-to-end smoke test (build + mocked ingest + comparison output):
121
+
122
+ ```bash
123
+ npm run smoke
124
+ ```
125
+
126
+ ## Automated tests
127
+
128
+ Run the Node test suite (build + unit tests):
129
+
130
+ ```bash
131
+ npm test
132
+ ```
133
+
134
+ Current test coverage includes:
135
+
136
+ - Tracker cost math correctness for known models
137
+ - Unknown model handling (no ingest + empty comparison)
138
+ - Fire-and-forget tracking behavior (`fetch` not awaited)
139
+ - Silent ingest failure handling (`.catch(() => {})`)
140
+ - `compareCostsByCapacity()` output shape
141
+ - `formatComparisonForCli()` output shape
142
+ - OpenAI wrapper behavior:
143
+ - non-stream response returned untouched
144
+ - stream response returned untouched
145
+ - stream tracking via `finalChatCompletion()`
146
+ - Anthropic wrapper behavior:
147
+ - non-stream response returned untouched
148
+ - stream response returned untouched
149
+ - stream tracking via `finalMessage()`
@@ -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, 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,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,22 @@
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
+ constructor(options?: CostwiseOptions);
12
+ trackUsage(snapshot: UsageSnapshot): void;
13
+ compareCosts(snapshot: UsageSnapshot): ModelComparison[];
14
+ compareCostsByCapacity(snapshot: UsageSnapshot): ModelComparisonByCapacity;
15
+ summarizeComparison(snapshot: UsageSnapshot): string;
16
+ formatComparisonForCli(snapshot: UsageSnapshot): CliComparisonFormat;
17
+ private createPayload;
18
+ private estimateCost;
19
+ private calculateCost;
20
+ }
21
+ export { MODEL_CAPACITIES, PRICING };
22
+ //# 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,EAEf,aAAa,EAEb,mBAAmB,EACnB,eAAe,EACf,yBAAyB,EACzB,aAAa,EACd,MAAM,YAAY,CAAC;AAEpB,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;gBAElB,OAAO,GAAE,eAAoB;IAKzC,UAAU,CAAC,QAAQ,EAAE,aAAa,GAAG,IAAI;IAgBzC,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"}
@@ -0,0 +1,196 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PRICING = exports.MODEL_CAPACITIES = exports.CostwiseTracker = void 0;
4
+ const OPENAI_PRICING = {
5
+ "gpt-5.4": { input: 2.5, output: 15 },
6
+ "gpt-5.4-mini": { input: 0.75, output: 4.5 },
7
+ "gpt-5.4-nano": { input: 0.2, output: 1.25 },
8
+ "gpt-5.4-pro": { input: 30, output: 180 },
9
+ "gpt-5.2": { input: 1.75, output: 14 },
10
+ "gpt-5.2-pro": { input: 21, output: 168 },
11
+ "o1": { input: 15, output: 60 },
12
+ "o1-pro": { input: 150, output: 600 },
13
+ "o3-mini": { input: 1.1, output: 4.4 },
14
+ "gpt-4o": { input: 2.5, output: 10 },
15
+ "gpt-4o-mini": { input: 0.15, output: 0.6 }
16
+ };
17
+ const ANTHROPIC_PRICING = {
18
+ "claude-opus-4.6": { input: 5, output: 25 },
19
+ "claude-opus-4.5": { input: 5, output: 25 },
20
+ "claude-opus-4.1": { input: 15, output: 75 },
21
+ "claude-opus-4": { input: 15, output: 75 },
22
+ "claude-sonnet-4.6": { input: 3, output: 15 },
23
+ "claude-sonnet-4.5": { input: 3, output: 15 },
24
+ "claude-sonnet-4": { input: 3, output: 15 },
25
+ "claude-haiku-4.5": { input: 1, output: 5 },
26
+ "claude-haiku-3.5": { input: 0.8, output: 4 },
27
+ "claude-haiku-3": { input: 0.25, output: 1.25 }
28
+ };
29
+ const PRICING = {
30
+ ...OPENAI_PRICING,
31
+ ...ANTHROPIC_PRICING
32
+ };
33
+ exports.PRICING = PRICING;
34
+ const MODEL_CAPACITIES = {
35
+ "gpt-5.4": { contextWindowTokens: 270_000, capacityClass: "frontier" },
36
+ "gpt-5.4-mini": { contextWindowTokens: 270_000, capacityClass: "high" },
37
+ "gpt-5.4-nano": { contextWindowTokens: 270_000, capacityClass: "nano" },
38
+ "gpt-5.4-pro": { contextWindowTokens: 270_000, capacityClass: "frontier" },
39
+ "gpt-5.2": { contextWindowTokens: 270_000, capacityClass: "high" },
40
+ "gpt-5.2-pro": { contextWindowTokens: 270_000, capacityClass: "frontier" },
41
+ o1: { capacityClass: "frontier" },
42
+ "o1-pro": { capacityClass: "frontier" },
43
+ "o3-mini": { capacityClass: "mini" },
44
+ "gpt-4o": { capacityClass: "high" },
45
+ "gpt-4o-mini": { capacityClass: "mini" },
46
+ "claude-opus-4.6": { contextWindowTokens: 1_000_000, capacityClass: "frontier" },
47
+ "claude-opus-4.5": { contextWindowTokens: 200_000, capacityClass: "frontier" },
48
+ "claude-opus-4.1": { contextWindowTokens: 200_000, capacityClass: "frontier" },
49
+ "claude-opus-4": { contextWindowTokens: 200_000, capacityClass: "frontier" },
50
+ "claude-sonnet-4.6": { contextWindowTokens: 1_000_000, capacityClass: "high" },
51
+ "claude-sonnet-4.5": { contextWindowTokens: 1_000_000, capacityClass: "high" },
52
+ "claude-sonnet-4": { contextWindowTokens: 1_000_000, capacityClass: "high" },
53
+ "claude-haiku-4.5": { contextWindowTokens: 200_000, capacityClass: "mini" },
54
+ "claude-haiku-3.5": { contextWindowTokens: 200_000, capacityClass: "mini" },
55
+ "claude-haiku-3": { contextWindowTokens: 200_000, capacityClass: "mini" }
56
+ };
57
+ exports.MODEL_CAPACITIES = MODEL_CAPACITIES;
58
+ const INGEST_URL = "https://api.costwise.dev/ingest";
59
+ class CostwiseTracker {
60
+ apiKey;
61
+ tag;
62
+ constructor(options = {}) {
63
+ this.apiKey = options.costwiseKey ?? options.costswiseKey ?? options.apiKey ?? process.env.COSTWISE_API_KEY;
64
+ this.tag = options.tag;
65
+ }
66
+ trackUsage(snapshot) {
67
+ const payload = this.createPayload(snapshot);
68
+ if (!payload || !this.apiKey) {
69
+ return;
70
+ }
71
+ void fetch(INGEST_URL, {
72
+ method: "POST",
73
+ headers: {
74
+ "content-type": "application/json",
75
+ authorization: `Bearer ${this.apiKey}`
76
+ },
77
+ body: JSON.stringify(payload)
78
+ }).catch(() => { });
79
+ }
80
+ compareCosts(snapshot) {
81
+ const currentCost = this.estimateCost(snapshot.model, snapshot.inputTokens, snapshot.outputTokens);
82
+ if (currentCost === null) {
83
+ return [];
84
+ }
85
+ return Object.entries(PRICING)
86
+ .map(([model, rates]) => {
87
+ const estimatedCost = this.calculateCost(snapshot.inputTokens, snapshot.outputTokens, rates);
88
+ return {
89
+ model,
90
+ inputRatePerMTok: rates.input,
91
+ outputRatePerMTok: rates.output,
92
+ estimatedCost,
93
+ deltaFromCurrentCost: estimatedCost - currentCost,
94
+ capacity: MODEL_CAPACITIES[model] ?? { capacityClass: "standard" }
95
+ };
96
+ })
97
+ .sort((a, b) => a.estimatedCost - b.estimatedCost);
98
+ }
99
+ compareCostsByCapacity(snapshot) {
100
+ const all = this.compareCosts(snapshot);
101
+ if (all.length === 0) {
102
+ return { byClass: {}, cheapestPerClass: {} };
103
+ }
104
+ const byClass = {};
105
+ for (const c of all) {
106
+ const cls = c.capacity.capacityClass;
107
+ const list = byClass[cls] ?? [];
108
+ list.push(c);
109
+ byClass[cls] = list;
110
+ }
111
+ for (const cls of Object.keys(byClass)) {
112
+ const list = byClass[cls];
113
+ if (list) {
114
+ list.sort((a, b) => a.estimatedCost - b.estimatedCost);
115
+ }
116
+ }
117
+ const cheapestPerClass = {};
118
+ for (const cls of Object.keys(byClass)) {
119
+ const list = byClass[cls];
120
+ if (list?.[0]) {
121
+ cheapestPerClass[cls] = list[0];
122
+ }
123
+ }
124
+ return { byClass, cheapestPerClass };
125
+ }
126
+ summarizeComparison(snapshot) {
127
+ const comparisons = this.compareCosts(snapshot);
128
+ if (comparisons.length === 0) {
129
+ return `No pricing entry found for model ${snapshot.model}.`;
130
+ }
131
+ const cheapest = comparisons[0];
132
+ const priciest = comparisons[comparisons.length - 1];
133
+ return `For ${snapshot.inputTokens} input + ${snapshot.outputTokens} output tokens, cheapest is ${cheapest.model} ($${cheapest.estimatedCost.toFixed(6)}), priciest is ${priciest.model} ($${priciest.estimatedCost.toFixed(6)}).`;
134
+ }
135
+ formatComparisonForCli(snapshot) {
136
+ const comparisons = this.compareCosts(snapshot);
137
+ if (comparisons.length === 0) {
138
+ const text = `Costwise: no pricing entry found for model ${snapshot.model}.`;
139
+ return { text, lines: [text] };
140
+ }
141
+ const byCapacity = this.compareCostsByCapacity(snapshot);
142
+ const cheapest = comparisons[0];
143
+ const current = comparisons.find((c) => c.model === snapshot.model) ?? null;
144
+ const delta = current ? current.estimatedCost - cheapest.estimatedCost : 0;
145
+ const lines = [
146
+ `Costwise comparison for ${snapshot.model}`,
147
+ `Usage: ${snapshot.inputTokens} input / ${snapshot.outputTokens} output tokens`,
148
+ `Current model cost: $${(current?.estimatedCost ?? 0).toFixed(6)}`,
149
+ `Cheapest overall: ${cheapest.model} ($${cheapest.estimatedCost.toFixed(6)})`,
150
+ `Potential savings: $${Math.max(0, delta).toFixed(6)}`
151
+ ];
152
+ const classes = ["nano", "mini", "standard", "high", "frontier"];
153
+ for (const cls of classes) {
154
+ const best = byCapacity.cheapestPerClass[cls];
155
+ if (best) {
156
+ lines.push(`Best ${cls}: ${best.model} ($${best.estimatedCost.toFixed(6)})`);
157
+ }
158
+ }
159
+ return { text: lines.join("\n"), lines };
160
+ }
161
+ createPayload(snapshot) {
162
+ const cost = this.estimateCost(snapshot.model, snapshot.inputTokens, snapshot.outputTokens);
163
+ if (cost === null) {
164
+ return null;
165
+ }
166
+ const input_tokens = Math.max(0, snapshot.inputTokens || 0);
167
+ const output_tokens = Math.max(0, snapshot.outputTokens || 0);
168
+ const tag = snapshot.tag ?? this.tag;
169
+ const timestamp = new Date().toISOString();
170
+ return {
171
+ model: snapshot.model,
172
+ input_tokens,
173
+ output_tokens,
174
+ cost,
175
+ estimated_cost: cost,
176
+ tag,
177
+ endpoint_tag: tag,
178
+ ts: timestamp,
179
+ timestamp
180
+ };
181
+ }
182
+ estimateCost(model, inputTokens, outputTokens) {
183
+ const rates = PRICING[model];
184
+ if (!rates) {
185
+ return null;
186
+ }
187
+ return this.calculateCost(inputTokens, outputTokens, rates);
188
+ }
189
+ calculateCost(inputTokens, outputTokens, rates) {
190
+ const input = Math.max(0, inputTokens || 0);
191
+ const output = Math.max(0, outputTokens || 0);
192
+ return (input / 1_000_000) * rates.input + (output / 1_000_000) * rates.output;
193
+ }
194
+ }
195
+ exports.CostwiseTracker = CostwiseTracker;
196
+ //# sourceMappingURL=tracker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tracker.js","sourceRoot":"","sources":["../../../src/tracker.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,47 @@
1
+ export type CostwiseOptions = {
2
+ apiKey?: string;
3
+ costwiseKey?: string;
4
+ costswiseKey?: string;
5
+ tag?: string;
6
+ };
7
+ export type IngestPayload = {
8
+ model: string;
9
+ input_tokens: number;
10
+ output_tokens: number;
11
+ cost: number;
12
+ estimated_cost: number;
13
+ tag?: string;
14
+ endpoint_tag?: string;
15
+ ts: string;
16
+ timestamp: string;
17
+ };
18
+ export type UsageSnapshot = {
19
+ model: string;
20
+ inputTokens: number;
21
+ outputTokens: number;
22
+ tag?: string;
23
+ };
24
+ export type ModelCapacity = {
25
+ contextWindowTokens?: number;
26
+ outputLimitTokens?: number;
27
+ capacityClass: "nano" | "mini" | "standard" | "high" | "frontier";
28
+ };
29
+ export type ModelComparison = {
30
+ model: string;
31
+ inputRatePerMTok: number;
32
+ outputRatePerMTok: number;
33
+ estimatedCost: number;
34
+ deltaFromCurrentCost: number;
35
+ capacity: ModelCapacity;
36
+ };
37
+ export type ModelCapacityClass = ModelCapacity["capacityClass"];
38
+ /** Grouped comparisons: each class lists models cheapest-first; cheapestPerClass picks one model per class. */
39
+ export type ModelComparisonByCapacity = {
40
+ byClass: Partial<Record<ModelCapacityClass, ModelComparison[]>>;
41
+ cheapestPerClass: Partial<Record<ModelCapacityClass, ModelComparison>>;
42
+ };
43
+ export type CliComparisonFormat = {
44
+ text: string;
45
+ lines: string[];
46
+ };
47
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,eAAe,GAAG;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,cAAc,EAAE,MAAM,CAAC;IACvB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,aAAa,EAAE,MAAM,GAAG,MAAM,GAAG,UAAU,GAAG,MAAM,GAAG,UAAU,CAAC;CACnE,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,gBAAgB,EAAE,MAAM,CAAC;IACzB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,aAAa,EAAE,MAAM,CAAC;IACtB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,QAAQ,EAAE,aAAa,CAAC;CACzB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG,aAAa,CAAC,eAAe,CAAC,CAAC;AAEhE,+GAA+G;AAC/G,MAAM,MAAM,yBAAyB,GAAG;IACtC,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,kBAAkB,EAAE,eAAe,EAAE,CAAC,CAAC,CAAC;IAChE,gBAAgB,EAAE,OAAO,CAAC,MAAM,CAAC,kBAAkB,EAAE,eAAe,CAAC,CAAC,CAAC;CACxE,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB,CAAC"}
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/types.ts"],"names":[],"mappings":""}
@@ -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, 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,aAAa,EACb,kBAAkB,EAClB,eAAe,EACf,yBAAyB,EAC1B,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,4 @@
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
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","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"}
@@ -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,48 @@
1
+ import Anthropic from "@anthropic-ai/sdk";
2
+ import { CostwiseTracker } from "./tracker.js";
3
+ export class CostwiseAnthropic extends Anthropic {
4
+ tracker;
5
+ tag;
6
+ constructor(options = {}) {
7
+ super(options);
8
+ this.tracker = new CostwiseTracker(options);
9
+ this.tag = options.tag;
10
+ this.wrapMessagesCreate();
11
+ }
12
+ wrapMessagesCreate() {
13
+ const originalCreate = this.messages.create.bind(this.messages);
14
+ this.messages.create = (async (...args) => {
15
+ const response = await originalCreate(...args);
16
+ if (this.hasFinalMessage(response)) {
17
+ void response
18
+ .finalMessage()
19
+ .then((message) => {
20
+ this.tracker.trackUsage({
21
+ model: message.model,
22
+ inputTokens: message.usage?.input_tokens ?? 0,
23
+ outputTokens: message.usage?.output_tokens ?? 0,
24
+ tag: this.tag
25
+ });
26
+ })
27
+ .catch(() => { });
28
+ }
29
+ else {
30
+ const message = response;
31
+ this.tracker.trackUsage({
32
+ model: message.model,
33
+ inputTokens: message.usage?.input_tokens ?? 0,
34
+ outputTokens: message.usage?.output_tokens ?? 0,
35
+ tag: this.tag
36
+ });
37
+ }
38
+ return response;
39
+ });
40
+ }
41
+ hasFinalMessage(value) {
42
+ return (typeof value === "object" &&
43
+ value !== null &&
44
+ "finalMessage" in value &&
45
+ typeof value.finalMessage === "function");
46
+ }
47
+ }
48
+ //# sourceMappingURL=anthropic.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"anthropic.js","sourceRoot":"","sources":["../../../src/anthropic.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,mBAAmB,CAAC;AAE1C,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAyB/C,MAAM,OAAO,iBAAkB,SAAQ,SAAS;IAC7B,OAAO,CAAkB;IACzB,GAAG,CAAU;IAE9B,YAAY,UAAwE,EAAE;QACpF,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,OAAO,GAAG,IAAI,eAAe,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"}
@@ -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,44 @@
1
+ import OpenAI from "openai";
2
+ import { CostwiseTracker } from "./tracker.js";
3
+ export class CostwiseOpenAI extends OpenAI {
4
+ tracker;
5
+ constructor(options = {}) {
6
+ super(options);
7
+ this.tracker = new CostwiseTracker(options);
8
+ this.wrapChatCompletionsCreate();
9
+ }
10
+ wrapChatCompletionsCreate() {
11
+ const originalCreate = this.chat.completions.create.bind(this.chat.completions);
12
+ this.chat.completions.create = (async (...args) => {
13
+ const response = await originalCreate(...args);
14
+ if (this.hasFinalChatCompletion(response)) {
15
+ void response
16
+ .finalChatCompletion()
17
+ .then((completion) => {
18
+ this.tracker.trackUsage({
19
+ model: completion.model,
20
+ inputTokens: completion.usage?.prompt_tokens ?? 0,
21
+ outputTokens: completion.usage?.completion_tokens ?? 0
22
+ });
23
+ })
24
+ .catch(() => { });
25
+ }
26
+ else {
27
+ const completion = response;
28
+ this.tracker.trackUsage({
29
+ model: completion.model,
30
+ inputTokens: completion.usage?.prompt_tokens ?? 0,
31
+ outputTokens: completion.usage?.completion_tokens ?? 0
32
+ });
33
+ }
34
+ return response;
35
+ });
36
+ }
37
+ hasFinalChatCompletion(value) {
38
+ return (typeof value === "object" &&
39
+ value !== null &&
40
+ "finalChatCompletion" in value &&
41
+ typeof value.finalChatCompletion === "function");
42
+ }
43
+ }
44
+ //# sourceMappingURL=openai.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai.js","sourceRoot":"","sources":["../../../src/openai.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAE5B,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAgB/C,MAAM,OAAO,cAAe,SAAQ,MAAM;IACvB,OAAO,CAAkB;IAE1C,YAAY,UAAqE,EAAE;QACjF,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,OAAO,GAAG,IAAI,eAAe,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"}
@@ -0,0 +1,22 @@
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
+ constructor(options?: CostwiseOptions);
12
+ trackUsage(snapshot: UsageSnapshot): void;
13
+ compareCosts(snapshot: UsageSnapshot): ModelComparison[];
14
+ compareCostsByCapacity(snapshot: UsageSnapshot): ModelComparisonByCapacity;
15
+ summarizeComparison(snapshot: UsageSnapshot): string;
16
+ formatComparisonForCli(snapshot: UsageSnapshot): CliComparisonFormat;
17
+ private createPayload;
18
+ private estimateCost;
19
+ private calculateCost;
20
+ }
21
+ export { MODEL_CAPACITIES, PRICING };
22
+ //# 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,EAEf,aAAa,EAEb,mBAAmB,EACnB,eAAe,EACf,yBAAyB,EACzB,aAAa,EACd,MAAM,YAAY,CAAC;AAEpB,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;gBAElB,OAAO,GAAE,eAAoB;IAKzC,UAAU,CAAC,QAAQ,EAAE,aAAa,GAAG,IAAI;IAgBzC,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"}
@@ -0,0 +1,191 @@
1
+ const OPENAI_PRICING = {
2
+ "gpt-5.4": { input: 2.5, output: 15 },
3
+ "gpt-5.4-mini": { input: 0.75, output: 4.5 },
4
+ "gpt-5.4-nano": { input: 0.2, output: 1.25 },
5
+ "gpt-5.4-pro": { input: 30, output: 180 },
6
+ "gpt-5.2": { input: 1.75, output: 14 },
7
+ "gpt-5.2-pro": { input: 21, output: 168 },
8
+ "o1": { input: 15, output: 60 },
9
+ "o1-pro": { input: 150, output: 600 },
10
+ "o3-mini": { input: 1.1, output: 4.4 },
11
+ "gpt-4o": { input: 2.5, output: 10 },
12
+ "gpt-4o-mini": { input: 0.15, output: 0.6 }
13
+ };
14
+ const ANTHROPIC_PRICING = {
15
+ "claude-opus-4.6": { input: 5, output: 25 },
16
+ "claude-opus-4.5": { input: 5, output: 25 },
17
+ "claude-opus-4.1": { input: 15, output: 75 },
18
+ "claude-opus-4": { input: 15, output: 75 },
19
+ "claude-sonnet-4.6": { input: 3, output: 15 },
20
+ "claude-sonnet-4.5": { input: 3, output: 15 },
21
+ "claude-sonnet-4": { input: 3, output: 15 },
22
+ "claude-haiku-4.5": { input: 1, output: 5 },
23
+ "claude-haiku-3.5": { input: 0.8, output: 4 },
24
+ "claude-haiku-3": { input: 0.25, output: 1.25 }
25
+ };
26
+ const PRICING = {
27
+ ...OPENAI_PRICING,
28
+ ...ANTHROPIC_PRICING
29
+ };
30
+ const MODEL_CAPACITIES = {
31
+ "gpt-5.4": { contextWindowTokens: 270_000, capacityClass: "frontier" },
32
+ "gpt-5.4-mini": { contextWindowTokens: 270_000, capacityClass: "high" },
33
+ "gpt-5.4-nano": { contextWindowTokens: 270_000, capacityClass: "nano" },
34
+ "gpt-5.4-pro": { contextWindowTokens: 270_000, capacityClass: "frontier" },
35
+ "gpt-5.2": { contextWindowTokens: 270_000, capacityClass: "high" },
36
+ "gpt-5.2-pro": { contextWindowTokens: 270_000, capacityClass: "frontier" },
37
+ o1: { capacityClass: "frontier" },
38
+ "o1-pro": { capacityClass: "frontier" },
39
+ "o3-mini": { capacityClass: "mini" },
40
+ "gpt-4o": { capacityClass: "high" },
41
+ "gpt-4o-mini": { capacityClass: "mini" },
42
+ "claude-opus-4.6": { contextWindowTokens: 1_000_000, capacityClass: "frontier" },
43
+ "claude-opus-4.5": { contextWindowTokens: 200_000, capacityClass: "frontier" },
44
+ "claude-opus-4.1": { contextWindowTokens: 200_000, capacityClass: "frontier" },
45
+ "claude-opus-4": { contextWindowTokens: 200_000, capacityClass: "frontier" },
46
+ "claude-sonnet-4.6": { contextWindowTokens: 1_000_000, capacityClass: "high" },
47
+ "claude-sonnet-4.5": { contextWindowTokens: 1_000_000, capacityClass: "high" },
48
+ "claude-sonnet-4": { contextWindowTokens: 1_000_000, capacityClass: "high" },
49
+ "claude-haiku-4.5": { contextWindowTokens: 200_000, capacityClass: "mini" },
50
+ "claude-haiku-3.5": { contextWindowTokens: 200_000, capacityClass: "mini" },
51
+ "claude-haiku-3": { contextWindowTokens: 200_000, capacityClass: "mini" }
52
+ };
53
+ const INGEST_URL = "https://api.costwise.dev/ingest";
54
+ export class CostwiseTracker {
55
+ apiKey;
56
+ tag;
57
+ constructor(options = {}) {
58
+ this.apiKey = options.costwiseKey ?? options.costswiseKey ?? options.apiKey ?? process.env.COSTWISE_API_KEY;
59
+ this.tag = options.tag;
60
+ }
61
+ trackUsage(snapshot) {
62
+ const payload = this.createPayload(snapshot);
63
+ if (!payload || !this.apiKey) {
64
+ return;
65
+ }
66
+ void fetch(INGEST_URL, {
67
+ method: "POST",
68
+ headers: {
69
+ "content-type": "application/json",
70
+ authorization: `Bearer ${this.apiKey}`
71
+ },
72
+ body: JSON.stringify(payload)
73
+ }).catch(() => { });
74
+ }
75
+ compareCosts(snapshot) {
76
+ const currentCost = this.estimateCost(snapshot.model, snapshot.inputTokens, snapshot.outputTokens);
77
+ if (currentCost === null) {
78
+ return [];
79
+ }
80
+ return Object.entries(PRICING)
81
+ .map(([model, rates]) => {
82
+ const estimatedCost = this.calculateCost(snapshot.inputTokens, snapshot.outputTokens, rates);
83
+ return {
84
+ model,
85
+ inputRatePerMTok: rates.input,
86
+ outputRatePerMTok: rates.output,
87
+ estimatedCost,
88
+ deltaFromCurrentCost: estimatedCost - currentCost,
89
+ capacity: MODEL_CAPACITIES[model] ?? { capacityClass: "standard" }
90
+ };
91
+ })
92
+ .sort((a, b) => a.estimatedCost - b.estimatedCost);
93
+ }
94
+ compareCostsByCapacity(snapshot) {
95
+ const all = this.compareCosts(snapshot);
96
+ if (all.length === 0) {
97
+ return { byClass: {}, cheapestPerClass: {} };
98
+ }
99
+ const byClass = {};
100
+ for (const c of all) {
101
+ const cls = c.capacity.capacityClass;
102
+ const list = byClass[cls] ?? [];
103
+ list.push(c);
104
+ byClass[cls] = list;
105
+ }
106
+ for (const cls of Object.keys(byClass)) {
107
+ const list = byClass[cls];
108
+ if (list) {
109
+ list.sort((a, b) => a.estimatedCost - b.estimatedCost);
110
+ }
111
+ }
112
+ const cheapestPerClass = {};
113
+ for (const cls of Object.keys(byClass)) {
114
+ const list = byClass[cls];
115
+ if (list?.[0]) {
116
+ cheapestPerClass[cls] = list[0];
117
+ }
118
+ }
119
+ return { byClass, cheapestPerClass };
120
+ }
121
+ summarizeComparison(snapshot) {
122
+ const comparisons = this.compareCosts(snapshot);
123
+ if (comparisons.length === 0) {
124
+ return `No pricing entry found for model ${snapshot.model}.`;
125
+ }
126
+ const cheapest = comparisons[0];
127
+ const priciest = comparisons[comparisons.length - 1];
128
+ return `For ${snapshot.inputTokens} input + ${snapshot.outputTokens} output tokens, cheapest is ${cheapest.model} ($${cheapest.estimatedCost.toFixed(6)}), priciest is ${priciest.model} ($${priciest.estimatedCost.toFixed(6)}).`;
129
+ }
130
+ formatComparisonForCli(snapshot) {
131
+ const comparisons = this.compareCosts(snapshot);
132
+ if (comparisons.length === 0) {
133
+ const text = `Costwise: no pricing entry found for model ${snapshot.model}.`;
134
+ return { text, lines: [text] };
135
+ }
136
+ const byCapacity = this.compareCostsByCapacity(snapshot);
137
+ const cheapest = comparisons[0];
138
+ const current = comparisons.find((c) => c.model === snapshot.model) ?? null;
139
+ const delta = current ? current.estimatedCost - cheapest.estimatedCost : 0;
140
+ const lines = [
141
+ `Costwise comparison for ${snapshot.model}`,
142
+ `Usage: ${snapshot.inputTokens} input / ${snapshot.outputTokens} output tokens`,
143
+ `Current model cost: $${(current?.estimatedCost ?? 0).toFixed(6)}`,
144
+ `Cheapest overall: ${cheapest.model} ($${cheapest.estimatedCost.toFixed(6)})`,
145
+ `Potential savings: $${Math.max(0, delta).toFixed(6)}`
146
+ ];
147
+ const classes = ["nano", "mini", "standard", "high", "frontier"];
148
+ for (const cls of classes) {
149
+ const best = byCapacity.cheapestPerClass[cls];
150
+ if (best) {
151
+ lines.push(`Best ${cls}: ${best.model} ($${best.estimatedCost.toFixed(6)})`);
152
+ }
153
+ }
154
+ return { text: lines.join("\n"), lines };
155
+ }
156
+ createPayload(snapshot) {
157
+ const cost = this.estimateCost(snapshot.model, snapshot.inputTokens, snapshot.outputTokens);
158
+ if (cost === null) {
159
+ return null;
160
+ }
161
+ const input_tokens = Math.max(0, snapshot.inputTokens || 0);
162
+ const output_tokens = Math.max(0, snapshot.outputTokens || 0);
163
+ const tag = snapshot.tag ?? this.tag;
164
+ const timestamp = new Date().toISOString();
165
+ return {
166
+ model: snapshot.model,
167
+ input_tokens,
168
+ output_tokens,
169
+ cost,
170
+ estimated_cost: cost,
171
+ tag,
172
+ endpoint_tag: tag,
173
+ ts: timestamp,
174
+ timestamp
175
+ };
176
+ }
177
+ estimateCost(model, inputTokens, outputTokens) {
178
+ const rates = PRICING[model];
179
+ if (!rates) {
180
+ return null;
181
+ }
182
+ return this.calculateCost(inputTokens, outputTokens, rates);
183
+ }
184
+ calculateCost(inputTokens, outputTokens, rates) {
185
+ const input = Math.max(0, inputTokens || 0);
186
+ const output = Math.max(0, outputTokens || 0);
187
+ return (input / 1_000_000) * rates.input + (output / 1_000_000) * rates.output;
188
+ }
189
+ }
190
+ export { MODEL_CAPACITIES, PRICING };
191
+ //# sourceMappingURL=tracker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tracker.js","sourceRoot":"","sources":["../../../src/tracker.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,47 @@
1
+ export type CostwiseOptions = {
2
+ apiKey?: string;
3
+ costwiseKey?: string;
4
+ costswiseKey?: string;
5
+ tag?: string;
6
+ };
7
+ export type IngestPayload = {
8
+ model: string;
9
+ input_tokens: number;
10
+ output_tokens: number;
11
+ cost: number;
12
+ estimated_cost: number;
13
+ tag?: string;
14
+ endpoint_tag?: string;
15
+ ts: string;
16
+ timestamp: string;
17
+ };
18
+ export type UsageSnapshot = {
19
+ model: string;
20
+ inputTokens: number;
21
+ outputTokens: number;
22
+ tag?: string;
23
+ };
24
+ export type ModelCapacity = {
25
+ contextWindowTokens?: number;
26
+ outputLimitTokens?: number;
27
+ capacityClass: "nano" | "mini" | "standard" | "high" | "frontier";
28
+ };
29
+ export type ModelComparison = {
30
+ model: string;
31
+ inputRatePerMTok: number;
32
+ outputRatePerMTok: number;
33
+ estimatedCost: number;
34
+ deltaFromCurrentCost: number;
35
+ capacity: ModelCapacity;
36
+ };
37
+ export type ModelCapacityClass = ModelCapacity["capacityClass"];
38
+ /** Grouped comparisons: each class lists models cheapest-first; cheapestPerClass picks one model per class. */
39
+ export type ModelComparisonByCapacity = {
40
+ byClass: Partial<Record<ModelCapacityClass, ModelComparison[]>>;
41
+ cheapestPerClass: Partial<Record<ModelCapacityClass, ModelComparison>>;
42
+ };
43
+ export type CliComparisonFormat = {
44
+ text: string;
45
+ lines: string[];
46
+ };
47
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,eAAe,GAAG;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,cAAc,EAAE,MAAM,CAAC;IACvB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,aAAa,EAAE,MAAM,GAAG,MAAM,GAAG,UAAU,GAAG,MAAM,GAAG,UAAU,CAAC;CACnE,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,gBAAgB,EAAE,MAAM,CAAC;IACzB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,aAAa,EAAE,MAAM,CAAC;IACtB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,QAAQ,EAAE,aAAa,CAAC;CACzB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG,aAAa,CAAC,eAAe,CAAC,CAAC;AAEhE,+GAA+G;AAC/G,MAAM,MAAM,yBAAyB,GAAG;IACtC,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,kBAAkB,EAAE,eAAe,EAAE,CAAC,CAAC,CAAC;IAChE,gBAAgB,EAAE,OAAO,CAAC,MAAM,CAAC,kBAAkB,EAAE,eAAe,CAAC,CAAC,CAAC;CACxE,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/types.ts"],"names":[],"mappings":""}
package/package.json CHANGED
@@ -1,9 +1,38 @@
1
1
  {
2
2
  "name": "@costwise/sdk",
3
- "version": "0.0.1",
3
+ "version": "0.0.2",
4
4
  "description": "AI API cost tracking for developers",
5
- "main": "index.js",
6
5
  "license": "MIT",
6
+ "type": "module",
7
+ "main": "./dist/cjs/index.js",
8
+ "module": "./dist/esm/index.js",
9
+ "types": "./dist/esm/index.d.ts",
10
+ "exports": {
11
+ ".": {
12
+ "types": "./dist/esm/index.d.ts",
13
+ "import": "./dist/esm/index.js",
14
+ "require": "./dist/cjs/index.js"
15
+ }
16
+ },
17
+ "files": [
18
+ "dist",
19
+ "README.md"
20
+ ],
21
+ "scripts": {
22
+ "build": "npm run build:esm && npm run build:cjs",
23
+ "build:esm": "tsc -p tsconfig.esm.json",
24
+ "build:cjs": "tsc -p tsconfig.cjs.json && node -e \"require('node:fs').writeFileSync('dist/cjs/package.json', '{\\\"type\\\":\\\"commonjs\\\"}\\n')\"",
25
+ "smoke": "npm run build && node smoke-test.mjs",
26
+ "test": "npm run build && node --test tests/**/*.test.mjs"
27
+ },
28
+ "peerDependencies": {
29
+ "@anthropic-ai/sdk": ">=0.58.0",
30
+ "openai": ">=6.0.0"
31
+ },
32
+ "devDependencies": {
33
+ "@types/node": "^24.6.0",
34
+ "typescript": "^5.9.2"
35
+ },
7
36
  "publishConfig": {
8
37
  "access": "public"
9
38
  }
package/index.js DELETED
@@ -1,3 +0,0 @@
1
- // costwise/index.js
2
- module.exports = {}
3
- // Coming soon