@llmtracer/sdk 2.1.0 → 2.5.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 (88) hide show
  1. package/README.md +84 -119
  2. package/dist/cjs/config.d.ts +8 -0
  3. package/dist/cjs/config.d.ts.map +1 -1
  4. package/dist/cjs/config.js +8 -0
  5. package/dist/cjs/config.js.map +1 -1
  6. package/dist/cjs/index.d.ts +11 -3
  7. package/dist/cjs/index.d.ts.map +1 -1
  8. package/dist/cjs/index.js +33 -1
  9. package/dist/cjs/index.js.map +1 -1
  10. package/dist/cjs/patcher.d.ts +1 -0
  11. package/dist/cjs/patcher.d.ts.map +1 -1
  12. package/dist/cjs/patcher.js +106 -1
  13. package/dist/cjs/patcher.js.map +1 -1
  14. package/dist/cjs/providers/anthropic.d.ts.map +1 -1
  15. package/dist/cjs/providers/anthropic.js +28 -3
  16. package/dist/cjs/providers/anthropic.js.map +1 -1
  17. package/dist/cjs/providers/google.d.ts +4 -0
  18. package/dist/cjs/providers/google.d.ts.map +1 -0
  19. package/dist/cjs/providers/google.js +138 -0
  20. package/dist/cjs/providers/google.js.map +1 -0
  21. package/dist/cjs/providers/index.d.ts +1 -0
  22. package/dist/cjs/providers/index.d.ts.map +1 -1
  23. package/dist/cjs/providers/index.js +4 -1
  24. package/dist/cjs/providers/index.js.map +1 -1
  25. package/dist/cjs/providers/openai.d.ts +6 -1
  26. package/dist/cjs/providers/openai.d.ts.map +1 -1
  27. package/dist/cjs/providers/openai.js +127 -5
  28. package/dist/cjs/providers/openai.js.map +1 -1
  29. package/dist/cjs/schema.d.ts +3 -0
  30. package/dist/cjs/schema.d.ts.map +1 -1
  31. package/dist/cjs/schema.js +20 -2
  32. package/dist/cjs/schema.js.map +1 -1
  33. package/dist/cjs/transport.d.ts +12 -0
  34. package/dist/cjs/transport.d.ts.map +1 -1
  35. package/dist/cjs/transport.js +115 -9
  36. package/dist/cjs/transport.js.map +1 -1
  37. package/dist/cjs/wrapper.d.ts +1 -1
  38. package/dist/cjs/wrapper.d.ts.map +1 -1
  39. package/dist/cjs/wrapper.js +13 -2
  40. package/dist/cjs/wrapper.js.map +1 -1
  41. package/dist/esm/config.d.ts +8 -0
  42. package/dist/esm/config.d.ts.map +1 -1
  43. package/dist/esm/config.js +8 -0
  44. package/dist/esm/config.js.map +1 -1
  45. package/dist/esm/index.d.ts +11 -3
  46. package/dist/esm/index.d.ts.map +1 -1
  47. package/dist/esm/index.js +33 -1
  48. package/dist/esm/index.js.map +1 -1
  49. package/dist/esm/patcher.d.ts +1 -0
  50. package/dist/esm/patcher.d.ts.map +1 -1
  51. package/dist/esm/patcher.js +106 -2
  52. package/dist/esm/patcher.js.map +1 -1
  53. package/dist/esm/providers/anthropic.d.ts.map +1 -1
  54. package/dist/esm/providers/anthropic.js +28 -3
  55. package/dist/esm/providers/anthropic.js.map +1 -1
  56. package/dist/esm/providers/google.d.ts +4 -0
  57. package/dist/esm/providers/google.d.ts.map +1 -0
  58. package/dist/esm/providers/google.js +101 -0
  59. package/dist/esm/providers/google.js.map +1 -0
  60. package/dist/esm/providers/index.d.ts +1 -0
  61. package/dist/esm/providers/index.d.ts.map +1 -1
  62. package/dist/esm/providers/index.js +1 -0
  63. package/dist/esm/providers/index.js.map +1 -1
  64. package/dist/esm/providers/openai.d.ts +6 -1
  65. package/dist/esm/providers/openai.d.ts.map +1 -1
  66. package/dist/esm/providers/openai.js +122 -5
  67. package/dist/esm/providers/openai.js.map +1 -1
  68. package/dist/esm/schema.d.ts +3 -0
  69. package/dist/esm/schema.d.ts.map +1 -1
  70. package/dist/esm/schema.js +20 -2
  71. package/dist/esm/schema.js.map +1 -1
  72. package/dist/esm/transport.d.ts +12 -0
  73. package/dist/esm/transport.d.ts.map +1 -1
  74. package/dist/esm/transport.js +114 -9
  75. package/dist/esm/transport.js.map +1 -1
  76. package/dist/esm/wrapper.d.ts +1 -1
  77. package/dist/esm/wrapper.d.ts.map +1 -1
  78. package/dist/esm/wrapper.js +13 -2
  79. package/dist/esm/wrapper.js.map +1 -1
  80. package/package.json +10 -14
  81. package/dist/cjs/auto.d.ts +0 -2
  82. package/dist/cjs/auto.d.ts.map +0 -1
  83. package/dist/cjs/auto.js +0 -5
  84. package/dist/cjs/auto.js.map +0 -1
  85. package/dist/esm/auto.d.ts +0 -2
  86. package/dist/esm/auto.d.ts.map +0 -1
  87. package/dist/esm/auto.js +0 -3
  88. package/dist/esm/auto.js.map +0 -1
