@ai-sdk-tool/proxy 0.0.0 → 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,13 @@
1
+ Copyright 2025 Woonggi Min (https://github.com/minpeter)
2
+
3
+ Licensed under the Apache License, Version 2.0 (the "License");
4
+ you may not use this file except in compliance with the License.
5
+ You may obtain a copy of the License at
6
+
7
+ http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+ Unless required by applicable law or agreed to in writing, software
10
+ distributed under the License is distributed on an "AS IS" BASIS,
11
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ See the License for the specific language governing permissions and
13
+ limitations under the License.
package/dist/index.cjs CHANGED
@@ -293,7 +293,7 @@ function mapOpenAIToolChoice(choice) {
293
293
  }
294
294
  function convertAISDKToolCallsToOpenAI(toolCalls) {
295
295
  return toolCalls.map((call) => ({
296
- id: `call_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
296
+ id: `call_${Date.now()}_${Math.random().toString(36).slice(2, 11)}`,
297
297
  type: "function",
298
298
  function: {
299
299
  name: call.toolName,
@@ -304,7 +304,7 @@ function convertAISDKToolCallsToOpenAI(toolCalls) {
304
304
 
305
305
  // src/response-utils.ts
306
306
  function generateResponseId() {
307
- return `chatcmpl-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
307
+ return `chatcmpl-${Date.now()}-${Math.random().toString(36).slice(2, 11)}`;
308
308
  }
309
309
  function getCurrentTimestamp() {
310
310
  return Math.floor(Date.now() / 1e3);
@@ -339,7 +339,7 @@ function convertAISDKResultToOpenAI(aisdkResult, model, stream = false) {
339
339
  };
340
340
  const openAIToolCalls = (_a = aisdkResult.toolCalls) == null ? void 0 : _a.map(
341
341
  (call) => ({
342
- id: `call_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
342
+ id: `call_${Date.now()}_${Math.random().toString(36).slice(2, 11)}`,
343
343
  type: "function",
344
344
  function: {
345
345
  name: call.toolName,
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/openai-request-converter.ts","../src/response-utils.ts","../src/response-converter.ts","../src/server.ts"],"sourcesContent":["// biome-ignore lint/performance/noBarrelFile: Package entrypoint - must re-export for public API\nexport {\n convertAISDKToolCallsToOpenAI,\n convertOpenAIRequestToAISDK,\n} from \"./openai-request-converter.js\";\nexport {\n convertAISDKResultToOpenAI,\n convertAISDKStreamChunkToOpenAI,\n createOpenAIStreamConverter,\n createSSEResponse,\n} from \"./response-converter.js\";\nexport { generateResponseId, getCurrentTimestamp } from \"./response-utils.js\";\nexport { OpenAIProxyServer } from \"./server.js\";\nexport type {\n AISDKTool,\n Logger,\n OpenAIChatRequest,\n OpenAIChatResponse,\n OpenAIChoice,\n OpenAIMessage,\n OpenAITool,\n OpenAIToolCall,\n OpenAIUsage,\n ProxyConfig,\n StreamChunk,\n} from \"./types.js\";\n","import type {\n ModelMessage,\n ToolContent,\n ToolResultOutput,\n} from \"@ai-sdk/provider-utils\";\nimport { z } from \"zod\";\nimport type {\n OpenAIChatRequest,\n OpenAICompleteToolCall,\n OpenAIMessage,\n ProxyConfig,\n} from \"./types.js\";\n\n// Type definitions for OpenAI tool parameters\ninterface OpenAIToolProperty {\n type: string;\n description?: string;\n enum?: string[];\n}\n\ninterface OpenAIToolParameters {\n type: string;\n properties?: Record<string, OpenAIToolProperty>;\n required?: string[];\n}\n\n// Type for AI SDK tool definition\ninterface AISDKTool {\n description: string;\n inputSchema: z.ZodTypeAny;\n}\n\n// Type for tool call object\ninterface ToolCall {\n toolName: string;\n args: unknown;\n}\n\n/**\n * Create Zod schema for OpenAI tool property\n */\nfunction createZodSchema(prop: OpenAIToolProperty): z.ZodTypeAny {\n if (prop.type === \"string\") {\n return prop.enum ? z.enum(prop.enum as [string, ...string[]]) : z.string();\n }\n if (prop.type === \"number\") {\n return z.number();\n }\n if (prop.type === \"boolean\") {\n return z.boolean();\n }\n if (prop.type === \"array\") {\n return z.array(z.any());\n }\n if (prop.type === \"object\") {\n return z.object({});\n }\n return z.any();\n}\n\n/**\n * Convert OpenAI tool schema to Zod schema\n */\nfunction convertOpenAIToolToZod(\n parameters: Record<string, unknown> | undefined\n): z.ZodObject<Record<string, z.ZodTypeAny>> {\n if (!parameters) {\n return z.object({});\n }\n\n const params = parameters as unknown as OpenAIToolParameters;\n if (!params.properties) {\n return z.object({});\n }\n\n const schemaShape: Record<string, z.ZodTypeAny> = {};\n for (const [key, prop] of Object.entries(params.properties)) {\n schemaShape[key] = createZodSchema(prop);\n }\n\n return z.object(schemaShape);\n}\n\n/**\n * Convert OpenAI tools to AI SDK format\n */\nfunction convertOpenAITools(\n openaiTools:\n | Array<{\n function: {\n name: string;\n description?: string;\n parameters: Record<string, unknown>;\n };\n }>\n | undefined\n): Record<string, AISDKTool> {\n const aisdkTools: Record<string, AISDKTool> = {};\n\n if (!openaiTools) {\n return aisdkTools;\n }\n\n for (const openaiTool of openaiTools) {\n const toolName = openaiTool.function.name;\n aisdkTools[toolName] = {\n description: openaiTool.function.description || \"\",\n inputSchema: convertOpenAIToolToZod(openaiTool.function.parameters),\n };\n }\n\n return aisdkTools;\n}\n\n/**\n * Convert stop parameter to stop sequences\n */\nfunction convertStopToSequences(\n stop: string | string[] | undefined\n): string[] | undefined {\n if (!stop) {\n return;\n }\n return Array.isArray(stop) ? stop : [stop];\n}\n\ninterface AITextPart {\n type: \"text\";\n text: string;\n}\ninterface AIToolCallPart {\n type: \"tool-call\";\n toolCallId: string;\n toolName: string;\n input: unknown;\n}\ntype TextToolOutput = Extract<ToolResultOutput, { type: \"text\" }>;\ntype JsonToolOutput = Extract<ToolResultOutput, { type: \"json\" }>;\n\n/**\n * Convert OpenAI chat completion request to AI SDK format\n */\nexport function normalizeMessageContent(\n content: OpenAIMessage[\"content\"]\n): AITextPart[] {\n if (typeof content === \"string\") {\n return content ? [{ type: \"text\" as const, text: content }] : [];\n }\n\n if (Array.isArray(content)) {\n const parts = content as Array<string | { text?: unknown }>;\n return parts\n .map((part) => {\n if (typeof part === \"string\") {\n return part;\n }\n if (part && typeof part === \"object\" && \"text\" in part) {\n const textValue = part.text;\n if (typeof textValue === \"string\") {\n return textValue;\n }\n if (textValue !== undefined) {\n return JSON.stringify(textValue);\n }\n }\n return JSON.stringify(part);\n })\n .filter((text): text is string => Boolean(text))\n .map((text) => ({ type: \"text\" as const, text }));\n }\n\n if (content === null || content === undefined) {\n return [];\n }\n\n if (typeof content === \"object\") {\n return [{ type: \"text\" as const, text: JSON.stringify(content) }];\n }\n\n return [{ type: \"text\" as const, text: String(content) }];\n}\n\nfunction buildToolCallParts(\n toolCalls: OpenAICompleteToolCall[]\n): AIToolCallPart[] {\n return toolCalls.map((toolCall) => {\n let parsedArgs: unknown = toolCall.function.arguments;\n if (typeof toolCall.function.arguments === \"string\") {\n try {\n parsedArgs = JSON.parse(toolCall.function.arguments || \"{}\");\n } catch {\n parsedArgs = toolCall.function.arguments;\n }\n }\n\n return {\n type: \"tool-call\" as const,\n toolCallId: toolCall.id,\n toolName: toolCall.function.name,\n input: parsedArgs,\n } satisfies AIToolCallPart;\n });\n}\n\nfunction buildAssistantContent(\n message: OpenAIMessage & { role: \"assistant\" }\n): Array<AITextPart | AIToolCallPart> | string {\n const textParts = normalizeMessageContent(message.content);\n const toolCallParts = message.tool_calls?.length\n ? buildToolCallParts(message.tool_calls)\n : [];\n\n if (toolCallParts.length === 0) {\n if (textParts.length === 0) {\n return \"\";\n }\n if (textParts.length === 1) {\n return textParts[0].text;\n }\n return textParts;\n }\n\n return [...textParts, ...toolCallParts];\n}\n\nfunction isJsonValue(value: unknown): value is JsonToolOutput[\"value\"] {\n if (\n value === null ||\n typeof value === \"string\" ||\n typeof value === \"number\" ||\n typeof value === \"boolean\"\n ) {\n return true;\n }\n\n if (Array.isArray(value)) {\n return value.every(isJsonValue);\n }\n\n if (typeof value === \"object\") {\n return Object.values(value as Record<string, unknown>).every(isJsonValue);\n }\n\n return false;\n}\n\nfunction buildToolOutput(rawValue: string): ToolResultOutput {\n if (!rawValue) {\n return { type: \"text\", value: \"\" } satisfies TextToolOutput;\n }\n\n try {\n const parsed = JSON.parse(rawValue);\n if (isJsonValue(parsed)) {\n return { type: \"json\", value: parsed } satisfies JsonToolOutput;\n }\n } catch {\n // Fall through to text output below\n }\n\n return { type: \"text\", value: rawValue } satisfies TextToolOutput;\n}\n\nfunction buildToolContent(\n message: OpenAIMessage & { role: \"tool\" },\n toolNameLookup: Map<string, string>\n): ToolContent {\n const textParts = normalizeMessageContent(message.content);\n const combined = textParts.map((part) => part.text).join(\"\\n\");\n const toolCallId = message.tool_call_id ?? \"\";\n const toolName = toolCallId\n ? (toolNameLookup.get(toolCallId) ?? toolCallId)\n : \"\";\n\n return [\n {\n type: \"tool-result\",\n toolCallId,\n toolName,\n output: buildToolOutput(combined),\n },\n ];\n}\n\nfunction convertMessageToModelMessage(\n message: OpenAIMessage,\n toolNameLookup: Map<string, string>\n): ModelMessage {\n if (message.role === \"assistant\") {\n if (message.tool_calls?.length) {\n for (const toolCall of message.tool_calls) {\n toolNameLookup.set(toolCall.id, toolCall.function.name);\n }\n }\n\n return {\n role: \"assistant\",\n content: buildAssistantContent(\n message as OpenAIMessage & { role: \"assistant\" }\n ),\n };\n }\n\n if (message.role === \"tool\") {\n return {\n role: \"tool\",\n content: buildToolContent(\n message as OpenAIMessage & { role: \"tool\" },\n toolNameLookup\n ),\n };\n }\n\n if (message.role === \"system\") {\n const text = normalizeMessageContent(message.content)\n .map((part) => part.text)\n .join(\"\\n\");\n return {\n role: \"system\",\n content: text,\n };\n }\n\n const userParts = normalizeMessageContent(message.content);\n if (userParts.length === 0) {\n return {\n role: \"user\",\n content: \"\",\n };\n }\n\n if (userParts.length === 1) {\n return {\n role: \"user\",\n content: userParts[0].text,\n };\n }\n\n return {\n role: \"user\",\n content: userParts,\n };\n}\n\nexport function convertOpenAIRequestToAISDK(\n openaiRequest: OpenAIChatRequest,\n proxyConfig?: Pick<ProxyConfig, \"parserDebug\">\n) {\n const {\n messages,\n tools: openaiTools,\n temperature,\n max_tokens,\n stop,\n tool_choice,\n } = openaiRequest;\n\n const toolNameLookup = new Map<string, string>();\n\n const aiMessages: ModelMessage[] = messages.map((message) =>\n convertMessageToModelMessage(message, toolNameLookup)\n );\n\n // Convert OpenAI tools to AI SDK format dynamically\n const aisdkTools = convertOpenAITools(openaiTools);\n\n const providerOptions = proxyConfig?.parserDebug\n ? {\n toolCallMiddleware: {\n debugLevel: proxyConfig.parserDebug.level,\n logErrors: proxyConfig.parserDebug.logErrors,\n captureSummary: proxyConfig.parserDebug.captureSummary,\n },\n }\n : undefined;\n\n return {\n messages: aiMessages,\n tools: aisdkTools,\n temperature,\n maxOutputTokens: max_tokens,\n stopSequences: convertStopToSequences(stop),\n toolChoice: mapOpenAIToolChoice(tool_choice),\n ...(providerOptions ? { providerOptions } : {}),\n };\n}\n\n// Map OpenAI tool_choice to AI SDK toolChoice\nexport function mapOpenAIToolChoice(\n choice: OpenAIChatRequest[\"tool_choice\"]\n): \"auto\" | \"none\" | { type: \"tool\"; toolName: string } | undefined {\n if (!choice) {\n return;\n }\n if (choice === \"auto\" || choice === \"none\") {\n return choice;\n }\n if (typeof choice === \"object\" && choice.type === \"function\") {\n return { type: \"tool\", toolName: choice.function.name };\n }\n return;\n}\n\n/**\n * Convert AI SDK tool calls to OpenAI format\n */\nexport function convertAISDKToolCallsToOpenAI(toolCalls: ToolCall[]): Array<{\n id: string;\n type: \"function\";\n function: {\n name: string;\n arguments: string;\n };\n}> {\n return toolCalls.map((call) => ({\n id: `call_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,\n type: \"function\" as const,\n function: {\n name: call.toolName,\n arguments: JSON.stringify(call.args),\n },\n }));\n}\n","export function generateResponseId(): string {\n return `chatcmpl-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;\n}\n\nexport function getCurrentTimestamp(): number {\n return Math.floor(Date.now() / 1000);\n}\n","import { generateResponseId, getCurrentTimestamp } from \"./response-utils.js\";\nimport type {\n OpenAIChatResponse,\n OpenAIChoice,\n OpenAIStreamingToolCall,\n OpenAIUsage,\n StreamChunk,\n} from \"./types.js\";\n\n/**\n * Convert AI SDK result to OpenAI chat completion response\n */\nexport function convertAISDKResultToOpenAI(\n // biome-ignore lint/suspicious/noExplicitAny: AI sdk integration boundary\n aisdkResult: any,\n model: string,\n stream = false\n): OpenAIChatResponse {\n const choices: OpenAIChoice[] = [];\n\n // Handle text content\n if (aisdkResult.text) {\n const choice: OpenAIChoice = {\n index: 0,\n finish_reason: aisdkResult.finishReason || \"stop\",\n };\n\n if (stream) {\n choice.delta = {\n role: \"assistant\",\n content: aisdkResult.text,\n };\n } else {\n choice.message = {\n role: \"assistant\",\n content: aisdkResult.text,\n };\n }\n choices.push(choice);\n }\n\n // Handle tool calls\n if (aisdkResult.toolCalls && aisdkResult.toolCalls.length > 0) {\n const choice: OpenAIChoice = {\n index: 0,\n finish_reason: \"tool_calls\",\n };\n\n const openAIToolCalls = aisdkResult.toolCalls?.map(\n (\n // biome-ignore lint/suspicious/noExplicitAny: AI SDK integration boundary\n call: any\n ) => ({\n id: `call_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,\n type: \"function\" as const,\n function: {\n name: call.toolName,\n arguments: JSON.stringify(call.args),\n },\n })\n );\n\n if (stream) {\n choice.delta = {\n role: \"assistant\",\n tool_calls: openAIToolCalls,\n };\n } else {\n choice.message = {\n role: \"assistant\",\n content: null,\n tool_calls: openAIToolCalls,\n };\n }\n\n choices.push(choice);\n }\n\n const response: OpenAIChatResponse = {\n id: generateResponseId(),\n object: stream ? \"chat.completion.chunk\" : \"chat.completion\",\n created: getCurrentTimestamp(),\n model,\n choices,\n };\n\n // Add usage if available\n if (aisdkResult.usage) {\n response.usage = {\n prompt_tokens: aisdkResult.usage.promptTokens || 0,\n completion_tokens: aisdkResult.usage.completionTokens || 0,\n total_tokens: aisdkResult.usage.totalTokens || 0,\n } as OpenAIUsage;\n }\n\n return response;\n}\n\n/**\n * Convert AI SDK stream chunk to OpenAI SSE format\n */\n\n// Type definitions for better type safety\ninterface ToolCallDelta {\n index?: number;\n id?: string;\n type?: \"function\";\n function?: {\n name?: string;\n arguments?: string;\n };\n}\n\ninterface AIStreamChunk {\n type: string;\n id?: string;\n text?: string;\n toolCallId?: string;\n toolName?: string;\n args?: string;\n input?: Record<string, unknown>;\n finishReason?: string;\n [key: string]: unknown;\n}\n\ntype ChunkHandler = (chunk: AIStreamChunk, model: string) => StreamChunk[];\n\n// Helper function to create finish response\nfunction createFinishResponse(\n model: string,\n finishReason: string,\n responseId: string\n): OpenAIChatResponse {\n // Ensure finish reason matches OpenAI's allowed types\n let validFinishReason: \"stop\" | \"length\" | \"tool_calls\" | \"content_filter\";\n\n if (finishReason === \"tool_calls\" || finishReason === \"tool-calls\") {\n validFinishReason = \"tool_calls\";\n } else if (finishReason === \"stop\") {\n validFinishReason = \"stop\";\n } else if (finishReason === \"length\") {\n validFinishReason = \"length\";\n } else if (finishReason === \"content_filter\") {\n validFinishReason = \"content_filter\";\n } else {\n validFinishReason = \"stop\"; // fallback to \"stop\" for unknown reasons\n }\n\n return {\n id: responseId,\n object: \"chat.completion.chunk\",\n created: getCurrentTimestamp(),\n model,\n choices: [\n {\n index: 0,\n delta: {},\n finish_reason: validFinishReason,\n },\n ],\n };\n}\n\n// Helper function to create content response\nfunction createContentResponse(\n model: string,\n content: string,\n responseId: string,\n isReasoning = false\n): OpenAIChatResponse {\n const delta: Record<string, unknown> = { role: \"assistant\" };\n\n if (isReasoning) {\n delta.reasoning_content = content;\n } else {\n delta.content = content;\n }\n\n return {\n id: responseId,\n object: \"chat.completion.chunk\",\n created: getCurrentTimestamp(),\n model,\n choices: [\n {\n index: 0,\n delta,\n },\n ],\n };\n}\n\n// Helper function to create tool call response\nfunction createToolCallResponse(\n model: string,\n toolCall: ToolCallDelta,\n responseId: string,\n includeRole = false\n): OpenAIChatResponse {\n return {\n id: responseId,\n object: \"chat.completion.chunk\",\n created: getCurrentTimestamp(),\n model,\n choices: [\n {\n index: 0,\n delta: {\n ...(includeRole ? { role: \"assistant\" as const } : {}),\n tool_calls: [\n {\n index: toolCall.index || 0,\n type: \"function\" as const,\n function: {\n name: toolCall.function?.name || \"\",\n arguments: toolCall.function?.arguments || \"\",\n },\n },\n ],\n },\n },\n ],\n };\n}\n\n// (legacy stateless handler removed)\n\nexport function createOpenAIStreamConverter(\n model: string,\n options?: {\n logChunks?: boolean;\n }\n) {\n let streamHasToolCalls = false;\n let streamFinishSent = false;\n let streamResponseId = generateResponseId();\n\n const logChunk =\n options?.logChunks === false\n ? undefined\n : (chunk: unknown) => {\n const logType =\n process.env.USE_MIDDLEWARE === \"true\" ? \"middleware\" : \"native\";\n console.log(\n `🔍 AI SDK Chunk [${logType}]:`,\n JSON.stringify(chunk, null, 2)\n );\n };\n\n const handlers: Record<string, ChunkHandler> = {\n start: () => [],\n \"reasoning-delta\": (chunk) => {\n if (!chunk.text) {\n return [];\n }\n return [\n {\n data: JSON.stringify(\n createContentResponse(model, chunk.text, streamResponseId, true)\n ),\n },\n ];\n },\n \"text-delta\": (chunk) => {\n if (!chunk.text) {\n return [];\n }\n return [\n {\n data: JSON.stringify(\n createContentResponse(model, chunk.text, streamResponseId, false)\n ),\n },\n ];\n },\n \"tool-call\": (chunk) => {\n const toolCallId = chunk.toolCallId || `call_${generateResponseId()}`;\n const toolName = chunk.toolName || \"\";\n const argsString =\n typeof chunk.input === \"string\"\n ? chunk.input\n : JSON.stringify(chunk.input ?? {});\n const toolCallDelta: OpenAIStreamingToolCall = {\n index: 0,\n id: toolCallId,\n type: \"function\",\n function: { name: toolName, arguments: argsString },\n };\n const response = createToolCallResponse(\n model,\n toolCallDelta,\n streamResponseId,\n true\n );\n return [{ data: JSON.stringify(response) }];\n },\n \"reasoning-end\": () => [],\n \"text-end\": () => [],\n \"finish-step\": (chunk) => {\n if (streamFinishSent) {\n return [];\n }\n const hadToolCalls = streamHasToolCalls;\n let finishReason = chunk.finishReason || \"stop\";\n if (finishReason === \"tool_calls\" || finishReason === \"tool-calls\") {\n finishReason = \"tool_calls\";\n }\n const resolvedReason = hadToolCalls ? \"tool_calls\" : finishReason;\n streamFinishSent = true;\n streamHasToolCalls = false;\n return [\n {\n data: JSON.stringify(\n createFinishResponse(model, resolvedReason, streamResponseId)\n ),\n },\n ];\n },\n \"tool-call-delta\": (chunk) => {\n const toolCall = {\n index: chunk.toolCallId ? Number(chunk.toolCallId) : 0,\n type: \"function\" as const,\n function: {\n name: chunk.toolName || \"\",\n arguments: chunk.args || \"\",\n },\n };\n return [\n {\n data: JSON.stringify(\n createToolCallResponse(model, toolCall, streamResponseId)\n ),\n },\n ];\n },\n \"tool-result\": (chunk) => {\n const resultText = `\\n[Tool: ${chunk.toolName} returned ${JSON.stringify(chunk.output)}]\\n`;\n return [\n {\n data: JSON.stringify(\n createContentResponse(model, resultText, streamResponseId, false)\n ),\n },\n ];\n },\n finish: (chunk) => {\n if (streamFinishSent) {\n return [];\n }\n const hadToolCalls = streamHasToolCalls;\n let finishReason = chunk.finishReason || \"stop\";\n if (finishReason === \"tool_calls\" || finishReason === \"tool-calls\") {\n finishReason = \"tool_calls\";\n }\n const resolvedReason = hadToolCalls ? \"tool_calls\" : finishReason;\n streamFinishSent = true;\n streamHasToolCalls = false;\n return [\n {\n data: JSON.stringify(\n createFinishResponse(model, resolvedReason, streamResponseId)\n ),\n },\n ];\n },\n };\n\n return (\n // biome-ignore lint/suspicious/noExplicitAny: ai sdk boundary\n chunk: any\n ): StreamChunk[] => {\n const out: StreamChunk[] = [];\n\n logChunk?.(chunk);\n\n if (chunk.type === \"start\") {\n streamHasToolCalls = false;\n streamFinishSent = false;\n streamResponseId = chunk.id ?? generateResponseId();\n }\n\n const handler = handlers[chunk.type];\n if (handler) {\n const result = handler(chunk as AIStreamChunk, model);\n if (chunk.type === \"tool-call\" || chunk.type === \"tool-call-delta\") {\n streamHasToolCalls = true;\n }\n out.push(...result);\n } else {\n console.warn(`⚠️ Unknown AI SDK chunk type: ${chunk.type}`, chunk);\n }\n\n if (chunk.type === \"finish-step\" || chunk.type === \"finish\") {\n streamHasToolCalls = false;\n }\n\n return out.filter((resultChunk) => {\n try {\n const parsed = JSON.parse(resultChunk.data);\n const delta = parsed.choices?.[0]?.delta;\n return (\n delta &&\n (delta.role ||\n delta.content ||\n (delta as NonNullable<OpenAIChoice[\"delta\"]>).reasoning_content ||\n (delta.tool_calls && delta.tool_calls.length > 0) ||\n parsed.choices?.[0]?.finish_reason)\n );\n } catch {\n return true;\n }\n });\n };\n}\n\nexport function convertAISDKStreamChunkToOpenAI(\n // biome-ignore lint/suspicious/noExplicitAny: o sdk integration boundary\n chunk: any,\n model: string\n): StreamChunk[] {\n const convert = createOpenAIStreamConverter(model);\n return convert(chunk);\n}\n\n/**\n * Create SSE formatted response\n */\nexport function createSSEResponse(chunks: StreamChunk[]): string {\n return chunks.map((chunk) => `data: ${chunk.data}\\n\\n`).join(\"\");\n}\n","import { zodSchema } from \"@ai-sdk/provider-utils\";\nimport cors from \"@fastify/cors\";\nimport { generateText, streamText } from \"ai\";\nimport Fastify, {\n type FastifyInstance,\n type FastifyReply,\n type FastifyRequest,\n} from \"fastify\";\nimport { toJSONSchema, type ZodTypeAny } from \"zod\";\nimport { convertOpenAIRequestToAISDK } from \"./openai-request-converter.js\";\nimport {\n convertAISDKResultToOpenAI,\n createOpenAIStreamConverter,\n} from \"./response-converter.js\";\nimport type {\n AISDKTool,\n Logger,\n OpenAIChatRequest,\n ProxyConfig,\n} from \"./types.js\";\n\ntype ConvertedParams = ReturnType<typeof convertOpenAIRequestToAISDK>;\n\nfunction serializeZodSchema(schema: ZodTypeAny | undefined): unknown {\n if (!schema) {\n return null;\n }\n\n // Use Zod v4's built-in JSON Schema conversion\n const jsonSchema = toJSONSchema(schema, {\n unrepresentable: \"any\",\n });\n\n // Remove $schema field for cleaner output\n if (typeof jsonSchema === \"object\" && jsonSchema !== null) {\n const { $schema, ...rest } = jsonSchema as Record<string, unknown>;\n return rest;\n }\n\n return jsonSchema;\n}\n\nfunction serializeMessages(messages: OpenAIChatRequest[\"messages\"]) {\n return messages.map((message, index) => ({\n index,\n role: message.role,\n content: message.content,\n toolCalls: message.tool_calls,\n }));\n}\n\nfunction logIncomingRequest(\n openaiRequest: OpenAIChatRequest,\n enabled: boolean\n) {\n if (!enabled) {\n return;\n }\n const toolNames = (openaiRequest.tools ?? [])\n .map((tool) => (\"function\" in tool ? tool.function?.name : undefined))\n .filter((name): name is string => Boolean(name));\n\n console.log(\n \"[proxy] Incoming OpenAI request\",\n JSON.stringify(\n {\n model: openaiRequest.model,\n stream: Boolean(openaiRequest.stream),\n temperature: openaiRequest.temperature,\n maxTokens: openaiRequest.max_tokens,\n toolNames,\n toolChoice: openaiRequest.tool_choice,\n messages: serializeMessages(openaiRequest.messages),\n tools: openaiRequest.tools,\n },\n null,\n 2\n )\n );\n}\n\nfunction serializeAISDKMessages(messages: ConvertedParams[\"messages\"]) {\n return messages?.map((message, index) => ({\n index,\n role: message.role,\n content: message.content,\n }));\n}\n\nfunction logRequestConversion(\n openaiRequest: OpenAIChatRequest,\n aisdkParams: ConvertedParams,\n enabled: boolean\n) {\n if (!enabled) {\n return;\n }\n const messages = aisdkParams.messages ?? [];\n console.log(\n \"[proxy] Converted AI SDK params\",\n JSON.stringify(\n {\n model: openaiRequest.model,\n hasSystemMessage: messages.some((message) => message.role === \"system\"),\n messages: serializeAISDKMessages(messages),\n tools: Object.entries(aisdkParams.tools ?? {}).map(([name, tool]) => ({\n name,\n description: tool.description,\n inputSchema: serializeZodSchema(tool.inputSchema),\n })),\n temperature: aisdkParams.temperature,\n maxOutputTokens: aisdkParams.maxOutputTokens,\n stopSequences: aisdkParams.stopSequences,\n },\n null,\n 2\n )\n );\n}\n\nexport class OpenAIProxyServer {\n private readonly fastify: FastifyInstance;\n private readonly config: ProxyConfig;\n private readonly logger: Logger;\n\n constructor(config: ProxyConfig) {\n this.config = {\n port: 3000,\n host: \"localhost\",\n cors: true,\n ...config,\n };\n this.logger = (config.logger ?? console) as Logger;\n\n this.fastify = Fastify();\n\n // Enable CORS\n if (this.config.cors) {\n this.fastify.register(cors);\n }\n\n this.setupRoutes();\n }\n\n private setupRoutes(): void {\n // Health check endpoint\n this.fastify.get(\n \"/health\",\n async (_request: FastifyRequest, _reply: FastifyReply) => ({\n status: \"ok\",\n timestamp: new Date().toISOString(),\n })\n );\n\n // OpenAI-compatible chat completions endpoint\n this.fastify.post(\n \"/v1/chat/completions\",\n (request: FastifyRequest, reply: FastifyReply) => {\n try {\n const openaiRequest = request.body as OpenAIChatRequest;\n\n // Validate request\n if (\n !(openaiRequest.messages && Array.isArray(openaiRequest.messages))\n ) {\n return reply.code(400).send({\n error: {\n message: \"Messages array is required\",\n type: \"invalid_request_error\",\n },\n });\n }\n\n logIncomingRequest(\n openaiRequest,\n this.config.logging?.requests ?? true\n );\n\n // Convert OpenAI request to AI SDK format\n const aisdkParams = convertOpenAIRequestToAISDK(openaiRequest, {\n parserDebug: this.config.parserDebug,\n });\n logRequestConversion(\n openaiRequest,\n aisdkParams,\n this.config.logging?.conversions ?? true\n );\n\n // Handle streaming vs non-streaming\n if (openaiRequest.stream) {\n return this.handleStreamingRequest(\n aisdkParams,\n openaiRequest,\n reply\n );\n }\n return this.handleNonStreamingRequest(\n aisdkParams,\n openaiRequest,\n reply\n );\n } catch (error) {\n this.logger.error(\"Request handling error:\", error);\n return reply.code(500).send({\n error: {\n message: \"Internal server error\",\n type: \"server_error\",\n },\n });\n }\n }\n );\n\n // Models endpoint\n this.fastify.get(\"/v1/models\", async () => ({\n object: \"list\",\n data: [\n {\n id: \"wrapped-model\",\n object: \"model\",\n created: Math.floor(Date.now() / 1000),\n owned_by: \"ai-sdk-tool-proxy\",\n },\n ],\n }));\n }\n\n // Merge server-defined tools (with execute) and request-defined tools (schema-only)\n // Server tools take precedence when names overlap.\n private mergeTools(\n serverTools?: Record<string, AISDKTool>,\n requestTools?: Record<string, AISDKTool>\n ) {\n const toProviderTool = (tool: AISDKTool | undefined): unknown => {\n if (!tool) {\n return;\n }\n\n return {\n description: tool.description,\n inputSchema: zodSchema(tool.inputSchema),\n ...(tool.execute ? { execute: tool.execute } : {}),\n };\n };\n\n const merged: Record<string, unknown> = {};\n\n for (const [name, t] of Object.entries(requestTools ?? {})) {\n const pt = toProviderTool(t);\n if (pt) {\n merged[name] = pt;\n }\n }\n\n for (const [name, t] of Object.entries(serverTools ?? {})) {\n const pt = toProviderTool(t);\n if (pt) {\n merged[name] = pt; // override request tool\n }\n }\n\n return Object.keys(merged).length > 0 ? merged : undefined;\n }\n\n private async handleStreamingRequest(\n // biome-ignore lint/suspicious/noExplicitAny: o sdk integration boundary\n aisdkParams: any,\n openaiRequest: OpenAIChatRequest,\n reply: FastifyReply\n ): Promise<void> {\n // Set SSE headers\n reply.raw.writeHead(200, {\n \"Content-Type\": \"text/event-stream\",\n \"Cache-Control\": \"no-cache\",\n Connection: \"keep-alive\",\n \"Access-Control-Allow-Origin\": \"*\",\n });\n\n try {\n const mergedTools = this.mergeTools(this.config.tools, aisdkParams.tools);\n const result = await streamText({\n model: this.config.model,\n ...aisdkParams,\n ...(mergedTools ? { tools: mergedTools } : {}),\n });\n\n const convert = createOpenAIStreamConverter(openaiRequest.model, {\n logChunks: this.config.logging?.streamChunks ?? true,\n });\n for await (const chunk of result.fullStream) {\n const openaiChunks = convert(chunk);\n for (const openaiChunk of openaiChunks) {\n reply.raw.write(`data: ${openaiChunk.data}\\n\\n`);\n }\n }\n\n reply.raw.write(\"data: [DONE]\\n\\n\");\n reply.raw.end();\n } catch (error) {\n this.logger.error(\"Streaming error:\", error);\n reply.raw.write('data: {\"error\": {\"message\": \"Streaming error\"}}\\n\\n');\n reply.raw.end();\n }\n\n return reply;\n }\n\n private async handleNonStreamingRequest(\n // biome-ignore lint/suspicious/noExplicitAny: o sdk integration boundary\n aisdkParams: any,\n openaiRequest: OpenAIChatRequest,\n reply: FastifyReply\n ): Promise<void> {\n try {\n const mergedTools = this.mergeTools(this.config.tools, aisdkParams.tools);\n const result = await generateText({\n model: this.config.model,\n ...aisdkParams,\n ...(mergedTools ? { tools: mergedTools } : {}),\n });\n\n const openaiResponse = convertAISDKResultToOpenAI(\n result,\n openaiRequest.model,\n false\n );\n\n reply.send(openaiResponse);\n } catch (error) {\n this.logger.error(\"Generation error:\", error);\n return reply.code(500).send({\n error: {\n message: \"Generation failed\",\n type: \"generation_error\",\n },\n });\n }\n }\n\n async start(): Promise<void> {\n try {\n await this.fastify.listen({\n port: this.config.port || 3000,\n host: this.config.host || \"localhost\",\n });\n\n this.logger.info(\n `🚀 OpenAI Proxy Server running on http://${this.config.host}:${this.config.port}`\n );\n this.logger.info(\n `📡 Endpoint: http://${this.config.host}:${this.config.port}/v1/chat/completions`\n );\n this.logger.info(\n `🏥 Health: http://${this.config.host}:${this.config.port}/health`\n );\n } catch (error) {\n this.logger.error(\"Failed to start server:\", error);\n process.exit(1);\n }\n }\n\n async stop(): Promise<void> {\n try {\n await this.fastify.close();\n this.logger.info(\"🛑 Server stopped\");\n } catch (error) {\n this.logger.error(\"Error stopping server:\", error);\n }\n }\n}\n"],"mappings":"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","names":["_a","import_zod","_a","Fastify","cors"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/openai-request-converter.ts","../src/response-utils.ts","../src/response-converter.ts","../src/server.ts"],"sourcesContent":["// biome-ignore lint/performance/noBarrelFile: Package entrypoint - must re-export for public API\nexport {\n convertAISDKToolCallsToOpenAI,\n convertOpenAIRequestToAISDK,\n} from \"./openai-request-converter.js\";\nexport {\n convertAISDKResultToOpenAI,\n convertAISDKStreamChunkToOpenAI,\n createOpenAIStreamConverter,\n createSSEResponse,\n} from \"./response-converter.js\";\nexport { generateResponseId, getCurrentTimestamp } from \"./response-utils.js\";\nexport { OpenAIProxyServer } from \"./server.js\";\nexport type {\n AISDKTool,\n Logger,\n OpenAIChatRequest,\n OpenAIChatResponse,\n OpenAIChoice,\n OpenAIMessage,\n OpenAITool,\n OpenAIToolCall,\n OpenAIUsage,\n ProxyConfig,\n StreamChunk,\n} from \"./types.js\";\n","import type {\n ModelMessage,\n ToolContent,\n ToolResultOutput,\n} from \"@ai-sdk/provider-utils\";\nimport { z } from \"zod\";\nimport type {\n OpenAIChatRequest,\n OpenAICompleteToolCall,\n OpenAIMessage,\n ProxyConfig,\n} from \"./types.js\";\n\n// Type definitions for OpenAI tool parameters\ninterface OpenAIToolProperty {\n type: string;\n description?: string;\n enum?: string[];\n}\n\ninterface OpenAIToolParameters {\n type: string;\n properties?: Record<string, OpenAIToolProperty>;\n required?: string[];\n}\n\n// Type for AI SDK tool definition\ninterface AISDKTool {\n description: string;\n inputSchema: z.ZodTypeAny;\n}\n\n// Type for tool call object\ninterface ToolCall {\n toolName: string;\n args: unknown;\n}\n\n/**\n * Create Zod schema for OpenAI tool property\n */\nfunction createZodSchema(prop: OpenAIToolProperty): z.ZodTypeAny {\n if (prop.type === \"string\") {\n return prop.enum ? z.enum(prop.enum as [string, ...string[]]) : z.string();\n }\n if (prop.type === \"number\") {\n return z.number();\n }\n if (prop.type === \"boolean\") {\n return z.boolean();\n }\n if (prop.type === \"array\") {\n return z.array(z.any());\n }\n if (prop.type === \"object\") {\n return z.object({});\n }\n return z.any();\n}\n\n/**\n * Convert OpenAI tool schema to Zod schema\n */\nfunction convertOpenAIToolToZod(\n parameters: Record<string, unknown> | undefined\n): z.ZodObject<Record<string, z.ZodTypeAny>> {\n if (!parameters) {\n return z.object({});\n }\n\n const params = parameters as unknown as OpenAIToolParameters;\n if (!params.properties) {\n return z.object({});\n }\n\n const schemaShape: Record<string, z.ZodTypeAny> = {};\n for (const [key, prop] of Object.entries(params.properties)) {\n schemaShape[key] = createZodSchema(prop);\n }\n\n return z.object(schemaShape);\n}\n\n/**\n * Convert OpenAI tools to AI SDK format\n */\nfunction convertOpenAITools(\n openaiTools:\n | Array<{\n function: {\n name: string;\n description?: string;\n parameters: Record<string, unknown>;\n };\n }>\n | undefined\n): Record<string, AISDKTool> {\n const aisdkTools: Record<string, AISDKTool> = {};\n\n if (!openaiTools) {\n return aisdkTools;\n }\n\n for (const openaiTool of openaiTools) {\n const toolName = openaiTool.function.name;\n aisdkTools[toolName] = {\n description: openaiTool.function.description || \"\",\n inputSchema: convertOpenAIToolToZod(openaiTool.function.parameters),\n };\n }\n\n return aisdkTools;\n}\n\n/**\n * Convert stop parameter to stop sequences\n */\nfunction convertStopToSequences(\n stop: string | string[] | undefined\n): string[] | undefined {\n if (!stop) {\n return;\n }\n return Array.isArray(stop) ? stop : [stop];\n}\n\ninterface AITextPart {\n type: \"text\";\n text: string;\n}\ninterface AIToolCallPart {\n type: \"tool-call\";\n toolCallId: string;\n toolName: string;\n input: unknown;\n}\ntype TextToolOutput = Extract<ToolResultOutput, { type: \"text\" }>;\ntype JsonToolOutput = Extract<ToolResultOutput, { type: \"json\" }>;\n\n/**\n * Convert OpenAI chat completion request to AI SDK format\n */\nexport function normalizeMessageContent(\n content: OpenAIMessage[\"content\"]\n): AITextPart[] {\n if (typeof content === \"string\") {\n return content ? [{ type: \"text\" as const, text: content }] : [];\n }\n\n if (Array.isArray(content)) {\n const parts = content as Array<string | { text?: unknown }>;\n return parts\n .map((part) => {\n if (typeof part === \"string\") {\n return part;\n }\n if (part && typeof part === \"object\" && \"text\" in part) {\n const textValue = part.text;\n if (typeof textValue === \"string\") {\n return textValue;\n }\n if (textValue !== undefined) {\n return JSON.stringify(textValue);\n }\n }\n return JSON.stringify(part);\n })\n .filter((text): text is string => Boolean(text))\n .map((text) => ({ type: \"text\" as const, text }));\n }\n\n if (content === null || content === undefined) {\n return [];\n }\n\n if (typeof content === \"object\") {\n return [{ type: \"text\" as const, text: JSON.stringify(content) }];\n }\n\n return [{ type: \"text\" as const, text: String(content) }];\n}\n\nfunction buildToolCallParts(\n toolCalls: OpenAICompleteToolCall[]\n): AIToolCallPart[] {\n return toolCalls.map((toolCall) => {\n let parsedArgs: unknown = toolCall.function.arguments;\n if (typeof toolCall.function.arguments === \"string\") {\n try {\n parsedArgs = JSON.parse(toolCall.function.arguments || \"{}\");\n } catch {\n parsedArgs = toolCall.function.arguments;\n }\n }\n\n return {\n type: \"tool-call\" as const,\n toolCallId: toolCall.id,\n toolName: toolCall.function.name,\n input: parsedArgs,\n } satisfies AIToolCallPart;\n });\n}\n\nfunction buildAssistantContent(\n message: OpenAIMessage & { role: \"assistant\" }\n): Array<AITextPart | AIToolCallPart> | string {\n const textParts = normalizeMessageContent(message.content);\n const toolCallParts = message.tool_calls?.length\n ? buildToolCallParts(message.tool_calls)\n : [];\n\n if (toolCallParts.length === 0) {\n if (textParts.length === 0) {\n return \"\";\n }\n if (textParts.length === 1) {\n return textParts[0].text;\n }\n return textParts;\n }\n\n return [...textParts, ...toolCallParts];\n}\n\nfunction isJsonValue(value: unknown): value is JsonToolOutput[\"value\"] {\n if (\n value === null ||\n typeof value === \"string\" ||\n typeof value === \"number\" ||\n typeof value === \"boolean\"\n ) {\n return true;\n }\n\n if (Array.isArray(value)) {\n return value.every(isJsonValue);\n }\n\n if (typeof value === \"object\") {\n return Object.values(value as Record<string, unknown>).every(isJsonValue);\n }\n\n return false;\n}\n\nfunction buildToolOutput(rawValue: string): ToolResultOutput {\n if (!rawValue) {\n return { type: \"text\", value: \"\" } satisfies TextToolOutput;\n }\n\n try {\n const parsed = JSON.parse(rawValue);\n if (isJsonValue(parsed)) {\n return { type: \"json\", value: parsed } satisfies JsonToolOutput;\n }\n } catch {\n // Fall through to text output below\n }\n\n return { type: \"text\", value: rawValue } satisfies TextToolOutput;\n}\n\nfunction buildToolContent(\n message: OpenAIMessage & { role: \"tool\" },\n toolNameLookup: Map<string, string>\n): ToolContent {\n const textParts = normalizeMessageContent(message.content);\n const combined = textParts.map((part) => part.text).join(\"\\n\");\n const toolCallId = message.tool_call_id ?? \"\";\n const toolName = toolCallId\n ? (toolNameLookup.get(toolCallId) ?? toolCallId)\n : \"\";\n\n return [\n {\n type: \"tool-result\",\n toolCallId,\n toolName,\n output: buildToolOutput(combined),\n },\n ];\n}\n\nfunction convertMessageToModelMessage(\n message: OpenAIMessage,\n toolNameLookup: Map<string, string>\n): ModelMessage {\n if (message.role === \"assistant\") {\n if (message.tool_calls?.length) {\n for (const toolCall of message.tool_calls) {\n toolNameLookup.set(toolCall.id, toolCall.function.name);\n }\n }\n\n return {\n role: \"assistant\",\n content: buildAssistantContent(\n message as OpenAIMessage & { role: \"assistant\" }\n ),\n };\n }\n\n if (message.role === \"tool\") {\n return {\n role: \"tool\",\n content: buildToolContent(\n message as OpenAIMessage & { role: \"tool\" },\n toolNameLookup\n ),\n };\n }\n\n if (message.role === \"system\") {\n const text = normalizeMessageContent(message.content)\n .map((part) => part.text)\n .join(\"\\n\");\n return {\n role: \"system\",\n content: text,\n };\n }\n\n const userParts = normalizeMessageContent(message.content);\n if (userParts.length === 0) {\n return {\n role: \"user\",\n content: \"\",\n };\n }\n\n if (userParts.length === 1) {\n return {\n role: \"user\",\n content: userParts[0].text,\n };\n }\n\n return {\n role: \"user\",\n content: userParts,\n };\n}\n\nexport function convertOpenAIRequestToAISDK(\n openaiRequest: OpenAIChatRequest,\n proxyConfig?: Pick<ProxyConfig, \"parserDebug\">\n) {\n const {\n messages,\n tools: openaiTools,\n temperature,\n max_tokens,\n stop,\n tool_choice,\n } = openaiRequest;\n\n const toolNameLookup = new Map<string, string>();\n\n const aiMessages: ModelMessage[] = messages.map((message) =>\n convertMessageToModelMessage(message, toolNameLookup)\n );\n\n // Convert OpenAI tools to AI SDK format dynamically\n const aisdkTools = convertOpenAITools(openaiTools);\n\n const providerOptions = proxyConfig?.parserDebug\n ? {\n toolCallMiddleware: {\n debugLevel: proxyConfig.parserDebug.level,\n logErrors: proxyConfig.parserDebug.logErrors,\n captureSummary: proxyConfig.parserDebug.captureSummary,\n },\n }\n : undefined;\n\n return {\n messages: aiMessages,\n tools: aisdkTools,\n temperature,\n maxOutputTokens: max_tokens,\n stopSequences: convertStopToSequences(stop),\n toolChoice: mapOpenAIToolChoice(tool_choice),\n ...(providerOptions ? { providerOptions } : {}),\n };\n}\n\n// Map OpenAI tool_choice to AI SDK toolChoice\nexport function mapOpenAIToolChoice(\n choice: OpenAIChatRequest[\"tool_choice\"]\n): \"auto\" | \"none\" | { type: \"tool\"; toolName: string } | undefined {\n if (!choice) {\n return;\n }\n if (choice === \"auto\" || choice === \"none\") {\n return choice;\n }\n if (typeof choice === \"object\" && choice.type === \"function\") {\n return { type: \"tool\", toolName: choice.function.name };\n }\n return;\n}\n\n/**\n * Convert AI SDK tool calls to OpenAI format\n */\nexport function convertAISDKToolCallsToOpenAI(toolCalls: ToolCall[]): Array<{\n id: string;\n type: \"function\";\n function: {\n name: string;\n arguments: string;\n };\n}> {\n return toolCalls.map((call) => ({\n id: `call_${Date.now()}_${Math.random().toString(36).slice(2, 11)}`,\n type: \"function\" as const,\n function: {\n name: call.toolName,\n arguments: JSON.stringify(call.args),\n },\n }));\n}\n","export function generateResponseId(): string {\n return `chatcmpl-${Date.now()}-${Math.random().toString(36).slice(2, 11)}`;\n}\n\nexport function getCurrentTimestamp(): number {\n return Math.floor(Date.now() / 1000);\n}\n","import { generateResponseId, getCurrentTimestamp } from \"./response-utils.js\";\nimport type {\n OpenAIChatResponse,\n OpenAIChoice,\n OpenAIStreamingToolCall,\n OpenAIUsage,\n StreamChunk,\n} from \"./types.js\";\n\n/**\n * Convert AI SDK result to OpenAI chat completion response\n */\nexport function convertAISDKResultToOpenAI(\n // biome-ignore lint/suspicious/noExplicitAny: AI sdk integration boundary\n aisdkResult: any,\n model: string,\n stream = false\n): OpenAIChatResponse {\n const choices: OpenAIChoice[] = [];\n\n // Handle text content\n if (aisdkResult.text) {\n const choice: OpenAIChoice = {\n index: 0,\n finish_reason: aisdkResult.finishReason || \"stop\",\n };\n\n if (stream) {\n choice.delta = {\n role: \"assistant\",\n content: aisdkResult.text,\n };\n } else {\n choice.message = {\n role: \"assistant\",\n content: aisdkResult.text,\n };\n }\n choices.push(choice);\n }\n\n // Handle tool calls\n if (aisdkResult.toolCalls && aisdkResult.toolCalls.length > 0) {\n const choice: OpenAIChoice = {\n index: 0,\n finish_reason: \"tool_calls\",\n };\n\n const openAIToolCalls = aisdkResult.toolCalls?.map(\n (\n // biome-ignore lint/suspicious/noExplicitAny: AI SDK integration boundary\n call: any\n ) => ({\n id: `call_${Date.now()}_${Math.random().toString(36).slice(2, 11)}`,\n type: \"function\" as const,\n function: {\n name: call.toolName,\n arguments: JSON.stringify(call.args),\n },\n })\n );\n\n if (stream) {\n choice.delta = {\n role: \"assistant\",\n tool_calls: openAIToolCalls,\n };\n } else {\n choice.message = {\n role: \"assistant\",\n content: null,\n tool_calls: openAIToolCalls,\n };\n }\n\n choices.push(choice);\n }\n\n const response: OpenAIChatResponse = {\n id: generateResponseId(),\n object: stream ? \"chat.completion.chunk\" : \"chat.completion\",\n created: getCurrentTimestamp(),\n model,\n choices,\n };\n\n // Add usage if available\n if (aisdkResult.usage) {\n response.usage = {\n prompt_tokens: aisdkResult.usage.promptTokens || 0,\n completion_tokens: aisdkResult.usage.completionTokens || 0,\n total_tokens: aisdkResult.usage.totalTokens || 0,\n } as OpenAIUsage;\n }\n\n return response;\n}\n\n/**\n * Convert AI SDK stream chunk to OpenAI SSE format\n */\n\n// Type definitions for better type safety\ninterface ToolCallDelta {\n index?: number;\n id?: string;\n type?: \"function\";\n function?: {\n name?: string;\n arguments?: string;\n };\n}\n\ninterface AIStreamChunk {\n type: string;\n id?: string;\n text?: string;\n toolCallId?: string;\n toolName?: string;\n args?: string;\n input?: Record<string, unknown>;\n finishReason?: string;\n [key: string]: unknown;\n}\n\ntype ChunkHandler = (chunk: AIStreamChunk, model: string) => StreamChunk[];\n\n// Helper function to create finish response\nfunction createFinishResponse(\n model: string,\n finishReason: string,\n responseId: string\n): OpenAIChatResponse {\n // Ensure finish reason matches OpenAI's allowed types\n let validFinishReason: \"stop\" | \"length\" | \"tool_calls\" | \"content_filter\";\n\n if (finishReason === \"tool_calls\" || finishReason === \"tool-calls\") {\n validFinishReason = \"tool_calls\";\n } else if (finishReason === \"stop\") {\n validFinishReason = \"stop\";\n } else if (finishReason === \"length\") {\n validFinishReason = \"length\";\n } else if (finishReason === \"content_filter\") {\n validFinishReason = \"content_filter\";\n } else {\n validFinishReason = \"stop\"; // fallback to \"stop\" for unknown reasons\n }\n\n return {\n id: responseId,\n object: \"chat.completion.chunk\",\n created: getCurrentTimestamp(),\n model,\n choices: [\n {\n index: 0,\n delta: {},\n finish_reason: validFinishReason,\n },\n ],\n };\n}\n\n// Helper function to create content response\nfunction createContentResponse(\n model: string,\n content: string,\n responseId: string,\n isReasoning = false\n): OpenAIChatResponse {\n const delta: Record<string, unknown> = { role: \"assistant\" };\n\n if (isReasoning) {\n delta.reasoning_content = content;\n } else {\n delta.content = content;\n }\n\n return {\n id: responseId,\n object: \"chat.completion.chunk\",\n created: getCurrentTimestamp(),\n model,\n choices: [\n {\n index: 0,\n delta,\n },\n ],\n };\n}\n\n// Helper function to create tool call response\nfunction createToolCallResponse(\n model: string,\n toolCall: ToolCallDelta,\n responseId: string,\n includeRole = false\n): OpenAIChatResponse {\n return {\n id: responseId,\n object: \"chat.completion.chunk\",\n created: getCurrentTimestamp(),\n model,\n choices: [\n {\n index: 0,\n delta: {\n ...(includeRole ? { role: \"assistant\" as const } : {}),\n tool_calls: [\n {\n index: toolCall.index || 0,\n type: \"function\" as const,\n function: {\n name: toolCall.function?.name || \"\",\n arguments: toolCall.function?.arguments || \"\",\n },\n },\n ],\n },\n },\n ],\n };\n}\n\n// (legacy stateless handler removed)\n\nexport function createOpenAIStreamConverter(\n model: string,\n options?: {\n logChunks?: boolean;\n }\n) {\n let streamHasToolCalls = false;\n let streamFinishSent = false;\n let streamResponseId = generateResponseId();\n\n const logChunk =\n options?.logChunks === false\n ? undefined\n : (chunk: unknown) => {\n const logType =\n process.env.USE_MIDDLEWARE === \"true\" ? \"middleware\" : \"native\";\n console.log(\n `🔍 AI SDK Chunk [${logType}]:`,\n JSON.stringify(chunk, null, 2)\n );\n };\n\n const handlers: Record<string, ChunkHandler> = {\n start: () => [],\n \"reasoning-delta\": (chunk) => {\n if (!chunk.text) {\n return [];\n }\n return [\n {\n data: JSON.stringify(\n createContentResponse(model, chunk.text, streamResponseId, true)\n ),\n },\n ];\n },\n \"text-delta\": (chunk) => {\n if (!chunk.text) {\n return [];\n }\n return [\n {\n data: JSON.stringify(\n createContentResponse(model, chunk.text, streamResponseId, false)\n ),\n },\n ];\n },\n \"tool-call\": (chunk) => {\n const toolCallId = chunk.toolCallId || `call_${generateResponseId()}`;\n const toolName = chunk.toolName || \"\";\n const argsString =\n typeof chunk.input === \"string\"\n ? chunk.input\n : JSON.stringify(chunk.input ?? {});\n const toolCallDelta: OpenAIStreamingToolCall = {\n index: 0,\n id: toolCallId,\n type: \"function\",\n function: { name: toolName, arguments: argsString },\n };\n const response = createToolCallResponse(\n model,\n toolCallDelta,\n streamResponseId,\n true\n );\n return [{ data: JSON.stringify(response) }];\n },\n \"reasoning-end\": () => [],\n \"text-end\": () => [],\n \"finish-step\": (chunk) => {\n if (streamFinishSent) {\n return [];\n }\n const hadToolCalls = streamHasToolCalls;\n let finishReason = chunk.finishReason || \"stop\";\n if (finishReason === \"tool_calls\" || finishReason === \"tool-calls\") {\n finishReason = \"tool_calls\";\n }\n const resolvedReason = hadToolCalls ? \"tool_calls\" : finishReason;\n streamFinishSent = true;\n streamHasToolCalls = false;\n return [\n {\n data: JSON.stringify(\n createFinishResponse(model, resolvedReason, streamResponseId)\n ),\n },\n ];\n },\n \"tool-call-delta\": (chunk) => {\n const toolCall = {\n index: chunk.toolCallId ? Number(chunk.toolCallId) : 0,\n type: \"function\" as const,\n function: {\n name: chunk.toolName || \"\",\n arguments: chunk.args || \"\",\n },\n };\n return [\n {\n data: JSON.stringify(\n createToolCallResponse(model, toolCall, streamResponseId)\n ),\n },\n ];\n },\n \"tool-result\": (chunk) => {\n const resultText = `\\n[Tool: ${chunk.toolName} returned ${JSON.stringify(chunk.output)}]\\n`;\n return [\n {\n data: JSON.stringify(\n createContentResponse(model, resultText, streamResponseId, false)\n ),\n },\n ];\n },\n finish: (chunk) => {\n if (streamFinishSent) {\n return [];\n }\n const hadToolCalls = streamHasToolCalls;\n let finishReason = chunk.finishReason || \"stop\";\n if (finishReason === \"tool_calls\" || finishReason === \"tool-calls\") {\n finishReason = \"tool_calls\";\n }\n const resolvedReason = hadToolCalls ? \"tool_calls\" : finishReason;\n streamFinishSent = true;\n streamHasToolCalls = false;\n return [\n {\n data: JSON.stringify(\n createFinishResponse(model, resolvedReason, streamResponseId)\n ),\n },\n ];\n },\n };\n\n return (\n // biome-ignore lint/suspicious/noExplicitAny: ai sdk boundary\n chunk: any\n ): StreamChunk[] => {\n const out: StreamChunk[] = [];\n\n logChunk?.(chunk);\n\n if (chunk.type === \"start\") {\n streamHasToolCalls = false;\n streamFinishSent = false;\n streamResponseId = chunk.id ?? generateResponseId();\n }\n\n const handler = handlers[chunk.type];\n if (handler) {\n const result = handler(chunk as AIStreamChunk, model);\n if (chunk.type === \"tool-call\" || chunk.type === \"tool-call-delta\") {\n streamHasToolCalls = true;\n }\n out.push(...result);\n } else {\n console.warn(`⚠️ Unknown AI SDK chunk type: ${chunk.type}`, chunk);\n }\n\n if (chunk.type === \"finish-step\" || chunk.type === \"finish\") {\n streamHasToolCalls = false;\n }\n\n return out.filter((resultChunk) => {\n try {\n const parsed = JSON.parse(resultChunk.data);\n const delta = parsed.choices?.[0]?.delta;\n return (\n delta &&\n (delta.role ||\n delta.content ||\n (delta as NonNullable<OpenAIChoice[\"delta\"]>).reasoning_content ||\n (delta.tool_calls && delta.tool_calls.length > 0) ||\n parsed.choices?.[0]?.finish_reason)\n );\n } catch {\n return true;\n }\n });\n };\n}\n\nexport function convertAISDKStreamChunkToOpenAI(\n // biome-ignore lint/suspicious/noExplicitAny: o sdk integration boundary\n chunk: any,\n model: string\n): StreamChunk[] {\n const convert = createOpenAIStreamConverter(model);\n return convert(chunk);\n}\n\n/**\n * Create SSE formatted response\n */\nexport function createSSEResponse(chunks: StreamChunk[]): string {\n return chunks.map((chunk) => `data: ${chunk.data}\\n\\n`).join(\"\");\n}\n","import { zodSchema } from \"@ai-sdk/provider-utils\";\nimport cors from \"@fastify/cors\";\nimport { generateText, streamText } from \"ai\";\nimport Fastify, {\n type FastifyInstance,\n type FastifyReply,\n type FastifyRequest,\n} from \"fastify\";\nimport { toJSONSchema, type ZodTypeAny } from \"zod\";\nimport { convertOpenAIRequestToAISDK } from \"./openai-request-converter.js\";\nimport {\n convertAISDKResultToOpenAI,\n createOpenAIStreamConverter,\n} from \"./response-converter.js\";\nimport type {\n AISDKTool,\n Logger,\n OpenAIChatRequest,\n ProxyConfig,\n} from \"./types.js\";\n\ntype ConvertedParams = ReturnType<typeof convertOpenAIRequestToAISDK>;\n\nfunction serializeZodSchema(schema: ZodTypeAny | undefined): unknown {\n if (!schema) {\n return null;\n }\n\n // Use Zod v4's built-in JSON Schema conversion\n const jsonSchema = toJSONSchema(schema, {\n unrepresentable: \"any\",\n });\n\n // Remove $schema field for cleaner output\n if (typeof jsonSchema === \"object\" && jsonSchema !== null) {\n const { $schema, ...rest } = jsonSchema as Record<string, unknown>;\n return rest;\n }\n\n return jsonSchema;\n}\n\nfunction serializeMessages(messages: OpenAIChatRequest[\"messages\"]) {\n return messages.map((message, index) => ({\n index,\n role: message.role,\n content: message.content,\n toolCalls: message.tool_calls,\n }));\n}\n\nfunction logIncomingRequest(\n openaiRequest: OpenAIChatRequest,\n enabled: boolean\n) {\n if (!enabled) {\n return;\n }\n const toolNames = (openaiRequest.tools ?? [])\n .map((tool) => (\"function\" in tool ? tool.function?.name : undefined))\n .filter((name): name is string => Boolean(name));\n\n console.log(\n \"[proxy] Incoming OpenAI request\",\n JSON.stringify(\n {\n model: openaiRequest.model,\n stream: Boolean(openaiRequest.stream),\n temperature: openaiRequest.temperature,\n maxTokens: openaiRequest.max_tokens,\n toolNames,\n toolChoice: openaiRequest.tool_choice,\n messages: serializeMessages(openaiRequest.messages),\n tools: openaiRequest.tools,\n },\n null,\n 2\n )\n );\n}\n\nfunction serializeAISDKMessages(messages: ConvertedParams[\"messages\"]) {\n return messages?.map((message, index) => ({\n index,\n role: message.role,\n content: message.content,\n }));\n}\n\nfunction logRequestConversion(\n openaiRequest: OpenAIChatRequest,\n aisdkParams: ConvertedParams,\n enabled: boolean\n) {\n if (!enabled) {\n return;\n }\n const messages = aisdkParams.messages ?? [];\n console.log(\n \"[proxy] Converted AI SDK params\",\n JSON.stringify(\n {\n model: openaiRequest.model,\n hasSystemMessage: messages.some((message) => message.role === \"system\"),\n messages: serializeAISDKMessages(messages),\n tools: Object.entries(aisdkParams.tools ?? {}).map(([name, tool]) => ({\n name,\n description: tool.description,\n inputSchema: serializeZodSchema(tool.inputSchema),\n })),\n temperature: aisdkParams.temperature,\n maxOutputTokens: aisdkParams.maxOutputTokens,\n stopSequences: aisdkParams.stopSequences,\n },\n null,\n 2\n )\n );\n}\n\nexport class OpenAIProxyServer {\n private readonly fastify: FastifyInstance;\n private readonly config: ProxyConfig;\n private readonly logger: Logger;\n\n constructor(config: ProxyConfig) {\n this.config = {\n port: 3000,\n host: \"localhost\",\n cors: true,\n ...config,\n };\n this.logger = (config.logger ?? console) as Logger;\n\n this.fastify = Fastify();\n\n // Enable CORS\n if (this.config.cors) {\n this.fastify.register(cors);\n }\n\n this.setupRoutes();\n }\n\n private setupRoutes(): void {\n // Health check endpoint\n this.fastify.get(\n \"/health\",\n async (_request: FastifyRequest, _reply: FastifyReply) => ({\n status: \"ok\",\n timestamp: new Date().toISOString(),\n })\n );\n\n // OpenAI-compatible chat completions endpoint\n this.fastify.post(\n \"/v1/chat/completions\",\n (request: FastifyRequest, reply: FastifyReply) => {\n try {\n const openaiRequest = request.body as OpenAIChatRequest;\n\n // Validate request\n if (\n !(openaiRequest.messages && Array.isArray(openaiRequest.messages))\n ) {\n return reply.code(400).send({\n error: {\n message: \"Messages array is required\",\n type: \"invalid_request_error\",\n },\n });\n }\n\n logIncomingRequest(\n openaiRequest,\n this.config.logging?.requests ?? true\n );\n\n // Convert OpenAI request to AI SDK format\n const aisdkParams = convertOpenAIRequestToAISDK(openaiRequest, {\n parserDebug: this.config.parserDebug,\n });\n logRequestConversion(\n openaiRequest,\n aisdkParams,\n this.config.logging?.conversions ?? true\n );\n\n // Handle streaming vs non-streaming\n if (openaiRequest.stream) {\n return this.handleStreamingRequest(\n aisdkParams,\n openaiRequest,\n reply\n );\n }\n return this.handleNonStreamingRequest(\n aisdkParams,\n openaiRequest,\n reply\n );\n } catch (error) {\n this.logger.error(\"Request handling error:\", error);\n return reply.code(500).send({\n error: {\n message: \"Internal server error\",\n type: \"server_error\",\n },\n });\n }\n }\n );\n\n // Models endpoint\n this.fastify.get(\"/v1/models\", async () => ({\n object: \"list\",\n data: [\n {\n id: \"wrapped-model\",\n object: \"model\",\n created: Math.floor(Date.now() / 1000),\n owned_by: \"ai-sdk-tool-proxy\",\n },\n ],\n }));\n }\n\n // Merge server-defined tools (with execute) and request-defined tools (schema-only)\n // Server tools take precedence when names overlap.\n private mergeTools(\n serverTools?: Record<string, AISDKTool>,\n requestTools?: Record<string, AISDKTool>\n ) {\n const toProviderTool = (tool: AISDKTool | undefined): unknown => {\n if (!tool) {\n return;\n }\n\n return {\n description: tool.description,\n inputSchema: zodSchema(tool.inputSchema),\n ...(tool.execute ? { execute: tool.execute } : {}),\n };\n };\n\n const merged: Record<string, unknown> = {};\n\n for (const [name, t] of Object.entries(requestTools ?? {})) {\n const pt = toProviderTool(t);\n if (pt) {\n merged[name] = pt;\n }\n }\n\n for (const [name, t] of Object.entries(serverTools ?? {})) {\n const pt = toProviderTool(t);\n if (pt) {\n merged[name] = pt; // override request tool\n }\n }\n\n return Object.keys(merged).length > 0 ? merged : undefined;\n }\n\n private async handleStreamingRequest(\n // biome-ignore lint/suspicious/noExplicitAny: o sdk integration boundary\n aisdkParams: any,\n openaiRequest: OpenAIChatRequest,\n reply: FastifyReply\n ): Promise<void> {\n // Set SSE headers\n reply.raw.writeHead(200, {\n \"Content-Type\": \"text/event-stream\",\n \"Cache-Control\": \"no-cache\",\n Connection: \"keep-alive\",\n \"Access-Control-Allow-Origin\": \"*\",\n });\n\n try {\n const mergedTools = this.mergeTools(this.config.tools, aisdkParams.tools);\n const result = await streamText({\n model: this.config.model,\n ...aisdkParams,\n ...(mergedTools ? { tools: mergedTools } : {}),\n });\n\n const convert = createOpenAIStreamConverter(openaiRequest.model, {\n logChunks: this.config.logging?.streamChunks ?? true,\n });\n for await (const chunk of result.fullStream) {\n const openaiChunks = convert(chunk);\n for (const openaiChunk of openaiChunks) {\n reply.raw.write(`data: ${openaiChunk.data}\\n\\n`);\n }\n }\n\n reply.raw.write(\"data: [DONE]\\n\\n\");\n reply.raw.end();\n } catch (error) {\n this.logger.error(\"Streaming error:\", error);\n reply.raw.write('data: {\"error\": {\"message\": \"Streaming error\"}}\\n\\n');\n reply.raw.end();\n }\n\n return reply;\n }\n\n private async handleNonStreamingRequest(\n // biome-ignore lint/suspicious/noExplicitAny: o sdk integration boundary\n aisdkParams: any,\n openaiRequest: OpenAIChatRequest,\n reply: FastifyReply\n ): Promise<void> {\n try {\n const mergedTools = this.mergeTools(this.config.tools, aisdkParams.tools);\n const result = await generateText({\n model: this.config.model,\n ...aisdkParams,\n ...(mergedTools ? { tools: mergedTools } : {}),\n });\n\n const openaiResponse = convertAISDKResultToOpenAI(\n result,\n openaiRequest.model,\n false\n );\n\n reply.send(openaiResponse);\n } catch (error) {\n this.logger.error(\"Generation error:\", error);\n return reply.code(500).send({\n error: {\n message: \"Generation failed\",\n type: \"generation_error\",\n },\n });\n }\n }\n\n async start(): Promise<void> {\n try {\n await this.fastify.listen({\n port: this.config.port || 3000,\n host: this.config.host || \"localhost\",\n });\n\n this.logger.info(\n `🚀 OpenAI Proxy Server running on http://${this.config.host}:${this.config.port}`\n );\n this.logger.info(\n `📡 Endpoint: http://${this.config.host}:${this.config.port}/v1/chat/completions`\n );\n this.logger.info(\n `🏥 Health: http://${this.config.host}:${this.config.port}/health`\n );\n } catch (error) {\n this.logger.error(\"Failed to start server:\", error);\n process.exit(1);\n }\n }\n\n async stop(): Promise<void> {\n try {\n await this.fastify.close();\n this.logger.info(\"🛑 Server stopped\");\n } catch (error) {\n this.logger.error(\"Error stopping server:\", error);\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACKA,iBAAkB;AAoClB,SAAS,gBAAgB,MAAwC;AAC/D,MAAI,KAAK,SAAS,UAAU;AAC1B,WAAO,KAAK,OAAO,aAAE,KAAK,KAAK,IAA6B,IAAI,aAAE,OAAO;AAAA,EAC3E;AACA,MAAI,KAAK,SAAS,UAAU;AAC1B,WAAO,aAAE,OAAO;AAAA,EAClB;AACA,MAAI,KAAK,SAAS,WAAW;AAC3B,WAAO,aAAE,QAAQ;AAAA,EACnB;AACA,MAAI,KAAK,SAAS,SAAS;AACzB,WAAO,aAAE,MAAM,aAAE,IAAI,CAAC;AAAA,EACxB;AACA,MAAI,KAAK,SAAS,UAAU;AAC1B,WAAO,aAAE,OAAO,CAAC,CAAC;AAAA,EACpB;AACA,SAAO,aAAE,IAAI;AACf;AAKA,SAAS,uBACP,YAC2C;AAC3C,MAAI,CAAC,YAAY;AACf,WAAO,aAAE,OAAO,CAAC,CAAC;AAAA,EACpB;AAEA,QAAM,SAAS;AACf,MAAI,CAAC,OAAO,YAAY;AACtB,WAAO,aAAE,OAAO,CAAC,CAAC;AAAA,EACpB;AAEA,QAAM,cAA4C,CAAC;AACnD,aAAW,CAAC,KAAK,IAAI,KAAK,OAAO,QAAQ,OAAO,UAAU,GAAG;AAC3D,gBAAY,GAAG,IAAI,gBAAgB,IAAI;AAAA,EACzC;AAEA,SAAO,aAAE,OAAO,WAAW;AAC7B;AAKA,SAAS,mBACP,aAS2B;AAC3B,QAAM,aAAwC,CAAC;AAE/C,MAAI,CAAC,aAAa;AAChB,WAAO;AAAA,EACT;AAEA,aAAW,cAAc,aAAa;AACpC,UAAM,WAAW,WAAW,SAAS;AACrC,eAAW,QAAQ,IAAI;AAAA,MACrB,aAAa,WAAW,SAAS,eAAe;AAAA,MAChD,aAAa,uBAAuB,WAAW,SAAS,UAAU;AAAA,IACpE;AAAA,EACF;AAEA,SAAO;AACT;AAKA,SAAS,uBACP,MACsB;AACtB,MAAI,CAAC,MAAM;AACT;AAAA,EACF;AACA,SAAO,MAAM,QAAQ,IAAI,IAAI,OAAO,CAAC,IAAI;AAC3C;AAkBO,SAAS,wBACd,SACc;AACd,MAAI,OAAO,YAAY,UAAU;AAC/B,WAAO,UAAU,CAAC,EAAE,MAAM,QAAiB,MAAM,QAAQ,CAAC,IAAI,CAAC;AAAA,EACjE;AAEA,MAAI,MAAM,QAAQ,OAAO,GAAG;AAC1B,UAAM,QAAQ;AACd,WAAO,MACJ,IAAI,CAAC,SAAS;AACb,UAAI,OAAO,SAAS,UAAU;AAC5B,eAAO;AAAA,MACT;AACA,UAAI,QAAQ,OAAO,SAAS,YAAY,UAAU,MAAM;AACtD,cAAM,YAAY,KAAK;AACvB,YAAI,OAAO,cAAc,UAAU;AACjC,iBAAO;AAAA,QACT;AACA,YAAI,cAAc,QAAW;AAC3B,iBAAO,KAAK,UAAU,SAAS;AAAA,QACjC;AAAA,MACF;AACA,aAAO,KAAK,UAAU,IAAI;AAAA,IAC5B,CAAC,EACA,OAAO,CAAC,SAAyB,QAAQ,IAAI,CAAC,EAC9C,IAAI,CAAC,UAAU,EAAE,MAAM,QAAiB,KAAK,EAAE;AAAA,EACpD;AAEA,MAAI,YAAY,QAAQ,YAAY,QAAW;AAC7C,WAAO,CAAC;AAAA,EACV;AAEA,MAAI,OAAO,YAAY,UAAU;AAC/B,WAAO,CAAC,EAAE,MAAM,QAAiB,MAAM,KAAK,UAAU,OAAO,EAAE,CAAC;AAAA,EAClE;AAEA,SAAO,CAAC,EAAE,MAAM,QAAiB,MAAM,OAAO,OAAO,EAAE,CAAC;AAC1D;AAEA,SAAS,mBACP,WACkB;AAClB,SAAO,UAAU,IAAI,CAAC,aAAa;AACjC,QAAI,aAAsB,SAAS,SAAS;AAC5C,QAAI,OAAO,SAAS,SAAS,cAAc,UAAU;AACnD,UAAI;AACF,qBAAa,KAAK,MAAM,SAAS,SAAS,aAAa,IAAI;AAAA,MAC7D,SAAQ;AACN,qBAAa,SAAS,SAAS;AAAA,MACjC;AAAA,IACF;AAEA,WAAO;AAAA,MACL,MAAM;AAAA,MACN,YAAY,SAAS;AAAA,MACrB,UAAU,SAAS,SAAS;AAAA,MAC5B,OAAO;AAAA,IACT;AAAA,EACF,CAAC;AACH;AAEA,SAAS,sBACP,SAC6C;AA9M/C;AA+ME,QAAM,YAAY,wBAAwB,QAAQ,OAAO;AACzD,QAAM,kBAAgB,aAAQ,eAAR,mBAAoB,UACtC,mBAAmB,QAAQ,UAAU,IACrC,CAAC;AAEL,MAAI,cAAc,WAAW,GAAG;AAC9B,QAAI,UAAU,WAAW,GAAG;AAC1B,aAAO;AAAA,IACT;AACA,QAAI,UAAU,WAAW,GAAG;AAC1B,aAAO,UAAU,CAAC,EAAE;AAAA,IACtB;AACA,WAAO;AAAA,EACT;AAEA,SAAO,CAAC,GAAG,WAAW,GAAG,aAAa;AACxC;AAEA,SAAS,YAAY,OAAkD;AACrE,MACE,UAAU,QACV,OAAO,UAAU,YACjB,OAAO,UAAU,YACjB,OAAO,UAAU,WACjB;AACA,WAAO;AAAA,EACT;AAEA,MAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,WAAO,MAAM,MAAM,WAAW;AAAA,EAChC;AAEA,MAAI,OAAO,UAAU,UAAU;AAC7B,WAAO,OAAO,OAAO,KAAgC,EAAE,MAAM,WAAW;AAAA,EAC1E;AAEA,SAAO;AACT;AAEA,SAAS,gBAAgB,UAAoC;AAC3D,MAAI,CAAC,UAAU;AACb,WAAO,EAAE,MAAM,QAAQ,OAAO,GAAG;AAAA,EACnC;AAEA,MAAI;AACF,UAAM,SAAS,KAAK,MAAM,QAAQ;AAClC,QAAI,YAAY,MAAM,GAAG;AACvB,aAAO,EAAE,MAAM,QAAQ,OAAO,OAAO;AAAA,IACvC;AAAA,EACF,SAAQ;AAAA,EAER;AAEA,SAAO,EAAE,MAAM,QAAQ,OAAO,SAAS;AACzC;AAEA,SAAS,iBACP,SACA,gBACa;AA1Qf;AA2QE,QAAM,YAAY,wBAAwB,QAAQ,OAAO;AACzD,QAAM,WAAW,UAAU,IAAI,CAAC,SAAS,KAAK,IAAI,EAAE,KAAK,IAAI;AAC7D,QAAM,cAAa,aAAQ,iBAAR,YAAwB;AAC3C,QAAM,WAAW,cACZ,oBAAe,IAAI,UAAU,MAA7B,YAAkC,aACnC;AAEJ,SAAO;AAAA,IACL;AAAA,MACE,MAAM;AAAA,MACN;AAAA,MACA;AAAA,MACA,QAAQ,gBAAgB,QAAQ;AAAA,IAClC;AAAA,EACF;AACF;AAEA,SAAS,6BACP,SACA,gBACc;AA/RhB;AAgSE,MAAI,QAAQ,SAAS,aAAa;AAChC,SAAI,aAAQ,eAAR,mBAAoB,QAAQ;AAC9B,iBAAW,YAAY,QAAQ,YAAY;AACzC,uBAAe,IAAI,SAAS,IAAI,SAAS,SAAS,IAAI;AAAA,MACxD;AAAA,IACF;AAEA,WAAO;AAAA,MACL,MAAM;AAAA,MACN,SAAS;AAAA,QACP;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,MAAI,QAAQ,SAAS,QAAQ;AAC3B,WAAO;AAAA,MACL,MAAM;AAAA,MACN,SAAS;AAAA,QACP;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,MAAI,QAAQ,SAAS,UAAU;AAC7B,UAAM,OAAO,wBAAwB,QAAQ,OAAO,EACjD,IAAI,CAAC,SAAS,KAAK,IAAI,EACvB,KAAK,IAAI;AACZ,WAAO;AAAA,MACL,MAAM;AAAA,MACN,SAAS;AAAA,IACX;AAAA,EACF;AAEA,QAAM,YAAY,wBAAwB,QAAQ,OAAO;AACzD,MAAI,UAAU,WAAW,GAAG;AAC1B,WAAO;AAAA,MACL,MAAM;AAAA,MACN,SAAS;AAAA,IACX;AAAA,EACF;AAEA,MAAI,UAAU,WAAW,GAAG;AAC1B,WAAO;AAAA,MACL,MAAM;AAAA,MACN,SAAS,UAAU,CAAC,EAAE;AAAA,IACxB;AAAA,EACF;AAEA,SAAO;AAAA,IACL,MAAM;AAAA,IACN,SAAS;AAAA,EACX;AACF;AAEO,SAAS,4BACd,eACA,aACA;AACA,QAAM;AAAA,IACJ;AAAA,IACA,OAAO;AAAA,IACP;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI;AAEJ,QAAM,iBAAiB,oBAAI,IAAoB;AAE/C,QAAM,aAA6B,SAAS;AAAA,IAAI,CAAC,YAC/C,6BAA6B,SAAS,cAAc;AAAA,EACtD;AAGA,QAAM,aAAa,mBAAmB,WAAW;AAEjD,QAAM,mBAAkB,2CAAa,eACjC;AAAA,IACE,oBAAoB;AAAA,MAClB,YAAY,YAAY,YAAY;AAAA,MACpC,WAAW,YAAY,YAAY;AAAA,MACnC,gBAAgB,YAAY,YAAY;AAAA,IAC1C;AAAA,EACF,IACA;AAEJ,SAAO;AAAA,IACL,UAAU;AAAA,IACV,OAAO;AAAA,IACP;AAAA,IACA,iBAAiB;AAAA,IACjB,eAAe,uBAAuB,IAAI;AAAA,IAC1C,YAAY,oBAAoB,WAAW;AAAA,IAC3C,GAAI,kBAAkB,EAAE,gBAAgB,IAAI,CAAC;AAAA,EAC/C;AACF;AAGO,SAAS,oBACd,QACkE;AAClE,MAAI,CAAC,QAAQ;AACX;AAAA,EACF;AACA,MAAI,WAAW,UAAU,WAAW,QAAQ;AAC1C,WAAO;AAAA,EACT;AACA,MAAI,OAAO,WAAW,YAAY,OAAO,SAAS,YAAY;AAC5D,WAAO,EAAE,MAAM,QAAQ,UAAU,OAAO,SAAS,KAAK;AAAA,EACxD;AACA;AACF;AAKO,SAAS,8BAA8B,WAO3C;AACD,SAAO,UAAU,IAAI,CAAC,UAAU;AAAA,IAC9B,IAAI,QAAQ,KAAK,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,GAAG,EAAE,CAAC;AAAA,IACjE,MAAM;AAAA,IACN,UAAU;AAAA,MACR,MAAM,KAAK;AAAA,MACX,WAAW,KAAK,UAAU,KAAK,IAAI;AAAA,IACrC;AAAA,EACF,EAAE;AACJ;;;ACtaO,SAAS,qBAA6B;AAC3C,SAAO,YAAY,KAAK,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,GAAG,EAAE,CAAC;AAC1E;AAEO,SAAS,sBAA8B;AAC5C,SAAO,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI;AACrC;;;ACMO,SAAS,2BAEd,aACA,OACA,SAAS,OACW;AAjBtB;AAkBE,QAAM,UAA0B,CAAC;AAGjC,MAAI,YAAY,MAAM;AACpB,UAAM,SAAuB;AAAA,MAC3B,OAAO;AAAA,MACP,eAAe,YAAY,gBAAgB;AAAA,IAC7C;AAEA,QAAI,QAAQ;AACV,aAAO,QAAQ;AAAA,QACb,MAAM;AAAA,QACN,SAAS,YAAY;AAAA,MACvB;AAAA,IACF,OAAO;AACL,aAAO,UAAU;AAAA,QACf,MAAM;AAAA,QACN,SAAS,YAAY;AAAA,MACvB;AAAA,IACF;AACA,YAAQ,KAAK,MAAM;AAAA,EACrB;AAGA,MAAI,YAAY,aAAa,YAAY,UAAU,SAAS,GAAG;AAC7D,UAAM,SAAuB;AAAA,MAC3B,OAAO;AAAA,MACP,eAAe;AAAA,IACjB;AAEA,UAAM,mBAAkB,iBAAY,cAAZ,mBAAuB;AAAA,MAC7C,CAEE,UACI;AAAA,QACJ,IAAI,QAAQ,KAAK,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,GAAG,EAAE,CAAC;AAAA,QACjE,MAAM;AAAA,QACN,UAAU;AAAA,UACR,MAAM,KAAK;AAAA,UACX,WAAW,KAAK,UAAU,KAAK,IAAI;AAAA,QACrC;AAAA,MACF;AAAA;AAGF,QAAI,QAAQ;AACV,aAAO,QAAQ;AAAA,QACb,MAAM;AAAA,QACN,YAAY;AAAA,MACd;AAAA,IACF,OAAO;AACL,aAAO,UAAU;AAAA,QACf,MAAM;AAAA,QACN,SAAS;AAAA,QACT,YAAY;AAAA,MACd;AAAA,IACF;AAEA,YAAQ,KAAK,MAAM;AAAA,EACrB;AAEA,QAAM,WAA+B;AAAA,IACnC,IAAI,mBAAmB;AAAA,IACvB,QAAQ,SAAS,0BAA0B;AAAA,IAC3C,SAAS,oBAAoB;AAAA,IAC7B;AAAA,IACA;AAAA,EACF;AAGA,MAAI,YAAY,OAAO;AACrB,aAAS,QAAQ;AAAA,MACf,eAAe,YAAY,MAAM,gBAAgB;AAAA,MACjD,mBAAmB,YAAY,MAAM,oBAAoB;AAAA,MACzD,cAAc,YAAY,MAAM,eAAe;AAAA,IACjD;AAAA,EACF;AAEA,SAAO;AACT;AAgCA,SAAS,qBACP,OACA,cACA,YACoB;AAEpB,MAAI;AAEJ,MAAI,iBAAiB,gBAAgB,iBAAiB,cAAc;AAClE,wBAAoB;AAAA,EACtB,WAAW,iBAAiB,QAAQ;AAClC,wBAAoB;AAAA,EACtB,WAAW,iBAAiB,UAAU;AACpC,wBAAoB;AAAA,EACtB,WAAW,iBAAiB,kBAAkB;AAC5C,wBAAoB;AAAA,EACtB,OAAO;AACL,wBAAoB;AAAA,EACtB;AAEA,SAAO;AAAA,IACL,IAAI;AAAA,IACJ,QAAQ;AAAA,IACR,SAAS,oBAAoB;AAAA,IAC7B;AAAA,IACA,SAAS;AAAA,MACP;AAAA,QACE,OAAO;AAAA,QACP,OAAO,CAAC;AAAA,QACR,eAAe;AAAA,MACjB;AAAA,IACF;AAAA,EACF;AACF;AAGA,SAAS,sBACP,OACA,SACA,YACA,cAAc,OACM;AACpB,QAAM,QAAiC,EAAE,MAAM,YAAY;AAE3D,MAAI,aAAa;AACf,UAAM,oBAAoB;AAAA,EAC5B,OAAO;AACL,UAAM,UAAU;AAAA,EAClB;AAEA,SAAO;AAAA,IACL,IAAI;AAAA,IACJ,QAAQ;AAAA,IACR,SAAS,oBAAoB;AAAA,IAC7B;AAAA,IACA,SAAS;AAAA,MACP;AAAA,QACE,OAAO;AAAA,QACP;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAGA,SAAS,uBACP,OACA,UACA,YACA,cAAc,OACM;AAtMtB;AAuME,SAAO;AAAA,IACL,IAAI;AAAA,IACJ,QAAQ;AAAA,IACR,SAAS,oBAAoB;AAAA,IAC7B;AAAA,IACA,SAAS;AAAA,MACP;AAAA,QACE,OAAO;AAAA,QACP,OAAO;AAAA,UACL,GAAI,cAAc,EAAE,MAAM,YAAqB,IAAI,CAAC;AAAA,UACpD,YAAY;AAAA,YACV;AAAA,cACE,OAAO,SAAS,SAAS;AAAA,cACzB,MAAM;AAAA,cACN,UAAU;AAAA,gBACR,QAAM,cAAS,aAAT,mBAAmB,SAAQ;AAAA,gBACjC,aAAW,cAAS,aAAT,mBAAmB,cAAa;AAAA,cAC7C;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAIO,SAAS,4BACd,OACA,SAGA;AACA,MAAI,qBAAqB;AACzB,MAAI,mBAAmB;AACvB,MAAI,mBAAmB,mBAAmB;AAE1C,QAAM,YACJ,mCAAS,eAAc,QACnB,SACA,CAAC,UAAmB;AAClB,UAAM,UACJ,QAAQ,IAAI,mBAAmB,SAAS,eAAe;AACzD,YAAQ;AAAA,MACN,2BAAoB,OAAO;AAAA,MAC3B,KAAK,UAAU,OAAO,MAAM,CAAC;AAAA,IAC/B;AAAA,EACF;AAEN,QAAM,WAAyC;AAAA,IAC7C,OAAO,MAAM,CAAC;AAAA,IACd,mBAAmB,CAAC,UAAU;AAC5B,UAAI,CAAC,MAAM,MAAM;AACf,eAAO,CAAC;AAAA,MACV;AACA,aAAO;AAAA,QACL;AAAA,UACE,MAAM,KAAK;AAAA,YACT,sBAAsB,OAAO,MAAM,MAAM,kBAAkB,IAAI;AAAA,UACjE;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,IACA,cAAc,CAAC,UAAU;AACvB,UAAI,CAAC,MAAM,MAAM;AACf,eAAO,CAAC;AAAA,MACV;AACA,aAAO;AAAA,QACL;AAAA,UACE,MAAM,KAAK;AAAA,YACT,sBAAsB,OAAO,MAAM,MAAM,kBAAkB,KAAK;AAAA,UAClE;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,IACA,aAAa,CAAC,UAAU;AAnR5B;AAoRM,YAAM,aAAa,MAAM,cAAc,QAAQ,mBAAmB,CAAC;AACnE,YAAM,WAAW,MAAM,YAAY;AACnC,YAAM,aACJ,OAAO,MAAM,UAAU,WACnB,MAAM,QACN,KAAK,WAAU,WAAM,UAAN,YAAe,CAAC,CAAC;AACtC,YAAM,gBAAyC;AAAA,QAC7C,OAAO;AAAA,QACP,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,UAAU,EAAE,MAAM,UAAU,WAAW,WAAW;AAAA,MACpD;AACA,YAAM,WAAW;AAAA,QACf;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AACA,aAAO,CAAC,EAAE,MAAM,KAAK,UAAU,QAAQ,EAAE,CAAC;AAAA,IAC5C;AAAA,IACA,iBAAiB,MAAM,CAAC;AAAA,IACxB,YAAY,MAAM,CAAC;AAAA,IACnB,eAAe,CAAC,UAAU;AACxB,UAAI,kBAAkB;AACpB,eAAO,CAAC;AAAA,MACV;AACA,YAAM,eAAe;AACrB,UAAI,eAAe,MAAM,gBAAgB;AACzC,UAAI,iBAAiB,gBAAgB,iBAAiB,cAAc;AAClE,uBAAe;AAAA,MACjB;AACA,YAAM,iBAAiB,eAAe,eAAe;AACrD,yBAAmB;AACnB,2BAAqB;AACrB,aAAO;AAAA,QACL;AAAA,UACE,MAAM,KAAK;AAAA,YACT,qBAAqB,OAAO,gBAAgB,gBAAgB;AAAA,UAC9D;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,IACA,mBAAmB,CAAC,UAAU;AAC5B,YAAM,WAAW;AAAA,QACf,OAAO,MAAM,aAAa,OAAO,MAAM,UAAU,IAAI;AAAA,QACrD,MAAM;AAAA,QACN,UAAU;AAAA,UACR,MAAM,MAAM,YAAY;AAAA,UACxB,WAAW,MAAM,QAAQ;AAAA,QAC3B;AAAA,MACF;AACA,aAAO;AAAA,QACL;AAAA,UACE,MAAM,KAAK;AAAA,YACT,uBAAuB,OAAO,UAAU,gBAAgB;AAAA,UAC1D;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,IACA,eAAe,CAAC,UAAU;AACxB,YAAM,aAAa;AAAA,SAAY,MAAM,QAAQ,aAAa,KAAK,UAAU,MAAM,MAAM,CAAC;AAAA;AACtF,aAAO;AAAA,QACL;AAAA,UACE,MAAM,KAAK;AAAA,YACT,sBAAsB,OAAO,YAAY,kBAAkB,KAAK;AAAA,UAClE;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,IACA,QAAQ,CAAC,UAAU;AACjB,UAAI,kBAAkB;AACpB,eAAO,CAAC;AAAA,MACV;AACA,YAAM,eAAe;AACrB,UAAI,eAAe,MAAM,gBAAgB;AACzC,UAAI,iBAAiB,gBAAgB,iBAAiB,cAAc;AAClE,uBAAe;AAAA,MACjB;AACA,YAAM,iBAAiB,eAAe,eAAe;AACrD,yBAAmB;AACnB,2BAAqB;AACrB,aAAO;AAAA,QACL;AAAA,UACE,MAAM,KAAK;AAAA,YACT,qBAAqB,OAAO,gBAAgB,gBAAgB;AAAA,UAC9D;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO,CAEL,UACkB;AAlXtB;AAmXI,UAAM,MAAqB,CAAC;AAE5B,yCAAW;AAEX,QAAI,MAAM,SAAS,SAAS;AAC1B,2BAAqB;AACrB,yBAAmB;AACnB,0BAAmB,WAAM,OAAN,YAAY,mBAAmB;AAAA,IACpD;AAEA,UAAM,UAAU,SAAS,MAAM,IAAI;AACnC,QAAI,SAAS;AACX,YAAM,SAAS,QAAQ,OAAwB,KAAK;AACpD,UAAI,MAAM,SAAS,eAAe,MAAM,SAAS,mBAAmB;AAClE,6BAAqB;AAAA,MACvB;AACA,UAAI,KAAK,GAAG,MAAM;AAAA,IACpB,OAAO;AACL,cAAQ,KAAK,2CAAiC,MAAM,IAAI,IAAI,KAAK;AAAA,IACnE;AAEA,QAAI,MAAM,SAAS,iBAAiB,MAAM,SAAS,UAAU;AAC3D,2BAAqB;AAAA,IACvB;AAEA,WAAO,IAAI,OAAO,CAAC,gBAAgB;AA5YvC,UAAAA,KAAA;AA6YM,UAAI;AACF,cAAM,SAAS,KAAK,MAAM,YAAY,IAAI;AAC1C,cAAM,SAAQ,MAAAA,MAAA,OAAO,YAAP,gBAAAA,IAAiB,OAAjB,mBAAqB;AACnC,eACE,UACC,MAAM,QACL,MAAM,WACL,MAA6C,qBAC7C,MAAM,cAAc,MAAM,WAAW,SAAS,OAC/C,kBAAO,YAAP,mBAAiB,OAAjB,mBAAqB;AAAA,MAE3B,SAAQ;AACN,eAAO;AAAA,MACT;AAAA,IACF,CAAC;AAAA,EACH;AACF;AAEO,SAAS,gCAEd,OACA,OACe;AACf,QAAM,UAAU,4BAA4B,KAAK;AACjD,SAAO,QAAQ,KAAK;AACtB;AAKO,SAAS,kBAAkB,QAA+B;AAC/D,SAAO,OAAO,IAAI,CAAC,UAAU,SAAS,MAAM,IAAI;AAAA;AAAA,CAAM,EAAE,KAAK,EAAE;AACjE;;;AC7aA,4BAA0B;AAC1B,kBAAiB;AACjB,gBAAyC;AACzC,qBAIO;AACP,IAAAC,cAA8C;AAe9C,SAAS,mBAAmB,QAAyC;AACnE,MAAI,CAAC,QAAQ;AACX,WAAO;AAAA,EACT;AAGA,QAAM,iBAAa,0BAAa,QAAQ;AAAA,IACtC,iBAAiB;AAAA,EACnB,CAAC;AAGD,MAAI,OAAO,eAAe,YAAY,eAAe,MAAM;AACzD,UAAM,EAAE,SAAS,GAAG,KAAK,IAAI;AAC7B,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AAEA,SAAS,kBAAkB,UAAyC;AAClE,SAAO,SAAS,IAAI,CAAC,SAAS,WAAW;AAAA,IACvC;AAAA,IACA,MAAM,QAAQ;AAAA,IACd,SAAS,QAAQ;AAAA,IACjB,WAAW,QAAQ;AAAA,EACrB,EAAE;AACJ;AAEA,SAAS,mBACP,eACA,SACA;AAtDF;AAuDE,MAAI,CAAC,SAAS;AACZ;AAAA,EACF;AACA,QAAM,cAAa,mBAAc,UAAd,YAAuB,CAAC,GACxC,IAAI,CAAC,SAAM;AA3DhB,QAAAC;AA2DoB,yBAAc,QAAOA,MAAA,KAAK,aAAL,gBAAAA,IAAe,OAAO;AAAA,GAAU,EACpE,OAAO,CAAC,SAAyB,QAAQ,IAAI,CAAC;AAEjD,UAAQ;AAAA,IACN;AAAA,IACA,KAAK;AAAA,MACH;AAAA,QACE,OAAO,cAAc;AAAA,QACrB,QAAQ,QAAQ,cAAc,MAAM;AAAA,QACpC,aAAa,cAAc;AAAA,QAC3B,WAAW,cAAc;AAAA,QACzB;AAAA,QACA,YAAY,cAAc;AAAA,QAC1B,UAAU,kBAAkB,cAAc,QAAQ;AAAA,QAClD,OAAO,cAAc;AAAA,MACvB;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;AAEA,SAAS,uBAAuB,UAAuC;AACrE,SAAO,qCAAU,IAAI,CAAC,SAAS,WAAW;AAAA,IACxC;AAAA,IACA,MAAM,QAAQ;AAAA,IACd,SAAS,QAAQ;AAAA,EACnB;AACF;AAEA,SAAS,qBACP,eACA,aACA,SACA;AA7FF;AA8FE,MAAI,CAAC,SAAS;AACZ;AAAA,EACF;AACA,QAAM,YAAW,iBAAY,aAAZ,YAAwB,CAAC;AAC1C,UAAQ;AAAA,IACN;AAAA,IACA,KAAK;AAAA,MACH;AAAA,QACE,OAAO,cAAc;AAAA,QACrB,kBAAkB,SAAS,KAAK,CAAC,YAAY,QAAQ,SAAS,QAAQ;AAAA,QACtE,UAAU,uBAAuB,QAAQ;AAAA,QACzC,OAAO,OAAO,SAAQ,iBAAY,UAAZ,YAAqB,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,MAAM,IAAI,OAAO;AAAA,UACpE;AAAA,UACA,aAAa,KAAK;AAAA,UAClB,aAAa,mBAAmB,KAAK,WAAW;AAAA,QAClD,EAAE;AAAA,QACF,aAAa,YAAY;AAAA,QACzB,iBAAiB,YAAY;AAAA,QAC7B,eAAe,YAAY;AAAA,MAC7B;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;AAEO,IAAM,oBAAN,MAAwB;AAAA,EAK7B,YAAY,QAAqB;AA7HnC;AA8HI,SAAK,SAAS;AAAA,MACZ,MAAM;AAAA,MACN,MAAM;AAAA,MACN,MAAM;AAAA,MACN,GAAG;AAAA,IACL;AACA,SAAK,UAAU,YAAO,WAAP,YAAiB;AAEhC,SAAK,cAAU,eAAAC,SAAQ;AAGvB,QAAI,KAAK,OAAO,MAAM;AACpB,WAAK,QAAQ,SAAS,YAAAC,OAAI;AAAA,IAC5B;AAEA,SAAK,YAAY;AAAA,EACnB;AAAA,EAEQ,cAAoB;AAE1B,SAAK,QAAQ;AAAA,MACX;AAAA,MACA,OAAO,UAA0B,YAA0B;AAAA,QACzD,QAAQ;AAAA,QACR,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,MACpC;AAAA,IACF;AAGA,SAAK,QAAQ;AAAA,MACX;AAAA,MACA,CAAC,SAAyB,UAAwB;AA7JxD;AA8JQ,YAAI;AACF,gBAAM,gBAAgB,QAAQ;AAG9B,cACE,EAAE,cAAc,YAAY,MAAM,QAAQ,cAAc,QAAQ,IAChE;AACA,mBAAO,MAAM,KAAK,GAAG,EAAE,KAAK;AAAA,cAC1B,OAAO;AAAA,gBACL,SAAS;AAAA,gBACT,MAAM;AAAA,cACR;AAAA,YACF,CAAC;AAAA,UACH;AAEA;AAAA,YACE;AAAA,aACA,gBAAK,OAAO,YAAZ,mBAAqB,aAArB,YAAiC;AAAA,UACnC;AAGA,gBAAM,cAAc,4BAA4B,eAAe;AAAA,YAC7D,aAAa,KAAK,OAAO;AAAA,UAC3B,CAAC;AACD;AAAA,YACE;AAAA,YACA;AAAA,aACA,gBAAK,OAAO,YAAZ,mBAAqB,gBAArB,YAAoC;AAAA,UACtC;AAGA,cAAI,cAAc,QAAQ;AACxB,mBAAO,KAAK;AAAA,cACV;AAAA,cACA;AAAA,cACA;AAAA,YACF;AAAA,UACF;AACA,iBAAO,KAAK;AAAA,YACV;AAAA,YACA;AAAA,YACA;AAAA,UACF;AAAA,QACF,SAAS,OAAO;AACd,eAAK,OAAO,MAAM,2BAA2B,KAAK;AAClD,iBAAO,MAAM,KAAK,GAAG,EAAE,KAAK;AAAA,YAC1B,OAAO;AAAA,cACL,SAAS;AAAA,cACT,MAAM;AAAA,YACR;AAAA,UACF,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF;AAGA,SAAK,QAAQ,IAAI,cAAc,aAAa;AAAA,MAC1C,QAAQ;AAAA,MACR,MAAM;AAAA,QACJ;AAAA,UACE,IAAI;AAAA,UACJ,QAAQ;AAAA,UACR,SAAS,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI;AAAA,UACrC,UAAU;AAAA,QACZ;AAAA,MACF;AAAA,IACF,EAAE;AAAA,EACJ;AAAA;AAAA;AAAA,EAIQ,WACN,aACA,cACA;AACA,UAAM,iBAAiB,CAAC,SAAyC;AAC/D,UAAI,CAAC,MAAM;AACT;AAAA,MACF;AAEA,aAAO;AAAA,QACL,aAAa,KAAK;AAAA,QAClB,iBAAa,iCAAU,KAAK,WAAW;AAAA,QACvC,GAAI,KAAK,UAAU,EAAE,SAAS,KAAK,QAAQ,IAAI,CAAC;AAAA,MAClD;AAAA,IACF;AAEA,UAAM,SAAkC,CAAC;AAEzC,eAAW,CAAC,MAAM,CAAC,KAAK,OAAO,QAAQ,sCAAgB,CAAC,CAAC,GAAG;AAC1D,YAAM,KAAK,eAAe,CAAC;AAC3B,UAAI,IAAI;AACN,eAAO,IAAI,IAAI;AAAA,MACjB;AAAA,IACF;AAEA,eAAW,CAAC,MAAM,CAAC,KAAK,OAAO,QAAQ,oCAAe,CAAC,CAAC,GAAG;AACzD,YAAM,KAAK,eAAe,CAAC;AAC3B,UAAI,IAAI;AACN,eAAO,IAAI,IAAI;AAAA,MACjB;AAAA,IACF;AAEA,WAAO,OAAO,KAAK,MAAM,EAAE,SAAS,IAAI,SAAS;AAAA,EACnD;AAAA,EAEA,MAAc,uBAEZ,aACA,eACA,OACe;AA7QnB;AA+QI,UAAM,IAAI,UAAU,KAAK;AAAA,MACvB,gBAAgB;AAAA,MAChB,iBAAiB;AAAA,MACjB,YAAY;AAAA,MACZ,+BAA+B;AAAA,IACjC,CAAC;AAED,QAAI;AACF,YAAM,cAAc,KAAK,WAAW,KAAK,OAAO,OAAO,YAAY,KAAK;AACxE,YAAM,SAAS,UAAM,sBAAW;AAAA,QAC9B,OAAO,KAAK,OAAO;AAAA,QACnB,GAAG;AAAA,QACH,GAAI,cAAc,EAAE,OAAO,YAAY,IAAI,CAAC;AAAA,MAC9C,CAAC;AAED,YAAM,UAAU,4BAA4B,cAAc,OAAO;AAAA,QAC/D,YAAW,gBAAK,OAAO,YAAZ,mBAAqB,iBAArB,YAAqC;AAAA,MAClD,CAAC;AACD,uBAAiB,SAAS,OAAO,YAAY;AAC3C,cAAM,eAAe,QAAQ,KAAK;AAClC,mBAAW,eAAe,cAAc;AACtC,gBAAM,IAAI,MAAM,SAAS,YAAY,IAAI;AAAA;AAAA,CAAM;AAAA,QACjD;AAAA,MACF;AAEA,YAAM,IAAI,MAAM,kBAAkB;AAClC,YAAM,IAAI,IAAI;AAAA,IAChB,SAAS,OAAO;AACd,WAAK,OAAO,MAAM,oBAAoB,KAAK;AAC3C,YAAM,IAAI,MAAM,qDAAqD;AACrE,YAAM,IAAI,IAAI;AAAA,IAChB;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,MAAc,0BAEZ,aACA,eACA,OACe;AACf,QAAI;AACF,YAAM,cAAc,KAAK,WAAW,KAAK,OAAO,OAAO,YAAY,KAAK;AACxE,YAAM,SAAS,UAAM,wBAAa;AAAA,QAChC,OAAO,KAAK,OAAO;AAAA,QACnB,GAAG;AAAA,QACH,GAAI,cAAc,EAAE,OAAO,YAAY,IAAI,CAAC;AAAA,MAC9C,CAAC;AAED,YAAM,iBAAiB;AAAA,QACrB;AAAA,QACA,cAAc;AAAA,QACd;AAAA,MACF;AAEA,YAAM,KAAK,cAAc;AAAA,IAC3B,SAAS,OAAO;AACd,WAAK,OAAO,MAAM,qBAAqB,KAAK;AAC5C,aAAO,MAAM,KAAK,GAAG,EAAE,KAAK;AAAA,QAC1B,OAAO;AAAA,UACL,SAAS;AAAA,UACT,MAAM;AAAA,QACR;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AAAA,EAEA,MAAM,QAAuB;AAC3B,QAAI;AACF,YAAM,KAAK,QAAQ,OAAO;AAAA,QACxB,MAAM,KAAK,OAAO,QAAQ;AAAA,QAC1B,MAAM,KAAK,OAAO,QAAQ;AAAA,MAC5B,CAAC;AAED,WAAK,OAAO;AAAA,QACV,mDAA4C,KAAK,OAAO,IAAI,IAAI,KAAK,OAAO,IAAI;AAAA,MAClF;AACA,WAAK,OAAO;AAAA,QACV,8BAAuB,KAAK,OAAO,IAAI,IAAI,KAAK,OAAO,IAAI;AAAA,MAC7D;AACA,WAAK,OAAO;AAAA,QACV,4BAAqB,KAAK,OAAO,IAAI,IAAI,KAAK,OAAO,IAAI;AAAA,MAC3D;AAAA,IACF,SAAS,OAAO;AACd,WAAK,OAAO,MAAM,2BAA2B,KAAK;AAClD,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF;AAAA,EAEA,MAAM,OAAsB;AAC1B,QAAI;AACF,YAAM,KAAK,QAAQ,MAAM;AACzB,WAAK,OAAO,KAAK,0BAAmB;AAAA,IACtC,SAAS,OAAO;AACd,WAAK,OAAO,MAAM,0BAA0B,KAAK;AAAA,IACnD;AAAA,EACF;AACF;","names":["_a","import_zod","_a","Fastify","cors"]}
package/dist/index.js CHANGED
@@ -249,7 +249,7 @@ function mapOpenAIToolChoice(choice) {
249
249
  }
250
250
  function convertAISDKToolCallsToOpenAI(toolCalls) {
251
251
  return toolCalls.map((call) => ({
252
- id: `call_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
252
+ id: `call_${Date.now()}_${Math.random().toString(36).slice(2, 11)}`,
253
253
  type: "function",
254
254
  function: {
255
255
  name: call.toolName,
@@ -260,7 +260,7 @@ function convertAISDKToolCallsToOpenAI(toolCalls) {
260
260
 
261
261
  // src/response-utils.ts
262
262
  function generateResponseId() {
263
- return `chatcmpl-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
263
+ return `chatcmpl-${Date.now()}-${Math.random().toString(36).slice(2, 11)}`;
264
264
  }
265
265
  function getCurrentTimestamp() {
266
266
  return Math.floor(Date.now() / 1e3);
@@ -295,7 +295,7 @@ function convertAISDKResultToOpenAI(aisdkResult, model, stream = false) {
295
295
  };
296
296
  const openAIToolCalls = (_a = aisdkResult.toolCalls) == null ? void 0 : _a.map(
297
297
  (call) => ({
298
- id: `call_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
298
+ id: `call_${Date.now()}_${Math.random().toString(36).slice(2, 11)}`,
299
299
  type: "function",
300
300
  function: {
301
301
  name: call.toolName,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/openai-request-converter.ts","../src/response-utils.ts","../src/response-converter.ts","../src/server.ts"],"sourcesContent":["import type {\n ModelMessage,\n ToolContent,\n ToolResultOutput,\n} from \"@ai-sdk/provider-utils\";\nimport { z } from \"zod\";\nimport type {\n OpenAIChatRequest,\n OpenAICompleteToolCall,\n OpenAIMessage,\n ProxyConfig,\n} from \"./types.js\";\n\n// Type definitions for OpenAI tool parameters\ninterface OpenAIToolProperty {\n type: string;\n description?: string;\n enum?: string[];\n}\n\ninterface OpenAIToolParameters {\n type: string;\n properties?: Record<string, OpenAIToolProperty>;\n required?: string[];\n}\n\n// Type for AI SDK tool definition\ninterface AISDKTool {\n description: string;\n inputSchema: z.ZodTypeAny;\n}\n\n// Type for tool call object\ninterface ToolCall {\n toolName: string;\n args: unknown;\n}\n\n/**\n * Create Zod schema for OpenAI tool property\n */\nfunction createZodSchema(prop: OpenAIToolProperty): z.ZodTypeAny {\n if (prop.type === \"string\") {\n return prop.enum ? z.enum(prop.enum as [string, ...string[]]) : z.string();\n }\n if (prop.type === \"number\") {\n return z.number();\n }\n if (prop.type === \"boolean\") {\n return z.boolean();\n }\n if (prop.type === \"array\") {\n return z.array(z.any());\n }\n if (prop.type === \"object\") {\n return z.object({});\n }\n return z.any();\n}\n\n/**\n * Convert OpenAI tool schema to Zod schema\n */\nfunction convertOpenAIToolToZod(\n parameters: Record<string, unknown> | undefined\n): z.ZodObject<Record<string, z.ZodTypeAny>> {\n if (!parameters) {\n return z.object({});\n }\n\n const params = parameters as unknown as OpenAIToolParameters;\n if (!params.properties) {\n return z.object({});\n }\n\n const schemaShape: Record<string, z.ZodTypeAny> = {};\n for (const [key, prop] of Object.entries(params.properties)) {\n schemaShape[key] = createZodSchema(prop);\n }\n\n return z.object(schemaShape);\n}\n\n/**\n * Convert OpenAI tools to AI SDK format\n */\nfunction convertOpenAITools(\n openaiTools:\n | Array<{\n function: {\n name: string;\n description?: string;\n parameters: Record<string, unknown>;\n };\n }>\n | undefined\n): Record<string, AISDKTool> {\n const aisdkTools: Record<string, AISDKTool> = {};\n\n if (!openaiTools) {\n return aisdkTools;\n }\n\n for (const openaiTool of openaiTools) {\n const toolName = openaiTool.function.name;\n aisdkTools[toolName] = {\n description: openaiTool.function.description || \"\",\n inputSchema: convertOpenAIToolToZod(openaiTool.function.parameters),\n };\n }\n\n return aisdkTools;\n}\n\n/**\n * Convert stop parameter to stop sequences\n */\nfunction convertStopToSequences(\n stop: string | string[] | undefined\n): string[] | undefined {\n if (!stop) {\n return;\n }\n return Array.isArray(stop) ? stop : [stop];\n}\n\ninterface AITextPart {\n type: \"text\";\n text: string;\n}\ninterface AIToolCallPart {\n type: \"tool-call\";\n toolCallId: string;\n toolName: string;\n input: unknown;\n}\ntype TextToolOutput = Extract<ToolResultOutput, { type: \"text\" }>;\ntype JsonToolOutput = Extract<ToolResultOutput, { type: \"json\" }>;\n\n/**\n * Convert OpenAI chat completion request to AI SDK format\n */\nexport function normalizeMessageContent(\n content: OpenAIMessage[\"content\"]\n): AITextPart[] {\n if (typeof content === \"string\") {\n return content ? [{ type: \"text\" as const, text: content }] : [];\n }\n\n if (Array.isArray(content)) {\n const parts = content as Array<string | { text?: unknown }>;\n return parts\n .map((part) => {\n if (typeof part === \"string\") {\n return part;\n }\n if (part && typeof part === \"object\" && \"text\" in part) {\n const textValue = part.text;\n if (typeof textValue === \"string\") {\n return textValue;\n }\n if (textValue !== undefined) {\n return JSON.stringify(textValue);\n }\n }\n return JSON.stringify(part);\n })\n .filter((text): text is string => Boolean(text))\n .map((text) => ({ type: \"text\" as const, text }));\n }\n\n if (content === null || content === undefined) {\n return [];\n }\n\n if (typeof content === \"object\") {\n return [{ type: \"text\" as const, text: JSON.stringify(content) }];\n }\n\n return [{ type: \"text\" as const, text: String(content) }];\n}\n\nfunction buildToolCallParts(\n toolCalls: OpenAICompleteToolCall[]\n): AIToolCallPart[] {\n return toolCalls.map((toolCall) => {\n let parsedArgs: unknown = toolCall.function.arguments;\n if (typeof toolCall.function.arguments === \"string\") {\n try {\n parsedArgs = JSON.parse(toolCall.function.arguments || \"{}\");\n } catch {\n parsedArgs = toolCall.function.arguments;\n }\n }\n\n return {\n type: \"tool-call\" as const,\n toolCallId: toolCall.id,\n toolName: toolCall.function.name,\n input: parsedArgs,\n } satisfies AIToolCallPart;\n });\n}\n\nfunction buildAssistantContent(\n message: OpenAIMessage & { role: \"assistant\" }\n): Array<AITextPart | AIToolCallPart> | string {\n const textParts = normalizeMessageContent(message.content);\n const toolCallParts = message.tool_calls?.length\n ? buildToolCallParts(message.tool_calls)\n : [];\n\n if (toolCallParts.length === 0) {\n if (textParts.length === 0) {\n return \"\";\n }\n if (textParts.length === 1) {\n return textParts[0].text;\n }\n return textParts;\n }\n\n return [...textParts, ...toolCallParts];\n}\n\nfunction isJsonValue(value: unknown): value is JsonToolOutput[\"value\"] {\n if (\n value === null ||\n typeof value === \"string\" ||\n typeof value === \"number\" ||\n typeof value === \"boolean\"\n ) {\n return true;\n }\n\n if (Array.isArray(value)) {\n return value.every(isJsonValue);\n }\n\n if (typeof value === \"object\") {\n return Object.values(value as Record<string, unknown>).every(isJsonValue);\n }\n\n return false;\n}\n\nfunction buildToolOutput(rawValue: string): ToolResultOutput {\n if (!rawValue) {\n return { type: \"text\", value: \"\" } satisfies TextToolOutput;\n }\n\n try {\n const parsed = JSON.parse(rawValue);\n if (isJsonValue(parsed)) {\n return { type: \"json\", value: parsed } satisfies JsonToolOutput;\n }\n } catch {\n // Fall through to text output below\n }\n\n return { type: \"text\", value: rawValue } satisfies TextToolOutput;\n}\n\nfunction buildToolContent(\n message: OpenAIMessage & { role: \"tool\" },\n toolNameLookup: Map<string, string>\n): ToolContent {\n const textParts = normalizeMessageContent(message.content);\n const combined = textParts.map((part) => part.text).join(\"\\n\");\n const toolCallId = message.tool_call_id ?? \"\";\n const toolName = toolCallId\n ? (toolNameLookup.get(toolCallId) ?? toolCallId)\n : \"\";\n\n return [\n {\n type: \"tool-result\",\n toolCallId,\n toolName,\n output: buildToolOutput(combined),\n },\n ];\n}\n\nfunction convertMessageToModelMessage(\n message: OpenAIMessage,\n toolNameLookup: Map<string, string>\n): ModelMessage {\n if (message.role === \"assistant\") {\n if (message.tool_calls?.length) {\n for (const toolCall of message.tool_calls) {\n toolNameLookup.set(toolCall.id, toolCall.function.name);\n }\n }\n\n return {\n role: \"assistant\",\n content: buildAssistantContent(\n message as OpenAIMessage & { role: \"assistant\" }\n ),\n };\n }\n\n if (message.role === \"tool\") {\n return {\n role: \"tool\",\n content: buildToolContent(\n message as OpenAIMessage & { role: \"tool\" },\n toolNameLookup\n ),\n };\n }\n\n if (message.role === \"system\") {\n const text = normalizeMessageContent(message.content)\n .map((part) => part.text)\n .join(\"\\n\");\n return {\n role: \"system\",\n content: text,\n };\n }\n\n const userParts = normalizeMessageContent(message.content);\n if (userParts.length === 0) {\n return {\n role: \"user\",\n content: \"\",\n };\n }\n\n if (userParts.length === 1) {\n return {\n role: \"user\",\n content: userParts[0].text,\n };\n }\n\n return {\n role: \"user\",\n content: userParts,\n };\n}\n\nexport function convertOpenAIRequestToAISDK(\n openaiRequest: OpenAIChatRequest,\n proxyConfig?: Pick<ProxyConfig, \"parserDebug\">\n) {\n const {\n messages,\n tools: openaiTools,\n temperature,\n max_tokens,\n stop,\n tool_choice,\n } = openaiRequest;\n\n const toolNameLookup = new Map<string, string>();\n\n const aiMessages: ModelMessage[] = messages.map((message) =>\n convertMessageToModelMessage(message, toolNameLookup)\n );\n\n // Convert OpenAI tools to AI SDK format dynamically\n const aisdkTools = convertOpenAITools(openaiTools);\n\n const providerOptions = proxyConfig?.parserDebug\n ? {\n toolCallMiddleware: {\n debugLevel: proxyConfig.parserDebug.level,\n logErrors: proxyConfig.parserDebug.logErrors,\n captureSummary: proxyConfig.parserDebug.captureSummary,\n },\n }\n : undefined;\n\n return {\n messages: aiMessages,\n tools: aisdkTools,\n temperature,\n maxOutputTokens: max_tokens,\n stopSequences: convertStopToSequences(stop),\n toolChoice: mapOpenAIToolChoice(tool_choice),\n ...(providerOptions ? { providerOptions } : {}),\n };\n}\n\n// Map OpenAI tool_choice to AI SDK toolChoice\nexport function mapOpenAIToolChoice(\n choice: OpenAIChatRequest[\"tool_choice\"]\n): \"auto\" | \"none\" | { type: \"tool\"; toolName: string } | undefined {\n if (!choice) {\n return;\n }\n if (choice === \"auto\" || choice === \"none\") {\n return choice;\n }\n if (typeof choice === \"object\" && choice.type === \"function\") {\n return { type: \"tool\", toolName: choice.function.name };\n }\n return;\n}\n\n/**\n * Convert AI SDK tool calls to OpenAI format\n */\nexport function convertAISDKToolCallsToOpenAI(toolCalls: ToolCall[]): Array<{\n id: string;\n type: \"function\";\n function: {\n name: string;\n arguments: string;\n };\n}> {\n return toolCalls.map((call) => ({\n id: `call_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,\n type: \"function\" as const,\n function: {\n name: call.toolName,\n arguments: JSON.stringify(call.args),\n },\n }));\n}\n","export function generateResponseId(): string {\n return `chatcmpl-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;\n}\n\nexport function getCurrentTimestamp(): number {\n return Math.floor(Date.now() / 1000);\n}\n","import { generateResponseId, getCurrentTimestamp } from \"./response-utils.js\";\nimport type {\n OpenAIChatResponse,\n OpenAIChoice,\n OpenAIStreamingToolCall,\n OpenAIUsage,\n StreamChunk,\n} from \"./types.js\";\n\n/**\n * Convert AI SDK result to OpenAI chat completion response\n */\nexport function convertAISDKResultToOpenAI(\n // biome-ignore lint/suspicious/noExplicitAny: AI sdk integration boundary\n aisdkResult: any,\n model: string,\n stream = false\n): OpenAIChatResponse {\n const choices: OpenAIChoice[] = [];\n\n // Handle text content\n if (aisdkResult.text) {\n const choice: OpenAIChoice = {\n index: 0,\n finish_reason: aisdkResult.finishReason || \"stop\",\n };\n\n if (stream) {\n choice.delta = {\n role: \"assistant\",\n content: aisdkResult.text,\n };\n } else {\n choice.message = {\n role: \"assistant\",\n content: aisdkResult.text,\n };\n }\n choices.push(choice);\n }\n\n // Handle tool calls\n if (aisdkResult.toolCalls && aisdkResult.toolCalls.length > 0) {\n const choice: OpenAIChoice = {\n index: 0,\n finish_reason: \"tool_calls\",\n };\n\n const openAIToolCalls = aisdkResult.toolCalls?.map(\n (\n // biome-ignore lint/suspicious/noExplicitAny: AI SDK integration boundary\n call: any\n ) => ({\n id: `call_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,\n type: \"function\" as const,\n function: {\n name: call.toolName,\n arguments: JSON.stringify(call.args),\n },\n })\n );\n\n if (stream) {\n choice.delta = {\n role: \"assistant\",\n tool_calls: openAIToolCalls,\n };\n } else {\n choice.message = {\n role: \"assistant\",\n content: null,\n tool_calls: openAIToolCalls,\n };\n }\n\n choices.push(choice);\n }\n\n const response: OpenAIChatResponse = {\n id: generateResponseId(),\n object: stream ? \"chat.completion.chunk\" : \"chat.completion\",\n created: getCurrentTimestamp(),\n model,\n choices,\n };\n\n // Add usage if available\n if (aisdkResult.usage) {\n response.usage = {\n prompt_tokens: aisdkResult.usage.promptTokens || 0,\n completion_tokens: aisdkResult.usage.completionTokens || 0,\n total_tokens: aisdkResult.usage.totalTokens || 0,\n } as OpenAIUsage;\n }\n\n return response;\n}\n\n/**\n * Convert AI SDK stream chunk to OpenAI SSE format\n */\n\n// Type definitions for better type safety\ninterface ToolCallDelta {\n index?: number;\n id?: string;\n type?: \"function\";\n function?: {\n name?: string;\n arguments?: string;\n };\n}\n\ninterface AIStreamChunk {\n type: string;\n id?: string;\n text?: string;\n toolCallId?: string;\n toolName?: string;\n args?: string;\n input?: Record<string, unknown>;\n finishReason?: string;\n [key: string]: unknown;\n}\n\ntype ChunkHandler = (chunk: AIStreamChunk, model: string) => StreamChunk[];\n\n// Helper function to create finish response\nfunction createFinishResponse(\n model: string,\n finishReason: string,\n responseId: string\n): OpenAIChatResponse {\n // Ensure finish reason matches OpenAI's allowed types\n let validFinishReason: \"stop\" | \"length\" | \"tool_calls\" | \"content_filter\";\n\n if (finishReason === \"tool_calls\" || finishReason === \"tool-calls\") {\n validFinishReason = \"tool_calls\";\n } else if (finishReason === \"stop\") {\n validFinishReason = \"stop\";\n } else if (finishReason === \"length\") {\n validFinishReason = \"length\";\n } else if (finishReason === \"content_filter\") {\n validFinishReason = \"content_filter\";\n } else {\n validFinishReason = \"stop\"; // fallback to \"stop\" for unknown reasons\n }\n\n return {\n id: responseId,\n object: \"chat.completion.chunk\",\n created: getCurrentTimestamp(),\n model,\n choices: [\n {\n index: 0,\n delta: {},\n finish_reason: validFinishReason,\n },\n ],\n };\n}\n\n// Helper function to create content response\nfunction createContentResponse(\n model: string,\n content: string,\n responseId: string,\n isReasoning = false\n): OpenAIChatResponse {\n const delta: Record<string, unknown> = { role: \"assistant\" };\n\n if (isReasoning) {\n delta.reasoning_content = content;\n } else {\n delta.content = content;\n }\n\n return {\n id: responseId,\n object: \"chat.completion.chunk\",\n created: getCurrentTimestamp(),\n model,\n choices: [\n {\n index: 0,\n delta,\n },\n ],\n };\n}\n\n// Helper function to create tool call response\nfunction createToolCallResponse(\n model: string,\n toolCall: ToolCallDelta,\n responseId: string,\n includeRole = false\n): OpenAIChatResponse {\n return {\n id: responseId,\n object: \"chat.completion.chunk\",\n created: getCurrentTimestamp(),\n model,\n choices: [\n {\n index: 0,\n delta: {\n ...(includeRole ? { role: \"assistant\" as const } : {}),\n tool_calls: [\n {\n index: toolCall.index || 0,\n type: \"function\" as const,\n function: {\n name: toolCall.function?.name || \"\",\n arguments: toolCall.function?.arguments || \"\",\n },\n },\n ],\n },\n },\n ],\n };\n}\n\n// (legacy stateless handler removed)\n\nexport function createOpenAIStreamConverter(\n model: string,\n options?: {\n logChunks?: boolean;\n }\n) {\n let streamHasToolCalls = false;\n let streamFinishSent = false;\n let streamResponseId = generateResponseId();\n\n const logChunk =\n options?.logChunks === false\n ? undefined\n : (chunk: unknown) => {\n const logType =\n process.env.USE_MIDDLEWARE === \"true\" ? \"middleware\" : \"native\";\n console.log(\n `🔍 AI SDK Chunk [${logType}]:`,\n JSON.stringify(chunk, null, 2)\n );\n };\n\n const handlers: Record<string, ChunkHandler> = {\n start: () => [],\n \"reasoning-delta\": (chunk) => {\n if (!chunk.text) {\n return [];\n }\n return [\n {\n data: JSON.stringify(\n createContentResponse(model, chunk.text, streamResponseId, true)\n ),\n },\n ];\n },\n \"text-delta\": (chunk) => {\n if (!chunk.text) {\n return [];\n }\n return [\n {\n data: JSON.stringify(\n createContentResponse(model, chunk.text, streamResponseId, false)\n ),\n },\n ];\n },\n \"tool-call\": (chunk) => {\n const toolCallId = chunk.toolCallId || `call_${generateResponseId()}`;\n const toolName = chunk.toolName || \"\";\n const argsString =\n typeof chunk.input === \"string\"\n ? chunk.input\n : JSON.stringify(chunk.input ?? {});\n const toolCallDelta: OpenAIStreamingToolCall = {\n index: 0,\n id: toolCallId,\n type: \"function\",\n function: { name: toolName, arguments: argsString },\n };\n const response = createToolCallResponse(\n model,\n toolCallDelta,\n streamResponseId,\n true\n );\n return [{ data: JSON.stringify(response) }];\n },\n \"reasoning-end\": () => [],\n \"text-end\": () => [],\n \"finish-step\": (chunk) => {\n if (streamFinishSent) {\n return [];\n }\n const hadToolCalls = streamHasToolCalls;\n let finishReason = chunk.finishReason || \"stop\";\n if (finishReason === \"tool_calls\" || finishReason === \"tool-calls\") {\n finishReason = \"tool_calls\";\n }\n const resolvedReason = hadToolCalls ? \"tool_calls\" : finishReason;\n streamFinishSent = true;\n streamHasToolCalls = false;\n return [\n {\n data: JSON.stringify(\n createFinishResponse(model, resolvedReason, streamResponseId)\n ),\n },\n ];\n },\n \"tool-call-delta\": (chunk) => {\n const toolCall = {\n index: chunk.toolCallId ? Number(chunk.toolCallId) : 0,\n type: \"function\" as const,\n function: {\n name: chunk.toolName || \"\",\n arguments: chunk.args || \"\",\n },\n };\n return [\n {\n data: JSON.stringify(\n createToolCallResponse(model, toolCall, streamResponseId)\n ),\n },\n ];\n },\n \"tool-result\": (chunk) => {\n const resultText = `\\n[Tool: ${chunk.toolName} returned ${JSON.stringify(chunk.output)}]\\n`;\n return [\n {\n data: JSON.stringify(\n createContentResponse(model, resultText, streamResponseId, false)\n ),\n },\n ];\n },\n finish: (chunk) => {\n if (streamFinishSent) {\n return [];\n }\n const hadToolCalls = streamHasToolCalls;\n let finishReason = chunk.finishReason || \"stop\";\n if (finishReason === \"tool_calls\" || finishReason === \"tool-calls\") {\n finishReason = \"tool_calls\";\n }\n const resolvedReason = hadToolCalls ? \"tool_calls\" : finishReason;\n streamFinishSent = true;\n streamHasToolCalls = false;\n return [\n {\n data: JSON.stringify(\n createFinishResponse(model, resolvedReason, streamResponseId)\n ),\n },\n ];\n },\n };\n\n return (\n // biome-ignore lint/suspicious/noExplicitAny: ai sdk boundary\n chunk: any\n ): StreamChunk[] => {\n const out: StreamChunk[] = [];\n\n logChunk?.(chunk);\n\n if (chunk.type === \"start\") {\n streamHasToolCalls = false;\n streamFinishSent = false;\n streamResponseId = chunk.id ?? generateResponseId();\n }\n\n const handler = handlers[chunk.type];\n if (handler) {\n const result = handler(chunk as AIStreamChunk, model);\n if (chunk.type === \"tool-call\" || chunk.type === \"tool-call-delta\") {\n streamHasToolCalls = true;\n }\n out.push(...result);\n } else {\n console.warn(`⚠️ Unknown AI SDK chunk type: ${chunk.type}`, chunk);\n }\n\n if (chunk.type === \"finish-step\" || chunk.type === \"finish\") {\n streamHasToolCalls = false;\n }\n\n return out.filter((resultChunk) => {\n try {\n const parsed = JSON.parse(resultChunk.data);\n const delta = parsed.choices?.[0]?.delta;\n return (\n delta &&\n (delta.role ||\n delta.content ||\n (delta as NonNullable<OpenAIChoice[\"delta\"]>).reasoning_content ||\n (delta.tool_calls && delta.tool_calls.length > 0) ||\n parsed.choices?.[0]?.finish_reason)\n );\n } catch {\n return true;\n }\n });\n };\n}\n\nexport function convertAISDKStreamChunkToOpenAI(\n // biome-ignore lint/suspicious/noExplicitAny: o sdk integration boundary\n chunk: any,\n model: string\n): StreamChunk[] {\n const convert = createOpenAIStreamConverter(model);\n return convert(chunk);\n}\n\n/**\n * Create SSE formatted response\n */\nexport function createSSEResponse(chunks: StreamChunk[]): string {\n return chunks.map((chunk) => `data: ${chunk.data}\\n\\n`).join(\"\");\n}\n","import { zodSchema } from \"@ai-sdk/provider-utils\";\nimport cors from \"@fastify/cors\";\nimport { generateText, streamText } from \"ai\";\nimport Fastify, {\n type FastifyInstance,\n type FastifyReply,\n type FastifyRequest,\n} from \"fastify\";\nimport { toJSONSchema, type ZodTypeAny } from \"zod\";\nimport { convertOpenAIRequestToAISDK } from \"./openai-request-converter.js\";\nimport {\n convertAISDKResultToOpenAI,\n createOpenAIStreamConverter,\n} from \"./response-converter.js\";\nimport type {\n AISDKTool,\n Logger,\n OpenAIChatRequest,\n ProxyConfig,\n} from \"./types.js\";\n\ntype ConvertedParams = ReturnType<typeof convertOpenAIRequestToAISDK>;\n\nfunction serializeZodSchema(schema: ZodTypeAny | undefined): unknown {\n if (!schema) {\n return null;\n }\n\n // Use Zod v4's built-in JSON Schema conversion\n const jsonSchema = toJSONSchema(schema, {\n unrepresentable: \"any\",\n });\n\n // Remove $schema field for cleaner output\n if (typeof jsonSchema === \"object\" && jsonSchema !== null) {\n const { $schema, ...rest } = jsonSchema as Record<string, unknown>;\n return rest;\n }\n\n return jsonSchema;\n}\n\nfunction serializeMessages(messages: OpenAIChatRequest[\"messages\"]) {\n return messages.map((message, index) => ({\n index,\n role: message.role,\n content: message.content,\n toolCalls: message.tool_calls,\n }));\n}\n\nfunction logIncomingRequest(\n openaiRequest: OpenAIChatRequest,\n enabled: boolean\n) {\n if (!enabled) {\n return;\n }\n const toolNames = (openaiRequest.tools ?? [])\n .map((tool) => (\"function\" in tool ? tool.function?.name : undefined))\n .filter((name): name is string => Boolean(name));\n\n console.log(\n \"[proxy] Incoming OpenAI request\",\n JSON.stringify(\n {\n model: openaiRequest.model,\n stream: Boolean(openaiRequest.stream),\n temperature: openaiRequest.temperature,\n maxTokens: openaiRequest.max_tokens,\n toolNames,\n toolChoice: openaiRequest.tool_choice,\n messages: serializeMessages(openaiRequest.messages),\n tools: openaiRequest.tools,\n },\n null,\n 2\n )\n );\n}\n\nfunction serializeAISDKMessages(messages: ConvertedParams[\"messages\"]) {\n return messages?.map((message, index) => ({\n index,\n role: message.role,\n content: message.content,\n }));\n}\n\nfunction logRequestConversion(\n openaiRequest: OpenAIChatRequest,\n aisdkParams: ConvertedParams,\n enabled: boolean\n) {\n if (!enabled) {\n return;\n }\n const messages = aisdkParams.messages ?? [];\n console.log(\n \"[proxy] Converted AI SDK params\",\n JSON.stringify(\n {\n model: openaiRequest.model,\n hasSystemMessage: messages.some((message) => message.role === \"system\"),\n messages: serializeAISDKMessages(messages),\n tools: Object.entries(aisdkParams.tools ?? {}).map(([name, tool]) => ({\n name,\n description: tool.description,\n inputSchema: serializeZodSchema(tool.inputSchema),\n })),\n temperature: aisdkParams.temperature,\n maxOutputTokens: aisdkParams.maxOutputTokens,\n stopSequences: aisdkParams.stopSequences,\n },\n null,\n 2\n )\n );\n}\n\nexport class OpenAIProxyServer {\n private readonly fastify: FastifyInstance;\n private readonly config: ProxyConfig;\n private readonly logger: Logger;\n\n constructor(config: ProxyConfig) {\n this.config = {\n port: 3000,\n host: \"localhost\",\n cors: true,\n ...config,\n };\n this.logger = (config.logger ?? console) as Logger;\n\n this.fastify = Fastify();\n\n // Enable CORS\n if (this.config.cors) {\n this.fastify.register(cors);\n }\n\n this.setupRoutes();\n }\n\n private setupRoutes(): void {\n // Health check endpoint\n this.fastify.get(\n \"/health\",\n async (_request: FastifyRequest, _reply: FastifyReply) => ({\n status: \"ok\",\n timestamp: new Date().toISOString(),\n })\n );\n\n // OpenAI-compatible chat completions endpoint\n this.fastify.post(\n \"/v1/chat/completions\",\n (request: FastifyRequest, reply: FastifyReply) => {\n try {\n const openaiRequest = request.body as OpenAIChatRequest;\n\n // Validate request\n if (\n !(openaiRequest.messages && Array.isArray(openaiRequest.messages))\n ) {\n return reply.code(400).send({\n error: {\n message: \"Messages array is required\",\n type: \"invalid_request_error\",\n },\n });\n }\n\n logIncomingRequest(\n openaiRequest,\n this.config.logging?.requests ?? true\n );\n\n // Convert OpenAI request to AI SDK format\n const aisdkParams = convertOpenAIRequestToAISDK(openaiRequest, {\n parserDebug: this.config.parserDebug,\n });\n logRequestConversion(\n openaiRequest,\n aisdkParams,\n this.config.logging?.conversions ?? true\n );\n\n // Handle streaming vs non-streaming\n if (openaiRequest.stream) {\n return this.handleStreamingRequest(\n aisdkParams,\n openaiRequest,\n reply\n );\n }\n return this.handleNonStreamingRequest(\n aisdkParams,\n openaiRequest,\n reply\n );\n } catch (error) {\n this.logger.error(\"Request handling error:\", error);\n return reply.code(500).send({\n error: {\n message: \"Internal server error\",\n type: \"server_error\",\n },\n });\n }\n }\n );\n\n // Models endpoint\n this.fastify.get(\"/v1/models\", async () => ({\n object: \"list\",\n data: [\n {\n id: \"wrapped-model\",\n object: \"model\",\n created: Math.floor(Date.now() / 1000),\n owned_by: \"ai-sdk-tool-proxy\",\n },\n ],\n }));\n }\n\n // Merge server-defined tools (with execute) and request-defined tools (schema-only)\n // Server tools take precedence when names overlap.\n private mergeTools(\n serverTools?: Record<string, AISDKTool>,\n requestTools?: Record<string, AISDKTool>\n ) {\n const toProviderTool = (tool: AISDKTool | undefined): unknown => {\n if (!tool) {\n return;\n }\n\n return {\n description: tool.description,\n inputSchema: zodSchema(tool.inputSchema),\n ...(tool.execute ? { execute: tool.execute } : {}),\n };\n };\n\n const merged: Record<string, unknown> = {};\n\n for (const [name, t] of Object.entries(requestTools ?? {})) {\n const pt = toProviderTool(t);\n if (pt) {\n merged[name] = pt;\n }\n }\n\n for (const [name, t] of Object.entries(serverTools ?? {})) {\n const pt = toProviderTool(t);\n if (pt) {\n merged[name] = pt; // override request tool\n }\n }\n\n return Object.keys(merged).length > 0 ? merged : undefined;\n }\n\n private async handleStreamingRequest(\n // biome-ignore lint/suspicious/noExplicitAny: o sdk integration boundary\n aisdkParams: any,\n openaiRequest: OpenAIChatRequest,\n reply: FastifyReply\n ): Promise<void> {\n // Set SSE headers\n reply.raw.writeHead(200, {\n \"Content-Type\": \"text/event-stream\",\n \"Cache-Control\": \"no-cache\",\n Connection: \"keep-alive\",\n \"Access-Control-Allow-Origin\": \"*\",\n });\n\n try {\n const mergedTools = this.mergeTools(this.config.tools, aisdkParams.tools);\n const result = await streamText({\n model: this.config.model,\n ...aisdkParams,\n ...(mergedTools ? { tools: mergedTools } : {}),\n });\n\n const convert = createOpenAIStreamConverter(openaiRequest.model, {\n logChunks: this.config.logging?.streamChunks ?? true,\n });\n for await (const chunk of result.fullStream) {\n const openaiChunks = convert(chunk);\n for (const openaiChunk of openaiChunks) {\n reply.raw.write(`data: ${openaiChunk.data}\\n\\n`);\n }\n }\n\n reply.raw.write(\"data: [DONE]\\n\\n\");\n reply.raw.end();\n } catch (error) {\n this.logger.error(\"Streaming error:\", error);\n reply.raw.write('data: {\"error\": {\"message\": \"Streaming error\"}}\\n\\n');\n reply.raw.end();\n }\n\n return reply;\n }\n\n private async handleNonStreamingRequest(\n // biome-ignore lint/suspicious/noExplicitAny: o sdk integration boundary\n aisdkParams: any,\n openaiRequest: OpenAIChatRequest,\n reply: FastifyReply\n ): Promise<void> {\n try {\n const mergedTools = this.mergeTools(this.config.tools, aisdkParams.tools);\n const result = await generateText({\n model: this.config.model,\n ...aisdkParams,\n ...(mergedTools ? { tools: mergedTools } : {}),\n });\n\n const openaiResponse = convertAISDKResultToOpenAI(\n result,\n openaiRequest.model,\n false\n );\n\n reply.send(openaiResponse);\n } catch (error) {\n this.logger.error(\"Generation error:\", error);\n return reply.code(500).send({\n error: {\n message: \"Generation failed\",\n type: \"generation_error\",\n },\n });\n }\n }\n\n async start(): Promise<void> {\n try {\n await this.fastify.listen({\n port: this.config.port || 3000,\n host: this.config.host || \"localhost\",\n });\n\n this.logger.info(\n `🚀 OpenAI Proxy Server running on http://${this.config.host}:${this.config.port}`\n );\n this.logger.info(\n `📡 Endpoint: http://${this.config.host}:${this.config.port}/v1/chat/completions`\n );\n this.logger.info(\n `🏥 Health: http://${this.config.host}:${this.config.port}/health`\n );\n } catch (error) {\n this.logger.error(\"Failed to start server:\", error);\n process.exit(1);\n }\n }\n\n async stop(): Promise<void> {\n try {\n await this.fastify.close();\n this.logger.info(\"🛑 Server stopped\");\n } catch (error) {\n this.logger.error(\"Error stopping server:\", error);\n }\n }\n}\n"],"mappings":"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","names":["_a","_a"]}
1
+ {"version":3,"sources":["../src/openai-request-converter.ts","../src/response-utils.ts","../src/response-converter.ts","../src/server.ts"],"sourcesContent":["import type {\n ModelMessage,\n ToolContent,\n ToolResultOutput,\n} from \"@ai-sdk/provider-utils\";\nimport { z } from \"zod\";\nimport type {\n OpenAIChatRequest,\n OpenAICompleteToolCall,\n OpenAIMessage,\n ProxyConfig,\n} from \"./types.js\";\n\n// Type definitions for OpenAI tool parameters\ninterface OpenAIToolProperty {\n type: string;\n description?: string;\n enum?: string[];\n}\n\ninterface OpenAIToolParameters {\n type: string;\n properties?: Record<string, OpenAIToolProperty>;\n required?: string[];\n}\n\n// Type for AI SDK tool definition\ninterface AISDKTool {\n description: string;\n inputSchema: z.ZodTypeAny;\n}\n\n// Type for tool call object\ninterface ToolCall {\n toolName: string;\n args: unknown;\n}\n\n/**\n * Create Zod schema for OpenAI tool property\n */\nfunction createZodSchema(prop: OpenAIToolProperty): z.ZodTypeAny {\n if (prop.type === \"string\") {\n return prop.enum ? z.enum(prop.enum as [string, ...string[]]) : z.string();\n }\n if (prop.type === \"number\") {\n return z.number();\n }\n if (prop.type === \"boolean\") {\n return z.boolean();\n }\n if (prop.type === \"array\") {\n return z.array(z.any());\n }\n if (prop.type === \"object\") {\n return z.object({});\n }\n return z.any();\n}\n\n/**\n * Convert OpenAI tool schema to Zod schema\n */\nfunction convertOpenAIToolToZod(\n parameters: Record<string, unknown> | undefined\n): z.ZodObject<Record<string, z.ZodTypeAny>> {\n if (!parameters) {\n return z.object({});\n }\n\n const params = parameters as unknown as OpenAIToolParameters;\n if (!params.properties) {\n return z.object({});\n }\n\n const schemaShape: Record<string, z.ZodTypeAny> = {};\n for (const [key, prop] of Object.entries(params.properties)) {\n schemaShape[key] = createZodSchema(prop);\n }\n\n return z.object(schemaShape);\n}\n\n/**\n * Convert OpenAI tools to AI SDK format\n */\nfunction convertOpenAITools(\n openaiTools:\n | Array<{\n function: {\n name: string;\n description?: string;\n parameters: Record<string, unknown>;\n };\n }>\n | undefined\n): Record<string, AISDKTool> {\n const aisdkTools: Record<string, AISDKTool> = {};\n\n if (!openaiTools) {\n return aisdkTools;\n }\n\n for (const openaiTool of openaiTools) {\n const toolName = openaiTool.function.name;\n aisdkTools[toolName] = {\n description: openaiTool.function.description || \"\",\n inputSchema: convertOpenAIToolToZod(openaiTool.function.parameters),\n };\n }\n\n return aisdkTools;\n}\n\n/**\n * Convert stop parameter to stop sequences\n */\nfunction convertStopToSequences(\n stop: string | string[] | undefined\n): string[] | undefined {\n if (!stop) {\n return;\n }\n return Array.isArray(stop) ? stop : [stop];\n}\n\ninterface AITextPart {\n type: \"text\";\n text: string;\n}\ninterface AIToolCallPart {\n type: \"tool-call\";\n toolCallId: string;\n toolName: string;\n input: unknown;\n}\ntype TextToolOutput = Extract<ToolResultOutput, { type: \"text\" }>;\ntype JsonToolOutput = Extract<ToolResultOutput, { type: \"json\" }>;\n\n/**\n * Convert OpenAI chat completion request to AI SDK format\n */\nexport function normalizeMessageContent(\n content: OpenAIMessage[\"content\"]\n): AITextPart[] {\n if (typeof content === \"string\") {\n return content ? [{ type: \"text\" as const, text: content }] : [];\n }\n\n if (Array.isArray(content)) {\n const parts = content as Array<string | { text?: unknown }>;\n return parts\n .map((part) => {\n if (typeof part === \"string\") {\n return part;\n }\n if (part && typeof part === \"object\" && \"text\" in part) {\n const textValue = part.text;\n if (typeof textValue === \"string\") {\n return textValue;\n }\n if (textValue !== undefined) {\n return JSON.stringify(textValue);\n }\n }\n return JSON.stringify(part);\n })\n .filter((text): text is string => Boolean(text))\n .map((text) => ({ type: \"text\" as const, text }));\n }\n\n if (content === null || content === undefined) {\n return [];\n }\n\n if (typeof content === \"object\") {\n return [{ type: \"text\" as const, text: JSON.stringify(content) }];\n }\n\n return [{ type: \"text\" as const, text: String(content) }];\n}\n\nfunction buildToolCallParts(\n toolCalls: OpenAICompleteToolCall[]\n): AIToolCallPart[] {\n return toolCalls.map((toolCall) => {\n let parsedArgs: unknown = toolCall.function.arguments;\n if (typeof toolCall.function.arguments === \"string\") {\n try {\n parsedArgs = JSON.parse(toolCall.function.arguments || \"{}\");\n } catch {\n parsedArgs = toolCall.function.arguments;\n }\n }\n\n return {\n type: \"tool-call\" as const,\n toolCallId: toolCall.id,\n toolName: toolCall.function.name,\n input: parsedArgs,\n } satisfies AIToolCallPart;\n });\n}\n\nfunction buildAssistantContent(\n message: OpenAIMessage & { role: \"assistant\" }\n): Array<AITextPart | AIToolCallPart> | string {\n const textParts = normalizeMessageContent(message.content);\n const toolCallParts = message.tool_calls?.length\n ? buildToolCallParts(message.tool_calls)\n : [];\n\n if (toolCallParts.length === 0) {\n if (textParts.length === 0) {\n return \"\";\n }\n if (textParts.length === 1) {\n return textParts[0].text;\n }\n return textParts;\n }\n\n return [...textParts, ...toolCallParts];\n}\n\nfunction isJsonValue(value: unknown): value is JsonToolOutput[\"value\"] {\n if (\n value === null ||\n typeof value === \"string\" ||\n typeof value === \"number\" ||\n typeof value === \"boolean\"\n ) {\n return true;\n }\n\n if (Array.isArray(value)) {\n return value.every(isJsonValue);\n }\n\n if (typeof value === \"object\") {\n return Object.values(value as Record<string, unknown>).every(isJsonValue);\n }\n\n return false;\n}\n\nfunction buildToolOutput(rawValue: string): ToolResultOutput {\n if (!rawValue) {\n return { type: \"text\", value: \"\" } satisfies TextToolOutput;\n }\n\n try {\n const parsed = JSON.parse(rawValue);\n if (isJsonValue(parsed)) {\n return { type: \"json\", value: parsed } satisfies JsonToolOutput;\n }\n } catch {\n // Fall through to text output below\n }\n\n return { type: \"text\", value: rawValue } satisfies TextToolOutput;\n}\n\nfunction buildToolContent(\n message: OpenAIMessage & { role: \"tool\" },\n toolNameLookup: Map<string, string>\n): ToolContent {\n const textParts = normalizeMessageContent(message.content);\n const combined = textParts.map((part) => part.text).join(\"\\n\");\n const toolCallId = message.tool_call_id ?? \"\";\n const toolName = toolCallId\n ? (toolNameLookup.get(toolCallId) ?? toolCallId)\n : \"\";\n\n return [\n {\n type: \"tool-result\",\n toolCallId,\n toolName,\n output: buildToolOutput(combined),\n },\n ];\n}\n\nfunction convertMessageToModelMessage(\n message: OpenAIMessage,\n toolNameLookup: Map<string, string>\n): ModelMessage {\n if (message.role === \"assistant\") {\n if (message.tool_calls?.length) {\n for (const toolCall of message.tool_calls) {\n toolNameLookup.set(toolCall.id, toolCall.function.name);\n }\n }\n\n return {\n role: \"assistant\",\n content: buildAssistantContent(\n message as OpenAIMessage & { role: \"assistant\" }\n ),\n };\n }\n\n if (message.role === \"tool\") {\n return {\n role: \"tool\",\n content: buildToolContent(\n message as OpenAIMessage & { role: \"tool\" },\n toolNameLookup\n ),\n };\n }\n\n if (message.role === \"system\") {\n const text = normalizeMessageContent(message.content)\n .map((part) => part.text)\n .join(\"\\n\");\n return {\n role: \"system\",\n content: text,\n };\n }\n\n const userParts = normalizeMessageContent(message.content);\n if (userParts.length === 0) {\n return {\n role: \"user\",\n content: \"\",\n };\n }\n\n if (userParts.length === 1) {\n return {\n role: \"user\",\n content: userParts[0].text,\n };\n }\n\n return {\n role: \"user\",\n content: userParts,\n };\n}\n\nexport function convertOpenAIRequestToAISDK(\n openaiRequest: OpenAIChatRequest,\n proxyConfig?: Pick<ProxyConfig, \"parserDebug\">\n) {\n const {\n messages,\n tools: openaiTools,\n temperature,\n max_tokens,\n stop,\n tool_choice,\n } = openaiRequest;\n\n const toolNameLookup = new Map<string, string>();\n\n const aiMessages: ModelMessage[] = messages.map((message) =>\n convertMessageToModelMessage(message, toolNameLookup)\n );\n\n // Convert OpenAI tools to AI SDK format dynamically\n const aisdkTools = convertOpenAITools(openaiTools);\n\n const providerOptions = proxyConfig?.parserDebug\n ? {\n toolCallMiddleware: {\n debugLevel: proxyConfig.parserDebug.level,\n logErrors: proxyConfig.parserDebug.logErrors,\n captureSummary: proxyConfig.parserDebug.captureSummary,\n },\n }\n : undefined;\n\n return {\n messages: aiMessages,\n tools: aisdkTools,\n temperature,\n maxOutputTokens: max_tokens,\n stopSequences: convertStopToSequences(stop),\n toolChoice: mapOpenAIToolChoice(tool_choice),\n ...(providerOptions ? { providerOptions } : {}),\n };\n}\n\n// Map OpenAI tool_choice to AI SDK toolChoice\nexport function mapOpenAIToolChoice(\n choice: OpenAIChatRequest[\"tool_choice\"]\n): \"auto\" | \"none\" | { type: \"tool\"; toolName: string } | undefined {\n if (!choice) {\n return;\n }\n if (choice === \"auto\" || choice === \"none\") {\n return choice;\n }\n if (typeof choice === \"object\" && choice.type === \"function\") {\n return { type: \"tool\", toolName: choice.function.name };\n }\n return;\n}\n\n/**\n * Convert AI SDK tool calls to OpenAI format\n */\nexport function convertAISDKToolCallsToOpenAI(toolCalls: ToolCall[]): Array<{\n id: string;\n type: \"function\";\n function: {\n name: string;\n arguments: string;\n };\n}> {\n return toolCalls.map((call) => ({\n id: `call_${Date.now()}_${Math.random().toString(36).slice(2, 11)}`,\n type: \"function\" as const,\n function: {\n name: call.toolName,\n arguments: JSON.stringify(call.args),\n },\n }));\n}\n","export function generateResponseId(): string {\n return `chatcmpl-${Date.now()}-${Math.random().toString(36).slice(2, 11)}`;\n}\n\nexport function getCurrentTimestamp(): number {\n return Math.floor(Date.now() / 1000);\n}\n","import { generateResponseId, getCurrentTimestamp } from \"./response-utils.js\";\nimport type {\n OpenAIChatResponse,\n OpenAIChoice,\n OpenAIStreamingToolCall,\n OpenAIUsage,\n StreamChunk,\n} from \"./types.js\";\n\n/**\n * Convert AI SDK result to OpenAI chat completion response\n */\nexport function convertAISDKResultToOpenAI(\n // biome-ignore lint/suspicious/noExplicitAny: AI sdk integration boundary\n aisdkResult: any,\n model: string,\n stream = false\n): OpenAIChatResponse {\n const choices: OpenAIChoice[] = [];\n\n // Handle text content\n if (aisdkResult.text) {\n const choice: OpenAIChoice = {\n index: 0,\n finish_reason: aisdkResult.finishReason || \"stop\",\n };\n\n if (stream) {\n choice.delta = {\n role: \"assistant\",\n content: aisdkResult.text,\n };\n } else {\n choice.message = {\n role: \"assistant\",\n content: aisdkResult.text,\n };\n }\n choices.push(choice);\n }\n\n // Handle tool calls\n if (aisdkResult.toolCalls && aisdkResult.toolCalls.length > 0) {\n const choice: OpenAIChoice = {\n index: 0,\n finish_reason: \"tool_calls\",\n };\n\n const openAIToolCalls = aisdkResult.toolCalls?.map(\n (\n // biome-ignore lint/suspicious/noExplicitAny: AI SDK integration boundary\n call: any\n ) => ({\n id: `call_${Date.now()}_${Math.random().toString(36).slice(2, 11)}`,\n type: \"function\" as const,\n function: {\n name: call.toolName,\n arguments: JSON.stringify(call.args),\n },\n })\n );\n\n if (stream) {\n choice.delta = {\n role: \"assistant\",\n tool_calls: openAIToolCalls,\n };\n } else {\n choice.message = {\n role: \"assistant\",\n content: null,\n tool_calls: openAIToolCalls,\n };\n }\n\n choices.push(choice);\n }\n\n const response: OpenAIChatResponse = {\n id: generateResponseId(),\n object: stream ? \"chat.completion.chunk\" : \"chat.completion\",\n created: getCurrentTimestamp(),\n model,\n choices,\n };\n\n // Add usage if available\n if (aisdkResult.usage) {\n response.usage = {\n prompt_tokens: aisdkResult.usage.promptTokens || 0,\n completion_tokens: aisdkResult.usage.completionTokens || 0,\n total_tokens: aisdkResult.usage.totalTokens || 0,\n } as OpenAIUsage;\n }\n\n return response;\n}\n\n/**\n * Convert AI SDK stream chunk to OpenAI SSE format\n */\n\n// Type definitions for better type safety\ninterface ToolCallDelta {\n index?: number;\n id?: string;\n type?: \"function\";\n function?: {\n name?: string;\n arguments?: string;\n };\n}\n\ninterface AIStreamChunk {\n type: string;\n id?: string;\n text?: string;\n toolCallId?: string;\n toolName?: string;\n args?: string;\n input?: Record<string, unknown>;\n finishReason?: string;\n [key: string]: unknown;\n}\n\ntype ChunkHandler = (chunk: AIStreamChunk, model: string) => StreamChunk[];\n\n// Helper function to create finish response\nfunction createFinishResponse(\n model: string,\n finishReason: string,\n responseId: string\n): OpenAIChatResponse {\n // Ensure finish reason matches OpenAI's allowed types\n let validFinishReason: \"stop\" | \"length\" | \"tool_calls\" | \"content_filter\";\n\n if (finishReason === \"tool_calls\" || finishReason === \"tool-calls\") {\n validFinishReason = \"tool_calls\";\n } else if (finishReason === \"stop\") {\n validFinishReason = \"stop\";\n } else if (finishReason === \"length\") {\n validFinishReason = \"length\";\n } else if (finishReason === \"content_filter\") {\n validFinishReason = \"content_filter\";\n } else {\n validFinishReason = \"stop\"; // fallback to \"stop\" for unknown reasons\n }\n\n return {\n id: responseId,\n object: \"chat.completion.chunk\",\n created: getCurrentTimestamp(),\n model,\n choices: [\n {\n index: 0,\n delta: {},\n finish_reason: validFinishReason,\n },\n ],\n };\n}\n\n// Helper function to create content response\nfunction createContentResponse(\n model: string,\n content: string,\n responseId: string,\n isReasoning = false\n): OpenAIChatResponse {\n const delta: Record<string, unknown> = { role: \"assistant\" };\n\n if (isReasoning) {\n delta.reasoning_content = content;\n } else {\n delta.content = content;\n }\n\n return {\n id: responseId,\n object: \"chat.completion.chunk\",\n created: getCurrentTimestamp(),\n model,\n choices: [\n {\n index: 0,\n delta,\n },\n ],\n };\n}\n\n// Helper function to create tool call response\nfunction createToolCallResponse(\n model: string,\n toolCall: ToolCallDelta,\n responseId: string,\n includeRole = false\n): OpenAIChatResponse {\n return {\n id: responseId,\n object: \"chat.completion.chunk\",\n created: getCurrentTimestamp(),\n model,\n choices: [\n {\n index: 0,\n delta: {\n ...(includeRole ? { role: \"assistant\" as const } : {}),\n tool_calls: [\n {\n index: toolCall.index || 0,\n type: \"function\" as const,\n function: {\n name: toolCall.function?.name || \"\",\n arguments: toolCall.function?.arguments || \"\",\n },\n },\n ],\n },\n },\n ],\n };\n}\n\n// (legacy stateless handler removed)\n\nexport function createOpenAIStreamConverter(\n model: string,\n options?: {\n logChunks?: boolean;\n }\n) {\n let streamHasToolCalls = false;\n let streamFinishSent = false;\n let streamResponseId = generateResponseId();\n\n const logChunk =\n options?.logChunks === false\n ? undefined\n : (chunk: unknown) => {\n const logType =\n process.env.USE_MIDDLEWARE === \"true\" ? \"middleware\" : \"native\";\n console.log(\n `🔍 AI SDK Chunk [${logType}]:`,\n JSON.stringify(chunk, null, 2)\n );\n };\n\n const handlers: Record<string, ChunkHandler> = {\n start: () => [],\n \"reasoning-delta\": (chunk) => {\n if (!chunk.text) {\n return [];\n }\n return [\n {\n data: JSON.stringify(\n createContentResponse(model, chunk.text, streamResponseId, true)\n ),\n },\n ];\n },\n \"text-delta\": (chunk) => {\n if (!chunk.text) {\n return [];\n }\n return [\n {\n data: JSON.stringify(\n createContentResponse(model, chunk.text, streamResponseId, false)\n ),\n },\n ];\n },\n \"tool-call\": (chunk) => {\n const toolCallId = chunk.toolCallId || `call_${generateResponseId()}`;\n const toolName = chunk.toolName || \"\";\n const argsString =\n typeof chunk.input === \"string\"\n ? chunk.input\n : JSON.stringify(chunk.input ?? {});\n const toolCallDelta: OpenAIStreamingToolCall = {\n index: 0,\n id: toolCallId,\n type: \"function\",\n function: { name: toolName, arguments: argsString },\n };\n const response = createToolCallResponse(\n model,\n toolCallDelta,\n streamResponseId,\n true\n );\n return [{ data: JSON.stringify(response) }];\n },\n \"reasoning-end\": () => [],\n \"text-end\": () => [],\n \"finish-step\": (chunk) => {\n if (streamFinishSent) {\n return [];\n }\n const hadToolCalls = streamHasToolCalls;\n let finishReason = chunk.finishReason || \"stop\";\n if (finishReason === \"tool_calls\" || finishReason === \"tool-calls\") {\n finishReason = \"tool_calls\";\n }\n const resolvedReason = hadToolCalls ? \"tool_calls\" : finishReason;\n streamFinishSent = true;\n streamHasToolCalls = false;\n return [\n {\n data: JSON.stringify(\n createFinishResponse(model, resolvedReason, streamResponseId)\n ),\n },\n ];\n },\n \"tool-call-delta\": (chunk) => {\n const toolCall = {\n index: chunk.toolCallId ? Number(chunk.toolCallId) : 0,\n type: \"function\" as const,\n function: {\n name: chunk.toolName || \"\",\n arguments: chunk.args || \"\",\n },\n };\n return [\n {\n data: JSON.stringify(\n createToolCallResponse(model, toolCall, streamResponseId)\n ),\n },\n ];\n },\n \"tool-result\": (chunk) => {\n const resultText = `\\n[Tool: ${chunk.toolName} returned ${JSON.stringify(chunk.output)}]\\n`;\n return [\n {\n data: JSON.stringify(\n createContentResponse(model, resultText, streamResponseId, false)\n ),\n },\n ];\n },\n finish: (chunk) => {\n if (streamFinishSent) {\n return [];\n }\n const hadToolCalls = streamHasToolCalls;\n let finishReason = chunk.finishReason || \"stop\";\n if (finishReason === \"tool_calls\" || finishReason === \"tool-calls\") {\n finishReason = \"tool_calls\";\n }\n const resolvedReason = hadToolCalls ? \"tool_calls\" : finishReason;\n streamFinishSent = true;\n streamHasToolCalls = false;\n return [\n {\n data: JSON.stringify(\n createFinishResponse(model, resolvedReason, streamResponseId)\n ),\n },\n ];\n },\n };\n\n return (\n // biome-ignore lint/suspicious/noExplicitAny: ai sdk boundary\n chunk: any\n ): StreamChunk[] => {\n const out: StreamChunk[] = [];\n\n logChunk?.(chunk);\n\n if (chunk.type === \"start\") {\n streamHasToolCalls = false;\n streamFinishSent = false;\n streamResponseId = chunk.id ?? generateResponseId();\n }\n\n const handler = handlers[chunk.type];\n if (handler) {\n const result = handler(chunk as AIStreamChunk, model);\n if (chunk.type === \"tool-call\" || chunk.type === \"tool-call-delta\") {\n streamHasToolCalls = true;\n }\n out.push(...result);\n } else {\n console.warn(`⚠️ Unknown AI SDK chunk type: ${chunk.type}`, chunk);\n }\n\n if (chunk.type === \"finish-step\" || chunk.type === \"finish\") {\n streamHasToolCalls = false;\n }\n\n return out.filter((resultChunk) => {\n try {\n const parsed = JSON.parse(resultChunk.data);\n const delta = parsed.choices?.[0]?.delta;\n return (\n delta &&\n (delta.role ||\n delta.content ||\n (delta as NonNullable<OpenAIChoice[\"delta\"]>).reasoning_content ||\n (delta.tool_calls && delta.tool_calls.length > 0) ||\n parsed.choices?.[0]?.finish_reason)\n );\n } catch {\n return true;\n }\n });\n };\n}\n\nexport function convertAISDKStreamChunkToOpenAI(\n // biome-ignore lint/suspicious/noExplicitAny: o sdk integration boundary\n chunk: any,\n model: string\n): StreamChunk[] {\n const convert = createOpenAIStreamConverter(model);\n return convert(chunk);\n}\n\n/**\n * Create SSE formatted response\n */\nexport function createSSEResponse(chunks: StreamChunk[]): string {\n return chunks.map((chunk) => `data: ${chunk.data}\\n\\n`).join(\"\");\n}\n","import { zodSchema } from \"@ai-sdk/provider-utils\";\nimport cors from \"@fastify/cors\";\nimport { generateText, streamText } from \"ai\";\nimport Fastify, {\n type FastifyInstance,\n type FastifyReply,\n type FastifyRequest,\n} from \"fastify\";\nimport { toJSONSchema, type ZodTypeAny } from \"zod\";\nimport { convertOpenAIRequestToAISDK } from \"./openai-request-converter.js\";\nimport {\n convertAISDKResultToOpenAI,\n createOpenAIStreamConverter,\n} from \"./response-converter.js\";\nimport type {\n AISDKTool,\n Logger,\n OpenAIChatRequest,\n ProxyConfig,\n} from \"./types.js\";\n\ntype ConvertedParams = ReturnType<typeof convertOpenAIRequestToAISDK>;\n\nfunction serializeZodSchema(schema: ZodTypeAny | undefined): unknown {\n if (!schema) {\n return null;\n }\n\n // Use Zod v4's built-in JSON Schema conversion\n const jsonSchema = toJSONSchema(schema, {\n unrepresentable: \"any\",\n });\n\n // Remove $schema field for cleaner output\n if (typeof jsonSchema === \"object\" && jsonSchema !== null) {\n const { $schema, ...rest } = jsonSchema as Record<string, unknown>;\n return rest;\n }\n\n return jsonSchema;\n}\n\nfunction serializeMessages(messages: OpenAIChatRequest[\"messages\"]) {\n return messages.map((message, index) => ({\n index,\n role: message.role,\n content: message.content,\n toolCalls: message.tool_calls,\n }));\n}\n\nfunction logIncomingRequest(\n openaiRequest: OpenAIChatRequest,\n enabled: boolean\n) {\n if (!enabled) {\n return;\n }\n const toolNames = (openaiRequest.tools ?? [])\n .map((tool) => (\"function\" in tool ? tool.function?.name : undefined))\n .filter((name): name is string => Boolean(name));\n\n console.log(\n \"[proxy] Incoming OpenAI request\",\n JSON.stringify(\n {\n model: openaiRequest.model,\n stream: Boolean(openaiRequest.stream),\n temperature: openaiRequest.temperature,\n maxTokens: openaiRequest.max_tokens,\n toolNames,\n toolChoice: openaiRequest.tool_choice,\n messages: serializeMessages(openaiRequest.messages),\n tools: openaiRequest.tools,\n },\n null,\n 2\n )\n );\n}\n\nfunction serializeAISDKMessages(messages: ConvertedParams[\"messages\"]) {\n return messages?.map((message, index) => ({\n index,\n role: message.role,\n content: message.content,\n }));\n}\n\nfunction logRequestConversion(\n openaiRequest: OpenAIChatRequest,\n aisdkParams: ConvertedParams,\n enabled: boolean\n) {\n if (!enabled) {\n return;\n }\n const messages = aisdkParams.messages ?? [];\n console.log(\n \"[proxy] Converted AI SDK params\",\n JSON.stringify(\n {\n model: openaiRequest.model,\n hasSystemMessage: messages.some((message) => message.role === \"system\"),\n messages: serializeAISDKMessages(messages),\n tools: Object.entries(aisdkParams.tools ?? {}).map(([name, tool]) => ({\n name,\n description: tool.description,\n inputSchema: serializeZodSchema(tool.inputSchema),\n })),\n temperature: aisdkParams.temperature,\n maxOutputTokens: aisdkParams.maxOutputTokens,\n stopSequences: aisdkParams.stopSequences,\n },\n null,\n 2\n )\n );\n}\n\nexport class OpenAIProxyServer {\n private readonly fastify: FastifyInstance;\n private readonly config: ProxyConfig;\n private readonly logger: Logger;\n\n constructor(config: ProxyConfig) {\n this.config = {\n port: 3000,\n host: \"localhost\",\n cors: true,\n ...config,\n };\n this.logger = (config.logger ?? console) as Logger;\n\n this.fastify = Fastify();\n\n // Enable CORS\n if (this.config.cors) {\n this.fastify.register(cors);\n }\n\n this.setupRoutes();\n }\n\n private setupRoutes(): void {\n // Health check endpoint\n this.fastify.get(\n \"/health\",\n async (_request: FastifyRequest, _reply: FastifyReply) => ({\n status: \"ok\",\n timestamp: new Date().toISOString(),\n })\n );\n\n // OpenAI-compatible chat completions endpoint\n this.fastify.post(\n \"/v1/chat/completions\",\n (request: FastifyRequest, reply: FastifyReply) => {\n try {\n const openaiRequest = request.body as OpenAIChatRequest;\n\n // Validate request\n if (\n !(openaiRequest.messages && Array.isArray(openaiRequest.messages))\n ) {\n return reply.code(400).send({\n error: {\n message: \"Messages array is required\",\n type: \"invalid_request_error\",\n },\n });\n }\n\n logIncomingRequest(\n openaiRequest,\n this.config.logging?.requests ?? true\n );\n\n // Convert OpenAI request to AI SDK format\n const aisdkParams = convertOpenAIRequestToAISDK(openaiRequest, {\n parserDebug: this.config.parserDebug,\n });\n logRequestConversion(\n openaiRequest,\n aisdkParams,\n this.config.logging?.conversions ?? true\n );\n\n // Handle streaming vs non-streaming\n if (openaiRequest.stream) {\n return this.handleStreamingRequest(\n aisdkParams,\n openaiRequest,\n reply\n );\n }\n return this.handleNonStreamingRequest(\n aisdkParams,\n openaiRequest,\n reply\n );\n } catch (error) {\n this.logger.error(\"Request handling error:\", error);\n return reply.code(500).send({\n error: {\n message: \"Internal server error\",\n type: \"server_error\",\n },\n });\n }\n }\n );\n\n // Models endpoint\n this.fastify.get(\"/v1/models\", async () => ({\n object: \"list\",\n data: [\n {\n id: \"wrapped-model\",\n object: \"model\",\n created: Math.floor(Date.now() / 1000),\n owned_by: \"ai-sdk-tool-proxy\",\n },\n ],\n }));\n }\n\n // Merge server-defined tools (with execute) and request-defined tools (schema-only)\n // Server tools take precedence when names overlap.\n private mergeTools(\n serverTools?: Record<string, AISDKTool>,\n requestTools?: Record<string, AISDKTool>\n ) {\n const toProviderTool = (tool: AISDKTool | undefined): unknown => {\n if (!tool) {\n return;\n }\n\n return {\n description: tool.description,\n inputSchema: zodSchema(tool.inputSchema),\n ...(tool.execute ? { execute: tool.execute } : {}),\n };\n };\n\n const merged: Record<string, unknown> = {};\n\n for (const [name, t] of Object.entries(requestTools ?? {})) {\n const pt = toProviderTool(t);\n if (pt) {\n merged[name] = pt;\n }\n }\n\n for (const [name, t] of Object.entries(serverTools ?? {})) {\n const pt = toProviderTool(t);\n if (pt) {\n merged[name] = pt; // override request tool\n }\n }\n\n return Object.keys(merged).length > 0 ? merged : undefined;\n }\n\n private async handleStreamingRequest(\n // biome-ignore lint/suspicious/noExplicitAny: o sdk integration boundary\n aisdkParams: any,\n openaiRequest: OpenAIChatRequest,\n reply: FastifyReply\n ): Promise<void> {\n // Set SSE headers\n reply.raw.writeHead(200, {\n \"Content-Type\": \"text/event-stream\",\n \"Cache-Control\": \"no-cache\",\n Connection: \"keep-alive\",\n \"Access-Control-Allow-Origin\": \"*\",\n });\n\n try {\n const mergedTools = this.mergeTools(this.config.tools, aisdkParams.tools);\n const result = await streamText({\n model: this.config.model,\n ...aisdkParams,\n ...(mergedTools ? { tools: mergedTools } : {}),\n });\n\n const convert = createOpenAIStreamConverter(openaiRequest.model, {\n logChunks: this.config.logging?.streamChunks ?? true,\n });\n for await (const chunk of result.fullStream) {\n const openaiChunks = convert(chunk);\n for (const openaiChunk of openaiChunks) {\n reply.raw.write(`data: ${openaiChunk.data}\\n\\n`);\n }\n }\n\n reply.raw.write(\"data: [DONE]\\n\\n\");\n reply.raw.end();\n } catch (error) {\n this.logger.error(\"Streaming error:\", error);\n reply.raw.write('data: {\"error\": {\"message\": \"Streaming error\"}}\\n\\n');\n reply.raw.end();\n }\n\n return reply;\n }\n\n private async handleNonStreamingRequest(\n // biome-ignore lint/suspicious/noExplicitAny: o sdk integration boundary\n aisdkParams: any,\n openaiRequest: OpenAIChatRequest,\n reply: FastifyReply\n ): Promise<void> {\n try {\n const mergedTools = this.mergeTools(this.config.tools, aisdkParams.tools);\n const result = await generateText({\n model: this.config.model,\n ...aisdkParams,\n ...(mergedTools ? { tools: mergedTools } : {}),\n });\n\n const openaiResponse = convertAISDKResultToOpenAI(\n result,\n openaiRequest.model,\n false\n );\n\n reply.send(openaiResponse);\n } catch (error) {\n this.logger.error(\"Generation error:\", error);\n return reply.code(500).send({\n error: {\n message: \"Generation failed\",\n type: \"generation_error\",\n },\n });\n }\n }\n\n async start(): Promise<void> {\n try {\n await this.fastify.listen({\n port: this.config.port || 3000,\n host: this.config.host || \"localhost\",\n });\n\n this.logger.info(\n `🚀 OpenAI Proxy Server running on http://${this.config.host}:${this.config.port}`\n );\n this.logger.info(\n `📡 Endpoint: http://${this.config.host}:${this.config.port}/v1/chat/completions`\n );\n this.logger.info(\n `🏥 Health: http://${this.config.host}:${this.config.port}/health`\n );\n } catch (error) {\n this.logger.error(\"Failed to start server:\", error);\n process.exit(1);\n }\n }\n\n async stop(): Promise<void> {\n try {\n await this.fastify.close();\n this.logger.info(\"🛑 Server stopped\");\n } catch (error) {\n this.logger.error(\"Error stopping server:\", error);\n }\n }\n}\n"],"mappings":"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","names":["_a","_a"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-sdk-tool/proxy",
3
- "version": "0.0.0",
3
+ "version": "0.0.1",
4
4
  "description": "OpenAI-compatible proxy server for AI SDK tool middleware",
5
5
  "type": "module",
6
6
  "repository": {
@@ -24,30 +24,23 @@
24
24
  "publishConfig": {
25
25
  "access": "public"
26
26
  },
27
- "scripts": {
28
- "build": "pnpm clean && tsup --tsconfig tsconfig.build.json",
29
- "build:watch": "pnpm clean && tsup --watch --tsconfig tsconfig.build.json",
30
- "clean": "rm -rf dist *.tsbuildinfo",
31
- "typecheck": "tsc --noEmit",
32
- "test": "vitest run"
33
- },
34
27
  "dependencies": {
35
- "@ai-sdk/provider": "3.0.0",
36
- "@ai-sdk/provider-utils": "4.0.0",
28
+ "@ai-sdk/provider": "3.0.1",
29
+ "@ai-sdk/provider-utils": "4.0.2",
37
30
  "@fastify/cors": "^11.2.0",
38
- "ai": "6.0.1",
31
+ "ai": "6.0.5",
39
32
  "fastify": "^5.6.2",
40
- "zod": "^4.2.1"
33
+ "zod": "^4.3.4"
41
34
  },
42
35
  "devDependencies": {
43
- "@ai-sdk-tool/parser": "workspace:*",
44
- "@ai-sdk/openai-compatible": "2.0.0",
45
- "@ai-sdkx/tsconfig": "workspace:*",
36
+ "@ai-sdk/openai-compatible": "2.0.2",
46
37
  "@types/node": "^25.0.3",
47
38
  "@vitest/coverage-v8": "^4.0.16",
48
39
  "@vitest/ui": "^4.0.16",
49
40
  "tsup": "^8.5.1",
50
- "vitest": "^4.0.16"
41
+ "vitest": "^4.0.16",
42
+ "@ai-sdk-tool/parser": "3.0.0",
43
+ "@ai-sdkx/tsconfig": "0.0.1"
51
44
  },
52
45
  "keywords": [
53
46
  "ai",
@@ -58,5 +51,12 @@
58
51
  "middleware"
59
52
  ],
60
53
  "author": "",
61
- "license": "Apache-2.0"
62
- }
54
+ "license": "Apache-2.0",
55
+ "scripts": {
56
+ "build": "pnpm clean && tsup --tsconfig tsconfig.build.json",
57
+ "build:watch": "pnpm clean && tsup --watch --tsconfig tsconfig.build.json",
58
+ "clean": "rm -rf dist *.tsbuildinfo",
59
+ "typecheck": "tsc --noEmit",
60
+ "test": "vitest run"
61
+ }
62
+ }