@usagetap/sdk 0.10.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 (45) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +83 -22
  3. package/dist/adapters/anthropic.cjs +943 -0
  4. package/dist/adapters/anthropic.cjs.map +1 -0
  5. package/dist/adapters/anthropic.d.cts +81 -0
  6. package/dist/adapters/anthropic.d.ts +81 -0
  7. package/dist/adapters/anthropic.mjs +940 -0
  8. package/dist/adapters/anthropic.mjs.map +1 -0
  9. package/dist/adapters/openai.cjs +601 -17
  10. package/dist/adapters/openai.cjs.map +1 -1
  11. package/dist/adapters/openai.d.cts +57 -2
  12. package/dist/adapters/openai.d.ts +57 -2
  13. package/dist/adapters/openai.mjs +601 -18
  14. package/dist/adapters/openai.mjs.map +1 -1
  15. package/dist/adapters/openrouter.cjs.map +1 -1
  16. package/dist/adapters/openrouter.d.cts +1 -1
  17. package/dist/adapters/openrouter.d.ts +1 -1
  18. package/dist/adapters/openrouter.mjs.map +1 -1
  19. package/dist/anthropic/index.cjs +943 -0
  20. package/dist/anthropic/index.cjs.map +1 -0
  21. package/dist/anthropic/index.d.cts +2 -0
  22. package/dist/anthropic/index.d.ts +2 -0
  23. package/dist/anthropic/index.mjs +940 -0
  24. package/dist/anthropic/index.mjs.map +1 -0
  25. package/dist/{client-DEbk0Q2l.d.cts → client-BA-QlnRq.d.cts} +95 -1
  26. package/dist/{client-DEbk0Q2l.d.ts → client-BA-QlnRq.d.ts} +95 -1
  27. package/dist/express/index.cjs +597 -17
  28. package/dist/express/index.cjs.map +1 -1
  29. package/dist/express/index.d.cts +1 -1
  30. package/dist/express/index.d.ts +1 -1
  31. package/dist/express/index.mjs +597 -17
  32. package/dist/express/index.mjs.map +1 -1
  33. package/dist/index.cjs +586 -1
  34. package/dist/index.cjs.map +1 -1
  35. package/dist/index.d.cts +2 -2
  36. package/dist/index.d.ts +2 -2
  37. package/dist/index.mjs +581 -2
  38. package/dist/index.mjs.map +1 -1
  39. package/dist/openai/index.cjs +601 -17
  40. package/dist/openai/index.cjs.map +1 -1
  41. package/dist/openai/index.d.cts +2 -2
  42. package/dist/openai/index.d.ts +2 -2
  43. package/dist/openai/index.mjs +601 -18
  44. package/dist/openai/index.mjs.map +1 -1
  45. package/package.json +22 -2
package/dist/index.mjs CHANGED
@@ -113,9 +113,500 @@ async function runWithRetry(operation, options, shouldRetry, onSchedule, signal)
113
113
  throw lastError instanceof Error ? lastError : new Error(String(lastError));
114
114
  }
115
115
 
