@stigg/agent-sdk-js 0.0.0-stage → 0.2.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/README.md +1411 -2
- package/dist/bindings/client/core/registry.d.ts +12 -0
- package/dist/bindings/client/core/registry.js +22 -0
- package/dist/bindings/client/core/types.d.ts +126 -0
- package/dist/bindings/client/core/types.js +13 -0
- package/dist/bindings/client/core/wrap-client.d.ts +6 -0
- package/dist/bindings/client/core/wrap-client.js +261 -0
- package/dist/bindings/client/gateways/bedrock/bedrock-recipe.d.ts +17 -0
- package/dist/bindings/client/gateways/bedrock/bedrock-recipe.js +134 -0
- package/dist/bindings/client/gateways/bedrock/types.d.ts +13 -0
- package/dist/bindings/client/gateways/bedrock/types.js +2 -0
- package/dist/bindings/client/gateways/cloudflare/cloudflare-recipe.d.ts +10 -0
- package/dist/bindings/client/gateways/cloudflare/cloudflare-recipe.js +254 -0
- package/dist/bindings/client/gateways/cloudflare/types.d.ts +35 -0
- package/dist/bindings/client/gateways/cloudflare/types.js +2 -0
- package/dist/bindings/client/gateways/databricks/databricks-recipe.d.ts +32 -0
- package/dist/bindings/client/gateways/databricks/databricks-recipe.js +324 -0
- package/dist/bindings/client/gateways/databricks/types.d.ts +30 -0
- package/dist/bindings/client/gateways/databricks/types.js +2 -0
- package/dist/bindings/client/gateways/litellm/litellm-recipe.d.ts +17 -0
- package/dist/bindings/client/gateways/litellm/litellm-recipe.js +158 -0
- package/dist/bindings/client/gateways/litellm/types.d.ts +30 -0
- package/dist/bindings/client/gateways/litellm/types.js +2 -0
- package/dist/bindings/client/gateways/openrouter/openrouter-recipe.d.ts +20 -0
- package/dist/bindings/client/gateways/openrouter/openrouter-recipe.js +233 -0
- package/dist/bindings/client/gateways/openrouter/sdk-usage.d.ts +37 -0
- package/dist/bindings/client/gateways/openrouter/sdk-usage.js +63 -0
- package/dist/bindings/client/gateways/openrouter/types.d.ts +78 -0
- package/dist/bindings/client/gateways/openrouter/types.js +2 -0
- package/dist/bindings/client/providers/anthropic/anthropic-recipe.d.ts +34 -0
- package/dist/bindings/client/providers/anthropic/anthropic-recipe.js +169 -0
- package/dist/bindings/client/providers/gemini/gemini-recipe.d.ts +54 -0
- package/dist/bindings/client/providers/gemini/gemini-recipe.js +243 -0
- package/dist/bindings/client/providers/groq/groq-recipe.d.ts +20 -0
- package/dist/bindings/client/providers/groq/groq-recipe.js +84 -0
- package/dist/bindings/client/providers/mistral/mistral-recipe.d.ts +22 -0
- package/dist/bindings/client/providers/mistral/mistral-recipe.js +114 -0
- package/dist/bindings/client/providers/mistral/types.d.ts +38 -0
- package/dist/bindings/client/providers/mistral/types.js +2 -0
- package/dist/bindings/client/providers/ollama/ollama-recipe.d.ts +31 -0
- package/dist/bindings/client/providers/ollama/ollama-recipe.js +107 -0
- package/dist/bindings/client/providers/ollama/types.d.ts +24 -0
- package/dist/bindings/client/providers/ollama/types.js +2 -0
- package/dist/bindings/client/providers/openai/openai-recipe.d.ts +71 -0
- package/dist/bindings/client/providers/openai/openai-recipe.js +122 -0
- package/dist/bindings/client/providers/typesafe/typesafe-recipe.d.ts +44 -0
- package/dist/bindings/client/providers/typesafe/typesafe-recipe.js +83 -0
- package/dist/bindings/proxy/headers.d.ts +6 -0
- package/dist/bindings/proxy/headers.js +12 -0
- package/dist/bindings/proxy/index.d.ts +21 -0
- package/dist/bindings/proxy/index.js +18 -0
- package/dist/bindings/proxy/types.d.ts +8 -0
- package/dist/bindings/proxy/types.js +2 -0
- package/dist/bindings/shared/base-url.d.ts +44 -0
- package/dist/bindings/shared/base-url.js +90 -0
- package/dist/bindings/shared/estimate.d.ts +27 -0
- package/dist/bindings/shared/estimate.js +38 -0
- package/dist/bindings/shared/meter-stream.d.ts +18 -0
- package/dist/bindings/shared/meter-stream.js +151 -0
- package/dist/bindings/shared/token-usage.d.ts +345 -0
- package/dist/bindings/shared/token-usage.js +735 -0
- package/dist/bindings/shared/types.d.ts +170 -0
- package/dist/bindings/shared/types.js +2 -0
- package/dist/bindings/shared/weighted-metrics.d.ts +37 -0
- package/dist/bindings/shared/weighted-metrics.js +47 -0
- package/dist/config.d.ts +145 -0
- package/dist/config.js +99 -0
- package/dist/core/context.d.ts +160 -0
- package/dist/core/context.js +221 -0
- package/dist/core/dimensions.d.ts +22 -0
- package/dist/core/dimensions.js +47 -0
- package/dist/core/hooks.d.ts +21 -0
- package/dist/core/hooks.js +47 -0
- package/dist/core/session.d.ts +190 -0
- package/dist/core/session.js +448 -0
- package/dist/decision-text.d.ts +15 -0
- package/dist/decision-text.js +54 -0
- package/dist/engine/composite-engine.d.ts +72 -0
- package/dist/engine/composite-engine.js +135 -0
- package/dist/engine/create-engine.d.ts +16 -0
- package/dist/engine/create-engine.js +93 -0
- package/dist/engine/decision.d.ts +42 -0
- package/dist/engine/decision.js +135 -0
- package/dist/engine/engine.d.ts +166 -0
- package/dist/engine/engine.js +11 -0
- package/dist/engine/node-sdk-engine.d.ts +125 -0
- package/dist/engine/node-sdk-engine.js +262 -0
- package/dist/engine/report.d.ts +106 -0
- package/dist/engine/report.js +188 -0
- package/dist/engine/rest-governance-engine.d.ts +47 -0
- package/dist/engine/rest-governance-engine.js +220 -0
- package/dist/errors.d.ts +86 -0
- package/dist/errors.js +161 -0
- package/dist/headers.d.ts +40 -0
- package/dist/headers.js +82 -0
- package/dist/index.d.ts +63 -0
- package/dist/index.js +124 -0
- package/dist/internal.d.ts +33 -0
- package/dist/internal.js +91 -0
- package/dist/logger.d.ts +15 -0
- package/dist/logger.js +20 -0
- package/dist/sdk-identity.d.ts +36 -0
- package/dist/sdk-identity.js +43 -0
- package/dist/stigg-agent-sdk.d.ts +300 -0
- package/dist/stigg-agent-sdk.js +669 -0
- package/dist/types.d.ts +676 -0
- package/dist/types.js +147 -0
- package/package.json +94 -3
package/dist/errors.js
ADDED
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isGovernanceNotEnabled = exports.isEngineError = exports.GovernanceNotEnabledError = exports.EngineError = exports.AccessDeniedError = void 0;
|
|
4
|
+
exports.isAccessDenied = isAccessDenied;
|
|
5
|
+
exports.isMeterMismatchError = isMeterMismatchError;
|
|
6
|
+
exports.asEngineError = asEngineError;
|
|
7
|
+
exports.isTransportFailure = isTransportFailure;
|
|
8
|
+
exports.asGovernanceError = asGovernanceError;
|
|
9
|
+
exports.looksLikeGovernanceNotEnabled = looksLikeGovernanceNotEnabled;
|
|
10
|
+
const MARKER = Symbol.for('stigg.agent-sdk.error');
|
|
11
|
+
const mark = (err, kind) => {
|
|
12
|
+
Object.defineProperty(err, MARKER, { value: kind, enumerable: false });
|
|
13
|
+
return err;
|
|
14
|
+
};
|
|
15
|
+
const isKind = (err, kind) => typeof err === 'object' && err !== null && err[MARKER] === kind;
|
|
16
|
+
/**
|
|
17
|
+
* Thrown only where there is no return path for a decision - inside a wrapped client method,
|
|
18
|
+
* which must hand back the vendor's own response type or nothing at all. Everywhere else a
|
|
19
|
+
* denial is a returned `AccessDecision`.
|
|
20
|
+
*/
|
|
21
|
+
class AccessDeniedError extends Error {
|
|
22
|
+
decision;
|
|
23
|
+
constructor(decision) {
|
|
24
|
+
const by = decision.deniedBy ? ` by ${decision.deniedBy}` : '';
|
|
25
|
+
super(`Denied${by}: ${decision.reason ?? 'no budget remaining'}`);
|
|
26
|
+
this.name = 'AccessDeniedError';
|
|
27
|
+
this.decision = decision;
|
|
28
|
+
mark(this, 'denied');
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
exports.AccessDeniedError = AccessDeniedError;
|
|
32
|
+
/** Anything the engine could not complete: transport, timeout, 4xx/5xx, bad input. */
|
|
33
|
+
class EngineError extends Error {
|
|
34
|
+
status;
|
|
35
|
+
operation;
|
|
36
|
+
/**
|
|
37
|
+
* What the server had already accepted when this failed.
|
|
38
|
+
*
|
|
39
|
+
* An ingest is up to two calls - the features, then the wallet - so a rejection on the second
|
|
40
|
+
* leaves the first one's spend sitting at Stigg. Reporting that turn as nothing landed would
|
|
41
|
+
* understate a bill the customer is going to see, which is the one direction a meter must not
|
|
42
|
+
* be wrong in.
|
|
43
|
+
*/
|
|
44
|
+
reported;
|
|
45
|
+
/**
|
|
46
|
+
* Whether what landed was a replay. Carried with `reported`, because counting those metrics
|
|
47
|
+
* again is the one thing a caller must not do with keys Stigg had already seen - and
|
|
48
|
+
* `undefined` means here what it means everywhere: the event API could not say.
|
|
49
|
+
*/
|
|
50
|
+
replayed;
|
|
51
|
+
constructor(operation, message, options) {
|
|
52
|
+
super(`${operation}: ${message}`, options?.cause === undefined ? undefined : { cause: options.cause });
|
|
53
|
+
this.name = 'EngineError';
|
|
54
|
+
this.operation = operation;
|
|
55
|
+
this.status = options?.status;
|
|
56
|
+
this.reported = options?.reported;
|
|
57
|
+
this.replayed = options?.replayed;
|
|
58
|
+
mark(this, 'engine');
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
exports.EngineError = EngineError;
|
|
62
|
+
/**
|
|
63
|
+
* Per-agent budgets are not enabled for this Stigg environment. An account state, not a transient
|
|
64
|
+
* failure, and the class keeps the platform's own name because that is what has to be turned on.
|
|
65
|
+
*
|
|
66
|
+
* The message says what to do rather than what is missing. "Governance is not enabled" names an
|
|
67
|
+
* internal capability to someone who was trying to charge for agent usage and has no reason to
|
|
68
|
+
* know the two are the same thing - so the first line is the fix, and the feature name follows it
|
|
69
|
+
* for whoever has to go and find the setting.
|
|
70
|
+
*/
|
|
71
|
+
class GovernanceNotEnabledError extends Error {
|
|
72
|
+
constructor(detail = 'Per-agent budgets are not enabled for this Stigg environment, so an agent cannot be ' +
|
|
73
|
+
'given an identity or a budget. Enable Governance for the account to use them - or drop ' +
|
|
74
|
+
'`agentId` and the budget fields, and checks and usage apply to the customer instead.') {
|
|
75
|
+
super(detail);
|
|
76
|
+
this.name = 'GovernanceNotEnabledError';
|
|
77
|
+
mark(this, 'not-enabled');
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
exports.GovernanceNotEnabledError = GovernanceNotEnabledError;
|
|
81
|
+
/** Returns the decision when `err` is a governance denial - the one-liner for a binding catch. */
|
|
82
|
+
function isAccessDenied(err) {
|
|
83
|
+
if (isKind(err, 'denied'))
|
|
84
|
+
return err.decision;
|
|
85
|
+
// Vendor SDKs wrap callback errors, so the denial can arrive one level down.
|
|
86
|
+
const cause = err?.cause;
|
|
87
|
+
if (cause && isKind(cause, 'denied'))
|
|
88
|
+
return cause.decision;
|
|
89
|
+
return undefined;
|
|
90
|
+
}
|
|
91
|
+
const isEngineError = (err) => isKind(err, 'engine');
|
|
92
|
+
exports.isEngineError = isEngineError;
|
|
93
|
+
const isGovernanceNotEnabled = (err) => isKind(err, 'not-enabled');
|
|
94
|
+
exports.isGovernanceNotEnabled = isGovernanceNotEnabled;
|
|
95
|
+
/**
|
|
96
|
+
* True when Stigg refused a usage report because the feature is backed by a raw-events meter.
|
|
97
|
+
* Ingest forks by meter type, and this error is the definitive signal for which fork to take -
|
|
98
|
+
* `meterType` alone does not say (a raw-events feature can report `INCREMENTAL`).
|
|
99
|
+
*/
|
|
100
|
+
function isMeterMismatchError(err) {
|
|
101
|
+
const any = err;
|
|
102
|
+
const code = any?.code ?? any?.error?.code ?? '';
|
|
103
|
+
if (code.startsWith('CannotReportUsageForEntitlementWithMeter'))
|
|
104
|
+
return true;
|
|
105
|
+
const message = any?.message ?? '';
|
|
106
|
+
return message.includes('report usage for entitlement with meter') || message.includes('use reportEvent');
|
|
107
|
+
}
|
|
108
|
+
/** Whatever a client threw, as the seam's own error - keeping the status where there was one. */
|
|
109
|
+
function asEngineError(operation, err, partial) {
|
|
110
|
+
const status = err?.status;
|
|
111
|
+
// Re-wrapping must not drop a partial acknowledgement: the run handle wraps again on its way
|
|
112
|
+
// out, and whatever landed is just as true one frame up.
|
|
113
|
+
const landed = partial ?? (err instanceof EngineError ? { reported: err.reported, replayed: err.replayed } : {});
|
|
114
|
+
return new EngineError(operation, err instanceof Error ? err.message : String(err), {
|
|
115
|
+
status,
|
|
116
|
+
cause: err,
|
|
117
|
+
reported: landed.reported,
|
|
118
|
+
replayed: landed.replayed,
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* True when a failure looks like "this transport is not answering" rather than "Stigg refused".
|
|
123
|
+
*
|
|
124
|
+
* The distinction decides whether another transport is worth trying: a 404 on the GraphQL
|
|
125
|
+
* endpoint or a refused connection says nothing about the request, while a 400 or a 403 says the
|
|
126
|
+
* request itself is wrong and would be wrong on any transport. Deliberately narrow - demoting on
|
|
127
|
+
* a business error would hide a real problem behind a silent re-route.
|
|
128
|
+
*/
|
|
129
|
+
function isTransportFailure(err) {
|
|
130
|
+
const any = err;
|
|
131
|
+
if (any?.status && [404, 500, 502, 503, 504].includes(any.status))
|
|
132
|
+
return true;
|
|
133
|
+
const code = any?.cause?.code ?? '';
|
|
134
|
+
if (['ECONNREFUSED', 'ENOTFOUND', 'ETIMEDOUT', 'ECONNRESET', 'EAI_AGAIN'].includes(code))
|
|
135
|
+
return true;
|
|
136
|
+
const message = `${any?.message ?? ''} ${any?.cause?.message ?? ''}`;
|
|
137
|
+
if (/status code (404|5\d\d)/i.test(message))
|
|
138
|
+
return true;
|
|
139
|
+
return /ECONNREFUSED|ENOTFOUND|ETIMEDOUT|ECONNRESET|socket hang up|fetch failed|network error/i.test(message);
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* The seam's error for an operation that only governance can serve.
|
|
143
|
+
*
|
|
144
|
+
* Entities and assignments exist nowhere else, so a 403 on one of them is the account saying the
|
|
145
|
+
* feature is off - a state the caller can act on - rather than a call that failed. Every other
|
|
146
|
+
* failure is an ordinary engine error.
|
|
147
|
+
*/
|
|
148
|
+
function asGovernanceError(operation, err) {
|
|
149
|
+
if (looksLikeGovernanceNotEnabled(err))
|
|
150
|
+
return new GovernanceNotEnabledError();
|
|
151
|
+
return asEngineError(operation, err);
|
|
152
|
+
}
|
|
153
|
+
/** Recognizes the account-state 403 in whatever shape the transport surfaced it. */
|
|
154
|
+
function looksLikeGovernanceNotEnabled(err) {
|
|
155
|
+
if ((0, exports.isGovernanceNotEnabled)(err))
|
|
156
|
+
return true;
|
|
157
|
+
const any = err;
|
|
158
|
+
if (any?.code === 'GovernanceNotEnabled' || any?.error?.code === 'GovernanceNotEnabled')
|
|
159
|
+
return true;
|
|
160
|
+
return any?.status === 403 && (any.message ?? '').includes('Governance is not enabled');
|
|
161
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The wire convention for splitting the run lifecycle across a process boundary.
|
|
3
|
+
*
|
|
4
|
+
* A gateway is out-of-process and sees requests, not runs. These headers are what lets the
|
|
5
|
+
* application keep governance in-process while something downstream still ingests against the
|
|
6
|
+
* right entity - so the convention belongs to the core, not to any one binding.
|
|
7
|
+
*/
|
|
8
|
+
export declare const GOVERNANCE_HEADERS: {
|
|
9
|
+
readonly customer: "x-stigg-customer-id";
|
|
10
|
+
readonly dimensions: "x-stigg-dimensions";
|
|
11
|
+
readonly run: "x-stigg-run-id";
|
|
12
|
+
/**
|
|
13
|
+
* Which key in `dimensions` names the agent, when one does.
|
|
14
|
+
*
|
|
15
|
+
* Sent because the far end cannot work it out. Governance resolves an entity per attribution
|
|
16
|
+
* key, and which keys those are is declared on the entity types in the account - so a receiver
|
|
17
|
+
* holding only `{ agentId: 'a-1', region: 'eu' }` cannot tell the attribution from the
|
|
18
|
+
* metadata. Guessing either way is wrong in a direction that costs money: treat every
|
|
19
|
+
* dimension as attribution and an ordinary `region` rounds the draw up; treat none as
|
|
20
|
+
* attribution and a real agent's budget stops counting.
|
|
21
|
+
*/
|
|
22
|
+
readonly attributionKey: "x-stigg-attribution-key";
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* What `run.headers()` produces - all three, always.
|
|
26
|
+
*
|
|
27
|
+
* Built rather than parsed, so the type says so: an empty map or an unrelated one is not a set of
|
|
28
|
+
* governance headers, and there is no point discovering that at the far end of a request. The
|
|
29
|
+
* receiving side is deliberately looser, because what arrives there is whatever was sent.
|
|
30
|
+
*/
|
|
31
|
+
export type GovernanceHeaders = Record<(typeof GOVERNANCE_HEADERS)[keyof typeof GOVERNANCE_HEADERS], string>;
|
|
32
|
+
export type ParsedGovernanceHeaders = {
|
|
33
|
+
customerId: string;
|
|
34
|
+
dimensions: Record<string, string>;
|
|
35
|
+
runId?: string;
|
|
36
|
+
/** The key under which `dimensions` names the agent, when the sender named one. */
|
|
37
|
+
attributionKey?: string;
|
|
38
|
+
};
|
|
39
|
+
/** The receiving side. Returns undefined when the request carries no attribution to act on. */
|
|
40
|
+
export declare function parseGovernanceHeaders(headers: Record<string, string | string[] | undefined>): ParsedGovernanceHeaders | undefined;
|
package/dist/headers.js
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.GOVERNANCE_HEADERS = void 0;
|
|
4
|
+
exports.parseGovernanceHeaders = parseGovernanceHeaders;
|
|
5
|
+
/**
|
|
6
|
+
* The wire convention for splitting the run lifecycle across a process boundary.
|
|
7
|
+
*
|
|
8
|
+
* A gateway is out-of-process and sees requests, not runs. These headers are what lets the
|
|
9
|
+
* application keep governance in-process while something downstream still ingests against the
|
|
10
|
+
* right entity - so the convention belongs to the core, not to any one binding.
|
|
11
|
+
*/
|
|
12
|
+
exports.GOVERNANCE_HEADERS = {
|
|
13
|
+
customer: 'x-stigg-customer-id',
|
|
14
|
+
dimensions: 'x-stigg-dimensions',
|
|
15
|
+
run: 'x-stigg-run-id',
|
|
16
|
+
/**
|
|
17
|
+
* Which key in `dimensions` names the agent, when one does.
|
|
18
|
+
*
|
|
19
|
+
* Sent because the far end cannot work it out. Governance resolves an entity per attribution
|
|
20
|
+
* key, and which keys those are is declared on the entity types in the account - so a receiver
|
|
21
|
+
* holding only `{ agentId: 'a-1', region: 'eu' }` cannot tell the attribution from the
|
|
22
|
+
* metadata. Guessing either way is wrong in a direction that costs money: treat every
|
|
23
|
+
* dimension as attribution and an ordinary `region` rounds the draw up; treat none as
|
|
24
|
+
* attribution and a real agent's budget stops counting.
|
|
25
|
+
*/
|
|
26
|
+
attributionKey: 'x-stigg-attribution-key',
|
|
27
|
+
};
|
|
28
|
+
/** The receiving side. Returns undefined when the request carries no attribution to act on. */
|
|
29
|
+
function parseGovernanceHeaders(headers) {
|
|
30
|
+
// Node lowercases what it receives, but a map built by hand or converted from `Headers` keeps
|
|
31
|
+
// whatever case the sender used, and losing attribution over it would be silent.
|
|
32
|
+
// What a header is worth, whichever container it arrived in: `'c'` and `['c']` are the same
|
|
33
|
+
// value under this function's own argument type, so comparing the containers would call them a
|
|
34
|
+
// disagreement. A header present but blank is a header that is not set.
|
|
35
|
+
const valueOf = (raw) => {
|
|
36
|
+
const first = Array.isArray(raw) ? raw[0] : raw;
|
|
37
|
+
return first?.trim() ? first.trim() : undefined;
|
|
38
|
+
};
|
|
39
|
+
const lookup = new Map();
|
|
40
|
+
const ambiguous = new Set();
|
|
41
|
+
for (const [key, raw] of Object.entries(headers)) {
|
|
42
|
+
const name = key.toLowerCase();
|
|
43
|
+
const value = valueOf(raw);
|
|
44
|
+
// Two spellings of one header, disagreeing. Folding case makes them the same name, and
|
|
45
|
+
// letting the last one win would attribute the request to whichever the map happened to
|
|
46
|
+
// iterate second - a silently wrong customer reads exactly like a right one.
|
|
47
|
+
if (lookup.has(name) && lookup.get(name) !== value)
|
|
48
|
+
ambiguous.add(name);
|
|
49
|
+
lookup.set(name, value);
|
|
50
|
+
}
|
|
51
|
+
const read = (name) => (ambiguous.has(name) ? undefined : lookup.get(name));
|
|
52
|
+
const customerId = read(exports.GOVERNANCE_HEADERS.customer);
|
|
53
|
+
if (!customerId)
|
|
54
|
+
return undefined;
|
|
55
|
+
let dimensions = {};
|
|
56
|
+
const raw = read(exports.GOVERNANCE_HEADERS.dimensions);
|
|
57
|
+
if (raw) {
|
|
58
|
+
try {
|
|
59
|
+
const parsed = JSON.parse(raw);
|
|
60
|
+
// `JSON.parse` succeeds on `null`, arrays and scalars, none of which are a dimensions map.
|
|
61
|
+
if (isDimensions(parsed))
|
|
62
|
+
dimensions = parsed;
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
// A malformed header must not cost the request; usage just loses its entity attribution.
|
|
66
|
+
dimensions = {};
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
// Only honoured when it names a dimension that is actually there: a key with nothing under it
|
|
70
|
+
// attributes to no entity, and treating it as though it did would round a draw up for nothing.
|
|
71
|
+
const attributionKey = read(exports.GOVERNANCE_HEADERS.attributionKey);
|
|
72
|
+
return {
|
|
73
|
+
customerId,
|
|
74
|
+
dimensions,
|
|
75
|
+
runId: read(exports.GOVERNANCE_HEADERS.run),
|
|
76
|
+
...(attributionKey && dimensions[attributionKey] ? { attributionKey } : {}),
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
const isDimensions = (value) => typeof value === 'object' &&
|
|
80
|
+
value !== null &&
|
|
81
|
+
!Array.isArray(value) &&
|
|
82
|
+
Object.values(value).every((entry) => typeof entry === 'string');
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public surface.
|
|
3
|
+
*
|
|
4
|
+
* Importing this file pulls in no vendor package. The recipes below are exported from here, but
|
|
5
|
+
* each one is duck-typed against the shape a vendor returns rather than written against its SDK,
|
|
6
|
+
* so `@anthropic-ai/sdk`, `openai` and the rest stay out of the dependency tree entirely.
|
|
7
|
+
*
|
|
8
|
+
* What is exported here is the vocabulary, the client, and the seams worth extending: a recipe,
|
|
9
|
+
* a metrics mapper, a `GovernanceEngine`. The implementations behind those seams - the concrete
|
|
10
|
+
* engines, decision construction, config resolution, the metric tables - live in
|
|
11
|
+
* `@stigg/agent-sdk-js/internal`, under a weaker compatibility promise.
|
|
12
|
+
*/
|
|
13
|
+
export { StiggAgentSDK } from './stigg-agent-sdk';
|
|
14
|
+
export type { StiggContext } from './core/context';
|
|
15
|
+
export type { SessionSummary, HookContext, IngestOptions, SessionHooks } from './core/session';
|
|
16
|
+
export { RAW_PREFIX, flattenRaw } from './core/dimensions';
|
|
17
|
+
export type { CacheOptions, ErrorContext, NodeSdkClient, StiggAgentSDKOptions } from './config';
|
|
18
|
+
export { describeDecision, remedyMessage } from './decision-text';
|
|
19
|
+
export { GOVERNANCE_HEADERS, parseGovernanceHeaders } from './headers';
|
|
20
|
+
export type { GovernanceHeaders, ParsedGovernanceHeaders } from './headers';
|
|
21
|
+
export { consoleLogger, noopLogger } from './logger';
|
|
22
|
+
export type { Logger } from './logger';
|
|
23
|
+
export { EngineError, AccessDeniedError, GovernanceNotEnabledError, isEngineError, isAccessDenied, isGovernanceNotEnabled, looksLikeGovernanceNotEnabled, } from './errors';
|
|
24
|
+
export type { EngineCapabilities, EngineChainNode, EngineCheckParams, EngineCheckResult, EngineReportParams, EngineReportResult, EngineResolution, EntityInput, EventIngest, EntityPlacement, GovernanceEngine, } from './engine/engine';
|
|
25
|
+
export { unitsPerTokens, vendorMetrics, emptyTokenUsage, entitlementId, entitlementKind, entitlementRef, toMeasurement, } from './types';
|
|
26
|
+
export type { AgentBudget, AgentOptions, AgentScope, ClientGovernance, CheckErrorAction, ClientOptions, DecisionSource, DeregisterInput, Entitlement, AccessDecision, Remedy, WrappedClient, IngestContext, IngestMode, IngestResult, Measurement, RegisterInput, GatedSurface, ChatOf, CallContext, TokenUsage, Metrics, MetricsMapper, } from './types';
|
|
27
|
+
export { wrapClient } from './bindings/client/core/wrap-client';
|
|
28
|
+
export { createClientRegistry, hasMethod } from './bindings/client/core/registry';
|
|
29
|
+
export type { ClientRecipe, ClientRegistry, MethodRecipe, MetricsFor, MetricsOf, MeteredResponse, } from './bindings/client/core/types';
|
|
30
|
+
export type { ObservedVendor } from './bindings/shared/token-usage';
|
|
31
|
+
export { anthropicRecipe, estimateFromMaxTokens } from './bindings/client/providers/anthropic/anthropic-recipe';
|
|
32
|
+
export type { AnthropicMetric, AnthropicMetrics } from './bindings/client/providers/anthropic/anthropic-recipe';
|
|
33
|
+
export { openAIRecipe } from './bindings/client/providers/openai/openai-recipe';
|
|
34
|
+
export type { OpenAIMetric, OpenAIMetrics } from './bindings/client/providers/openai/openai-recipe';
|
|
35
|
+
export { geminiRecipe, geminiChatRecipe, estimateFromMaxOutputTokens, } from './bindings/client/providers/gemini/gemini-recipe';
|
|
36
|
+
export type { GeminiMetric, GeminiMetrics } from './bindings/client/providers/gemini/gemini-recipe';
|
|
37
|
+
export { openrouterRecipe } from './bindings/client/gateways/openrouter/openrouter-recipe';
|
|
38
|
+
export type { OpenRouterMetric, OpenRouterMetrics } from './bindings/client/gateways/openrouter/openrouter-recipe';
|
|
39
|
+
export type { OpenRouterRecipeOptions } from './bindings/client/gateways/openrouter/types';
|
|
40
|
+
export { litellmRecipe } from './bindings/client/gateways/litellm/litellm-recipe';
|
|
41
|
+
export type { LiteLLMMetric, LiteLLMMetrics } from './bindings/client/gateways/litellm/litellm-recipe';
|
|
42
|
+
export type { LiteLLMRecipeOptions } from './bindings/client/gateways/litellm/types';
|
|
43
|
+
export { groqRecipe } from './bindings/client/providers/groq/groq-recipe';
|
|
44
|
+
export type { GroqMetric, GroqMetrics } from './bindings/client/providers/groq/groq-recipe';
|
|
45
|
+
export { mistralRecipe } from './bindings/client/providers/mistral/mistral-recipe';
|
|
46
|
+
export type { MistralMetric, MistralMetrics } from './bindings/client/providers/mistral/mistral-recipe';
|
|
47
|
+
export { ollamaRecipe } from './bindings/client/providers/ollama/ollama-recipe';
|
|
48
|
+
export type { OllamaMetric, OllamaMetrics } from './bindings/client/providers/ollama/ollama-recipe';
|
|
49
|
+
export { databricksRecipe, databricksExternalRecipe } from './bindings/client/gateways/databricks/databricks-recipe';
|
|
50
|
+
export type { DatabricksMetricName, DatabricksMetrics } from './bindings/client/gateways/databricks/databricks-recipe';
|
|
51
|
+
export type { DatabricksRecipeOptions } from './bindings/client/gateways/databricks/types';
|
|
52
|
+
export { bedrockRecipe } from './bindings/client/gateways/bedrock/bedrock-recipe';
|
|
53
|
+
export type { BedrockMetricName, BedrockMetrics } from './bindings/client/gateways/bedrock/bedrock-recipe';
|
|
54
|
+
export type { BedrockRecipeOptions } from './bindings/client/gateways/bedrock/types';
|
|
55
|
+
export { cloudflareRecipe } from './bindings/client/gateways/cloudflare/cloudflare-recipe';
|
|
56
|
+
export type { CloudflareMetricName, CloudflareMetrics } from './bindings/client/gateways/cloudflare/cloudflare-recipe';
|
|
57
|
+
export type { CloudflareRecipeOptions } from './bindings/client/gateways/cloudflare/types';
|
|
58
|
+
export { typesafeRecipe, estimateFromState } from './bindings/client/providers/typesafe/typesafe-recipe';
|
|
59
|
+
export type { TypeSafeMetric, TypeSafeMetrics } from './bindings/client/providers/typesafe/typesafe-recipe';
|
|
60
|
+
export { weightedMetrics } from './bindings/shared/weighted-metrics';
|
|
61
|
+
export type { WeightedMetricsOptions } from './bindings/shared/weighted-metrics';
|
|
62
|
+
export type { ProxyIngestInput } from './bindings/proxy';
|
|
63
|
+
export { normalizedMetrics, normalizeUsage } from './bindings/shared/token-usage';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.normalizeUsage = exports.normalizedMetrics = exports.weightedMetrics = exports.estimateFromState = exports.typesafeRecipe = exports.cloudflareRecipe = exports.bedrockRecipe = exports.databricksExternalRecipe = exports.databricksRecipe = exports.ollamaRecipe = exports.mistralRecipe = exports.groqRecipe = exports.litellmRecipe = exports.openrouterRecipe = exports.estimateFromMaxOutputTokens = exports.geminiChatRecipe = exports.geminiRecipe = exports.openAIRecipe = exports.estimateFromMaxTokens = exports.anthropicRecipe = exports.hasMethod = exports.createClientRegistry = exports.wrapClient = exports.toMeasurement = exports.entitlementRef = exports.entitlementKind = exports.entitlementId = exports.emptyTokenUsage = exports.vendorMetrics = exports.unitsPerTokens = exports.looksLikeGovernanceNotEnabled = exports.isGovernanceNotEnabled = exports.isAccessDenied = exports.isEngineError = exports.GovernanceNotEnabledError = exports.AccessDeniedError = exports.EngineError = exports.noopLogger = exports.consoleLogger = exports.parseGovernanceHeaders = exports.GOVERNANCE_HEADERS = exports.remedyMessage = exports.describeDecision = exports.flattenRaw = exports.RAW_PREFIX = exports.StiggAgentSDK = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Public surface.
|
|
6
|
+
*
|
|
7
|
+
* Importing this file pulls in no vendor package. The recipes below are exported from here, but
|
|
8
|
+
* each one is duck-typed against the shape a vendor returns rather than written against its SDK,
|
|
9
|
+
* so `@anthropic-ai/sdk`, `openai` and the rest stay out of the dependency tree entirely.
|
|
10
|
+
*
|
|
11
|
+
* What is exported here is the vocabulary, the client, and the seams worth extending: a recipe,
|
|
12
|
+
* a metrics mapper, a `GovernanceEngine`. The implementations behind those seams - the concrete
|
|
13
|
+
* engines, decision construction, config resolution, the metric tables - live in
|
|
14
|
+
* `@stigg/agent-sdk-js/internal`, under a weaker compatibility promise.
|
|
15
|
+
*/
|
|
16
|
+
var stigg_agent_sdk_1 = require("./stigg-agent-sdk");
|
|
17
|
+
Object.defineProperty(exports, "StiggAgentSDK", { enumerable: true, get: function () { return stigg_agent_sdk_1.StiggAgentSDK; } });
|
|
18
|
+
// What an event carries off the vendor's own usage object, for anyone building the payload by hand.
|
|
19
|
+
var dimensions_1 = require("./core/dimensions");
|
|
20
|
+
Object.defineProperty(exports, "RAW_PREFIX", { enumerable: true, get: function () { return dimensions_1.RAW_PREFIX; } });
|
|
21
|
+
Object.defineProperty(exports, "flattenRaw", { enumerable: true, get: function () { return dimensions_1.flattenRaw; } });
|
|
22
|
+
var decision_text_1 = require("./decision-text");
|
|
23
|
+
Object.defineProperty(exports, "describeDecision", { enumerable: true, get: function () { return decision_text_1.describeDecision; } });
|
|
24
|
+
Object.defineProperty(exports, "remedyMessage", { enumerable: true, get: function () { return decision_text_1.remedyMessage; } });
|
|
25
|
+
var headers_1 = require("./headers");
|
|
26
|
+
Object.defineProperty(exports, "GOVERNANCE_HEADERS", { enumerable: true, get: function () { return headers_1.GOVERNANCE_HEADERS; } });
|
|
27
|
+
Object.defineProperty(exports, "parseGovernanceHeaders", { enumerable: true, get: function () { return headers_1.parseGovernanceHeaders; } });
|
|
28
|
+
var logger_1 = require("./logger");
|
|
29
|
+
Object.defineProperty(exports, "consoleLogger", { enumerable: true, get: function () { return logger_1.consoleLogger; } });
|
|
30
|
+
Object.defineProperty(exports, "noopLogger", { enumerable: true, get: function () { return logger_1.noopLogger; } });
|
|
31
|
+
var errors_1 = require("./errors");
|
|
32
|
+
Object.defineProperty(exports, "EngineError", { enumerable: true, get: function () { return errors_1.EngineError; } });
|
|
33
|
+
Object.defineProperty(exports, "AccessDeniedError", { enumerable: true, get: function () { return errors_1.AccessDeniedError; } });
|
|
34
|
+
Object.defineProperty(exports, "GovernanceNotEnabledError", { enumerable: true, get: function () { return errors_1.GovernanceNotEnabledError; } });
|
|
35
|
+
Object.defineProperty(exports, "isEngineError", { enumerable: true, get: function () { return errors_1.isEngineError; } });
|
|
36
|
+
Object.defineProperty(exports, "isAccessDenied", { enumerable: true, get: function () { return errors_1.isAccessDenied; } });
|
|
37
|
+
Object.defineProperty(exports, "isGovernanceNotEnabled", { enumerable: true, get: function () { return errors_1.isGovernanceNotEnabled; } });
|
|
38
|
+
Object.defineProperty(exports, "looksLikeGovernanceNotEnabled", { enumerable: true, get: function () { return errors_1.looksLikeGovernanceNotEnabled; } });
|
|
39
|
+
var types_1 = require("./types");
|
|
40
|
+
Object.defineProperty(exports, "unitsPerTokens", { enumerable: true, get: function () { return types_1.unitsPerTokens; } });
|
|
41
|
+
Object.defineProperty(exports, "vendorMetrics", { enumerable: true, get: function () { return types_1.vendorMetrics; } });
|
|
42
|
+
Object.defineProperty(exports, "emptyTokenUsage", { enumerable: true, get: function () { return types_1.emptyTokenUsage; } });
|
|
43
|
+
Object.defineProperty(exports, "entitlementId", { enumerable: true, get: function () { return types_1.entitlementId; } });
|
|
44
|
+
Object.defineProperty(exports, "entitlementKind", { enumerable: true, get: function () { return types_1.entitlementKind; } });
|
|
45
|
+
Object.defineProperty(exports, "entitlementRef", { enumerable: true, get: function () { return types_1.entitlementRef; } });
|
|
46
|
+
Object.defineProperty(exports, "toMeasurement", { enumerable: true, get: function () { return types_1.toMeasurement; } });
|
|
47
|
+
// Bindings: the generic halves only.
|
|
48
|
+
var wrap_client_1 = require("./bindings/client/core/wrap-client");
|
|
49
|
+
Object.defineProperty(exports, "wrapClient", { enumerable: true, get: function () { return wrap_client_1.wrapClient; } });
|
|
50
|
+
var registry_1 = require("./bindings/client/core/registry");
|
|
51
|
+
Object.defineProperty(exports, "createClientRegistry", { enumerable: true, get: function () { return registry_1.createClientRegistry; } });
|
|
52
|
+
Object.defineProperty(exports, "hasMethod", { enumerable: true, get: function () { return registry_1.hasMethod; } });
|
|
53
|
+
var anthropic_recipe_1 = require("./bindings/client/providers/anthropic/anthropic-recipe");
|
|
54
|
+
Object.defineProperty(exports, "anthropicRecipe", { enumerable: true, get: function () { return anthropic_recipe_1.anthropicRecipe; } });
|
|
55
|
+
Object.defineProperty(exports, "estimateFromMaxTokens", { enumerable: true, get: function () { return anthropic_recipe_1.estimateFromMaxTokens; } });
|
|
56
|
+
var openai_recipe_1 = require("./bindings/client/providers/openai/openai-recipe");
|
|
57
|
+
Object.defineProperty(exports, "openAIRecipe", { enumerable: true, get: function () { return openai_recipe_1.openAIRecipe; } });
|
|
58
|
+
// Two recipes for one vendor, because a `GoogleGenAI` client and a `Chat` it created share no
|
|
59
|
+
// method - and a chat holds the *unwrapped* models module privately, so wrapping the client alone
|
|
60
|
+
// would leave every conversation ungoverned. Wrap the chat as well: `stigg.wrap(ai.chats.create(…))`.
|
|
61
|
+
var gemini_recipe_1 = require("./bindings/client/providers/gemini/gemini-recipe");
|
|
62
|
+
Object.defineProperty(exports, "geminiRecipe", { enumerable: true, get: function () { return gemini_recipe_1.geminiRecipe; } });
|
|
63
|
+
Object.defineProperty(exports, "geminiChatRecipe", { enumerable: true, get: function () { return gemini_recipe_1.geminiChatRecipe; } });
|
|
64
|
+
Object.defineProperty(exports, "estimateFromMaxOutputTokens", { enumerable: true, get: function () { return gemini_recipe_1.estimateFromMaxOutputTokens; } });
|
|
65
|
+
// A default: it reports the same token counters as every other vendor, and adds what only a
|
|
66
|
+
// gateway knows - the model that served, the request id, and the `cost` it charged. Billing that
|
|
67
|
+
// cost instead of the tokens is a mapper away, and never inferred from a base URL:
|
|
68
|
+
// `weightedMetrics(openrouterRecipe(), 'credits', { cost: 1 })`.
|
|
69
|
+
var openrouter_recipe_1 = require("./bindings/client/gateways/openrouter/openrouter-recipe");
|
|
70
|
+
Object.defineProperty(exports, "openrouterRecipe", { enumerable: true, get: function () { return openrouter_recipe_1.openrouterRecipe; } });
|
|
71
|
+
// A default too, on the same terms. Its `cost` comes from `x-litellm-response-cost`, which a
|
|
72
|
+
// streamed call cannot carry because headers precede the body - so a run billing cost gets
|
|
73
|
+
// nothing from a stream. Name it at `wrap(client, { recipe })` to give it your proxy's base URL.
|
|
74
|
+
var litellm_recipe_1 = require("./bindings/client/gateways/litellm/litellm-recipe");
|
|
75
|
+
Object.defineProperty(exports, "litellmRecipe", { enumerable: true, get: function () { return litellm_recipe_1.litellmRecipe; } });
|
|
76
|
+
// Built in, and matched by hostname ahead of `openAIRecipe` so its traffic reports as `groq.*`.
|
|
77
|
+
// A provider that speaks the OpenAI wire format: same counters, its own vendor name, and one
|
|
78
|
+
// surface, because `chat.completions.create` is the only generation endpoint Groq serves.
|
|
79
|
+
var groq_recipe_1 = require("./bindings/client/providers/groq/groq-recipe");
|
|
80
|
+
Object.defineProperty(exports, "groqRecipe", { enumerable: true, get: function () { return groq_recipe_1.groqRecipe; } });
|
|
81
|
+
// Built in. Eight generation surfaces over one usage block, reported under the *wire's* names
|
|
82
|
+
// rather than the camelCase its generated SDK renames them to - see the recipe for why, and for
|
|
83
|
+
// the two call styles it cannot reach (the standalone `funcs/` form, and a stream read by hand).
|
|
84
|
+
var mistral_recipe_1 = require("./bindings/client/providers/mistral/mistral-recipe");
|
|
85
|
+
Object.defineProperty(exports, "mistralRecipe", { enumerable: true, get: function () { return mistral_recipe_1.mistralRecipe; } });
|
|
86
|
+
// Built in. A self-hosted engine rather than a vendor that bills: `chat` and `generate` are flat
|
|
87
|
+
// methods on the client, and the counters they report measure the customer's own capacity, since
|
|
88
|
+
// there is no invoice behind them. See the recipe for the surfaces it declines and why.
|
|
89
|
+
var ollama_recipe_1 = require("./bindings/client/providers/ollama/ollama-recipe");
|
|
90
|
+
Object.defineProperty(exports, "ollamaRecipe", { enumerable: true, get: function () { return ollama_recipe_1.ollamaRecipe; } });
|
|
91
|
+
// A default too, and the gateway that states no price. Bedrock's client is a command bus rather
|
|
92
|
+
// than a method tree, so the recipe gates `send` and reads the command to tell inference from the
|
|
93
|
+
// rest of the API; it reports Bedrock's own token counters and no `cost`, because there is none on
|
|
94
|
+
// the response to report. See the recipe for what that means for a run that wanted to bill spend.
|
|
95
|
+
// Databricks model serving, as two recipes for two payers over one wire. `databricksRecipe` is a
|
|
96
|
+
// default, matched on the workspace URL: Foundation Model API traffic, billed to your Databricks
|
|
97
|
+
// account in DBUs. `databricksExternalRecipe` is the same wire reaching an endpoint configured
|
|
98
|
+
// with your own upstream key, where the upstream provider invoices - it is opt-in because the two
|
|
99
|
+
// are indistinguishable from the client and naming it is an assertion about your own workspace,
|
|
100
|
+
// not something the SDK detected. Neither reports a `cost`: Databricks states no price on any
|
|
101
|
+
// response, on either route. See the recipe header for what a wrong assertion costs.
|
|
102
|
+
var databricks_recipe_1 = require("./bindings/client/gateways/databricks/databricks-recipe");
|
|
103
|
+
Object.defineProperty(exports, "databricksRecipe", { enumerable: true, get: function () { return databricks_recipe_1.databricksRecipe; } });
|
|
104
|
+
Object.defineProperty(exports, "databricksExternalRecipe", { enumerable: true, get: function () { return databricks_recipe_1.databricksExternalRecipe; } });
|
|
105
|
+
var bedrock_recipe_1 = require("./bindings/client/gateways/bedrock/bedrock-recipe");
|
|
106
|
+
Object.defineProperty(exports, "bedrockRecipe", { enumerable: true, get: function () { return bedrock_recipe_1.bedrockRecipe; } });
|
|
107
|
+
// Built in as well. One method, no stream, and two counters - see the recipe for why a
|
|
108
|
+
// question-answering API has neither a cache counter nor a cost to report.
|
|
109
|
+
// Cloudflare Workers AI - a provider, not a gateway: Cloudflare runs these models on its own GPUs
|
|
110
|
+
// and invoices them, and `@cf/<author>/…` names who made the weights rather than who bills. A
|
|
111
|
+
// default, matched on `api.cloudflare.com`, covering both the OpenAI-compatible route and the
|
|
112
|
+
// `cloudflare` package's own `ai.run`. It reports tokens and no `cost` - Cloudflare bills in
|
|
113
|
+
// Neurons and publishes none of them on any response. See the recipe for the streamed `ai.run`
|
|
114
|
+
// limitation.
|
|
115
|
+
var cloudflare_recipe_1 = require("./bindings/client/gateways/cloudflare/cloudflare-recipe");
|
|
116
|
+
Object.defineProperty(exports, "cloudflareRecipe", { enumerable: true, get: function () { return cloudflare_recipe_1.cloudflareRecipe; } });
|
|
117
|
+
var typesafe_recipe_1 = require("./bindings/client/providers/typesafe/typesafe-recipe");
|
|
118
|
+
Object.defineProperty(exports, "typesafeRecipe", { enumerable: true, get: function () { return typesafe_recipe_1.typesafeRecipe; } });
|
|
119
|
+
Object.defineProperty(exports, "estimateFromState", { enumerable: true, get: function () { return typesafe_recipe_1.estimateFromState; } });
|
|
120
|
+
var weighted_metrics_1 = require("./bindings/shared/weighted-metrics");
|
|
121
|
+
Object.defineProperty(exports, "weightedMetrics", { enumerable: true, get: function () { return weighted_metrics_1.weightedMetrics; } });
|
|
122
|
+
var token_usage_1 = require("./bindings/shared/token-usage");
|
|
123
|
+
Object.defineProperty(exports, "normalizedMetrics", { enumerable: true, get: function () { return token_usage_1.normalizedMetrics; } });
|
|
124
|
+
Object.defineProperty(exports, "normalizeUsage", { enumerable: true, get: function () { return token_usage_1.normalizeUsage; } });
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Internal surface - `@stigg/agent-sdk-js/internal`.
|
|
3
|
+
*
|
|
4
|
+
* Everything here is an implementation detail: the concrete engines behind the `GovernanceEngine`
|
|
5
|
+
* seam, the pure functions that build a decision, config resolution, and the metric tables the
|
|
6
|
+
* recipes are written against. It is exported because the tests and anyone extending the SDK need
|
|
7
|
+
* to reach it, and reaching into `dist/` by path is worse than a named door.
|
|
8
|
+
*
|
|
9
|
+
* The contract is weaker than `index.ts`: these names can change in a minor release. Anything you
|
|
10
|
+
* can do from the public barrel, do from there instead.
|
|
11
|
+
*/
|
|
12
|
+
export { createGovernanceEngine } from './engine/create-engine';
|
|
13
|
+
export type { CreatedEngine, EngineClientOptions } from './engine/create-engine';
|
|
14
|
+
export { CompositeEngine } from './engine/composite-engine';
|
|
15
|
+
export { NodeSdkEngine } from './engine/node-sdk-engine';
|
|
16
|
+
export { RestGovernanceEngine } from './engine/rest-governance-engine';
|
|
17
|
+
export { describeResolution } from './engine/engine';
|
|
18
|
+
export type { EngineOpSource } from './engine/engine';
|
|
19
|
+
export { withDecisionText, policyDecision, remedyFor, toDecision, unenforcedDecision } from './engine/decision';
|
|
20
|
+
export type { DecisionContext } from './engine/decision';
|
|
21
|
+
export { resolveConfig } from './config';
|
|
22
|
+
export type { ResolvedConfig, EngineConfig } from './config';
|
|
23
|
+
export { isTransportFailure, isMeterMismatchError, asEngineError } from './errors';
|
|
24
|
+
export { prefixed } from './logger';
|
|
25
|
+
export { noCustomer, overrideContext, resolveContext, isEnforced } from './core/context';
|
|
26
|
+
export type { ResolvedContext } from './core/context';
|
|
27
|
+
export { GovernanceSession } from './core/session';
|
|
28
|
+
export type { SessionDeps } from './core/session';
|
|
29
|
+
export { ANTHROPIC_METRICS, GEMINI_METRICS, MISTRAL_METRICS, MISTRAL_METRIC_NAME_MAP, OLLAMA_METRICS, TYPESAFE_METRICS, GATEWAY_METRICS, DATABRICKS_METRICS, DATABRICKS_QUERY_METRIC_NAME_MAP, WORKERS_AI_METRICS, OPENAI_CHAT_METRICS, OPENAI_METRICS, OPENAI_RESPONSES_METRICS, METRIC_PATHS, metricName, metricNamesMatchPaths, pickMetrics, pickRenamedMetrics, addMetrics, addTokenUsage, fromFlatTokenUsage, fromGeminiUsage, fromLangChainUsage, fromMistralUsage, fromOllamaUsage, fromOpenAIUsage, fromResponsesUsage, observedMeasurement, } from './bindings/shared/token-usage';
|
|
30
|
+
export type { ObservedVendor } from './bindings/shared/token-usage';
|
|
31
|
+
export { DEFAULT_RECIPES } from './stigg-agent-sdk';
|
|
32
|
+
export { meterStream } from './bindings/shared/meter-stream';
|
|
33
|
+
export { eventNameFor } from './bindings/client/core/types';
|
package/dist/internal.js
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Internal surface - `@stigg/agent-sdk-js/internal`.
|
|
4
|
+
*
|
|
5
|
+
* Everything here is an implementation detail: the concrete engines behind the `GovernanceEngine`
|
|
6
|
+
* seam, the pure functions that build a decision, config resolution, and the metric tables the
|
|
7
|
+
* recipes are written against. It is exported because the tests and anyone extending the SDK need
|
|
8
|
+
* to reach it, and reaching into `dist/` by path is worse than a named door.
|
|
9
|
+
*
|
|
10
|
+
* The contract is weaker than `index.ts`: these names can change in a minor release. Anything you
|
|
11
|
+
* can do from the public barrel, do from there instead.
|
|
12
|
+
*/
|
|
13
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
+
exports.meterStream = exports.DEFAULT_RECIPES = exports.observedMeasurement = exports.fromResponsesUsage = exports.fromOpenAIUsage = exports.fromOllamaUsage = exports.fromMistralUsage = exports.fromLangChainUsage = exports.fromGeminiUsage = exports.fromFlatTokenUsage = exports.addTokenUsage = exports.addMetrics = exports.pickRenamedMetrics = exports.pickMetrics = exports.metricNamesMatchPaths = exports.metricName = exports.METRIC_PATHS = exports.OPENAI_RESPONSES_METRICS = exports.OPENAI_METRICS = exports.OPENAI_CHAT_METRICS = exports.WORKERS_AI_METRICS = exports.DATABRICKS_QUERY_METRIC_NAME_MAP = exports.DATABRICKS_METRICS = exports.GATEWAY_METRICS = exports.TYPESAFE_METRICS = exports.OLLAMA_METRICS = exports.MISTRAL_METRIC_NAME_MAP = exports.MISTRAL_METRICS = exports.GEMINI_METRICS = exports.ANTHROPIC_METRICS = exports.GovernanceSession = exports.isEnforced = exports.resolveContext = exports.overrideContext = exports.noCustomer = exports.prefixed = exports.asEngineError = exports.isMeterMismatchError = exports.isTransportFailure = exports.resolveConfig = exports.unenforcedDecision = exports.toDecision = exports.remedyFor = exports.policyDecision = exports.withDecisionText = exports.describeResolution = exports.RestGovernanceEngine = exports.NodeSdkEngine = exports.CompositeEngine = exports.createGovernanceEngine = void 0;
|
|
15
|
+
exports.eventNameFor = void 0;
|
|
16
|
+
// The engine seam's implementations. The interface itself is public - see `index.ts`.
|
|
17
|
+
var create_engine_1 = require("./engine/create-engine");
|
|
18
|
+
Object.defineProperty(exports, "createGovernanceEngine", { enumerable: true, get: function () { return create_engine_1.createGovernanceEngine; } });
|
|
19
|
+
var composite_engine_1 = require("./engine/composite-engine");
|
|
20
|
+
Object.defineProperty(exports, "CompositeEngine", { enumerable: true, get: function () { return composite_engine_1.CompositeEngine; } });
|
|
21
|
+
var node_sdk_engine_1 = require("./engine/node-sdk-engine");
|
|
22
|
+
Object.defineProperty(exports, "NodeSdkEngine", { enumerable: true, get: function () { return node_sdk_engine_1.NodeSdkEngine; } });
|
|
23
|
+
var rest_governance_engine_1 = require("./engine/rest-governance-engine");
|
|
24
|
+
Object.defineProperty(exports, "RestGovernanceEngine", { enumerable: true, get: function () { return rest_governance_engine_1.RestGovernanceEngine; } });
|
|
25
|
+
var engine_1 = require("./engine/engine");
|
|
26
|
+
Object.defineProperty(exports, "describeResolution", { enumerable: true, get: function () { return engine_1.describeResolution; } });
|
|
27
|
+
// Engine result -> the structured refusal, as pure functions.
|
|
28
|
+
var decision_1 = require("./engine/decision");
|
|
29
|
+
Object.defineProperty(exports, "withDecisionText", { enumerable: true, get: function () { return decision_1.withDecisionText; } });
|
|
30
|
+
Object.defineProperty(exports, "policyDecision", { enumerable: true, get: function () { return decision_1.policyDecision; } });
|
|
31
|
+
Object.defineProperty(exports, "remedyFor", { enumerable: true, get: function () { return decision_1.remedyFor; } });
|
|
32
|
+
Object.defineProperty(exports, "toDecision", { enumerable: true, get: function () { return decision_1.toDecision; } });
|
|
33
|
+
Object.defineProperty(exports, "unenforcedDecision", { enumerable: true, get: function () { return decision_1.unenforcedDecision; } });
|
|
34
|
+
// Config resolution: the target and the options, as the transport actually needs them.
|
|
35
|
+
var config_1 = require("./config");
|
|
36
|
+
Object.defineProperty(exports, "resolveConfig", { enumerable: true, get: function () { return config_1.resolveConfig; } });
|
|
37
|
+
// Error predicates that describe transport and enablement, not the caller's contract.
|
|
38
|
+
var errors_1 = require("./errors");
|
|
39
|
+
Object.defineProperty(exports, "isTransportFailure", { enumerable: true, get: function () { return errors_1.isTransportFailure; } });
|
|
40
|
+
Object.defineProperty(exports, "isMeterMismatchError", { enumerable: true, get: function () { return errors_1.isMeterMismatchError; } });
|
|
41
|
+
Object.defineProperty(exports, "asEngineError", { enumerable: true, get: function () { return errors_1.asEngineError; } });
|
|
42
|
+
var logger_1 = require("./logger");
|
|
43
|
+
Object.defineProperty(exports, "prefixed", { enumerable: true, get: function () { return logger_1.prefixed; } });
|
|
44
|
+
// Context resolution: the split that keeps a gated call's own overhead to a property read.
|
|
45
|
+
var context_1 = require("./core/context");
|
|
46
|
+
Object.defineProperty(exports, "noCustomer", { enumerable: true, get: function () { return context_1.noCustomer; } });
|
|
47
|
+
Object.defineProperty(exports, "overrideContext", { enumerable: true, get: function () { return context_1.overrideContext; } });
|
|
48
|
+
Object.defineProperty(exports, "resolveContext", { enumerable: true, get: function () { return context_1.resolveContext; } });
|
|
49
|
+
Object.defineProperty(exports, "isEnforced", { enumerable: true, get: function () { return context_1.isEnforced; } });
|
|
50
|
+
var session_1 = require("./core/session");
|
|
51
|
+
Object.defineProperty(exports, "GovernanceSession", { enumerable: true, get: function () { return session_1.GovernanceSession; } });
|
|
52
|
+
// What each vendor calls its counters, and where they are read from. A recipe is written against
|
|
53
|
+
// these; a consumer reads `recipe.metrics` instead.
|
|
54
|
+
var token_usage_1 = require("./bindings/shared/token-usage");
|
|
55
|
+
Object.defineProperty(exports, "ANTHROPIC_METRICS", { enumerable: true, get: function () { return token_usage_1.ANTHROPIC_METRICS; } });
|
|
56
|
+
Object.defineProperty(exports, "GEMINI_METRICS", { enumerable: true, get: function () { return token_usage_1.GEMINI_METRICS; } });
|
|
57
|
+
Object.defineProperty(exports, "MISTRAL_METRICS", { enumerable: true, get: function () { return token_usage_1.MISTRAL_METRICS; } });
|
|
58
|
+
Object.defineProperty(exports, "MISTRAL_METRIC_NAME_MAP", { enumerable: true, get: function () { return token_usage_1.MISTRAL_METRIC_NAME_MAP; } });
|
|
59
|
+
Object.defineProperty(exports, "OLLAMA_METRICS", { enumerable: true, get: function () { return token_usage_1.OLLAMA_METRICS; } });
|
|
60
|
+
Object.defineProperty(exports, "TYPESAFE_METRICS", { enumerable: true, get: function () { return token_usage_1.TYPESAFE_METRICS; } });
|
|
61
|
+
Object.defineProperty(exports, "GATEWAY_METRICS", { enumerable: true, get: function () { return token_usage_1.GATEWAY_METRICS; } });
|
|
62
|
+
Object.defineProperty(exports, "DATABRICKS_METRICS", { enumerable: true, get: function () { return token_usage_1.DATABRICKS_METRICS; } });
|
|
63
|
+
Object.defineProperty(exports, "DATABRICKS_QUERY_METRIC_NAME_MAP", { enumerable: true, get: function () { return token_usage_1.DATABRICKS_QUERY_METRIC_NAME_MAP; } });
|
|
64
|
+
Object.defineProperty(exports, "WORKERS_AI_METRICS", { enumerable: true, get: function () { return token_usage_1.WORKERS_AI_METRICS; } });
|
|
65
|
+
Object.defineProperty(exports, "OPENAI_CHAT_METRICS", { enumerable: true, get: function () { return token_usage_1.OPENAI_CHAT_METRICS; } });
|
|
66
|
+
Object.defineProperty(exports, "OPENAI_METRICS", { enumerable: true, get: function () { return token_usage_1.OPENAI_METRICS; } });
|
|
67
|
+
Object.defineProperty(exports, "OPENAI_RESPONSES_METRICS", { enumerable: true, get: function () { return token_usage_1.OPENAI_RESPONSES_METRICS; } });
|
|
68
|
+
Object.defineProperty(exports, "METRIC_PATHS", { enumerable: true, get: function () { return token_usage_1.METRIC_PATHS; } });
|
|
69
|
+
Object.defineProperty(exports, "metricName", { enumerable: true, get: function () { return token_usage_1.metricName; } });
|
|
70
|
+
Object.defineProperty(exports, "metricNamesMatchPaths", { enumerable: true, get: function () { return token_usage_1.metricNamesMatchPaths; } });
|
|
71
|
+
Object.defineProperty(exports, "pickMetrics", { enumerable: true, get: function () { return token_usage_1.pickMetrics; } });
|
|
72
|
+
Object.defineProperty(exports, "pickRenamedMetrics", { enumerable: true, get: function () { return token_usage_1.pickRenamedMetrics; } });
|
|
73
|
+
Object.defineProperty(exports, "addMetrics", { enumerable: true, get: function () { return token_usage_1.addMetrics; } });
|
|
74
|
+
Object.defineProperty(exports, "addTokenUsage", { enumerable: true, get: function () { return token_usage_1.addTokenUsage; } });
|
|
75
|
+
Object.defineProperty(exports, "fromFlatTokenUsage", { enumerable: true, get: function () { return token_usage_1.fromFlatTokenUsage; } });
|
|
76
|
+
Object.defineProperty(exports, "fromGeminiUsage", { enumerable: true, get: function () { return token_usage_1.fromGeminiUsage; } });
|
|
77
|
+
Object.defineProperty(exports, "fromLangChainUsage", { enumerable: true, get: function () { return token_usage_1.fromLangChainUsage; } });
|
|
78
|
+
Object.defineProperty(exports, "fromMistralUsage", { enumerable: true, get: function () { return token_usage_1.fromMistralUsage; } });
|
|
79
|
+
Object.defineProperty(exports, "fromOllamaUsage", { enumerable: true, get: function () { return token_usage_1.fromOllamaUsage; } });
|
|
80
|
+
Object.defineProperty(exports, "fromOpenAIUsage", { enumerable: true, get: function () { return token_usage_1.fromOpenAIUsage; } });
|
|
81
|
+
Object.defineProperty(exports, "fromResponsesUsage", { enumerable: true, get: function () { return token_usage_1.fromResponsesUsage; } });
|
|
82
|
+
Object.defineProperty(exports, "observedMeasurement", { enumerable: true, get: function () { return token_usage_1.observedMeasurement; } });
|
|
83
|
+
// The recipes `wrap` matches against when no recipe is named. Exposed so a caller - the examples'
|
|
84
|
+
// own offline seeding, above all - can enumerate what this package governs without keeping a
|
|
85
|
+
// second copy of the list that silently falls behind each time a vendor is added.
|
|
86
|
+
var stigg_agent_sdk_1 = require("./stigg-agent-sdk");
|
|
87
|
+
Object.defineProperty(exports, "DEFAULT_RECIPES", { enumerable: true, get: function () { return stigg_agent_sdk_1.DEFAULT_RECIPES; } });
|
|
88
|
+
var meter_stream_1 = require("./bindings/shared/meter-stream");
|
|
89
|
+
Object.defineProperty(exports, "meterStream", { enumerable: true, get: function () { return meter_stream_1.meterStream; } });
|
|
90
|
+
var types_1 = require("./bindings/client/core/types");
|
|
91
|
+
Object.defineProperty(exports, "eventNameFor", { enumerable: true, get: function () { return types_1.eventNameFor; } });
|
package/dist/logger.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The smallest logger the SDK can depend on. Structural, so any console-shaped object - or a
|
|
3
|
+
* pino/winston child - satisfies it without an adapter.
|
|
4
|
+
*/
|
|
5
|
+
export interface Logger {
|
|
6
|
+
debug(message: string, ...args: unknown[]): void;
|
|
7
|
+
info(message: string, ...args: unknown[]): void;
|
|
8
|
+
warn(message: string, ...args: unknown[]): void;
|
|
9
|
+
error(message: string, ...args: unknown[]): void;
|
|
10
|
+
}
|
|
11
|
+
/** What `logger: 'none'` resolves to, for a process that wants the SDK silent. */
|
|
12
|
+
export declare const noopLogger: Logger;
|
|
13
|
+
export declare const consoleLogger: Logger;
|
|
14
|
+
/** Prefixes every line, so example output shows which subsystem spoke. */
|
|
15
|
+
export declare const prefixed: (logger: Logger, prefix: string) => Logger;
|