package/README.md CHANGED
@@ -1,8 +1,6 @@
1
1
  # @llmtracer/sdk
2
2
 
3
- See where your AI budget goes. Lightweight LLM cost tracking SDK for OpenAI.
4
-
5
- Wrap your OpenAI client in two lines and get automatic tracking of every API call -- tokens, latency, cost, and model usage -- with zero changes to your application code.
3
+ Track cost, latency, and token usage across OpenAI, Anthropic, and Google Gemini — in one line of code.
6
4
 
7
5
  ## Install
8
6
 
@@ -10,117 +8,108 @@ Wrap your OpenAI client in two lines and get automatic tracking of every API cal
10
8
  npm install @llmtracer/sdk
11
9
  ```
12
10
 
13
- ## Quickstart
11
+ ## Quick Start
14
12
 
15
13
  ```typescript
16
- import { LLMTracer } from "@llmtracer/sdk";
17
- import OpenAI from "openai";
14
+ import llmtracer from '@llmtracer/sdk';
18
15
 
19
- const tracer = new LLMTracer({
20
- apiKey: process.env.LLMTRACER_KEY,
21
- });
16
+ llmtracer.init({ apiKey: 'lt_...' });
22
17
 
23
- const openai = new OpenAI();
18
+ // All OpenAI, Anthropic, and Google Gemini calls are now tracked automatically.
19
+ ```
24
20
 
25
- // 2 lines -- that's it
26
- tracer.instrumentOpenAI(openai, {
27
- tags: { feature: "customer-support-bot", env: "production" },
28
- });
21
+ No wrappers, no manual instrumentation, no code changes. The SDK auto-patches your provider clients at import time.
29
22
 
30
- // Every OpenAI call is now automatically tracked
31
- const response = await openai.chat.completions.create({
32
- model: "gpt-4o",
33
- messages: [{ role: "user", content: "Hello" }],
34
- });
23
+ View your dashboard at [llmtracer.dev](https://llmtracer.dev).
35
24
 
36
- // In serverless (Lambda, Cloud Functions), flush before returning
37
- await tracer.flush();
38
- ```
25
+ ## What Gets Captured
26
+
27
+ Every LLM call is automatically tracked with:
39
28
 
40
- ## Tagging Guide
29
+ - **Provider, model, tokens** (input + output), latency, cost
30
+ - **Google Gemini**: thinking tokens (2.5 models), tool tokens, cached tokens
31
+ - **Anthropic**: cache creation + read tokens
32
+ - **OpenAI**: reasoning tokens (o1/o3/o4), cached tokens
33
+ - **Caller file, function, and line number**
34
+ - **Auto-flush on process exit** via `process.on('beforeExit')`, `SIGINT`, and `SIGTERM`
41
35
 
42
- Tags let you slice costs by any dimension in the dashboard. Global tags (set in the constructor) apply to all calls. Per-call tags (set via the `llmtracer` property) override globals for that specific call.
36
+ ## Environment Variable Pattern
43
37
 
