@velum-labs/routekit-gateway 1.0.6 → 1.0.8
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/providers/anthropic-codec.js +127 -4
- package/dist/providers/bedrock-source.d.ts +1 -1
- package/dist/providers/bedrock-source.js +0 -2
- package/dist/test/bedrock-source.test.js +12 -7
- package/dist/test/chat.test.js +1 -1
- package/dist/test/provider-validation-anthropic.test.js +171 -0
- package/package.json +7 -7
|
@@ -135,6 +135,114 @@ function anthropicToolChoice(choice, parallelToolCalls) {
|
|
|
135
135
|
? { type: "tool", name: fn.name, ...disableParallel }
|
|
136
136
|
: undefined;
|
|
137
137
|
}
|
|
138
|
+
const ANTHROPIC_SUPPORTED_SCHEMA_KEYWORDS = new Set([
|
|
139
|
+
"$defs",
|
|
140
|
+
"$ref",
|
|
141
|
+
"additionalProperties",
|
|
142
|
+
"allOf",
|
|
143
|
+
"anyOf",
|
|
144
|
+
"const",
|
|
145
|
+
"description",
|
|
146
|
+
"enum",
|
|
147
|
+
"format",
|
|
148
|
+
"items",
|
|
149
|
+
"minItems",
|
|
150
|
+
"oneOf",
|
|
151
|
+
"pattern",
|
|
152
|
+
"properties",
|
|
153
|
+
"required",
|
|
154
|
+
"title",
|
|
155
|
+
"type"
|
|
156
|
+
]);
|
|
157
|
+
const ANTHROPIC_SUPPORTED_STRING_FORMATS = new Set([
|
|
158
|
+
"date",
|
|
159
|
+
"date-time",
|
|
160
|
+
"duration",
|
|
161
|
+
"email",
|
|
162
|
+
"hostname",
|
|
163
|
+
"ipv4",
|
|
164
|
+
"ipv6",
|
|
165
|
+
"time",
|
|
166
|
+
"uri",
|
|
167
|
+
"uuid"
|
|
168
|
+
]);
|
|
169
|
+
function isRecord(value) {
|
|
170
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
171
|
+
}
|
|
172
|
+
function cloneSchemaValue(value) {
|
|
173
|
+
if (Array.isArray(value))
|
|
174
|
+
return value.map(cloneSchemaValue);
|
|
175
|
+
if (!isRecord(value))
|
|
176
|
+
return value;
|
|
177
|
+
return Object.fromEntries(Object.entries(value).map(([key, child]) => [key, cloneSchemaValue(child)]));
|
|
178
|
+
}
|
|
179
|
+
function sanitizedSchemaMap(value) {
|
|
180
|
+
if (!isRecord(value))
|
|
181
|
+
return cloneSchemaValue(value);
|
|
182
|
+
return Object.fromEntries(Object.entries(value).map(([key, schema]) => [key, anthropicStructuredOutputSchema(schema)]));
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Anthropic structured outputs accept only a subset of JSON Schema. Match the
|
|
186
|
+
* documented SDK behavior by retaining that subset, converting `oneOf` to
|
|
187
|
+
* `anyOf`, and moving omitted constraints into descriptions for model guidance.
|
|
188
|
+
* Callers remain responsible for validating the parsed response against the
|
|
189
|
+
* original schema.
|
|
190
|
+
*/
|
|
191
|
+
function anthropicStructuredOutputSchema(schema) {
|
|
192
|
+
if (!isRecord(schema))
|
|
193
|
+
return cloneSchemaValue(schema);
|
|
194
|
+
if (typeof schema.$ref === "string")
|
|
195
|
+
return { $ref: schema.$ref };
|
|
196
|
+
const sanitized = {};
|
|
197
|
+
const deferredConstraints = [];
|
|
198
|
+
let oneOf;
|
|
199
|
+
for (const [key, value] of Object.entries(schema)) {
|
|
200
|
+
if (!ANTHROPIC_SUPPORTED_SCHEMA_KEYWORDS.has(key) ||
|
|
201
|
+
(key === "minItems" && value !== 0 && value !== 1) ||
|
|
202
|
+
(key === "format" &&
|
|
203
|
+
(typeof value !== "string" || !ANTHROPIC_SUPPORTED_STRING_FORMATS.has(value)))) {
|
|
204
|
+
deferredConstraints.push([key, cloneSchemaValue(value)]);
|
|
205
|
+
continue;
|
|
206
|
+
}
|
|
207
|
+
if (key === "$defs" || key === "properties") {
|
|
208
|
+
sanitized[key] = sanitizedSchemaMap(value);
|
|
209
|
+
continue;
|
|
210
|
+
}
|
|
211
|
+
if ((key === "allOf" || key === "anyOf") && Array.isArray(value)) {
|
|
212
|
+
sanitized[key] = value.map(anthropicStructuredOutputSchema);
|
|
213
|
+
continue;
|
|
214
|
+
}
|
|
215
|
+
if (key === "oneOf") {
|
|
216
|
+
oneOf = value;
|
|
217
|
+
continue;
|
|
218
|
+
}
|
|
219
|
+
if (key === "additionalProperties" || key === "items") {
|
|
220
|
+
sanitized[key] = Array.isArray(value)
|
|
221
|
+
? value.map(anthropicStructuredOutputSchema)
|
|
222
|
+
: anthropicStructuredOutputSchema(value);
|
|
223
|
+
continue;
|
|
224
|
+
}
|
|
225
|
+
sanitized[key] = cloneSchemaValue(value);
|
|
226
|
+
}
|
|
227
|
+
if (oneOf !== undefined) {
|
|
228
|
+
if (!Object.hasOwn(sanitized, "anyOf") && Array.isArray(oneOf)) {
|
|
229
|
+
sanitized.anyOf = oneOf.map(anthropicStructuredOutputSchema);
|
|
230
|
+
}
|
|
231
|
+
else {
|
|
232
|
+
deferredConstraints.push(["oneOf", cloneSchemaValue(oneOf)]);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
if (deferredConstraints.length > 0) {
|
|
236
|
+
const constraintDescription = `{${deferredConstraints
|
|
237
|
+
.map(([key, value]) => `${key}: ${JSON.stringify(value)}`)
|
|
238
|
+
.join(", ")}}`;
|
|
239
|
+
sanitized.description =
|
|
240
|
+
typeof sanitized.description === "string" && sanitized.description.length > 0
|
|
241
|
+
? `${sanitized.description}\n\n${constraintDescription}`
|
|
242
|
+
: constraintDescription;
|
|
243
|
+
}
|
|
244
|
+
return sanitized;
|
|
245
|
+
}
|
|
138
246
|
function anthropicStructuredOutputFormat(responseFormat) {
|
|
139
247
|
if (responseFormat?.type !== "json_schema" ||
|
|
140
248
|
typeof responseFormat.json_schema?.schema !== "object" ||
|
|
@@ -143,7 +251,22 @@ function anthropicStructuredOutputFormat(responseFormat) {
|
|
|
143
251
|
}
|
|
144
252
|
return {
|
|
145
253
|
type: "json_schema",
|
|
146
|
-
schema: responseFormat.json_schema.schema
|
|
254
|
+
schema: anthropicStructuredOutputSchema(responseFormat.json_schema.schema)
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
function sanitizedAnthropicOutputConfig(outputConfig) {
|
|
258
|
+
if (outputConfig === undefined)
|
|
259
|
+
return undefined;
|
|
260
|
+
const format = outputConfig.format;
|
|
261
|
+
if (!isRecord(format) || format.type !== "json_schema" || !isRecord(format.schema)) {
|
|
262
|
+
return outputConfig;
|
|
263
|
+
}
|
|
264
|
+
return {
|
|
265
|
+
...outputConfig,
|
|
266
|
+
format: {
|
|
267
|
+
...format,
|
|
268
|
+
schema: anthropicStructuredOutputSchema(format.schema)
|
|
269
|
+
}
|
|
147
270
|
};
|
|
148
271
|
}
|
|
149
272
|
export function anthropicMessages(body, model) {
|
|
@@ -211,7 +334,7 @@ export function anthropicMessages(body, model) {
|
|
|
211
334
|
const translatedOutput = selection.mode === "effort" ? { effort: selection.effort } : undefined;
|
|
212
335
|
const thinking = metadata?.thinking ?? translatedThinking;
|
|
213
336
|
const structuredOutputFormat = anthropicStructuredOutputFormat(body.response_format);
|
|
214
|
-
const outputConfig = metadata?.output_config != null
|
|
337
|
+
const outputConfig = sanitizedAnthropicOutputConfig(metadata?.output_config != null
|
|
215
338
|
? {
|
|
216
339
|
...metadata.output_config,
|
|
217
340
|
...(structuredOutputFormat !== undefined &&
|
|
@@ -224,7 +347,7 @@ export function anthropicMessages(body, model) {
|
|
|
224
347
|
...translatedOutput,
|
|
225
348
|
...(structuredOutputFormat !== undefined ? { format: structuredOutputFormat } : {})
|
|
226
349
|
}
|
|
227
|
-
: undefined;
|
|
350
|
+
: undefined);
|
|
228
351
|
const toolChoice = anthropicToolChoice(body.tool_choice, body.parallel_tool_calls);
|
|
229
352
|
return {
|
|
230
353
|
model,
|
|
@@ -246,7 +369,7 @@ export function anthropicMessages(body, model) {
|
|
|
246
369
|
{
|
|
247
370
|
name: tool.function.name,
|
|
248
371
|
description: tool.function.description,
|
|
249
|
-
input_schema: tool.function.parameters ?? { type: "object" }
|
|
372
|
+
input_schema: anthropicStructuredOutputSchema(tool.function.parameters ?? { type: "object" })
|
|
250
373
|
}
|
|
251
374
|
])
|
|
252
375
|
}
|
|
@@ -18,7 +18,7 @@ export type BedrockProviderSourceOptions = {
|
|
|
18
18
|
mantleBackend?: BedrockMantleBackend;
|
|
19
19
|
};
|
|
20
20
|
export { fromBedrockConverseOutput, toBedrockConverseInput };
|
|
21
|
-
export declare const BEDROCK_OPENAI_ALLOWLIST: readonly ["openai.gpt-5.
|
|
21
|
+
export declare const BEDROCK_OPENAI_ALLOWLIST: readonly ["openai.gpt-5.6-sol", "openai.gpt-5.6-terra", "openai.gpt-5.6-luna"];
|
|
22
22
|
export declare function isBedrockOpenAiModel(modelId: string): boolean;
|
|
23
23
|
/**
|
|
24
24
|
* Remove OpenAI/Codex protocol fields that bedrock-mantle rejects while
|
|
@@ -12,8 +12,6 @@ import { OpenAiBackend } from "./openai-backend.js";
|
|
|
12
12
|
import { gatewayTry, gatewayTryPromise } from "../effect/gateway.js";
|
|
13
13
|
export { fromBedrockConverseOutput, toBedrockConverseInput };
|
|
14
14
|
export const BEDROCK_OPENAI_ALLOWLIST = [
|
|
15
|
-
"openai.gpt-5.4",
|
|
16
|
-
"openai.gpt-5.5",
|
|
17
15
|
"openai.gpt-5.6-sol",
|
|
18
16
|
"openai.gpt-5.6-terra",
|
|
19
17
|
"openai.gpt-5.6-luna"
|
|
@@ -126,13 +126,18 @@ test("Bedrock discovery includes active Anthropic foundations and paginated back
|
|
|
126
126
|
assert.equal(commands.length, 3);
|
|
127
127
|
});
|
|
128
128
|
test("Bedrock OpenAI model ids stay on mantle and never match Anthropic Converse", () => {
|
|
129
|
-
assert.equal(isBedrockOpenAiModel("openai.gpt-5.
|
|
129
|
+
assert.equal(isBedrockOpenAiModel("openai.gpt-5.7"), true);
|
|
130
130
|
assert.equal(isBedrockOpenAiModel("openai.gpt-5.6-sol"), true);
|
|
131
131
|
assert.equal(isBedrockOpenAiModel("us.openai.gpt-5.6-terra"), true);
|
|
132
132
|
assert.equal(isBedrockOpenAiModel("anthropic.claude-3"), false);
|
|
133
133
|
assert.equal(isBedrockOpenAiModel("us.anthropic.claude-3"), false);
|
|
134
134
|
});
|
|
135
|
-
test("Bedrock discovery
|
|
135
|
+
test("Bedrock discovery advertises only verified OpenAI mantle models", async () => {
|
|
136
|
+
assert.deepEqual(BEDROCK_OPENAI_ALLOWLIST, [
|
|
137
|
+
"openai.gpt-5.6-sol",
|
|
138
|
+
"openai.gpt-5.6-terra",
|
|
139
|
+
"openai.gpt-5.6-luna"
|
|
140
|
+
]);
|
|
136
141
|
const source = new BedrockProviderSource({
|
|
137
142
|
env: { AWS_BEARER_TOKEN_BEDROCK: "bedrock-key", AWS_REGION: "us-east-1" },
|
|
138
143
|
controlClient: {
|
|
@@ -205,14 +210,14 @@ test("Bedrock routes OpenAI models through mantle and leaves Anthropic on Conver
|
|
|
205
210
|
}
|
|
206
211
|
}
|
|
207
212
|
});
|
|
208
|
-
assert.equal(source.responses.kind === "responses" && source.responses.supports("openai.gpt-5.
|
|
213
|
+
assert.equal(source.responses.kind === "responses" && source.responses.supports("openai.gpt-5.6-sol"), true);
|
|
209
214
|
assert.equal(source.responses.kind === "responses" && source.responses.supports("anthropic.claude-3"), false);
|
|
210
215
|
assert.equal(source.capabilities.reasoningForModel("openai.gpt-5.6-sol")?.wireShape, "openai-responses");
|
|
211
216
|
const openaiChat = await runRouteKitEffect(source.requests.chat({
|
|
212
|
-
model: "openai.gpt-5.
|
|
217
|
+
model: "openai.gpt-5.6-sol",
|
|
213
218
|
messages: [{ role: "user", content: "hi" }]
|
|
214
219
|
}));
|
|
215
|
-
assert.deepEqual(await openaiChat.json(), { id: "chat", model: "openai.gpt-5.
|
|
220
|
+
assert.deepEqual(await openaiChat.json(), { id: "chat", model: "openai.gpt-5.6-sol" });
|
|
216
221
|
assert.equal(source.responses.kind, "responses");
|
|
217
222
|
if (source.responses.kind !== "responses")
|
|
218
223
|
throw new Error("expected Responses support");
|
|
@@ -232,7 +237,7 @@ test("Bedrock routes OpenAI models through mantle and leaves Anthropic on Conver
|
|
|
232
237
|
assert.equal(runtimeCalls.length, 1);
|
|
233
238
|
assert.equal(runtimeCalls[0] instanceof ConverseCommand, true);
|
|
234
239
|
assert.deepEqual(mantleCalls, [
|
|
235
|
-
{ kind: "chat", model: "openai.gpt-5.
|
|
240
|
+
{ kind: "chat", model: "openai.gpt-5.6-sol" },
|
|
236
241
|
{ kind: "responses", model: "openai.gpt-5.6-terra" }
|
|
237
242
|
]);
|
|
238
243
|
const rejected = await runRouteKitEffect(source.responses.execute({
|
|
@@ -304,7 +309,7 @@ test("Bedrock OpenAI chat without a mantle key returns 400 and skips Converse",
|
|
|
304
309
|
}
|
|
305
310
|
});
|
|
306
311
|
const response = await runRouteKitEffect(source.requests.chat({
|
|
307
|
-
model: "openai.gpt-5.
|
|
312
|
+
model: "openai.gpt-5.6-luna",
|
|
308
313
|
messages: [{ role: "user", content: "hi" }]
|
|
309
314
|
}));
|
|
310
315
|
assert.equal(response.status, 400);
|
package/dist/test/chat.test.js
CHANGED
|
@@ -134,7 +134,7 @@ test("GPT-5 Chat Completions translate max_tokens to max_completion_tokens", asy
|
|
|
134
134
|
for (const model of [
|
|
135
135
|
"gpt-5.6-sol",
|
|
136
136
|
"openai.gpt-5.6-luna",
|
|
137
|
-
"bedrock/openai.gpt-5.
|
|
137
|
+
"bedrock/openai.gpt-5.6-sol",
|
|
138
138
|
"routekit/bedrock/us.openai.gpt-5.7"
|
|
139
139
|
]) {
|
|
140
140
|
const response = await fetch(`${gateway.url()}/v1/chat/completions`, {
|
|
@@ -35,6 +35,177 @@ test("Responses JSON schemas reach Anthropic as native structured output formats
|
|
|
35
35
|
}
|
|
36
36
|
});
|
|
37
37
|
});
|
|
38
|
+
test("Anthropic structured outputs defer unsupported JSON Schema constraints", () => {
|
|
39
|
+
const schema = {
|
|
40
|
+
type: "object",
|
|
41
|
+
additionalProperties: false,
|
|
42
|
+
required: ["minimum", "scores", "labels"],
|
|
43
|
+
properties: {
|
|
44
|
+
minimum: { type: "integer", minimum: 1, maximum: 16_384 },
|
|
45
|
+
scores: {
|
|
46
|
+
type: "array",
|
|
47
|
+
minItems: 20,
|
|
48
|
+
maxItems: 20,
|
|
49
|
+
items: { type: "number", minimum: 0, maximum: 1 }
|
|
50
|
+
},
|
|
51
|
+
labels: {
|
|
52
|
+
type: "array",
|
|
53
|
+
minItems: 1,
|
|
54
|
+
items: { type: "string", minLength: 1, maxLength: 128 }
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
const original = structuredClone(schema);
|
|
59
|
+
const outbound = anthropicMessages({
|
|
60
|
+
model: "claude-opus-5",
|
|
61
|
+
messages: [{ role: "user", content: "author evaluations" }],
|
|
62
|
+
response_format: {
|
|
63
|
+
type: "json_schema",
|
|
64
|
+
json_schema: { name: "routekit_evaluations", schema, strict: true }
|
|
65
|
+
}
|
|
66
|
+
}, "claude-opus-5");
|
|
67
|
+
assert.deepEqual(schema, original);
|
|
68
|
+
assert.deepEqual(outbound.output_config, {
|
|
69
|
+
format: {
|
|
70
|
+
type: "json_schema",
|
|
71
|
+
schema: {
|
|
72
|
+
type: "object",
|
|
73
|
+
additionalProperties: false,
|
|
74
|
+
required: ["minimum", "scores", "labels"],
|
|
75
|
+
properties: {
|
|
76
|
+
minimum: {
|
|
77
|
+
type: "integer",
|
|
78
|
+
description: "{minimum: 1, maximum: 16384}"
|
|
79
|
+
},
|
|
80
|
+
scores: {
|
|
81
|
+
type: "array",
|
|
82
|
+
items: {
|
|
83
|
+
type: "number",
|
|
84
|
+
description: "{minimum: 0, maximum: 1}"
|
|
85
|
+
},
|
|
86
|
+
description: "{minItems: 20, maxItems: 20}"
|
|
87
|
+
},
|
|
88
|
+
labels: {
|
|
89
|
+
type: "array",
|
|
90
|
+
minItems: 1,
|
|
91
|
+
items: {
|
|
92
|
+
type: "string",
|
|
93
|
+
description: "{minLength: 1, maxLength: 128}"
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
const nativeOutbound = anthropicMessages(anthropicToChat({
|
|
101
|
+
model: "claude-opus-5",
|
|
102
|
+
messages: [{ role: "user", content: "author evaluations" }],
|
|
103
|
+
output_config: {
|
|
104
|
+
format: { type: "json_schema", schema }
|
|
105
|
+
}
|
|
106
|
+
}, "claude-opus-5"), "claude-opus-5");
|
|
107
|
+
assert.deepEqual(nativeOutbound.output_config, outbound.output_config);
|
|
108
|
+
});
|
|
109
|
+
test("Anthropic tool input schemas defer unsupported JSON Schema constraints", () => {
|
|
110
|
+
const parameters = {
|
|
111
|
+
type: "object",
|
|
112
|
+
additionalProperties: false,
|
|
113
|
+
required: ["limit", "scores"],
|
|
114
|
+
properties: {
|
|
115
|
+
limit: { type: "integer", minimum: 1, maximum: 16_384 },
|
|
116
|
+
scores: {
|
|
117
|
+
type: "array",
|
|
118
|
+
minItems: 20,
|
|
119
|
+
maxItems: 20,
|
|
120
|
+
items: { type: "number", minimum: 0, maximum: 1 }
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
const original = structuredClone(parameters);
|
|
125
|
+
const outbound = anthropicMessages({
|
|
126
|
+
model: "claude-opus-5",
|
|
127
|
+
messages: [{ role: "user", content: "score the inputs" }],
|
|
128
|
+
tools: [
|
|
129
|
+
{
|
|
130
|
+
type: "function",
|
|
131
|
+
function: {
|
|
132
|
+
name: "score_inputs",
|
|
133
|
+
description: "score structured inputs",
|
|
134
|
+
parameters
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
]
|
|
138
|
+
}, "claude-opus-5");
|
|
139
|
+
assert.deepEqual(parameters, original);
|
|
140
|
+
assert.deepEqual(outbound.tools, [
|
|
141
|
+
{
|
|
142
|
+
name: "score_inputs",
|
|
143
|
+
description: "score structured inputs",
|
|
144
|
+
input_schema: {
|
|
145
|
+
type: "object",
|
|
146
|
+
additionalProperties: false,
|
|
147
|
+
required: ["limit", "scores"],
|
|
148
|
+
properties: {
|
|
149
|
+
limit: {
|
|
150
|
+
type: "integer",
|
|
151
|
+
description: "{minimum: 1, maximum: 16384}"
|
|
152
|
+
},
|
|
153
|
+
scores: {
|
|
154
|
+
type: "array",
|
|
155
|
+
items: {
|
|
156
|
+
type: "number",
|
|
157
|
+
description: "{minimum: 0, maximum: 1}"
|
|
158
|
+
},
|
|
159
|
+
description: "{minItems: 20, maxItems: 20}"
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
]);
|
|
165
|
+
});
|
|
166
|
+
test("Anthropic structured outputs keep only supported schema keywords and formats", () => {
|
|
167
|
+
const outbound = anthropicMessages({
|
|
168
|
+
model: "claude-opus-5",
|
|
169
|
+
messages: [{ role: "user", content: "return a structured value" }],
|
|
170
|
+
response_format: {
|
|
171
|
+
type: "json_schema",
|
|
172
|
+
json_schema: {
|
|
173
|
+
name: "routekit_supported_schema",
|
|
174
|
+
strict: true,
|
|
175
|
+
schema: {
|
|
176
|
+
type: "object",
|
|
177
|
+
minProperties: 1,
|
|
178
|
+
properties: {
|
|
179
|
+
identifier: {
|
|
180
|
+
type: "string",
|
|
181
|
+
pattern: "^[a-z]+$",
|
|
182
|
+
format: "regex"
|
|
183
|
+
},
|
|
184
|
+
createdAt: {
|
|
185
|
+
type: "string",
|
|
186
|
+
format: "date-time"
|
|
187
|
+
},
|
|
188
|
+
choice: {
|
|
189
|
+
oneOf: [{ const: "one" }, { const: "two" }]
|
|
190
|
+
}
|
|
191
|
+
},
|
|
192
|
+
required: ["identifier", "createdAt", "choice"],
|
|
193
|
+
additionalProperties: false
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}, "claude-opus-5");
|
|
198
|
+
const schema = outbound.output_config.format.schema;
|
|
199
|
+
const properties = schema.properties;
|
|
200
|
+
assert.equal(schema.minProperties, undefined);
|
|
201
|
+
assert.match(schema.description, /minProperties/u);
|
|
202
|
+
assert.equal(properties.identifier.format, undefined);
|
|
203
|
+
assert.equal(properties.identifier.pattern, "^[a-z]+$");
|
|
204
|
+
assert.match(properties.identifier.description, /format/u);
|
|
205
|
+
assert.equal(properties.createdAt.format, "date-time");
|
|
206
|
+
assert.equal(properties.choice.oneOf, undefined);
|
|
207
|
+
assert.deepEqual(properties.choice.anyOf, [{ const: "one" }, { const: "two" }]);
|
|
208
|
+
});
|
|
38
209
|
test("direct provider backends reject malformed reasoning controls before transport", async () => {
|
|
39
210
|
const cases = [
|
|
40
211
|
{
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@velum-labs/routekit-gateway",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "1.0.
|
|
4
|
+
"version": "1.0.8",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
7
7
|
"url": "git+https://github.com/velum-labs/routekit.git",
|
|
@@ -45,12 +45,12 @@
|
|
|
45
45
|
"@aws-sdk/client-bedrock": "3.1095.0",
|
|
46
46
|
"@aws-sdk/client-bedrock-runtime": "3.1095.0",
|
|
47
47
|
"effect": "4.0.0-rc.108",
|
|
48
|
-
"@velum-labs/routekit-config-core": "1.0.
|
|
49
|
-
"@velum-labs/routekit-contracts": "1.0.
|
|
50
|
-
"@velum-labs/routekit-eval-contracts": "1.0.
|
|
51
|
-
"@velum-labs/routekit-eval-core": "1.0.
|
|
52
|
-
"@velum-labs/routekit-registry": "1.0.
|
|
53
|
-
"@velum-labs/routekit-runtime": "1.0.
|
|
48
|
+
"@velum-labs/routekit-config-core": "1.0.8",
|
|
49
|
+
"@velum-labs/routekit-contracts": "1.0.8",
|
|
50
|
+
"@velum-labs/routekit-eval-contracts": "1.0.8",
|
|
51
|
+
"@velum-labs/routekit-eval-core": "1.0.8",
|
|
52
|
+
"@velum-labs/routekit-registry": "1.0.8",
|
|
53
|
+
"@velum-labs/routekit-runtime": "1.0.8"
|
|
54
54
|
},
|
|
55
55
|
"keywords": [
|
|
56
56
|
"routekit",
|