Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion apps/api/dev/checkModelCapabilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const modelsPath = path.resolve(__dirname, '..', 'models.json');
const patterns = {
imageInput: [/vision/, /gpt-4o/, /gpt-4-vision/, /vl/, /multi_modal/],
imageOutput: [/image/, /imagen/, /dall-e/, /veo/, /sora/, /(?:^|[-_/])imagine(?:[-_/]|$)/],
audioInput: [/whisper/, /asr/, /transcribe/, /audio\-input/],
audioInput: [/whisper/, /asr/, /transcribe/, /audio-input/],
audioOutput: [/tts/, /audio/],
toolCalling: [/function/, /tool[_-]?call(?:ing)?/, /tool-use/, /deep-research/, /computer-use/, /^o3/, /^o4/, /(?:^|[-_/])agent(?:ic)?(?:[-_/]|$)/, /(?:^|[-_/])reasoner(?:[-_/]|$)/],
};
Expand Down
2 changes: 1 addition & 1 deletion apps/api/dev/cloneRedisDb.bun.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import dotenv from 'dotenv';
import path from 'node:path';
import { createClient } from '../../langgraph-control-plane/node_modules/redis';
import { createClient } from 'redis';

function log(message: string): void {
console.log(`[experimental-redis-clone] ${message}`);
Expand Down
2 changes: 1 addition & 1 deletion apps/api/dev/testApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ async function readResponseBody(response: globalThis.Response): Promise<string>
const decoder = new TextDecoder();
let result = '';

while (true) {
for (;;) {
const { done, value } = await reader.read();
if (done) break;
if (value) {
Expand Down
4 changes: 3 additions & 1 deletion apps/api/dev/testImageGenProviders.ts
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,8 @@ main().catch((err) => {
process.exit(1);
}).finally(async () => {
if (redis) {
try { await redis.quit(); } catch {}
try { await redis.quit(); } catch {
// Best-effort cleanup for this developer probe.
}
}
});
12 changes: 6 additions & 6 deletions apps/api/dev/testModelLiveProbes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1170,7 +1170,7 @@ const SAMPLE_AUDIO_BASE64 =
'UklGRsQPAABXQVZFZm10IBAAAAABAAEAQB8AAIA+AAACABAAZGF0YaAPAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';

function resolveProviderUrl(p: LoadedProviderData, endpointHint?: EndpointHint): string {
let url = p.provider_url || '';
const url = p.provider_url || '';

if (!p.id.includes('openai')) return url;

Expand Down Expand Up @@ -1231,7 +1231,7 @@ function resolveModerationsUrl(p: LoadedProviderData): string {
}

function resolveCompletionsUrl(p: LoadedProviderData): string {
let url = p.provider_url || '';
const url = p.provider_url || '';
if (!url) return 'https://api.openai.com/v1/completions';
if (url.includes('/chat/completions')) return url.replace('/chat/completions', '/completions');
if (url.includes('/responses')) return url.replace('/responses', '/completions');
Expand Down Expand Up @@ -1372,7 +1372,7 @@ async function withProviderLimit<T>(providerId: string, fn: () => Promise<T>): P
const semaphore = isOpenRouter ? openrouterSemaphore : getProviderSemaphore(providerId);
await semaphore.acquire();
try {
while (true) {
for (;;) {
const now = Date.now();
const providerWaitUntil = Math.max(
rateLimitUntil.get(providerId) || 0,
Expand Down Expand Up @@ -1457,7 +1457,7 @@ function pickProvider(

function getProbePrompt(testName: string, isRelace: boolean): string {
if (isRelace) {
return '<code>\nfunction greet() {\n return \"hello\";\n}\n</code>\n<update>\nChange the greeting to \"goodbye\".\n</update>';
return '<code>\nfunction greet() {\n return "hello";\n}\n</code>\n<update>\nChange the greeting to "goodbye".\n</update>';
}
switch (testName) {
case 'image_input':
Expand Down Expand Up @@ -1735,7 +1735,7 @@ async function testCapability(
return message;
};

while (true) {
for (;;) {
try {
if (mode === 'stream' && typeof (provider as any).sendMessageStream === 'function') {
const message = buildTestMessage();
Expand Down Expand Up @@ -2464,7 +2464,7 @@ async function main() {
if (endpointHintOverride) endpointTried.add(endpointHintOverride);
let retriesLeft = MAX_RETRIES;

while (true) {
for (;;) {
const imageUrlOverride = key === 'image_input' ? SAMPLE_IMAGE_URLS[imageUrlIndex] : undefined;
if (!provider) {
outcome = 'fail: no valid provider';
Expand Down
4 changes: 3 additions & 1 deletion apps/api/dev/testNanoBananaProviders.ts
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,8 @@ main().catch((err) => {
process.exit(1);
}).finally(async () => {
if (redis) {
try { await redis.quit(); } catch {}
try { await redis.quit(); } catch {
// Best-effort cleanup for this developer probe.
}
}
});
2 changes: 1 addition & 1 deletion apps/api/dev/updateproviders.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ async function updateProviders(
disabled: false // Add required disabled field
};

let providers = await dataManager.load<LoadedProviders>('providers');
const providers = await dataManager.load<LoadedProviders>('providers');
if (!Array.isArray(providers)) {
console.error('Invalid providers data format. Expected an array of providers.');
process.exit(1);
Expand Down
4 changes: 2 additions & 2 deletions apps/api/modules/dataManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1463,8 +1463,8 @@ class DataManager {
dataSourcePreference === 'redis' && hasRedisKeys
? this.normalizeKeysSchema(redisKeys).normalized
: dataSourcePreference === 'filesystem' &&
hasFsKeys &&
!fsInvalid
hasFsKeys &&
!fsInvalid
? this.normalizeKeysSchema(fsKeys).normalized
: hasRedisKeys
? this.normalizeKeysSchema(redisKeys).normalized
Expand Down
5 changes: 3 additions & 2 deletions apps/api/modules/errorClassification.ts
Original file line number Diff line number Diff line change
Expand Up @@ -990,7 +990,8 @@ export function isProviderAuthConfigurationError(error: any): boolean {
Boolean((error as any)?.lastProviderErrorSummary) ||
Boolean((error as any)?.errorDetails?.lastProviderId) ||
Boolean((error as any)?.errorDetails?.lastProviderError) ||
Boolean((error as any)?.errorDetails?.lastProviderErrorSummary); message.includes('unsupported parameter') ||
Boolean((error as any)?.errorDetails?.lastProviderErrorSummary) ||
message.includes('unsupported parameter') ||
message.includes('not supported with this model') ||
message.includes('invalid_request_error') ||
message.includes('resource has been exhausted') ||
Expand All @@ -1000,7 +1001,7 @@ export function isProviderAuthConfigurationError(error: any): boolean {
message.includes('invalid_api_key') ||
message.includes('key_invalid') ||
message.includes('401') ||
message.includes('402');
message.includes('402') ||
Boolean((error as any)?.errorDetails?.lastProviderId) ||
Boolean((error as any)?.errorDetails?.attemptedProviders);
const wrappedAuthOrQuotaSignal =
Expand Down
8 changes: 6 additions & 2 deletions apps/api/modules/errorLogger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ function sanitizeProviderErrorText(value: string): string {
const label = match.toLowerCase().includes('authorization') ? 'authorization' : 'api_key';
return `${label}${separator} [redacted]`;
})
.replace(/\bauthorization\b\s*[:=]\s*bearer\s+[A-Za-z0-9._\-]+/gi, 'authorization: [redacted]');
.replace(/\bauthorization\b\s*[:=]\s*bearer\s+[A-Za-z0-9._-]+/gi, 'authorization: [redacted]');
}

function sanitizeProviderErrorValue<T>(value: T): T {
Expand Down Expand Up @@ -359,7 +359,11 @@ function classifyFingerprintErrorText(text: string): string {
const lower = normalizeFingerprintString(text).toLowerCase();
if (!lower) return '';

const quotaMetricMatch = lower.match(/quota exceeded for metric:?\s*([^,]+)/i) || lower.match(/quota exceeded for metric:\s*([^,]+)/i);
const normalizedMetricText = lower.replace(
`quota exceeded for metric:${String.fromCharCode(31)}`,
'quota exceeded for metric:'
);
const quotaMetricMatch = normalizedMetricText.match(/quota exceeded for metric:\s*([^,]+)/i);
if (quotaMetricMatch?.[1]) {
return `quota:${quotaMetricMatch[1].trim()}`;
}
Expand Down
6 changes: 3 additions & 3 deletions apps/api/modules/geminiMediaValidation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -470,7 +470,7 @@ export function validateGeminiModelCapabilityRequest(modelId: string, body: unkn
const hasToolCallingHint =
requestJson.includes('tool_choice') ||
requestJson.includes('tool_calls') ||
requestJson.includes('\"tools\"') ||
requestJson.includes('"tools"') ||
requestJson.includes('function_declarations') ||
requestJson.includes('function_calling');

Expand Down Expand Up @@ -505,7 +505,7 @@ export function validateGeminiModelCapabilityRequest(modelId: string, body: unkn
requestJson.includes('image_base64') ||
requestJson.includes('b64_json') ||
requestJson.includes('response_format":"b64_json') ||
requestJson.includes('response_format\":\"b64_json') ||
requestJson.includes('response_format":"b64_json') ||
requestJson.includes('response_format') && requestJson.includes('b64_json') ||
(requestJson.includes('modalities') && requestJson.includes('image')) ||
(requestJson.includes('response_format') && requestJson.includes('image'));
Expand Down Expand Up @@ -688,7 +688,7 @@ export function validateGeminiModelCapabilityRequest(modelId: string, body: unkn
requestJson.includes('function_calling') ||
requestJson.includes('parallel_tool_calls') ||
requestJson.includes('tool_calls') ||
requestJson.includes('\"tools\"') ||
requestJson.includes('"tools"') ||
requestJson.includes('[probe:tool_calling]');

const hasUnsupportedAudioHintForLyria =
Expand Down
6 changes: 4 additions & 2 deletions apps/api/modules/imageFetch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,14 +149,16 @@ async function readResponseBodyWithLimit(
const chunks: Buffer[] = [];
let total = 0;

while (true) {
for (;;) {
const { done, value } = await reader.read();
if (done) break;
if (!value || value.length === 0) continue;
const chunk = Buffer.from(value);
total += chunk.length;
if (maxBytes > 0 && total > maxBytes) {
try { await reader.cancel(); } catch {}
try { await reader.cancel(); } catch {
// The abort and size error below remain authoritative.
}
controller?.abort(new Error('Image exceeds max size.'));
throw new Error('Image exceeds max size.');
}
Expand Down
3 changes: 2 additions & 1 deletion apps/api/modules/mediaParsing.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export function normalizeInputAudio(audio: { data: string; format: string }): { buffer: Buffer; mimeType: string; extension: string } | null {
let { data, format } = audio;
let { data } = audio;
const { format } = audio;
let mimeType = format;

if (typeof data === 'string' && data.startsWith('data:')) {
Expand Down
2 changes: 1 addition & 1 deletion apps/api/modules/openaiAudio.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ export async function forwardTtsToOpenAI(options: {

if (stream && upstreamRes.body) {
const reader = upstreamRes.body.getReader();
while (true) {
for (;;) {
const { done, value } = await reader.read();
if (done) break;
if (value && value.length > 0) response.write(value);
Expand Down
12 changes: 9 additions & 3 deletions apps/api/modules/openaiFallbacks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1442,7 +1442,9 @@ function sendResponsesTextResult(params: {
response.setHeader('Content-Type', 'text/event-stream');
response.setHeader('Cache-Control', 'no-cache');
response.setHeader('Connection', 'keep-alive');
try { (response as any).flushHeaders?.(); } catch {}
try { (response as any).flushHeaders?.(); } catch {
// Flushing is optional for compatible response implementations.
}

const pendingMessageItem = createResponsesMessageItem('', { id: messageId, status: 'in_progress' });
const finalMessageItem = Array.isArray(responseBody.output)
Expand Down Expand Up @@ -1586,7 +1588,9 @@ export async function handleImageGenFallbackFromChatOrResponses(params: {
response.setHeader('Content-Type', 'text/event-stream');
response.setHeader('Cache-Control', 'no-cache');
response.setHeader('Connection', 'keep-alive');
try { (response as any).flushHeaders?.(); } catch {}
try { (response as any).flushHeaders?.(); } catch {
// Flushing is optional for compatible response implementations.
}

const firstChunk = {
id,
Expand Down Expand Up @@ -1715,7 +1719,9 @@ export async function handleVideoGenFallbackFromChatOrResponses(params: {
response.setHeader('Content-Type', 'text/event-stream');
response.setHeader('Cache-Control', 'no-cache');
response.setHeader('Connection', 'keep-alive');
try { (response as any).flushHeaders?.(); } catch {}
try { (response as any).flushHeaders?.(); } catch {
// Flushing is optional for compatible response implementations.
}

const firstChunk = {
id,
Expand Down
2 changes: 1 addition & 1 deletion apps/api/modules/openaiRequestSupport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ export function createSseDataParser(
return (chunk: string) => {
buffer += chunk;

while (true) {
for (;;) {
const lineBreakIndex = buffer.indexOf('\n');
if (lineBreakIndex === -1) break;

Expand Down
8 changes: 4 additions & 4 deletions apps/api/modules/openaiResponsesFormat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ function buildResponsesFunctionCallItem(
typeof rawCall?.call_id === 'string' && rawCall.call_id.trim()
? rawCall.call_id.trim()
: typeof rawCall?.tool_call_id === 'string' &&
rawCall.tool_call_id.trim()
rawCall.tool_call_id.trim()
? rawCall.tool_call_id.trim()
: undefined;
const id = normalizeFunctionCallItemId(rawCall?.id, callId);
Expand Down Expand Up @@ -224,7 +224,7 @@ export function buildResponsesUsage(
typeof usage?.total_tokens === 'number'
? usage.total_tokens
: typeof inputTokens === 'number' ||
typeof outputTokens === 'number'
typeof outputTokens === 'number'
? (inputTokens || 0) + (outputTokens || 0)
: undefined;

Expand All @@ -237,7 +237,7 @@ export function buildResponsesUsage(
input_tokens_details: {
cached_tokens: 0
}
}
}
: {}),
...(typeof outputTokens === 'number'
? { output_tokens: outputTokens }
Expand All @@ -247,7 +247,7 @@ export function buildResponsesUsage(
output_tokens_details: {
reasoning_tokens: 0
}
}
}
: {}),
...(typeof totalTokens === 'number'
? { total_tokens: totalTokens }
Expand Down
4 changes: 2 additions & 2 deletions apps/api/modules/requestQueue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -640,7 +640,7 @@ let cachedCpuCount: number | null = null;
function getSystemMemoryBytes(): number {
if (cachedSystemMemoryBytes !== null) return cachedSystemMemoryBytes;
try {
cachedSystemMemoryBytes = Number(require('os').totalmem?.() || 0);
cachedSystemMemoryBytes = Number(os.totalmem?.() || 0);
} catch {
cachedSystemMemoryBytes = 0;
}
Expand All @@ -650,7 +650,7 @@ function getSystemMemoryBytes(): number {
function getCpuCount(): number {
if (cachedCpuCount !== null) return cachedCpuCount;
try {
const cpus = require('os').cpus?.();
const cpus = os.cpus?.();
cachedCpuCount = Array.isArray(cpus) && cpus.length > 0 ? cpus.length : 1;
} catch {
cachedCpuCount = 1;
Expand Down
2 changes: 1 addition & 1 deletion apps/api/modules/validators.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import Ajv, { ErrorObject } from 'ajv';
import { Ajv, type ErrorObject } from 'ajv';

export interface AdminProviderPayload {
providerId: string;
Expand Down
1 change: 1 addition & 0 deletions apps/api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
"concurrently": "^10.0.3",
"eslint": "^8.57.1",
"jest": "^30.4.2",
"redis": "^4.7.0",
"rimraf": "^5.0.10",
"ts-jest": "^29.4.11",
"ts-node-dev": "^1.1.8",
Expand Down
2 changes: 1 addition & 1 deletion apps/api/providers/gemini.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1086,7 +1086,7 @@ export class GeminiAI implements IAIProvider {
*/
async sendMessage(message: IMessage): Promise<ProviderResponse> {
const originalParts = Array.isArray((message as any)?.parts) ? (message as any).parts : null;
let retriedWithInlinedRemoteMedia = false;
const retriedWithInlinedRemoteMedia = false;
if (Array.isArray((message as any)?.parts) && (message as any).parts.length > 0) {
try {
(message as any).parts = await inlineUnsupportedRemoteImageParts(
Expand Down
4 changes: 2 additions & 2 deletions apps/api/providers/handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1841,7 +1841,7 @@ export class MessageHandler {
Number(modelData?.disabled_at || 0)
);
if (newestFailureAt <= 0) {
return Boolean(provider.disabled || modelData?.disabled)
return provider.disabled || modelData?.disabled
? 'transient'
: null;
}
Expand Down Expand Up @@ -3674,7 +3674,7 @@ export class MessageHandler {
: typeof (modelStats as any)
?.token_generation_speed ===
'number' &&
(modelStats as any)
(modelStats as any)
.token_generation_speed > 0
? (modelStats as any)
.token_generation_speed
Expand Down
Loading
Loading