diff --git a/src/proxy/middleware/request/preprocessors/apply-quota-limits.ts b/src/proxy/middleware/request/preprocessors/apply-quota-limits.ts index 8c83302..62627f0 100644 --- a/src/proxy/middleware/request/preprocessors/apply-quota-limits.ts +++ b/src/proxy/middleware/request/preprocessors/apply-quota-limits.ts @@ -34,4 +34,4 @@ export const applyQuotaLimits: RequestPreprocessor = (req) => { } ); } -}; +}; \ No newline at end of file diff --git a/src/proxy/middleware/request/preprocessors/count-prompt-tokens.ts b/src/proxy/middleware/request/preprocessors/count-prompt-tokens.ts index 3ccc5a1..eadd1e4 100644 --- a/src/proxy/middleware/request/preprocessors/count-prompt-tokens.ts +++ b/src/proxy/middleware/request/preprocessors/count-prompt-tokens.ts @@ -22,6 +22,12 @@ export const countPromptTokens: RequestPreprocessor = async (req) => { result = await countTokens({ req, prompt, service }); break; } + case "openai-responses": { + req.outputTokens = req.body.max_completion_tokens || req.body.max_tokens; + const prompt: OpenAIChatMessage[] = req.body.messages; + result = await countTokens({ req, prompt, service }); + break; + } case "openai-text": { req.outputTokens = req.body.max_tokens; const prompt: string = req.body.prompt; diff --git a/src/proxy/middleware/request/preprocessors/language-filter.ts b/src/proxy/middleware/request/preprocessors/language-filter.ts index b193d07..e455129 100644 --- a/src/proxy/middleware/request/preprocessors/language-filter.ts +++ b/src/proxy/middleware/request/preprocessors/language-filter.ts @@ -78,6 +78,7 @@ function getPromptFromRequest(req: Request) { .join("\n\n"); case "anthropic-text": case "openai-text": + case "openai-responses": case "openai-image": case "mistral-text": return body.prompt; diff --git a/src/proxy/middleware/request/preprocessors/validate-vision.ts b/src/proxy/middleware/request/preprocessors/validate-vision.ts index 705c2f9..8b203d9 100644 --- a/src/proxy/middleware/request/preprocessors/validate-vision.ts +++ b/src/proxy/middleware/request/preprocessors/validate-vision.ts @@ -23,6 +23,9 @@ export const validateVision: RequestPreprocessor = async (req) => { case "openai": hasImage = containsImageContentOpenAI(req.body.messages); break; + case "openai-responses": + hasImage = containsImageContentOpenAI(req.body.messages); + break; case "anthropic-chat": hasImage = containsImageContentAnthropic(req.body.messages); break; diff --git a/src/proxy/middleware/response/error-generator.ts b/src/proxy/middleware/response/error-generator.ts index e8ba40a..436054c 100644 --- a/src/proxy/middleware/response/error-generator.ts +++ b/src/proxy/middleware/response/error-generator.ts @@ -194,6 +194,21 @@ export function buildSpoofedCompletion({ switch (format) { case "openai": + case "openai-responses": + return { + id: "error-" + id, + object: "chat.completion", + created: Date.now(), + model, + usage: { prompt_tokens: 0, completion_tokens: 0, total_tokens: 0 }, + choices: [ + { + message: { role: "assistant", content }, + finish_reason: title, + index: 0, + }, + ], + }; case "mistral-ai": return { id: "error-" + id, @@ -283,6 +298,15 @@ export function buildSpoofedSSE({ switch (format) { case "openai": + case "openai-responses": + event = { + id: "chatcmpl-" + id, + object: "chat.completion.chunk", + created: Date.now(), + model, + choices: [{ delta: { content }, index: 0, finish_reason: title }], + }; + break; case "mistral-ai": event = { id: "chatcmpl-" + id, diff --git a/src/proxy/middleware/response/log-prompt.ts b/src/proxy/middleware/response/log-prompt.ts index cd641c3..d0c8b79 100644 --- a/src/proxy/middleware/response/log-prompt.ts +++ b/src/proxy/middleware/response/log-prompt.ts @@ -72,6 +72,8 @@ const getPromptForRequest = ( // format. switch (req.outboundApi) { case "openai": + case "openai-responses": + return req.body.messages; case "mistral-ai": return req.body.messages; case "anthropic-chat": diff --git a/src/proxy/middleware/response/streaming/event-aggregator.ts b/src/proxy/middleware/response/streaming/event-aggregator.ts index 1311fd1..0f0377e 100644 --- a/src/proxy/middleware/response/streaming/event-aggregator.ts +++ b/src/proxy/middleware/response/streaming/event-aggregator.ts @@ -84,7 +84,8 @@ export class EventAggregator { getFinalResponse() { switch (this.responseFormat) { case "openai": - case "google-ai": // TODO: this is probably wrong now that we support native Google Makersuite prompts + case "openai-responses": + case "google-ai": return mergeEventsForOpenAIChat(this.events); case "openai-text": return mergeEventsForOpenAIText(this.events); diff --git a/src/shared/key-management/azure/provider.ts b/src/shared/key-management/azure/provider.ts index b8b2243..535acac 100644 --- a/src/shared/key-management/azure/provider.ts +++ b/src/shared/key-management/azure/provider.ts @@ -79,6 +79,7 @@ export class AzureOpenAIKeyProvider implements KeyProvider { "azure-gpt41-nanoTokens": 0, "azure-o1Tokens": 0, "azure-o1-miniTokens": 0, + "azure-o1-proTokens": 0, "azure-o3-miniTokens": 0, "azure-o3Tokens": 0, "azure-o4-miniTokens": 0, diff --git a/src/shared/users/user-store.ts b/src/shared/users/user-store.ts index bfe4c67..09be8f4 100644 --- a/src/shared/users/user-store.ts +++ b/src/shared/users/user-store.ts @@ -427,6 +427,7 @@ function getModelFamilyForQuotaUsage( switch (api) { case "openai": case "openai-text": + case "openai-responses": case "openai-image": return getOpenAIModelFamily(model); case "anthropic-chat":