@tensorcost/sdk 0.6.0 → 1.0.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 (93) hide show
  1. package/CHANGELOG.md +51 -8
  2. package/README.md +63 -99
  3. package/dist/adapters/crewai.d.ts +4 -0
  4. package/dist/adapters/crewai.d.ts.map +1 -0
  5. package/dist/adapters/crewai.js +6 -0
  6. package/dist/adapters/crewai.js.map +1 -0
  7. package/dist/adapters/langchain.d.ts +4 -0
  8. package/dist/adapters/langchain.d.ts.map +1 -0
  9. package/dist/adapters/langchain.js +6 -0
  10. package/dist/adapters/langchain.js.map +1 -0
  11. package/dist/adapters/llamaindex.d.ts +4 -0
  12. package/dist/adapters/llamaindex.d.ts.map +1 -0
  13. package/dist/adapters/llamaindex.js +6 -0
  14. package/dist/adapters/llamaindex.js.map +1 -0
  15. package/dist/adapters/vercel-ai.d.ts +4 -0
  16. package/dist/adapters/vercel-ai.d.ts.map +1 -0
  17. package/dist/adapters/vercel-ai.js +6 -0
  18. package/dist/adapters/vercel-ai.js.map +1 -0
  19. package/dist/admit-client.d.ts +39 -0
  20. package/dist/admit-client.d.ts.map +1 -0
  21. package/dist/admit-client.js +93 -0
  22. package/dist/admit-client.js.map +1 -0
  23. package/dist/applied.d.ts +6 -1
  24. package/dist/applied.d.ts.map +1 -1
  25. package/dist/applied.js +13 -1
  26. package/dist/applied.js.map +1 -1
  27. package/dist/circuit-observations.d.ts +12 -0
  28. package/dist/circuit-observations.d.ts.map +1 -0
  29. package/dist/circuit-observations.js +37 -0
  30. package/dist/circuit-observations.js.map +1 -0
  31. package/dist/circuit.d.ts +4 -1
  32. package/dist/circuit.d.ts.map +1 -1
  33. package/dist/circuit.js +13 -7
  34. package/dist/circuit.js.map +1 -1
  35. package/dist/config.d.ts +2 -3
  36. package/dist/config.d.ts.map +1 -1
  37. package/dist/config.js +52 -6
  38. package/dist/config.js.map +1 -1
  39. package/dist/decision.d.ts +11 -0
  40. package/dist/decision.d.ts.map +1 -0
  41. package/dist/decision.js +40 -0
  42. package/dist/decision.js.map +1 -0
  43. package/dist/errors.d.ts +20 -0
  44. package/dist/errors.d.ts.map +1 -1
  45. package/dist/errors.js +24 -0
  46. package/dist/errors.js.map +1 -1
  47. package/dist/index.d.ts +8 -3
  48. package/dist/index.d.ts.map +1 -1
  49. package/dist/index.js +7 -2
  50. package/dist/index.js.map +1 -1
  51. package/dist/layer.d.ts +27 -0
  52. package/dist/layer.d.ts.map +1 -0
  53. package/dist/layer.js +77 -0
  54. package/dist/layer.js.map +1 -0
  55. package/dist/providers/anthropic.d.ts +9 -0
  56. package/dist/providers/anthropic.d.ts.map +1 -1
  57. package/dist/providers/anthropic.js +100 -14
  58. package/dist/providers/anthropic.js.map +1 -1
  59. package/dist/providers/bedrock.d.ts +1 -1
  60. package/dist/providers/bedrock.d.ts.map +1 -1
  61. package/dist/providers/bedrock.js +4 -2
  62. package/dist/providers/bedrock.js.map +1 -1
  63. package/dist/providers/openai.d.ts +9 -0
  64. package/dist/providers/openai.d.ts.map +1 -1
  65. package/dist/providers/openai.js +108 -17
  66. package/dist/providers/openai.js.map +1 -1
  67. package/dist/providers/vertex.d.ts +1 -1
  68. package/dist/providers/vertex.d.ts.map +1 -1
  69. package/dist/providers/vertex.js +9 -2
  70. package/dist/providers/vertex.js.map +1 -1
  71. package/dist/proxy-client.d.ts +18 -6
  72. package/dist/proxy-client.d.ts.map +1 -1
  73. package/dist/proxy-client.js +65 -10
  74. package/dist/proxy-client.js.map +1 -1
  75. package/dist/sdk-layer.d.ts +26 -0
  76. package/dist/sdk-layer.d.ts.map +1 -0
  77. package/dist/sdk-layer.js +73 -0
  78. package/dist/sdk-layer.js.map +1 -0
  79. package/dist/transport.d.ts +3 -1
  80. package/dist/transport.d.ts.map +1 -1
  81. package/dist/transport.js +6 -2
  82. package/dist/transport.js.map +1 -1
  83. package/dist/types.d.ts +70 -15
  84. package/dist/types.d.ts.map +1 -1
  85. package/dist/version.d.ts +9 -0
  86. package/dist/version.d.ts.map +1 -0
  87. package/dist/version.js +10 -0
  88. package/dist/version.js.map +1 -0
  89. package/dist/wrap.d.ts +13 -17
  90. package/dist/wrap.d.ts.map +1 -1
  91. package/dist/wrap.js +62 -69
  92. package/dist/wrap.js.map +1 -1
  93. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -2,18 +2,61 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
