@usagetap/sdk 1.0.0 → 1.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.
Files changed (44) hide show
  1. package/README.md +53 -16
  2. package/dist/adapters/anthropic.cjs +943 -0
  3. package/dist/adapters/anthropic.cjs.map +1 -0
  4. package/dist/adapters/anthropic.d.cts +81 -0
  5. package/dist/adapters/anthropic.d.ts +81 -0
  6. package/dist/adapters/anthropic.mjs +940 -0
  7. package/dist/adapters/anthropic.mjs.map +1 -0
  8. package/dist/adapters/openai.cjs +601 -17
  9. package/dist/adapters/openai.cjs.map +1 -1
  10. package/dist/adapters/openai.d.cts +57 -2
  11. package/dist/adapters/openai.d.ts +57 -2
  12. package/dist/adapters/openai.mjs +601 -18
  13. package/dist/adapters/openai.mjs.map +1 -1
  14. package/dist/adapters/openrouter.cjs.map +1 -1
  15. package/dist/adapters/openrouter.d.cts +1 -1
  16. package/dist/adapters/openrouter.d.ts +1 -1
  17. package/dist/adapters/openrouter.mjs.map +1 -1
  18. package/dist/anthropic/index.cjs +943 -0
  19. package/dist/anthropic/index.cjs.map +1 -0
  20. package/dist/anthropic/index.d.cts +2 -0
  21. package/dist/anthropic/index.d.ts +2 -0
  22. package/dist/anthropic/index.mjs +940 -0
  23. package/dist/anthropic/index.mjs.map +1 -0
  24. package/dist/{client-BHNMYvlO.d.cts → client-BA-QlnRq.d.cts} +32 -1
  25. package/dist/{client-BHNMYvlO.d.ts → client-BA-QlnRq.d.ts} +32 -1
  26. package/dist/express/index.cjs +597 -17
  27. package/dist/express/index.cjs.map +1 -1
  28. package/dist/express/index.d.cts +1 -1
  29. package/dist/express/index.d.ts +1 -1
  30. package/dist/express/index.mjs +597 -17
  31. package/dist/express/index.mjs.map +1 -1
  32. package/dist/index.cjs +77 -9
  33. package/dist/index.cjs.map +1 -1
  34. package/dist/index.d.cts +2 -2
  35. package/dist/index.d.ts +2 -2
  36. package/dist/index.mjs +76 -10
  37. package/dist/index.mjs.map +1 -1
  38. package/dist/openai/index.cjs +601 -17
  39. package/dist/openai/index.cjs.map +1 -1
  40. package/dist/openai/index.d.cts +2 -2
  41. package/dist/openai/index.d.ts +2 -2
  42. package/dist/openai/index.mjs +601 -18
  43. package/dist/openai/index.mjs.map +1 -1
  44. package/package.json +21 -1
package/README.md CHANGED
@@ -8,15 +8,16 @@ Server-only JavaScript/TypeScript client for UsageTap. The SDK helps you instrum
8
8
 
9
9
  Optional adapters live behind subpath exports so their peer dependencies stay out of the core bundle:
10
10
 
11
- - `@usagetap/sdk/openai` – OpenAI/OpenRouter helpers (`wrapOpenAI`, `streamOpenAIRoute`, etc.)
12
- - `@usagetap/sdk/express` – Express middleware
13
- - `@usagetap/sdk/react` – React chat hook
11
+ - `@usagetap/sdk/openai` – OpenAI/OpenRouter helpers (`wrapOpenAI`, `streamOpenAIRoute`, etc.)
12
+ - `@usagetap/sdk/anthropic` – Anthropic helper (`wrapAnthropic`)
13
+ - `@usagetap/sdk/express` – Express middleware
14
+ - `@usagetap/sdk/react` – React chat hook
14
15
 
15
16
  Install only the peer dependencies for the adapters you actually use.
16
17
 
17
18
  ## Quick start
18
19
 
19
- Install the peer dependency for your vendor (e.g. `openai`) and the UsageTap SDK in your server runtime.
20
+ Install the peer dependency for your vendor (e.g. `openai` or `@anthropic-ai/sdk`) and the UsageTap SDK in your server runtime.
20
21
 
21
22
  ```bash
22
23
  npm install @usagetap/sdk openai
@@ -115,12 +116,17 @@ Prefer a zero-boilerplate integration? Keep scrolling—`wrapOpenAI` applies the
115
116
  ```ts
116
117
  import { wrapOpenAI } from "@usagetap/sdk/openai";
117
118
 
