Files
OmniRoute/open-sse/config/providerPluginManifest.ts
Ankit e61b75f007 fix(config): externalize ws for copilot-m365-web executor (#6098, closes #6062)
Externalize ws / bufferutil / utf-8-validate in serverExternalPackages so the copilot-m365-web WebSocket masking path works at runtime (bundling ws → TypeError: b.mask is not a function → 80s chat timeout). Regression guard in next-config.test.ts.

Co-authored-by: diegosouzapw <diegosouza.pw@gmail.com>
2026-07-03 16:36:35 -03:00

187 lines
5.2 KiB
TypeScript

import type { RegistryEntry, RegistryModel } from "./providers/shared.ts";
export type ProviderPluginCapability =
| "apikey"
| "custom-executor"
| "oauth"
| "passthrough-models"
| "responses"
| "sidecar-candidate";
export interface ProviderPluginModel {
id: string;
name: string;
contextLength?: number;
maxOutputTokens?: number;
toolCalling?: boolean;
supportsReasoning?: boolean;
supportsVision?: boolean;
unsupportedParams?: readonly string[];
targetFormat?: string;
}
export interface ProviderPluginManifestEntry {
id: string;
alias?: string;
format: string;
executor: string;
auth: {
type: string;
header: string;
prefix?: string;
};
endpoints: {
baseUrl?: string;
baseUrls?: string[];
responsesBaseUrl?: string;
chatPath?: string;
modelsUrl?: string;
};
capabilities: ProviderPluginCapability[];
passthroughModels: boolean;
defaultContextLength?: number;
timeoutMs?: number;
models: ProviderPluginModel[];
sidecar: {
eligible: boolean;
reasons: string[];
};
}
export interface ProviderPluginManifest {
schemaVersion: 1;
generatedFrom: "open-sse/config/providers";
providers: ProviderPluginManifestEntry[];
}
const SIDECAR_COMPATIBLE_EXECUTORS = new Set(["default"]);
function compactObject<T extends Record<string, unknown>>(value: T): Partial<T> {
return Object.fromEntries(
Object.entries(value).filter(([, entryValue]) => entryValue !== undefined),
) as Partial<T>;
}
function mapModel(model: RegistryModel): ProviderPluginModel {
return compactObject({
id: model.id,
name: model.name,
contextLength: model.contextLength,
maxOutputTokens: model.maxOutputTokens,
toolCalling: model.toolCalling,
supportsReasoning: model.supportsReasoning,
supportsVision: model.supportsVision,
unsupportedParams: model.unsupportedParams,
targetFormat: model.targetFormat,
}) as ProviderPluginModel;
}
function sidecarEligibility(entry: RegistryEntry): { eligible: boolean; reasons: string[] } {
const reasons: string[] = [];
if (!SIDECAR_COMPATIBLE_EXECUTORS.has(entry.executor)) {
reasons.push(`custom executor: ${entry.executor}`);
}
if (entry.authType !== "apikey" && entry.authType !== "optional" && entry.authType !== "none") {
reasons.push(`auth type requires TS handling: ${entry.authType}`);
}
if (!entry.baseUrl && !entry.baseUrls?.length && !entry.responsesBaseUrl) {
reasons.push("no static upstream endpoint");
}
if (typeof entry.urlBuilder === "function") {
reasons.push("dynamic URL builder");
}
if (entry.oauth) {
reasons.push("oauth metadata");
}
if (entry.poolConfig) {
reasons.push("session pool config");
}
return {
eligible: reasons.length === 0,
reasons,
};
}
function capabilitiesFor(entry: RegistryEntry, eligible: boolean): ProviderPluginCapability[] {
const capabilities = new Set<ProviderPluginCapability>();
if (entry.authType === "apikey" || entry.authType === "optional") {
capabilities.add("apikey");
}
if (entry.authType === "oauth" || entry.oauth) {
capabilities.add("oauth");
}
if (entry.responsesBaseUrl) {
capabilities.add("responses");
}
if (entry.passthroughModels) {
capabilities.add("passthrough-models");
}
if (entry.executor !== "default") {
capabilities.add("custom-executor");
}
if (eligible) {
capabilities.add("sidecar-candidate");
}
return [...capabilities].sort();
}
export function createProviderPluginManifestEntry(
entry: RegistryEntry,
): ProviderPluginManifestEntry {
const sidecar = sidecarEligibility(entry);
return {
id: entry.id,
...(entry.alias ? { alias: entry.alias } : {}),
format: entry.format,
executor: entry.executor,
auth: compactObject({
type: entry.authType,
header: entry.authHeader,
prefix: entry.authPrefix,
}) as ProviderPluginManifestEntry["auth"],
endpoints: compactObject({
baseUrl: entry.baseUrl,
baseUrls: entry.baseUrls,
responsesBaseUrl: entry.responsesBaseUrl,
chatPath: entry.chatPath,
modelsUrl: entry.modelsUrl,
}) as ProviderPluginManifestEntry["endpoints"],
capabilities: capabilitiesFor(entry, sidecar.eligible),
passthroughModels: entry.passthroughModels === true,
...(typeof entry.defaultContextLength === "number"
? { defaultContextLength: entry.defaultContextLength }
: {}),
...(typeof entry.timeoutMs === "number" ? { timeoutMs: entry.timeoutMs } : {}),
models: (entry.models ?? []).map(mapModel),
sidecar,
};
}
export function generateProviderPluginManifestFromRegistry(
registry: Record<string, RegistryEntry>,
): ProviderPluginManifest {
return {
schemaVersion: 1,
generatedFrom: "open-sse/config/providers",
providers: Object.values(registry)
.map(createProviderPluginManifestEntry)
.sort((a, b) => a.id.localeCompare(b.id)),
};
}
export function getProviderPluginManifestEntryFromRegistry(
registry: Record<string, RegistryEntry>,
provider: string,
): ProviderPluginManifestEntry | null {
const entry =
registry[provider] ||
Object.values(registry).find((candidate) => candidate.alias === provider);
return entry ? createProviderPluginManifestEntry(entry) : null;
}