mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-07-31 04:12:10 +03:00
perf: extract optimizations from perf/cpu-optimization-chat-completions
Extract 3 high-value CPU/RAM optimizations from perf branch: 1. estimateSizeFast() — fast object-tree size estimator replacing JSON.stringify().length in isSmallEnoughForSemanticCache(). Walks object tree with a stack, zero string allocation, early exit at 256KB. 2. Consolidate settings reads — move getCachedSettings() to a single early read in handleChatCore(), eliminating a redundant second read 200 lines later. Also removes the isDetailedLoggingEnabled() wrapper call (reads settings internally) in favor of direct field check. 3. Registry Proxy→direct export — convert 8 registries from lazy Proxy+getOrCreate pattern to simple exported const objects. Eliminates Proxy trap overhead on every provider property access during routing. Affected: audio, embedding, image, moderation, music, rerank, search, video registries (-451 lines of Proxy boilerplate). These changes are independent of the CPU leak fix (limiter eviction) and complement it by reducing per-request CPU overhead.
This commit is contained in:
@@ -22,11 +22,7 @@ export interface AudioProvider {
|
||||
models: AudioModel[];
|
||||
}
|
||||
|
||||
let _AUDIO_TRANSCRIPTION_PROVIDERS: Record<string, AudioProvider> | null = null;
|
||||
|
||||
function getOrCreateTranscriptionProviders(): Record<string, AudioProvider> {
|
||||
if (!_AUDIO_TRANSCRIPTION_PROVIDERS) {
|
||||
_AUDIO_TRANSCRIPTION_PROVIDERS = {
|
||||
export const AUDIO_TRANSCRIPTION_PROVIDERS: Record<string, AudioProvider> = {
|
||||
openai: {
|
||||
id: "openai",
|
||||
baseUrl: "https://api.openai.com/v1/audio/transcriptions",
|
||||
@@ -149,56 +145,9 @@ function getOrCreateTranscriptionProviders(): Record<string, AudioProvider> {
|
||||
{ id: "elevenlabs/audio-isolation", name: "ElevenLabs Audio Isolation" },
|
||||
],
|
||||
},
|
||||
};
|
||||
}
|
||||
return _AUDIO_TRANSCRIPTION_PROVIDERS;
|
||||
}
|
||||
};
|
||||
|
||||
export const AUDIO_TRANSCRIPTION_PROVIDERS: Record<string, AudioProvider> = new Proxy({} as Record<string, AudioProvider>, {
|
||||
get(target, key: string) {
|
||||
if (key in target) {
|
||||
return target[key];
|
||||
}
|
||||
return getOrCreateTranscriptionProviders()[key];
|
||||
},
|
||||
set(target, key: string, value) {
|
||||
target[key] = value;
|
||||
getOrCreateTranscriptionProviders()[key] = value;
|
||||
return true;
|
||||
},
|
||||
deleteProperty(target, key: string) {
|
||||
delete target[key];
|
||||
delete getOrCreateTranscriptionProviders()[key];
|
||||
return true;
|
||||
},
|
||||
ownKeys(target) {
|
||||
const targetKeys = Reflect.ownKeys(target);
|
||||
const registryKeys = Reflect.ownKeys(getOrCreateTranscriptionProviders());
|
||||
return Array.from(new Set([...targetKeys, ...registryKeys]));
|
||||
},
|
||||
has(target, key) {
|
||||
return key in target || key in getOrCreateTranscriptionProviders();
|
||||
},
|
||||
getOwnPropertyDescriptor(target, key) {
|
||||
if (key in target) {
|
||||
return Reflect.getOwnPropertyDescriptor(target, key);
|
||||
}
|
||||
if (key in getOrCreateTranscriptionProviders()) {
|
||||
return { configurable: true, enumerable: true, value: getOrCreateTranscriptionProviders()[key as string] };
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
});
|
||||
|
||||
export function getTranscriptionProviders(): Record<string, AudioProvider> {
|
||||
return AUDIO_TRANSCRIPTION_PROVIDERS;
|
||||
}
|
||||
|
||||
let _AUDIO_SPEECH_PROVIDERS: Record<string, AudioProvider> | null = null;
|
||||
|
||||
function getOrCreateSpeechProviders(): Record<string, AudioProvider> {
|
||||
if (!_AUDIO_SPEECH_PROVIDERS) {
|
||||
_AUDIO_SPEECH_PROVIDERS = {
|
||||
export const AUDIO_SPEECH_PROVIDERS: Record<string, AudioProvider> = {
|
||||
openai: {
|
||||
id: "openai",
|
||||
baseUrl: "https://api.openai.com/v1/audio/speech",
|
||||
@@ -418,57 +367,22 @@ function getOrCreateSpeechProviders(): Record<string, AudioProvider> {
|
||||
{ id: "mimo-v2.5-tts-voiceclone", name: "MiMo V2.5 Voice Clone" },
|
||||
],
|
||||
},
|
||||
};
|
||||
}
|
||||
return _AUDIO_SPEECH_PROVIDERS;
|
||||
}
|
||||
|
||||
export const AUDIO_SPEECH_PROVIDERS: Record<string, AudioProvider> = new Proxy({} as Record<string, AudioProvider>, {
|
||||
get(target, key: string) {
|
||||
if (key in target) {
|
||||
return target[key];
|
||||
}
|
||||
return getOrCreateSpeechProviders()[key];
|
||||
},
|
||||
set(target, key: string, value) {
|
||||
target[key] = value;
|
||||
getOrCreateSpeechProviders()[key] = value;
|
||||
return true;
|
||||
},
|
||||
deleteProperty(target, key: string) {
|
||||
delete target[key];
|
||||
delete getOrCreateSpeechProviders()[key];
|
||||
return true;
|
||||
},
|
||||
ownKeys(target) {
|
||||
const targetKeys = Reflect.ownKeys(target);
|
||||
const registryKeys = Reflect.ownKeys(getOrCreateSpeechProviders());
|
||||
return Array.from(new Set([...targetKeys, ...registryKeys]));
|
||||
},
|
||||
has(target, key) {
|
||||
return key in target || key in getOrCreateSpeechProviders();
|
||||
},
|
||||
getOwnPropertyDescriptor(target, key) {
|
||||
if (key in target) {
|
||||
return Reflect.getOwnPropertyDescriptor(target, key);
|
||||
}
|
||||
if (key in getOrCreateSpeechProviders()) {
|
||||
return { configurable: true, enumerable: true, value: getOrCreateSpeechProviders()[key as string] };
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
});
|
||||
|
||||
export function getSpeechProviders(): Record<string, AudioProvider> {
|
||||
return AUDIO_SPEECH_PROVIDERS;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Get transcription provider config by ID
|
||||
*/
|
||||
export function getTranscriptionProvider(providerId: string): AudioProvider | null {
|
||||
return AUDIO_TRANSCRIPTION_PROVIDERS[providerId] || null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get speech provider config by ID
|
||||
*/
|
||||
export function getSpeechProvider(providerId: string): AudioProvider | null {
|
||||
return AUDIO_SPEECH_PROVIDERS[providerId] || null;
|
||||
}
|
||||
|
||||
export interface ProviderNodeRow {
|
||||
prefix: string;
|
||||
name: string;
|
||||
|
||||
@@ -45,11 +45,7 @@ export function buildDynamicEmbeddingProvider(node: EmbeddingProviderNodeRow): E
|
||||
};
|
||||
}
|
||||
|
||||
let _EMBEDDING_PROVIDERS: Record<string, EmbeddingProvider> | null = null;
|
||||
|
||||
function getOrCreateEmbeddingProviders(): Record<string, EmbeddingProvider> {
|
||||
if (!_EMBEDDING_PROVIDERS) {
|
||||
_EMBEDDING_PROVIDERS = {
|
||||
export const EMBEDDING_PROVIDERS: Record<string, EmbeddingProvider> = {
|
||||
cohere: {
|
||||
id: "cohere",
|
||||
baseUrl: "https://api.cohere.com/v2/embed",
|
||||
@@ -237,50 +233,7 @@ function getOrCreateEmbeddingProviders(): Record<string, EmbeddingProvider> {
|
||||
{ id: "jina-colbert-v2", name: "Jina ColBERT v2", dimensions: 128 },
|
||||
],
|
||||
},
|
||||
};
|
||||
}
|
||||
return _EMBEDDING_PROVIDERS;
|
||||
}
|
||||
|
||||
export const EMBEDDING_PROVIDERS: Record<string, EmbeddingProvider> = new Proxy({} as Record<string, EmbeddingProvider>, {
|
||||
get(target, key: string) {
|
||||
if (key in target) {
|
||||
return target[key];
|
||||
}
|
||||
return getOrCreateEmbeddingProviders()[key];
|
||||
},
|
||||
set(target, key: string, value) {
|
||||
target[key] = value;
|
||||
getOrCreateEmbeddingProviders()[key] = value;
|
||||
return true;
|
||||
},
|
||||
deleteProperty(target, key: string) {
|
||||
delete target[key];
|
||||
delete getOrCreateEmbeddingProviders()[key];
|
||||
return true;
|
||||
},
|
||||
ownKeys(target) {
|
||||
const targetKeys = Reflect.ownKeys(target);
|
||||
const registryKeys = Reflect.ownKeys(getOrCreateEmbeddingProviders());
|
||||
return Array.from(new Set([...targetKeys, ...registryKeys]));
|
||||
},
|
||||
has(target, key) {
|
||||
return key in target || key in getOrCreateEmbeddingProviders();
|
||||
},
|
||||
getOwnPropertyDescriptor(target, key) {
|
||||
if (key in target) {
|
||||
return Reflect.getOwnPropertyDescriptor(target, key);
|
||||
}
|
||||
if (key in getOrCreateEmbeddingProviders()) {
|
||||
return { configurable: true, enumerable: true, value: getOrCreateEmbeddingProviders()[key as string] };
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
});
|
||||
|
||||
export function getEmbeddingProviders(): Record<string, EmbeddingProvider> {
|
||||
return EMBEDDING_PROVIDERS;
|
||||
}
|
||||
};
|
||||
|
||||
const EMBEDDING_PROVIDER_ALIASES: Record<string, string> = {
|
||||
jina: "jina-ai",
|
||||
|
||||
@@ -112,11 +112,7 @@ function findImageModelConfig(providerId, modelId) {
|
||||
return provider.models.find((model) => model.id === modelId) || null;
|
||||
}
|
||||
|
||||
let _IMAGE_PROVIDERS: Record<string, ImageProviderConfig> | null = null;
|
||||
|
||||
function getOrCreateImageProviders(): Record<string, ImageProviderConfig> {
|
||||
if (!_IMAGE_PROVIDERS) {
|
||||
_IMAGE_PROVIDERS = {
|
||||
export const IMAGE_PROVIDERS: Record<string, ImageProviderConfig> = {
|
||||
openai: {
|
||||
id: "openai",
|
||||
baseUrl: "https://api.openai.com/v1/images/generations",
|
||||
@@ -544,53 +540,14 @@ function getOrCreateImageProviders(): Record<string, ImageProviderConfig> {
|
||||
supportedSizes: ["1024x1024", "1024x1280", "1280x1024"],
|
||||
},
|
||||
};
|
||||
}
|
||||
return _IMAGE_PROVIDERS;
|
||||
}
|
||||
|
||||
export function getImageProviders(): Record<string, ImageProviderConfig> {
|
||||
return IMAGE_PROVIDERS;
|
||||
}
|
||||
|
||||
export const IMAGE_PROVIDERS = new Proxy({} as Record<string, ImageProviderConfig>, {
|
||||
get(target, key: string) {
|
||||
if (key in target) {
|
||||
return target[key];
|
||||
}
|
||||
return getOrCreateImageProviders()[key];
|
||||
},
|
||||
set(target, key: string, value) {
|
||||
target[key] = value;
|
||||
getOrCreateImageProviders()[key] = value;
|
||||
return true;
|
||||
},
|
||||
deleteProperty(target, key: string) {
|
||||
delete target[key];
|
||||
delete getOrCreateImageProviders()[key];
|
||||
return true;
|
||||
},
|
||||
ownKeys(target) {
|
||||
const targetKeys = Reflect.ownKeys(target);
|
||||
const registryKeys = Reflect.ownKeys(getOrCreateImageProviders());
|
||||
return Array.from(new Set([...targetKeys, ...registryKeys]));
|
||||
},
|
||||
has(target, key) {
|
||||
return key in target || key in getOrCreateImageProviders();
|
||||
},
|
||||
getOwnPropertyDescriptor(target, key) {
|
||||
if (key in target) {
|
||||
return Reflect.getOwnPropertyDescriptor(target, key);
|
||||
}
|
||||
if (key in getOrCreateImageProviders()) {
|
||||
return { configurable: true, enumerable: true, value: getOrCreateImageProviders()[key as string] };
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* Get image provider config by ID
|
||||
*/
|
||||
export function getImageProvider(providerId) {
|
||||
return IMAGE_PROVIDERS[providerId] || null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse image model string (format: "provider/model")
|
||||
* Returns { provider, model }
|
||||
|
||||
@@ -5,11 +5,7 @@
|
||||
* Follows OpenAI's moderation API format.
|
||||
*/
|
||||
|
||||
let _MODERATION_PROVIDERS: Record<string, any> | null = null;
|
||||
|
||||
function getOrCreateModerationProviders(): Record<string, any> {
|
||||
if (!_MODERATION_PROVIDERS) {
|
||||
_MODERATION_PROVIDERS = {
|
||||
export const MODERATION_PROVIDERS = {
|
||||
openai: {
|
||||
id: "openai",
|
||||
baseUrl: "https://api.openai.com/v1/moderations",
|
||||
@@ -20,55 +16,18 @@ function getOrCreateModerationProviders(): Record<string, any> {
|
||||
{ id: "text-moderation-latest", name: "Text Moderation Latest" },
|
||||
],
|
||||
},
|
||||
};
|
||||
}
|
||||
return _MODERATION_PROVIDERS;
|
||||
}
|
||||
|
||||
export const MODERATION_PROVIDERS = new Proxy({} as Record<string, any>, {
|
||||
get(target, key: string) {
|
||||
if (key in target) {
|
||||
return target[key];
|
||||
}
|
||||
return getOrCreateModerationProviders()[key];
|
||||
},
|
||||
set(target, key: string, value) {
|
||||
target[key] = value;
|
||||
getOrCreateModerationProviders()[key] = value;
|
||||
return true;
|
||||
},
|
||||
deleteProperty(target, key: string) {
|
||||
delete target[key];
|
||||
delete getOrCreateModerationProviders()[key];
|
||||
return true;
|
||||
},
|
||||
ownKeys(target) {
|
||||
const targetKeys = Reflect.ownKeys(target);
|
||||
const registryKeys = Reflect.ownKeys(getOrCreateModerationProviders());
|
||||
return Array.from(new Set([...targetKeys, ...registryKeys]));
|
||||
},
|
||||
has(target, key) {
|
||||
return key in target || key in getOrCreateModerationProviders();
|
||||
},
|
||||
getOwnPropertyDescriptor(target, key) {
|
||||
if (key in target) {
|
||||
return Reflect.getOwnPropertyDescriptor(target, key);
|
||||
}
|
||||
if (key in getOrCreateModerationProviders()) {
|
||||
return { configurable: true, enumerable: true, value: getOrCreateModerationProviders()[key as string] };
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
});
|
||||
|
||||
export function getModerationProviders(): Record<string, any> {
|
||||
return MODERATION_PROVIDERS;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Get moderation provider config by ID
|
||||
*/
|
||||
export function getModerationProvider(providerId) {
|
||||
return MODERATION_PROVIDERS[providerId] || null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse moderation model string
|
||||
*/
|
||||
export function parseModerationModel(modelStr) {
|
||||
if (!modelStr) return { provider: null, model: null };
|
||||
|
||||
@@ -87,6 +46,9 @@ export function parseModerationModel(modelStr) {
|
||||
return { provider: null, model: modelStr };
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all moderation models as a flat list
|
||||
*/
|
||||
export function getAllModerationModels() {
|
||||
const models = [];
|
||||
for (const [providerId, config] of Object.entries(MODERATION_PROVIDERS)) {
|
||||
|
||||
@@ -23,11 +23,7 @@ interface MusicProvider {
|
||||
models: MusicModel[];
|
||||
}
|
||||
|
||||
let _MUSIC_PROVIDERS: Record<string, MusicProvider> | null = null;
|
||||
|
||||
function getOrCreateMusicProviders(): Record<string, MusicProvider> {
|
||||
if (!_MUSIC_PROVIDERS) {
|
||||
_MUSIC_PROVIDERS = {
|
||||
export const MUSIC_PROVIDERS: Record<string, MusicProvider> = {
|
||||
kie: {
|
||||
id: "kie",
|
||||
baseUrl: "https://api.kie.ai",
|
||||
@@ -86,59 +82,25 @@ function getOrCreateMusicProviders(): Record<string, MusicProvider> {
|
||||
{ id: "musicgen-medium", name: "MusicGen Medium" },
|
||||
],
|
||||
},
|
||||
};
|
||||
}
|
||||
return _MUSIC_PROVIDERS;
|
||||
}
|
||||
|
||||
export const MUSIC_PROVIDERS: Record<string, MusicProvider> = new Proxy({} as Record<string, MusicProvider>, {
|
||||
get(target, key: string) {
|
||||
if (key in target) {
|
||||
return target[key];
|
||||
}
|
||||
return getOrCreateMusicProviders()[key];
|
||||
},
|
||||
set(target, key: string, value) {
|
||||
target[key] = value;
|
||||
getOrCreateMusicProviders()[key] = value;
|
||||
return true;
|
||||
},
|
||||
deleteProperty(target, key: string) {
|
||||
delete target[key];
|
||||
delete getOrCreateMusicProviders()[key];
|
||||
return true;
|
||||
},
|
||||
ownKeys(target) {
|
||||
const targetKeys = Reflect.ownKeys(target);
|
||||
const registryKeys = Reflect.ownKeys(getOrCreateMusicProviders());
|
||||
return Array.from(new Set([...targetKeys, ...registryKeys]));
|
||||
},
|
||||
has(target, key) {
|
||||
return key in target || key in getOrCreateMusicProviders();
|
||||
},
|
||||
getOwnPropertyDescriptor(target, key) {
|
||||
if (key in target) {
|
||||
return Reflect.getOwnPropertyDescriptor(target, key);
|
||||
}
|
||||
if (key in getOrCreateMusicProviders()) {
|
||||
return { configurable: true, enumerable: true, value: getOrCreateMusicProviders()[key as string] };
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
});
|
||||
|
||||
export function getMusicProviders(): Record<string, MusicProvider> {
|
||||
return MUSIC_PROVIDERS;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Get music provider config by ID
|
||||
*/
|
||||
export function getMusicProvider(providerId: string): MusicProvider | null {
|
||||
return MUSIC_PROVIDERS[providerId] || null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse music model string (format: "provider/model" or just "model")
|
||||
*/
|
||||
export function parseMusicModel(modelStr: string | null) {
|
||||
return parseModelFromRegistry(modelStr, MUSIC_PROVIDERS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all music models as a flat list
|
||||
*/
|
||||
export function getAllMusicModels() {
|
||||
return getAllModelsFromRegistry(MUSIC_PROVIDERS);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,11 +8,7 @@
|
||||
* keyed by provider ID (e.g. "cohere", "together").
|
||||
*/
|
||||
|
||||
let _RERANK_PROVIDERS: Record<string, any> | null = null;
|
||||
|
||||
function getOrCreateRerankProviders(): Record<string, any> {
|
||||
if (!_RERANK_PROVIDERS) {
|
||||
_RERANK_PROVIDERS = {
|
||||
export const RERANK_PROVIDERS = {
|
||||
cohere: {
|
||||
id: "cohere",
|
||||
baseUrl: "https://api.cohere.com/v2/rerank",
|
||||
@@ -75,50 +71,7 @@ function getOrCreateRerankProviders(): Record<string, any> {
|
||||
{ id: "jina-reranker-m0", name: "Jina Reranker m0" },
|
||||
],
|
||||
},
|
||||
};
|
||||
}
|
||||
return _RERANK_PROVIDERS;
|
||||
}
|
||||
|
||||
export const RERANK_PROVIDERS = new Proxy({} as Record<string, any>, {
|
||||
get(target, key: string) {
|
||||
if (key in target) {
|
||||
return target[key];
|
||||
}
|
||||
return getOrCreateRerankProviders()[key];
|
||||
},
|
||||
set(target, key: string, value) {
|
||||
target[key] = value;
|
||||
getOrCreateRerankProviders()[key] = value;
|
||||
return true;
|
||||
},
|
||||
deleteProperty(target, key: string) {
|
||||
delete target[key];
|
||||
delete getOrCreateRerankProviders()[key];
|
||||
return true;
|
||||
},
|
||||
ownKeys(target) {
|
||||
const targetKeys = Reflect.ownKeys(target);
|
||||
const registryKeys = Reflect.ownKeys(getOrCreateRerankProviders());
|
||||
return Array.from(new Set([...targetKeys, ...registryKeys]));
|
||||
},
|
||||
has(target, key) {
|
||||
return key in target || key in getOrCreateRerankProviders();
|
||||
},
|
||||
getOwnPropertyDescriptor(target, key) {
|
||||
if (key in target) {
|
||||
return Reflect.getOwnPropertyDescriptor(target, key);
|
||||
}
|
||||
if (key in getOrCreateRerankProviders()) {
|
||||
return { configurable: true, enumerable: true, value: getOrCreateRerankProviders()[key as string] };
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
});
|
||||
|
||||
export function getRerankProviders(): Record<string, any> {
|
||||
return RERANK_PROVIDERS;
|
||||
}
|
||||
};
|
||||
|
||||
const RERANK_PROVIDER_ALIASES = {
|
||||
jina: "jina-ai",
|
||||
|
||||
@@ -26,11 +26,7 @@ export interface SearchProviderConfig {
|
||||
cacheTTLMs: number;
|
||||
}
|
||||
|
||||
let _SEARCH_PROVIDERS: Record<string, SearchProviderConfig> | null = null;
|
||||
|
||||
function getOrCreateSearchProviders(): Record<string, SearchProviderConfig> {
|
||||
if (!_SEARCH_PROVIDERS) {
|
||||
_SEARCH_PROVIDERS = {
|
||||
export const SEARCH_PROVIDERS: Record<string, SearchProviderConfig> = {
|
||||
"serper-search": {
|
||||
id: "serper-search",
|
||||
name: "Serper Search",
|
||||
@@ -222,52 +218,14 @@ function getOrCreateSearchProviders(): Record<string, SearchProviderConfig> {
|
||||
timeoutMs: 10_000,
|
||||
cacheTTLMs: 5 * 60 * 1000,
|
||||
},
|
||||
};
|
||||
}
|
||||
return _SEARCH_PROVIDERS;
|
||||
}
|
||||
};
|
||||
|
||||
export const SEARCH_PROVIDERS: Record<string, SearchProviderConfig> = new Proxy({} as Record<string, SearchProviderConfig>, {
|
||||
get(target, key: string) {
|
||||
if (key in target) {
|
||||
return target[key];
|
||||
}
|
||||
return getOrCreateSearchProviders()[key];
|
||||
},
|
||||
set(target, key: string, value) {
|
||||
target[key] = value;
|
||||
getOrCreateSearchProviders()[key] = value;
|
||||
return true;
|
||||
},
|
||||
deleteProperty(target, key: string) {
|
||||
delete target[key];
|
||||
delete getOrCreateSearchProviders()[key];
|
||||
return true;
|
||||
},
|
||||
ownKeys(target) {
|
||||
const targetKeys = Reflect.ownKeys(target);
|
||||
const registryKeys = Reflect.ownKeys(getOrCreateSearchProviders());
|
||||
return Array.from(new Set([...targetKeys, ...registryKeys]));
|
||||
},
|
||||
has(target, key) {
|
||||
return key in target || key in getOrCreateSearchProviders();
|
||||
},
|
||||
getOwnPropertyDescriptor(target, key) {
|
||||
if (key in target) {
|
||||
return Reflect.getOwnPropertyDescriptor(target, key);
|
||||
}
|
||||
if (key in getOrCreateSearchProviders()) {
|
||||
return { configurable: true, enumerable: true, value: getOrCreateSearchProviders()[key as string] };
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
});
|
||||
|
||||
export function getSearchProviders(): Record<string, SearchProviderConfig> {
|
||||
return SEARCH_PROVIDERS;
|
||||
}
|
||||
|
||||
export const SEARCH_CREDENTIAL_FALLBACKS: Record<string, string> = { "perplexity-search": "perplexity",
|
||||
/**
|
||||
* Credential fallback mapping — search providers that can reuse credentials
|
||||
* from a related provider (e.g., perplexity-search uses the same API key as perplexity chat).
|
||||
*/
|
||||
export const SEARCH_CREDENTIAL_FALLBACKS: Record<string, string> = {
|
||||
"perplexity-search": "perplexity",
|
||||
"ollama-search": "ollama-cloud",
|
||||
"zai-search": "zai",
|
||||
};
|
||||
|
||||
@@ -24,11 +24,7 @@ interface VideoProvider {
|
||||
models: VideoModel[];
|
||||
}
|
||||
|
||||
let _VIDEO_PROVIDERS: Record<string, VideoProvider> | null = null;
|
||||
|
||||
function getOrCreateVideoProviders(): Record<string, VideoProvider> {
|
||||
if (!_VIDEO_PROVIDERS) {
|
||||
_VIDEO_PROVIDERS = {
|
||||
export const VIDEO_PROVIDERS: Record<string, VideoProvider> = {
|
||||
kie: {
|
||||
id: "kie",
|
||||
baseUrl: "https://api.kie.ai",
|
||||
@@ -152,59 +148,25 @@ function getOrCreateVideoProviders(): Record<string, VideoProvider> {
|
||||
format: "runwayml",
|
||||
models: RUNWAYML_SUPPORTED_VIDEO_MODELS,
|
||||
},
|
||||
};
|
||||
}
|
||||
return _VIDEO_PROVIDERS;
|
||||
}
|
||||
|
||||
export const VIDEO_PROVIDERS: Record<string, VideoProvider> = new Proxy({} as Record<string, VideoProvider>, {
|
||||
get(target, key: string) {
|
||||
if (key in target) {
|
||||
return target[key];
|
||||
}
|
||||
return getOrCreateVideoProviders()[key];
|
||||
},
|
||||
set(target, key: string, value) {
|
||||
target[key] = value;
|
||||
getOrCreateVideoProviders()[key] = value;
|
||||
return true;
|
||||
},
|
||||
deleteProperty(target, key: string) {
|
||||
delete target[key];
|
||||
delete getOrCreateVideoProviders()[key];
|
||||
return true;
|
||||
},
|
||||
ownKeys(target) {
|
||||
const targetKeys = Reflect.ownKeys(target);
|
||||
const registryKeys = Reflect.ownKeys(getOrCreateVideoProviders());
|
||||
return Array.from(new Set([...targetKeys, ...registryKeys]));
|
||||
},
|
||||
has(target, key) {
|
||||
return key in target || key in getOrCreateVideoProviders();
|
||||
},
|
||||
getOwnPropertyDescriptor(target, key) {
|
||||
if (key in target) {
|
||||
return Reflect.getOwnPropertyDescriptor(target, key);
|
||||
}
|
||||
if (key in getOrCreateVideoProviders()) {
|
||||
return { configurable: true, enumerable: true, value: getOrCreateVideoProviders()[key as string] };
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
});
|
||||
|
||||
export function getVideoProviders(): Record<string, VideoProvider> {
|
||||
return VIDEO_PROVIDERS;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Get video provider config by ID
|
||||
*/
|
||||
export function getVideoProvider(providerId: string): VideoProvider | null {
|
||||
return VIDEO_PROVIDERS[providerId] || null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse video model string (format: "provider/model" or just "model")
|
||||
*/
|
||||
export function parseVideoModel(modelStr: string | null) {
|
||||
return parseModelFromRegistry(modelStr, VIDEO_PROVIDERS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all video models as a flat list
|
||||
*/
|
||||
export function getAllVideoModels() {
|
||||
return getAllModelsFromRegistry(VIDEO_PROVIDERS);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ import {
|
||||
connectionHasExtraKeys,
|
||||
type KeyHealth,
|
||||
} from "../services/apiKeyRotator.ts";
|
||||
import { isDetailedLoggingEnabled } from "@/lib/db/detailedLogs";
|
||||
|
||||
import {
|
||||
getCallLogPipelineCaptureStreamChunks,
|
||||
getChatLogTextLimit,
|
||||
@@ -277,12 +277,32 @@ function cloneBoundedChatLogPayload(value: unknown, depth = 0): unknown {
|
||||
return result;
|
||||
}
|
||||
|
||||
function isSmallEnoughForSemanticCache(value: unknown): boolean {
|
||||
try {
|
||||
return JSON.stringify(value).length <= 256 * 1024;
|
||||
} catch {
|
||||
return false;
|
||||
/** Fast size estimator — walks object tree without JSON.stringify */
|
||||
function estimateSizeFast(value: unknown): number {
|
||||
let bytes = 0;
|
||||
const stack: unknown[] = [value];
|
||||
while (stack.length > 0) {
|
||||
const v = stack.pop();
|
||||
if (v === null || v === undefined) continue;
|
||||
if (typeof v === "string") {
|
||||
bytes += v.length;
|
||||
if (bytes > 262144) return bytes;
|
||||
} else if (typeof v === "number") bytes += 8;
|
||||
else if (typeof v === "boolean") bytes += 4;
|
||||
else if (typeof v === "object") {
|
||||
if (Array.isArray(v)) {
|
||||
for (let i = 0; i < v.length; i++) stack.push(v[i]);
|
||||
} else {
|
||||
const vals = Object.values(v);
|
||||
for (let i = 0; i < vals.length; i++) stack.push(vals[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
function isSmallEnoughForSemanticCache(value: unknown): boolean {
|
||||
return estimateSizeFast(value) <= 256 * 1024;
|
||||
}
|
||||
|
||||
function extractMemoryTextFromResponse(
|
||||
@@ -1915,7 +1935,13 @@ export async function handleChatCore({
|
||||
);
|
||||
}
|
||||
const noLogEnabled = apiKeyInfo?.noLog === true;
|
||||
const detailedLoggingEnabled = !noLogEnabled && (await isDetailedLoggingEnabled());
|
||||
// Consolidate settings reads — fetch once, reuse throughout the request
|
||||
const settings = cachedSettings ?? (await getCachedSettings());
|
||||
const detailedLoggingEnabled =
|
||||
!noLogEnabled &&
|
||||
(settings.call_log_pipeline_enabled === true ||
|
||||
settings.call_log_pipeline_enabled === "1" ||
|
||||
settings.call_log_pipeline_enabled === "true");
|
||||
const capturePipelineStreamChunks =
|
||||
detailedLoggingEnabled && getCallLogPipelineCaptureStreamChunks();
|
||||
const skillRequestId = generateRequestId();
|
||||
@@ -2134,7 +2160,6 @@ export async function handleChatCore({
|
||||
nativeCodexPassthrough && isCompactResponsesEndpoint(endpointPath)
|
||||
? false
|
||||
: resolveStreamFlag(body?.stream, acceptHeader, sourceFormat);
|
||||
const settings = cachedSettings ?? (await getCachedSettings());
|
||||
credentials = applyCodexGlobalFastServiceTier(provider, credentials, settings, {
|
||||
model: requestedModel,
|
||||
body: body && typeof body === "object" ? (body as Record<string, unknown>) : null,
|
||||
|
||||
Reference in New Issue
Block a user