- ## 0.6.0 — 2026-08-04
5
+ ## 1.0.0 — 2026-09-13
6
6
 
7
- SDK metadata story — lets you group traces by prompt template or deployment in
8
- the TensorCost dashboard — plus observe-only Google Vertex AI wrap.
7
+ Major release: control-layer ceilings replace the `appliedMode` boolean.
8
+ Effective layer is always `min(code.maxLayer, console published layer)`.
9
9
 
10
10
  ### Added
11
11
 
12
- **Google Vertex AI support (observe-only)** — `wrap()` detects `@google/genai`
13
- `GoogleGenAI` clients with `vertexai: true` and patches
14
- `models.generateContent` / `models.generateContentStream`. Observations use
15
- `provider: "vertex"`. Applied mode raises `TensorCostConfigError`.
16
- Gemini Developer API clients (`vertexai: false`) are not detected.
12
+ **Control layers (`maxLayer`)** — `off`, `observe`, `govern`, `steer`, `route`.
13
+ At `govern`, metadata-only `POST /admit` may refuse before the provider is
14
+ called. SDK fetches console ceiling via `GET /sdk-layer` (30s cache).
15
+
16
+ **Wire headers** — `x-tc-sdk-version`, `x-tc-sdk-capabilities`, `x-tc-max-layer`
17
+ on proxied requests; parses `x-tc-decision` on responses.
18
+
19
+ **Framework adapters** — `wrapLangChain`, `wrapLlamaIndex`, `wrapCrewAI`,
20
+ `wrapVercelAi`.
21
+
22
+ **Google Vertex AI (observe-only)** — `@google/genai` clients with
23
+ `vertexai: true`; `models.generateContent` / streaming variants.
24
+
25
+ **Grant intersection** — `maxGrants` caps console data grants from code;
26
+ prompt cache writes gated on `retain_completions`.
27
+
28
+ ### Changed
29
+
30
+ **Breaking:** `appliedMode` is deprecated — use `maxLayer: "route"`. Default
31
+ proxy header `x-tc-max-layer` is now `observe` (was `route`).
32
+
33
+ ### Fixed
34
+
35
+ Circuit breaker re-probes proxy after fail-open; cold-start layer cache no
36
+ longer skips decay window.
37
+
38
+ ## 0.7.0 — 2026-08-22
39
+
40
+ A-04 chargeback attribution — stamp end-customer cohort and product feature on
41
+ every observation and forward them through applied-mode proxy headers.
42
+
43
+ ### Added
44
+
45
+ **`customer` / `feature` options** — optional chargeback dimensions (max 128
46
+ chars each). Set at wrap time via `wrap({ customer, feature })` or
47
+ `TENSORCOST_CUSTOMER` / `TENSORCOST_FEATURE` env vars. Per-call overrides via
48
+ `.withMeta({ customer, feature })` on OpenAI and Anthropic clients. Values land
49
+ as top-level `customer` / `feature` fields on observations (not inside
50
+ `metadata`) and as `x-tc-customer` / `x-tc-feature` in applied mode.
51
+
52
+ Bedrock and Vertex clients support wrap-time defaults only (no `withMeta()`).
53
+
54
+ ## 0.6.0 — 2026-05-28
55
+
56
+ SDK metadata story — lets you group traces by prompt template or deployment in
57
+ the TensorCost dashboard.
58
+
59
+ ### Added
17
60
 
18
61
  **`deployment` option** — stamp a git SHA, CI run id, or release label on every
19
62
  observation emitted by a wrapped client. The backend groups by this value when
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @tensorcost/sdk
2
2
 
3
- One-line wrapper SDK for TensorCost — fire-and-forget LLM observability for OpenAI, Anthropic, and AWS Bedrock clients in Node.js.
3
+ One-line wrapper SDK for TensorCost — fire-and-forget LLM observability and optional inference control for OpenAI, Anthropic, AWS Bedrock, and Google Vertex AI clients in Node.js.
4
4
 
5
5
  ## Install
6
6
 
@@ -28,7 +28,7 @@ const resp = await client.chat.completions.create({
28
28
  });
29
29
  ```
30
30
 
31
- Anthropic is just as simple:
31
+ Anthropic works the same way:
32
32
 
33
33
  ```ts
34
34
  import Anthropic from "@anthropic-ai/sdk";