116
+ // src/prompt-compression.ts
117
+ var DEFAULT_TTC_ENDPOINT = "https://api.thetokencompany.com/v1/compress";
118
+ var DEFAULT_TTC_MODEL = "bear-2";
119
+ var DEFAULT_TTC_AGGRESSIVENESS = 0.2;
120
+ var PROTECTED_TEXT_PATTERN = /<ttc_safe>[\s\S]*?<\/ttc_safe>|<usagetap_safe>[\s\S]*?<\/usagetap_safe>/g;
121
+ function protectPromptText(text) {
122
+ return `<ttc_safe>${text}</ttc_safe>`;
123
+ }
124
+ var protect = protectPromptText;
125
+ async function compressPrompt(options) {
126
+ try {
127
+ if (options.provider === "thetokencompany" || options.tokenCompanyApiKey) {
128
+ return await compressWithTheTokenCompany(options);
129
+ }
130
+ if (options.provider === "toon") {
131
+ return compressPromptToon(options.input);
132
+ }
133
+ return compressPromptHeuristic(options.input);
134
+ } catch (error) {
135
+ if (options.failOpen === false) {
136
+ throw error;
137
+ }
138
+ return createPromptCompressionFallback(
139
+ options.input,
140
+ options.provider ?? (options.tokenCompanyApiKey ? "thetokencompany" : "heuristic"),
141
+ error
142
+ );
143
+ }
144
+ }
145
+ function compressPromptHeuristic(input) {
146
+ const original = stableStringifyInput(input);
147
+ const techniques = /* @__PURE__ */ new Set();
148
+ const compressedInput = compressValue(input, techniques, { allowToonString: false });
149
+ const compressed = stableStringifyInput(compressedInput);
150
+ const chosenInput = compressed.length <= original.length ? compressedInput : input;
151
+ const chosen = compressed.length <= original.length ? compressed : original;
152
+ if (!techniques.size) {
153
+ techniques.add("no-op");
154
+ }
155
+ return buildResult(
156
+ input,
157
+ chosenInput,
158
+ "heuristic",
159
+ original,
160
+ chosen,
161
+ Array.from(techniques)
162
+ );
163
+ }
164
+ function compressPromptToon(input) {
165
+ const original = stableStringifyInput(input);
166
+ const compressedInput = typeof input === "string" ? compressText(input, /* @__PURE__ */ new Set(), { allowToonString: true }) : encodeToon(input);
167
+ const compressed = stableStringifyInput(compressedInput);
168
+ return buildResult(input, compressedInput, "toon", original, compressed, [
169
+ "toon",
170
+ "json-minify"
171
+ ]);
172
+ }
173
+ async function compressWithTheTokenCompany(options) {
174
+ if (!options.tokenCompanyApiKey) {
175
+ throw new Error(
176
+ "tokenCompanyApiKey is required when provider is thetokencompany"
177
+ );
178
+ }
179
+ const fetchCandidate = options.fetchImpl ?? globalThis.fetch;
180
+ if (typeof fetchCandidate !== "function") {
181
+ throw new Error(
182
+ "A fetch implementation is required for The Token Company compression"
183
+ );
184
+ }
185
+ const original = stableStringifyInput(options.input);
186
+ const heuristic = compressPromptHeuristic(options.input);
187
+ const input = typeof heuristic.compressedInput === "string" ? heuristic.compressedInput : stableStringifyInput(heuristic.compressedInput);
188
+ const model = options.tokenCompanyModel ?? DEFAULT_TTC_MODEL;
189
+ const aggressiveness = options.tokenCompanyAggressiveness ?? DEFAULT_TTC_AGGRESSIVENESS;
190
+ if (typeof aggressiveness !== "number" || !Number.isFinite(aggressiveness) || aggressiveness < 0 || aggressiveness > 1) {
191
+ throw new Error("tokenCompanyAggressiveness must be between 0.0 and 1.0");
192
+ }
193
+ const response = await fetchCandidate(
194
+ options.tokenCompanyEndpoint ?? DEFAULT_TTC_ENDPOINT,
195
+ {
196
+ method: "POST",
197
+ headers: {
198
+ authorization: `Bearer ${options.tokenCompanyApiKey}`,
199
+ "content-type": "application/json"
200
+ },
201
+ body: JSON.stringify({
202
+ model,
203
+ input,
204
+ compression_settings: { aggressiveness },
205
+ ...options.tokenCompanyAppId ? { app_id: options.tokenCompanyAppId } : {}
206
+ }),
207
+ signal: options.signal
208
+ }
209
+ );
210
+ if (!response.ok) {
211
+ throw new Error(
212
+ `The Token Company compression failed with HTTP ${response.status}`
213
+ );
214
+ }
215
+ const payload = await response.json();
216
+ const tokenCompanyResult = normalizeTheTokenCompanyCompressResponse(payload);
217
+ const compressedInput = payload.compressedInput ?? payload.compressed ?? tokenCompanyResult?.output ?? payload.output ?? payload.text;
218
+ if (compressedInput === void 0) {
219
+ throw new Error("The Token Company response did not include compressed content");
220
+ }
221
+ const compressed = stableStringifyInput(compressedInput);
222
+ const tokenCounts = tokenCompanyResult ? {
223
+ originalTokens: tokenCompanyResult.input_tokens,
224
+ compressedTokens: tokenCompanyResult.output_tokens,
225
+ savedTokens: tokenCompanyResult.tokens_saved
226
+ } : void 0;
227
+ return buildResult(
228
+ options.input,
229
+ compressedInput,
230
+ "thetokencompany",
231
+ original,
232
+ compressed,
233
+ [...heuristic.techniques, "thetokencompany"],
234
+ tokenCounts
235
+ );
236
+ }
237
+ function normalizeTheTokenCompanyCompressResponse(data) {
238
+ if (typeof data.output !== "string" || typeof data.output_tokens !== "number") {
239
+ return void 0;
240
+ }
241
+ const inputTokens = typeof data.input_tokens === "number" ? data.input_tokens : data.original_input_tokens;
242
+ if (typeof inputTokens !== "number") {
243
+ return void 0;
244
+ }
245
+ const tokensSaved = typeof data.tokens_saved === "number" ? data.tokens_saved : inputTokens - data.output_tokens;
246
+ const compressionRatio = typeof data.compression_ratio === "number" ? data.compression_ratio : data.output_tokens === 0 ? 0 : inputTokens / data.output_tokens;
247
+ return {
248
+ output: data.output,
249
+ output_tokens: data.output_tokens,
250
+ input_tokens: inputTokens,
251
+ tokens_saved: tokensSaved,
252
+ compression_ratio: compressionRatio
253
+ };
254
+ }
255
+ function createPromptCompressionFallback(input, provider = "heuristic", error) {
256
+ const original = stableStringifyInput(input);
257
+ const techniques = ["fallback-original"];
258
+ if (error) {
259
+ techniques.push("compression-error");
260
+ }
261
+ return buildResult(input, input, provider, original, original, techniques);
262
+ }
263
+ function buildResult(input, compressedInput, provider, original, compressed, techniques, tokenCounts) {
264
+ const originalCharacters = original.length;
265
+ const compressedCharacters = compressed.length;
266
+ const savedCharacters = Math.max(
267
+ 0,
268
+ originalCharacters - compressedCharacters
269
+ );
270
+ const originalTokens = tokenCounts?.originalTokens ?? estimatePromptTokens(original);
271
+ const compressedTokens = tokenCounts?.compressedTokens ?? estimatePromptTokens(compressed);
272
+ const savedTokens = Math.max(
273
+ 0,
274
+ tokenCounts?.savedTokens ?? originalTokens - compressedTokens
275
+ );
276
+ return {
277
+ input,
278
+ compressedInput,
279
+ provider,
280
+ originalCharacters,
281
+ compressedCharacters,
282
+ savedCharacters,
283
+ originalTokens,
284
+ compressedTokens,
285
+ savedTokens,
286
+ tokenSavingsRatio: originalTokens > 0 ? savedTokens / originalTokens : 0,
287
+ savingsRatio: originalCharacters > 0 ? savedCharacters / originalCharacters : 0,
288
+ techniques
289
+ };
290
+ }
291
+ function estimatePromptTokens(input) {
292
+ const text = typeof input === "string" ? input : stableStringifyInput(input);
293
+ return text.match(/[\p{L}\p{N}]+|[^\s]/gu)?.length ?? 0;
294
+ }
295
+ function compressValue(value, techniques, options) {
296
+ if (typeof value === "string") return compressText(value, techniques, options);
297
+ if (Array.isArray(value)) {
298
+ techniques.add("json-minify");
299
+ return value.map((item) => compressValue(item, techniques, options));
300
+ }
301
+ if (value && typeof value === "object") {
302
+ techniques.add("json-minify");
303
+ return Object.keys(value).reduce((acc, key) => {
304
+ const child = value[key];
305
+ if (child !== void 0) {
306
+ acc[key] = compressValue(child, techniques, options);
307
+ }
308
+ return acc;
309
+ }, {});
310
+ }
311
+ return value;
312
+ }
313
+ function compressText(value, techniques, options) {
314
+ const protectedSpans = [];
315
+ const text = value.replace(PROTECTED_TEXT_PATTERN, (match) => {
316
+ const placeholder = `__USAGETAP_PROTECTED_${protectedSpans.length}__`;
317
+ protectedSpans.push(match);
318
+ techniques.add("protected-text");
319
+ return placeholder;
320
+ });
321
+ const compressed = compressTextWithoutProtection(text, techniques, options);
322
+ return protectedSpans.reduce(
323
+ (output, span, index) => output.replace(`__USAGETAP_PROTECTED_${index}__`, span),
324
+ compressed
325
+ );
326
+ }
327
+ function compressTextWithoutProtection(value, techniques, options) {
328
+ const fencePattern = /```([\w-]+)?\n([\s\S]*?)```/g;
329
+ const parts = [];
330
+ let cursor = 0;
331
+ let match;
332
+ while ((match = fencePattern.exec(value)) !== null) {
333
+ const before = value.slice(cursor, match.index);
334
+ const compressedBefore = compressPlainTextAndEmbeddedJson(
335
+ before,
336
+ techniques,
337
+ options
338
+ );
339
+ if (compressedBefore) parts.push(compressedBefore);
340
+ const lang = match[1]?.toLowerCase();
341
+ const code = cleanCodeBlock(match[2] ?? "");
342
+ const compressedCode = lang === "json" ? compressJsonText(code, techniques, options) : void 0;
343
+ if (compressedCode?.format === "toon") {
344
+ parts.push(`\`\`\`toon
345
+ ${compressedCode.text}
346
+ \`\`\``);
347
+ } else if (compressedCode?.format === "json") {
348
+ parts.push(`\`\`\`json
349
+ ${compressedCode.text}
350
+ \`\`\``);
351
+ } else {
352
+ if (code !== match[2]) {
353
+ techniques.add("code-whitespace");
354
+ }
355
+ parts.push(lang ? `\`\`\`${lang}
356
+ ${code}
357
+ \`\`\`` : `\`\`\`
358
+ ${code}
359
+ \`\`\``);
360
+ }
361
+ cursor = match.index + match[0].length;
362
+ }
363
+ const after = compressPlainTextAndEmbeddedJson(value.slice(cursor), techniques, options);
364
+ if (after) parts.push(after);
365
+ return parts.join("\n").trim();
366
+ }
367
+ function compressPlainText(value, techniques) {
368
+ const compressed = value.split("\n").map((line) => line.trim()).filter((line) => line).join("\n").replace(/[ \t]{2,}/g, " ").trim();
369
+ if (compressed !== value.trim()) {
370
+ techniques.add("text-whitespace");
371
+ }
372
+ return compressed;
373
+ }
374
+ function compressPlainTextAndEmbeddedJson(value, techniques, options) {
375
+ const normalized = compressPlainText(value, techniques);
376
+ return compressEmbeddedJson(normalized, techniques, options);
377
+ }
378
+ function cleanCodeBlock(code) {
379
+ const lines = code.replace(/\r\n/g, "\n").split("\n");
380
+ while (lines.length && lines[0].trim() === "") lines.shift();
381
+ while (lines.length && lines[lines.length - 1].trim() === "") lines.pop();
382
+ const commonIndent = lines.filter((line) => line.trim()).reduce((min, line) => {
383
+ const indent = /^[ \t]*/.exec(line)?.[0].length ?? 0;
384
+ return min === void 0 ? indent : Math.min(min, indent);
385
+ }, void 0);
386
+ return lines.map((line) => commonIndent ? line.slice(commonIndent) : line).join("\n").replace(/[ \t]+$/gm, "");
387
+ }
388
+ function stableStringifyInput(input) {
389
+ if (typeof input === "string") return input;
390
+ return JSON.stringify(input) ?? String(input);
391
+ }
392
+ function compressJsonText(text, techniques, options) {
393
+ const parsed = safeParseJson(text);
394
+ if (parsed === void 0) {
395
+ return void 0;
396
+ }
397
+ const compactJson = JSON.stringify(parsed);
398
+ const candidates = [
399
+ { format: "json", text: compactJson }
400
+ ];
401
+ if (options.allowToonString || shouldUseToonForJson(parsed)) {
402
+ candidates.push({ format: "toon", text: encodeToon(parsed) });
403
+ }
404
+ const originalLength = text.trim().length;
405
+ const best = candidates.reduce(
406
+ (winner, candidate) => candidate.text.length < winner.text.length ? candidate : winner
407
+ );
408
+ if (best.text.length >= originalLength) {
409
+ return void 0;
410
+ }
411
+ techniques.add(best.format === "toon" ? "embedded-json-toon" : "embedded-json-minify");
412
+ return best;
413
+ }
414
+ function compressEmbeddedJson(text, techniques, options) {
415
+ let result = "";
416
+ let cursor = 0;
417
+ while (cursor < text.length) {
418
+ const start = findNextJsonStart(text, cursor);
419
+ if (start < 0) {
420
+ result += text.slice(cursor);
421
+ break;
422
+ }
423
+ result += text.slice(cursor, start);
424
+ const span = findBalancedJsonSpan(text, start);
425
+ if (!span) {
426
+ result += text[start];
427
+ cursor = start + 1;
428
+ continue;
429
+ }
430
+ const candidate = compressJsonText(span.text, techniques, options);
431
+ if (candidate) {
432
+ result += candidate.text;
433
+ } else {
434
+ result += span.text;
435
+ }
436
+ cursor = span.end;
437
+ }
438
+ return result;
439
+ }
440
+ function findNextJsonStart(text, from) {
441
+ const objectStart = text.indexOf("{", from);
442
+ const arrayStart = text.indexOf("[", from);
443
+ if (objectStart < 0) return arrayStart;
444
+ if (arrayStart < 0) return objectStart;
445
+ return Math.min(objectStart, arrayStart);
446
+ }
447
+ function findBalancedJsonSpan(text, start) {
448
+ const opener = text[start];
449
+ const closer = opener === "{" ? "}" : opener === "[" ? "]" : void 0;
450
+ if (!closer) return void 0;
451
+ const stack = [closer];
452
+ let inString = false;
453
+ let escaped = false;
454
+ for (let index = start + 1; index < text.length; index += 1) {
455
+ const char = text[index];
456
+ if (inString) {
457
+ if (escaped) {
458
+ escaped = false;
459
+ } else if (char === "\\") {
460
+ escaped = true;
461
+ } else if (char === '"') {
462
+ inString = false;
463
+ }
464
+ continue;
465
+ }
466
+ if (char === '"') {
467
+ inString = true;
468
+ continue;
469
+ }
470
+ if (char === "{" || char === "[") {
471
+ stack.push(char === "{" ? "}" : "]");
472
+ continue;
473
+ }
474
+ if (char === stack[stack.length - 1]) {
475
+ stack.pop();
476
+ if (!stack.length) {
477
+ const end = index + 1;
478
+ return { text: text.slice(start, end), end };
479
+ }
480
+ }
481
+ }
482
+ return void 0;
483
+ }
484
+ function safeParseJson(text) {
485
+ try {
486
+ return JSON.parse(text);
487
+ } catch {
488
+ return void 0;
489
+ }
490
+ }
491
+ function shouldUseToonForJson(value) {
492
+ if (Array.isArray(value)) {
493
+ return isUniformObjectArray(value) || value.some(shouldUseToonForJson);
494
+ }
495
+ if (isPlainObject(value)) {
496
+ return Object.values(value).some(shouldUseToonForJson);
497
+ }
498
+ return false;
499
+ }
500
+ function encodeToon(value, indent = 0) {
501
+ if (isPrimitive(value)) {
502
+ return scalarToToon(value);
503
+ }
504
+ if (Array.isArray(value)) {
505
+ return encodeArrayToon(value, indent);
506
+ }
507
+ if (isPlainObject(value)) {
508
+ const lines = [];
509
+ for (const [key, child] of Object.entries(value)) {
510
+ lines.push(...encodePropertyToon(key, child, indent));
511
+ }
512
+ return lines.join("\n");
513
+ }
514
+ return scalarToToon(String(value));
515
+ }
516
+ function encodePropertyToon(key, value, indent) {
517
+ const prefix = " ".repeat(indent);
518
+ const toonKey = keyToToon(key);
519
+ if (isPrimitive(value)) {
520
+ return [`${prefix}${toonKey}: ${scalarToToon(value)}`];
521
+ }
522
+ if (Array.isArray(value)) {
523
+ if (value.every(isPrimitive)) {
524
+ return [`${prefix}${toonKey}[${value.length}]: ${value.map(scalarToToon).join(",")}`];
525
+ }
526
+ if (isUniformObjectArray(value)) {
527
+ const fields = Object.keys(value[0]);
528
+ const header = `${prefix}${toonKey}[${value.length}]{${fields.map(keyToToon).join(",")}}:`;
529
+ const rows = value.map(
530
+ (item) => `${" ".repeat(indent + 2)}${fields.map(
531
+ (field) => scalarToToon(item[field])
532
+ ).join(",")}`
533
+ );
534
+ return [header, ...rows];
535
+ }
536
+ return [
537
+ `${prefix}${toonKey}[${value.length}]:`,
538
+ ...value.flatMap((item, index) => {
539
+ if (isPrimitive(item)) {
540
+ return [`${" ".repeat(indent + 2)}- ${scalarToToon(item)}`];
541
+ }
542
+ return [
543
+ `${" ".repeat(indent + 2)}- item${index}:`,
544
+ ...encodeToon(item, indent + 4).split("\n")
545
+ ];
546
+ })
547
+ ];
548
+ }
549
+ return [`${prefix}${toonKey}:`, ...encodeToon(value, indent + 2).split("\n")];
550
+ }
551
+ function encodeArrayToon(value, indent) {
552
+ if (value.every(isPrimitive)) {
553
+ return `[${value.length}]: ${value.map(scalarToToon).join(",")}`;
554
+ }
555
+ if (isUniformObjectArray(value)) {
556
+ const fields = Object.keys(value[0]);
557
+ return [
558
+ `[${value.length}]{${fields.map(keyToToon).join(",")}}:`,
559
+ ...value.map(
560
+ (item) => `${" ".repeat(indent + 2)}${fields.map(
561
+ (field) => scalarToToon(item[field])
562
+ ).join(",")}`
563
+ )
564
+ ].join("\n");
565
+ }
566
+ return value.flatMap((item, index) => [
567
+ `${" ".repeat(indent)}- item${index}:`,
568
+ ...encodeToon(item, indent + 2).split("\n")
569
+ ]).join("\n");
570
+ }
571
+ function isUniformObjectArray(value) {
572
+ if (!value.length || !value.every(isPlainObject)) {
573
+ return false;
574
+ }
575
+ const fields = Object.keys(value[0]);
576
+ if (!fields.length) {
577
+ return false;
578
+ }
579
+ return value.every((item) => {
580
+ const record = item;
581
+ const itemFields = Object.keys(record);
582
+ return itemFields.length === fields.length && fields.every((field) => itemFields.includes(field) && isPrimitive(record[field]));
583
+ });
584
+ }
585
+ function isPlainObject(value) {
586
+ return typeof value === "object" && value !== null && !Array.isArray(value);
587
+ }
588
+ function isPrimitive(value) {
589
+ return value === null || typeof value === "string" || typeof value === "number" || typeof value === "boolean";
590
+ }
591
+ function keyToToon(key) {
592
+ return /^[A-Za-z_][A-Za-z0-9_-]*$/.test(key) ? key : JSON.stringify(key);
593
+ }
594
+ function scalarToToon(value) {
595
+ if (value === null) return "null";
596
+ if (typeof value === "number" || typeof value === "boolean") {
597
+ return String(value);
598
+ }
599
+ const text = String(value);
600
+ if (text && !/^(true|false|null|-?\d+(?:\.\d+)?)$/i.test(text) && /^[A-Za-z0-9_./@-]+(?: [A-Za-z0-9_./@-]+)*$/.test(text)) {
601
+ return text;
602
+ }
603
+ return JSON.stringify(text);
604
+ }
605
+
116
606
  // src/client.ts