118
- const ai = wrapOpenAI(openai, usageTap, {
119
- defaultContext: {
120
- customerId: "cust_123",
121
- feature: "chat.send",
122
- requested: { standard: true, premium: true, search: true, reasoningLevel: "HIGH" },
123
- },
119
+ const ai = wrapOpenAI(openai, usageTap, {
120
+ defaultContext: {
121
+ customerId: "cust_123",
122
+ feature: "chat.send",
123
+ requested: { standard: true, premium: true, search: true, reasoningLevel: "HIGH" },
124
+ },
125
+ promptCompression: {
126
+ provider: "heuristic",
127
+ roles: { user: true, tool: true },
128
+ minTokens: 500,
129
+ },
124
130
  });
125
131
  ```
126
132
 
@@ -129,6 +135,8 @@ const ai = wrapOpenAI(openai, usageTap, {
129
135
  Prompt compression is an explicit step after `call_begin`. `beginCall` only starts the call and returns the `callId`; `promptCompress` compresses locally, records savings metadata against that call, and returns the compressed prompt for your vendor request. Raw prompt content is not sent to UsageTap.
130
136
 
131
137
  ```ts
138
+ import { protectPromptText } from "@usagetap/sdk";
139
+
132
140
  const begin = await usageTap.beginCall({
133
141
  customerId: "cust_123",
134
142
  feature: "chat.send",
@@ -136,7 +144,7 @@ const begin = await usageTap.beginCall({
136
144
 
137
145
  const compressed = await usageTap.promptCompress({
138
146
  callId: begin.data.callId,
139
- input: "Please summarize this long prompt...",
147
+ input: `Please summarize this long prompt but keep ${protectPromptText("PLAN_ID_PRO_2026")} exact.`,
140
148
  });
141
149
 
142
150
  const response = await openai.responses.create({
@@ -147,6 +155,33 @@ const response = await openai.responses.create({
147
155
 
148
156
  The default heuristic is conservative: it normalizes whitespace, preserves fenced code indentation, minifies valid embedded JSON, and converts eligible JSON data blocks to TOON when that is smaller. Pass `provider: "toon"` to force local TOON-style encoding for structured data. Savings include both character counts and approximate token counts using lightweight regex tokenization (`[\p{L}\p{N}]+|[^\s]`), not a model-specific BPE tokenizer. If compression or savings reporting fails, the SDK returns the original input with zero savings so the vendor call can continue.
149
157
 
158
+ `wrapOpenAI()` and `wrapAnthropic()` can also compress prompts automatically after `call_begin` and before the vendor request. This is opt-in via `promptCompression`; assistant messages are skipped by default so historical assistant turns are not rewritten. Compression telemetry is aggregated once per UsageTap call, and stats are available on `ai.promptCompression.totalTokensSaved`.
159
+
160
+ ```ts
161
+ import Anthropic from "@anthropic-ai/sdk";
162
+ import { wrapAnthropic } from "@usagetap/sdk/anthropic";
163
+
164
+ const anthropic = wrapAnthropic(
165
+ new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY! }),
166
+ usageTap,
167
+ {
168
+ defaultContext: { customerId: "cust_123", feature: "chat.send" },
169
+ promptCompression: { roles: { system: true, user: true, tool: true } },
170
+ },
171
+ );
172
+
173
+ await anthropic.messages.create({
174
+ model: "claude-3-5-haiku-latest",
175
+ max_tokens: 512,
176
+ system: "Long system prompt",
177
+ messages: [{ role: "user", content: "Long user prompt" }],
178
+ });
179
+ ```
180
+
181
+ When using The Token Company, configure `tokenCompanyApiKey` on `UsageTapClient` and set `provider: "thetokencompany"`. Optional `tokenCompanyModel`, `tokenCompanyAggressiveness`, and `tokenCompanyAppId` are supported at the client, manual `promptCompress`, and wrapper levels. Use `protectPromptText()` for text that must be passed through unchanged by compression-compatible providers.
182
+
183
+ For advanced custom flows, `compressPromptInput(input, options?)` returns compression results without recording telemetry, and `recordPromptCompression({ callId, promptCompression })` records precomputed savings metadata against a call.
184
+
150
185
  > **Heads up:** `UsageTapClient` always negotiates the canonical UsageTap media type by sending `Accept: application/vnd.usagetap.v1+json`. Every response now uses the `{ result, data, correlationId }` envelope exclusively and the begin payload includes `data.idempotency.key` (always matching `callId`), per-meter snapshots, and subscription metadata. Set `autoIdempotency: false` (or pass your own `idempotency`) to skip the SDK's auto-generated key and rely on the server's deterministic fallback when retriable semantics are acceptable.
151
186
 
152
187
  ### Streaming helpers
@@ -439,15 +474,17 @@ Key exports from `@usagetap/sdk`:
439
474
  - `incrementCustomMeter` – track custom usage metrics beyond standard LLM counters (agent actions, documents, API calls, etc.).
440
475
  - `checkUsage` – lightweight method to query current usage status without creating a call session.
441
476
  - `promptCompress` / `compressPromptToon` – compress prompt input after `call_begin`, return the compressed payload, and record savings metadata for the call.
477
+ - `protectPromptText` / `protect` – mark exact text spans that compatible compressors should not rewrite.
442
478
  - `wrapFetch` – wraps a fetch function to automatically instrument OpenAI API calls (minimal integration).
443
479
  - `createIdempotencyKey` – helper for generating UsageTap-compatible idempotency keys.
444
480
  - Type definitions for canonical UsageTap request/response payloads.
445
481
 
446
- Optional subpaths:
447
-
448
- - `@usagetap/sdk/openai` – `wrapOpenAI`, `createOpenAIAdapter`, `streamOpenAIRoute`, `toNextResponse`, `pipeToResponse`, and related types.
449
- - `@usagetap/sdk/express` – `withUsage`, `withUsageMiddleware`, and corresponding Express request types.
450
- - `@usagetap/sdk/react` – `useChatWithUsage` and supporting types for building chat interfaces.
482
+ Optional subpaths:
483
+
484
+ - `@usagetap/sdk/openai` – `wrapOpenAI`, `createOpenAIAdapter`, `streamOpenAIRoute`, `toNextResponse`, `pipeToResponse`, and related types.
485
+ - `@usagetap/sdk/anthropic` – `wrapAnthropic` and related prompt compression types.
486
+ - `@usagetap/sdk/express` – `withUsage`, `withUsageMiddleware`, and corresponding Express request types.
487
+ - `@usagetap/sdk/react` – `useChatWithUsage` and supporting types for building chat interfaces.
451
488
 
452
489
  All helpers are designed for server runtimes. Use `UsageTapClient` with `allowBrowser: true` only for sandbox/test scenarios.
453
490