44
- ### Track cost by feature
38
+ ```typescript
39
+ import llmtracer from '@llmtracer/sdk';
45
40
 
46
- ```javascript
47
- await openai.chat.completions.create({
48
- model: "gpt-4o",
49
- messages: [...],
50
- llmtracer: { tags: { feature: "chat" } }
41
+ llmtracer.init({
42
+ apiKey: process.env.LLMTRACER_API_KEY,
43
+ debug: true, // prints token counts to console
51
44
  });
52
45
  ```
53
46
 
54
- ### Track cost by user (for B2B apps)
47
+ ## Multi-App Tracking
55
48
 
56
- ```javascript
57
- await openai.chat.completions.create({
58
- model: "gpt-4o",
59
- messages: [...],
60
- llmtracer: { tags: { feature: "chat", user_id: req.user.id } }
61
- });
49
+ If you have multiple services sharing an API key, set `appName` to filter by application in the dashboard:
50
+
51
+ ```typescript
52
+ llmtracer.init({ apiKey: 'lt_...', appName: 'billing-service' });
62
53
  ```
63
54
 
64
- ### Track cost by customer/tenant
55
+ Or via environment variable:
65
56
 
66
- ```javascript
67
- await openai.chat.completions.create({
68
- model: "gpt-4o",
69
- messages: [...],
70
- llmtracer: { tags: { customer: req.tenant.name, feature: "search" } }
71
- });
57
+ ```bash
58
+ export LLMTRACER_APP_NAME=billing-service
72
59
  ```
73
60
 
74
- ### Track cost by conversation
61
+ ## Trace Context and Tags
75
62
 
76
- ```javascript
77
- await openai.chat.completions.create({
78
- model: "gpt-4o",
79
- messages: [...],
80
- llmtracer: { tags: { conversation_id: sessionId, feature: "chat" } }
63
+ ```typescript
64
+ await llmtracer.trace({ tags: { feature: 'chat', user_id: 'u_sarah' } }, async () => {
65
+ const response = await openai.chat.completions.create({ ... });
81
66
  });
82
67
  ```
83
68
 
84
- ### Track environment (global tag)
69
+ Tags appear in the dashboard's Breakdown page and Top Tags card. Use them to answer questions like "which user costs the most?" or "which feature should I optimize?"
85
70
 
86
- ```javascript
87
- const tracer = new LLMTracer({
88
- apiKey: "lt_...",
89
- });
71
+ ### Tagging Patterns
90
72
 
91
- tracer.instrumentOpenAI(openai, {
92
- tags: { env: process.env.NODE_ENV } // applies to all calls
93
- });
94
- ```
73
+ | Pattern | Tag | Example |
74
+ |---------|-----|---------|
75
+ | Track cost by feature | `feature` | `"chat"`, `"search"`, `"summarize"` |
76
+ | Track cost by user | `user_id` | `"u_sarah"`, `"u_mike"` |
77
+ | Track cost by customer (B2B) | `customer` | `"acme-corp"`, `"initech"` |
78
+ | Track cost by conversation | `conversation_id` | `"conv_abc123"` |
79
+ | Track environment | `env` | `"production"`, `"staging"` |
95
80
 
96
- Tags appear in the dashboard's Breakdown page and Top Tags card. Use them to answer questions like "which customer costs the most?" or "which feature should I optimize?"
81
+ ## Supported Providers
82
+
83
+ | Provider | Package | Auto-patched |
84
+ |----------|---------|-------------|
85
+ | OpenAI | `openai` | ✅ |
86
+ | Anthropic | `@anthropic-ai/sdk` | ✅ |
87
+ | Google Gemini | `@google/genai` | ✅ |
97
88
 
98
89
  ## Serverless Usage
99
90
 
100
- In environments like AWS Lambda or Google Cloud Functions, call `flush()` before your function returns to ensure all events are sent:
91
+ Auto-flush handles graceful shutdown in long-running processes. For serverless environments (Lambda, Cloud Functions, etc.), flush before returning:
101
92
 
102
93
  ```typescript
103
94
  export async function handler(event) {
104
95
  const response = await openai.chat.completions.create({ ... });
105
- await tracer.flush();
96
+ await llmtracer.flush();
106
97
  return response;
107
98
  }
108
99
  ```
109
100
 
110
- ## Agentic Workflow Tracking
101
+ ## Debug Mode
111
102
 
112
- Group related LLM calls into traces with named phases:
103
+ Enable `debug: true` to print token counts to the console:
113
104
 
114
105
  ```typescript
115
- await tracer.trace("user-request-123", async (t) => {
116
- await t.phase("planning", async () => {
117
- await openai.chat.completions.create({ ... });
118
- });
119
-
120
- await t.phase("execution", async () => {
121
- await openai.chat.completions.create({ ... });
122
- });
123
- });
106
+ llmtracer.init({ apiKey: 'lt_...', debug: true });
107
+ ```
108
+
109
+ ```
110
+ [llmtracer] openai gpt-4o | 1,247 in → 384 out | $0.0094 | 1.2s
111
+ [llmtracer] anthropic claude-sonnet-4-5 | 2,100 in → 512 out (cache_read: 1,800) | $0.0031 | 0.8s
112
+ [llmtracer] google gemini-2.5-pro | 900 in → 280 out (thinking: 1,420) | $0.0067 | 2.1s
124
113
  ```
125
114
 
126
115
  ## Streaming Support
@@ -129,8 +118,8 @@ Streaming calls are instrumented automatically. Token counts are captured from t
129
118
 
130
119
  ```typescript
131
120
  const stream = await openai.chat.completions.create({
132
- model: "gpt-4o",
133
- messages: [{ role: "user", content: "Hello" }],
121
+ model: 'gpt-4o',
122
+ messages: [{ role: 'user', content: 'Hello' }],
134
123
  stream: true,
135
124
  });
136
125
 
@@ -141,55 +130,31 @@ for await (const chunk of stream) {
141
130
 
142
131
  ## Configuration
143
132
 
144
- | Option | Type | Default | Description |
145
- |---|---|---|---|
146
- | `apiKey` | `string` | *required* | Your LLM Tracer API key (starts with `lt_`) |
147
- | `endpoint` | `string` | Production URL | Ingestion endpoint URL |
148
- | `maxBatchSize` | `number` | `50` | Max events per batch before auto-flush |
149
- | `flushIntervalMs` | `number` | `10000` | Auto-flush interval in milliseconds |
150
- | `maxQueueSize` | `number` | `10000` | Max events in queue before dropping oldest |
151
- | `maxRetries` | `number` | `3` | Max retry attempts for failed flushes |
152
- | `retryBaseMs` | `number` | `1000` | Base delay for exponential backoff |
153
- | `sampleRate` | `number` | `1.0` | Sampling rate (0.0-1.0). `1.0` captures everything |
154
- | `capturePrompt` | `boolean` | `false` | Whether to capture full prompt content |
155
- | `debug` | `boolean` | `false` | Enable debug logging to console |
156
- | `onFlush` | `function` | `null` | Callback after each flush with stats |
157
- | `onError` | `function` | `null` | Callback on transport errors |
158
-
159
- ## API Reference
160
-
161
- ### `new LLMTracer(config)`
162
-
163
- Create a new tracer instance. See [Configuration](#configuration) for options.
164
-
165
- ### `tracer.instrumentOpenAI(client, options?)`
166
-
167
- Instrument an OpenAI client instance. All subsequent `chat.completions.create` calls (streaming and non-streaming) will be tracked automatically.
168
-
169
- - `client` -- an OpenAI client instance
170
- - `options.tags` -- key-value pairs attached to every event (e.g. `{ env: "production" }`)
171
-
172
- ### `tracer.flush(): Promise<void>`
173
-
174
- Flush all buffered events to the backend. Call this in serverless environments before the function returns.
175
-
176
- ### `tracer.trace(traceId, fn): Promise<void>`
177
-
178
- Track an agentic workflow. All LLM calls within the callback are grouped under the given `traceId`. Use `t.phase(name, fn)` inside the callback to label phases.
179
-
180
- ### `tracer.shutdown(): Promise<void>`
181
-
182
- Flush remaining events and stop the auto-flush timer. Call this on graceful shutdown.
133
+ | Option | Type | Default | Range | Description |
134
+ |---|---|---|---|---|
135
+ | `apiKey` | `string` | *required* | — | Your LLM Tracer API key (starts with `lt_`) |
136
+ | `appName` | `string` | `undefined` | | Application name for multi-app filtering. Falls back to `LLMTRACER_APP_NAME` env var |
137
+ | `endpoint` | `string` | Production URL | | Ingestion endpoint URL |
138
+ | `maxBatchSize` | `number` | `50` | 1–500 | Max events per HTTP request |
139
+ | `flushIntervalMs` | `number` | `5000` | 1000–60000 | Auto-flush interval in milliseconds |
140
+ | `maxQueueSize` | `number` | `1000` | 100–10000 | Max events in queue before dropping oldest |
141
+ | `maxRetries` | `number` | `3` | 0–10 | Max retry attempts for failed flushes |
142
+ | `sampleRate` | `number` | `1.0` | 0.01.0 | Sampling rate. `0.5` captures ~50% of events |
143
+ | `debug` | `boolean` | `false` | | Enable debug logging to console |
144
+ | `skipExitHandlers` | `boolean` | `false` | | Skip process exit handlers (for plugins/serverless) |
145
+
146
+ All numeric options are validated on `init()`. Out-of-range values are replaced with the default, and a warning is logged when `debug: true`.
183
147
 
184
148
  ## Reliability
185
149
 
186
150
  The SDK is designed to never interfere with your application:
187
151
 
188
- - **Never throws** -- all internal errors are swallowed silently (enable `debug: true` for visibility)
189
- - **Batching** -- events are queued and sent in configurable batches
190
- - **Retry with backoff** -- failed flushes are retried with exponential backoff and jitter
191
- - **Circuit breaker** -- after 5 consecutive failures, stops attempting for 60 seconds
192
- - **Queue overflow** -- drops oldest events when the queue exceeds `maxQueueSize`
152
+ - **Never throws** all internal errors are swallowed silently (enable `debug: true` for visibility)
153
+ - **Batching** events are queued and sent in batches of `maxBatchSize`
154
+ - **Retry with backoff** failed flushes are retried up to `maxRetries` times with exponential backoff (`min(1000 * 2^attempt, 30000)`) plus random jitter (0–1000ms)
155
+ - **Drop after retries** after `maxRetries` consecutive failures, the batch is dropped to prevent unbounded memory growth
156
+ - **Queue overflow** drops oldest events when the queue exceeds `maxQueueSize`
157
+ - **Sampling** — set `sampleRate` below 1.0 to reduce volume in high-throughput environments
193
158
 
194
159
  ## License
195
160
 
@@ -1,7 +1,15 @@
1
1
  export declare const config: {
2
2
  apiKey: string;
3
+ sessionId: string;
3
4
  endpoint: string;
4
5
  debug: boolean;
5
6
  enabled: boolean;
7
+ appName: string;
8
+ skipExitHandlers: boolean;
9
+ maxBatchSize: number;
10
+ flushIntervalMs: number;
11
+ maxQueueSize: number;
12
+ maxRetries: number;
13
+ sampleRate: number;
6
14
  };
7
15
  //# sourceMappingURL=config.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/config.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,MAAM;;;;;CAKlB,CAAC"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/config.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,MAAM;;;;;;;;;;;;;CAalB,CAAC"}
@@ -3,8 +3,16 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.config = void 0;
4
4
  exports.config = {
5
5
  apiKey: '',
6
+ sessionId: '',
6
7
  endpoint: 'https://us-central1-llmtracer-alt.cloudfunctions.net/v1Events',
7
8
  debug: false,
8
9
  enabled: false,
10
+ appName: '',
11
+ skipExitHandlers: false,
12
+ maxBatchSize: 50,
13
+ flushIntervalMs: 5000,
14
+ maxQueueSize: 1000,
15
+ maxRetries: 3,
16
+ sampleRate: 1.0,
9
17
  };
10
18
  //# sourceMappingURL=config.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/config.ts"],"names":[],"mappings":";;;AAAa,QAAA,MAAM,GAAG;IACpB,MAAM,EAAE,EAAE;IACV,QAAQ,EAAE,+DAA+D;IACzE,KAAK,EAAE,KAAK;IACZ,OAAO,EAAE,KAAK;CACf,CAAC"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/config.ts"],"names":[],"mappings":";;;AAAa,QAAA,MAAM,GAAG;IACpB,MAAM,EAAE,EAAE;IACV,SAAS,EAAE,EAAE;IACb,QAAQ,EAAE,+DAA+D;IACzE,KAAK,EAAE,KAAK;IACZ,OAAO,EAAE,KAAK;IACd,OAAO,EAAE,EAAE;IACX,gBAAgB,EAAE,KAAK;IACvB,YAAY,EAAE,EAAE;IAChB,eAAe,EAAE,IAAI;IACrB,YAAY,EAAE,IAAI;IAClB,UAAU,EAAE,CAAC;IACb,UAAU,EAAE,GAAG;CAChB,CAAC"}
@@ -1,12 +1,20 @@
1
1
  import { config } from './config';
2
2
  import * as transport from './transport';
3
3
  import * as patcher from './patcher';
4
- export declare const __version__ = "2.0.0";
5
- export declare function init(options?: {
4
+ export declare const __version__ = "2.4.0";
5
+ export interface InitOptions {
6
6
  apiKey?: string;
7
7
  debug?: boolean;
8
8
  endpoint?: string;
9
- }): void;
9
+ appName?: string;
10
+ skipExitHandlers?: boolean;
11
+ maxBatchSize?: number;
12
+ flushIntervalMs?: number;
13
+ maxQueueSize?: number;
14
+ maxRetries?: number;
15
+ sampleRate?: number;
16
+ }
17
+ export declare function init(options?: InitOptions): void;
10
18
  export declare function trace<T>(tags: Record<string, any>, fn: () => T | Promise<T>): T | Promise<T>;
11
19
  export declare function flush(): Promise<void>;
12
20
  export { patcher as _patcher, transport as _transport, config as _config };
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAElC,OAAO,KAAK,SAAS,MAAM,aAAa,CAAC;AACzC,OAAO,KAAK,OAAO,MAAM,WAAW,CAAC;AAErC,eAAO,MAAM,WAAW,UAAU,CAAC;AAEnC,wBAAgB,IAAI,CAAC,OAAO,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAsB5F;AAED,wBAAgB,KAAK,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAS5F;AAED,wBAAsB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAM3C;AAGD,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,SAAS,IAAI,UAAU,EAAE,MAAM,IAAI,OAAO,EAAE,CAAC;AAG3E,QAAA,MAAM,SAAS;;;;;CAAsC,CAAC;AACtD,eAAe,SAAS,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAElC,OAAO,KAAK,SAAS,MAAM,aAAa,CAAC;AACzC,OAAO,KAAK,OAAO,MAAM,WAAW,CAAC;AAGrC,eAAO,MAAM,WAAW,UAAU,CAAC;AAEnC,MAAM,WAAW,WAAW;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAUD,wBAAgB,IAAI,CAAC,OAAO,CAAC,EAAE,WAAW,GAAG,IAAI,CA6ChD;AAED,wBAAgB,KAAK,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAS5F;AAED,wBAAsB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAM3C;AAGD,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,SAAS,IAAI,UAAU,EAAE,MAAM,IAAI,OAAO,EAAE,CAAC;AAG3E,QAAA,MAAM,SAAS;;;;;CAAsC,CAAC;AACtD,eAAe,SAAS,CAAC"}
package/dist/cjs/index.js CHANGED
@@ -44,13 +44,42 @@ const transport = __importStar(require("./transport"));
44
44
  exports._transport = transport;
45
45
  const patcher = __importStar(require("./patcher"));
46
46
  exports._patcher = patcher;
47
- exports.__version__ = '2.0.0';
47
+ const crypto_1 = require("crypto");
48
+ exports.__version__ = '2.4.0';
49
+ function clampWithWarning(name, value, min, max, defaultVal, debug) {
50
+ if (typeof value !== 'number' || isNaN(value) || value < min || value > max) {
51
+ if (debug)
52
+ console.log(`[llmtracer] ${name}=${value} out of range [${min}, ${max}]. Using default ${defaultVal}.`);
53
+ return defaultVal;
54
+ }
55
+ return value;
56
+ }
48
57
  function init(options) {
49
58
  try {
50
59
  config_1.config.apiKey = options?.apiKey || process.env.LLMTRACER_API_KEY || '';
51
60
  config_1.config.debug = options?.debug || false;
52
61
  config_1.config.endpoint = options?.endpoint || 'https://us-central1-llmtracer-alt.cloudfunctions.net/v1Events';
62
+ config_1.config.appName = options?.appName || process.env.LLMTRACER_APP_NAME || '';
63
+ config_1.config.skipExitHandlers = options?.skipExitHandlers || false;
53
64
  config_1.config.enabled = Boolean(config_1.config.apiKey);
65
+ // Validate and apply new config options
66
+ const d = config_1.config.debug;
67
+ config_1.config.maxBatchSize = options?.maxBatchSize !== undefined
68
+ ? clampWithWarning('maxBatchSize', options.maxBatchSize, 1, 500, 50, d) : 50;
69
+ config_1.config.flushIntervalMs = options?.flushIntervalMs !== undefined
70
+ ? clampWithWarning('flushIntervalMs', options.flushIntervalMs, 1000, 60000, 5000, d) : 5000;
71
+ config_1.config.maxQueueSize = options?.maxQueueSize !== undefined
72
+ ? clampWithWarning('maxQueueSize', options.maxQueueSize, 100, 10000, 1000, d) : 1000;
73
+ config_1.config.maxRetries = options?.maxRetries !== undefined
74
+ ? clampWithWarning('maxRetries', options.maxRetries, 0, 10, 3, d) : 3;
75
+ config_1.config.sampleRate = options?.sampleRate !== undefined
76
+ ? clampWithWarning('sampleRate', options.sampleRate, 0.0, 1.0, 1.0, d) : 1.0;
77
+ try {
78
+ config_1.config.sessionId = (0, crypto_1.randomUUID)();
79
+ }
80
+ catch {
81
+ config_1.config.sessionId = '';
82
+ }
54
83
  if (!config_1.config.enabled) {
55
84
  if (config_1.config.debug)
56
85
  console.log('[llmtracer] No API key found. Tracing disabled.');
@@ -59,6 +88,9 @@ function init(options) {
59
88
  transport.start();
60
89
  patcher.patchOpenAI(config_1.config.debug);
61
90
  patcher.patchAnthropic(config_1.config.debug);
91
+ patcher.patchGoogle(config_1.config.debug);
92
+ if (config_1.config.debug)
93
+ console.log(`[llmtracer] Session: ${config_1.config.sessionId}`);
62
94
  if (config_1.config.debug)
63
95
  console.log('[llmtracer] Ready. Events \u2192 dashboard.llmtracer.com');
64
96
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAOA,oBAsBC;AAED,sBASC;AAED,sBAMC;AAhDD,qCAAkC;AAmD+B,wFAnDxD,eAAM,OAmDyD;AAlDxE,mDAAqC;AACrC,uDAAyC;AAiDE,+BAAU;AAhDrD,mDAAqC;AAgDjB,2BAAQ;AA9Cf,QAAA,WAAW,GAAG,OAAO,CAAC;AAEnC,SAAgB,IAAI,CAAC,OAAiE;IACpF,IAAI,CAAC;QACH,eAAM,CAAC,MAAM,GAAG,OAAO,EAAE,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,EAAE,CAAC;QACvE,eAAM,CAAC,KAAK,GAAG,OAAO,EAAE,KAAK,IAAI,KAAK,CAAC;QACvC,eAAM,CAAC,QAAQ,GAAG,OAAO,EAAE,QAAQ,IAAI,+DAA+D,CAAC;QACvG,eAAM,CAAC,OAAO,GAAG,OAAO,CAAC,eAAM,CAAC,MAAM,CAAC,CAAC;QAExC,IAAI,CAAC,eAAM,CAAC,OAAO,EAAE,CAAC;YACpB,IAAI,eAAM,CAAC,KAAK;gBAAE,OAAO,CAAC,GAAG,CAAC,iDAAiD,CAAC,CAAC;YACjF,OAAO;QACT,CAAC;QAED,SAAS,CAAC,KAAK,EAAE,CAAC;QAElB,OAAO,CAAC,WAAW,CAAC,eAAM,CAAC,KAAK,CAAC,CAAC;QAClC,OAAO,CAAC,cAAc,CAAC,eAAM,CAAC,KAAK,CAAC,CAAC;QAErC,IAAI,eAAM,CAAC,KAAK;YAAE,OAAO,CAAC,GAAG,CAAC,0DAA0D,CAAC,CAAC;IAC5F,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,eAAM,CAAC,OAAO,GAAG,KAAK,CAAC;QACvB,IAAI,eAAM,CAAC,KAAK;YAAE,OAAO,CAAC,GAAG,CAAC,8BAA8B,CAAC,qBAAqB,CAAC,CAAC;IACtF,CAAC;AACH,CAAC;AAED,SAAgB,KAAK,CAAI,IAAyB,EAAE,EAAwB;IAC1E,IAAI,CAAC;QACH,IAAI,CAAC,eAAM,CAAC,OAAO,EAAE,CAAC;YACpB,OAAO,EAAE,EAAE,CAAC;QACd,CAAC;QACD,OAAO,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IAC/B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,EAAE,CAAC;IACd,CAAC;AACH,CAAC;AAEM,KAAK,UAAU,KAAK;IACzB,IAAI,CAAC;QACH,MAAM,SAAS,CAAC,KAAK,EAAE,CAAC;IAC1B,CAAC;IAAC,MAAM,CAAC;QACP,2BAA2B;IAC7B,CAAC;AACH,CAAC;AAKD,4DAA4D;AAC5D,MAAM,SAAS,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,WAAW,EAAX,mBAAW,EAAE,CAAC;AACtD,kBAAe,SAAS,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,5 @@
1
1
  export declare function patchOpenAI(debug: boolean): void;
2
2
  export declare function patchAnthropic(debug: boolean): void;
3
+ export declare function patchGoogle(debug: boolean): void;
3
4
  export declare function unpatchAll(): void;
4
5
  //# sourceMappingURL=patcher.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"patcher.d.ts","sourceRoot":"","sources":["../../src/patcher.ts"],"names":[],"mappings":"AA4BA,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAyBhD;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAyBnD;AAED,wBAAgB,UAAU,IAAI,IAAI,CAMjC"}
1
+ {"version":3,"file":"patcher.d.ts","sourceRoot":"","sources":["../../src/patcher.ts"],"names":[],"mappings":"AA6BA,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CA6FhD;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAyBnD;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAqChD;AAED,wBAAgB,UAAU,IAAI,IAAI,CAMjC"}
@@ -2,10 +2,12 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.patchOpenAI = patchOpenAI;
4
4
  exports.patchAnthropic = patchAnthropic;
5
+ exports.patchGoogle = patchGoogle;
5
6
  exports.unpatchAll = unpatchAll;
6
7
  const wrapper_1 = require("./wrapper");
7
8
  const openai_1 = require("./providers/openai");
8
9
  const anthropic_1 = require("./providers/anthropic");
10
+ const google_1 = require("./providers/google");
9
11
  const originals = new Map();
10
12
  function getPackageVersion(packageName) {
11
13
  try {
@@ -47,9 +49,76 @@ function patchOpenAI(debug) {
47
49
  methodName: 'create',
48
50
  original: originalCreate,
49
51
  });
52
+ // ── Multi-modal endpoints ──────────────────────────────────
53
+ const capabilities = ['chat'];
54
+ // STT (Whisper)
55
+ try {
56
+ const sttModule = require('openai/resources/audio/transcriptions');
57
+ const TranscriptionsProto = sttModule.Transcriptions?.prototype;
58
+ if (TranscriptionsProto && !TranscriptionsProto._llmtracer_patched) {
59
+ const orig = TranscriptionsProto.create;
60
+ TranscriptionsProto.create = (0, wrapper_1.makeAsyncWrapper)(orig, 'openai', openai_1.parseTranscriptionResponse, null);
61
+ TranscriptionsProto._llmtracer_patched = true;
62
+ originals.set('openai.Transcriptions.create', { target: TranscriptionsProto, methodName: 'create', original: orig });
63
+ capabilities.push('stt');
64
+ }
65
+ }
66
+ catch { /* module not available */ }
67
+ // TTS
68
+ try {
69
+ const ttsModule = require('openai/resources/audio/speech');
70
+ const SpeechProto = ttsModule.Speech?.prototype;
71
+ if (SpeechProto && !SpeechProto._llmtracer_patched) {
72
+ const orig = SpeechProto.create;
73
+ SpeechProto.create = (0, wrapper_1.makeAsyncWrapper)(orig, 'openai', openai_1.parseSpeechResponse, null);
74
+ SpeechProto._llmtracer_patched = true;
75
+ originals.set('openai.Speech.create', { target: SpeechProto, methodName: 'create', original: orig });
76
+ capabilities.push('tts');
77
+ }
78
+ }
79
+ catch { /* module not available */ }
80
+ // Embeddings
81
+ try {
82
+ const embedModule = require('openai/resources/embeddings');
83
+ const EmbeddingsProto = embedModule.Embeddings?.prototype;
84
+ if (EmbeddingsProto && !EmbeddingsProto._llmtracer_patched) {
85
+ const orig = EmbeddingsProto.create;
86
+ EmbeddingsProto.create = (0, wrapper_1.makeAsyncWrapper)(orig, 'openai', openai_1.parseEmbeddingResponse, null);
87
+ EmbeddingsProto._llmtracer_patched = true;
88
+ originals.set('openai.Embeddings.create', { target: EmbeddingsProto, methodName: 'create', original: orig });
89
+ capabilities.push('embeddings');
90
+ }
91
+ }
92
+ catch { /* module not available */ }
93
+ // Images (DALL-E)
94
+ try {
95
+ const imgModule = require('openai/resources/images');
96
+ const ImagesProto = imgModule.Images?.prototype;
97
+ if (ImagesProto && !ImagesProto._llmtracer_patched) {
98
+ const orig = ImagesProto.generate;
99
+ ImagesProto.generate = (0, wrapper_1.makeAsyncWrapper)(orig, 'openai', openai_1.parseImageResponse, null);
100
+ ImagesProto._llmtracer_patched = true;
101
+ originals.set('openai.Images.generate', { target: ImagesProto, methodName: 'generate', original: orig });
102
+ capabilities.push('images');
103
+ }
104
+ }
105
+ catch { /* module not available */ }
106
+ // Moderations
107
+ try {
108
+ const modModule = require('openai/resources/moderations');
109
+ const ModerationsProto = modModule.Moderations?.prototype;
110
+ if (ModerationsProto && !ModerationsProto._llmtracer_patched) {
111
+ const orig = ModerationsProto.create;
112
+ ModerationsProto.create = (0, wrapper_1.makeAsyncWrapper)(orig, 'openai', openai_1.parseModerationResponse, null);
113
+ ModerationsProto._llmtracer_patched = true;
114
+ originals.set('openai.Moderations.create', { target: ModerationsProto, methodName: 'create', original: orig });
115
+ capabilities.push('moderation');
116
+ }
117
+ }
118
+ catch { /* module not available */ }
50
119
  if (debug) {
51
120
  const version = getPackageVersion('openai');
52
- console.log(`[llmtracer] \u2713 Patched openai (v${version})`);
121
+ console.log(`[llmtracer] \u2713 Patched openai (v${version}) \u2014 ${capabilities.join(' + ')}`);
53
122
  }
54
123
  }
55
124
  catch (e) {
@@ -83,6 +152,42 @@ function patchAnthropic(debug) {
83
152
  console.log(`[llmtracer] \u2717 anthropic not found or patch failed: ${e}`);
84
153
  }
85
154
  }
155
+ function patchGoogle(debug) {
156
+ try {
157
+ const googleModule = require('@google/genai');
158
+ const GenModel = googleModule.GenerativeModel?.prototype;
159
+ if (!GenModel)
160
+ throw new Error('GenerativeModel prototype not found');
161
+ if (GenModel._llmtracer_patched)
162
+ return;
163
+ const originalGenerate = GenModel.generateContent;
164
+ GenModel.generateContent = (0, wrapper_1.makeAsyncWrapper)(originalGenerate, 'google', google_1.parseGoogleResponse, google_1.wrapGoogleStream);
165
+ GenModel._llmtracer_patched = true;
166
+ originals.set('google.GenerativeModel.generateContent', {
167
+ target: GenModel,
168
+ methodName: 'generateContent',
169
+ original: originalGenerate,
170
+ });
171
+ // Also patch generateContentStream if it exists
172
+ if (typeof GenModel.generateContentStream === 'function') {
173
+ const originalStream = GenModel.generateContentStream;
174
+ GenModel.generateContentStream = (0, wrapper_1.makeAsyncWrapper)(originalStream, 'google', google_1.parseGoogleResponse, google_1.wrapGoogleStream);
175
+ originals.set('google.GenerativeModel.generateContentStream', {
176
+ target: GenModel,
177
+ methodName: 'generateContentStream',
178
+ original: originalStream,
179
+ });
180
+ }
181
+ if (debug) {
182
+ const version = getPackageVersion('@google/genai');
183
+ console.log(`[llmtracer] \u2713 Patched google (v${version})`);
184
+ }
185
+ }
186
+ catch (e) {
187
+ if (debug)
188
+ console.log(`[llmtracer] \u2717 google not found or patch failed: ${e}`);
189
+ }
190
+ }
86
191
  function unpatchAll() {
87
192
  for (const [, entry] of originals) {
88
193
  entry.target[entry.methodName] = entry.original;
@@ -1 +1 @@
1
- {"version":3,"file":"patcher.js","sourceRoot":"","sources":["../../src/patcher.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"patcher.js","sourceRoot":"","sources":["../../src/patcher.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"anthropic.d.ts","sourceRoot":"","sources":["../../../src/providers/anthropic.ts"],"names":[],"mappings":"AACA,OAAO,EAA4B,WAAW,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAGhF,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,GAAG,GAAG,YAAY,CAQhE;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,GAAG,CA4D1G"}
1
+ {"version":3,"file":"anthropic.d.ts","sourceRoot":"","sources":["../../../src/providers/anthropic.ts"],"names":[],"mappings":"AACA,OAAO,EAA4B,WAAW,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAGhF,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,GAAG,GAAG,YAAY,CA0BhE;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,GAAG,CA2E1G"}