Initial commit: OmniAI Web Frontend
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,96 @@
|
||||
import { isOptionalApiRouteMissing } from "./apiErrorUtils";
|
||||
import { isRecord, serverRequest } from "./serverConnection";
|
||||
|
||||
export interface ModelCapabilityOption {
|
||||
value: string;
|
||||
label: string;
|
||||
description?: string;
|
||||
badge?: string;
|
||||
enabled?: boolean;
|
||||
status?: "available" | "maintenance" | "disabled" | string;
|
||||
}
|
||||
|
||||
export interface WebModelCapabilities {
|
||||
source: "server" | "fallback";
|
||||
imageModels: ModelCapabilityOption[];
|
||||
videoModels: ModelCapabilityOption[];
|
||||
chatModels: ModelCapabilityOption[];
|
||||
updatedAt?: string;
|
||||
}
|
||||
|
||||
function toStringValue(value: unknown, fallback = ""): string {
|
||||
if (typeof value === "string") return value.trim() || fallback;
|
||||
if (typeof value === "number" && Number.isFinite(value)) return String(value);
|
||||
return fallback;
|
||||
}
|
||||
|
||||
function normalizeModelOption(raw: unknown): ModelCapabilityOption | null {
|
||||
if (typeof raw === "string") {
|
||||
const value = raw.trim();
|
||||
return value ? { value, label: value } : null;
|
||||
}
|
||||
if (!isRecord(raw)) return null;
|
||||
|
||||
const value = toStringValue(raw.value ?? raw.id ?? raw.model ?? raw.modelKey ?? raw.model_key);
|
||||
if (!value) return null;
|
||||
|
||||
const status = toStringValue(raw.status);
|
||||
const enabled = raw.enabled === undefined ? status !== "maintenance" && status !== "disabled" : Boolean(raw.enabled);
|
||||
if (!enabled) return null;
|
||||
|
||||
return {
|
||||
value,
|
||||
label: toStringValue(raw.label ?? raw.displayName ?? raw.display_name ?? raw.name, value),
|
||||
description: toStringValue(raw.description) || undefined,
|
||||
badge: toStringValue(raw.badge) || undefined,
|
||||
enabled,
|
||||
status: status || "available",
|
||||
};
|
||||
}
|
||||
|
||||
function normalizeModelList(value: unknown): ModelCapabilityOption[] {
|
||||
return Array.isArray(value)
|
||||
? value.map(normalizeModelOption).filter((item): item is ModelCapabilityOption => Boolean(item))
|
||||
: [];
|
||||
}
|
||||
|
||||
function createFallbackCapabilities(): WebModelCapabilities {
|
||||
return {
|
||||
source: "fallback",
|
||||
imageModels: [],
|
||||
videoModels: [],
|
||||
chatModels: [],
|
||||
};
|
||||
}
|
||||
|
||||
let modelCapabilitiesRouteMissing = false;
|
||||
|
||||
export const modelCapabilitiesClient = {
|
||||
async get(name = "web-model-capabilities"): Promise<WebModelCapabilities> {
|
||||
if (import.meta.env.DEV && name === "web-model-capabilities") return createFallbackCapabilities();
|
||||
if (modelCapabilitiesRouteMissing) return createFallbackCapabilities();
|
||||
|
||||
let payload: unknown;
|
||||
try {
|
||||
payload = await serverRequest<unknown>(`config/profile?name=${encodeURIComponent(name)}`);
|
||||
} catch (error) {
|
||||
if (isOptionalApiRouteMissing(error)) {
|
||||
modelCapabilitiesRouteMissing = true;
|
||||
return createFallbackCapabilities();
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
|
||||
const raw = isRecord(payload) && isRecord(payload.config) ? payload.config : payload;
|
||||
const config = isRecord(raw) ? raw : {};
|
||||
const models = isRecord(config.models) ? config.models : {};
|
||||
|
||||
return {
|
||||
source: "server",
|
||||
imageModels: normalizeModelList(config.imageModels ?? config.image_models ?? models.image),
|
||||
videoModels: normalizeModelList(config.videoModels ?? config.video_models ?? models.video),
|
||||
chatModels: normalizeModelList(config.chatModels ?? config.chat_models ?? models.chat ?? models.agent ?? models.text),
|
||||
updatedAt: toStringValue((payload as { updatedAt?: unknown; updated_at?: unknown })?.updatedAt ?? (payload as { updated_at?: unknown })?.updated_at),
|
||||
};
|
||||
},
|
||||
};
|
||||
Reference in New Issue
Block a user