(
params: BuildPayloadParams,
options: {
selectedModel: string
}
)
| 247 | * Build the request payload for the copilot backend. |
| 248 | */ |
| 249 | export async function buildCopilotRequestPayload( |
| 250 | params: BuildPayloadParams, |
| 251 | options: { |
| 252 | selectedModel: string |
| 253 | } |
| 254 | ): Promise<Record<string, unknown>> { |
| 255 | const { |
| 256 | message, |
| 257 | workflowId, |
| 258 | userId, |
| 259 | userMessageId, |
| 260 | mode, |
| 261 | provider, |
| 262 | contexts, |
| 263 | fileAttachments, |
| 264 | commands, |
| 265 | chatId, |
| 266 | prefetch, |
| 267 | implicitFeedback, |
| 268 | } = params |
| 269 | |
| 270 | const selectedModel = options.selectedModel |
| 271 | |
| 272 | const effectiveMode = mode === 'agent' ? 'build' : mode |
| 273 | const transportMode = effectiveMode === 'build' ? 'agent' : effectiveMode |
| 274 | |
| 275 | // Track uploaded files in the DB and build context tags instead of base64 inlining |
| 276 | const uploadContexts: Array<{ type: string; content: string; tag?: string; path?: string }> = [] |
| 277 | if (chatId && params.workspaceId && fileAttachments && fileAttachments.length > 0) { |
| 278 | for (const f of fileAttachments) { |
| 279 | const filename = (f.filename ?? f.name ?? 'file') as string |
| 280 | const mediaType = (f.media_type ?? f.mimeType ?? 'application/octet-stream') as string |
| 281 | try { |
| 282 | const { displayName } = await trackChatUpload( |
| 283 | params.workspaceId, |
| 284 | userId, |
| 285 | chatId, |
| 286 | f.key, |
| 287 | filename, |
| 288 | mediaType, |
| 289 | f.size |
| 290 | ) |
| 291 | // Encode the read path per the percent-encoded VFS convention (matches |
| 292 | // files/ and the uploads glob output). The materialize_file `fileName` |
| 293 | // arg stays the raw display name — the upload resolver accepts both. |
| 294 | let encodedUploadName = displayName |
| 295 | try { |
| 296 | encodedUploadName = encodeVfsSegment(displayName) |
| 297 | } catch { |
| 298 | encodedUploadName = displayName |
| 299 | } |
| 300 | const lines = [ |
| 301 | `File "${displayName}" (${mediaType}, ${f.size} bytes) uploaded.`, |
| 302 | `Read with: read("uploads/${encodedUploadName}")`, |
| 303 | `To save permanently: materialize_file(fileName: "${displayName}")`, |
| 304 | ] |
| 305 | if (displayName.endsWith('.json')) { |
| 306 | lines.push( |
no test coverage detected