MCPcopy Create free account
hub / github.com/dwgx/WindsurfAPI / buildRawGetChatMessageRequest

Function buildRawGetChatMessageRequest

src/windsurf.js:154–230  ·  view source on GitHub ↗
(apiKey, messages, modelEnum, modelName, sessionId = null)

Source from the content-addressed store, hash-verified

152 * @param {string} [modelName] - Model name string (optional)
153 */
154export function buildRawGetChatMessageRequest(apiKey, messages, modelEnum, modelName, sessionId = null) {
155 const parts = [];
156 const conversationId = randomUUID();
157
158 // Field 1: Metadata — pass through the caller's session id so the
159 // legacy Raw channel uses the same per-LS session as Cascade instead
160 // of a fresh UUID per request (anti-fingerprint).
161 parts.push(writeMessageField(1, buildMetadata(apiKey, undefined, sessionId)));
162
163 // Field 2: repeated ChatMessage (skip system, handled separately).
164 // Windsurf's legacy RawGetChatMessage backend rejects role=tool and
165 // doesn't know about assistant tool_calls. Degrade both to plain text
166 // so multi-turn conversations that carry tool history still flow
167 // through without triggering "proto: cannot parse invalid wire-format
168 // data" upstream. Cascade models are unaffected — they use a different
169 // endpoint (SendUserCascadeMessage) with full tool support.
170 let systemPrompt = '';
171 for (const msg of messages) {
172 if (msg.role === 'system') {
173 systemPrompt += (systemPrompt ? '\n' : '') +
174 (typeof msg.content === 'string' ? msg.content : JSON.stringify(msg.content));
175 continue;
176 }
177
178 let source;
179 let text;
180 const baseText = typeof msg.content === 'string' ? msg.content
181 : Array.isArray(msg.content) ? msg.content.filter(c => c.type === 'text').map(c => c.text).join('\n')
182 : msg.content == null ? '' : JSON.stringify(msg.content);
183
184 switch (msg.role) {
185 case 'user':
186 source = SOURCE.USER;
187 text = baseText;
188 break;
189 case 'assistant':
190 source = SOURCE.ASSISTANT;
191 // If the assistant previously called tools, append the call descriptions
192 // so the model sees its own prior tool usage as text. Empty string OK.
193 if (Array.isArray(msg.tool_calls) && msg.tool_calls.length) {
194 const tcLines = msg.tool_calls.map(tc =>
195 `[called tool ${tc.function?.name || 'unknown'} with ${tc.function?.arguments || '{}'}]`
196 ).join('\n');
197 text = baseText ? `${baseText}\n${tcLines}` : tcLines;
198 } else {
199 text = baseText;
200 }
201 break;
202 case 'tool':
203 // Rewrite tool-result turn as a synthetic user utterance so the
204 // server-side schema accepts it.
205 source = SOURCE.USER;
206 text = `[tool result${msg.tool_call_id ? ` for ${msg.tool_call_id}` : ''}]: ${baseText}`;
207 break;
208 default:
209 source = SOURCE.USER;
210 text = baseText;
211 }

Callers 1

rawGetChatMessageMethod · 0.90

Calls 6

writeMessageFieldFunction · 0.90
writeStringFieldFunction · 0.90
writeVarintFieldFunction · 0.90
buildChatMessageFunction · 0.85
pushMethod · 0.80
buildMetadataFunction · 0.70

Tested by

no test coverage detected