mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-21 06:32:16 +03:00
fix(dashboard): disambiguate colliding passthrough model aliases (port from 9router#1850) (#6431)
disambiguate colliding passthrough model aliases (port #1850) (net +1/-0, test OK). Integrated into release/v3.8.46.
This commit is contained in:
committed by
GitHub
parent
2ecaae7c40
commit
b67f2c58da
@@ -14,6 +14,7 @@
|
||||
*/
|
||||
import React, { useState, useMemo } from "react";
|
||||
import { Button } from "@/shared/components";
|
||||
import { generateUniqueModelAlias } from "./passthroughAlias.ts";
|
||||
import {
|
||||
matchesModelCatalogQuery,
|
||||
normalizeModelCatalogSource,
|
||||
@@ -323,22 +324,18 @@ export default function PassthroughModelsSection({
|
||||
: filteredModels;
|
||||
const activeCount = allModels.filter((model) => !model.isHidden).length;
|
||||
|
||||
// Generate default alias from modelId (last part after /)
|
||||
const generateDefaultAlias = (modelId: string) => {
|
||||
const parts = modelId.split("/");
|
||||
return parts[parts.length - 1];
|
||||
};
|
||||
|
||||
const handleAdd = async () => {
|
||||
if (!newModel.trim() || adding) return;
|
||||
const modelId = newModel.trim();
|
||||
const defaultAlias = generateDefaultAlias(modelId);
|
||||
|
||||
// Check if alias already exists
|
||||
if (modelAliases[defaultAlias]) {
|
||||
alert(t("aliasExistsAlert", { alias: defaultAlias }));
|
||||
// #1850: block re-adding the SAME model, but disambiguate DISTINCT models
|
||||
// that would otherwise collapse to the same last-segment alias (e.g.
|
||||
// enx/gpt-5.5 vs enx/codebuddy/gpt-5.5 → both "gpt-5.5").
|
||||
if (Object.values(modelAliases).includes(modelId)) {
|
||||
alert(t("aliasExistsAlert", { alias: modelId }));
|
||||
return;
|
||||
}
|
||||
const defaultAlias = generateUniqueModelAlias(modelId, modelAliases);
|
||||
|
||||
setAdding(true);
|
||||
try {
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
* Generate a unique default alias for a passthrough model id (9router#1850).
|
||||
*
|
||||
* The naive "last path segment" alias collapses distinct namespaced ids to the
|
||||
* same alias — e.g. `enx/codebuddy/gpt-5.5` and `enx/gpt-5.5` both become
|
||||
* `gpt-5.5` — so the second model could never be added (the UI only alerted
|
||||
* "alias already exists"). This disambiguates deterministically:
|
||||
* 1. the bare last segment, if free;
|
||||
* 2. progressively more-qualified names joined with "-" (parent segments
|
||||
* prepended), if the shorter form is taken;
|
||||
* 3. a numeric suffix on the last segment as a final fallback.
|
||||
*
|
||||
* Pure — no React/DOM deps — so it is unit-testable.
|
||||
*/
|
||||
export function generateUniqueModelAlias(
|
||||
modelId: string,
|
||||
existingAliases: Record<string, unknown> = {}
|
||||
): string {
|
||||
const parts = String(modelId ?? "")
|
||||
.split("/")
|
||||
.filter(Boolean);
|
||||
|
||||
if (parts.length === 0) {
|
||||
// No usable segments (e.g. "" or "///") — fall back to the raw id + numeric.
|
||||
const base = String(modelId ?? "").trim() || "model";
|
||||
return isTaken(base, existingAliases) ? nextNumeric(base, existingAliases) : base;
|
||||
}
|
||||
|
||||
// 1 + 2: try last segment, then last-2 joined, … up to the full path.
|
||||
for (let take = 1; take <= parts.length; take++) {
|
||||
const candidate = parts.slice(parts.length - take).join("-");
|
||||
if (!isTaken(candidate, existingAliases)) return candidate;
|
||||
}
|
||||
|
||||
// 3: every qualified form is taken → numeric suffix on the last segment.
|
||||
return nextNumeric(parts[parts.length - 1], existingAliases);
|
||||
}
|
||||
|
||||
function isTaken(alias: string, existingAliases: Record<string, unknown>): boolean {
|
||||
return Object.prototype.hasOwnProperty.call(existingAliases, alias);
|
||||
}
|
||||
|
||||
function nextNumeric(base: string, existingAliases: Record<string, unknown>): string {
|
||||
let i = 2;
|
||||
while (isTaken(`${base}-${i}`, existingAliases)) i++;
|
||||
return `${base}-${i}`;
|
||||
}
|
||||
Reference in New Issue
Block a user