@crowdin/app-project-module 0.68.1 → 0.70.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/out/index.js +21 -3
- package/out/modules/ai-provider/handlers/chat-completions.js +20 -21
- package/out/modules/ai-provider/handlers/get-model-list.js +3 -2
- package/out/modules/ai-provider/types.d.ts +112 -7
- package/out/modules/ai-provider/util/index.d.ts +5 -0
- package/out/modules/ai-provider/util/index.js +72 -1
- package/out/modules/api/api.js +4 -4
- package/out/modules/file-processing/handlers/pre-post-process.js +6 -0
- package/out/modules/file-processing/types.d.ts +16 -8
- package/out/modules/integration/util/cron.js +8 -5
- package/out/modules/integration/util/webhooks.js +5 -4
- package/out/modules/manifest.js +46 -0
- package/out/modules/organization-settings-menu/index.d.ts +6 -0
- package/out/modules/organization-settings-menu/index.js +18 -0
- package/out/modules/profile-settings-menu/index.d.ts +6 -0
- package/out/modules/profile-settings-menu/index.js +18 -0
- package/out/modules/webhooks/handlers/webhook-handler.d.ts +5 -0
- package/out/modules/webhooks/handlers/webhook-handler.js +78 -0
- package/out/modules/webhooks/index.d.ts +6 -0
- package/out/modules/webhooks/index.js +18 -0
- package/out/modules/webhooks/types.d.ts +294 -0
- package/out/modules/webhooks/types.js +2 -0
- package/out/modules/workflow-step-type/handlers/delete-step.d.ts +5 -0
- package/out/modules/workflow-step-type/handlers/delete-step.js +70 -0
- package/out/modules/workflow-step-type/handlers/step-settings-save.d.ts +5 -0
- package/out/modules/workflow-step-type/handlers/step-settings-save.js +80 -0
- package/out/modules/workflow-step-type/index.d.ts +6 -0
- package/out/modules/workflow-step-type/index.js +36 -0
- package/out/modules/workflow-step-type/types.d.ts +57 -0
- package/out/modules/workflow-step-type/types.js +2 -0
- package/out/modules/workflow-step-type/util/index.d.ts +3 -0
- package/out/modules/workflow-step-type/util/index.js +16 -0
- package/out/static/js/form.js +32 -32
- package/out/static/js/main.js +2 -2
- package/out/storage/index.d.ts +1 -0
- package/out/storage/mysql.d.ts +1 -0
- package/out/storage/mysql.js +9 -0
- package/out/storage/postgre.d.ts +1 -0
- package/out/storage/postgre.js +9 -0
- package/out/storage/sqlite.d.ts +1 -0
- package/out/storage/sqlite.js +3 -0
- package/out/types.d.ts +19 -1
- package/out/util/logger.d.ts +5 -2
- package/out/util/logger.js +26 -10
- package/out/views/main.handlebars +48 -24
- package/package.json +16 -8
package/out/index.js
CHANGED
|
@@ -74,11 +74,15 @@ const fileProcessingApps = __importStar(require("./modules/file-processing"));
|
|
|
74
74
|
const integrationApp = __importStar(require("./modules/integration"));
|
|
75
75
|
const modalApp = __importStar(require("./modules/modal"));
|
|
76
76
|
const organizationMenuApp = __importStar(require("./modules/organization-menu"));
|
|
77
|
+
const organizationSettingsMenuApp = __importStar(require("./modules/organization-settings-menu"));
|
|
77
78
|
const profileResourcesMenuApp = __importStar(require("./modules/profile-resources-menu"));
|
|
79
|
+
const profileSettingsMenuApp = __importStar(require("./modules/profile-settings-menu"));
|
|
78
80
|
const projectMenuApp = __importStar(require("./modules/project-menu"));
|
|
79
81
|
const projectMenuCrowdsourceApp = __importStar(require("./modules/project-menu-crowdsource"));
|
|
80
82
|
const projectReportsApp = __importStar(require("./modules/project-reports"));
|
|
81
83
|
const projectToolsApp = __importStar(require("./modules/project-tools"));
|
|
84
|
+
const webhooks = __importStar(require("./modules/webhooks"));
|
|
85
|
+
const workflowStepType = __importStar(require("./modules/workflow-step-type"));
|
|
82
86
|
const subscription_1 = require("./util/subscription");
|
|
83
87
|
var types_2 = require("./types");
|
|
84
88
|
Object.defineProperty(exports, "ProjectPermissions", { enumerable: true, get: function () { return types_2.ProjectPermissions; } });
|
|
@@ -122,7 +126,14 @@ function addCrowdinEndpoints(app, clientConfig) {
|
|
|
122
126
|
}
|
|
123
127
|
storage.initialize(config);
|
|
124
128
|
logger.initialize(config);
|
|
125
|
-
app.use(
|
|
129
|
+
app.use((req, res, next) => {
|
|
130
|
+
if (config.webhooks && req.path === '/webhooks') {
|
|
131
|
+
return terminus_express_1.default.raw({ type: '*/*', limit: '50mb' })(req, res, next);
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
return terminus_express_1.default.json({ limit: '50mb' })(req, res, next);
|
|
135
|
+
}
|
|
136
|
+
});
|
|
126
137
|
if (!config.disableLogsFormatter) {
|
|
127
138
|
logsFormatter.setup();
|
|
128
139
|
app.use(logsFormatter.contextResolverMiddleware());
|
|
@@ -141,7 +152,9 @@ function addCrowdinEndpoints(app, clientConfig) {
|
|
|
141
152
|
editorRightPanelApp.register({ config, app });
|
|
142
153
|
projectMenuApp.register({ config, app });
|
|
143
154
|
profileResourcesMenuApp.register({ config, app });
|
|
155
|
+
profileSettingsMenuApp.register({ config, app });
|
|
144
156
|
organizationMenuApp.register({ config, app });
|
|
157
|
+
organizationSettingsMenuApp.register({ config, app });
|
|
145
158
|
projectMenuCrowdsourceApp.register({ config, app });
|
|
146
159
|
projectToolsApp.register({ config, app });
|
|
147
160
|
projectReportsApp.register({ config, app });
|
|
@@ -175,6 +188,8 @@ function addCrowdinEndpoints(app, clientConfig) {
|
|
|
175
188
|
aiTools.registerAiTools({ config, app });
|
|
176
189
|
aiTools.registerAiToolWidgets({ config, app });
|
|
177
190
|
externalQaCheck.register({ config, app });
|
|
191
|
+
webhooks.register({ config, app });
|
|
192
|
+
workflowStepType.register({ config, app });
|
|
178
193
|
addFormSchema({ config, app });
|
|
179
194
|
return Object.assign(Object.assign({}, exports.metadataStore), { establishCrowdinConnection: (authRequest, moduleKey) => {
|
|
180
195
|
let jwtToken = '';
|
|
@@ -191,13 +206,13 @@ function addCrowdinEndpoints(app, clientConfig) {
|
|
|
191
206
|
checkSubscriptionExpiration: false,
|
|
192
207
|
moduleKey,
|
|
193
208
|
});
|
|
194
|
-
}, encryptCrowdinConnection: (data) => (0, util_1.encryptData)(config, JSON.stringify(data)), dencryptCrowdinConnection: (hash) => __awaiter(this, void 0, void 0, function* () {
|
|
209
|
+
}, encryptCrowdinConnection: (data) => (0, util_1.encryptData)(config, JSON.stringify(data)), dencryptCrowdinConnection: (hash, autoRenew) => __awaiter(this, void 0, void 0, function* () {
|
|
195
210
|
const { crowdinId, extra } = JSON.parse((0, util_1.decryptData)(config, hash));
|
|
196
211
|
const credentials = yield storage.getStorage().getCrowdinCredentials(crowdinId);
|
|
197
212
|
if (!credentials) {
|
|
198
213
|
throw new Error('Failed to find Crowdin credentials');
|
|
199
214
|
}
|
|
200
|
-
const { client } = yield (0, connection_1.prepareCrowdinClient)({ config, credentials });
|
|
215
|
+
const { client } = yield (0, connection_1.prepareCrowdinClient)({ config, credentials, autoRenew });
|
|
201
216
|
return { client, extra };
|
|
202
217
|
}) });
|
|
203
218
|
}
|
|
@@ -240,6 +255,9 @@ function convertClientConfig(clientConfig) {
|
|
|
240
255
|
throw new Error('Missing [clientId, clientSecret] parameters');
|
|
241
256
|
}
|
|
242
257
|
}
|
|
258
|
+
if (clientConfig.projectIntegration) {
|
|
259
|
+
clientConfig.api = Object.assign({ default: true }, clientConfig.api);
|
|
260
|
+
}
|
|
243
261
|
return Object.assign(Object.assign({}, clientConfig), { baseUrl: baseUrl.endsWith('/') ? baseUrl.slice(0, -1) : baseUrl, clientId,
|
|
244
262
|
clientSecret, awsConfig: {
|
|
245
263
|
tmpBucketName,
|
|
@@ -13,12 +13,7 @@ const util_1 = require("../../../util");
|
|
|
13
13
|
const logger_1 = require("../../../util/logger");
|
|
14
14
|
const files_1 = require("../../integration/util/files");
|
|
15
15
|
const util_2 = require("../util");
|
|
16
|
-
|
|
17
|
-
// Crowdin documentation https://support.crowdin.com/developer/crowdin-apps-module-custom-ai/#expected-response-from-the-app
|
|
18
|
-
const ROLES = {
|
|
19
|
-
assistant: 'assistant',
|
|
20
|
-
};
|
|
21
|
-
const DEFAULT_ROLE = ROLES.assistant;
|
|
16
|
+
const DEFAULT_ROLE = 'assistant';
|
|
22
17
|
const getErrorStatus = (e) => {
|
|
23
18
|
if (typeof e === 'object' && 'status' in e && typeof e.status === 'number') {
|
|
24
19
|
return e.status;
|
|
@@ -39,7 +34,7 @@ function handle(aiProvider) {
|
|
|
39
34
|
let message;
|
|
40
35
|
let data;
|
|
41
36
|
const chunks = [];
|
|
42
|
-
const { crowdinApiClient: client, crowdinContext: context, body: { messages, model, action, stream, responseFormat: { type: responseFormatType } = { type: undefined }, }, } = req;
|
|
37
|
+
const { crowdinApiClient: client, crowdinContext: context, body: { messages, model, action, stream, tools, tool_choice: toolChoice, responseFormat: { type: responseFormatType } = { type: undefined }, }, } = req;
|
|
43
38
|
isStream = !!stream;
|
|
44
39
|
const startStream = () => {
|
|
45
40
|
if (!res.headersSent) {
|
|
@@ -47,11 +42,12 @@ function handle(aiProvider) {
|
|
|
47
42
|
Connection: 'keep-alive',
|
|
48
43
|
'Cache-Control': 'no-cache',
|
|
49
44
|
'Content-Type': 'text/event-stream',
|
|
45
|
+
'X-Accel-Buffering': 'no',
|
|
50
46
|
});
|
|
51
47
|
}
|
|
52
48
|
};
|
|
53
49
|
const result = yield aiProvider.chatCompletions({
|
|
54
|
-
messages,
|
|
50
|
+
messages: messages.map(util_2.inputMessageToChatCompletionMessage),
|
|
55
51
|
model,
|
|
56
52
|
action,
|
|
57
53
|
responseFormat: responseFormatType,
|
|
@@ -59,19 +55,26 @@ function handle(aiProvider) {
|
|
|
59
55
|
context,
|
|
60
56
|
req,
|
|
61
57
|
isStream,
|
|
62
|
-
|
|
58
|
+
tools,
|
|
59
|
+
toolChoice,
|
|
60
|
+
/* eslint-disable @typescript-eslint/camelcase */
|
|
61
|
+
sendEvent: ({ content, role, tool_calls }) => __awaiter(this, void 0, void 0, function* () {
|
|
63
62
|
if (!isStream) {
|
|
64
|
-
chunks.push({ content, role });
|
|
63
|
+
chunks.push({ content, role, tool_calls });
|
|
65
64
|
return;
|
|
66
65
|
}
|
|
67
66
|
startStream();
|
|
67
|
+
const delta = {
|
|
68
|
+
role: role || DEFAULT_ROLE,
|
|
69
|
+
content: content || null,
|
|
70
|
+
};
|
|
71
|
+
if (!!tool_calls) {
|
|
72
|
+
delta.tool_calls = tool_calls;
|
|
73
|
+
}
|
|
68
74
|
const message = {
|
|
69
75
|
choices: [
|
|
70
76
|
{
|
|
71
|
-
delta
|
|
72
|
-
role: role || DEFAULT_ROLE,
|
|
73
|
-
content,
|
|
74
|
-
},
|
|
77
|
+
delta,
|
|
75
78
|
},
|
|
76
79
|
],
|
|
77
80
|
};
|
|
@@ -92,18 +95,14 @@ function handle(aiProvider) {
|
|
|
92
95
|
data = result;
|
|
93
96
|
}
|
|
94
97
|
if (chunks.length) {
|
|
95
|
-
data =
|
|
96
|
-
{
|
|
97
|
-
role: chunks[0].role || DEFAULT_ROLE,
|
|
98
|
-
content: chunks.map((chunk) => chunk.content).join(''),
|
|
99
|
-
},
|
|
100
|
-
];
|
|
98
|
+
data = (0, util_2.mergeChatCompletionChunks)(chunks);
|
|
101
99
|
}
|
|
102
100
|
if (data && data.length > 0) {
|
|
103
101
|
choices = data.map((message) => ({
|
|
104
102
|
message: {
|
|
105
103
|
role: message.role || DEFAULT_ROLE,
|
|
106
|
-
content: message.content,
|
|
104
|
+
content: message.content || null,
|
|
105
|
+
tool_calls: message.tool_calls,
|
|
107
106
|
},
|
|
108
107
|
}));
|
|
109
108
|
}
|
|
@@ -22,13 +22,14 @@ function handle(aiProvider) {
|
|
|
22
22
|
context: req.crowdinContext,
|
|
23
23
|
});
|
|
24
24
|
const data = modelList.map((model) => {
|
|
25
|
-
var _a, _b, _c, _d;
|
|
25
|
+
var _a, _b, _c, _d, _e;
|
|
26
26
|
return ({
|
|
27
27
|
id: model.id,
|
|
28
28
|
supportsJsonMode: (_a = model.supportsJsonMode) !== null && _a !== void 0 ? _a : false,
|
|
29
29
|
supportsFunctionCalling: (_b = model.supportsFunctionCalling) !== null && _b !== void 0 ? _b : false,
|
|
30
30
|
supportsStreaming: (_c = model.supportsStreaming) !== null && _c !== void 0 ? _c : false,
|
|
31
|
-
|
|
31
|
+
supportsVision: (_d = model.supportsVision) !== null && _d !== void 0 ? _d : false,
|
|
32
|
+
contextWindowLimit: (_e = model.contextWindowLimit) !== null && _e !== void 0 ? _e : exports.CONTEXT_WINDOW_LIMIT,
|
|
32
33
|
});
|
|
33
34
|
});
|
|
34
35
|
res.send({ data });
|
|
@@ -17,8 +17,8 @@ export interface AiProviderModule extends Environments, ModuleKey {
|
|
|
17
17
|
/**
|
|
18
18
|
* processes a sequence of conversation messages and generates responses from the assistant
|
|
19
19
|
*/
|
|
20
|
-
chatCompletions: ({ messages, model, action, responseFormat, client, context, req, }: {
|
|
21
|
-
messages:
|
|
20
|
+
chatCompletions: ({ messages, model, action, responseFormat, client, context, req, isStream, sendEvent, tools, toolChoice, }: {
|
|
21
|
+
messages: ChatCompletionMessage[];
|
|
22
22
|
model: string;
|
|
23
23
|
action: string;
|
|
24
24
|
responseFormat: string;
|
|
@@ -26,8 +26,10 @@ export interface AiProviderModule extends Environments, ModuleKey {
|
|
|
26
26
|
context: CrowdinContextInfo;
|
|
27
27
|
req: CrowdinClientRequest;
|
|
28
28
|
isStream: boolean;
|
|
29
|
-
sendEvent: (chunk:
|
|
30
|
-
|
|
29
|
+
sendEvent: (chunk: ChatCompletionChunkMessage) => Promise<void>;
|
|
30
|
+
tools?: ChatCompletionTool[];
|
|
31
|
+
toolChoice?: string | AiToolChoice;
|
|
32
|
+
}) => Promise<ChatCompletionResponseMessage[] | ExtendedResult<ChatCompletionResponseMessage[]> | void>;
|
|
31
33
|
/**
|
|
32
34
|
* provides a list of available model
|
|
33
35
|
*/
|
|
@@ -41,9 +43,112 @@ export interface SupportedModels {
|
|
|
41
43
|
supportsJsonMode?: boolean;
|
|
42
44
|
supportsFunctionCalling?: boolean;
|
|
43
45
|
supportsStreaming?: boolean;
|
|
46
|
+
supportsVision?: boolean;
|
|
44
47
|
contextWindowLimit?: number;
|
|
45
48
|
}
|
|
46
|
-
export interface
|
|
47
|
-
|
|
48
|
-
|
|
49
|
+
export interface ChatCompletionTool {
|
|
50
|
+
type: 'function';
|
|
51
|
+
function: ChatCompletionToolFunctionDeclaration;
|
|
49
52
|
}
|
|
53
|
+
export interface ChatCompletionToolFunctionDeclaration {
|
|
54
|
+
/**
|
|
55
|
+
* The name of the function to be called. Must be a-z, A-Z, 0-9, or contain underscores and dashes, with a maximum length of 64.
|
|
56
|
+
*/
|
|
57
|
+
name: string;
|
|
58
|
+
/**
|
|
59
|
+
* A description of what the function does, used by the model to choose when and how to call the function.
|
|
60
|
+
*/
|
|
61
|
+
description?: string;
|
|
62
|
+
/**
|
|
63
|
+
* The parameters the functions accepts, described as a JSON Schema object.
|
|
64
|
+
* https://json-schema.org/understanding-json-schema/
|
|
65
|
+
*/
|
|
66
|
+
parameters?: object;
|
|
67
|
+
}
|
|
68
|
+
export interface AiToolChoice {
|
|
69
|
+
type: 'function';
|
|
70
|
+
function: {
|
|
71
|
+
/**
|
|
72
|
+
* The name of the function to call.
|
|
73
|
+
*/
|
|
74
|
+
name: string;
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
export type ChatCompletionMessage = ChatCompletionSystemMessage | ChatCompletionUserMessage | ChatCompletionAssistantMessage | ChatCompletionToolMessage;
|
|
78
|
+
export interface ChatCompletionSystemMessage {
|
|
79
|
+
role: 'system';
|
|
80
|
+
content: string | ChatCompletionContentPartText[];
|
|
81
|
+
}
|
|
82
|
+
export interface ChatCompletionUserMessage {
|
|
83
|
+
role?: 'user';
|
|
84
|
+
content: string | ChatCompletionContentPart[];
|
|
85
|
+
}
|
|
86
|
+
export type ChatCompletionResponseMessage = ChatCompletionAssistantMessage;
|
|
87
|
+
export interface ChatCompletionAssistantMessage {
|
|
88
|
+
role?: 'assistant';
|
|
89
|
+
content?: string | ChatCompletionContentPartText[] | null;
|
|
90
|
+
tool_calls?: ChatCompletionMessageToolCall[] | null;
|
|
91
|
+
}
|
|
92
|
+
export interface ChatCompletionChunkMessage {
|
|
93
|
+
role?: ROLES;
|
|
94
|
+
content?: string | null;
|
|
95
|
+
tool_calls?: ChatCompletionDeltaMessageToolCall[];
|
|
96
|
+
}
|
|
97
|
+
export interface ChatCompletionToolMessage {
|
|
98
|
+
content: string | ChatCompletionContentPartText[];
|
|
99
|
+
role: 'tool';
|
|
100
|
+
/**
|
|
101
|
+
* Tool call that this message is responding to.
|
|
102
|
+
*/
|
|
103
|
+
tool_call_id: string;
|
|
104
|
+
}
|
|
105
|
+
export type ROLES = 'user' | 'assistant' | 'system' | 'tool';
|
|
106
|
+
export type ChatCompletionContentPart = ChatCompletionContentPartText | ChatCompletionContentPartImage;
|
|
107
|
+
export type ChatCompletionContentPartText = {
|
|
108
|
+
type: 'text';
|
|
109
|
+
text: string;
|
|
110
|
+
};
|
|
111
|
+
export type ChatCompletionContentPartImage = {
|
|
112
|
+
type: 'image_url';
|
|
113
|
+
image_url: {
|
|
114
|
+
/**
|
|
115
|
+
* Either a URL of the image or the base64 encoded image data.
|
|
116
|
+
*/
|
|
117
|
+
url: string;
|
|
118
|
+
};
|
|
119
|
+
};
|
|
120
|
+
export interface ChatCompletionMessageToolCall {
|
|
121
|
+
id: string;
|
|
122
|
+
type: 'function';
|
|
123
|
+
function: {
|
|
124
|
+
/**
|
|
125
|
+
* The arguments to call the function with, as generated by the model in JSON format.
|
|
126
|
+
* Note that the model does not always generate valid JSON.
|
|
127
|
+
*/
|
|
128
|
+
arguments?: string;
|
|
129
|
+
name: string;
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
export interface ChatCompletionDeltaMessageToolCall {
|
|
133
|
+
index: number;
|
|
134
|
+
id?: string;
|
|
135
|
+
type?: 'function';
|
|
136
|
+
function?: {
|
|
137
|
+
/**
|
|
138
|
+
* The arguments to call the function with, as generated by the model in JSON format.
|
|
139
|
+
* Note that the model does not always generate valid JSON.
|
|
140
|
+
*/
|
|
141
|
+
arguments?: string;
|
|
142
|
+
name?: string;
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
export interface InputMessage {
|
|
146
|
+
role?: ROLES;
|
|
147
|
+
content: string | InputContentPart[];
|
|
148
|
+
}
|
|
149
|
+
export type InputContentPart = ChatCompletionContentPartText | InputChatCompletionContentPartImage;
|
|
150
|
+
export type InputChatCompletionContentPartImage = {
|
|
151
|
+
type: 'image';
|
|
152
|
+
mimeType: string;
|
|
153
|
+
url: string;
|
|
154
|
+
};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { AppModuleAggregateError } from '../../../util/logger';
|
|
2
|
+
import { ChatCompletionChunkMessage, ChatCompletionContentPart, ChatCompletionMessage, ChatCompletionMessageToolCall, ChatCompletionResponseMessage, InputContentPart, InputMessage } from '../types';
|
|
2
3
|
interface RateLimitErrorOptions {
|
|
3
4
|
error?: Error;
|
|
4
5
|
message?: string;
|
|
@@ -8,4 +9,8 @@ export declare class RateLimitError extends AppModuleAggregateError {
|
|
|
8
9
|
readonly status = 429;
|
|
9
10
|
constructor({ error, message }?: RateLimitErrorOptions);
|
|
10
11
|
}
|
|
12
|
+
export declare function normalizeContentParts(content: string | InputContentPart[]): string | ChatCompletionContentPart[];
|
|
13
|
+
export declare function inputMessageToChatCompletionMessage(message: InputMessage): ChatCompletionMessage;
|
|
14
|
+
export declare function mergeToolCalls(chunks: ChatCompletionChunkMessage[]): ChatCompletionMessageToolCall[] | null;
|
|
15
|
+
export declare function mergeChatCompletionChunks(chunks: ChatCompletionChunkMessage[]): ChatCompletionResponseMessage[];
|
|
11
16
|
export {};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.RateLimitError = exports.isRateLimitError = void 0;
|
|
3
|
+
exports.mergeChatCompletionChunks = exports.mergeToolCalls = exports.inputMessageToChatCompletionMessage = exports.normalizeContentParts = exports.RateLimitError = exports.isRateLimitError = void 0;
|
|
4
4
|
const logger_1 = require("../../../util/logger");
|
|
5
5
|
const HTTP_RATE_LIMIT = 429;
|
|
6
6
|
function isRateLimitError(e) {
|
|
@@ -19,3 +19,74 @@ class RateLimitError extends logger_1.AppModuleAggregateError {
|
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
21
|
exports.RateLimitError = RateLimitError;
|
|
22
|
+
function normalizeContentParts(content) {
|
|
23
|
+
return Array.isArray(content)
|
|
24
|
+
? content.map((part) => part.type === 'image'
|
|
25
|
+
? {
|
|
26
|
+
type: 'image_url',
|
|
27
|
+
// eslint-disable-next-line @typescript-eslint/camelcase
|
|
28
|
+
image_url: {
|
|
29
|
+
url: part.url,
|
|
30
|
+
},
|
|
31
|
+
}
|
|
32
|
+
: part)
|
|
33
|
+
: content;
|
|
34
|
+
}
|
|
35
|
+
exports.normalizeContentParts = normalizeContentParts;
|
|
36
|
+
function inputMessageToChatCompletionMessage(message) {
|
|
37
|
+
switch (message.role) {
|
|
38
|
+
case undefined:
|
|
39
|
+
case 'user':
|
|
40
|
+
return {
|
|
41
|
+
role: 'user',
|
|
42
|
+
content: normalizeContentParts(message.content),
|
|
43
|
+
};
|
|
44
|
+
default:
|
|
45
|
+
return message;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
exports.inputMessageToChatCompletionMessage = inputMessageToChatCompletionMessage;
|
|
49
|
+
function mergeToolCalls(chunks) {
|
|
50
|
+
const toolCalls = [];
|
|
51
|
+
chunks.forEach((chunk) => {
|
|
52
|
+
if (!chunk.tool_calls) {
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
chunk.tool_calls.forEach((toolCallChunk) => {
|
|
56
|
+
const delta = toolCalls.find((toolCall) => toolCall.index === toolCallChunk.index);
|
|
57
|
+
if (!delta) {
|
|
58
|
+
toolCalls.push(toolCallChunk);
|
|
59
|
+
}
|
|
60
|
+
else if (!!toolCallChunk.function && 'arguments' in toolCallChunk.function) {
|
|
61
|
+
if (!delta.function) {
|
|
62
|
+
delta.function = toolCallChunk.function;
|
|
63
|
+
}
|
|
64
|
+
else if (!delta.function.arguments) {
|
|
65
|
+
delta.function.arguments = toolCallChunk.function.arguments;
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
delta.function.arguments += toolCallChunk.function.arguments;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
toolCalls.map((tool) => {
|
|
74
|
+
if ('index' in tool) {
|
|
75
|
+
delete tool.index;
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
return !toolCalls.length ? null : toolCalls;
|
|
79
|
+
}
|
|
80
|
+
exports.mergeToolCalls = mergeToolCalls;
|
|
81
|
+
function mergeChatCompletionChunks(chunks) {
|
|
82
|
+
/* eslint-disable @typescript-eslint/camelcase */
|
|
83
|
+
const tool_calls = mergeToolCalls(chunks);
|
|
84
|
+
return [
|
|
85
|
+
{
|
|
86
|
+
role: chunks[0].role || 'assistant',
|
|
87
|
+
content: tool_calls ? null : chunks.map((chunk) => chunk.content).join(''),
|
|
88
|
+
tool_calls,
|
|
89
|
+
},
|
|
90
|
+
];
|
|
91
|
+
}
|
|
92
|
+
exports.mergeChatCompletionChunks = mergeChatCompletionChunks;
|
package/out/modules/api/api.js
CHANGED
|
@@ -462,7 +462,7 @@ function addDefaultApiEndpoints(app, config) {
|
|
|
462
462
|
}
|
|
463
463
|
exports.addDefaultApiEndpoints = addDefaultApiEndpoints;
|
|
464
464
|
function addSwagerApiDocumentation(app, config) {
|
|
465
|
-
var _a, _b;
|
|
465
|
+
var _a, _b, _c;
|
|
466
466
|
const options = {
|
|
467
467
|
swaggerDefinition: {
|
|
468
468
|
openapi: '3.0.0',
|
|
@@ -492,16 +492,16 @@ function addSwagerApiDocumentation(app, config) {
|
|
|
492
492
|
},
|
|
493
493
|
],
|
|
494
494
|
},
|
|
495
|
-
apis: config.projectIntegration
|
|
495
|
+
apis: config.projectIntegration && ((_a = config.api) === null || _a === void 0 ? void 0 : _a.default)
|
|
496
496
|
? [path_1.default.resolve(__dirname, './base.js'), path_1.default.resolve(__dirname, './components.js'), __filename]
|
|
497
497
|
: [],
|
|
498
498
|
};
|
|
499
|
-
if ((
|
|
499
|
+
if ((_b = config.api) === null || _b === void 0 ? void 0 : _b.docFile) {
|
|
500
500
|
options.apis.push(config.api.docFile);
|
|
501
501
|
}
|
|
502
502
|
const swaggerSpec = (0, swagger_jsdoc_1.default)(options);
|
|
503
503
|
// remove Login info from doc
|
|
504
|
-
if (config.projectIntegration && !((
|
|
504
|
+
if (config.projectIntegration && !((_c = config.projectIntegration) === null || _c === void 0 ? void 0 : _c.loginForm)) {
|
|
505
505
|
delete swaggerSpec.paths['/login'];
|
|
506
506
|
delete swaggerSpec.paths['/login-fields'];
|
|
507
507
|
delete swaggerSpec.components.schemas['Login'];
|
|
@@ -23,9 +23,15 @@ function handle(baseConfig, config, folderName) {
|
|
|
23
23
|
fs_1.default.mkdirSync(path_1.default.join(folderPath, folderName), { recursive: true });
|
|
24
24
|
}
|
|
25
25
|
return (0, util_1.runAsyncWrapper)((req, res) => __awaiter(this, void 0, void 0, function* () {
|
|
26
|
+
var _a;
|
|
26
27
|
const response = {};
|
|
27
28
|
const baseFilesUrl = `${baseConfig.baseUrl}/file/download/${folderName}`;
|
|
28
29
|
const body = req.body;
|
|
30
|
+
// Skip assets (e.g., images, videos, or other media files) as they typically don't need to be processed
|
|
31
|
+
if (((_a = body === null || body === void 0 ? void 0 : body.file) === null || _a === void 0 ? void 0 : _a.type) === 'assets' && !('processAssets' in config && config.processAssets)) {
|
|
32
|
+
res.sendStatus(304);
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
29
35
|
let processingError;
|
|
30
36
|
let fileContent;
|
|
31
37
|
let rawContent;
|
|
@@ -60,17 +60,24 @@ export interface CustomFileFormatLogic extends FileProcessLogic {
|
|
|
60
60
|
}
|
|
61
61
|
export type FileImportExportLogic = FilePreImportLogic | FilePostImportLogic | FilePreExportLogic | FilePostExportLogic;
|
|
62
62
|
export type FileImportExportContent = ProcessFileString[] | Buffer | undefined;
|
|
63
|
-
export interface
|
|
64
|
-
fileProcess: (req: ProcessFileRequest, content: FileImportExportContent, client: Crowdin, context: CrowdinContextInfo, projectId: number) => Promise<
|
|
63
|
+
export interface BaseFileProcessLogic<T> {
|
|
64
|
+
fileProcess: (req: ProcessFileRequest, content: FileImportExportContent, client: Crowdin, context: CrowdinContextInfo, projectId: number) => Promise<T>;
|
|
65
65
|
}
|
|
66
|
-
export interface
|
|
67
|
-
|
|
66
|
+
export interface FilePreImportLogic extends FileProcessLogic, BaseFileProcessLogic<ContentFileResponse> {
|
|
67
|
+
/**
|
|
68
|
+
* Set to `true` to enable asset processing in the application.
|
|
69
|
+
*/
|
|
70
|
+
processAssets?: boolean;
|
|
71
|
+
}
|
|
72
|
+
export interface FilePostImportLogic extends FileProcessLogic, BaseFileProcessLogic<StringsFileResponse> {
|
|
68
73
|
}
|
|
69
|
-
export interface FilePreExportLogic extends FileProcessLogic {
|
|
70
|
-
fileProcess: (req: ProcessFileRequest, content: FileImportExportContent, client: Crowdin, context: CrowdinContextInfo, projectId: number) => Promise<StringsFileResponse>;
|
|
74
|
+
export interface FilePreExportLogic extends FileProcessLogic, BaseFileProcessLogic<StringsFileResponse> {
|
|
71
75
|
}
|
|
72
|
-
export interface FilePostExportLogic extends FileProcessLogic {
|
|
73
|
-
|
|
76
|
+
export interface FilePostExportLogic extends FileProcessLogic, BaseFileProcessLogic<ContentFileResponse> {
|
|
77
|
+
/**
|
|
78
|
+
* Set to `true` to enable asset processing in the application.
|
|
79
|
+
*/
|
|
80
|
+
processAssets?: boolean;
|
|
74
81
|
}
|
|
75
82
|
export interface ProcessFileRequest {
|
|
76
83
|
jobType: ProcessFileJobType;
|
|
@@ -87,6 +94,7 @@ export interface ProcessFileRecord {
|
|
|
87
94
|
path?: string;
|
|
88
95
|
id?: number;
|
|
89
96
|
name?: string;
|
|
97
|
+
type?: string;
|
|
90
98
|
}
|
|
91
99
|
export declare enum ProcessFileJobType {
|
|
92
100
|
PARSE_FILE = "parse-file",
|
|
@@ -175,6 +175,8 @@ function processSyncSettings({ config, integration, period, syncSettings, }) {
|
|
|
175
175
|
user_id: crowdinCredentials.userId,
|
|
176
176
|
},
|
|
177
177
|
},
|
|
178
|
+
crowdinId: crowdinCredentials.id,
|
|
179
|
+
clientId: integrationCredentials.id,
|
|
178
180
|
};
|
|
179
181
|
try {
|
|
180
182
|
const preparedCrowdinClient = yield (0, connection_1.prepareCrowdinClient)({
|
|
@@ -187,7 +189,7 @@ function processSyncSettings({ config, integration, period, syncSettings, }) {
|
|
|
187
189
|
crowdinClient = preparedCrowdinClient.client;
|
|
188
190
|
}
|
|
189
191
|
catch (e) {
|
|
190
|
-
(0, logger_1.logError)(e);
|
|
192
|
+
(0, logger_1.logError)(e, context);
|
|
191
193
|
return;
|
|
192
194
|
}
|
|
193
195
|
const { expired } = yield (0, subscription_1.checkSubscription)({
|
|
@@ -205,7 +207,7 @@ function processSyncSettings({ config, integration, period, syncSettings, }) {
|
|
|
205
207
|
.data;
|
|
206
208
|
}
|
|
207
209
|
catch (e) {
|
|
208
|
-
(0, logger_1.logError)(e);
|
|
210
|
+
(0, logger_1.logError)(e, context);
|
|
209
211
|
return;
|
|
210
212
|
}
|
|
211
213
|
// eslint-disable-next-line @typescript-eslint/camelcase
|
|
@@ -229,7 +231,7 @@ function processSyncSettings({ config, integration, period, syncSettings, }) {
|
|
|
229
231
|
});
|
|
230
232
|
}
|
|
231
233
|
catch (e) {
|
|
232
|
-
(0, logger_1.logError)(e);
|
|
234
|
+
(0, logger_1.logError)(e, context);
|
|
233
235
|
return;
|
|
234
236
|
}
|
|
235
237
|
}
|
|
@@ -268,6 +270,7 @@ function processSyncSettings({ config, integration, period, syncSettings, }) {
|
|
|
268
270
|
crowdinClient,
|
|
269
271
|
onlyApproved,
|
|
270
272
|
onlyTranslated,
|
|
273
|
+
context,
|
|
271
274
|
});
|
|
272
275
|
if (Object.keys(filesToProcess).length <= 0) {
|
|
273
276
|
return;
|
|
@@ -410,7 +413,7 @@ function getNewFoldersFile(folders, snapshotFiles) {
|
|
|
410
413
|
files = files.filter((file) => 'type' in file);
|
|
411
414
|
return files;
|
|
412
415
|
}
|
|
413
|
-
function getOnlyTranslatedOrApprovedFiles({ projectId, crowdinFiles, crowdinClient, onlyApproved, onlyTranslated, }) {
|
|
416
|
+
function getOnlyTranslatedOrApprovedFiles({ projectId, crowdinFiles, crowdinClient, onlyApproved, onlyTranslated, context, }) {
|
|
414
417
|
return __awaiter(this, void 0, void 0, function* () {
|
|
415
418
|
(0, logger_1.log)(`Filtering files to process only ${onlyApproved ? 'approved' : 'translated'} files`);
|
|
416
419
|
const filesInfo = yield Promise.all(Object.keys(crowdinFiles).map((fileId) => __awaiter(this, void 0, void 0, function* () {
|
|
@@ -425,7 +428,7 @@ function getOnlyTranslatedOrApprovedFiles({ projectId, crowdinFiles, crowdinClie
|
|
|
425
428
|
}
|
|
426
429
|
catch (e) {
|
|
427
430
|
delete crowdinFiles[fileId];
|
|
428
|
-
(0, logger_1.logError)(e);
|
|
431
|
+
(0, logger_1.logError)(e, context);
|
|
429
432
|
}
|
|
430
433
|
})));
|
|
431
434
|
const filteredFiles = {};
|
|
@@ -36,6 +36,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
36
36
|
};
|
|
37
37
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
38
38
|
exports.listenQueueMessage = exports.updateCrowdinFromWebhookRequest = exports.prepareWebhookData = exports.unregisterAllCrowdinWebhooks = exports.unregisterWebhooks = exports.registerWebhooks = exports.HookEvents = void 0;
|
|
39
|
+
const logsFormatter = __importStar(require("@crowdin/logs-formatter"));
|
|
39
40
|
const crowdinAppFunctions = __importStar(require("@crowdin/crowdin-apps-functions"));
|
|
40
41
|
const amqplib_1 = __importDefault(require("amqplib"));
|
|
41
42
|
const types_1 = require("../types");
|
|
@@ -265,8 +266,7 @@ function prepareWebhookData({ config, integration, provider, webhookUrlParam, })
|
|
|
265
266
|
if (!crowdinCredentials) {
|
|
266
267
|
return { projectId, crowdinClient, rootFolder, appSettings, syncSettings, preparedIntegrationCredentials };
|
|
267
268
|
}
|
|
268
|
-
const context = {
|
|
269
|
-
jwtPayload: {
|
|
269
|
+
const context = Object.assign({ jwtPayload: {
|
|
270
270
|
context: {
|
|
271
271
|
// eslint-disable-next-line @typescript-eslint/camelcase
|
|
272
272
|
project_id: projectId,
|
|
@@ -275,8 +275,9 @@ function prepareWebhookData({ config, integration, provider, webhookUrlParam, })
|
|
|
275
275
|
// eslint-disable-next-line @typescript-eslint/camelcase
|
|
276
276
|
user_id: crowdinCredentials === null || crowdinCredentials === void 0 ? void 0 : crowdinCredentials.userId,
|
|
277
277
|
},
|
|
278
|
-
},
|
|
279
|
-
|
|
278
|
+
}, crowdinId: crowdinCredentials.id }, ((integrationCredentials === null || integrationCredentials === void 0 ? void 0 : integrationCredentials.id) && { clientId: integrationCredentials.id }));
|
|
279
|
+
logsFormatter.resetContext();
|
|
280
|
+
logsFormatter.setContext(context);
|
|
280
281
|
crowdinClient = yield (0, connection_1.prepareCrowdinClient)({
|
|
281
282
|
config,
|
|
282
283
|
credentials: crowdinCredentials,
|