@tensorcost/sdk 1.3.3 → 1.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.
- package/CHANGELOG.md +226 -1
- package/README.md +35 -16
- package/dist/admit-client.d.ts +56 -0
- package/dist/admit-client.d.ts.map +1 -1
- package/dist/admit-client.js +93 -11
- package/dist/admit-client.js.map +1 -1
- package/dist/applied.d.ts +114 -0
- package/dist/applied.d.ts.map +1 -1
- package/dist/applied.js +40 -50
- package/dist/applied.js.map +1 -1
- package/dist/errors.d.ts +179 -24
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +165 -23
- package/dist/errors.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/provider-errors.d.ts +15 -0
- package/dist/provider-errors.d.ts.map +1 -0
- package/dist/provider-errors.js +69 -0
- package/dist/provider-errors.js.map +1 -0
- package/dist/providers/anthropic.d.ts +54 -0
- package/dist/providers/anthropic.d.ts.map +1 -1
- package/dist/providers/anthropic.js +57 -14
- package/dist/providers/anthropic.js.map +1 -1
- package/dist/providers/bedrock.d.ts +4 -1
- package/dist/providers/bedrock.d.ts.map +1 -1
- package/dist/providers/bedrock.js +3 -2
- package/dist/providers/bedrock.js.map +1 -1
- package/dist/providers/detect.d.ts.map +1 -1
- package/dist/providers/detect.js +9 -6
- package/dist/providers/detect.js.map +1 -1
- package/dist/providers/openai.d.ts.map +1 -1
- package/dist/providers/openai.js +21 -44
- package/dist/providers/openai.js.map +1 -1
- package/dist/providers/vertex.d.ts +17 -0
- package/dist/providers/vertex.d.ts.map +1 -1
- package/dist/providers/vertex.js +5 -2
- package/dist/providers/vertex.js.map +1 -1
- package/dist/proxy-client.d.ts +157 -0
- package/dist/proxy-client.d.ts.map +1 -1
- package/dist/proxy-client.js +189 -175
- package/dist/proxy-client.js.map +1 -1
- package/dist/refusal.d.ts +43 -0
- package/dist/refusal.d.ts.map +1 -0
- package/dist/refusal.js +154 -0
- package/dist/refusal.js.map +1 -0
- package/dist/transport.d.ts.map +1 -1
- package/dist/transport.js +45 -13
- package/dist/transport.js.map +1 -1
- package/dist/types.d.ts +15 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/wrap-overhead.d.ts +43 -0
- package/dist/wrap-overhead.d.ts.map +1 -1
- package/dist/wrap-overhead.js +28 -1
- package/dist/wrap-overhead.js.map +1 -1
- package/dist/wrap.d.ts +25 -0
- package/dist/wrap.d.ts.map +1 -1
- package/dist/wrap.js +51 -8
- package/dist/wrap.js.map +1 -1
- package/package.json +1 -1
package/dist/errors.js
CHANGED
|
@@ -8,11 +8,27 @@
|
|
|
8
8
|
* Hierarchy:
|
|
9
9
|
*
|
|
10
10
|
* TensorCostError (base)
|
|
11
|
-
* ├── TensorCostNetworkError couldn't reach the proxy at all
|
|
12
|
-
* ├── TensorCostTimeoutError request or idle window exceeded limit
|
|
13
|
-
* ├── TensorCostProxyError proxy responded with 5xx
|
|
14
|
-
* ├── TensorCostQuotaError proxy
|
|
15
|
-
*
|
|
11
|
+
* ├── TensorCostNetworkError couldn't reach the proxy at all ┐
|
|
12
|
+
* ├── TensorCostTimeoutError request or idle window exceeded limit │ outages: the only
|
|
13
|
+
* ├── TensorCostProxyError proxy responded with 5xx │ errors that may fall
|
|
14
|
+
* ├── TensorCostQuotaError proxy 429, or 402 plan ceiling ┘ back to the provider
|
|
15
|
+
* ├── TensorCostProviderError proxy relayed an upstream provider 4xx
|
|
16
|
+
* │ (rethrown as the provider SDK's own error
|
|
17
|
+
* │ type when the client can build one)
|
|
18
|
+
* ├── TensorCostGatewayRejectedError non-JSON 4xx from in front of TensorCost
|
|
19
|
+
* ├── TensorCostKeyRejectedError token exchange rejected the API key
|
|
20
|
+
* └── TensorCostRefusedError TensorCost refused the call (terminal)
|
|
21
|
+
* ├── TensorCostRunBudgetExceededError
|
|
22
|
+
* ├── TensorCostRunStoppedError
|
|
23
|
+
* ├── TensorCostPeriodBudgetExceededError
|
|
24
|
+
* │ └── TensorCostBudgetHardCapError
|
|
25
|
+
* ├── TensorCostModelGovernanceDeniedError
|
|
26
|
+
* ├── TensorCostGuardrailHardStopError
|
|
27
|
+
* ├── TensorCostComplianceDeniedError
|
|
28
|
+
* └── TensorCostComplianceTeamMismatchError
|
|
29
|
+
*
|
|
30
|
+
* A refusal code this SDK version doesn't model still arrives as a plain
|
|
31
|
+
* TensorCostRefusedError with its `code`, `reason` and message intact.
|
|
16
32
|
*
|
|
17
33
|
* All subclasses carry:
|
|
18
34
|
* - `rootCause` the underlying Error, if any (avoids clash with ES2022 Error.cause)
|
|
@@ -62,7 +78,9 @@ export class TensorCostProxyError extends TensorCostError {
|
|
|
62
78
|
}
|
|
63
79
|
}
|
|
64
80
|
/**
|
|
65
|
-
* The proxy returned 429 Too Many Requests
|
|
81
|
+
* The proxy returned 429 Too Many Requests (TensorCost's own rate limit),
|
|
82
|
+
* or 402 with no refusal body (the plan's monthly proxy-request ceiling;
|
|
83
|
+
* `status` says which). Neither carries a refusal, so both may fall back.
|
|
66
84
|
* `retryAfterMs` is set when the response included a `Retry-After` header.
|
|
67
85
|
*/
|
|
68
86
|
export class TensorCostQuotaError extends TensorCostError {
|
|
@@ -72,13 +90,64 @@ export class TensorCostQuotaError extends TensorCostError {
|
|
|
72
90
|
}
|
|
73
91
|
}
|
|
74
92
|
/**
|
|
75
|
-
* The proxy
|
|
76
|
-
*
|
|
77
|
-
*
|
|
93
|
+
* The proxy reached the upstream provider and relayed the provider's own
|
|
94
|
+
* 4xx (OpenAI 400 invalid request, Anthropic 401, and so on). `status` is
|
|
95
|
+
* the provider's status and `body` is what the provider sent, parsed as
|
|
96
|
+
* JSON when it was JSON. Never falls back: the provider would only answer
|
|
97
|
+
* the same way again.
|
|
78
98
|
*/
|
|
79
99
|
export class TensorCostProviderError extends TensorCostError {
|
|
80
100
|
constructor(message, opts = {}) {
|
|
81
101
|
super(message, opts);
|
|
102
|
+
this.body = opts.body ?? null;
|
|
103
|
+
this.headers = opts.headers ?? {};
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Something in front of TensorCost turned the request away: a 4xx whose
|
|
108
|
+
* body isn't JSON (an HTML page from a firewall or load balancer, or
|
|
109
|
+
* nothing at all). Neither TensorCost nor the provider saw the call.
|
|
110
|
+
* Terminal: going around it would mean going around whatever put the
|
|
111
|
+
* firewall there, and the next call would most likely meet it too.
|
|
112
|
+
*/
|
|
113
|
+
export class TensorCostGatewayRejectedError extends TensorCostError {
|
|
114
|
+
constructor(status, bodyText, opts = {}) {
|
|
115
|
+
super(`tensorcost: the request was rejected with ${status} before it reached TensorCost ` +
|
|
116
|
+
"or the provider (for example by a firewall or load balancer in front of the " +
|
|
117
|
+
"TensorCost proxy). Check the proxy URL and anything in front of it.", { ...opts, status });
|
|
118
|
+
this.bodyText = bodyText;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* The token exchange rejected the TensorCost API key (401 or 403): revoked,
|
|
123
|
+
* mistyped, or issued for a different tenant than the one configured. Not
|
|
124
|
+
* an outage, so it never fails open.
|
|
125
|
+
*/
|
|
126
|
+
export class TensorCostKeyRejectedError extends TensorCostError {
|
|
127
|
+
constructor(status, opts = {}) {
|
|
128
|
+
super(`tensorcost: the TensorCost key was rejected (${status}); check it's current and ` +
|
|
129
|
+
"that it belongs to the configured tenant id", { ...opts, status });
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* TensorCost answered and the answer is no: a budget, a stop, a policy.
|
|
134
|
+
*
|
|
135
|
+
* Every refusal is terminal. It never retries and never falls back to the
|
|
136
|
+
* provider, because the proxy that sent it is healthy and the refusal is
|
|
137
|
+
* the product. `code` is the server's refusal code (null when the server
|
|
138
|
+
* refused without naming one), `reason` its optional sub-reason, and
|
|
139
|
+
* `detail` the refusal object as the server sent it.
|
|
140
|
+
*
|
|
141
|
+
* Subclasses cover the codes this SDK version models. Anything else, a
|
|
142
|
+
* code added on the server after this release included, is thrown as this
|
|
143
|
+
* class directly so it is still terminal.
|
|
144
|
+
*/
|
|
145
|
+
export class TensorCostRefusedError extends TensorCostError {
|
|
146
|
+
constructor(message, refusal = {}, opts = {}) {
|
|
147
|
+
super(message, opts);
|
|
148
|
+
this.code = refusal.code ?? null;
|
|
149
|
+
this.reason = refusal.reason ?? null;
|
|
150
|
+
this.detail = refusal.detail ?? null;
|
|
82
151
|
}
|
|
83
152
|
}
|
|
84
153
|
/**
|
|
@@ -93,38 +162,112 @@ export class TensorCostProviderError extends TensorCostError {
|
|
|
93
162
|
* anyway, bill the customer, and reduce the cap to a suggestion.
|
|
94
163
|
*
|
|
95
164
|
* See `shouldFallBackToProvider()` in proxy-client.ts, which is the single
|
|
96
|
-
* predicate every provider wrapper consults before falling back.
|
|
165
|
+
* predicate every provider wrapper consults before falling back. Since
|
|
166
|
+
* 1.5.0 it is an allow-list of outages, so a refusal can't slip past it.
|
|
97
167
|
*/
|
|
98
|
-
export class TensorCostRunBudgetExceededError extends
|
|
168
|
+
export class TensorCostRunBudgetExceededError extends TensorCostRefusedError {
|
|
99
169
|
constructor(message, workflowId, capCents, spentCents, opts = {}) {
|
|
100
|
-
super(message, opts);
|
|
170
|
+
super(message, { code: "RUN_BUDGET_EXCEEDED", detail: opts.detail ?? null }, opts);
|
|
101
171
|
this.workflowId = workflowId;
|
|
102
172
|
this.capCents = capCents;
|
|
103
173
|
this.spentCents = spentCents;
|
|
104
174
|
}
|
|
105
175
|
}
|
|
176
|
+
/**
|
|
177
|
+
* An operator stopped the agent run this call belongs to, and the proxy
|
|
178
|
+
* refused the request (HTTP 403, `code: "RUN_STOPPED"`).
|
|
179
|
+
*
|
|
180
|
+
* Terminal for the same reason as the budget refusals: a stop is a decision
|
|
181
|
+
* from a healthy proxy, so falling back to the provider would simply undo
|
|
182
|
+
* it. Carries the who / when / why the proxy recorded.
|
|
183
|
+
*/
|
|
184
|
+
export class TensorCostRunStoppedError extends TensorCostRefusedError {
|
|
185
|
+
/**
|
|
186
|
+
* Build the error from the proxy's 403 `error` object. Shared by the
|
|
187
|
+
* chat-completions client and the govern-layer admit client, which both
|
|
188
|
+
* receive the same body.
|
|
189
|
+
*/
|
|
190
|
+
static fromProxyBody(detail, opts = {}) {
|
|
191
|
+
const str = (v) => (typeof v === "string" ? v : null);
|
|
192
|
+
return new TensorCostRunStoppedError(str(detail?.["message"]) ?? "tensorcost: agent run was stopped", {
|
|
193
|
+
workflowId: str(detail?.["workflow_id"]),
|
|
194
|
+
stoppedBy: str(detail?.["stopped_by"]),
|
|
195
|
+
stoppedAt: str(detail?.["stopped_at"]),
|
|
196
|
+
reason: str(detail?.["reason"]),
|
|
197
|
+
}, { ...opts, detail: detail ?? null });
|
|
198
|
+
}
|
|
199
|
+
constructor(message, detail = {}, opts = {}) {
|
|
200
|
+
super(message, { code: "RUN_STOPPED", reason: detail.reason ?? null, detail: opts.detail ?? null }, { ...opts, status: opts.status ?? 403 });
|
|
201
|
+
this.code = "RUN_STOPPED";
|
|
202
|
+
this.workflowId = detail.workflowId ?? null;
|
|
203
|
+
this.stoppedBy = detail.stoppedBy ?? null;
|
|
204
|
+
this.stoppedAt = detail.stoppedAt ?? null;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
106
207
|
/**
|
|
107
208
|
* Daily or monthly agent/team spend cap exceeded (HTTP 403,
|
|
108
209
|
* `code: "PERIOD_BUDGET_EXCEEDED"`). Terminal — must not fall back to the
|
|
109
210
|
* provider or the cap becomes a suggestion.
|
|
110
211
|
*/
|
|
111
|
-
export class TensorCostPeriodBudgetExceededError extends
|
|
212
|
+
export class TensorCostPeriodBudgetExceededError extends TensorCostRefusedError {
|
|
112
213
|
constructor(message, scope, period, capCents, spentCents, opts = {}) {
|
|
113
|
-
super(message,
|
|
214
|
+
super(message, {
|
|
215
|
+
code: opts.code ?? "PERIOD_BUDGET_EXCEEDED",
|
|
216
|
+
reason: opts.reason ?? null,
|
|
217
|
+
detail: opts.detail ?? null,
|
|
218
|
+
}, opts);
|
|
114
219
|
this.scope = scope;
|
|
115
220
|
this.period = period;
|
|
116
221
|
this.capCents = capCents;
|
|
117
222
|
this.spentCents = spentCents;
|
|
118
223
|
}
|
|
119
224
|
}
|
|
225
|
+
/**
|
|
226
|
+
* A money budget's hard cap refused the call (HTTP 403).
|
|
227
|
+
*
|
|
228
|
+
* The server sends `error.code: "PERIOD_BUDGET_EXCEEDED"` with
|
|
229
|
+
* `error.budget_code: "BUDGET_HARD_CAP"` (that code is what made 1.4.0
|
|
230
|
+
* treat it as terminal), and older servers sent `error.code:
|
|
231
|
+
* "BUDGET_HARD_CAP"`. Both map here. `code` keeps whichever the server
|
|
232
|
+
* sent; `budgetCode` is always "BUDGET_HARD_CAP".
|
|
233
|
+
*
|
|
234
|
+
* It extends TensorCostPeriodBudgetExceededError because 1.4.0 already
|
|
235
|
+
* raised that class for the current wire shape, so an existing `catch` for
|
|
236
|
+
* it keeps working, and scope / period / capCents / spentCents are filled
|
|
237
|
+
* the same way.
|
|
238
|
+
*
|
|
239
|
+
* `reason: "spend_not_known_yet"` (with `retryable: true` on the wire)
|
|
240
|
+
* means the budget hasn't been counted yet, usually for a few seconds after
|
|
241
|
+
* it is created or its scope changes, so the cap holds calls until the
|
|
242
|
+
* first count lands. That case is `retryable`, and `retryAfterSeconds`
|
|
243
|
+
* comes from the Retry-After header or the body's `retry_after_seconds`.
|
|
244
|
+
* The SDK does not retry on its own.
|
|
245
|
+
*/
|
|
246
|
+
export class TensorCostBudgetHardCapError extends TensorCostPeriodBudgetExceededError {
|
|
247
|
+
constructor(message, fields = {}, opts = {}) {
|
|
248
|
+
super(message, fields.scope ?? null, fields.period ?? null, fields.capCents ?? null, fields.spentCents ?? null, {
|
|
249
|
+
...opts,
|
|
250
|
+
status: opts.status ?? 403,
|
|
251
|
+
code: fields.code ?? "BUDGET_HARD_CAP",
|
|
252
|
+
reason: fields.reason ?? null,
|
|
253
|
+
detail: fields.detail ?? null,
|
|
254
|
+
});
|
|
255
|
+
this.budgetCode = "BUDGET_HARD_CAP";
|
|
256
|
+
this.budgetId = fields.budgetId ?? null;
|
|
257
|
+
this.budgetName = fields.budgetName ?? null;
|
|
258
|
+
this.burnPct = fields.burnPct ?? null;
|
|
259
|
+
this.retryable = fields.retryable === true || this.reason === "spend_not_known_yet";
|
|
260
|
+
this.retryAfterSeconds = fields.retryAfterSeconds ?? null;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
120
263
|
/**
|
|
121
264
|
* Tenant model governance refused this model (HTTP 403,
|
|
122
265
|
* `code: "MODEL_GOVERNANCE_DENIED"`). Terminal — must not fall back to the
|
|
123
266
|
* provider, or Enforce would become a suggestion.
|
|
124
267
|
*/
|
|
125
|
-
export class TensorCostModelGovernanceDeniedError extends
|
|
268
|
+
export class TensorCostModelGovernanceDeniedError extends TensorCostRefusedError {
|
|
126
269
|
constructor(message, provider, model, governanceStatus, opts = {}) {
|
|
127
|
-
super(message, opts);
|
|
270
|
+
super(message, { code: "MODEL_GOVERNANCE_DENIED", detail: opts.detail ?? null }, opts);
|
|
128
271
|
this.provider = provider;
|
|
129
272
|
this.model = model;
|
|
130
273
|
this.governanceStatus = governanceStatus;
|
|
@@ -135,23 +278,22 @@ export class TensorCostModelGovernanceDeniedError extends TensorCostError {
|
|
|
135
278
|
* `code: "GUARDRAIL_HARD_STOP"`). Terminal — same fail-closed contract as
|
|
136
279
|
* run-budget and model governance denials.
|
|
137
280
|
*/
|
|
138
|
-
export class TensorCostGuardrailHardStopError extends
|
|
281
|
+
export class TensorCostGuardrailHardStopError extends TensorCostRefusedError {
|
|
139
282
|
constructor(message, policyId, opts = {}) {
|
|
140
|
-
super(message, opts);
|
|
283
|
+
super(message, { code: "GUARDRAIL_HARD_STOP", reason: opts.reason ?? null, detail: opts.detail ?? null }, opts);
|
|
141
284
|
this.policyId = policyId;
|
|
142
285
|
}
|
|
143
286
|
}
|
|
144
287
|
/** Compliance policy refused this call (metadata or in-process DLP). */
|
|
145
|
-
export class TensorCostComplianceDeniedError extends
|
|
288
|
+
export class TensorCostComplianceDeniedError extends TensorCostRefusedError {
|
|
146
289
|
constructor(message, reason, opts = {}) {
|
|
147
|
-
super(message, { ...opts, status: opts.status ?? 403 });
|
|
148
|
-
this.reason = reason;
|
|
290
|
+
super(message, { code: "COMPLIANCE_DENIED", reason, detail: opts.detail ?? null }, { ...opts, status: opts.status ?? 403 });
|
|
149
291
|
}
|
|
150
292
|
}
|
|
151
293
|
/** Client team_id does not match token-bound team scope. */
|
|
152
|
-
export class TensorCostComplianceTeamMismatchError extends
|
|
294
|
+
export class TensorCostComplianceTeamMismatchError extends TensorCostRefusedError {
|
|
153
295
|
constructor(message, opts = {}) {
|
|
154
|
-
super(message, { ...opts, status: opts.status ?? 403 });
|
|
296
|
+
super(message, { code: "COMPLIANCE_TEAM_MISMATCH", detail: opts.detail ?? null }, { ...opts, status: opts.status ?? 403 });
|
|
155
297
|
}
|
|
156
298
|
}
|
|
157
299
|
//# sourceMappingURL=errors.js.map
|
package/dist/errors.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ export { wrap } from "./wrap.js";
|
|
|
2
2
|
export { prewarm, flushObservations } from "./prewarm.js";
|
|
3
3
|
export { MissingConfigError, TensorCostConfigError } from "./config.js";
|
|
4
4
|
export { UnsupportedClientError } from "./providers/detect.js";
|
|
5
|
-
export { TensorCostError, TensorCostNetworkError, TensorCostTimeoutError, TensorCostProxyError, TensorCostQuotaError, TensorCostProviderError, TensorCostRunBudgetExceededError, TensorCostPeriodBudgetExceededError, TensorCostModelGovernanceDeniedError, TensorCostGuardrailHardStopError, TensorCostComplianceDeniedError, TensorCostComplianceTeamMismatchError, } from "./errors.js";
|
|
5
|
+
export { TensorCostError, TensorCostNetworkError, TensorCostTimeoutError, TensorCostProxyError, TensorCostQuotaError, TensorCostProviderError, TensorCostGatewayRejectedError, TensorCostKeyRejectedError, TensorCostRefusedError, TensorCostBudgetHardCapError, TensorCostRunBudgetExceededError, TensorCostRunStoppedError, TensorCostPeriodBudgetExceededError, TensorCostModelGovernanceDeniedError, TensorCostGuardrailHardStopError, TensorCostComplianceDeniedError, TensorCostComplianceTeamMismatchError, } from "./errors.js";
|
|
6
6
|
export type { LifecycleEvent, BeforeRequestEvent, AfterResponseEvent, OnRetryEvent, OnErrorEvent, OnFallbackEvent, LifecycleEventCallback, } from "./telemetry.js";
|
|
7
7
|
export type { RetryConfig } from "./retry.js";
|
|
8
8
|
export type { WrapOptions, Observation, Provider, ObservationModality, ControlLayer, DataGrant, } from "./types.js";
|
|
@@ -11,5 +11,5 @@ export { wrapLlamaIndex } from "./adapters/llamaindex.js";
|
|
|
11
11
|
export { wrapCrewAI } from "./adapters/crewai.js";
|
|
12
12
|
export { wrapVercelAi } from "./adapters/vercel-ai.js";
|
|
13
13
|
export { intersectGrants } from "./layer.js";
|
|
14
|
-
export declare const version = "1.
|
|
14
|
+
export declare const version = "1.5.0";
|
|
15
15
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAC1D,OAAO,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACxE,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EACL,eAAe,EACf,sBAAsB,EACtB,sBAAsB,EACtB,oBAAoB,EACpB,oBAAoB,EACpB,uBAAuB,EACvB,gCAAgC,EAChC,mCAAmC,EACnC,oCAAoC,EACpC,gCAAgC,EAChC,+BAA+B,EAC/B,qCAAqC,GACtC,MAAM,aAAa,CAAC;AACrB,YAAY,EACV,cAAc,EACd,kBAAkB,EAClB,kBAAkB,EAClB,YAAY,EACZ,YAAY,EACZ,eAAe,EACf,sBAAsB,GACvB,MAAM,gBAAgB,CAAC;AACxB,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC9C,YAAY,EACV,WAAW,EACX,WAAW,EACX,QAAQ,EACR,mBAAmB,EACnB,YAAY,EACZ,SAAS,GACV,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACxD,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAE7C,eAAO,MAAM,OAAO,UAAU,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAC1D,OAAO,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACxE,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EACL,eAAe,EACf,sBAAsB,EACtB,sBAAsB,EACtB,oBAAoB,EACpB,oBAAoB,EACpB,uBAAuB,EACvB,8BAA8B,EAC9B,0BAA0B,EAC1B,sBAAsB,EACtB,4BAA4B,EAC5B,gCAAgC,EAChC,yBAAyB,EACzB,mCAAmC,EACnC,oCAAoC,EACpC,gCAAgC,EAChC,+BAA+B,EAC/B,qCAAqC,GACtC,MAAM,aAAa,CAAC;AACrB,YAAY,EACV,cAAc,EACd,kBAAkB,EAClB,kBAAkB,EAClB,YAAY,EACZ,YAAY,EACZ,eAAe,EACf,sBAAsB,GACvB,MAAM,gBAAgB,CAAC;AACxB,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC9C,YAAY,EACV,WAAW,EACX,WAAW,EACX,QAAQ,EACR,mBAAmB,EACnB,YAAY,EACZ,SAAS,GACV,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACxD,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAE7C,eAAO,MAAM,OAAO,UAAU,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -2,11 +2,11 @@ export { wrap } from "./wrap.js";
|
|
|
2
2
|
export { prewarm, flushObservations } from "./prewarm.js";
|
|
3
3
|
export { MissingConfigError, TensorCostConfigError } from "./config.js";
|
|
4
4
|
export { UnsupportedClientError } from "./providers/detect.js";
|
|
5
|
-
export { TensorCostError, TensorCostNetworkError, TensorCostTimeoutError, TensorCostProxyError, TensorCostQuotaError, TensorCostProviderError, TensorCostRunBudgetExceededError, TensorCostPeriodBudgetExceededError, TensorCostModelGovernanceDeniedError, TensorCostGuardrailHardStopError, TensorCostComplianceDeniedError, TensorCostComplianceTeamMismatchError, } from "./errors.js";
|
|
5
|
+
export { TensorCostError, TensorCostNetworkError, TensorCostTimeoutError, TensorCostProxyError, TensorCostQuotaError, TensorCostProviderError, TensorCostGatewayRejectedError, TensorCostKeyRejectedError, TensorCostRefusedError, TensorCostBudgetHardCapError, TensorCostRunBudgetExceededError, TensorCostRunStoppedError, TensorCostPeriodBudgetExceededError, TensorCostModelGovernanceDeniedError, TensorCostGuardrailHardStopError, TensorCostComplianceDeniedError, TensorCostComplianceTeamMismatchError, } from "./errors.js";
|
|
6
6
|
export { wrapLangChain } from "./adapters/langchain.js";
|
|
7
7
|
export { wrapLlamaIndex } from "./adapters/llamaindex.js";
|
|
8
8
|
export { wrapCrewAI } from "./adapters/crewai.js";
|
|
9
9
|
export { wrapVercelAi } from "./adapters/vercel-ai.js";
|
|
10
10
|
export { intersectGrants } from "./layer.js";
|
|
11
|
-
export const version = "1.
|
|
11
|
+
export const version = "1.5.0";
|
|
12
12
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAC1D,OAAO,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACxE,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EACL,eAAe,EACf,sBAAsB,EACtB,sBAAsB,EACtB,oBAAoB,EACpB,oBAAoB,EACpB,uBAAuB,EACvB,gCAAgC,EAChC,mCAAmC,EACnC,oCAAoC,EACpC,gCAAgC,EAChC,+BAA+B,EAC/B,qCAAqC,GACtC,MAAM,aAAa,CAAC;AAmBrB,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACxD,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAE7C,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAC1D,OAAO,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACxE,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EACL,eAAe,EACf,sBAAsB,EACtB,sBAAsB,EACtB,oBAAoB,EACpB,oBAAoB,EACpB,uBAAuB,EACvB,8BAA8B,EAC9B,0BAA0B,EAC1B,sBAAsB,EACtB,4BAA4B,EAC5B,gCAAgC,EAChC,yBAAyB,EACzB,mCAAmC,EACnC,oCAAoC,EACpC,gCAAgC,EAChC,+BAA+B,EAC/B,qCAAqC,GACtC,MAAM,aAAa,CAAC;AAmBrB,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACxD,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAE7C,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rethrowing a relayed provider error as the provider SDK's own type.
|
|
3
|
+
*
|
|
4
|
+
* When the proxy relays an OpenAI 400, a caller written against the openai
|
|
5
|
+
* package expects `openai.BadRequestError`, not a TensorCost class. Both
|
|
6
|
+
* openai@4 and @anthropic-ai/sdk build their status errors through the
|
|
7
|
+
* client's `makeStatusError(status, body, message, headers)` (which calls
|
|
8
|
+
* `APIError.generate`), so the SDK asks the client to build it, exactly as
|
|
9
|
+
* the client would have for a direct call. Clients without that method, or
|
|
10
|
+
* whose factory rejects both header shapes below, get the
|
|
11
|
+
* TensorCostProviderError as is.
|
|
12
|
+
*/
|
|
13
|
+
/** The provider SDK's error for `err`, or `err` itself when one can't be built. */
|
|
14
|
+
export declare function providerNativeError(client: unknown, err: unknown): unknown;
|
|
15
|
+
//# sourceMappingURL=provider-errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider-errors.d.ts","sourceRoot":"","sources":["../src/provider-errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAuCH,mFAAmF;AACnF,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,GAAG,OAAO,CAsB1E"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rethrowing a relayed provider error as the provider SDK's own type.
|
|
3
|
+
*
|
|
4
|
+
* When the proxy relays an OpenAI 400, a caller written against the openai
|
|
5
|
+
* package expects `openai.BadRequestError`, not a TensorCost class. Both
|
|
6
|
+
* openai@4 and @anthropic-ai/sdk build their status errors through the
|
|
7
|
+
* client's `makeStatusError(status, body, message, headers)` (which calls
|
|
8
|
+
* `APIError.generate`), so the SDK asks the client to build it, exactly as
|
|
9
|
+
* the client would have for a direct call. Clients without that method, or
|
|
10
|
+
* whose factory rejects both header shapes below, get the
|
|
11
|
+
* TensorCostProviderError as is.
|
|
12
|
+
*/
|
|
13
|
+
import { TensorCostProviderError } from "./errors.js";
|
|
14
|
+
function statusErrorFactory(client) {
|
|
15
|
+
if (!client || typeof client !== "object")
|
|
16
|
+
return null;
|
|
17
|
+
const c = client;
|
|
18
|
+
if (typeof c["makeStatusError"] === "function") {
|
|
19
|
+
return c["makeStatusError"].bind(client);
|
|
20
|
+
}
|
|
21
|
+
// Older shapes expose the error class on the constructor instead.
|
|
22
|
+
const ctor = client.constructor;
|
|
23
|
+
const apiError = ctor?.["APIError"];
|
|
24
|
+
if (apiError && typeof apiError.generate === "function") {
|
|
25
|
+
return apiError.generate.bind(apiError);
|
|
26
|
+
}
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* The two header shapes the factories expect. openai@4 reads
|
|
31
|
+
* `headers["x-request-id"]` off a plain object; openai v5/v6 and current
|
|
32
|
+
* @anthropic-ai/sdk call `headers.get(...)` on a `Headers` instance and throw
|
|
33
|
+
* on a plain object. The plain object goes first (openai@4 would take a
|
|
34
|
+
* `Headers` too but lose the request id), then a `Headers` instance.
|
|
35
|
+
*/
|
|
36
|
+
function headerShapes(headers) {
|
|
37
|
+
const shapes = [headers];
|
|
38
|
+
if (typeof Headers === "function")
|
|
39
|
+
shapes.push(new Headers(headers));
|
|
40
|
+
return shapes;
|
|
41
|
+
}
|
|
42
|
+
/** The provider SDK's error for `err`, or `err` itself when one can't be built. */
|
|
43
|
+
export function providerNativeError(client, err) {
|
|
44
|
+
if (!(err instanceof TensorCostProviderError) || err.status === null)
|
|
45
|
+
return err;
|
|
46
|
+
const make = statusErrorFactory(client);
|
|
47
|
+
if (!make)
|
|
48
|
+
return err;
|
|
49
|
+
const body = err.body !== null && typeof err.body === "object" ? err.body : undefined;
|
|
50
|
+
for (const headers of headerShapes(err.headers)) {
|
|
51
|
+
let native;
|
|
52
|
+
try {
|
|
53
|
+
native = make(err.status, body, undefined, headers);
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
if (native instanceof Error) {
|
|
59
|
+
Object.defineProperty(native, "tensorcost", {
|
|
60
|
+
value: err,
|
|
61
|
+
enumerable: false,
|
|
62
|
+
configurable: true,
|
|
63
|
+
});
|
|
64
|
+
return native;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return err;
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=provider-errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider-errors.js","sourceRoot":"","sources":["../src/provider-errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAStD,SAAS,kBAAkB,CAAC,MAAe;IACzC,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IACvD,MAAM,CAAC,GAAG,MAAiC,CAAC;IAC5C,IAAI,OAAO,CAAC,CAAC,iBAAiB,CAAC,KAAK,UAAU,EAAE,CAAC;QAC/C,OAAQ,CAAC,CAAC,iBAAiB,CAAqB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAChE,CAAC;IACD,kEAAkE;IAClE,MAAM,IAAI,GAAI,MAAoD,CAAC,WAAW,CAAC;IAC/E,MAAM,QAAQ,GAAG,IAAI,EAAE,CAAC,UAAU,CAA+C,CAAC;IAClF,IAAI,QAAQ,IAAI,OAAO,QAAQ,CAAC,QAAQ,KAAK,UAAU,EAAE,CAAC;QACxD,OAAO,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC1C,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;GAMG;AACH,SAAS,YAAY,CAAC,OAA+B;IACnD,MAAM,MAAM,GAAc,CAAC,OAAO,CAAC,CAAC;IACpC,IAAI,OAAO,OAAO,KAAK,UAAU;QAAE,MAAM,CAAC,IAAI,CAAC,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;IACrE,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,mFAAmF;AACnF,MAAM,UAAU,mBAAmB,CAAC,MAAe,EAAE,GAAY;IAC/D,IAAI,CAAC,CAAC,GAAG,YAAY,uBAAuB,CAAC,IAAI,GAAG,CAAC,MAAM,KAAK,IAAI;QAAE,OAAO,GAAG,CAAC;IACjF,MAAM,IAAI,GAAG,kBAAkB,CAAC,MAAM,CAAC,CAAC;IACxC,IAAI,CAAC,IAAI;QAAE,OAAO,GAAG,CAAC;IACtB,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,KAAK,IAAI,IAAI,OAAO,GAAG,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;IACtF,KAAK,MAAM,OAAO,IAAI,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;QAChD,IAAI,MAAe,CAAC;QACpB,IAAI,CAAC;YACH,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;QACtD,CAAC;QAAC,MAAM,CAAC;YACP,SAAS;QACX,CAAC;QACD,IAAI,MAAM,YAAY,KAAK,EAAE,CAAC;YAC5B,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,YAAY,EAAE;gBAC1C,KAAK,EAAE,GAAG;gBACV,UAAU,EAAE,KAAK;gBACjB,YAAY,EAAE,IAAI;aACnB,CAAC,CAAC;YACH,OAAO,MAAM,CAAC;QAChB,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Anthropic client wrapping.
|
|
3
|
+
*
|
|
4
|
+
* Intercepts `client.messages.create`. Same observation contract as the
|
|
5
|
+
* OpenAI wrapper — only metadata is captured (model, input/output tokens),
|
|
6
|
+
* never the message content itself.
|
|
7
|
+
*
|
|
8
|
+
* Applied-mode hardening (v0.4.0): messages.create routes through the
|
|
9
|
+
* proxy-client module, which handles retries, timeouts, typed errors,
|
|
10
|
+
* telemetry hooks, and the fail-open circuit breaker.
|
|
11
|
+
*/
|
|
12
|
+
import type { ObservationTransport } from "../transport.js";
|
|
13
|
+
import type { CircuitBreaker } from "../circuit.js";
|
|
14
|
+
import type { LifecycleEventCallback } from "../telemetry.js";
|
|
15
|
+
import type { RetryConfig } from "../retry.js";
|
|
16
|
+
import type { ControlLayer } from "../layer.js";
|
|
17
|
+
import type { SdkLayerClient } from "../sdk-layer.js";
|
|
18
|
+
export interface AppliedModeHardeningOpts {
|
|
19
|
+
maxLayer: ControlLayer;
|
|
20
|
+
appliedMode: boolean;
|
|
21
|
+
proxyUrl: string | null;
|
|
22
|
+
baseUrl: string;
|
|
23
|
+
sdkLayer: SdkLayerClient;
|
|
24
|
+
retry: RetryConfig;
|
|
25
|
+
timeoutMs: number;
|
|
26
|
+
headersTimeoutMs: number;
|
|
27
|
+
idleTimeoutMs: number;
|
|
28
|
+
onLifecycleEvent: LifecycleEventCallback | undefined;
|
|
29
|
+
failOpenEnabled: boolean;
|
|
30
|
+
circuit: CircuitBreaker;
|
|
31
|
+
application?: string | null;
|
|
32
|
+
tags?: string[];
|
|
33
|
+
customer?: string | null;
|
|
34
|
+
feature?: string | null;
|
|
35
|
+
teamId?: string | null;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* The layer an Anthropic client actually runs at.
|
|
39
|
+
*
|
|
40
|
+
* The proxy has no Anthropic Messages route yet, so steer/route can't put
|
|
41
|
+
* the proxy in the request path for Claude. Before 1.5.0 that proxy call
|
|
42
|
+
* failed and fail-open sent the call straight to Anthropic, which meant
|
|
43
|
+
* nothing could stop a Claude run. Govern runs the pre-call /admit check
|
|
44
|
+
* instead, so stops, caps and budgets still apply. One warning per
|
|
45
|
+
* process says so.
|
|
46
|
+
*/
|
|
47
|
+
export declare function anthropicLayer(requested: ControlLayer): ControlLayer;
|
|
48
|
+
export declare function install(client: unknown, transport: ObservationTransport, tenantId: string | null, environment: string | null, connectionId: string | null, hardeningIn: AppliedModeHardeningOpts, deployment?: string | null, promptTemplateId?: string | null, agentId?: string | null, workflowId?: string | null): void;
|
|
49
|
+
export declare const __test__: {
|
|
50
|
+
MARKER: string;
|
|
51
|
+
WITH_META_MARKER: string;
|
|
52
|
+
resetPinWarning(): void;
|
|
53
|
+
};
|
|
54
|
+
//# sourceMappingURL=anthropic.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"anthropic.d.ts","sourceRoot":"","sources":["../../src/providers/anthropic.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"anthropic.d.ts","sourceRoot":"","sources":["../../src/providers/anthropic.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAuB5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEpD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AAC9D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAatD,MAAM,WAAW,wBAAwB;IACvC,QAAQ,EAAE,YAAY,CAAC;IACvB,WAAW,EAAE,OAAO,CAAC;IACrB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,cAAc,CAAC;IACzB,KAAK,EAAE,WAAW,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB,EAAE,MAAM,CAAC;IACzB,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,EAAE,sBAAsB,GAAG,SAAS,CAAC;IACrD,eAAe,EAAE,OAAO,CAAC;IACzB,OAAO,EAAE,cAAc,CAAC;IACxB,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;IACxB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB;AAyfD;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,YAAY,GAAG,YAAY,CAcpE;AAED,wBAAgB,OAAO,CACrB,MAAM,EAAE,OAAO,EACf,SAAS,EAAE,oBAAoB,EAC/B,QAAQ,EAAE,MAAM,GAAG,IAAI,EACvB,WAAW,EAAE,MAAM,GAAG,IAAI,EAC1B,YAAY,EAAE,MAAM,GAAG,IAAI,EAC3B,WAAW,EAAE,wBAAwB,EACrC,UAAU,GAAE,MAAM,GAAG,IAAW,EAChC,gBAAgB,GAAE,MAAM,GAAG,IAAW,EACtC,OAAO,GAAE,MAAM,GAAG,IAAW,EAC7B,UAAU,GAAE,MAAM,GAAG,IAAW,GAC/B,IAAI,CA8GN;AAED,eAAO,MAAM,QAAQ;;;uBAGA,IAAI;CAGxB,CAAC"}
|
|
@@ -13,13 +13,15 @@ import { proxyRequest, proxyRequestStream, sseChunksFromStream, shouldFallBackTo
|
|
|
13
13
|
import { admitRequest } from "../admit-client.js";
|
|
14
14
|
import { assertTeamScope, complianceStampFrom, enforceInProcessDlp, } from "../compliance-guard.js";
|
|
15
15
|
import { extractAnthropicMessagesText } from "../dlp.js";
|
|
16
|
-
import { TensorCostProxyError,
|
|
16
|
+
import { TensorCostProxyError, TensorCostComplianceDeniedError, TensorCostComplianceTeamMismatchError, TensorCostRefusedError, } from "../errors.js";
|
|
17
|
+
import { providerTarget } from "../applied.js";
|
|
18
|
+
import { providerNativeError } from "../provider-errors.js";
|
|
17
19
|
import { emitEvent } from "../telemetry.js";
|
|
18
20
|
import { needsProxyUrl } from "../layer.js";
|
|
19
21
|
import { decisionMetadata } from "../decision.js";
|
|
20
22
|
import { SDK_VERSION } from "../version.js";
|
|
21
23
|
import { resolveModelCallLink } from "../trace-link.js";
|
|
22
|
-
import { WrapOverhead, postObservation, withAwaitExcluded } from "../wrap-overhead.js";
|
|
24
|
+
import { WrapOverhead, observationScope, postObservation, withAwaitExcluded, } from "../wrap-overhead.js";
|
|
23
25
|
const MARKER = "__tensorcost_wrapped__";
|
|
24
26
|
const WITH_META_MARKER = "__tensorcost_with_meta__";
|
|
25
27
|
function nowIso() {
|
|
@@ -113,16 +115,26 @@ function wrapMethod(bound, opts) {
|
|
|
113
115
|
team_id: opts.hardening.teamId ?? null,
|
|
114
116
|
},
|
|
115
117
|
transport: opts.transport,
|
|
116
|
-
failOpen:
|
|
118
|
+
failOpen: opts.hardening.failOpenEnabled,
|
|
117
119
|
});
|
|
118
120
|
});
|
|
119
121
|
if (!admit.allowed) {
|
|
120
|
-
|
|
122
|
+
// The admit client types every refusal by its code. The generic
|
|
123
|
+
// error is only a guard; it used to say "model governance" for
|
|
124
|
+
// every refusal, budget caps included.
|
|
125
|
+
throw (admit.refusal ??
|
|
126
|
+
new TensorCostRefusedError("tensorcost: request refused at govern layer", {}, {
|
|
127
|
+
status: 403,
|
|
128
|
+
attempt: 1,
|
|
129
|
+
}));
|
|
121
130
|
}
|
|
122
131
|
decisionMeta = decisionMetadata(admit.decisionHeader);
|
|
123
132
|
}
|
|
124
133
|
catch (err) {
|
|
125
|
-
|
|
134
|
+
// Same rule as the proxy path: go around TensorCost only when it
|
|
135
|
+
// is unavailable (token exchange or admit unreachable), and only
|
|
136
|
+
// with failOpenEnabled. A refusal, known code or not, stops the call.
|
|
137
|
+
if (!shouldFallBackToProvider(err) || !opts.hardening.failOpenEnabled)
|
|
126
138
|
throw err;
|
|
127
139
|
}
|
|
128
140
|
}
|
|
@@ -140,15 +152,11 @@ function wrapMethod(bound, opts) {
|
|
|
140
152
|
? { compliance_frameworks: complianceStamp.compliance_frameworks }
|
|
141
153
|
: {}),
|
|
142
154
|
...(complianceStamp.dlp_action ? { dlp_action: complianceStamp.dlp_action } : {}),
|
|
155
|
+
...observationScope(opts.hardening.application, opts.hardening.tags),
|
|
143
156
|
});
|
|
144
157
|
const proxyUrl = opts.hardening.proxyUrl;
|
|
145
158
|
if (needsProxyUrl(effectiveLayer) && proxyUrl) {
|
|
146
|
-
|
|
147
|
-
const dh = opts.clientRef && typeof opts.clientRef === "object"
|
|
148
|
-
? opts.clientRef["defaultHeaders"]
|
|
149
|
-
: undefined;
|
|
150
|
-
const providerUrl = dh?.["x-tc-provider-url"] ?? "https://api.anthropic.com";
|
|
151
|
-
const providerAuth = dh?.["x-tc-provider-auth"] ?? "";
|
|
159
|
+
const { providerUrl, providerAuth } = providerTarget(opts.clientRef, "anthropic", "https://api.anthropic.com");
|
|
152
160
|
const body = {
|
|
153
161
|
...(firstArg && typeof firstArg === "object" ? firstArg : {}),
|
|
154
162
|
model: String(model),
|
|
@@ -234,7 +242,7 @@ function wrapMethod(bound, opts) {
|
|
|
234
242
|
}
|
|
235
243
|
catch (proxyErr) {
|
|
236
244
|
if (!shouldFallBackToProvider(proxyErr))
|
|
237
|
-
throw proxyErr;
|
|
245
|
+
throw providerNativeError(opts.clientRef, proxyErr);
|
|
238
246
|
proxyFailed = true;
|
|
239
247
|
proxyFailureError = proxyErr;
|
|
240
248
|
}
|
|
@@ -436,9 +444,38 @@ function wrapMethod(bound, opts) {
|
|
|
436
444
|
Object.defineProperty(wrapped, MARKER, { value: true, enumerable: false });
|
|
437
445
|
return wrapped;
|
|
438
446
|
}
|
|
439
|
-
|
|
447
|
+
let pinWarned = false;
|
|
448
|
+
/**
|
|
449
|
+
* The layer an Anthropic client actually runs at.
|
|
450
|
+
*
|
|
451
|
+
* The proxy has no Anthropic Messages route yet, so steer/route can't put
|
|
452
|
+
* the proxy in the request path for Claude. Before 1.5.0 that proxy call
|
|
453
|
+
* failed and fail-open sent the call straight to Anthropic, which meant
|
|
454
|
+
* nothing could stop a Claude run. Govern runs the pre-call /admit check
|
|
455
|
+
* instead, so stops, caps and budgets still apply. One warning per
|
|
456
|
+
* process says so.
|
|
457
|
+
*/
|
|
458
|
+
export function anthropicLayer(requested) {
|
|
459
|
+
if (!needsProxyUrl(requested))
|
|
460
|
+
return requested;
|
|
461
|
+
if (!pinWarned) {
|
|
462
|
+
pinWarned = true;
|
|
463
|
+
// eslint-disable-next-line no-console
|
|
464
|
+
console.warn(`tensorcost: maxLayer '${requested}' isn't available for Anthropic clients yet ` +
|
|
465
|
+
"(the TensorCost proxy has no Anthropic Messages route), so this client runs " +
|
|
466
|
+
"in 'govern': every call is checked with /admit before it goes to Anthropic, " +
|
|
467
|
+
"which is what lets a run be stopped or capped. Set maxLayer: 'govern' to " +
|
|
468
|
+
"silence this warning.");
|
|
469
|
+
}
|
|
470
|
+
return "govern";
|
|
471
|
+
}
|
|
472
|
+
export function install(client, transport, tenantId, environment, connectionId, hardeningIn, deployment = null, promptTemplateId = null, agentId = null, workflowId = null) {
|
|
440
473
|
if (!client || typeof client !== "object")
|
|
441
474
|
return;
|
|
475
|
+
const pinned = anthropicLayer(hardeningIn.maxLayer);
|
|
476
|
+
const hardening = pinned === hardeningIn.maxLayer
|
|
477
|
+
? hardeningIn
|
|
478
|
+
: { ...hardeningIn, maxLayer: pinned, appliedMode: false };
|
|
442
479
|
const c = client;
|
|
443
480
|
const messages = c.messages;
|
|
444
481
|
let originalMessagesBound;
|
|
@@ -521,5 +558,11 @@ export function install(client, transport, tenantId, environment, connectionId,
|
|
|
521
558
|
};
|
|
522
559
|
}
|
|
523
560
|
}
|
|
524
|
-
export const __test__ = {
|
|
561
|
+
export const __test__ = {
|
|
562
|
+
MARKER,
|
|
563
|
+
WITH_META_MARKER,
|
|
564
|
+
resetPinWarning() {
|
|
565
|
+
pinWarned = false;
|
|
566
|
+
},
|
|
567
|
+
};
|
|
525
568
|
//# sourceMappingURL=anthropic.js.map
|