@sentropic/llm-mesh 0.28.0 → 0.28.1
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 +92 -0
- package/dist/capabilities.d.ts +3 -0
- package/dist/capabilities.d.ts.map +1 -1
- package/dist/capabilities.js.map +1 -1
- package/dist/catalog.d.ts +134 -1
- package/dist/catalog.d.ts.map +1 -1
- package/dist/catalog.js +15 -0
- package/dist/catalog.js.map +1 -1
- package/dist/decision/adapter-result.d.ts +6 -0
- package/dist/decision/adapter-result.d.ts.map +1 -0
- package/dist/decision/adapter-result.js +148 -0
- package/dist/decision/adapter-result.js.map +1 -0
- package/dist/decision/adapter.d.ts +58 -0
- package/dist/decision/adapter.d.ts.map +1 -0
- package/dist/decision/adapter.js +70 -0
- package/dist/decision/adapter.js.map +1 -0
- package/dist/decision/admission.d.ts +23 -0
- package/dist/decision/admission.d.ts.map +1 -0
- package/dist/decision/admission.js +115 -0
- package/dist/decision/admission.js.map +1 -0
- package/dist/decision/budget.d.ts +60 -0
- package/dist/decision/budget.d.ts.map +1 -0
- package/dist/decision/budget.js +2 -0
- package/dist/decision/budget.js.map +1 -0
- package/dist/decision/client.d.ts +23 -0
- package/dist/decision/client.d.ts.map +1 -0
- package/dist/decision/client.js +836 -0
- package/dist/decision/client.js.map +1 -0
- package/dist/decision/criterion.d.ts +5 -0
- package/dist/decision/criterion.d.ts.map +1 -0
- package/dist/decision/criterion.js +54 -0
- package/dist/decision/criterion.js.map +1 -0
- package/dist/decision/deadline.d.ts +8 -0
- package/dist/decision/deadline.d.ts.map +1 -0
- package/dist/decision/deadline.js +56 -0
- package/dist/decision/deadline.js.map +1 -0
- package/dist/decision/descriptor-validation.d.ts +5 -0
- package/dist/decision/descriptor-validation.d.ts.map +1 -0
- package/dist/decision/descriptor-validation.js +99 -0
- package/dist/decision/descriptor-validation.js.map +1 -0
- package/dist/decision/descriptor.d.ts +81 -0
- package/dist/decision/descriptor.d.ts.map +1 -0
- package/dist/decision/descriptor.js +36 -0
- package/dist/decision/descriptor.js.map +1 -0
- package/dist/decision/dispatch.d.ts +11 -0
- package/dist/decision/dispatch.d.ts.map +1 -0
- package/dist/decision/dispatch.js +56 -0
- package/dist/decision/dispatch.js.map +1 -0
- package/dist/decision/errors.d.ts +43 -0
- package/dist/decision/errors.d.ts.map +1 -0
- package/dist/decision/errors.js +47 -0
- package/dist/decision/errors.js.map +1 -0
- package/dist/decision/execution.d.ts +31 -0
- package/dist/decision/execution.d.ts.map +1 -0
- package/dist/decision/execution.js +79 -0
- package/dist/decision/execution.js.map +1 -0
- package/dist/decision/host-options.d.ts +26 -0
- package/dist/decision/host-options.d.ts.map +1 -0
- package/dist/decision/host-options.js +2 -0
- package/dist/decision/host-options.js.map +1 -0
- package/dist/decision/host.d.ts +14 -0
- package/dist/decision/host.d.ts.map +1 -0
- package/dist/decision/host.js +6 -0
- package/dist/decision/host.js.map +1 -0
- package/dist/decision/index.d.ts +12 -0
- package/dist/decision/index.d.ts.map +1 -0
- package/dist/decision/index.js +3 -0
- package/dist/decision/index.js.map +1 -0
- package/dist/decision/jev-codec.d.ts +30 -0
- package/dist/decision/jev-codec.d.ts.map +1 -0
- package/dist/decision/jev-codec.js +51 -0
- package/dist/decision/jev-codec.js.map +1 -0
- package/dist/decision/jev-response.d.ts +7 -0
- package/dist/decision/jev-response.d.ts.map +1 -0
- package/dist/decision/jev-response.js +42 -0
- package/dist/decision/jev-response.js.map +1 -0
- package/dist/decision/jev-verdict.d.ts +14 -0
- package/dist/decision/jev-verdict.d.ts.map +1 -0
- package/dist/decision/jev-verdict.js +71 -0
- package/dist/decision/jev-verdict.js.map +1 -0
- package/dist/decision/policy.d.ts +11 -0
- package/dist/decision/policy.d.ts.map +1 -0
- package/dist/decision/policy.js +33 -0
- package/dist/decision/policy.js.map +1 -0
- package/dist/decision/pricing.d.ts +40 -0
- package/dist/decision/pricing.d.ts.map +1 -0
- package/dist/decision/pricing.js +65 -0
- package/dist/decision/pricing.js.map +1 -0
- package/dist/decision/raw.d.ts +7 -0
- package/dist/decision/raw.d.ts.map +1 -0
- package/dist/decision/raw.js +53 -0
- package/dist/decision/raw.js.map +1 -0
- package/dist/decision/receipt.d.ts +120 -0
- package/dist/decision/receipt.d.ts.map +1 -0
- package/dist/decision/receipt.js +58 -0
- package/dist/decision/receipt.js.map +1 -0
- package/dist/decision/request-policy.d.ts +3 -0
- package/dist/decision/request-policy.d.ts.map +1 -0
- package/dist/decision/request-policy.js +19 -0
- package/dist/decision/request-policy.js.map +1 -0
- package/dist/decision/request.d.ts +85 -0
- package/dist/decision/request.d.ts.map +1 -0
- package/dist/decision/request.js +49 -0
- package/dist/decision/request.js.map +1 -0
- package/dist/decision/service.d.ts +39 -0
- package/dist/decision/service.d.ts.map +1 -0
- package/dist/decision/service.js +138 -0
- package/dist/decision/service.js.map +1 -0
- package/dist/decision/structured.d.ts +125 -0
- package/dist/decision/structured.d.ts.map +1 -0
- package/dist/decision/structured.js +250 -0
- package/dist/decision/structured.js.map +1 -0
- package/dist/decision/validate-result.d.ts +8 -0
- package/dist/decision/validate-result.d.ts.map +1 -0
- package/dist/decision/validate-result.js +91 -0
- package/dist/decision/validate-result.js.map +1 -0
- package/dist/decision/validation-context.d.ts +55 -0
- package/dist/decision/validation-context.d.ts.map +1 -0
- package/dist/decision/validation-context.js +134 -0
- package/dist/decision/validation-context.js.map +1 -0
- package/dist/decision/validation.d.ts +19 -0
- package/dist/decision/validation.d.ts.map +1 -0
- package/dist/decision/validation.js +86 -0
- package/dist/decision/validation.js.map +1 -0
- package/dist/decision/verdict.d.ts +81 -0
- package/dist/decision/verdict.d.ts.map +1 -0
- package/dist/decision/verdict.js +140 -0
- package/dist/decision/verdict.js.map +1 -0
- package/dist/providers.d.ts +4 -3
- package/dist/providers.d.ts.map +1 -1
- package/dist/providers.js +2 -1
- package/dist/providers.js.map +1 -1
- package/dist/registry.d.ts +6 -0
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js.map +1 -1
- package/dist/transport/jev.d.ts +23 -0
- package/dist/transport/jev.d.ts.map +1 -0
- package/dist/transport/jev.js +107 -0
- package/dist/transport/jev.js.map +1 -0
- package/package.json +13 -1
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { DecisionRequest } from './request.js';
|
|
2
|
+
import type { DecisionEvaluatorDescriptor } from './descriptor.js';
|
|
3
|
+
import type { DecisionErrorCode } from './errors.js';
|
|
4
|
+
export interface DecisionHostPolicy {
|
|
5
|
+
timeoutMs?: number;
|
|
6
|
+
maxCostMicroUsd?: string;
|
|
7
|
+
allowRaw?: boolean;
|
|
8
|
+
}
|
|
9
|
+
/** Capability/decision refusal precedes credential acquisition and financial admission. */
|
|
10
|
+
export declare function validateDecisionPolicy(request: DecisionRequest, descriptor: DecisionEvaluatorDescriptor, host?: DecisionHostPolicy): DecisionErrorCode | null;
|
|
11
|
+
//# sourceMappingURL=policy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"policy.d.ts","sourceRoot":"","sources":["../../src/decision/policy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,iBAAiB,CAAC;AACnE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAGrD,MAAM,WAAW,kBAAkB;IAAG,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAE;AACxG,2FAA2F;AAC3F,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,2BAA2B,EACtG,IAAI,GAAE,kBAAuB,GAAG,iBAAiB,GAAG,IAAI,CAqBzD"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { encodeJevRequest } from './jev-codec.js';
|
|
2
|
+
/** Capability/decision refusal precedes credential acquisition and financial admission. */
|
|
3
|
+
export function validateDecisionPolicy(request, descriptor, host = {}) {
|
|
4
|
+
const encoded = encodeJevRequest(request, descriptor);
|
|
5
|
+
if (!encoded.ok)
|
|
6
|
+
return encoded.code;
|
|
7
|
+
const criterion = encoded.criterion;
|
|
8
|
+
if (descriptor.qualification.servedIdentity !== 'qualified')
|
|
9
|
+
return 'PROVIDER_UNAVAILABLE';
|
|
10
|
+
if (request.policy?.explanation === 'required' || request.decision?.kind === 'provider')
|
|
11
|
+
return 'CAPABILITY_UNSUPPORTED';
|
|
12
|
+
if (request.raw?.mode === 'allowlisted' && host.allowRaw !== true)
|
|
13
|
+
return 'CAPABILITY_UNSUPPORTED';
|
|
14
|
+
if (criterion.kind === 'choice' && criterion.options.some((option) => ['__proto__', 'constructor', 'prototype'].includes(option.id))) {
|
|
15
|
+
return 'CAPABILITY_UNSUPPORTED';
|
|
16
|
+
}
|
|
17
|
+
const rule = request.decision;
|
|
18
|
+
if (rule?.kind === 'threshold') {
|
|
19
|
+
if (criterion.kind === 'choice')
|
|
20
|
+
return 'CAPABILITY_UNSUPPORTED';
|
|
21
|
+
const max = criterion.kind === 'binary' ? 1 : criterion.levels.length - 1;
|
|
22
|
+
if (rule.value < 0 || rule.value > max)
|
|
23
|
+
return 'REQUEST_INVALID';
|
|
24
|
+
}
|
|
25
|
+
if (rule?.kind === 'labels') {
|
|
26
|
+
if (criterion.kind !== 'choice')
|
|
27
|
+
return 'CAPABILITY_UNSUPPORTED';
|
|
28
|
+
if (!rule.passing.every((label) => criterion.options.some((option) => option.id === label)))
|
|
29
|
+
return 'REQUEST_INVALID';
|
|
30
|
+
}
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=policy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"policy.js","sourceRoot":"","sources":["../../src/decision/policy.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAGlD,2FAA2F;AAC3F,MAAM,UAAU,sBAAsB,CAAC,OAAwB,EAAE,UAAuC,EACtG,OAA2B,EAAE;IAC7B,MAAM,OAAO,GAAG,gBAAgB,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;IACtD,IAAI,CAAC,OAAO,CAAC,EAAE;QAAE,OAAO,OAAO,CAAC,IAAI,CAAC;IACrC,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC;IACpC,IAAI,UAAU,CAAC,aAAa,CAAC,cAAc,KAAK,WAAW;QAAE,OAAO,sBAAsB,CAAC;IAC3F,IAAI,OAAO,CAAC,MAAM,EAAE,WAAW,KAAK,UAAU,IAAI,OAAO,CAAC,QAAQ,EAAE,IAAI,KAAK,UAAU;QAAE,OAAO,wBAAwB,CAAC;IACzH,IAAI,OAAO,CAAC,GAAG,EAAE,IAAI,KAAK,aAAa,IAAI,IAAI,CAAC,QAAQ,KAAK,IAAI;QAAE,OAAO,wBAAwB,CAAC;IACnG,IAAI,SAAS,CAAC,IAAI,KAAK,QAAQ,IAAI,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,WAAW,EAAE,aAAa,EAAE,WAAW,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;QACrI,OAAO,wBAAwB,CAAC;IAClC,CAAC;IACD,MAAM,IAAI,GAAG,OAAO,CAAC,QAAQ,CAAC;IAC9B,IAAI,IAAI,EAAE,IAAI,KAAK,WAAW,EAAE,CAAC;QAC/B,IAAI,SAAS,CAAC,IAAI,KAAK,QAAQ;YAAE,OAAO,wBAAwB,CAAC;QACjE,MAAM,GAAG,GAAG,SAAS,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC;QAC1E,IAAI,IAAI,CAAC,KAAK,GAAG,CAAC,IAAI,IAAI,CAAC,KAAK,GAAG,GAAG;YAAE,OAAO,iBAAiB,CAAC;IACnE,CAAC;IACD,IAAI,IAAI,EAAE,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC5B,IAAI,SAAS,CAAC,IAAI,KAAK,QAAQ;YAAE,OAAO,wBAAwB,CAAC;QACjE,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,EAAE,KAAK,KAAK,CAAC,CAAC;YAAE,OAAO,iBAAiB,CAAC;IACxH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { DecisionRequest, MicroUsd } from './request.js';
|
|
2
|
+
import type { DecisionBackendProtocol, DecisionEvaluatorDescriptor } from './descriptor.js';
|
|
3
|
+
import type { DecisionCost, DecisionUsage } from './receipt.js';
|
|
4
|
+
/** Projection of the host's existing immutable provider/model price row. The
|
|
5
|
+
* optional authority/protocol cells bind a row to one price authority and
|
|
6
|
+
* backend protocol; present cells must match the descriptor (§3.2
|
|
7
|
+
* Accounting), so two authorities cannot share a revision silently. */
|
|
8
|
+
export interface DecisionPrice {
|
|
9
|
+
providerId: string;
|
|
10
|
+
modelId: string;
|
|
11
|
+
priceRevision: string;
|
|
12
|
+
inputMicroUsdPerMtok: MicroUsd;
|
|
13
|
+
outputMicroUsdPerMtok: MicroUsd;
|
|
14
|
+
minimumMicroUsd: MicroUsd;
|
|
15
|
+
identityMismatchPricing: 'requested-model' | 'requires-reconciliation';
|
|
16
|
+
authority: string;
|
|
17
|
+
protocol: DecisionBackendProtocol;
|
|
18
|
+
}
|
|
19
|
+
export interface DecisionQuote {
|
|
20
|
+
price: DecisionPrice;
|
|
21
|
+
reservedMicroUsd: MicroUsd;
|
|
22
|
+
}
|
|
23
|
+
export declare const isMicroUsd: (value: unknown) => value is string;
|
|
24
|
+
export declare function quoteDecision(request: DecisionRequest, descriptor: DecisionEvaluatorDescriptor, candidate: unknown, hostCap?: MicroUsd): {
|
|
25
|
+
ok: true;
|
|
26
|
+
quote: DecisionQuote;
|
|
27
|
+
} | {
|
|
28
|
+
ok: false;
|
|
29
|
+
code: 'PRICING_UNAVAILABLE' | 'BUDGET_BOUND_UNAVAILABLE' | 'BUDGET_EXHAUSTED';
|
|
30
|
+
};
|
|
31
|
+
/** Uncertain execution uses the reserve, never invented tokens or a zero charge.
|
|
32
|
+
* Any priced component whose usage is unknown keeps the settlement pending
|
|
33
|
+
* and charges at least the full reserve: known input spend never releases
|
|
34
|
+
* the unknown output liability. */
|
|
35
|
+
export declare function priceDecisionUsage(usage: DecisionUsage, quote: DecisionQuote, identityMismatch?: boolean): {
|
|
36
|
+
cost: DecisionCost;
|
|
37
|
+
pending: boolean;
|
|
38
|
+
overrun: boolean;
|
|
39
|
+
};
|
|
40
|
+
//# sourceMappingURL=pricing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pricing.d.ts","sourceRoot":"","sources":["../../src/decision/pricing.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAC9D,OAAO,KAAK,EAAE,uBAAuB,EAAE,2BAA2B,EAAE,MAAM,iBAAiB,CAAC;AAC5F,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAIhE;;;uEAGuE;AACvE,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAC;IAC3D,oBAAoB,EAAE,QAAQ,CAAC;IAAC,qBAAqB,EAAE,QAAQ,CAAC;IAAC,eAAe,EAAE,QAAQ,CAAC;IAC3F,uBAAuB,EAAE,iBAAiB,GAAG,yBAAyB,CAAC;IACvE,SAAS,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,uBAAuB,CAAC;CACtD;AACD,MAAM,WAAW,aAAa;IAAG,KAAK,EAAE,aAAa,CAAC;IAAC,gBAAgB,EAAE,QAAQ,CAAA;CAAE;AACnF,eAAO,MAAM,UAAU,UAAW,OAAO,oBAAoF,CAAC;AAI9H,wBAAgB,aAAa,CAAC,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,2BAA2B,EAAE,SAAS,EAAE,OAAO,EACjH,OAAO,CAAC,EAAE,QAAQ,GAAG;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,aAAa,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,qBAAqB,GAAG,0BAA0B,GAAG,kBAAkB,CAAA;CAAE,CA6BvJ;AAED;;;mCAGmC;AACnC,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,aAAa,EAAE,KAAK,EAAE,aAAa,EAAE,gBAAgB,UAAQ,GACrG;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,OAAO,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAmB3D"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { freezeDecisionData } from './descriptor-validation.js';
|
|
2
|
+
import { hasOnlyKeys, isCorrelationId, isRecord, snapshotBoundedJson } from './validation.js';
|
|
3
|
+
export const isMicroUsd = (value) => typeof value === 'string' && /^(0|[1-9][0-9]*)$/.test(value);
|
|
4
|
+
const ceilRate = (tokens, rate) => (BigInt(tokens) * BigInt(rate) + 999999n) / 1000000n;
|
|
5
|
+
const minimum = (value, price) => value > BigInt(price.minimumMicroUsd) ? value : BigInt(price.minimumMicroUsd);
|
|
6
|
+
export function quoteDecision(request, descriptor, candidate, hostCap) {
|
|
7
|
+
const snapshot = snapshotBoundedJson(candidate);
|
|
8
|
+
const value = snapshot.ok ? snapshot.value : null;
|
|
9
|
+
if (!isRecord(value) || !hasOnlyKeys(value, ['providerId', 'modelId', 'priceRevision', 'inputMicroUsdPerMtok',
|
|
10
|
+
'outputMicroUsdPerMtok', 'minimumMicroUsd', 'identityMismatchPricing', 'authority', 'protocol']) || value.providerId !== descriptor.evaluator.providerId
|
|
11
|
+
|| value.modelId !== descriptor.wireModel || value.priceRevision !== descriptor.priceProtocol.revision
|
|
12
|
+
|| !isCorrelationId(value.priceRevision)
|
|
13
|
+
|| !isMicroUsd(value.inputMicroUsdPerMtok) || !isMicroUsd(value.outputMicroUsdPerMtok) || !isMicroUsd(value.minimumMicroUsd)
|
|
14
|
+
|| !['requested-model', 'requires-reconciliation'].some((v) => v === value.identityMismatchPricing)
|
|
15
|
+
|| value.authority !== descriptor.priceProtocol.authority
|
|
16
|
+
|| value.protocol !== (descriptor.protocol ?? 'jev-native'))
|
|
17
|
+
return { ok: false, code: 'PRICING_UNAVAILABLE' };
|
|
18
|
+
const price = freezeDecisionData(value);
|
|
19
|
+
if (descriptor.qualification.billingBound !== 'qualified')
|
|
20
|
+
return { ok: false, code: 'BUDGET_BOUND_UNAVAILABLE' };
|
|
21
|
+
const isJev = (descriptor.protocol ?? 'jev-native') === 'jev-native';
|
|
22
|
+
// JEV has no qualified output liability bound. A nonzero output rate cannot be reserved.
|
|
23
|
+
if (isJev && price.outputMicroUsdPerMtok !== '0')
|
|
24
|
+
return { ok: false, code: 'BUDGET_BOUND_UNAVAILABLE' };
|
|
25
|
+
// Non-JEV protocols price output work, so quoting requires the descriptor's
|
|
26
|
+
// enforced output/reasoning bound. Without it no finite liability exists.
|
|
27
|
+
const outputBound = descriptor.maxBillableOutputTokens;
|
|
28
|
+
if (!isJev && (typeof outputBound !== 'number' || !Number.isSafeInteger(outputBound) || outputBound < 1)) {
|
|
29
|
+
return { ok: false, code: 'BUDGET_BOUND_UNAVAILABLE' };
|
|
30
|
+
}
|
|
31
|
+
const inputReserve = ceilRate(descriptor.maxBillableInputTokens, price.inputMicroUsdPerMtok);
|
|
32
|
+
const outputReserve = isJev ? 0n : ceilRate(descriptor.maxBillableOutputTokens, price.outputMicroUsdPerMtok);
|
|
33
|
+
const reserve = minimum(inputReserve + outputReserve, price);
|
|
34
|
+
const caps = [hostCap, request.policy?.budget?.maxCostMicroUsd].filter((v) => v !== undefined);
|
|
35
|
+
if (caps.some((cap) => !isMicroUsd(cap)))
|
|
36
|
+
return { ok: false, code: 'PRICING_UNAVAILABLE' };
|
|
37
|
+
if (caps.some((cap) => reserve > BigInt(cap)))
|
|
38
|
+
return { ok: false, code: 'BUDGET_EXHAUSTED' };
|
|
39
|
+
return { ok: true, quote: freezeDecisionData({ price, reservedMicroUsd: reserve.toString() }) };
|
|
40
|
+
}
|
|
41
|
+
/** Uncertain execution uses the reserve, never invented tokens or a zero charge.
|
|
42
|
+
* Any priced component whose usage is unknown keeps the settlement pending
|
|
43
|
+
* and charges at least the full reserve: known input spend never releases
|
|
44
|
+
* the unknown output liability. */
|
|
45
|
+
export function priceDecisionUsage(usage, quote, identityMismatch = false) {
|
|
46
|
+
const input = usage.tokens.input;
|
|
47
|
+
const output = usage.tokens.output;
|
|
48
|
+
const applicable = !identityMismatch || quote.price.identityMismatchPricing === 'requested-model';
|
|
49
|
+
const inputKnown = input.source === 'provider' && applicable;
|
|
50
|
+
const outputKnown = inputKnown && output.source === 'provider';
|
|
51
|
+
const inputPriced = quote.price.inputMicroUsdPerMtok !== '0';
|
|
52
|
+
const outputPriced = quote.price.outputMicroUsdPerMtok !== '0';
|
|
53
|
+
const pricedUnknown = (inputPriced && !inputKnown) || (outputPriced && !outputKnown);
|
|
54
|
+
const inputAmount = inputKnown ? ceilRate(input.value, quote.price.inputMicroUsdPerMtok) : 0n;
|
|
55
|
+
const outputAmount = outputKnown ? ceilRate(output.value, quote.price.outputMicroUsdPerMtok) : 0n;
|
|
56
|
+
const computed = inputKnown || outputKnown ? minimum(inputAmount + outputAmount, quote.price) : BigInt(quote.reservedMicroUsd);
|
|
57
|
+
const reserved = BigInt(quote.reservedMicroUsd);
|
|
58
|
+
const amount = pricedUnknown && computed < reserved ? reserved : computed;
|
|
59
|
+
const fullyUnknown = !inputKnown && !outputKnown;
|
|
60
|
+
return { cost: { status: 'estimated', amountMicroUsd: amount.toString(),
|
|
61
|
+
source: fullyUnknown || pricedUnknown ? 'reserved-liability' : 'reported-usage-times-rate',
|
|
62
|
+
priceRevision: quote.price.priceRevision, rounding: 'ceil-micro-usd' },
|
|
63
|
+
pending: pricedUnknown, overrun: amount > reserved };
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=pricing.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pricing.js","sourceRoot":"","sources":["../../src/decision/pricing.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { DecisionRequest } from './request.js';
|
|
2
|
+
import type { DecisionVerdict } from './verdict.js';
|
|
3
|
+
/** Drop whole optional native fields to fit; never truncate the typed verdict. */
|
|
4
|
+
export declare function makeJevProviderRaw(native: unknown, request: DecisionRequest): DecisionVerdict['providerRaw'];
|
|
5
|
+
/** Raw remains optional, bounded and tied to the already validated native evidence. */
|
|
6
|
+
export declare function parseJevProviderRaw(candidate: unknown, native: unknown, request: DecisionRequest): DecisionVerdict['providerRaw'] | null;
|
|
7
|
+
//# sourceMappingURL=raw.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"raw.d.ts","sourceRoot":"","sources":["../../src/decision/raw.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAQ,MAAM,cAAc,CAAC;AAC1D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAOpD,kFAAkF;AAClF,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,eAAe,GAAG,eAAe,CAAC,aAAa,CAAC,CAa5G;AAED,uFAAuF;AACvF,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,eAAe,GAAG,eAAe,CAAC,aAAa,CAAC,GAAG,IAAI,CAkBxI"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { hasOnlyKeys, isRecord, snapshotBoundedJson } from './validation.js';
|
|
2
|
+
const fields = ['noul', 'score', 'choice', 'probabilities', 'confidence'];
|
|
3
|
+
const bytes = (value) => new TextEncoder().encode(JSON.stringify(value)).byteLength;
|
|
4
|
+
const limit = (request) => Math.min(16384, request.raw?.maxBytes ?? 16384);
|
|
5
|
+
/** Drop whole optional native fields to fit; never truncate the typed verdict. */
|
|
6
|
+
export function makeJevProviderRaw(native, request) {
|
|
7
|
+
if (request.raw?.mode !== 'allowlisted' || limit(request) < 2)
|
|
8
|
+
return undefined;
|
|
9
|
+
const snapshot = snapshotBoundedJson(native);
|
|
10
|
+
if (!snapshot.ok || !isRecord(snapshot.value))
|
|
11
|
+
return undefined;
|
|
12
|
+
const data = {};
|
|
13
|
+
let truncated = false;
|
|
14
|
+
for (const field of fields) {
|
|
15
|
+
if (!Object.hasOwn(snapshot.value, field))
|
|
16
|
+
continue;
|
|
17
|
+
const next = { ...data, [field]: snapshot.value[field] };
|
|
18
|
+
if (bytes(next) > limit(request)) {
|
|
19
|
+
truncated = true;
|
|
20
|
+
continue;
|
|
21
|
+
}
|
|
22
|
+
data[field] = snapshot.value[field];
|
|
23
|
+
}
|
|
24
|
+
return { data, bytes: bytes(data), truncated };
|
|
25
|
+
}
|
|
26
|
+
/** Raw remains optional, bounded and tied to the already validated native evidence. */
|
|
27
|
+
export function parseJevProviderRaw(candidate, native, request) {
|
|
28
|
+
const snapshot = snapshotBoundedJson(candidate);
|
|
29
|
+
if (request.raw?.mode !== 'allowlisted' || !snapshot.ok || !isRecord(snapshot.value) || !isRecord(native))
|
|
30
|
+
return null;
|
|
31
|
+
const value = snapshot.value;
|
|
32
|
+
if (!hasOnlyKeys(value, ['data', 'bytes', 'truncated']) || !isRecord(value.data) || !hasOnlyKeys(value.data, fields)
|
|
33
|
+
|| typeof value.truncated !== 'boolean' || value.bytes !== bytes(value.data) || bytes(value.data) > limit(request))
|
|
34
|
+
return null;
|
|
35
|
+
const rawData = value.data;
|
|
36
|
+
for (const [field, data] of Object.entries(rawData)) {
|
|
37
|
+
if (!Object.hasOwn(native, field))
|
|
38
|
+
return null;
|
|
39
|
+
const expected = native[field];
|
|
40
|
+
if (isRecord(data) && isRecord(expected)) {
|
|
41
|
+
if (Object.keys(data).length !== Object.keys(expected).length
|
|
42
|
+
|| !Object.keys(data).every((key) => data[key] === expected[key]))
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
else if (data !== native[field])
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
const omitted = fields.some((field) => Object.hasOwn(native, field) && !Object.hasOwn(rawData, field));
|
|
49
|
+
if (value.truncated !== omitted)
|
|
50
|
+
return null;
|
|
51
|
+
return { data: value.data, bytes: value.bytes, truncated: value.truncated };
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=raw.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"raw.js","sourceRoot":"","sources":["../../src/decision/raw.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import type { DecisionError, DecisionErrorCode } from './errors.js';
|
|
2
|
+
import type { EvaluatorRef, DecisionRequest, MicroUsd } from './request.js';
|
|
3
|
+
import type { DecisionVerdict } from './verdict.js';
|
|
4
|
+
export type TokenCounter = {
|
|
5
|
+
value: number;
|
|
6
|
+
source: 'provider';
|
|
7
|
+
} | {
|
|
8
|
+
value: null;
|
|
9
|
+
source: 'not-reported';
|
|
10
|
+
};
|
|
11
|
+
export type TotalTokenCounter = TokenCounter | {
|
|
12
|
+
value: number;
|
|
13
|
+
source: 'derived-sum';
|
|
14
|
+
};
|
|
15
|
+
export interface DecisionUsage {
|
|
16
|
+
tokens: {
|
|
17
|
+
input: TokenCounter;
|
|
18
|
+
output: TokenCounter;
|
|
19
|
+
total: TotalTokenCounter;
|
|
20
|
+
};
|
|
21
|
+
evaluatorCalls: number | null;
|
|
22
|
+
explanations: number | null;
|
|
23
|
+
}
|
|
24
|
+
export type DecisionCost = {
|
|
25
|
+
status: 'actual';
|
|
26
|
+
amountMicroUsd: MicroUsd;
|
|
27
|
+
source: 'provider';
|
|
28
|
+
priceRevision?: string;
|
|
29
|
+
rounding: 'ceil-micro-usd';
|
|
30
|
+
} | {
|
|
31
|
+
status: 'estimated';
|
|
32
|
+
amountMicroUsd: MicroUsd;
|
|
33
|
+
source: 'reported-usage-times-rate' | 'call-rate' | 'reserved-liability';
|
|
34
|
+
priceRevision: string;
|
|
35
|
+
rounding: 'ceil-micro-usd';
|
|
36
|
+
} | {
|
|
37
|
+
status: 'not-incurred';
|
|
38
|
+
amountMicroUsd: '0';
|
|
39
|
+
source: 'no-dispatch';
|
|
40
|
+
};
|
|
41
|
+
export interface RetentionReceipt {
|
|
42
|
+
status: 'non-zdr' | 'unknown' | 'not-evaluated';
|
|
43
|
+
basis: 'published-policy' | 'none';
|
|
44
|
+
evidenceRefs: readonly string[];
|
|
45
|
+
retentionDays: number | null;
|
|
46
|
+
gap?: 'unknown (source-gap)';
|
|
47
|
+
}
|
|
48
|
+
export interface DecisionReceipt {
|
|
49
|
+
schemaVersion: 1;
|
|
50
|
+
callId: string;
|
|
51
|
+
correlationId: string;
|
|
52
|
+
evaluator: EvaluatorRef | null;
|
|
53
|
+
servedEvaluator: EvaluatorRef | null;
|
|
54
|
+
servedModelId: string | null;
|
|
55
|
+
providerRequestId?: string;
|
|
56
|
+
startedAt: string;
|
|
57
|
+
finishedAt: string;
|
|
58
|
+
latencyMs: number;
|
|
59
|
+
providerLatencyMs?: number;
|
|
60
|
+
/** Durable marker dispatch state; 'unknown' on ambiguous marker failure before provider call. */
|
|
61
|
+
dispatch: 'not-started' | 'started' | 'completed' | 'unknown';
|
|
62
|
+
/** Number of provider invocation attempts (0 if marking failed before provider dispatch). */
|
|
63
|
+
attempts: 0 | 1;
|
|
64
|
+
usage: DecisionUsage;
|
|
65
|
+
cost: DecisionCost;
|
|
66
|
+
retention: RetentionReceipt;
|
|
67
|
+
budget: {
|
|
68
|
+
state: 'not-admitted' | 'released' | 'settled' | 'pending-reconciliation';
|
|
69
|
+
reservedMicroUsd?: MicroUsd;
|
|
70
|
+
overrun: boolean;
|
|
71
|
+
};
|
|
72
|
+
outcome: 'verdict' | 'error';
|
|
73
|
+
errorCode?: DecisionErrorCode;
|
|
74
|
+
}
|
|
75
|
+
export type DecisionResult = {
|
|
76
|
+
kind: 'verdict';
|
|
77
|
+
ok: true;
|
|
78
|
+
verdict: DecisionVerdict;
|
|
79
|
+
receipt: DecisionReceipt;
|
|
80
|
+
} | {
|
|
81
|
+
kind: 'error';
|
|
82
|
+
ok: false;
|
|
83
|
+
error: DecisionError;
|
|
84
|
+
receipt: DecisionReceipt;
|
|
85
|
+
};
|
|
86
|
+
export interface DecisionClient {
|
|
87
|
+
decide(request: DecisionRequest, options?: {
|
|
88
|
+
signal?: AbortSignal;
|
|
89
|
+
}): Promise<DecisionResult>;
|
|
90
|
+
}
|
|
91
|
+
export interface DecisionConnectionFailure {
|
|
92
|
+
kind: 'connection-failure';
|
|
93
|
+
ok: false;
|
|
94
|
+
error: DecisionError & {
|
|
95
|
+
code: 'MESH_UNAVAILABLE' | 'TRANSPORT_FAILED' | 'TIMEOUT' | 'CANCELLED';
|
|
96
|
+
};
|
|
97
|
+
receipt: null;
|
|
98
|
+
usage: DecisionUsage;
|
|
99
|
+
callStatus: 'not-sent' | 'unknown';
|
|
100
|
+
correlationId: string;
|
|
101
|
+
}
|
|
102
|
+
export interface RemoteDecisionClient {
|
|
103
|
+
decide(request: DecisionRequest, options?: {
|
|
104
|
+
signal?: AbortSignal;
|
|
105
|
+
}): Promise<DecisionResult | DecisionConnectionFailure>;
|
|
106
|
+
}
|
|
107
|
+
/** Unknown counters stay null even when no dispatch proves zero evaluator calls. */
|
|
108
|
+
export declare function unreportedDecisionUsage(execution: 'not-dispatched' | 'unknown'): DecisionUsage;
|
|
109
|
+
/** Correlation is metadata, never financial idempotency or caller authority. */
|
|
110
|
+
export declare function resolveDecisionCorrelationId(value: string | undefined, generate?: () => string): string | null;
|
|
111
|
+
/** Each counter has independent provenance; only a safe, known total can be derived. */
|
|
112
|
+
export declare function parseDecisionUsage(candidate: unknown): DecisionUsage | null;
|
|
113
|
+
export declare function normalizeDecisionUsage(reported: {
|
|
114
|
+
inputTokens?: number | null;
|
|
115
|
+
outputTokens?: number | null;
|
|
116
|
+
totalTokens?: number | null;
|
|
117
|
+
evaluatorCalls: number | null;
|
|
118
|
+
explanations: number | null;
|
|
119
|
+
}): DecisionUsage | null;
|
|
120
|
+
//# sourceMappingURL=receipt.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"receipt.d.ts","sourceRoot":"","sources":["../../src/decision/receipt.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { hasOnlyKeys, isCorrelationId, isRecord, snapshotBoundedJson } from './validation.js';
|
|
2
|
+
/** Unknown counters stay null even when no dispatch proves zero evaluator calls. */
|
|
3
|
+
export function unreportedDecisionUsage(execution) {
|
|
4
|
+
return { tokens: { input: { value: null, source: 'not-reported' },
|
|
5
|
+
output: { value: null, source: 'not-reported' }, total: { value: null, source: 'not-reported' } },
|
|
6
|
+
evaluatorCalls: execution === 'not-dispatched' ? 0 : null,
|
|
7
|
+
explanations: execution === 'not-dispatched' ? 0 : null };
|
|
8
|
+
}
|
|
9
|
+
/** Correlation is metadata, never financial idempotency or caller authority. */
|
|
10
|
+
export function resolveDecisionCorrelationId(value, generate = () => globalThis.crypto.randomUUID()) {
|
|
11
|
+
const candidate = value === undefined ? generate() : value;
|
|
12
|
+
return isCorrelationId(candidate) ? candidate : null;
|
|
13
|
+
}
|
|
14
|
+
const isCount = (value) => typeof value === 'number' && Number.isSafeInteger(value) && value >= 0;
|
|
15
|
+
function isCounter(value, total) {
|
|
16
|
+
return isRecord(value) && hasOnlyKeys(value, ['value', 'source'])
|
|
17
|
+
&& (value.source === 'not-reported' ? value.value === null
|
|
18
|
+
: (value.source === 'provider' || (total && value.source === 'derived-sum')) && isCount(value.value));
|
|
19
|
+
}
|
|
20
|
+
/** Each counter has independent provenance; only a safe, known total can be derived. */
|
|
21
|
+
export function parseDecisionUsage(candidate) {
|
|
22
|
+
const snapshot = snapshotBoundedJson(candidate);
|
|
23
|
+
if (!snapshot.ok)
|
|
24
|
+
return null;
|
|
25
|
+
const value = snapshot.value;
|
|
26
|
+
if (!isRecord(value) || !hasOnlyKeys(value, ['tokens', 'evaluatorCalls', 'explanations'])
|
|
27
|
+
|| !isRecord(value.tokens) || !hasOnlyKeys(value.tokens, ['input', 'output', 'total'])
|
|
28
|
+
|| !isCounter(value.tokens.input, false) || !isCounter(value.tokens.output, false)
|
|
29
|
+
|| !isCounter(value.tokens.total, true)
|
|
30
|
+
|| (value.evaluatorCalls !== null && !isCount(value.evaluatorCalls))
|
|
31
|
+
|| (value.explanations !== null && !isCount(value.explanations)))
|
|
32
|
+
return null;
|
|
33
|
+
const usage = value;
|
|
34
|
+
const { input, output, total } = usage.tokens;
|
|
35
|
+
if (total.source === 'derived-sum') {
|
|
36
|
+
if (input.source !== 'provider' || output.source !== 'provider')
|
|
37
|
+
return null;
|
|
38
|
+
const sum = input.value + output.value;
|
|
39
|
+
if (!isCount(sum) || total.value !== sum)
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
return { tokens: { input: { ...input }, output: { ...output }, total: { ...total } },
|
|
43
|
+
evaluatorCalls: usage.evaluatorCalls, explanations: usage.explanations };
|
|
44
|
+
}
|
|
45
|
+
export function normalizeDecisionUsage(reported) {
|
|
46
|
+
const counter = (value) => value == null
|
|
47
|
+
? { value: null, source: 'not-reported' } : { value, source: 'provider' };
|
|
48
|
+
const input = counter(reported.inputTokens);
|
|
49
|
+
const output = counter(reported.outputTokens);
|
|
50
|
+
const total = reported.totalTokens != null
|
|
51
|
+
? { value: reported.totalTokens, source: 'provider' }
|
|
52
|
+
: input.source === 'provider' && output.source === 'provider'
|
|
53
|
+
? { value: input.value + output.value, source: 'derived-sum' }
|
|
54
|
+
: { value: null, source: 'not-reported' };
|
|
55
|
+
return parseDecisionUsage({ tokens: { input, output, total }, evaluatorCalls: reported.evaluatorCalls,
|
|
56
|
+
explanations: reported.explanations });
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=receipt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"receipt.js","sourceRoot":"","sources":["../../src/decision/receipt.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"request-policy.d.ts","sourceRoot":"","sources":["../../src/decision/request-policy.ts"],"names":[],"mappings":"AAEA,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAOvD;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAKnD"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { has, hasOnlyKeys, isMicroUsd, isRecord, DECISION_MAX_RAW_BYTES } from './validation.js';
|
|
2
|
+
export function isRequestPolicy(value) {
|
|
3
|
+
if (!isRecord(value) || !hasOnlyKeys(value, ['budget', 'timeoutMs', 'explanation']))
|
|
4
|
+
return false;
|
|
5
|
+
if (has(value, 'budget') && (!isRecord(value.budget)
|
|
6
|
+
|| !hasOnlyKeys(value.budget, ['maxCostMicroUsd']) || !isMicroUsd(value.budget.maxCostMicroUsd)))
|
|
7
|
+
return false;
|
|
8
|
+
if (has(value, 'timeoutMs') && (typeof value.timeoutMs !== 'number'
|
|
9
|
+
|| !Number.isSafeInteger(value.timeoutMs) || value.timeoutMs < 1 || value.timeoutMs > 60_000))
|
|
10
|
+
return false;
|
|
11
|
+
return !has(value, 'explanation') || ['none', 'if-available', 'required'].some((v) => v === value.explanation);
|
|
12
|
+
}
|
|
13
|
+
export function isRawPolicy(value) {
|
|
14
|
+
return isRecord(value) && hasOnlyKeys(value, ['mode', 'maxBytes'])
|
|
15
|
+
&& (value.mode === 'none' || value.mode === 'allowlisted')
|
|
16
|
+
&& (!has(value, 'maxBytes') || (typeof value.maxBytes === 'number'
|
|
17
|
+
&& Number.isSafeInteger(value.maxBytes) && value.maxBytes >= 0 && value.maxBytes <= DECISION_MAX_RAW_BYTES));
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=request-policy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"request-policy.js","sourceRoot":"","sources":["../../src/decision/request-policy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,WAAW,EAAE,UAAU,EAAE,QAAQ,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AAEjG,MAAM,UAAU,eAAe,CAAC,KAAc;IAC5C,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,CAAC,QAAQ,EAAE,WAAW,EAAE,aAAa,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IAClG,IAAI,GAAG,CAAC,KAAK,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC;WAC/C,CAAC,WAAW,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,iBAAiB,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IACjH,IAAI,GAAG,CAAC,KAAK,EAAE,WAAW,CAAC,IAAI,CAAC,OAAO,KAAK,CAAC,SAAS,KAAK,QAAQ;WAC9D,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,SAAS,CAAC,IAAI,KAAK,CAAC,SAAS,GAAG,CAAC,IAAI,KAAK,CAAC,SAAS,GAAG,MAAM,CAAC;QAAE,OAAO,KAAK,CAAC;IAC9G,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,aAAa,CAAC,IAAI,CAAC,MAAM,EAAE,cAAc,EAAE,UAAU,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,KAAK,CAAC,WAAW,CAAC,CAAC;AACjH,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,KAAc;IACxC,OAAO,QAAQ,CAAC,KAAK,CAAC,IAAI,WAAW,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;WAC7D,CAAC,KAAK,CAAC,IAAI,KAAK,MAAM,IAAI,KAAK,CAAC,IAAI,KAAK,aAAa,CAAC;WACvD,CAAC,CAAC,GAAG,CAAC,KAAK,EAAE,UAAU,CAAC,IAAI,CAAC,OAAO,KAAK,CAAC,QAAQ,KAAK,QAAQ;eAC7D,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,KAAK,CAAC,QAAQ,IAAI,CAAC,IAAI,KAAK,CAAC,QAAQ,IAAI,sBAAsB,CAAC,CAAC,CAAC;AACnH,CAAC"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import type { ProviderId } from '../providers.js';
|
|
2
|
+
export type Json = null | boolean | number | string | readonly Json[] | {
|
|
3
|
+
readonly [key: string]: Json;
|
|
4
|
+
};
|
|
5
|
+
/** Canonical nonnegative integer decimal micro-USD, never floating point. */
|
|
6
|
+
export type MicroUsd = string;
|
|
7
|
+
export interface EvaluatorRef {
|
|
8
|
+
providerId: ProviderId;
|
|
9
|
+
evaluatorId: string;
|
|
10
|
+
revision: string;
|
|
11
|
+
}
|
|
12
|
+
export interface DecisionInputs {
|
|
13
|
+
input?: Json;
|
|
14
|
+
output?: Json;
|
|
15
|
+
context?: readonly Json[];
|
|
16
|
+
reference?: Json;
|
|
17
|
+
state?: Json;
|
|
18
|
+
}
|
|
19
|
+
export type DecisionCriterion = {
|
|
20
|
+
kind: 'binary';
|
|
21
|
+
instructions: string;
|
|
22
|
+
criteria?: {
|
|
23
|
+
true: string;
|
|
24
|
+
false: string;
|
|
25
|
+
};
|
|
26
|
+
} | {
|
|
27
|
+
kind: 'graded';
|
|
28
|
+
instructions: string;
|
|
29
|
+
direction: 'higher-is-better' | 'lower-is-better' | 'unordered';
|
|
30
|
+
levels: readonly {
|
|
31
|
+
label: string;
|
|
32
|
+
description: string;
|
|
33
|
+
}[];
|
|
34
|
+
} | {
|
|
35
|
+
kind: 'choice';
|
|
36
|
+
instructions: string;
|
|
37
|
+
options: readonly {
|
|
38
|
+
id: string;
|
|
39
|
+
description: string;
|
|
40
|
+
}[];
|
|
41
|
+
} | {
|
|
42
|
+
kind: 'registered';
|
|
43
|
+
criteriaId: string;
|
|
44
|
+
revision: string;
|
|
45
|
+
};
|
|
46
|
+
export type DecisionRule = {
|
|
47
|
+
kind: 'provider';
|
|
48
|
+
} | {
|
|
49
|
+
kind: 'threshold';
|
|
50
|
+
field: 'score';
|
|
51
|
+
op: 'gte' | 'lte';
|
|
52
|
+
value: number;
|
|
53
|
+
} | {
|
|
54
|
+
kind: 'labels';
|
|
55
|
+
passing: readonly string[];
|
|
56
|
+
};
|
|
57
|
+
export interface DecisionRequest {
|
|
58
|
+
schemaVersion: 1;
|
|
59
|
+
evaluator: EvaluatorRef;
|
|
60
|
+
inputs: DecisionInputs;
|
|
61
|
+
criterion: DecisionCriterion;
|
|
62
|
+
decision?: DecisionRule;
|
|
63
|
+
policy?: {
|
|
64
|
+
budget?: {
|
|
65
|
+
maxCostMicroUsd: MicroUsd;
|
|
66
|
+
};
|
|
67
|
+
timeoutMs?: number;
|
|
68
|
+
explanation?: 'none' | 'if-available' | 'required';
|
|
69
|
+
};
|
|
70
|
+
raw?: {
|
|
71
|
+
mode: 'none' | 'allowlisted';
|
|
72
|
+
maxBytes?: number;
|
|
73
|
+
};
|
|
74
|
+
correlationId?: string;
|
|
75
|
+
}
|
|
76
|
+
export type DecisionRequestParseResult = {
|
|
77
|
+
ok: true;
|
|
78
|
+
request: DecisionRequest;
|
|
79
|
+
} | {
|
|
80
|
+
ok: false;
|
|
81
|
+
code: 'REQUEST_INVALID' | 'CAPABILITY_UNSUPPORTED' | 'PROVIDER_UNKNOWN';
|
|
82
|
+
};
|
|
83
|
+
/** Pure preflight parsing: capabilities and descriptor revisions remain service-owned. */
|
|
84
|
+
export declare function parseDecisionRequest(value: unknown): DecisionRequestParseResult;
|
|
85
|
+
//# sourceMappingURL=request.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"request.d.ts","sourceRoot":"","sources":["../../src/decision/request.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { isProviderId } from '../providers.js';
|
|
2
|
+
import { isDecisionCriterion, isDecisionRule } from './criterion.js';
|
|
3
|
+
import { isRawPolicy, isRequestPolicy } from './request-policy.js';
|
|
4
|
+
import { has, hasOnlyKeys, isCorrelationId, isRecord, isText, snapshotBoundedJson } from './validation.js';
|
|
5
|
+
/** Pure preflight parsing: capabilities and descriptor revisions remain service-owned. */
|
|
6
|
+
export function parseDecisionRequest(value) {
|
|
7
|
+
const invalid = { ok: false, code: 'REQUEST_INVALID' };
|
|
8
|
+
const snapshot = snapshotBoundedJson(value);
|
|
9
|
+
if (!snapshot.ok)
|
|
10
|
+
return invalid;
|
|
11
|
+
value = snapshot.value;
|
|
12
|
+
if (!isRecord(value))
|
|
13
|
+
return invalid;
|
|
14
|
+
// Unsupported retention policy takes precedence over ordinary extra-property errors.
|
|
15
|
+
if (isRecord(value.policy) && has(value.policy, 'zdr')) {
|
|
16
|
+
return { ok: false, code: 'CAPABILITY_UNSUPPORTED' };
|
|
17
|
+
}
|
|
18
|
+
if (!hasOnlyKeys(value, ['schemaVersion', 'evaluator', 'inputs', 'criterion', 'decision', 'policy', 'raw', 'correlationId'])
|
|
19
|
+
|| value.schemaVersion !== 1 || !isRecord(value.evaluator)
|
|
20
|
+
|| !hasOnlyKeys(value.evaluator, ['providerId', 'evaluatorId', 'revision'])
|
|
21
|
+
|| !isText(value.evaluator.providerId) || !isText(value.evaluator.evaluatorId)
|
|
22
|
+
|| !isText(value.evaluator.revision) || !isRecord(value.inputs)
|
|
23
|
+
|| !hasOnlyKeys(value.inputs, ['input', 'output', 'context', 'reference', 'state'])
|
|
24
|
+
|| (!has(value.inputs, 'output') && !has(value.inputs, 'state'))
|
|
25
|
+
|| (has(value.inputs, 'context') && !Array.isArray(value.inputs.context)))
|
|
26
|
+
return invalid;
|
|
27
|
+
const criterion = value.criterion;
|
|
28
|
+
if (!isDecisionCriterion(criterion))
|
|
29
|
+
return invalid;
|
|
30
|
+
if (has(value, 'decision')) {
|
|
31
|
+
const decision = value.decision;
|
|
32
|
+
if (!isDecisionRule(decision))
|
|
33
|
+
return invalid;
|
|
34
|
+
if (decision.kind === 'labels' && criterion.kind !== 'registered') {
|
|
35
|
+
const labels = criterion.kind === 'choice' ? criterion.options.map((v) => v.id)
|
|
36
|
+
: criterion.kind === 'graded' ? criterion.levels.map((v) => v.label) : [];
|
|
37
|
+
if (!decision.passing.every((label) => labels.includes(label)))
|
|
38
|
+
return invalid;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
if ((has(value, 'policy') && !isRequestPolicy(value.policy))
|
|
42
|
+
|| (has(value, 'raw') && !isRawPolicy(value.raw))
|
|
43
|
+
|| (has(value, 'correlationId') && !isCorrelationId(value.correlationId)))
|
|
44
|
+
return invalid;
|
|
45
|
+
if (!isProviderId(value.evaluator.providerId))
|
|
46
|
+
return { ok: false, code: 'PROVIDER_UNKNOWN' };
|
|
47
|
+
return { ok: true, request: value };
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=request.js.map
|