mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-12 18:22:48 +03:00
Merge-train validated (tip 6ce4effef8). Vitest failures confirmed as base-red (#9679).
This commit is contained in:
@@ -48,7 +48,7 @@ import { checkAndRefreshToken } from "../services/tokenRefresh";
|
||||
import { createHookContext, runHooks, initPreRequestRegistry } from "@/lib/middleware/registry";
|
||||
import { rejectPeerRequest } from "@/shared/resilience/peerRouting";
|
||||
import { deleteHandoff, getHandoff } from "@/lib/db/contextHandoffs";
|
||||
import { updateCombo } from "@/lib/db/combos";
|
||||
import { getComboByName, updateCombo } from "@/lib/db/combos";
|
||||
import { isModelAllowedForKey } from "@/lib/db/apiKeys";
|
||||
import { promoteSuccessfulComboModel } from "@/lib/combos/autoPromote";
|
||||
import {
|
||||
@@ -462,10 +462,14 @@ async function handleChatImplementation(
|
||||
// image-registry match is only image-only when the same provider/model pair is
|
||||
// absent from the chat catalog.
|
||||
const imageModel = getImageModelEntry(modelStr);
|
||||
// Exact stored combo names take precedence over colliding bare image aliases.
|
||||
// Keep this narrower than getComboForModel() so mappings and synthetic aliases
|
||||
// retain their existing resolution order.
|
||||
const isExactStoredCombo = imageModel ? Boolean(await getComboByName(modelStr)) : false;
|
||||
const isChatCatalogModel = imageModel
|
||||
? getModelsByProviderId(imageModel.provider).some((model) => model.id === imageModel.model)
|
||||
: false;
|
||||
if (imageModel && !isChatCatalogModel) {
|
||||
if (imageModel && !isExactStoredCombo && !isChatCatalogModel) {
|
||||
log.warn("CHAT", `Rejecting image-generation model on chat endpoint: ${modelStr}`);
|
||||
return errorResponse(
|
||||
HTTP_STATUS.BAD_REQUEST,
|
||||
|
||||
@@ -11,8 +11,11 @@ import assert from "node:assert/strict";
|
||||
import { createChatPipelineHarness } from "../integration/_chatPipelineHarness.ts";
|
||||
|
||||
const harness = await createChatPipelineHarness("chat-rejects-image-only-model");
|
||||
const { buildRequest, handleChat, resetStorage } = harness as {
|
||||
const { buildRequest, combosDb, handleChat, resetStorage } = harness as {
|
||||
buildRequest: (opts: { body: unknown }) => Request;
|
||||
combosDb: {
|
||||
createCombo: (data: Record<string, unknown>) => Promise<unknown>;
|
||||
};
|
||||
handleChat: (req: Request) => Promise<Response>;
|
||||
resetStorage: () => void | Promise<void>;
|
||||
};
|
||||
@@ -72,6 +75,32 @@ test("POST /v1/chat/completions with a chat model still reaches routing (guard i
|
||||
}
|
||||
});
|
||||
|
||||
test("POST /v1/chat/completions routes a stored chat combo whose name is an image alias (#8986)", async () => {
|
||||
await combosDb.createCombo({
|
||||
name: "fast",
|
||||
strategy: "priority",
|
||||
models: ["openai/gpt-4o"],
|
||||
});
|
||||
|
||||
const request = buildRequest({
|
||||
body: {
|
||||
model: "fast",
|
||||
messages: [{ role: "user", content: "hi" }],
|
||||
},
|
||||
});
|
||||
|
||||
const res = await handleChat(request);
|
||||
if (res.status === 400) {
|
||||
const body = (await res.json()) as { error?: { message?: string } };
|
||||
const msg = body?.error?.message || JSON.stringify(body);
|
||||
assert.doesNotMatch(
|
||||
msg,
|
||||
/image-generation model/i,
|
||||
"a stored chat combo must take precedence over a colliding image alias"
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
test("POST /v1/chat/completions allows a model registered for both chat and image generation", async () => {
|
||||
const request = buildRequest({
|
||||
body: {
|
||||
|
||||
Reference in New Issue
Block a user