@velum-labs/routekit-gateway 0.9.2 → 0.9.3
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/router.js +10 -0
- package/dist/server.js +2 -0
- package/dist/test/chat.test.js +5 -1
- package/dist/test/responses.test.js +4 -1
- package/dist/test/router.test.js +61 -0
- package/package.json +5 -5
package/dist/router.js
CHANGED
|
@@ -367,6 +367,9 @@ export class CatalogBackend {
|
|
|
367
367
|
nativeBody.reasoning_effort =
|
|
368
368
|
selection.effort;
|
|
369
369
|
}
|
|
370
|
+
else {
|
|
371
|
+
delete nativeBody.reasoning_effort;
|
|
372
|
+
}
|
|
370
373
|
}
|
|
371
374
|
return entry.source.chat(nativeBody, signal, {
|
|
372
375
|
...options,
|
|
@@ -437,6 +440,13 @@ export class CatalogBackend {
|
|
|
437
440
|
return selection;
|
|
438
441
|
}
|
|
439
442
|
const capability = entry.reasoning;
|
|
443
|
+
if (selection.mode === "effort" &&
|
|
444
|
+
selection.effort === "none" &&
|
|
445
|
+
(capability === undefined ||
|
|
446
|
+
capability.status === "unknown" ||
|
|
447
|
+
capability.status === "unsupported")) {
|
|
448
|
+
return { mode: "disabled" };
|
|
449
|
+
}
|
|
440
450
|
if (capability === undefined || capability.status === "unknown") {
|
|
441
451
|
return `model "${entry.publicId}" has no discovered reasoning controls`;
|
|
442
452
|
}
|
package/dist/server.js
CHANGED
|
@@ -247,6 +247,7 @@ export async function startGateway(options) {
|
|
|
247
247
|
: base.data ?? [];
|
|
248
248
|
writeJson(res, 200, {
|
|
249
249
|
object: "list",
|
|
250
|
+
default_model: backend.defaultModel,
|
|
250
251
|
data,
|
|
251
252
|
models: codexPickerModels(backend, base.data ?? [], merged.models, codexProviderRelay === undefined)
|
|
252
253
|
});
|
|
@@ -263,6 +264,7 @@ export async function startGateway(options) {
|
|
|
263
264
|
writeJson(res, 200, {
|
|
264
265
|
...modelPayload,
|
|
265
266
|
object: typeof modelPayload.object === "string" ? modelPayload.object : "list",
|
|
267
|
+
default_model: backend.defaultModel,
|
|
266
268
|
data,
|
|
267
269
|
models: codexPickerModels(backend, data.flatMap((entry) => typeof entry.id === "string"
|
|
268
270
|
? [{ ...entry, id: entry.id }]
|
package/dist/test/chat.test.js
CHANGED
|
@@ -333,12 +333,16 @@ test("forceModel overrides the requested model on every upstream call", async ()
|
|
|
333
333
|
test("lists models from the backend", async () => {
|
|
334
334
|
const mock = await startMock();
|
|
335
335
|
const gateway = await startGateway({
|
|
336
|
-
backend: new OpenAiBackend({
|
|
336
|
+
backend: new OpenAiBackend({
|
|
337
|
+
baseUrl: `${mock.url}/v1`,
|
|
338
|
+
defaultModel: "mlx-default"
|
|
339
|
+
})
|
|
337
340
|
});
|
|
338
341
|
try {
|
|
339
342
|
const response = await fetch(`${gateway.url()}/v1/models`);
|
|
340
343
|
assert.equal(response.status, 200);
|
|
341
344
|
const json = (await response.json());
|
|
345
|
+
assert.equal(json.default_model, "mlx-default");
|
|
342
346
|
assert.equal(json.data.length, 1);
|
|
343
347
|
}
|
|
344
348
|
finally {
|
|
@@ -657,6 +657,7 @@ test("Codex picker aliases use the canonical catalog and pooled native relay", a
|
|
|
657
657
|
const catalogResponse = await fetch(`${gateway.url()}/v1/models?client_version=1.0.0`);
|
|
658
658
|
assert.equal(catalogResponse.headers.get("etag"), null, "a projected managed catalog must not reuse the upstream ETag");
|
|
659
659
|
const catalog = (await catalogResponse.json());
|
|
660
|
+
assert.equal(catalog.default_model, "codex/gpt-5.5");
|
|
660
661
|
assert.deepEqual(catalog.data.map((model) => model.id), ["codex/gpt-5.5", "claude-code/claude-sonnet-4-6"]);
|
|
661
662
|
assert.deepEqual(catalog.models.map(({ slug, display_name }) => [slug, display_name]), [
|
|
662
663
|
["gpt-5.5", "GPT-5.5"],
|
|
@@ -693,11 +694,13 @@ test("Codex picker aliases use the canonical catalog and pooled native relay", a
|
|
|
693
694
|
body: JSON.stringify({
|
|
694
695
|
model: "claude-code/claude-sonnet-4-6",
|
|
695
696
|
instructions: "You are Codex, a coding agent based on GPT-5.",
|
|
696
|
-
input: "hi"
|
|
697
|
+
input: "hi",
|
|
698
|
+
reasoning: { effort: "none" }
|
|
697
699
|
})
|
|
698
700
|
});
|
|
699
701
|
assert.equal(foreign.status, 200);
|
|
700
702
|
assert.deepEqual(sourceCalls, ["claude-sonnet-4-6"]);
|
|
703
|
+
assert.equal(sourceBodies[0]?.reasoning_effort, undefined);
|
|
701
704
|
assert.ok(!JSON.stringify(sourceBodies[0]?.messages).includes("based on GPT-5"), "a stale startup-model identity must not cross into a foreign provider");
|
|
702
705
|
const unknown = await fetch(`${gateway.url()}/v1/responses`, {
|
|
703
706
|
method: "POST",
|
package/dist/test/router.test.js
CHANGED
|
@@ -268,6 +268,67 @@ test("catalog applies configured opaque efforts and rejects unavailable values b
|
|
|
268
268
|
assert.equal(calls.length, 1);
|
|
269
269
|
assert.equal(backend.reasoningCapabilities("openai/opaque")?.provenance, "config");
|
|
270
270
|
});
|
|
271
|
+
test("catalog treats Codex none as disabled only for models without reasoning controls", async () => {
|
|
272
|
+
const exercise = async (reasoning, effort) => {
|
|
273
|
+
const bodies = [];
|
|
274
|
+
const backend = await CatalogBackend.create({
|
|
275
|
+
config: {
|
|
276
|
+
providers: { openai: {} },
|
|
277
|
+
defaultModel: "openai/model"
|
|
278
|
+
},
|
|
279
|
+
sources: {
|
|
280
|
+
openai: {
|
|
281
|
+
sourceId: "openai",
|
|
282
|
+
async discoverModels() {
|
|
283
|
+
return [{ id: "model", ...(reasoning !== undefined ? { reasoning } : {}) }];
|
|
284
|
+
},
|
|
285
|
+
async chat(body) {
|
|
286
|
+
bodies.push(body);
|
|
287
|
+
return Response.json({});
|
|
288
|
+
},
|
|
289
|
+
async embeddings() {
|
|
290
|
+
return Response.json({});
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
});
|
|
295
|
+
return {
|
|
296
|
+
response: await backend.chat({
|
|
297
|
+
model: "openai/model",
|
|
298
|
+
reasoning_effort: effort,
|
|
299
|
+
messages: []
|
|
300
|
+
}),
|
|
301
|
+
bodies
|
|
302
|
+
};
|
|
303
|
+
};
|
|
304
|
+
for (const reasoning of [
|
|
305
|
+
undefined,
|
|
306
|
+
{ status: "unknown", provenance: "unknown" },
|
|
307
|
+
{ status: "unsupported", provenance: "provider" }
|
|
308
|
+
]) {
|
|
309
|
+
const normalized = await exercise(reasoning, "none");
|
|
310
|
+
assert.equal(normalized.response.status, 200);
|
|
311
|
+
assert.equal(normalized.bodies.length, 1);
|
|
312
|
+
assert.equal(normalized.bodies[0]?.reasoning_effort, undefined);
|
|
313
|
+
}
|
|
314
|
+
const undiscoveredEffort = await exercise(undefined, "medium");
|
|
315
|
+
assert.equal(undiscoveredEffort.response.status, 400);
|
|
316
|
+
assert.equal(undiscoveredEffort.bodies.length, 0);
|
|
317
|
+
const advertisedNone = await exercise({
|
|
318
|
+
status: "supported",
|
|
319
|
+
efforts: [{ id: "none" }, { id: "high" }],
|
|
320
|
+
provenance: "provider"
|
|
321
|
+
}, "none");
|
|
322
|
+
assert.equal(advertisedNone.response.status, 200);
|
|
323
|
+
assert.equal(advertisedNone.bodies[0]?.reasoning_effort, "none");
|
|
324
|
+
const unsupportedNone = await exercise({
|
|
325
|
+
status: "supported",
|
|
326
|
+
efforts: [{ id: "low" }, { id: "high" }],
|
|
327
|
+
provenance: "provider"
|
|
328
|
+
}, "none");
|
|
329
|
+
assert.equal(unsupportedNone.response.status, 400);
|
|
330
|
+
assert.equal(unsupportedNone.bodies.length, 0);
|
|
331
|
+
});
|
|
271
332
|
test("unknown models never fall through to the default source", async () => {
|
|
272
333
|
const backend = await CatalogBackend.create({
|
|
273
334
|
config: { providers: { openai: {} } },
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@velum-labs/routekit-gateway",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "0.9.
|
|
4
|
+
"version": "0.9.3",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
7
7
|
"url": "git+https://github.com/velum-labs/handoffkit.git",
|
|
@@ -27,10 +27,10 @@
|
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
29
|
"zod": "4.4.3",
|
|
30
|
-
"@velum-labs/routekit-
|
|
31
|
-
"@velum-labs/routekit-
|
|
32
|
-
"@velum-labs/routekit-tracing": "0.9.
|
|
33
|
-
"@velum-labs/routekit-runtime": "0.9.
|
|
30
|
+
"@velum-labs/routekit-contracts": "0.9.3",
|
|
31
|
+
"@velum-labs/routekit-registry": "0.9.3",
|
|
32
|
+
"@velum-labs/routekit-tracing": "0.9.3",
|
|
33
|
+
"@velum-labs/routekit-runtime": "0.9.3"
|
|
34
34
|
},
|
|
35
35
|
"keywords": [
|
|
36
36
|
"routekit",
|