@crowdin/app-project-module 0.66.1 → 0.68.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/README.md +3 -17
- package/out/index.js +25 -10
- package/out/middlewares/crowdin-client.d.ts +13 -2
- package/out/middlewares/crowdin-client.js +17 -3
- package/out/middlewares/ui-module.d.ts +5 -1
- package/out/middlewares/ui-module.js +5 -1
- package/out/modules/ai-prompt-provider/index.js +7 -2
- package/out/modules/ai-provider/handlers/chat-completions.js +75 -5
- package/out/modules/ai-provider/handlers/get-model-list.js +3 -2
- package/out/modules/ai-provider/index.js +13 -3
- package/out/modules/ai-provider/types.d.ts +5 -2
- package/out/modules/ai-tools/index.js +7 -2
- package/out/modules/ai-tools/types.d.ts +2 -2
- package/out/modules/api/api.js +66 -11
- package/out/modules/context-menu/index.js +1 -1
- package/out/modules/custom-mt/index.js +6 -1
- package/out/modules/custom-mt/types.d.ts +4 -2
- package/out/modules/custom-spell-check/index.js +14 -4
- package/out/modules/custom-spell-check/types.d.ts +2 -2
- package/out/modules/editor-right-panel/index.js +1 -1
- package/out/modules/external-qa-check/index.js +7 -2
- package/out/modules/external-qa-check/types.d.ts +2 -2
- package/out/modules/file-processing/index.js +30 -5
- package/out/modules/file-processing/types.d.ts +3 -2
- package/out/modules/file-processing/util/files.d.ts +1 -0
- package/out/modules/install.js +10 -2
- package/out/modules/integration/index.js +109 -18
- package/out/modules/integration/types.d.ts +2 -2
- package/out/modules/manifest.js +48 -22
- package/out/modules/modal/index.js +1 -1
- package/out/modules/organization-menu/index.js +1 -1
- package/out/modules/profile-resources-menu/index.js +1 -1
- package/out/modules/project-menu/index.js +1 -1
- package/out/modules/project-menu-crowdsource/index.js +1 -1
- package/out/modules/project-reports/index.js +1 -1
- package/out/modules/project-tools/index.js +1 -1
- package/out/static/css/crowdin-ui-colors.css +115 -0
- package/out/static/js/form.js +10 -10
- package/out/types.d.ts +16 -2
- package/out/util/handlebars.js +2 -2
- package/out/util/index.d.ts +0 -1
- package/out/util/index.js +1 -9
- package/out/views/main.handlebars +3 -19
- package/out/views/partials/head.handlebars +1 -0
- package/package.json +12 -12
package/README.md
CHANGED
|
@@ -2,26 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
Module that will automatically add all necessary endpoints for Crowdin App.
|
|
4
4
|
|
|
5
|
-
:bookmark: See the [docs](/
|
|
5
|
+
:bookmark: See the [docs](https://crowdin.github.io/app-project-module/) for more information.
|
|
6
6
|
|
|
7
7
|
## Contributing
|
|
8
8
|
|
|
9
|
-
If you
|
|
9
|
+
If you would like to contribute please read the [Contributing](/CONTRIBUTING.md) guidelines.
|
|
10
10
|
|
|
11
11
|
## Seeking Assistance
|
|
12
12
|
|
|
13
|
-
If you find any problems or would like to suggest a feature, please feel free to file an issue on
|
|
14
|
-
|
|
15
|
-
If you've found an error in these samples, please [Contact Customer Success Service](https://crowdin.com/contacts).
|
|
16
|
-
|
|
17
|
-
## License
|
|
18
|
-
|
|
19
|
-
<pre>
|
|
20
|
-
The Crowdin App Project module is licensed under the MIT License.
|
|
21
|
-
See the LICENSE.md file distributed with this work for additional
|
|
22
|
-
information regarding copyright ownership.
|
|
23
|
-
|
|
24
|
-
Except as contained in the LICENSE file, the name(s) of the above copyright
|
|
25
|
-
holders shall not be used in advertising or otherwise to promote the sale,
|
|
26
|
-
use or other dealings in this Software without prior written authorization.
|
|
27
|
-
</pre>
|
|
13
|
+
If you find any problems or would like to suggest a feature, please feel free to file an issue on GitHub at [Issues Page](https://github.com/crowdin/app-project-module/issues) or [Contact Customer Success Service](https://crowdin.com/contacts).
|
package/out/index.js
CHANGED
|
@@ -176,7 +176,7 @@ function addCrowdinEndpoints(app, clientConfig) {
|
|
|
176
176
|
aiTools.registerAiToolWidgets({ config, app });
|
|
177
177
|
externalQaCheck.register({ config, app });
|
|
178
178
|
addFormSchema({ config, app });
|
|
179
|
-
return Object.assign(Object.assign({}, exports.metadataStore), { establishCrowdinConnection: (authRequest) => {
|
|
179
|
+
return Object.assign(Object.assign({}, exports.metadataStore), { establishCrowdinConnection: (authRequest, moduleKey) => {
|
|
180
180
|
let jwtToken = '';
|
|
181
181
|
if (typeof authRequest === 'string') {
|
|
182
182
|
jwtToken = authRequest;
|
|
@@ -184,7 +184,13 @@ function addCrowdinEndpoints(app, clientConfig) {
|
|
|
184
184
|
else {
|
|
185
185
|
jwtToken = (0, crowdin_client_1.getToken)(authRequest);
|
|
186
186
|
}
|
|
187
|
-
return (0, crowdin_client_1.prepareCrowdinRequest)(
|
|
187
|
+
return (0, crowdin_client_1.prepareCrowdinRequest)({
|
|
188
|
+
jwtToken,
|
|
189
|
+
config,
|
|
190
|
+
optional: false,
|
|
191
|
+
checkSubscriptionExpiration: false,
|
|
192
|
+
moduleKey,
|
|
193
|
+
});
|
|
188
194
|
}, encryptCrowdinConnection: (data) => (0, util_1.encryptData)(config, JSON.stringify(data)), dencryptCrowdinConnection: (hash) => __awaiter(this, void 0, void 0, function* () {
|
|
189
195
|
const { crowdinId, extra } = JSON.parse((0, util_1.decryptData)(config, hash));
|
|
190
196
|
const credentials = yield storage.getStorage().getCrowdinCredentials(crowdinId);
|
|
@@ -197,18 +203,27 @@ function addCrowdinEndpoints(app, clientConfig) {
|
|
|
197
203
|
}
|
|
198
204
|
exports.addCrowdinEndpoints = addCrowdinEndpoints;
|
|
199
205
|
function addFormSchema({ app, config }) {
|
|
200
|
-
let moduleConfigWithForm;
|
|
201
|
-
const
|
|
206
|
+
let moduleConfigWithForm = null;
|
|
207
|
+
for (const moduleKey of Object.keys(config)) {
|
|
202
208
|
const moduleConfig = config[moduleKey];
|
|
203
209
|
if ((0, form_schema_1.hasFormSchema)(moduleConfig)) {
|
|
204
210
|
moduleConfigWithForm = (0, form_schema_1.getLowCodeUiConfigFromModuleConfig)(moduleConfig);
|
|
205
|
-
|
|
211
|
+
break;
|
|
206
212
|
}
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
213
|
+
}
|
|
214
|
+
if (moduleConfigWithForm) {
|
|
215
|
+
app.get('/api/form-data', json_response_1.default, (0, crowdin_client_1.default)({
|
|
216
|
+
config,
|
|
217
|
+
optional: false,
|
|
218
|
+
checkSubscriptionExpiration: true,
|
|
219
|
+
moduleKey: moduleConfigWithForm.key,
|
|
220
|
+
}), (0, credentials_masker_1.getRequestCredentialsMasker)({ moduleConfig: moduleConfigWithForm }), (0, form_data_display_1.default)(config));
|
|
221
|
+
app.post('/api/form-data', (0, crowdin_client_1.default)({
|
|
222
|
+
config,
|
|
223
|
+
optional: false,
|
|
224
|
+
checkSubscriptionExpiration: true,
|
|
225
|
+
moduleKey: moduleConfigWithForm.key,
|
|
226
|
+
}), (0, credentials_masker_1.postRequestCredentialsMasker)(moduleConfigWithForm), (0, form_data_save_1.default)(config));
|
|
212
227
|
}
|
|
213
228
|
}
|
|
214
229
|
function convertClientConfig(clientConfig) {
|
|
@@ -3,12 +3,23 @@ import Crowdin from '@crowdin/crowdin-api-client';
|
|
|
3
3
|
import { Response } from 'express';
|
|
4
4
|
import { Config, CrowdinClientRequest, CrowdinContextInfo, SubscriptionInfo } from '../types';
|
|
5
5
|
import { LogErrorFunction, LogFunction } from '../util/logger';
|
|
6
|
-
export declare function prepareCrowdinRequest(jwtToken
|
|
6
|
+
export declare function prepareCrowdinRequest({ jwtToken, config, optional, checkSubscriptionExpiration, moduleKey, }: {
|
|
7
|
+
jwtToken: string;
|
|
8
|
+
config: Config;
|
|
9
|
+
optional: boolean;
|
|
10
|
+
checkSubscriptionExpiration: boolean;
|
|
11
|
+
moduleKey: string[] | string | undefined;
|
|
12
|
+
}): Promise<{
|
|
7
13
|
context: CrowdinContextInfo;
|
|
8
14
|
logInfo: LogFunction;
|
|
9
15
|
logError: LogErrorFunction;
|
|
10
16
|
client?: Crowdin;
|
|
11
17
|
subscriptionInfo?: SubscriptionInfo;
|
|
12
18
|
}>;
|
|
13
|
-
export default function handle(config
|
|
19
|
+
export default function handle({ config, optional, checkSubscriptionExpiration, moduleKey, }: {
|
|
20
|
+
config: Config;
|
|
21
|
+
optional: boolean;
|
|
22
|
+
checkSubscriptionExpiration: boolean;
|
|
23
|
+
moduleKey?: string[] | string | undefined;
|
|
24
|
+
}): (req: CrowdinClientRequest | import("express").Request<import("express-serve-static-core").ParamsDictionary, any, any, import("qs").ParsedQs, Record<string, any>>, res: Response<any, Record<string, any>>, next: Function) => void;
|
|
14
25
|
export declare function getToken(req: CrowdinClientRequest): string | undefined;
|
|
@@ -17,7 +17,7 @@ const api_1 = require("../modules/api/api");
|
|
|
17
17
|
const connection_1 = require("../util/connection");
|
|
18
18
|
const logger_1 = require("../util/logger");
|
|
19
19
|
const subscription_1 = require("../util/subscription");
|
|
20
|
-
function prepareCrowdinRequest(jwtToken, config, optional = false, checkSubscriptionExpiration = true) {
|
|
20
|
+
function prepareCrowdinRequest({ jwtToken, config, optional = false, checkSubscriptionExpiration = true, moduleKey, }) {
|
|
21
21
|
return __awaiter(this, void 0, void 0, function* () {
|
|
22
22
|
(0, logger_1.log)('Validating jwt token from incoming request');
|
|
23
23
|
const jwtPayload = yield (0, crowdin_apps_functions_1.validateJwtToken)(jwtToken, config.clientSecret, config.jwtValidationOptions);
|
|
@@ -37,6 +37,14 @@ function prepareCrowdinRequest(jwtToken, config, optional = false, checkSubscrip
|
|
|
37
37
|
}
|
|
38
38
|
throw new Error("Can't find organization by id");
|
|
39
39
|
}
|
|
40
|
+
if (!!moduleKey && !!jwtPayload.module) {
|
|
41
|
+
if (typeof moduleKey === 'string' && moduleKey !== jwtPayload.module) {
|
|
42
|
+
throw new Error("Module key doesn't match");
|
|
43
|
+
}
|
|
44
|
+
if (Array.isArray(moduleKey) && !moduleKey.includes(jwtPayload.module)) {
|
|
45
|
+
throw new Error("Module key doesn't match");
|
|
46
|
+
}
|
|
47
|
+
}
|
|
40
48
|
logInfo('Building crowdin client instance');
|
|
41
49
|
const { client, token } = yield (0, connection_1.prepareCrowdinClient)({ config, credentials, autoRenew: true, context });
|
|
42
50
|
let subscriptionInfo;
|
|
@@ -55,7 +63,7 @@ function prepareCrowdinRequest(jwtToken, config, optional = false, checkSubscrip
|
|
|
55
63
|
});
|
|
56
64
|
}
|
|
57
65
|
exports.prepareCrowdinRequest = prepareCrowdinRequest;
|
|
58
|
-
function handle(config, optional = false, checkSubscriptionExpiration = true) {
|
|
66
|
+
function handle({ config, optional = false, checkSubscriptionExpiration = true, moduleKey, }) {
|
|
59
67
|
return (0, util_1.runAsyncWrapper)((req, res, next) => __awaiter(this, void 0, void 0, function* () {
|
|
60
68
|
var _a;
|
|
61
69
|
const jwtToken = getToken(req);
|
|
@@ -64,7 +72,13 @@ function handle(config, optional = false, checkSubscriptionExpiration = true) {
|
|
|
64
72
|
return res.status(403).send({ error: 'Access denied' });
|
|
65
73
|
}
|
|
66
74
|
try {
|
|
67
|
-
const data = yield prepareCrowdinRequest(
|
|
75
|
+
const data = yield prepareCrowdinRequest({
|
|
76
|
+
jwtToken,
|
|
77
|
+
config,
|
|
78
|
+
optional,
|
|
79
|
+
checkSubscriptionExpiration,
|
|
80
|
+
moduleKey,
|
|
81
|
+
});
|
|
68
82
|
if ((_a = config.api) === null || _a === void 0 ? void 0 : _a.default) {
|
|
69
83
|
data.context = (0, api_1.updateCrowdinContext)(req, data.context);
|
|
70
84
|
}
|
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
/// <reference types="qs" />
|
|
2
2
|
import { Request, Response } from 'express';
|
|
3
3
|
import { Config, UnauthorizedConfig } from '../types';
|
|
4
|
-
export default function handle(config
|
|
4
|
+
export default function handle({ config, allowUnauthorized, moduleType, }: {
|
|
5
|
+
config: Config | UnauthorizedConfig;
|
|
6
|
+
allowUnauthorized?: boolean;
|
|
7
|
+
moduleType?: string | undefined;
|
|
8
|
+
}): (req: import("../types").CrowdinClientRequest | Request<import("express-serve-static-core").ParamsDictionary, any, any, import("qs").ParsedQs, Record<string, any>>, res: Response<any, Record<string, any>>, next: Function) => void;
|
|
@@ -15,7 +15,7 @@ const util_1 = require("../util");
|
|
|
15
15
|
const connection_1 = require("../util/connection");
|
|
16
16
|
const logger_1 = require("../util/logger");
|
|
17
17
|
const subscription_1 = require("../util/subscription");
|
|
18
|
-
function handle(config, allowUnauthorized = false) {
|
|
18
|
+
function handle({ config, allowUnauthorized = false, moduleType, }) {
|
|
19
19
|
return (0, util_1.runAsyncWrapper)((req, res, next) => __awaiter(this, void 0, void 0, function* () {
|
|
20
20
|
if (allowUnauthorized) {
|
|
21
21
|
next();
|
|
@@ -32,6 +32,10 @@ function handle(config, allowUnauthorized = false) {
|
|
|
32
32
|
(0, logger_1.log)('Validating jwt token from incoming request');
|
|
33
33
|
const jwtPayload = yield (0, crowdin_apps_functions_1.validateJwtToken)(jwtToken, config.clientSecret, config.jwtValidationOptions);
|
|
34
34
|
const id = `${jwtPayload.domain || jwtPayload.context.organization_id}`;
|
|
35
|
+
if (moduleType && jwtPayload.module && jwtPayload.module !== moduleType) {
|
|
36
|
+
(0, logger_1.temporaryErrorDebug)('Access denied: ui-module', req);
|
|
37
|
+
return res.status(403).send({ error: 'Access denied' });
|
|
38
|
+
}
|
|
35
39
|
const context = {
|
|
36
40
|
jwtPayload,
|
|
37
41
|
clientId: (0, crowdin_apps_functions_1.constructCrowdinIdFromJwtPayload)(jwtPayload),
|
|
@@ -14,9 +14,14 @@ function register({ config, app }) {
|
|
|
14
14
|
if (!config.aiPromptProvider) {
|
|
15
15
|
return;
|
|
16
16
|
}
|
|
17
|
-
app.post('/prompt-provider/compile', json_response_1.default, (0, crowdin_client_1.default)(
|
|
17
|
+
app.post('/prompt-provider/compile', json_response_1.default, (0, crowdin_client_1.default)({
|
|
18
|
+
config,
|
|
19
|
+
optional: false,
|
|
20
|
+
checkSubscriptionExpiration: true,
|
|
21
|
+
moduleKey: config.aiPromptProvider.key,
|
|
22
|
+
}), (0, compile_1.default)(config.aiPromptProvider));
|
|
18
23
|
if (config.aiPromptProvider.formSchema) {
|
|
19
|
-
app.use('/prompt-provider/settings', (0, ui_module_1.default)(config, true), (0, render_ui_module_1.default)(config.aiPromptProvider));
|
|
24
|
+
app.use('/prompt-provider/settings', (0, ui_module_1.default)({ config, allowUnauthorized: true, moduleType: config.aiPromptProvider.key }), (0, render_ui_module_1.default)(config.aiPromptProvider));
|
|
20
25
|
}
|
|
21
26
|
app.get((0, util_1.getLogoUrl)(config.aiPromptProvider, '/ai-prompt-provider'), (req, res) => { var _a; return res.sendFile(((_a = config.aiPromptProvider) === null || _a === void 0 ? void 0 : _a.imagePath) || config.imagePath); });
|
|
22
27
|
}
|
|
@@ -13,13 +13,43 @@ 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
|
+
// more about roles in AI messages https://platform.openai.com/docs/api-reference/chat/create#chat-create-messages
|
|
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;
|
|
22
|
+
const getErrorStatus = (e) => {
|
|
23
|
+
if (typeof e === 'object' && 'status' in e && typeof e.status === 'number') {
|
|
24
|
+
return e.status;
|
|
25
|
+
}
|
|
26
|
+
return 500;
|
|
27
|
+
};
|
|
28
|
+
const getErrorCode = (e) => {
|
|
29
|
+
if (typeof e === 'object' && 'code' in e) {
|
|
30
|
+
return e.code;
|
|
31
|
+
}
|
|
32
|
+
return undefined;
|
|
33
|
+
};
|
|
16
34
|
function handle(aiProvider) {
|
|
17
35
|
return (0, util_1.runAsyncWrapper)((req, res) => __awaiter(this, void 0, void 0, function* () {
|
|
36
|
+
let isStream = false;
|
|
18
37
|
try {
|
|
19
38
|
let choices;
|
|
20
39
|
let message;
|
|
21
40
|
let data;
|
|
22
|
-
const
|
|
41
|
+
const chunks = [];
|
|
42
|
+
const { crowdinApiClient: client, crowdinContext: context, body: { messages, model, action, stream, responseFormat: { type: responseFormatType } = { type: undefined }, }, } = req;
|
|
43
|
+
isStream = !!stream;
|
|
44
|
+
const startStream = () => {
|
|
45
|
+
if (!res.headersSent) {
|
|
46
|
+
res.writeHead(200, {
|
|
47
|
+
Connection: 'keep-alive',
|
|
48
|
+
'Cache-Control': 'no-cache',
|
|
49
|
+
'Content-Type': 'text/event-stream',
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
};
|
|
23
53
|
const result = yield aiProvider.chatCompletions({
|
|
24
54
|
messages,
|
|
25
55
|
model,
|
|
@@ -28,7 +58,32 @@ function handle(aiProvider) {
|
|
|
28
58
|
client,
|
|
29
59
|
context,
|
|
30
60
|
req,
|
|
61
|
+
isStream,
|
|
62
|
+
sendEvent: ({ content, role }) => __awaiter(this, void 0, void 0, function* () {
|
|
63
|
+
if (!isStream) {
|
|
64
|
+
chunks.push({ content, role });
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
startStream();
|
|
68
|
+
const message = {
|
|
69
|
+
choices: [
|
|
70
|
+
{
|
|
71
|
+
delta: {
|
|
72
|
+
role: role || DEFAULT_ROLE,
|
|
73
|
+
content,
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
],
|
|
77
|
+
};
|
|
78
|
+
res.write(`data: ${JSON.stringify(message)}\n\n`);
|
|
79
|
+
}),
|
|
31
80
|
});
|
|
81
|
+
if (isStream) {
|
|
82
|
+
startStream();
|
|
83
|
+
res.write('[DONE]');
|
|
84
|
+
res.end();
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
32
87
|
if ((0, files_1.isExtendedResultType)(result)) {
|
|
33
88
|
data = result.data;
|
|
34
89
|
message = result.message;
|
|
@@ -36,10 +91,18 @@ function handle(aiProvider) {
|
|
|
36
91
|
else {
|
|
37
92
|
data = result;
|
|
38
93
|
}
|
|
94
|
+
if (chunks.length) {
|
|
95
|
+
data = [
|
|
96
|
+
{
|
|
97
|
+
role: chunks[0].role || DEFAULT_ROLE,
|
|
98
|
+
content: chunks.map((chunk) => chunk.content).join(''),
|
|
99
|
+
},
|
|
100
|
+
];
|
|
101
|
+
}
|
|
39
102
|
if (data && data.length > 0) {
|
|
40
103
|
choices = data.map((message) => ({
|
|
41
104
|
message: {
|
|
42
|
-
role: message.role ||
|
|
105
|
+
role: message.role || DEFAULT_ROLE,
|
|
43
106
|
content: message.content,
|
|
44
107
|
},
|
|
45
108
|
}));
|
|
@@ -50,10 +113,17 @@ function handle(aiProvider) {
|
|
|
50
113
|
if (req.logError) {
|
|
51
114
|
req.logError(e);
|
|
52
115
|
}
|
|
53
|
-
if (
|
|
54
|
-
res.status(429);
|
|
116
|
+
if (!res.headersSent) {
|
|
117
|
+
res.status((0, util_2.isRateLimitError)(e) ? 429 : getErrorStatus(e));
|
|
118
|
+
}
|
|
119
|
+
if (isStream && res.headersSent) {
|
|
120
|
+
res.write(`data: ${JSON.stringify({ error: { message: (0, logger_1.getErrorMessage)(e), code: getErrorCode(e) } })}\n\n`);
|
|
121
|
+
res.write('[DONE]');
|
|
122
|
+
res.end();
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
res.send({ error: { message: (0, logger_1.getErrorMessage)(e) } });
|
|
55
126
|
}
|
|
56
|
-
res.send({ error: { message: (0, logger_1.getErrorMessage)(e) } });
|
|
57
127
|
}
|
|
58
128
|
}));
|
|
59
129
|
}
|
|
@@ -22,12 +22,13 @@ function handle(aiProvider) {
|
|
|
22
22
|
context: req.crowdinContext,
|
|
23
23
|
});
|
|
24
24
|
const data = modelList.map((model) => {
|
|
25
|
-
var _a, _b, _c;
|
|
25
|
+
var _a, _b, _c, _d;
|
|
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
|
+
contextWindowLimit: (_d = model.contextWindowLimit) !== null && _d !== void 0 ? _d : exports.CONTEXT_WINDOW_LIMIT,
|
|
31
32
|
});
|
|
32
33
|
});
|
|
33
34
|
res.send({ data });
|
|
@@ -16,10 +16,20 @@ function register({ config, app }) {
|
|
|
16
16
|
return;
|
|
17
17
|
}
|
|
18
18
|
if (config.aiProvider.settingsUiModule) {
|
|
19
|
-
app.use('/settings', (0, ui_module_1.default)(config, true), (0, render_ui_module_1.default)(config.aiProvider.settingsUiModule));
|
|
19
|
+
app.use('/settings', (0, ui_module_1.default)({ config, allowUnauthorized: true, moduleType: config.aiProvider.key }), (0, render_ui_module_1.default)(config.aiProvider.settingsUiModule));
|
|
20
20
|
}
|
|
21
21
|
app.get((0, util_1.getLogoUrl)(config.aiProvider, '/aiprovider'), (req, res) => { var _a; return res.sendFile(((_a = config.aiProvider) === null || _a === void 0 ? void 0 : _a.imagePath) || config.imagePath); });
|
|
22
|
-
app.get('/models', json_response_1.default, (0, crowdin_client_1.default)(
|
|
23
|
-
|
|
22
|
+
app.get('/models', json_response_1.default, (0, crowdin_client_1.default)({
|
|
23
|
+
config,
|
|
24
|
+
optional: false,
|
|
25
|
+
checkSubscriptionExpiration: true,
|
|
26
|
+
moduleKey: config.aiProvider.key,
|
|
27
|
+
}), (0, get_model_list_1.default)(config.aiProvider));
|
|
28
|
+
app.post('/completions', json_response_1.default, (0, crowdin_client_1.default)({
|
|
29
|
+
config,
|
|
30
|
+
optional: false,
|
|
31
|
+
checkSubscriptionExpiration: true,
|
|
32
|
+
moduleKey: config.aiProvider.key,
|
|
33
|
+
}), (0, chat_completions_1.default)(config.aiProvider));
|
|
24
34
|
}
|
|
25
35
|
exports.register = register;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { CrowdinClientRequest, CrowdinContextInfo, Environments, UiModule } from '../../types';
|
|
1
|
+
import { CrowdinClientRequest, CrowdinContextInfo, Environments, ModuleKey, UiModule } from '../../types';
|
|
2
2
|
import Crowdin from '@crowdin/crowdin-api-client';
|
|
3
3
|
import { ExtendedResult } from '../integration/types';
|
|
4
|
-
export interface AiProviderModule extends Environments {
|
|
4
|
+
export interface AiProviderModule extends Environments, ModuleKey {
|
|
5
5
|
/**
|
|
6
6
|
* module name
|
|
7
7
|
*/
|
|
@@ -25,6 +25,8 @@ export interface AiProviderModule extends Environments {
|
|
|
25
25
|
client: Crowdin;
|
|
26
26
|
context: CrowdinContextInfo;
|
|
27
27
|
req: CrowdinClientRequest;
|
|
28
|
+
isStream: boolean;
|
|
29
|
+
sendEvent: (chunk: Message) => Promise<void>;
|
|
28
30
|
}) => Promise<Message[] | ExtendedResult<Message[]>>;
|
|
29
31
|
/**
|
|
30
32
|
* provides a list of available model
|
|
@@ -38,6 +40,7 @@ export interface SupportedModels {
|
|
|
38
40
|
id: string;
|
|
39
41
|
supportsJsonMode?: boolean;
|
|
40
42
|
supportsFunctionCalling?: boolean;
|
|
43
|
+
supportsStreaming?: boolean;
|
|
41
44
|
contextWindowLimit?: number;
|
|
42
45
|
}
|
|
43
46
|
export interface Message {
|
|
@@ -17,7 +17,12 @@ function registerAiTools({ config, app }) {
|
|
|
17
17
|
const tools = Array.isArray(config.aiTools) ? config.aiTools : [config.aiTools];
|
|
18
18
|
for (const tool of tools) {
|
|
19
19
|
if ((0, util_1.isUniqueFunctionName)(tool)) {
|
|
20
|
-
app.post((0, util_1.getAiToolUrl)(tool), json_response_1.default, (0, crowdin_client_1.default)(
|
|
20
|
+
app.post((0, util_1.getAiToolUrl)(tool), json_response_1.default, (0, crowdin_client_1.default)({
|
|
21
|
+
config,
|
|
22
|
+
optional: false,
|
|
23
|
+
checkSubscriptionExpiration: true,
|
|
24
|
+
moduleKey: tool.key,
|
|
25
|
+
}), (0, tool_calls_1.default)(tool));
|
|
21
26
|
}
|
|
22
27
|
else {
|
|
23
28
|
throw new Error(`The function name '${tool.function.name}' is not unique within aiTools and aiToolsWidget`);
|
|
@@ -32,7 +37,7 @@ function registerAiToolWidgets({ config, app }) {
|
|
|
32
37
|
const tools = Array.isArray(config.aiToolsWidget) ? config.aiToolsWidget : [config.aiToolsWidget];
|
|
33
38
|
for (const tool of tools) {
|
|
34
39
|
if ((0, util_1.isUniqueFunctionName)(tool)) {
|
|
35
|
-
app.use((0, util_1.getAiToolWidgetUrl)(tool), (0, ui_module_1.default)(config), (0, render_ui_module_1.default)(tool));
|
|
40
|
+
app.use((0, util_1.getAiToolWidgetUrl)(tool), (0, ui_module_1.default)({ config, moduleType: tool.key }), (0, render_ui_module_1.default)(tool));
|
|
36
41
|
}
|
|
37
42
|
else {
|
|
38
43
|
throw new Error(`The function name '${tool.function.name}' is not unique within aiTools and aiToolsWidget`);
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { CrowdinClientRequest, CrowdinContextInfo, Environments, UiModule } from '../../types';
|
|
1
|
+
import { CrowdinClientRequest, CrowdinContextInfo, Environments, ModuleKey, UiModule } from '../../types';
|
|
2
2
|
import Crowdin from '@crowdin/crowdin-api-client';
|
|
3
3
|
export interface AiToolWidget extends BaseAiTool, UiModule {
|
|
4
4
|
}
|
|
5
|
-
export interface AiTool extends BaseAiTool {
|
|
5
|
+
export interface AiTool extends BaseAiTool, ModuleKey {
|
|
6
6
|
/**
|
|
7
7
|
* function to handle requests
|
|
8
8
|
*/
|
package/out/modules/api/api.js
CHANGED
|
@@ -171,7 +171,12 @@ function addDefaultApiEndpoints(app, config) {
|
|
|
171
171
|
* data:
|
|
172
172
|
* $ref: '#/components/schemas/CrowdinFiles'
|
|
173
173
|
*/
|
|
174
|
-
app.get('/crowdin-files', json_response_1.default, (0, crowdin_client_1.default)(
|
|
174
|
+
app.get('/crowdin-files', json_response_1.default, (0, crowdin_client_1.default)({
|
|
175
|
+
config,
|
|
176
|
+
optional: false,
|
|
177
|
+
checkSubscriptionExpiration: true,
|
|
178
|
+
moduleKey: config.projectIntegration.key,
|
|
179
|
+
}), (0, integration_credentials_1.default)(config, config.projectIntegration), (0, crowdin_files_1.default)(config, config.projectIntegration));
|
|
175
180
|
/**
|
|
176
181
|
* @openapi
|
|
177
182
|
* /file-progress:
|
|
@@ -200,7 +205,12 @@ function addDefaultApiEndpoints(app, config) {
|
|
|
200
205
|
* data:
|
|
201
206
|
* $ref: '#/components/schemas/FileProgress'
|
|
202
207
|
*/
|
|
203
|
-
app.get('/file-progress', (0, crowdin_client_1.default)(
|
|
208
|
+
app.get('/file-progress', (0, crowdin_client_1.default)({
|
|
209
|
+
config,
|
|
210
|
+
optional: false,
|
|
211
|
+
checkSubscriptionExpiration: true,
|
|
212
|
+
moduleKey: config.projectIntegration.key,
|
|
213
|
+
}), (0, crowdin_file_progress_1.default)(config.projectIntegration));
|
|
204
214
|
/**
|
|
205
215
|
* @openapi
|
|
206
216
|
* /integration-files:
|
|
@@ -222,7 +232,12 @@ function addDefaultApiEndpoints(app, config) {
|
|
|
222
232
|
* $ref: '#/components/schemas/IntegrationFiles'
|
|
223
233
|
*
|
|
224
234
|
*/
|
|
225
|
-
app.get('/integration-files', json_response_1.default, (0, crowdin_client_1.default)(
|
|
235
|
+
app.get('/integration-files', json_response_1.default, (0, crowdin_client_1.default)({
|
|
236
|
+
config,
|
|
237
|
+
optional: false,
|
|
238
|
+
checkSubscriptionExpiration: true,
|
|
239
|
+
moduleKey: config.projectIntegration.key,
|
|
240
|
+
}), (0, integration_credentials_1.default)(config, config.projectIntegration), (0, integration_data_1.default)(config.projectIntegration));
|
|
226
241
|
/**
|
|
227
242
|
* @openapi
|
|
228
243
|
* /crowdin-update:
|
|
@@ -245,7 +260,12 @@ function addDefaultApiEndpoints(app, config) {
|
|
|
245
260
|
* data:
|
|
246
261
|
* $ref: '#/components/schemas/UpdateResponse'
|
|
247
262
|
*/
|
|
248
|
-
app.post('/crowdin-update', json_response_1.default, (0, crowdin_client_1.default)(
|
|
263
|
+
app.post('/crowdin-update', json_response_1.default, (0, crowdin_client_1.default)({
|
|
264
|
+
config,
|
|
265
|
+
optional: false,
|
|
266
|
+
checkSubscriptionExpiration: true,
|
|
267
|
+
moduleKey: config.projectIntegration.key,
|
|
268
|
+
}), (0, integration_credentials_1.default)(config, config.projectIntegration), (0, crowdin_update_1.default)(config, config.projectIntegration));
|
|
249
269
|
/**
|
|
250
270
|
* @openapi
|
|
251
271
|
* /integration-update:
|
|
@@ -268,7 +288,12 @@ function addDefaultApiEndpoints(app, config) {
|
|
|
268
288
|
* data:
|
|
269
289
|
* $ref: '#/components/schemas/UpdateResponse'
|
|
270
290
|
*/
|
|
271
|
-
app.post('/integration-update', json_response_1.default, (0, crowdin_client_1.default)(
|
|
291
|
+
app.post('/integration-update', json_response_1.default, (0, crowdin_client_1.default)({
|
|
292
|
+
config,
|
|
293
|
+
optional: false,
|
|
294
|
+
checkSubscriptionExpiration: true,
|
|
295
|
+
moduleKey: config.projectIntegration.key,
|
|
296
|
+
}), (0, integration_credentials_1.default)(config, config.projectIntegration), (0, integration_update_1.default)(config, config.projectIntegration));
|
|
272
297
|
/**
|
|
273
298
|
* @openapi
|
|
274
299
|
* /settings:
|
|
@@ -289,7 +314,12 @@ function addDefaultApiEndpoints(app, config) {
|
|
|
289
314
|
* data:
|
|
290
315
|
* $ref: '#/components/schemas/SettingsResponse'
|
|
291
316
|
*/
|
|
292
|
-
app.get('/settings', (0, crowdin_client_1.default)(
|
|
317
|
+
app.get('/settings', (0, crowdin_client_1.default)({
|
|
318
|
+
config,
|
|
319
|
+
optional: false,
|
|
320
|
+
checkSubscriptionExpiration: true,
|
|
321
|
+
moduleKey: config.projectIntegration.key,
|
|
322
|
+
}), (0, integration_credentials_1.default)(config, config.projectIntegration), (0, settings_1.default)());
|
|
293
323
|
/**
|
|
294
324
|
* @openapi
|
|
295
325
|
* /settings:
|
|
@@ -307,7 +337,12 @@ function addDefaultApiEndpoints(app, config) {
|
|
|
307
337
|
* 204:
|
|
308
338
|
* description: 'Application Settings was successfully update'
|
|
309
339
|
*/
|
|
310
|
-
app.post('/settings', (0, crowdin_client_1.default)(
|
|
340
|
+
app.post('/settings', (0, crowdin_client_1.default)({
|
|
341
|
+
config,
|
|
342
|
+
optional: false,
|
|
343
|
+
checkSubscriptionExpiration: true,
|
|
344
|
+
moduleKey: config.projectIntegration.key,
|
|
345
|
+
}), (0, integration_credentials_1.default)(config, config.projectIntegration), (0, settings_save_1.default)(config, config.projectIntegration));
|
|
311
346
|
/**
|
|
312
347
|
* @openapi
|
|
313
348
|
* /sync-settings:
|
|
@@ -338,7 +373,12 @@ function addDefaultApiEndpoints(app, config) {
|
|
|
338
373
|
* - { $ref: '#/components/schemas/CrowdinSyncSettingsResponse' }
|
|
339
374
|
* - { $ref: '#/components/schemas/IntegrationSyncSettingsResponse' }
|
|
340
375
|
*/
|
|
341
|
-
app.get('/sync-settings', json_response_1.default, (0, crowdin_client_1.default)(
|
|
376
|
+
app.get('/sync-settings', json_response_1.default, (0, crowdin_client_1.default)({
|
|
377
|
+
config,
|
|
378
|
+
optional: false,
|
|
379
|
+
checkSubscriptionExpiration: true,
|
|
380
|
+
moduleKey: config.projectIntegration.key,
|
|
381
|
+
}), (0, integration_credentials_1.default)(config, config.projectIntegration), (0, sync_settings_1.default)());
|
|
342
382
|
/**
|
|
343
383
|
* @openapi
|
|
344
384
|
* /sync-settings:
|
|
@@ -356,7 +396,12 @@ function addDefaultApiEndpoints(app, config) {
|
|
|
356
396
|
* 204:
|
|
357
397
|
* description: 'Application Sync Settings was successfully update'
|
|
358
398
|
*/
|
|
359
|
-
app.post('/sync-settings', json_response_1.default, (0, crowdin_client_1.default)(
|
|
399
|
+
app.post('/sync-settings', json_response_1.default, (0, crowdin_client_1.default)({
|
|
400
|
+
config,
|
|
401
|
+
optional: false,
|
|
402
|
+
checkSubscriptionExpiration: true,
|
|
403
|
+
moduleKey: config.projectIntegration.key,
|
|
404
|
+
}), (0, integration_credentials_1.default)(config, config.projectIntegration), (0, sync_settings_save_1.default)(config, config.projectIntegration));
|
|
360
405
|
if (config.projectIntegration.loginForm) {
|
|
361
406
|
/**
|
|
362
407
|
* @openapi
|
|
@@ -376,7 +421,12 @@ function addDefaultApiEndpoints(app, config) {
|
|
|
376
421
|
* data:
|
|
377
422
|
* $ref: '#/components/schemas/LoginFieldsResponse'
|
|
378
423
|
*/
|
|
379
|
-
app.get('/login-fields', json_response_1.default, (0, crowdin_client_1.default)(
|
|
424
|
+
app.get('/login-fields', json_response_1.default, (0, crowdin_client_1.default)({
|
|
425
|
+
config,
|
|
426
|
+
optional: false,
|
|
427
|
+
checkSubscriptionExpiration: true,
|
|
428
|
+
moduleKey: config.projectIntegration.key,
|
|
429
|
+
}), (req, res) => {
|
|
380
430
|
var _a;
|
|
381
431
|
let fields = [];
|
|
382
432
|
if ((_a = config.projectIntegration) === null || _a === void 0 ? void 0 : _a.loginForm.fields) {
|
|
@@ -401,7 +451,12 @@ function addDefaultApiEndpoints(app, config) {
|
|
|
401
451
|
* 204:
|
|
402
452
|
* description: 'Login successful'
|
|
403
453
|
*/
|
|
404
|
-
app.post('/login', (0, crowdin_client_1.default)(
|
|
454
|
+
app.post('/login', (0, crowdin_client_1.default)({
|
|
455
|
+
config,
|
|
456
|
+
optional: false,
|
|
457
|
+
checkSubscriptionExpiration: false,
|
|
458
|
+
moduleKey: config.projectIntegration.key,
|
|
459
|
+
}), (0, integration_login_1.default)(config, config.projectIntegration));
|
|
405
460
|
}
|
|
406
461
|
}
|
|
407
462
|
}
|
|
@@ -11,7 +11,7 @@ function register({ config, app }) {
|
|
|
11
11
|
var _a, _b;
|
|
12
12
|
const allowUnauthorized = !(0, util_1.isAuthorizedConfig)(config);
|
|
13
13
|
if (((_a = config.contextMenu) === null || _a === void 0 ? void 0 : _a.uiPath) || ((_b = config.contextMenu) === null || _b === void 0 ? void 0 : _b.formSchema)) {
|
|
14
|
-
app.use('/context', (0, ui_module_1.default)(config, allowUnauthorized), (0, render_ui_module_1.default)(config.contextMenu));
|
|
14
|
+
app.use('/context', (0, ui_module_1.default)({ config, allowUnauthorized, moduleType: config.contextMenu.key }), (0, render_ui_module_1.default)(config.contextMenu));
|
|
15
15
|
}
|
|
16
16
|
}
|
|
17
17
|
exports.register = register;
|
|
@@ -12,6 +12,11 @@ function register({ config, app }) {
|
|
|
12
12
|
return;
|
|
13
13
|
}
|
|
14
14
|
app.get((0, util_1.getLogoUrl)(config.customMT, '/mt'), (req, res) => { var _a; return res.sendFile(((_a = config.customMT) === null || _a === void 0 ? void 0 : _a.imagePath) || config.imagePath); });
|
|
15
|
-
app.post('/translate', (0, crowdin_client_1.default)(
|
|
15
|
+
app.post('/translate', (0, crowdin_client_1.default)({
|
|
16
|
+
config,
|
|
17
|
+
optional: false,
|
|
18
|
+
checkSubscriptionExpiration: true,
|
|
19
|
+
moduleKey: config.customMT.key,
|
|
20
|
+
}), (0, translate_1.default)(config.customMT));
|
|
16
21
|
}
|
|
17
22
|
exports.register = register;
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import Crowdin, { SourceStringsModel } from '@crowdin/crowdin-api-client';
|
|
2
|
-
import { CrowdinContextInfo } from '../../types';
|
|
3
|
-
export interface CustomMTLogic {
|
|
2
|
+
import { CrowdinContextInfo, ModuleKey } from '../../types';
|
|
3
|
+
export interface CustomMTLogic extends ModuleKey {
|
|
4
4
|
withContext?: boolean;
|
|
5
|
+
batchSize?: number;
|
|
6
|
+
maskEntities?: boolean;
|
|
5
7
|
translate: (client: Crowdin, context: CrowdinContextInfo, projectId: number, source: string, target: string, strings: CustomMtString[]) => Promise<string[]>;
|
|
6
8
|
validate?: (client: Crowdin) => Promise<void>;
|
|
7
9
|
}
|