@oxy.so/contracts 4.7.0 → 4.8.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/dist/cjs/.tsbuildinfo +1 -1
- package/dist/cjs/index.js +9 -1
- package/dist/cjs/inference/catalogue.js +5 -2
- package/dist/cjs/inference/request.js +33 -1
- package/dist/cjs/inference/scopedExecution.js +87 -0
- package/dist/esm/.tsbuildinfo +1 -1
- package/dist/esm/index.js +2 -0
- package/dist/esm/inference/catalogue.js +3 -0
- package/dist/esm/inference/request.js +32 -0
- package/dist/esm/inference/scopedExecution.js +83 -0
- package/dist/types/.tsbuildinfo +1 -1
- package/dist/types/index.d.ts +4 -0
- package/dist/types/inference/aliaModelRelease.d.ts +86 -86
- package/dist/types/inference/catalogue.d.ts +326 -136
- package/dist/types/inference/modelDocumentation.d.ts +234 -234
- package/dist/types/inference/realtime.d.ts +798 -798
- package/dist/types/inference/request.d.ts +2697 -424
- package/dist/types/inference/routingPolicy.d.ts +16 -16
- package/dist/types/inference/scopedExecution.d.ts +202 -0
- package/package.json +1 -1
package/dist/esm/index.js
CHANGED
|
@@ -184,3 +184,5 @@ export * from './notifications.js';
|
|
|
184
184
|
export * from './email/messages.js';
|
|
185
185
|
export * from './stickers.js';
|
|
186
186
|
export { decisionEffortSchema, decisionQuestionSchema, decisionInputSchema, decisionRequestSchema, decisionAnswerSchema, decisionResultSchema, decisionSuccessSchema, decisionFailureSchema, decisionInputBudget, decisionFitsGateway, decisionAnswersMatch, } from './inference/decisions.js';
|
|
187
|
+
export { SCOPED_EXECUTION_CONTRACT_VERSION, SCOPED_REQUEST_ENVELOPE_VERSION, scopedExecutionAudienceSchema, scopedExecutionSchema, canonicalScopedExecutionJson } from './inference/scopedExecution.js';
|
|
188
|
+
export { scopedInferenceRequestSchema } from './inference/request.js';
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { scopedExecutionAudienceSchema } from "./scopedExecution.js";
|
|
1
2
|
/**
|
|
2
3
|
* The canonical model catalogue.
|
|
3
4
|
*
|
|
@@ -488,6 +489,8 @@ export const modelDeploymentSchema = z
|
|
|
488
489
|
/** See `version.ts`: exchanged with the data plane on its own. */
|
|
489
490
|
schemaVersion: z.literal(2),
|
|
490
491
|
deploymentId: deploymentIdSchema,
|
|
492
|
+
/** Restrictive audience; never an eligibility approval. */
|
|
493
|
+
scopedExecution: scopedExecutionAudienceSchema.optional(),
|
|
491
494
|
provider: inferenceProviderSlugSchema,
|
|
492
495
|
/** Always revision-pinned: a deployment serves specific weights. */
|
|
493
496
|
modelReference: modelReferenceSchema,
|
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
*/
|
|
26
26
|
import { decisionInputSchema } from './decisions.js';
|
|
27
27
|
import { z } from "zod";
|
|
28
|
+
import { scopedExecutionSchema, SCOPED_REQUEST_ENVELOPE_VERSION } from "./scopedExecution.js";
|
|
28
29
|
import { inferenceAttributionSchema } from "./attribution.js";
|
|
29
30
|
import { inferenceApiFormatSchema, inferenceModalitySchema, reasoningEffortSchema, } from "./catalogue.js";
|
|
30
31
|
import { idempotencyKeySchema, inferenceTimestampSchema } from "./identifiers.js";
|
|
@@ -351,6 +352,8 @@ export const inferenceRequestSchema = z
|
|
|
351
352
|
.object({
|
|
352
353
|
/** See `version.ts`: this is the Oxy→data-plane request envelope. */
|
|
353
354
|
schemaVersion: z.literal(2),
|
|
355
|
+
/** Recognized so v2 refuses rather than silently stripping a restriction. */
|
|
356
|
+
scopedExecution: scopedExecutionSchema.optional(),
|
|
354
357
|
attribution: inferenceAttributionSchema,
|
|
355
358
|
target: routingTargetSchema,
|
|
356
359
|
modality: inferenceModalitySchema,
|
|
@@ -405,6 +408,8 @@ export const inferenceRequestSchema = z
|
|
|
405
408
|
authorizedRoutes: z.array(authorizedRouteSchema).min(1).optional(),
|
|
406
409
|
})
|
|
407
410
|
.superRefine((request, ctx) => {
|
|
411
|
+
if (request.scopedExecution !== undefined)
|
|
412
|
+
ctx.addIssue({ code: z.ZodIssueCode.custom, path: ["scopedExecution"], message: "Scoped execution requires envelope v3." });
|
|
408
413
|
if (request.input.format === "decisions" || request.client.apiFormat === "decisions") {
|
|
409
414
|
const exactModel = request.target.kind === "model" && request.target.modelReference.includes('@');
|
|
410
415
|
const foreignRoute = request.authorizedRoutes?.some((route) => request.target.kind !== "model" || route.modelReference !== request.target.modelReference || route.substitution !== "same_model");
|
|
@@ -534,3 +539,30 @@ export const inferenceRequestSchema = z
|
|
|
534
539
|
});
|
|
535
540
|
}
|
|
536
541
|
});
|
|
542
|
+
/** Explicit restrictive generation: old v2 receivers reject this version whole. */
|
|
543
|
+
export const scopedInferenceRequestSchema = inferenceRequestSchema.innerType()
|
|
544
|
+
.extend({ schemaVersion: z.literal(SCOPED_REQUEST_ENVELOPE_VERSION), scopedExecution: scopedExecutionSchema })
|
|
545
|
+
.superRefine((request, ctx) => {
|
|
546
|
+
const { scopedExecution: scope, ...base } = request;
|
|
547
|
+
const legacy = inferenceRequestSchema.safeParse({ ...base, schemaVersion: 2 });
|
|
548
|
+
if (!legacy.success)
|
|
549
|
+
for (const issue of legacy.error.issues)
|
|
550
|
+
ctx.addIssue(issue);
|
|
551
|
+
const principal = request.attribution.principal;
|
|
552
|
+
const route = request.authorizedRoutes?.[0];
|
|
553
|
+
if (request.input.format !== "decisions" || request.client.apiFormat !== "decisions" ||
|
|
554
|
+
scope.requestId !== request.attribution.requestId ||
|
|
555
|
+
scope.idempotencyKey !== request.idempotencyKey ||
|
|
556
|
+
scope.principal.accountId !== principal.billing.accountId ||
|
|
557
|
+
scope.principal.applicationId !== principal.applicationId ||
|
|
558
|
+
scope.principal.credentialId !== principal.credentialId ||
|
|
559
|
+
scope.principal.environment !== principal.environment ||
|
|
560
|
+
scope.policy.routingPolicyId !== request.routingPolicy.routingPolicyId ||
|
|
561
|
+
scope.policy.policyVersion !== request.routingPolicy.policyVersion ||
|
|
562
|
+
request.authorizedRoutes?.length !== 1 || route?.customerProviderCredential !== undefined ||
|
|
563
|
+
route?.deploymentId !== scope.deploymentId || route?.provider !== scope.provider ||
|
|
564
|
+
route?.modelReference !== scope.modelReference ||
|
|
565
|
+
request.target.kind !== "model" || request.target.modelReference !== scope.modelReference) {
|
|
566
|
+
ctx.addIssue({ code: z.ZodIssueCode.custom, path: ["scopedExecution"], message: "Scoped execution must restrict the exact attributed decisions request and one platform route." });
|
|
567
|
+
}
|
|
568
|
+
});
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { deploymentIdSchema, idempotencyKeySchema, inferenceEnvironmentSchema, inferenceProviderSlugSchema, modelReferenceSchema, requestIdSchema, } from "./identifiers.js";
|
|
3
|
+
import { exactDecimalSchema } from "./money.js";
|
|
4
|
+
/** Explicit extension negotiation; never replaces the legacy 3.5 handshake. */
|
|
5
|
+
export const SCOPED_EXECUTION_CONTRACT_VERSION = "3.6.0";
|
|
6
|
+
/** Scoped only; normal envelope v2 and metadata 3.5 remain unchanged. */
|
|
7
|
+
export const SCOPED_REQUEST_ENVELOPE_VERSION = 3;
|
|
8
|
+
const identity = z.string().min(1).max(256);
|
|
9
|
+
const sha256 = z.string().regex(/^[0-9a-f]{64}$/);
|
|
10
|
+
const maxCost = exactDecimalSchema.refine((value) => {
|
|
11
|
+
if (!exactDecimalSchema.safeParse(value).success)
|
|
12
|
+
return false;
|
|
13
|
+
const [whole, fraction = ""] = value.split(".");
|
|
14
|
+
const units = BigInt(whole) * 1000000000000n + BigInt(fraction.padEnd(12, "0"));
|
|
15
|
+
return units > 0n && units <= 10000000000n;
|
|
16
|
+
}, "scoped cost must be positive and at most 0.01 USD");
|
|
17
|
+
/** Restriction only: none of these identities grants catalogue eligibility. */
|
|
18
|
+
export const scopedExecutionAudienceSchema = z
|
|
19
|
+
.object({
|
|
20
|
+
permitId: identity,
|
|
21
|
+
idempotencyKey: idempotencyKeySchema,
|
|
22
|
+
fixtureSha256: sha256,
|
|
23
|
+
expiresAt: z.string().datetime(),
|
|
24
|
+
principal: z
|
|
25
|
+
.object({
|
|
26
|
+
accountId: identity,
|
|
27
|
+
applicationId: identity,
|
|
28
|
+
credentialId: identity,
|
|
29
|
+
environment: inferenceEnvironmentSchema,
|
|
30
|
+
})
|
|
31
|
+
.strict(),
|
|
32
|
+
policy: z
|
|
33
|
+
.object({
|
|
34
|
+
routingPolicyId: z.string().min(1).max(128),
|
|
35
|
+
policyVersion: z.number().int().positive().safe(),
|
|
36
|
+
})
|
|
37
|
+
.strict(),
|
|
38
|
+
deploymentId: deploymentIdSchema,
|
|
39
|
+
provider: inferenceProviderSlugSchema,
|
|
40
|
+
keyId: identity,
|
|
41
|
+
modelReference: modelReferenceSchema.refine((value) => value.includes("@"), "must pin a revision"),
|
|
42
|
+
upstreamModelId: identity,
|
|
43
|
+
priceVersionId: identity,
|
|
44
|
+
providerRateCardVersionId: identity,
|
|
45
|
+
providerSourceVersion: identity,
|
|
46
|
+
maxCostUsd: maxCost,
|
|
47
|
+
})
|
|
48
|
+
.strict();
|
|
49
|
+
export const scopedExecutionSchema = scopedExecutionAudienceSchema
|
|
50
|
+
.extend({
|
|
51
|
+
requestId: requestIdSchema,
|
|
52
|
+
snapshotId: identity,
|
|
53
|
+
catalogueEvidenceHash: sha256,
|
|
54
|
+
})
|
|
55
|
+
.strict();
|
|
56
|
+
/**
|
|
57
|
+
* Canonical JSON wire bytes: recursive UTF-16 key order, JSON string/number
|
|
58
|
+
* encoding, arrays in order, no whitespace. Hash the whole signed input, not a
|
|
59
|
+
* reparsed/defaulted decision. Reject non-JSON values rather than dropping them.
|
|
60
|
+
*/
|
|
61
|
+
export function canonicalScopedExecutionJson(value) {
|
|
62
|
+
if (value === null || typeof value === "string" || typeof value === "boolean")
|
|
63
|
+
return JSON.stringify(value);
|
|
64
|
+
if (typeof value === "number" && Number.isFinite(value))
|
|
65
|
+
return JSON.stringify(value);
|
|
66
|
+
if (Array.isArray(value)) {
|
|
67
|
+
const entries = Array.from(value, (entry, index) => {
|
|
68
|
+
if (!(index in value))
|
|
69
|
+
throw new Error("Scoped execution requires dense JSON arrays.");
|
|
70
|
+
return canonicalScopedExecutionJson(entry);
|
|
71
|
+
});
|
|
72
|
+
return `[${entries.join(",")}]`;
|
|
73
|
+
}
|
|
74
|
+
if (typeof value === "object" &&
|
|
75
|
+
value !== null &&
|
|
76
|
+
Object.getPrototypeOf(value) === Object.prototype) {
|
|
77
|
+
const entries = Object.keys(value)
|
|
78
|
+
.sort()
|
|
79
|
+
.map((key) => `${JSON.stringify(key)}:${canonicalScopedExecutionJson(value[key])}`);
|
|
80
|
+
return `{${entries.join(",")}}`;
|
|
81
|
+
}
|
|
82
|
+
throw new Error("Scoped execution requires JSON wire values.");
|
|
83
|
+
}
|