@@ -198,25 +198,42 @@ export async function endpointOai(
198
198
toolResults,
199
199
conversationId,
200
200
} ) => {
201
+ // Format messages for the chat API, handling multimodal content if supported
201
202
let messagesOpenAI : OpenAI . Chat . Completions . ChatCompletionMessageParam [ ] =
202
203
await prepareMessages ( messages , imageProcessor , ! model . tools && model . multimodal ) ;
203
204
204
- if ( messagesOpenAI ?. [ 0 ] ?. role !== "system" ) {
205
- messagesOpenAI = [ { role : "system" , content : "" } , ...messagesOpenAI ] ;
206
- }
205
+ // Check if a system message already exists as the first message
206
+ const hasSystemMessage = messagesOpenAI . length > 0 && messagesOpenAI [ 0 ] ?. role === "system" ;
207
207
208
- if ( messagesOpenAI ?. [ 0 ] ) {
209
- messagesOpenAI [ 0 ] . content = preprompt ?? "" ;
208
+ if ( hasSystemMessage ) {
209
+ // System message exists - preserve user configuration
210
+ if ( preprompt !== undefined ) {
211
+ // Prepend preprompt to existing system message if preprompt exists
212
+ const userSystemPrompt = messagesOpenAI [ 0 ] . content || "" ;
213
+ messagesOpenAI [ 0 ] . content =
214
+ preprompt + ( userSystemPrompt ? "\n\n" + userSystemPrompt : "" ) ;
215
+ }
216
+ // If no preprompt, user's system message remains unchanged
217
+ } else {
218
+ // No system message exists - create a new one with preprompt or empty string
219
+ messagesOpenAI = [ { role : "system" , content : preprompt ?? "" } , ...messagesOpenAI ] ;
210
220
}
211
221
212
- // if system role is not supported, convert first message to a user message.
213
- if ( ! model . systemRoleSupported && messagesOpenAI ?. [ 0 ] ?. role === "system" ) {
222
+ // Handle models that don't support system role by converting to user message
223
+ // This maintains compatibility with older or non-standard models
224
+ if (
225
+ ! model . systemRoleSupported &&
226
+ messagesOpenAI . length > 0 &&
227
+ messagesOpenAI [ 0 ] ?. role === "system"
228
+ ) {
214
229
messagesOpenAI [ 0 ] = {
215
230
...messagesOpenAI [ 0 ] ,
216
231
role : "user" ,
217
232
} ;
218
233
}
219
234
235
+ // Format tool results for the API to provide context for follow-up tool calls
236
+ // This creates the full conversation flow needed for multi-step tool interactions
220
237
if ( toolResults && toolResults . length > 0 ) {
221
238
const toolCallRequests : OpenAI . Chat . Completions . ChatCompletionAssistantMessageParam = {
222
239
role : "assistant" ,
@@ -253,12 +270,14 @@ export async function endpointOai(
253
270
messagesOpenAI . push ( ...responses ) ;
254
271
}
255
272
273
+ // Combine model defaults with request-specific parameters
256
274
const parameters = { ...model . parameters , ...generateSettings } ;
257
275
const toolCallChoices = createChatCompletionToolsArray ( tools ) ;
258
276
const body = {
259
277
model : model . id ?? model . name ,
260
278
messages : messagesOpenAI ,
261
279
stream : streamingSupported ,
280
+ // Support two different ways of specifying token limits depending on the model
262
281
...( useCompletionTokens
263
282
? { max_completion_tokens : parameters ?. max_new_tokens }
264
283
: { max_tokens : parameters ?. max_new_tokens } ) ,
@@ -267,9 +286,11 @@ export async function endpointOai(
267
286
top_p : parameters ?. top_p ,
268
287
frequency_penalty : parameters ?. repetition_penalty ,
269
288
presence_penalty : parameters ?. presence_penalty ,
289
+ // Only include tool configuration if tools are provided
270
290
...( toolCallChoices . length > 0 ? { tools : toolCallChoices , tool_choice : "auto" } : { } ) ,
271
291
} ;
272
292
293
+ // Handle both streaming and non-streaming responses with appropriate processors
273
294
if ( streamingSupported ) {
274
295
const openChatAICompletion = await openai . chat . completions . create (
275
296
body as ChatCompletionCreateParamsStreaming ,
0 commit comments