UNPKG

@crowdin/app-project-module

Version:

Module that generates for you all common endpoints for serving standalone Crowdin App

129 lines (128 loc) 5.07 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); const util_1 = require("../../../util"); const logger_1 = require("../../../util/logger"); const files_1 = require("../../integration/util/files"); const util_2 = require("../util"); const DEFAULT_ROLE = 'assistant'; const getErrorStatus = (e) => { if (typeof e === 'object' && 'status' in e && typeof e.status === 'number') { return e.status; } return 500; }; const getErrorCode = (e) => { if (typeof e === 'object' && 'code' in e) { return e.code; } return undefined; }; function handle(aiProvider) { return (0, util_1.runAsyncWrapper)((req, res) => __awaiter(this, void 0, void 0, function* () { let isStream = false; try { let choices; let message; let data; const chunks = []; const { crowdinApiClient: client, crowdinContext: context, body: { messages, model, action, stream, tools, tool_choice: toolChoice, responseFormat: { type: responseFormatType } = { type: undefined }, }, } = req; isStream = !!stream; const startStream = () => { if (!res.headersSent) { res.writeHead(200, { Connection: 'keep-alive', 'Cache-Control': 'no-cache', 'Content-Type': 'text/event-stream', 'X-Accel-Buffering': 'no', }); } }; const result = yield aiProvider.chatCompletions({ messages: messages.map(util_2.inputMessageToChatCompletionMessage), model, action, responseFormat: responseFormatType, client, context, req, isStream, tools, toolChoice, sendEvent: ({ content, role, tool_calls }) => __awaiter(this, void 0, void 0, function* () { if (!isStream) { chunks.push({ content, role, tool_calls }); return; } startStream(); const delta = { role: role || DEFAULT_ROLE, content: content || null, }; if (!!tool_calls) { delta.tool_calls = tool_calls; } const message = { choices: [ { delta, }, ], }; res.write(`data: ${JSON.stringify(message)}\n\n`); }), }); if (isStream) { startStream(); res.write('[DONE]'); res.end(); return; } if ((0, files_1.isExtendedResultType)(result)) { data = result.data; message = result.message; } else { data = result; } if (chunks.length) { data = (0, util_2.mergeChatCompletionChunks)(chunks); } if (data && data.length > 0) { choices = data.map((message) => ({ message: { role: message.role || DEFAULT_ROLE, content: message.content || null, tool_calls: message.tool_calls, }, })); } res.send({ choices, message }); } catch (e) { if (req.logError) { req.logError(e); } if (!res.headersSent) { res.status((0, util_2.isRateLimitError)(e) ? 429 : getErrorStatus(e)); } if (isStream && res.headersSent) { res.write(`data: ${JSON.stringify({ error: { message: (0, logger_1.getErrorMessage)(e), code: getErrorCode(e) } })}\n\n`); res.write('[DONE]'); res.end(); } else { res.send({ error: { message: (0, logger_1.getErrorMessage)(e) } }); } } })); } exports.default = handle;