incognitolm commited on
Commit
cfae871
·
1 Parent(s): 6a9c39c

Update chatStream.js

Browse files
Files changed (1) hide show
  1. server/chatStream.js +35 -4
server/chatStream.js CHANGED
@@ -123,17 +123,35 @@ export async function streamChat(ws, {
123
  const client = makeClient(accessToken, clientId);
124
  const enabledTools = buildToolList(tools);
125
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
126
  const messages = [
127
  { role: "system", content: SYSTEM_PROMPT },
128
  ...history.map(normalizeMessage).filter(Boolean),
129
- { role: "user", content: userMessage },
130
  ];
 
 
 
 
 
131
 
132
  // Validate messages before API call
133
  for (let i = 0; i < messages.length; i++) {
134
  const msg = messages[i];
135
  if (msg.role !== "assistant" || !msg.tool_calls) {
136
- if (typeof msg.content !== "string") {
137
  console.error(`Message ${i} has invalid content:`, msg);
138
  throw new Error(`Message ${i} missing or invalid content property`);
139
  }
@@ -158,10 +176,17 @@ export async function streamChat(ws, {
158
  const followUpMessages = [
159
  { role: "system", content: SYSTEM_PROMPT },
160
  ...history.map(normalizeMessage).filter(Boolean),
161
- { role: "user", content: userMessage },
 
 
 
 
 
 
 
162
  { role: "assistant", content: assistantText || "", tool_calls: toolCalls },
163
  ...toolResults,
164
- ];
165
 
166
  const followUpStream = await client.chat.completions.create({
167
  model: model || "lightning",
@@ -195,6 +220,12 @@ function normalizeMessage(msg) {
195
  return { role: "assistant", content: "", tool_calls: msg.tool_calls };
196
  }
197
  if (Array.isArray(msg.content)) {
 
 
 
 
 
 
198
  const textOnly = msg.content
199
  .filter(b => b.type === "text")
200
  .map(b => b.text)
 
123
  const client = makeClient(accessToken, clientId);
124
  const enabledTools = buildToolList(tools);
125
 
126
+ // Normalize userMessage: convert array content to string or keep as-is for image support
127
+ let normalizedUserMessage = userMessage;
128
+ if (Array.isArray(userMessage)) {
129
+ // If it has images, keep the array format for OpenAI to process images
130
+ // Otherwise extract text
131
+ const hasImages = userMessage.some(item => item.type === 'image_url');
132
+ if (hasImages) {
133
+ normalizedUserMessage = userMessage;
134
+ } else {
135
+ normalizedUserMessage = userMessage.filter(b => b.type === "text").map(b => b.text).join("\n") || "";
136
+ }
137
+ }
138
+
139
+ // Build messages array: only include user message if it's provided
140
  const messages = [
141
  { role: "system", content: SYSTEM_PROMPT },
142
  ...history.map(normalizeMessage).filter(Boolean),
 
143
  ];
144
+
145
+ // Add user message only if content was provided (not for edit-only requests)
146
+ if (userMessage !== undefined && userMessage !== null && userMessage !== '') {
147
+ messages.push({ role: "user", content: normalizedUserMessage });
148
+ }
149
 
150
  // Validate messages before API call
151
  for (let i = 0; i < messages.length; i++) {
152
  const msg = messages[i];
153
  if (msg.role !== "assistant" || !msg.tool_calls) {
154
+ if (typeof msg.content !== "string" && !Array.isArray(msg.content)) {
155
  console.error(`Message ${i} has invalid content:`, msg);
156
  throw new Error(`Message ${i} missing or invalid content property`);
157
  }
 
176
  const followUpMessages = [
177
  { role: "system", content: SYSTEM_PROMPT },
178
  ...history.map(normalizeMessage).filter(Boolean),
179
+ ];
180
+
181
+ // Include user message in follow-up only if it was in the original request
182
+ if (userMessage !== undefined && userMessage !== null && userMessage !== '') {
183
+ followUpMessages.push({ role: "user", content: normalizedUserMessage });
184
+ }
185
+
186
+ followUpMessages.push(
187
  { role: "assistant", content: assistantText || "", tool_calls: toolCalls },
188
  ...toolResults,
189
+ );
190
 
191
  const followUpStream = await client.chat.completions.create({
192
  model: model || "lightning",
 
220
  return { role: "assistant", content: "", tool_calls: msg.tool_calls };
221
  }
222
  if (Array.isArray(msg.content)) {
223
+ // If the array contains images, preserve the full array format
224
+ const hasImages = msg.content.some(item => item.type === 'image_url');
225
+ if (hasImages) {
226
+ return { role: msg.role, content: msg.content };
227
+ }
228
+ // Otherwise extract text only
229
  const textOnly = msg.content
230
  .filter(b => b.type === "text")
231
  .map(b => b.text)