@oxy.so/contracts 4.5.0 → 4.7.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/agency.js +49 -0
- package/dist/cjs/capabilityInvocation.js +173 -0
- package/dist/cjs/index.js +28 -6
- package/dist/cjs/inference/catalogue.js +55 -1
- package/dist/cjs/inference/decisions.js +245 -0
- package/dist/cjs/inference/request.js +13 -0
- package/dist/cjs/inference/routingPolicy.js +45 -1
- package/dist/cjs/inference/version.js +1 -1
- package/dist/esm/.tsbuildinfo +1 -1
- package/dist/esm/agency.js +49 -0
- package/dist/esm/capabilityInvocation.js +165 -0
- package/dist/esm/index.js +4 -2
- package/dist/esm/inference/catalogue.js +54 -0
- package/dist/esm/inference/decisions.js +239 -0
- package/dist/esm/inference/request.js +13 -0
- package/dist/esm/inference/routingPolicy.js +44 -1
- package/dist/esm/inference/version.js +1 -1
- package/dist/types/.tsbuildinfo +1 -1
- package/dist/types/agency.d.ts +6 -6
- package/dist/types/capabilityInvocation.d.ts +80 -0
- package/dist/types/index.d.ts +7 -3
- package/dist/types/inference/catalogue.d.ts +75 -22
- package/dist/types/inference/decisions.d.ts +1833 -0
- package/dist/types/inference/modelDocumentation.d.ts +16 -16
- package/dist/types/inference/realtime.d.ts +72 -72
- package/dist/types/inference/request.d.ts +520 -26
- package/dist/types/inference/routingPolicy.d.ts +44 -10
- package/dist/types/inference/streamEvents.d.ts +8 -8
- package/dist/types/inference/usage.d.ts +4 -4
- package/dist/types/inference/version.d.ts +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.decisionSuccessSchema = exports.decisionFailureSchema = exports.decisionResultSchema = exports.decisionAnswerSchema = exports.decisionRequestSchema = exports.decisionInputSchema = exports.decisionQuestionSchema = exports.decisionEffortSchema = void 0;
|
|
4
|
+
exports.decisionInputBudget = decisionInputBudget;
|
|
5
|
+
exports.decisionFitsGateway = decisionFitsGateway;
|
|
6
|
+
exports.decisionAnswersMatch = decisionAnswersMatch;
|
|
7
|
+
const zod_1 = require("zod");
|
|
8
|
+
const errors_1 = require("./errors");
|
|
9
|
+
const identifiers_1 = require("./identifiers");
|
|
10
|
+
const money_1 = require("./money");
|
|
11
|
+
const routingPolicy_1 = require("./routingPolicy");
|
|
12
|
+
const usage_1 = require("./usage");
|
|
13
|
+
const probability = zod_1.z.number().finite().min(0).max(1);
|
|
14
|
+
const text = zod_1.z.string().min(1).max(65536);
|
|
15
|
+
const id = zod_1.z.string().min(1).max(128);
|
|
16
|
+
const tolerance = 1e-6;
|
|
17
|
+
exports.decisionEffortSchema = zod_1.z.enum([
|
|
18
|
+
"instant",
|
|
19
|
+
"low",
|
|
20
|
+
"medium",
|
|
21
|
+
"high",
|
|
22
|
+
"xhigh",
|
|
23
|
+
]);
|
|
24
|
+
const common = { id, question: text, criteria: text.optional() };
|
|
25
|
+
exports.decisionQuestionSchema = zod_1.z.discriminatedUnion("kind", [
|
|
26
|
+
zod_1.z
|
|
27
|
+
.object({
|
|
28
|
+
...common,
|
|
29
|
+
kind: zod_1.z.literal("choice"),
|
|
30
|
+
options: zod_1.z.array(text).min(2).max(255),
|
|
31
|
+
})
|
|
32
|
+
.strict(),
|
|
33
|
+
zod_1.z
|
|
34
|
+
.object({
|
|
35
|
+
...common,
|
|
36
|
+
kind: zod_1.z.literal("score"),
|
|
37
|
+
levels: zod_1.z.array(text).min(2).max(10),
|
|
38
|
+
})
|
|
39
|
+
.strict(),
|
|
40
|
+
zod_1.z.object({ ...common, kind: zod_1.z.literal("noul") }).strict(),
|
|
41
|
+
]);
|
|
42
|
+
const payloadFields = {
|
|
43
|
+
state: zod_1.z.string().max(65536),
|
|
44
|
+
instructions: text.optional(),
|
|
45
|
+
questions: zod_1.z.array(exports.decisionQuestionSchema).min(1).max(255),
|
|
46
|
+
effort: exports.decisionEffortSchema.optional(),
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* Conservative serialized input accounting, including escaping and structure.
|
|
50
|
+
* Measures both the normalized payload and the provider's structured-question
|
|
51
|
+
* representation. Common instructions repeat per question there. A 255-byte
|
|
52
|
+
* model identity and 4096-byte gateway-policy allowance bound adapter metadata.
|
|
53
|
+
* Kaana must also check its final serialized body before sending it.
|
|
54
|
+
*/
|
|
55
|
+
function decisionInputBudget(payload) {
|
|
56
|
+
const bytes = (value) => new TextEncoder().encode(JSON.stringify(value).replace(/[<>&\u2028\u2029]/g, (char) => `\\u${char.charCodeAt(0).toString(16).padStart(4, "0")}`)).length;
|
|
57
|
+
const model = "x".repeat(255);
|
|
58
|
+
const measure = (questions) => {
|
|
59
|
+
const wireQuestions = Object.fromEntries(questions.map((q) => [q.id, {
|
|
60
|
+
type: q.kind,
|
|
61
|
+
instructions: {
|
|
62
|
+
question: q.question,
|
|
63
|
+
...(payload.instructions === undefined ? {} : { instructions: payload.instructions }),
|
|
64
|
+
...(q.criteria === undefined ? {} : { criteria: q.criteria }),
|
|
65
|
+
},
|
|
66
|
+
...(q.kind === "choice" ? { criteria: Object.fromEntries(q.options.map((label) => [label, null])) } :
|
|
67
|
+
q.kind === "score" ? { criteria: q.levels } : {}),
|
|
68
|
+
}]));
|
|
69
|
+
return Math.max(bytes({ ...payload, model, questions }), bytes({ model, state: payload.state, questions: wireQuestions, ...(payload.effort === undefined ? {} : { effort: payload.effort }) }));
|
|
70
|
+
};
|
|
71
|
+
const total = measure(payload.questions);
|
|
72
|
+
return { total, context: Math.max(...payload.questions.map((q) => measure([q]))), gateway: total + 4096 };
|
|
73
|
+
}
|
|
74
|
+
/** OpenRouter's TOTAL limit is separate from direct state-plus-longest context. */
|
|
75
|
+
function decisionFitsGateway(payload) {
|
|
76
|
+
return decisionInputBudget(payload).gateway <= 32000;
|
|
77
|
+
}
|
|
78
|
+
function validateInput(payload, ctx) {
|
|
79
|
+
if (new Set(payload.questions.map((q) => q.id)).size !==
|
|
80
|
+
payload.questions.length)
|
|
81
|
+
ctx.addIssue({
|
|
82
|
+
code: "custom",
|
|
83
|
+
path: ["questions"],
|
|
84
|
+
message: "Question IDs must be unique.",
|
|
85
|
+
});
|
|
86
|
+
for (const [index, question] of payload.questions.entries()) {
|
|
87
|
+
const labels = question.kind === "choice"
|
|
88
|
+
? question.options
|
|
89
|
+
: question.kind === "score"
|
|
90
|
+
? question.levels
|
|
91
|
+
: [];
|
|
92
|
+
if (new Set(labels).size !== labels.length)
|
|
93
|
+
ctx.addIssue({
|
|
94
|
+
code: "custom",
|
|
95
|
+
path: ["questions", index],
|
|
96
|
+
message: "Options and levels must be unique.",
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
const budget = decisionInputBudget(payload);
|
|
100
|
+
if (budget.total > 64000 || budget.context > 32000)
|
|
101
|
+
ctx.addIssue({
|
|
102
|
+
code: "custom",
|
|
103
|
+
path: ["state"],
|
|
104
|
+
message: "Decisions exceed the serialized 64000-byte total or 32000-byte per-question context budget.",
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
exports.decisionInputSchema = zod_1.z
|
|
108
|
+
.object(payloadFields)
|
|
109
|
+
.strict()
|
|
110
|
+
.superRefine(validateInput);
|
|
111
|
+
exports.decisionRequestSchema = zod_1.z
|
|
112
|
+
.object({
|
|
113
|
+
model: identifiers_1.modelReferenceSchema.refine((model) => model.includes("@"), "Decisions require a revision-pinned model."),
|
|
114
|
+
...payloadFields,
|
|
115
|
+
})
|
|
116
|
+
.strict()
|
|
117
|
+
.superRefine(validateInput);
|
|
118
|
+
exports.decisionAnswerSchema = zod_1.z
|
|
119
|
+
.discriminatedUnion("kind", [
|
|
120
|
+
zod_1.z
|
|
121
|
+
.object({
|
|
122
|
+
id,
|
|
123
|
+
kind: zod_1.z.literal("choice"),
|
|
124
|
+
/** Actual provider-selected option. Never reconstructed from probabilities. */
|
|
125
|
+
reply: text,
|
|
126
|
+
/** Provider-returned confidence, not a correctness probability. */
|
|
127
|
+
confidence: probability,
|
|
128
|
+
probabilities: zod_1.z.array(probability).min(2).max(255),
|
|
129
|
+
})
|
|
130
|
+
.strict(),
|
|
131
|
+
zod_1.z
|
|
132
|
+
.object({
|
|
133
|
+
id,
|
|
134
|
+
kind: zod_1.z.literal("score"),
|
|
135
|
+
/** Actual provider score. Kept separate from the validated expected index. */
|
|
136
|
+
reply: zod_1.z.number().finite().min(0).max(9),
|
|
137
|
+
confidence: probability,
|
|
138
|
+
mean: zod_1.z.number().finite().min(0).max(9),
|
|
139
|
+
distribution: zod_1.z.array(probability).min(2).max(10),
|
|
140
|
+
})
|
|
141
|
+
.strict(),
|
|
142
|
+
zod_1.z.object({ id, kind: zod_1.z.literal("noul"), probability }).strict(),
|
|
143
|
+
])
|
|
144
|
+
.superRefine((answer, ctx) => {
|
|
145
|
+
if (answer.kind === "noul")
|
|
146
|
+
return;
|
|
147
|
+
if (answer.kind === "score" && Math.abs(answer.reply - answer.mean) > tolerance) {
|
|
148
|
+
ctx.addIssue({ code: "custom", path: ["reply"], message: "Provider score must match the expected level index." });
|
|
149
|
+
}
|
|
150
|
+
const distribution = answer.kind === "choice" ? answer.probabilities : answer.distribution;
|
|
151
|
+
if (Math.abs(distribution.reduce((sum, value) => sum + value, 0) - 1) >
|
|
152
|
+
tolerance)
|
|
153
|
+
ctx.addIssue({
|
|
154
|
+
code: "custom",
|
|
155
|
+
message: "Probabilities must sum to one.",
|
|
156
|
+
});
|
|
157
|
+
if (answer.kind === "score" &&
|
|
158
|
+
Math.abs(distribution.reduce((sum, value, index) => sum + index * value, 0) -
|
|
159
|
+
answer.mean) > tolerance)
|
|
160
|
+
ctx.addIssue({
|
|
161
|
+
code: "custom",
|
|
162
|
+
path: ["mean"],
|
|
163
|
+
message: "Mean must equal the expected zero-based level index.",
|
|
164
|
+
});
|
|
165
|
+
});
|
|
166
|
+
const resultFields = {
|
|
167
|
+
schemaVersion: zod_1.z.literal(1),
|
|
168
|
+
requestId: identifiers_1.requestIdSchema,
|
|
169
|
+
model: identifiers_1.modelReferenceSchema.refine((model) => model.includes("@"), "Decisions require an immutable model revision."),
|
|
170
|
+
data: zod_1.z.array(exports.decisionAnswerSchema).min(1).max(255),
|
|
171
|
+
};
|
|
172
|
+
function uniqueAnswers(result, ctx) {
|
|
173
|
+
if (new Set(result.data.map((answer) => answer.id)).size !== result.data.length)
|
|
174
|
+
ctx.addIssue({
|
|
175
|
+
code: "custom",
|
|
176
|
+
path: ["data"],
|
|
177
|
+
message: "Answer IDs must be unique.",
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
exports.decisionResultSchema = zod_1.z
|
|
181
|
+
.object({ ...resultFields, usage: usage_1.normalizedUsageReportSchema })
|
|
182
|
+
.strict()
|
|
183
|
+
.superRefine(uniqueAnswers)
|
|
184
|
+
.superRefine((result, ctx) => {
|
|
185
|
+
if (result.usage.requestId !== result.requestId ||
|
|
186
|
+
result.usage.resolvedModelReference !== result.model ||
|
|
187
|
+
result.usage.outcome !== "completed") {
|
|
188
|
+
ctx.addIssue({
|
|
189
|
+
code: "custom",
|
|
190
|
+
path: ["usage"],
|
|
191
|
+
message: "Decision usage must describe this completed request and immutable model.",
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
});
|
|
195
|
+
/**
|
|
196
|
+
* Kaana's typed decisions failure. `usage` is present only when the provider
|
|
197
|
+
* measured something before failing; its absence means nothing was measured,
|
|
198
|
+
* never that the cost was zero. A failure carrying usage did execute.
|
|
199
|
+
*/
|
|
200
|
+
exports.decisionFailureSchema = zod_1.z
|
|
201
|
+
.object({
|
|
202
|
+
schemaVersion: zod_1.z.literal(1),
|
|
203
|
+
requestId: identifiers_1.requestIdSchema,
|
|
204
|
+
error: errors_1.inferenceErrorSchema,
|
|
205
|
+
usage: usage_1.normalizedUsageReportSchema.optional(),
|
|
206
|
+
})
|
|
207
|
+
.strict()
|
|
208
|
+
.superRefine((failure, ctx) => {
|
|
209
|
+
if (failure.error.requestId !== failure.requestId) {
|
|
210
|
+
ctx.addIssue({ code: "custom", path: ["error", "requestId"], message: "The error must answer this request." });
|
|
211
|
+
}
|
|
212
|
+
if (failure.usage !== undefined &&
|
|
213
|
+
(failure.usage.requestId !== failure.requestId || failure.usage.outcome === "completed")) {
|
|
214
|
+
ctx.addIssue({ code: "custom", path: ["usage"], message: "Failure usage must describe this request and an incomplete outcome." });
|
|
215
|
+
}
|
|
216
|
+
});
|
|
217
|
+
exports.decisionSuccessSchema = zod_1.z
|
|
218
|
+
.object({
|
|
219
|
+
...resultFields,
|
|
220
|
+
usage: zod_1.z.array(money_1.usageQuantitySchema),
|
|
221
|
+
routingPolicy: routingPolicy_1.routingPolicyReferenceSchema,
|
|
222
|
+
})
|
|
223
|
+
.strict()
|
|
224
|
+
.superRefine(uniqueAnswers);
|
|
225
|
+
/** Bind output to the exact request. Provider order is not semantic. */
|
|
226
|
+
function decisionAnswersMatch(input, answers) {
|
|
227
|
+
if (answers.length !== input.questions.length ||
|
|
228
|
+
new Set(answers.map((a) => a.id)).size !== answers.length)
|
|
229
|
+
return false;
|
|
230
|
+
return input.questions.every((question) => {
|
|
231
|
+
const answer = answers.find((candidate) => candidate.id === question.id);
|
|
232
|
+
if (!answer ||
|
|
233
|
+
!exports.decisionAnswerSchema.safeParse(answer).success ||
|
|
234
|
+
answer.kind !== question.kind)
|
|
235
|
+
return false;
|
|
236
|
+
if (question.kind === "choice" && answer.kind === "choice") {
|
|
237
|
+
const index = question.options.indexOf(answer.reply);
|
|
238
|
+
return question.options.length === answer.probabilities.length && index >= 0 &&
|
|
239
|
+
answer.probabilities[index] + tolerance >= Math.max(...answer.probabilities);
|
|
240
|
+
}
|
|
241
|
+
if (question.kind === "score" && answer.kind === "score")
|
|
242
|
+
return question.levels.length === answer.distribution.length;
|
|
243
|
+
return question.kind === "noul";
|
|
244
|
+
});
|
|
245
|
+
}
|
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
*/
|
|
27
27
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
28
28
|
exports.inferenceRequestSchema = exports.inferenceAudioOutputParametersSchema = exports.inferenceSpeechParametersSchema = exports.clientRequestMetadataSchema = exports.inferenceReasoningSchema = exports.responseFormatSchema = exports.toolChoiceSchema = exports.toolDefinitionSchema = exports.samplingParametersSchema = exports.inferenceInputSchema = exports.inferenceMessageSchema = exports.inferenceMessageRoleSchema = exports.inferenceToolCallSchema = exports.inferenceContentPartSchema = exports.inferenceContentSourceSchema = void 0;
|
|
29
|
+
const decisions_1 = require("./decisions");
|
|
29
30
|
const zod_1 = require("zod");
|
|
30
31
|
const attribution_1 = require("./attribution");
|
|
31
32
|
const catalogue_1 = require("./catalogue");
|
|
@@ -198,6 +199,7 @@ exports.inferenceMessageSchema = zod_1.z
|
|
|
198
199
|
* that both metering and provider translation depend on.
|
|
199
200
|
*/
|
|
200
201
|
exports.inferenceInputSchema = zod_1.z.discriminatedUnion("format", [
|
|
202
|
+
zod_1.z.object({ format: zod_1.z.literal("decisions"), decisions: decisions_1.decisionInputSchema }).strict(),
|
|
201
203
|
zod_1.z
|
|
202
204
|
.object({
|
|
203
205
|
format: zod_1.z.literal("messages"),
|
|
@@ -406,6 +408,17 @@ exports.inferenceRequestSchema = zod_1.z
|
|
|
406
408
|
authorizedRoutes: zod_1.z.array(routingPolicy_1.authorizedRouteSchema).min(1).optional(),
|
|
407
409
|
})
|
|
408
410
|
.superRefine((request, ctx) => {
|
|
411
|
+
if (request.input.format === "decisions" || request.client.apiFormat === "decisions") {
|
|
412
|
+
const exactModel = request.target.kind === "model" && request.target.modelReference.includes('@');
|
|
413
|
+
const foreignRoute = request.authorizedRoutes?.some((route) => request.target.kind !== "model" || route.modelReference !== request.target.modelReference || route.substitution !== "same_model");
|
|
414
|
+
if (request.input.format !== "decisions" || request.client.apiFormat !== "decisions" ||
|
|
415
|
+
request.modality !== "text" || request.stream || !exactModel || foreignRoute ||
|
|
416
|
+
request.maxOutputTokens !== undefined || Object.keys(request.sampling).length > 0 ||
|
|
417
|
+
request.tools.length > 0 || request.toolChoice !== undefined || request.responseFormat !== undefined ||
|
|
418
|
+
request.reasoning !== undefined || request.speech !== undefined || request.audioOutput !== undefined) {
|
|
419
|
+
ctx.addIssue({ code: zod_1.z.ZodIssueCode.custom, path: ["input"], message: "Decisions require exact-model typed nonstreaming input without generation controls or model substitution." });
|
|
420
|
+
}
|
|
421
|
+
}
|
|
409
422
|
const isSpeech = request.client.apiFormat === "audio_speech";
|
|
410
423
|
if (isSpeech && request.speech !== undefined && (request.modality !== "audio" || request.input.format !== "text" || request.stream)) {
|
|
411
424
|
ctx.addIssue({ code: zod_1.z.ZodIssueCode.custom, path: ["speech"], message: "speech requires audio modality, text input, parameters and non-streaming output" });
|
|
@@ -34,6 +34,7 @@
|
|
|
34
34
|
*/
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.authorizedRouteSchema = exports.routingPolicyReferenceSchema = exports.routingPolicySchema = exports.routingFallbackPolicySchema = exports.routingPolicyScopeSchema = exports.routingTargetSchema = void 0;
|
|
37
|
+
exports.effectiveSameModelDeployment = effectiveSameModelDeployment;
|
|
37
38
|
const zod_1 = require("zod");
|
|
38
39
|
const identifiers_1 = require("./identifiers");
|
|
39
40
|
const providerConnection_1 = require("./providerConnection");
|
|
@@ -88,10 +89,26 @@ exports.routingPolicyScopeSchema = zod_1.z.discriminatedUnion("kind", [
|
|
|
88
89
|
exports.routingFallbackPolicySchema = zod_1.z
|
|
89
90
|
.object({
|
|
90
91
|
disabled: zod_1.z.boolean(),
|
|
91
|
-
|
|
92
|
+
/**
|
|
93
|
+
* Same-model deployment failover. OPTIONAL since contract set 3.4.0, and
|
|
94
|
+
* absent means ON unless `disabled` is set: serving the same weights from
|
|
95
|
+
* another deployment of the same revision is an availability decision, not
|
|
96
|
+
* a substitution. A policy opts out with an explicit `false` (or
|
|
97
|
+
* `disabled: true`). See `effectiveSameModelDeployment`.
|
|
98
|
+
*/
|
|
99
|
+
sameModelDeployment: zod_1.z.boolean().optional(),
|
|
92
100
|
authorizedCrossModel: zod_1.z.array(identifiers_1.modelReferenceSchema).default([]),
|
|
93
101
|
})
|
|
94
102
|
.strict();
|
|
103
|
+
/**
|
|
104
|
+
* Whether a fallback block authorizes same-model deployment failover: an
|
|
105
|
+
* explicit `sameModelDeployment` wins; absent means on unless `disabled`.
|
|
106
|
+
*/
|
|
107
|
+
function effectiveSameModelDeployment(fallback) {
|
|
108
|
+
if (fallback.disabled)
|
|
109
|
+
return false;
|
|
110
|
+
return fallback.sameModelDeployment ?? true;
|
|
111
|
+
}
|
|
95
112
|
/**
|
|
96
113
|
* A versioned routing policy.
|
|
97
114
|
*
|
|
@@ -131,6 +148,14 @@ exports.routingPolicySchema = zod_1.z
|
|
|
131
148
|
allowedLicenseIds: zod_1.z.array(zod_1.z.string().min(1).max(128)).default([]),
|
|
132
149
|
requireCommercialUseRights: zod_1.z.boolean(),
|
|
133
150
|
fallback: exports.routingFallbackPolicySchema,
|
|
151
|
+
/**
|
|
152
|
+
* The routing profiles (power levels) this scope may target, by exact id
|
|
153
|
+
* (contract set 3.4.0). Empty means no restriction. A request naming a
|
|
154
|
+
* profile outside a non-empty list is refused with `policy_violation`, and
|
|
155
|
+
* `auto` only climbs to levels on the list. Concrete model targets are
|
|
156
|
+
* governed by the other controls, not by this list.
|
|
157
|
+
*/
|
|
158
|
+
allowedRoutingProfileIds: zod_1.z.array(identifiers_1.routingProfileIdSchema).default([]),
|
|
134
159
|
/** Whether the customer's own provider credentials may or must be used. */
|
|
135
160
|
byokPreference: zod_1.z.enum(["disabled", "prefer", "require"]),
|
|
136
161
|
/** Enterprise reserved capacity rather than shared endpoints. */
|
|
@@ -210,6 +235,25 @@ exports.routingPolicySchema = zod_1.z
|
|
|
210
235
|
}
|
|
211
236
|
}
|
|
212
237
|
}
|
|
238
|
+
const allowedProfiles = policy.allowedRoutingProfileIds;
|
|
239
|
+
if (new Set(allowedProfiles).size !== allowedProfiles.length) {
|
|
240
|
+
ctx.addIssue({
|
|
241
|
+
code: zod_1.z.ZodIssueCode.custom,
|
|
242
|
+
path: ["allowedRoutingProfileIds"],
|
|
243
|
+
message: "each routing profile is allowed at most once",
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
// A default the policy itself forbids would refuse every request that
|
|
247
|
+
// names no model — a policy that cannot serve its own default.
|
|
248
|
+
if (allowedProfiles.length > 0 &&
|
|
249
|
+
policy.defaultTarget?.kind === "routing_profile_id" &&
|
|
250
|
+
!allowedProfiles.includes(policy.defaultTarget.routingProfileId)) {
|
|
251
|
+
ctx.addIssue({
|
|
252
|
+
code: zod_1.z.ZodIssueCode.custom,
|
|
253
|
+
path: ["defaultTarget", "routingProfileId"],
|
|
254
|
+
message: "the default routing profile must be one of allowedRoutingProfileIds",
|
|
255
|
+
});
|
|
256
|
+
}
|
|
213
257
|
});
|
|
214
258
|
/**
|
|
215
259
|
* The reference a request records: which policy, at which of the customer's own
|
|
@@ -102,4 +102,4 @@ exports.INFERENCE_CONTRACT_VERSION = void 0;
|
|
|
102
102
|
* change to, say, the catalogue reject every in-flight inference request; the
|
|
103
103
|
* per-shape `schemaVersion` is what a message is validated against.
|
|
104
104
|
*/
|
|
105
|
-
exports.INFERENCE_CONTRACT_VERSION = '3.
|
|
105
|
+
exports.INFERENCE_CONTRACT_VERSION = '3.5.0';
|