117
607
  var CALL_BEGIN_PATH = "call_begin";
118
608
  var CALL_END_PATH = "call_end";
609
+ var COMPRESS_PROMPT_PATH = "compress_prompt";
119
610
  var CHECK_USAGE_PATH = "customers/{customerId}/usage";
120
611
  var CREATE_CUSTOMER_PATH = "customers";
121
612
  var CHANGE_PLAN_PATH = "customers/{customerId}/change_plan";
@@ -127,7 +618,7 @@ var IDEMPOTENCY_HEADER = "idempotency-key";
127
618
  var SDK_HEADER = "x-usage-sdk";
128
619
  var USER_AGENT = "UsageTapClient";
129
620
  var CANONICAL_MEDIA_TYPE = "application/vnd.usagetap.v1+json";
130
- var SDK_VERSION = "0.10.0" ;
621
+ var SDK_VERSION = "1.1.0" ;
131
622
  var HAS_WINDOW = typeof globalThis !== "undefined" && typeof globalThis.window !== "undefined";
132
623
  var UsageTapClient = class {
133
624
  apiKey;
@@ -142,6 +633,11 @@ var UsageTapClient = class {
142
633
  metricFn;
143
634
  authHeader;
144
635
  autoIdempotency;
636
+ tokenCompanyApiKey;
637
+ tokenCompanyEndpoint;
638
+ tokenCompanyModel;
639
+ tokenCompanyAggressiveness;
640
+ tokenCompanyAppId;
145
641
  constructor(options) {
146
642
  if (!options) {
147
643
  throw new UsageTapError(
@@ -187,6 +683,11 @@ var UsageTapClient = class {
187
683
  this.metricFn = options.onUsageMetric;
188
684
  this.authHeader = options.useApiKeyHeader ? API_KEY_HEADER : AUTH_HEADER;
189
685
  this.autoIdempotency = options.autoIdempotency ?? true;
686
+ this.tokenCompanyApiKey = options.tokenCompanyApiKey;
687
+ this.tokenCompanyEndpoint = options.tokenCompanyEndpoint;
688
+ this.tokenCompanyModel = options.tokenCompanyModel;
689
+ this.tokenCompanyAggressiveness = options.tokenCompanyAggressiveness;
690
+ this.tokenCompanyAppId = options.tokenCompanyAppId;
190
691
  }
191
692
  async beginCall(request, options = {}) {
192
693
  const idempotencyKey = request.idempotencyKey ?? request.idempotency ?? (this.autoIdempotency ? this.idempotencyGenerator() : void 0);
@@ -209,6 +710,70 @@ var UsageTapClient = class {
209
710
  );
210
711
  return response;
211
712
  }
713
+ async promptCompress(request, options = {}) {
714
+ if (!request?.callId) {
715
+ throw new UsageTapError(
716
+ "USAGETAP_BAD_REQUEST",
717
+ "promptCompress requires callId"
718
+ );
719
+ }
720
+ const result = await this.compressPromptInput(request.input, {
721
+ provider: request.provider,
722
+ tokenCompanyModel: request.tokenCompanyModel,
723
+ tokenCompanyAggressiveness: request.tokenCompanyAggressiveness,
724
+ tokenCompanyAppId: request.tokenCompanyAppId,
725
+ signal: options.signal
726
+ });
727
+ try {
728
+ await this.recordPromptCompression(
729
+ {
730
+ callId: request.callId,
731
+ promptCompression: this.toPromptCompressionTelemetry(result)
732
+ },
733
+ options
734
+ );
735
+ return { ...result, callId: request.callId };
736
+ } catch (error) {
737
+ return {
738
+ ...createPromptCompressionFallback(
739
+ request.input,
740
+ request.provider ?? result.provider,
741
+ error
742
+ ),
743
+ callId: request.callId
744
+ };
745
+ }
746
+ }
747
+ async compressPromptInput(input, options = {}) {
748
+ return compressPrompt({
749
+ input,
750
+ provider: options.provider,
751
+ tokenCompanyApiKey: this.tokenCompanyApiKey,
752
+ tokenCompanyEndpoint: this.tokenCompanyEndpoint,
753
+ tokenCompanyModel: options.tokenCompanyModel ?? this.tokenCompanyModel,
754
+ tokenCompanyAggressiveness: options.tokenCompanyAggressiveness ?? this.tokenCompanyAggressiveness,
755
+ tokenCompanyAppId: options.tokenCompanyAppId ?? this.tokenCompanyAppId,
756
+ fetchImpl: this.fetchImpl,
757
+ signal: options.signal,
758
+ failOpen: options.failOpen
759
+ });
760
+ }
761
+ async recordPromptCompression(request, options = {}) {
762
+ if (!request?.callId) {
763
+ throw new UsageTapError(
764
+ "USAGETAP_BAD_REQUEST",
765
+ "recordPromptCompression requires callId"
766
+ );
767
+ }
768
+ return this.request(
769
+ COMPRESS_PROMPT_PATH,
770
+ {
771
+ callId: request.callId,
772
+ promptCompression: request.promptCompression
773
+ },
774
+ options
775
+ );
776
+ }
212
777
  async endCall(request, options = {}) {
213
778
  if (!request?.callId) {
214
779
  throw new UsageTapError(
@@ -433,6 +998,20 @@ var UsageTapClient = class {
433
998
  }
434
999
  return handlerResult;
435
1000
  }
1001
+ toPromptCompressionTelemetry(result) {
1002
+ return {
1003
+ provider: result.provider,
1004
+ originalCharacters: result.originalCharacters,
1005
+ compressedCharacters: result.compressedCharacters,
1006
+ savedCharacters: result.savedCharacters,
1007
+ originalTokens: result.originalTokens,
1008
+ compressedTokens: result.compressedTokens,
1009
+ savedTokens: result.savedTokens,
1010
+ tokenSavingsRatio: result.tokenSavingsRatio,
1011
+ savingsRatio: result.savingsRatio,
1012
+ techniques: result.techniques
1013
+ };
1014
+ }
436
1015
  async request(path, payload, options) {
437
1016
  const url = new URL(path, this.baseUrl).toString();
438
1017
  const body = payload !== void 0 ? JSON.stringify(payload) : void 0;
@@ -1020,6 +1599,6 @@ async function finalizeCall(callState, usageTap, error, usage) {
1020
1599
  }
1021
1600
  }
1022
1601
 
1023
- export { UsageTapClient, UsageTapError, createIdempotencyKey, isUsageTapError, wrapFetch };
1602
+ export { UsageTapClient, UsageTapError, compressPrompt, compressPromptHeuristic, compressPromptToon, createIdempotencyKey, estimatePromptTokens, isUsageTapError, protect, protectPromptText, wrapFetch };
1024
1603
  //# sourceMappingURL=index.mjs.map
1025
1604
  //# sourceMappingURL=index.mjs.map