'use strict'; exports.main = async (event, context) => { // uniCloud HTTP 触发器:event 本身就是请求信息 // event.httpMethod = 'GET'/'POST'/'OPTIONS' // event.body = 请求体 // event.headers = 请求头 // context.callbackWaitsForEmptyEventLoop = true 保持连接 const corsHeaders = { 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Methods': 'GET, POST, OPTIONS', 'Access-Control-Allow-Headers': 'Content-Type, Authorization', 'Access-Control-Max-Age': '86400' }; // 处理 CORS 预检 if (event.httpMethod === 'OPTIONS') { return { statusCode: 204, headers: corsHeaders, body: '' }; } // 设置等待空事件循环(保持 SSE 连接) context.callbackWaitsForEmptyEventLoop = false; // 解析请求体 let body = {}; try { const raw = event.body || ''; if (event.isBase64Encoded) { body = JSON.parse(Buffer.from(raw, 'base64').toString()); } else { try { body = JSON.parse(raw); } catch (e) { const params = new URLSearchParams(raw); for (const [k, v] of params) body[k] = v; } } } catch (e) {} const { file_id, user_id, file_name, file_size, record_id } = body; if (!file_id) { return { statusCode: 400, headers: { ...corsHeaders, 'Content-Type': 'application/json' }, body: JSON.stringify({ error: '缺少 file_id' }) }; } const COZE_TOKEN = 'sat_OiXlI4Da5Q99fxmul6pNfExmA6hR898UbxBDwrvjZ638APxRSlFnXbz6zyFedKNG'; const BOT_ID = '7689821072762011698'; const objectString = JSON.stringify([ { type: 'file', file_id: file_id }, { type: 'text', text: '请审查这份合同' } ]); // 调用扣子(流式) try { const chatRes = await uniCloud.httpclient.request('https://api.coze.cn/v3/chat', { method: 'POST', dataType: 'text', contentType: 'json', timeout: 300000, headers: { 'Authorization': 'Bearer ' + COZE_TOKEN }, data: { bot_id: BOT_ID, user_id: user_id || 'anonymous', stream: true, auto_save_history: true, additional_messages: [{ role: 'user', content: objectString, content_type: 'object_string' }] } }); // 返回 SSE 格式 const text = chatRes.data || ''; const sseBody = text.split('\n').map(line => { if (line.startsWith('data:')) return line + '\n\n'; return ''; }).join('') + 'data: [DONE]\n\n'; return { statusCode: 200, headers: { ...corsHeaders, 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache', 'Connection': 'keep-alive' }, body: sseBody }; } catch (e) { return { statusCode: 500, headers: { ...corsHeaders, 'Content-Type': 'application/json' }, body: JSON.stringify({ error: e.message }) }; } };