@@ -52,9 +52,11 @@ await client.messages.create({
52
52
  | `TENSORCOST_API_KEY` | Long-lived API key from the TensorCost console | Yes |
53
53
  | `TENSORCOST_BASE_URL` | Backend base URL | No (default `https://api.tensorcost.com`) |
54
54
  | `TENSORCOST_TENANT_ID` | Optional explicit tenant id | No |
55
- | `TENSORCOST_PROXY_URL` | Proxy base URL for applied mode | Required when `appliedMode: true` |
55
+ | `TENSORCOST_PROXY_URL` | Inference-proxy base URL | Required when `maxLayer` is `steer` or `route` |
56
56
  | `TENSORCOST_ENVIRONMENT` | Environment tag stamped on every observation | No |
57
57
  | `TENSORCOST_CONNECTION_ID` | Provider-connection identifier | No |
58
+ | `TENSORCOST_AGENT_ID` / `TENSORCOST_WORKFLOW_ID` | Agent-run attribution defaults | No |
59
+ | `TENSORCOST_CUSTOMER` / `TENSORCOST_FEATURE` | Chargeback tag defaults | No |
58
60
 
59
61
  Or pass explicitly:
60
62
 
@@ -65,32 +67,37 @@ const client = wrap(new OpenAI(...), {
65
67
  });
66
68
  ```
67
69
 
68
- ## Applied mode (Layer 2)
70
+ ## Control layers (`maxLayer`)
69
71
 
70
- When you enable applied mode, the SDK routes inference requests through the TensorCost inference-proxy instead of directly to the AI provider. The proxy decides per-request whether to re-route to an alternate provider or pass through unchanged — the SDK doesn't make that call.
72
+ v1.0 replaces the old `appliedMode` boolean with a **control-layer ceiling**. A layer is a ceiling, not a mode — the effective layer is always `min(your maxLayer, console published layer)`.
73
+
74
+ | Layer | Behavior |
75
+ |---|---|
76
+ | `off` | No SDK wiring; client returned unchanged |
77
+ | `observe` | Telemetry only (**default** when `maxLayer` is omitted) |
78
+ | `govern` | Metadata-only `POST /admit` before the provider call; may refuse unsafe calls |
79
+ | `steer` | Proxy on the path; proxy may steer without full live routing |
80
+ | `route` | Full applied-mode routing through the inference-proxy |
71
81
 
72
82
  ```ts
73
83
  const client = wrap(new OpenAI({ apiKey: process.env.OPENAI_API_KEY }), {
74
84
  apiKey: "tc_live_xxx",
75
- appliedMode: true,
76
- proxyUrl: "https://proxy.tensorcost.com", // or set TENSORCOST_PROXY_URL
77
- });
78
-
79
- // Use normally — the SDK redirects the client to the proxy transparently.
80
- // Observe-only telemetry still fires after every call.
81
- const resp = await client.chat.completions.create({
82
- model: "gpt-4o-mini",
83
- messages: [{ role: "user", content: "hi" }],
85
+ maxLayer: "route",
86
+ proxyUrl: "https://api.my-instance.tensorcost.com", // or TENSORCOST_PROXY_URL
84
87
  });
85
88
  ```
86
89
 
87
- `wrap()` throws `TensorCostConfigError` at `wrap()` time if `appliedMode: true` and neither `proxyUrl` nor `TENSORCOST_PROXY_URL` is set. AWS Bedrock is not supported in applied mode — SigV4 signing happens inside the AWS SDK before the proxy layer can intercept it; passing a Bedrock client with `appliedMode: true` throws `TensorCostConfigError` immediately. Observe-only mode works fine for Bedrock.
90
+ `wrap()` throws `TensorCostConfigError` when `maxLayer` is `steer` or `route` and no `proxyUrl` / `TENSORCOST_PROXY_URL` is set.
91
+
92
+ The SDK fetches the console-published ceiling from `GET /api/inference-proxy/v1/sdk-layer` (30s cache, decays to `govern` after 5 minutes unreachable). Govern refusals and proxy decisions surface in the `x-tc-decision` response header.
88
93
 
89
- See [`docs/features/inference-proxy-applied-mode.md`](../../docs/features/inference-proxy-applied-mode.md) for the proxy-side design.
94
+ `appliedMode: true` still works but is **deprecated** — it maps to `maxLayer: "route"` with a console warning. Prefer `maxLayer` in new code.
90
95
 
91
- ## Applied-mode hardening (v0.4.0)
96
+ See [ADR-0026](https://github.com/vaadhlabs/tensorcost/blob/main/docs/adr/0026-sdk-control-layer-ceilings.md) and [`docs/features/inference-proxy-applied-mode.md`](../../docs/features/inference-proxy-applied-mode.md).
92
97
 
93
- When `appliedMode: true`, you can configure retry policy, timeouts, lifecycle hooks, and the fail-open circuit breaker.
98
+ ## Proxy hardening
99
+
100
+ When `maxLayer` is `govern`, `steer`, or `route`, you can configure retries, timeouts, lifecycle hooks, and the fail-open circuit breaker.
94
101
 
95
102
  ### Retries
96
103
 
@@ -98,7 +105,7 @@ When `appliedMode: true`, you can configure retry policy, timeouts, lifecycle ho
98
105
  import { wrap, RetryConfig } from "@tensorcost/sdk";
99
106
 
100
107
  const client = wrap(new OpenAI(...), {
101
- appliedMode: true,
108
+ maxLayer: "route",
102
109
  proxyUrl: "...",
103
110
  retry: { maxAttempts: 5, baseDelayMs: 500, maxDelayMs: 30_000 },
104
111
  });
@@ -110,9 +117,9 @@ const client = wrap(new OpenAI(...), {
110
117
 
111
118
  ```ts
112
119
  const client = wrap(new OpenAI(...), {
113
- appliedMode: true,
120
+ maxLayer: "route",
114
121
  proxyUrl: "...",
115
- timeoutMs: 30_000, // 30 seconds; default 60_000
122
+ timeoutMs: 30_000, // default 60_000
116
123
  });
117
124
  ```
118
125
 
@@ -124,22 +131,20 @@ Surfaces as `TensorCostTimeoutError` (with `timeoutKind: "total"`) when exceeded
124
131
  import { wrap, LifecycleEvent } from "@tensorcost/sdk";
125
132
 
126
133
  const client = wrap(new OpenAI(...), {
127
- appliedMode: true,
134
+ maxLayer: "route",
128
135
  proxyUrl: "...",
129
136
  onLifecycleEvent(event: LifecycleEvent) {
130
- // event.kind is one of:
131
- // "before_request" | "after_response" | "on_retry"
132
- // | "on_error" | "on_fallback"
137
+ // "before_request" | "after_response" | "on_retry" | "on_error" | "on_fallback"
133
138
  console.log(event.kind, event.model, event.attemptNumber);
134
139
  },
135
140
  });
136
141
  ```
137
142
 
138
- Events contain only request metadata — never prompt content, response bodies, or credentials. Errors thrown by the callback are swallowed.
143
+ Events contain only request metadata — never prompt content, response bodies, or credentials.
139
144
 
140
145
  ### Typed errors
141
146
 
142
- Every failure from the proxy path is a subclass of `TensorCostError`. Import the classes from `@tensorcost/sdk`:
147
+ Every failure from the proxy path is a subclass of `TensorCostError`:
143
148
 
144
149
  ```ts
145
150
  import {
@@ -150,119 +155,78 @@ import {
150
155
  TensorCostQuotaError,
151
156
  TensorCostProviderError,
152
157
  } from "@tensorcost/sdk";
153
-
154
- try {
155
- await client.chat.completions.create({ model: "gpt-4o-mini", messages: [] });
156
- } catch (err) {
157
- if (err instanceof TensorCostQuotaError) {
158
- console.log("rate limited; retry after", err.retryAfterMs, "ms");
159
- } else if (err instanceof TensorCostError) {
160
- console.log("tensorcost error", err.status, err.attempt);
161
- }
162
- }
163
158
  ```
164
159
 
165
160
  ### Circuit breaker
166
161
 
167
- After 3 consecutive proxy 5xx responses the circuit opens and requests route directly to the provider (fail-open). The circuit closes after 5 consecutive probe successes.
162
+ After consecutive proxy failures the circuit opens and requests route directly to the provider (fail-open). Set `failOpenEnabled: false` when direct provider access is unavailable — proxy failures then surface as `TensorCostProxyError` instead of falling back.
163
+
164
+ ## Agent-run attribution
168
165
 
169
- Set `failOpenEnabled: false` if direct provider access is unavailable (e.g. in-VPC deployments) — proxy failures then surface as `TensorCostProxyError` instead of falling back.
166
+ Tag spend so **Router · Agent runs** can roll up cost per workflow:
170
167
 
171
168
  ```ts
172
169
  const client = wrap(new OpenAI(...), {
173
- appliedMode: true,
174
- proxyUrl: "...",
175
- failOpenEnabled: false, // raise on proxy error instead of falling through
170
+ apiKey: "tc_live_xxx",
171
+ agentId: "support-bot",
176
172
  });
173
+
174
+ const scoped = client.withMeta({ workflowId: crypto.randomUUID() });
175
+ await scoped.chat.completions.create({ model: "gpt-4o-mini", messages: [...] });
177
176
  ```
178
177
 
178
+ `customer` / `feature` are separate chargeback tags — not substitutes for `agentId` / `workflowId`.
179
+
179
180
  ## Fail-open guarantee
180
181
 
181
- If TensorCost is slow, down, or misconfigured, your customer call STILL succeeds. The SDK swallows internal errors and surfaces them via `console.warn`. The one exception: a missing API key throws `MissingConfigError` at `wrap()` time — silently dropping every observation would be worse than a loud import-time failure.
182
+ If TensorCost is slow, down, or misconfigured, your customer call still succeeds. The SDK swallows internal errors and surfaces them via `console.warn`. The one exception: a missing API key throws `MissingConfigError` at `wrap()` time.
182
183
 
183
184
  ## What is captured
184
185
 
185
186
  Only metadata — never prompt or completion content:
186
187
 
187
- - Provider + model
188
- - Operation (`chat.completions`, `completions`, `messages`)
189
- - Request / response timestamps
190
- - Input / output token counts (from the provider's `usage` field)
188
+ - Provider + model + operation + modality
189
+ - Request / response timestamps and token counts
191
190
  - Status (`success` / `error`) and error class/message on failure
192
- - A correlation UUID
191
+ - Correlation UUID, environment, agent/workflow ids, chargeback tags
193
192
 
194
193
  ## AWS Bedrock (observe-only)
195
194
 
196
195
  ```ts
197
- import {
198
- BedrockRuntimeClient,
199
- InvokeModelCommand,
200
- } from "@aws-sdk/client-bedrock-runtime";
196
+ import { BedrockRuntimeClient, InvokeModelCommand } from "@aws-sdk/client-bedrock-runtime";
201
197
  import { wrap } from "@tensorcost/sdk";
202
198
 
203
- // The only change: wrap() before passing the client to the rest of your code.
204
199
  const client = wrap(
205
200
  new BedrockRuntimeClient({ region: process.env.AWS_REGION ?? "us-east-1" }),
206
201
  );
207
-
208
- // Everything else is unchanged.
209
- const response = await client.send(
210
- new InvokeModelCommand({
211
- modelId: "anthropic.claude-3-haiku-20240307-v1:0",
212
- body: JSON.stringify({
213
- anthropic_version: "bedrock-2023-05-31",
214
- max_tokens: 64,
215
- messages: [{ role: "user", content: "What is 2 + 2?" }],
216
- }),
217
- contentType: "application/json",
218
- accept: "application/json",
219
- }),
220
- );
221
202
  ```
222
203
 
223
- The SDK registers a Smithy middleware on `client.middlewareStack` that intercepts every `client.send()` call and emits a fire-and-forget observation with the model id, token counts, latency, and status. Your code is otherwise unchanged.
224
-
225
- ### Supported commands
204
+ Supported commands: `InvokeModelCommand`, `ConverseCommand`, and their streaming counterparts (streaming records latency/status; per-chunk token accounting is a follow-up).
226
205
 
227
- | Command | Operation recorded | Token counts |
228
- |---|---|---|
229
- | `InvokeModelCommand` | `bedrock.invoke_model` | Parsed from response body (Anthropic-on-Bedrock and Nova/Titan shapes) |
230
- | `ConverseCommand` | `bedrock.converse` | Read from `response.usage.inputTokens / outputTokens` |
231
- | `InvokeModelWithResponseStreamCommand` | `bedrock.invoke_model_stream` | Not yet — placeholder observation with `null` tokens |
232
- | `ConverseStreamCommand` | `bedrock.converse_stream` | Not yet — placeholder observation with `null` tokens |
206
+ **Steer/route are not supported for Bedrock** — SigV4 signing happens inside the AWS SDK before the proxy can intercept. Use `maxLayer: "govern"` or lower for Bedrock telemetry.
233
207
 
234
- Per-chunk token accounting for streaming commands is a follow-up workstream. The placeholder observations record latency and success/error status, which is enough for alerting and anomaly detection. Token cost attribution will arrive once per-model pricing is wired in on the backend.
208
+ `@aws-sdk/client-bedrock-runtime` is an optional peer dependency.
235
209
 
236
- ### Applied mode
210
+ ## Google Vertex AI (observe-only)
237
211
 
238
- Applied mode (`{ appliedMode: true }`) is not supported for Bedrock. AWS Bedrock uses SigV4 request signing inside the AWS SDK before our middleware sees the request, so we cannot intercept and re-route it the way we do for OpenAI/Anthropic HTTP-Bearer clients. Calling `wrap(bedrockClient, { appliedMode: true })` throws `TensorCostConfigError` immediately.
212
+ Wrap `@google/genai` clients constructed with `vertexai: true`. `models.generateContent` and streaming variants emit observations with `provider: "vertex"`. Steer/route are not supported (same signing constraint as Bedrock).
239
213
 
240
- ### Installation
214
+ ## Framework adapters
241
215
 
242
- `@aws-sdk/client-bedrock-runtime` is an optional peer dependency — you only need it if you're using Bedrock. The SDK will not pull it in for OpenAI/Anthropic-only users.
216
+ Optional helpers for common LLM frameworks (observe + proxy paths where supported):
243
217
 
244
- ```bash
245
- npm install @aws-sdk/client-bedrock-runtime
246
- # or
247
- pnpm add @aws-sdk/client-bedrock-runtime
218
+ ```ts
219
+ import { wrapLangChain, wrapLlamaIndex, wrapCrewAI, wrapVercelAi } from "@tensorcost/sdk";
248
220
  ```
249
221
 
250
222
  ## Currently supported
251
223
 
252
- - OpenAI (`openai` >= 4.x) — `chat.completions.create`, `completions.create`
253
- - Anthropic (`@anthropic-ai/sdk` >= 0.x) — `messages.create`
254
- - AWS Bedrock (`@aws-sdk/client-bedrock-runtime` >= 3.x) — `InvokeModelCommand`, `ConverseCommand` (observe-only)
255
- - Google Vertex AI (`@google/genai` with `vertexai: true`) — `models.generateContent` (observe-only). Optional peer: `@google/genai`.
256
-
257
- ## Coming soon
258
-
259
- - Gemini Developer API wrap (`vertexai: false`)
260
- - Streaming token accounting for Bedrock (`InvokeModelWithResponseStreamCommand`, `ConverseStreamCommand`)
261
- - Tool / function calling (multi-call trace stitching)
262
-
263
- Note: **Azure OpenAI** is supported by wrapping the standard `AzureOpenAI`
264
- client (observations report `provider: "openai"`).
224
+ - OpenAI (`openai` >= 4.x) — chat, completions, embeddings, responses
225
+ - Anthropic (`@anthropic-ai/sdk`) — messages
226
+ - AWS Bedrock (`@aws-sdk/client-bedrock-runtime`) — invoke/converse (+ streaming placeholders)
227
+ - Google Vertex AI (`@google/genai` with `vertexai: true`) — generateContent
228
+ - Azure OpenAI — wrap the standard `AzureOpenAI` client (observations report `provider: "openai"`)
265
229
 
266
230
  ## License
267
231
 
268
- Proprietary — TensorCost.
232
+ Apache-2.0
@@ -0,0 +1,4 @@
1
+ import type { WrapOptions } from "../types.js";
2
+ /** Thin passthrough — wraps the LLM used by CrewAI agents. */
3
+ export declare function wrapCrewAI<T>(client: T, options?: WrapOptions): T;
4
+ //# sourceMappingURL=crewai.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crewai.d.ts","sourceRoot":"","sources":["../../src/adapters/crewai.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAG/C,8DAA8D;AAC9D,wBAAgB,UAAU,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,CAAC,CAEjE"}
@@ -0,0 +1,6 @@
1
+ import { wrap } from "../wrap.js";
2
+ /** Thin passthrough — wraps the LLM used by CrewAI agents. */
3
+ export function wrapCrewAI(client, options) {
4
+ return wrap(client, options);
5
+ }
6
+ //# sourceMappingURL=crewai.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crewai.js","sourceRoot":"","sources":["../../src/adapters/crewai.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAElC,8DAA8D;AAC9D,MAAM,UAAU,UAAU,CAAI,MAAS,EAAE,OAAqB;IAC5D,OAAO,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAC/B,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { WrapOptions } from "../types.js";
2
+ /** Thin passthrough — wraps the underlying OpenAI/Anthropic client. */
3
+ export declare function wrapLangChain<T>(client: T, options?: WrapOptions): T;
4
+ //# sourceMappingURL=langchain.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"langchain.d.ts","sourceRoot":"","sources":["../../src/adapters/langchain.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAG/C,uEAAuE;AACvE,wBAAgB,aAAa,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,CAAC,CAEpE"}
@@ -0,0 +1,6 @@
1
+ import { wrap } from "../wrap.js";
2
+ /** Thin passthrough — wraps the underlying OpenAI/Anthropic client. */
3
+ export function wrapLangChain(client, options) {
4
+ return wrap(client, options);
5
+ }
6
+ //# sourceMappingURL=langchain.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"langchain.js","sourceRoot":"","sources":["../../src/adapters/langchain.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAElC,uEAAuE;AACvE,MAAM,UAAU,aAAa,CAAI,MAAS,EAAE,OAAqB;IAC/D,OAAO,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAC/B,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { WrapOptions } from "../types.js";
2
+ /** Thin passthrough — wraps the underlying LLM client instance. */
3
+ export declare function wrapLlamaIndex<T>(client: T, options?: WrapOptions): T;
4
+ //# sourceMappingURL=llamaindex.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"llamaindex.d.ts","sourceRoot":"","sources":["../../src/adapters/llamaindex.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAG/C,mEAAmE;AACnE,wBAAgB,cAAc,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,CAAC,CAErE"}
@@ -0,0 +1,6 @@
1
+ import { wrap } from "../wrap.js";
2
+ /** Thin passthrough — wraps the underlying LLM client instance. */
3
+ export function wrapLlamaIndex(client, options) {
4
+ return wrap(client, options);
5
+ }
6
+ //# sourceMappingURL=llamaindex.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"llamaindex.js","sourceRoot":"","sources":["../../src/adapters/llamaindex.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAElC,mEAAmE;AACnE,MAAM,UAAU,cAAc,CAAI,MAAS,EAAE,OAAqB;IAChE,OAAO,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAC/B,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { WrapOptions } from "../types.js";
2
+ /** Thin passthrough — wraps the provider client passed to Vercel AI SDK. */
3
+ export declare function wrapVercelAi<T>(client: T, options?: WrapOptions): T;
4
+ //# sourceMappingURL=vercel-ai.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vercel-ai.d.ts","sourceRoot":"","sources":["../../src/adapters/vercel-ai.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAG/C,4EAA4E;AAC5E,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,CAAC,CAEnE"}
@@ -0,0 +1,6 @@
1
+ import { wrap } from "../wrap.js";
2
+ /** Thin passthrough — wraps the provider client passed to Vercel AI SDK. */
3
+ export function wrapVercelAi(client, options) {
4
+ return wrap(client, options);
5
+ }
6
+ //# sourceMappingURL=vercel-ai.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vercel-ai.js","sourceRoot":"","sources":["../../src/adapters/vercel-ai.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAElC,4EAA4E;AAC5E,MAAM,UAAU,YAAY,CAAI,MAAS,EAAE,OAAqB;IAC9D,OAAO,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAC/B,CAAC"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Govern-layer admit — metadata-only POST /api/inference-proxy/v1/admit.
3
+ *
4
+ * Fail-open on transport failure: the customer's call proceeds to the
5
+ * provider and an error observation is emitted when transport is available.
6
+ */
7
+ import type { ControlLayer } from "./layer.js";
8
+ import type { Operation, Provider } from "./types.js";
9
+ import type { ObservationTransport } from "./transport.js";
10
+ export interface AdmitMetadata {
11
+ provider: Provider;
12
+ model: string;
13
+ operation: Operation;
14
+ correlation_id: string;
15
+ environment?: string | null;
16
+ connection_id?: string | null;
17
+ agent_id?: string;
18
+ workflow_id?: string;
19
+ customer?: string;
20
+ feature?: string;
21
+ application?: string | null;
22
+ tags?: string[];
23
+ }
24
+ export interface AdmitRequestOptions {
25
+ baseUrl: string;
26
+ bearerToken: string;
27
+ maxLayer: ControlLayer;
28
+ metadata: AdmitMetadata;
29
+ transport?: ObservationTransport;
30
+ failOpen?: boolean;
31
+ timeoutMs?: number;
32
+ fetchImpl?: typeof fetch;
33
+ }
34
+ export interface AdmitResult {
35
+ allowed: boolean;
36
+ decisionHeader: string | null;
37
+ }
38
+ export declare function admitRequest(opts: AdmitRequestOptions): Promise<AdmitResult>;
39
+ //# sourceMappingURL=admit-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"admit-client.d.ts","sourceRoot":"","sources":["../src/admit-client.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAI3D,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,QAAQ,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,SAAS,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,YAAY,CAAC;IACvB,QAAQ,EAAE,aAAa,CAAC;IACxB,SAAS,CAAC,EAAE,oBAAoB,CAAC;IACjC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;CAC1B;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AAED,wBAAsB,YAAY,CAChC,IAAI,EAAE,mBAAmB,GACxB,OAAO,CAAC,WAAW,CAAC,CA8DtB"}
@@ -0,0 +1,93 @@
1
+ /**
2
+ * Govern-layer admit — metadata-only POST /api/inference-proxy/v1/admit.
3
+ *
4
+ * Fail-open on transport failure: the customer's call proceeds to the
5
+ * provider and an error observation is emitted when transport is available.
6
+ */
7
+ import { ADMIT_PATH } from "./layer.js";
8
+ import { SDK_VERSION, sdkCapabilityHeader } from "./version.js";
9
+ export async function admitRequest(opts) {
10
+ const fetchImpl = opts.fetchImpl ?? globalThis.fetch.bind(globalThis);
11
+ const url = `${opts.baseUrl.replace(/\/+$/, "")}${ADMIT_PATH}`;
12
+ const headers = {
13
+ Authorization: `Bearer ${opts.bearerToken}`,
14
+ "Content-Type": "application/json",
15
+ "x-tc-sdk-version": SDK_VERSION,
16
+ "x-tc-sdk-capabilities": sdkCapabilityHeader(),
17
+ "x-tc-max-layer": opts.maxLayer,
18
+ };
19
+ const body = {
20
+ provider: opts.metadata.provider,
21
+ model: opts.metadata.model,
22
+ operation: opts.metadata.operation,
23
+ correlation_id: opts.metadata.correlation_id,
24
+ ...(opts.metadata.environment ? { environment: opts.metadata.environment } : {}),
25
+ ...(opts.metadata.connection_id ? { connection_id: opts.metadata.connection_id } : {}),
26
+ ...(opts.metadata.agent_id ? { agent_id: opts.metadata.agent_id } : {}),
27
+ ...(opts.metadata.workflow_id ? { workflow_id: opts.metadata.workflow_id } : {}),
28
+ ...(opts.metadata.customer ? { customer: opts.metadata.customer } : {}),
29
+ ...(opts.metadata.feature ? { feature: opts.metadata.feature } : {}),
30
+ ...(opts.metadata.application ? { application: opts.metadata.application } : {}),
31
+ ...(opts.metadata.tags && opts.metadata.tags.length > 0
32
+ ? { tags: opts.metadata.tags.join(",") }
33
+ : {}),
34
+ };
35
+ const controller = new AbortController();
36
+ const timer = setTimeout(() => controller.abort(), opts.timeoutMs ?? 5_000);
37
+ try {
38
+ const resp = await fetchImpl(url, {
39
+ method: "POST",
40
+ headers,
41
+ body: JSON.stringify(body),
42
+ signal: controller.signal,
43
+ });
44
+ const decisionHeader = resp.headers.get("x-tc-decision");
45
+ if (resp.status === 403) {
46
+ return { allowed: false, decisionHeader };
47
+ }
48
+ if (!resp.ok) {
49
+ throw new Error(`admit POST failed status=${resp.status}`);
50
+ }
51
+ return { allowed: true, decisionHeader };
52
+ }
53
+ catch (err) {
54
+ if (opts.failOpen !== false) {
55
+ postAdmitFailureObservation(opts, err);
56
+ return { allowed: true, decisionHeader: null };
57
+ }
58
+ throw err;
59
+ }
60
+ finally {
61
+ clearTimeout(timer);
62
+ }
63
+ }
64
+ function postAdmitFailureObservation(opts, err) {
65
+ if (!opts.transport)
66
+ return;
67
+ try {
68
+ opts.transport.post({
69
+ sdk_version: SDK_VERSION,
70
+ provider: opts.metadata.provider,
71
+ model: opts.metadata.model,
72
+ operation: opts.metadata.operation,
73
+ request_at: new Date().toISOString(),
74
+ response_at: new Date().toISOString(),
75
+ input_tokens: null,
76
+ output_tokens: null,
77
+ cost_usd_cents: null,
78
+ status: "success",
79
+ error_message: null,
80
+ correlation_id: opts.metadata.correlation_id,
81
+ ...(opts.metadata.environment ? { environment: opts.metadata.environment } : {}),
82
+ ...(opts.metadata.connection_id ? { connection_id: opts.metadata.connection_id } : {}),
83
+ metadata: {
84
+ decision_action: "allow",
85
+ decision_reason: "admit_unavailable",
86
+ },
87
+ });
88
+ }
89
+ catch {
90
+ /* belt-and-suspenders */
91
+ }
92
+ }
93
+ //# sourceMappingURL=admit-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"admit-client.js","sourceRoot":"","sources":["../src/admit-client.ts"],"names":[],"mappings":"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"}
package/dist/applied.d.ts CHANGED
@@ -84,7 +84,12 @@ declare function azureAuth(apiKey: string): string;
84
84
  * - If the client doesn't expose `apiKey` (can't build `x-tc-provider-auth`).
85
85
  * - If the provider is "bedrock" (not yet supported in v1).
86
86
  */
87
- export declare function installAppliedMode(client: unknown, proxyUrl: string, provider: "openai" | "anthropic"): void;
87
+ export declare function installAppliedMode(client: unknown, proxyUrl: string, provider: "openai" | "anthropic", scope?: {
88
+ application?: string | null;
89
+ tags?: string[];
90
+ customer?: string | null;
91
+ feature?: string | null;
92
+ }): void;
88
93
  export declare const PROXY_PATH_SUFFIX = "/api/inference-proxy/v1/chat/completions";
89
94
  export declare const __test__: {
90
95
  readBaseUrl: typeof readBaseUrl;
@@ -1 +1 @@
1
- {"version":3,"file":"applied.d.ts","sourceRoot":"","sources":["../src/applied.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAOH;;;GAGG;AAEH,gEAAgE;AAChE,iBAAS,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAE1C;AAED,oDAAoD;AACpD,iBAAS,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAE7C;AAED;;;;;GAKG;AACH,iBAAS,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,GAAG,IAAI,CAMnE;AAED;;;GAGG;AACH,iBAAS,UAAU,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,GAAG,IAAI,CAGlE;AAED;;;;;;;;GAQG;AACH,iBAAS,aAAa,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAI/D;AAED;;;;;;;;GAQG;AACH,iBAAS,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEzC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,OAAO,EACf,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,QAAQ,GAAG,WAAW,GAC/B,IAAI,CAiEN;AAED,eAAO,MAAM,iBAAiB,6CAAa,CAAC;AAE5C,eAAO,MAAM,QAAQ;;;;;;;CAOpB,CAAC"}
1
+ {"version":3,"file":"applied.d.ts","sourceRoot":"","sources":["../src/applied.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAOH;;;GAGG;AAEH,gEAAgE;AAChE,iBAAS,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAE1C;AAED,oDAAoD;AACpD,iBAAS,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAE7C;AAED;;;;;GAKG;AACH,iBAAS,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,GAAG,IAAI,CAMnE;AAED;;;GAGG;AACH,iBAAS,UAAU,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,GAAG,IAAI,CAGlE;AAED;;;;;;;;GAQG;AACH,iBAAS,aAAa,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAI/D;AAED;;;;;;;;GAQG;AACH,iBAAS,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEzC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,OAAO,EACf,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,QAAQ,GAAG,WAAW,EAChC,KAAK,CAAC,EAAE;IACN,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB,GACA,IAAI,CA6EN;AAED,eAAO,MAAM,iBAAiB,6CAAa,CAAC;AAE5C,eAAO,MAAM,QAAQ;;;;;;;CAOpB,CAAC"}
package/dist/applied.js CHANGED
@@ -107,7 +107,7 @@ function azureAuth(apiKey) {
107
107
  * - If the client doesn't expose `apiKey` (can't build `x-tc-provider-auth`).
108
108
  * - If the provider is "bedrock" (not yet supported in v1).
109
109
  */
110
- export function installAppliedMode(client, proxyUrl, provider) {
110
+ export function installAppliedMode(client, proxyUrl, provider, scope) {
111
111
  if (provider === "bedrock") {
112
112
  // Bedrock uses SigV4 signing on regional HTTPS endpoints. The AWS
113
113
  // SDK does not expose baseURL / defaultHeaders in the same shape,
@@ -160,6 +160,18 @@ export function installAppliedMode(client, proxyUrl, provider) {
160
160
  : {};
161
161
  headers["x-tc-provider-url"] = originalBaseUrl;
162
162
  headers["x-tc-provider-auth"] = providerAuth;
163
+ if (scope?.application) {
164
+ headers["x-tc-application"] = scope.application;
165
+ }
166
+ if (scope?.tags && scope.tags.length > 0) {
167
+ headers["x-tc-tags"] = scope.tags.join(",");
168
+ }
169
+ if (scope?.customer) {
170
+ headers["x-tc-customer"] = scope.customer;
171
+ }
172
+ if (scope?.feature) {
173
+ headers["x-tc-feature"] = scope.feature;
174
+ }
163
175
  c["defaultHeaders"] = headers;
164
176
  }
165
177
  export const PROXY_PATH_SUFFIX = PROXY_PATH;