@purpleschool/gptbot 0.5.99 → 0.6.1
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/build/constants/ai-model/enums/ai-model-config-selector-type.enum.js +1 -0
- package/build/constants/errors/errors.js +20 -0
- package/build/constants/subscription/enums/subscription-feature-type.enum.js +17 -2
- package/build/constants/tool/enums/tool-type.enum.js +2 -0
- package/build/helpers/ai-model/calc-base-text-generation-price.helper.js +15 -0
- package/build/helpers/ai-model/index.js +17 -0
- package/build/helpers/index.js +1 -0
- package/build/models/ai-model-config.schema.js +8 -1
- package/build/models/index.js +1 -0
- package/build/models/subscription-feature.schema.js +56 -25
- package/build/models/tools/paraphrase/paraphrase-model.schema.js +3 -0
- package/build/models/tools/paraphrase/paraphrase-style.schema.js +3 -0
- package/build/models/tools/stt/stt-model.schema.js +3 -0
- package/build/models/tools/tts/tts-model.schema.js +3 -0
- package/build/models/unlocked-by-subscription.schema.js +13 -0
- package/constants/ai-model/enums/ai-model-config-selector-type.enum.ts +1 -0
- package/constants/errors/errors.ts +20 -0
- package/constants/subscription/enums/subscription-feature-type.enum.ts +16 -1
- package/constants/tool/enums/tool-type.enum.ts +2 -0
- package/helpers/ai-model/calc-base-text-generation-price.helper.ts +24 -0
- package/helpers/ai-model/index.ts +1 -0
- package/helpers/index.ts +1 -0
- package/models/ai-model-config.schema.ts +12 -0
- package/models/index.ts +1 -0
- package/models/subscription-feature.schema.ts +77 -25
- package/models/tools/paraphrase/paraphrase-config.schema.ts +0 -1
- package/models/tools/paraphrase/paraphrase-model.schema.ts +3 -0
- package/models/tools/paraphrase/paraphrase-style.schema.ts +3 -0
- package/models/tools/stt/stt-model.schema.ts +3 -0
- package/models/tools/tts/tts-model.schema.ts +3 -0
- package/models/unlocked-by-subscription.schema.ts +14 -0
- package/package.json +1 -1
|
@@ -6,4 +6,5 @@ var AI_MODEL_CONFIG_PARAM;
|
|
|
6
6
|
AI_MODEL_CONFIG_PARAM["IMAGE_SIZE"] = "image-size";
|
|
7
7
|
AI_MODEL_CONFIG_PARAM["IMAGE_STYLE"] = "image-style";
|
|
8
8
|
AI_MODEL_CONFIG_PARAM["WEB_SEARCH"] = "web-search";
|
|
9
|
+
AI_MODEL_CONFIG_PARAM["EXTRA_SYMBOLS_PRICING"] = "extra-symbols-pricing";
|
|
9
10
|
})(AI_MODEL_CONFIG_PARAM || (exports.AI_MODEL_CONFIG_PARAM = AI_MODEL_CONFIG_PARAM = {}));
|
|
@@ -1418,4 +1418,24 @@ exports.ERRORS = {
|
|
|
1418
1418
|
message: 'Промпт категория не найдена',
|
|
1419
1419
|
httpCode: 404,
|
|
1420
1420
|
},
|
|
1421
|
+
PARAPHRASE_NO_ACCESS_TO_TYPE: {
|
|
1422
|
+
code: 'A307',
|
|
1423
|
+
message: 'Пользователь не имеет доступ к указанному типу инструмента для перефразирования',
|
|
1424
|
+
httpCode: 401,
|
|
1425
|
+
},
|
|
1426
|
+
PARAPHRASE_NO_ACCESS_TO_STYLE: {
|
|
1427
|
+
code: 'A308',
|
|
1428
|
+
message: 'Пользователь не имеет доступ к указанному стилю инструмента для перефразирования',
|
|
1429
|
+
httpCode: 401,
|
|
1430
|
+
},
|
|
1431
|
+
TTS_MODEL_NOT_AVAILABLE: {
|
|
1432
|
+
code: 'A309',
|
|
1433
|
+
message: 'Модель TTS не доступна на текущем тарифе',
|
|
1434
|
+
httpCode: 401,
|
|
1435
|
+
},
|
|
1436
|
+
SUBSCRIPTION_FEATURE_BUILD_ERROR: {
|
|
1437
|
+
code: 'A310',
|
|
1438
|
+
message: 'Произошла ошибка при построении списка функций подписки',
|
|
1439
|
+
httpCode: 500,
|
|
1440
|
+
},
|
|
1421
1441
|
};
|
|
@@ -1,11 +1,26 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.SUBSCRIPTION_FEATURE_TYPE = void 0;
|
|
3
|
+
exports.SUBSCRIPTION_FEATURE_KIND = exports.SUBSCRIPTION_FEATURE_TYPE = void 0;
|
|
4
4
|
var SUBSCRIPTION_FEATURE_TYPE;
|
|
5
5
|
(function (SUBSCRIPTION_FEATURE_TYPE) {
|
|
6
|
-
SUBSCRIPTION_FEATURE_TYPE["
|
|
6
|
+
SUBSCRIPTION_FEATURE_TYPE["TEXT_GENERATION_QUOTA"] = "text_generation_quota";
|
|
7
7
|
SUBSCRIPTION_FEATURE_TYPE["AI_MODEL_ACCESS"] = "ai_model_access";
|
|
8
8
|
SUBSCRIPTION_FEATURE_TYPE["MAX_INPUT_LENGTH"] = "max_input_length";
|
|
9
9
|
SUBSCRIPTION_FEATURE_TYPE["INFO"] = "info";
|
|
10
10
|
SUBSCRIPTION_FEATURE_TYPE["WEB_SEARCH"] = "web_search";
|
|
11
|
+
SUBSCRIPTION_FEATURE_TYPE["ADVANCED_TOOLS_ACCESS"] = "advanced_tools_access";
|
|
12
|
+
SUBSCRIPTION_FEATURE_TYPE["STT_MODEL_ACCESS"] = "stt_model_access";
|
|
13
|
+
SUBSCRIPTION_FEATURE_TYPE["TTS_MODEL_ACCESS"] = "tts_model_access";
|
|
14
|
+
SUBSCRIPTION_FEATURE_TYPE["IMAGE_GENERATION_QUOTA"] = "image_generation_quota";
|
|
15
|
+
SUBSCRIPTION_FEATURE_TYPE["TTS_QUOTA"] = "tts_quota";
|
|
16
|
+
SUBSCRIPTION_FEATURE_TYPE["STT_QUOTA"] = "stt_quota";
|
|
11
17
|
})(SUBSCRIPTION_FEATURE_TYPE || (exports.SUBSCRIPTION_FEATURE_TYPE = SUBSCRIPTION_FEATURE_TYPE = {}));
|
|
18
|
+
var SUBSCRIPTION_FEATURE_KIND;
|
|
19
|
+
(function (SUBSCRIPTION_FEATURE_KIND) {
|
|
20
|
+
SUBSCRIPTION_FEATURE_KIND["TEXT"] = "text";
|
|
21
|
+
SUBSCRIPTION_FEATURE_KIND["AI_MODEL"] = "ai_model";
|
|
22
|
+
SUBSCRIPTION_FEATURE_KIND["IMAGE"] = "image";
|
|
23
|
+
SUBSCRIPTION_FEATURE_KIND["TTS"] = "tts";
|
|
24
|
+
SUBSCRIPTION_FEATURE_KIND["STT"] = "stt";
|
|
25
|
+
SUBSCRIPTION_FEATURE_KIND["PRESENTATIONS"] = "presentations";
|
|
26
|
+
})(SUBSCRIPTION_FEATURE_KIND || (exports.SUBSCRIPTION_FEATURE_KIND = SUBSCRIPTION_FEATURE_KIND = {}));
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.calcBaseTextGenerationPrice = calcBaseTextGenerationPrice;
|
|
4
|
+
function calcBaseTextGenerationPrice({ symbolsInRequest, defaultPrice, config, }) {
|
|
5
|
+
if (!config) {
|
|
6
|
+
return defaultPrice;
|
|
7
|
+
}
|
|
8
|
+
const { stepSize, stepPrice } = config;
|
|
9
|
+
if (symbolsInRequest <= stepSize) {
|
|
10
|
+
return defaultPrice;
|
|
11
|
+
}
|
|
12
|
+
const symbolsBeyondFirstStep = symbolsInRequest - stepSize;
|
|
13
|
+
const additionalSteps = Math.ceil(symbolsBeyondFirstStep / stepSize);
|
|
14
|
+
return defaultPrice + Math.ceil(additionalSteps * stepPrice);
|
|
15
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./calc-base-text-generation-price.helper"), exports);
|
package/build/helpers/index.js
CHANGED
|
@@ -14,6 +14,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./ai-model"), exports);
|
|
17
18
|
__exportStar(require("./stt"), exports);
|
|
18
19
|
__exportStar(require("./subscription"), exports);
|
|
19
20
|
__exportStar(require("./tts"), exports);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.AiModelConfigSchema = exports.AiModelWebSearchParameter = exports.AiModelImageStyleParameter = exports.AiModelImageStyleOptionSchema = exports.AiModelImageSizeParameter = exports.AiModelImageSizeOptionSchema = exports.AiModelConfigParameterSchema = void 0;
|
|
3
|
+
exports.AiModelConfigSchema = exports.AiModelExtraSymbolsPricingParameter = exports.AiModelWebSearchParameter = exports.AiModelImageStyleParameter = exports.AiModelImageStyleOptionSchema = exports.AiModelImageSizeParameter = exports.AiModelImageSizeOptionSchema = exports.AiModelConfigParameterSchema = void 0;
|
|
4
4
|
const zod_1 = require("zod");
|
|
5
5
|
const constants_1 = require("../constants");
|
|
6
6
|
exports.AiModelConfigParameterSchema = zod_1.z.object({
|
|
@@ -32,6 +32,12 @@ exports.AiModelImageStyleParameter = zod_1.z.object({
|
|
|
32
32
|
exports.AiModelWebSearchParameter = zod_1.z.object({
|
|
33
33
|
webSearchPrice: zod_1.z.number(),
|
|
34
34
|
});
|
|
35
|
+
// EXTRA SYMBOLS PRICING
|
|
36
|
+
exports.AiModelExtraSymbolsPricingParameter = zod_1.z.object({
|
|
37
|
+
stepSize: zod_1.z.number(),
|
|
38
|
+
stepPrice: zod_1.z.number(),
|
|
39
|
+
isActive: zod_1.z.boolean(),
|
|
40
|
+
});
|
|
35
41
|
// CONFIG
|
|
36
42
|
exports.AiModelConfigSchema = zod_1.z.object({
|
|
37
43
|
parameters: zod_1.z
|
|
@@ -39,6 +45,7 @@ exports.AiModelConfigSchema = zod_1.z.object({
|
|
|
39
45
|
[constants_1.AI_MODEL_CONFIG_PARAM.IMAGE_SIZE]: exports.AiModelImageSizeParameter.optional(),
|
|
40
46
|
[constants_1.AI_MODEL_CONFIG_PARAM.IMAGE_STYLE]: exports.AiModelImageStyleParameter.optional(),
|
|
41
47
|
[constants_1.AI_MODEL_CONFIG_PARAM.WEB_SEARCH]: exports.AiModelWebSearchParameter.optional(),
|
|
48
|
+
[constants_1.AI_MODEL_CONFIG_PARAM.EXTRA_SYMBOLS_PRICING]: exports.AiModelExtraSymbolsPricingParameter.optional(),
|
|
42
49
|
})
|
|
43
50
|
.strict(),
|
|
44
51
|
});
|
package/build/models/index.js
CHANGED
|
@@ -49,6 +49,7 @@ __exportStar(require("./subscription.schema"), exports);
|
|
|
49
49
|
__exportStar(require("./telegram-user-data.schema"), exports);
|
|
50
50
|
__exportStar(require("./tool-job.schema"), exports);
|
|
51
51
|
__exportStar(require("./tool.schema"), exports);
|
|
52
|
+
__exportStar(require("./unlocked-by-subscription.schema"), exports);
|
|
52
53
|
__exportStar(require("./unregistered-user.schema"), exports);
|
|
53
54
|
__exportStar(require("./user-task.schema"), exports);
|
|
54
55
|
__exportStar(require("./user-to-product.schema"), exports);
|
|
@@ -1,49 +1,80 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.SubscriptionFeatureSchema = exports.WebSearchFeatureSchema = exports.MaxInputLengthFeatureSchema = exports.RequestsQuotaFeatureSchema = exports.AiModelAccessFeatureSchema = exports.SubscriptionFeatureBaseSchema = void 0;
|
|
3
|
+
exports.SubscriptionFeatureSchema = exports.STTQuotaFeatureSchema = exports.STTModelAccessFeatureSchema = exports.TTSQuotaFeatureSchema = exports.ImageGenerationQuotaFeatureSchema = exports.TtsModelAccessFeatureSchema = exports.AdvancedToolsAccessFeatureSchema = exports.WebSearchFeatureSchema = exports.MaxInputLengthFeatureSchema = exports.RequestsQuotaFeatureSchema = exports.AiModelAccessFeatureSchema = exports.SubscriptionFeatureBaseSchema = void 0;
|
|
4
4
|
const constants_1 = require("../constants");
|
|
5
5
|
const zod_1 = require("zod");
|
|
6
6
|
exports.SubscriptionFeatureBaseSchema = zod_1.z.object({
|
|
7
|
-
|
|
8
|
-
iconVariants: zod_1.z.object({
|
|
9
|
-
light: zod_1.z.object({
|
|
10
|
-
svg: zod_1.z.string(),
|
|
11
|
-
png: zod_1.z.string(),
|
|
12
|
-
}),
|
|
13
|
-
dark: zod_1.z.object({
|
|
14
|
-
svg: zod_1.z.string(),
|
|
15
|
-
png: zod_1.z.string(),
|
|
16
|
-
}),
|
|
17
|
-
}),
|
|
7
|
+
kind: zod_1.z.nativeEnum(constants_1.SUBSCRIPTION_FEATURE_KIND),
|
|
18
8
|
type: zod_1.z.nativeEnum(constants_1.SUBSCRIPTION_FEATURE_TYPE),
|
|
9
|
+
title: zod_1.z.string(),
|
|
19
10
|
});
|
|
20
11
|
exports.AiModelAccessFeatureSchema = exports.SubscriptionFeatureBaseSchema.extend({
|
|
21
12
|
type: zod_1.z.literal(constants_1.SUBSCRIPTION_FEATURE_TYPE.AI_MODEL_ACCESS),
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
13
|
+
kind: zod_1.z.literal(constants_1.SUBSCRIPTION_FEATURE_KIND.AI_MODEL),
|
|
14
|
+
order: zod_1.z.number(),
|
|
15
|
+
modelId: zod_1.z.string(),
|
|
16
|
+
contentType: zod_1.z.nativeEnum(constants_1.AI_MODEL_CONTENT_TYPE),
|
|
17
|
+
isAvailable: zod_1.z.boolean(),
|
|
18
|
+
maxInputLength: zod_1.z.number(),
|
|
28
19
|
});
|
|
29
20
|
exports.RequestsQuotaFeatureSchema = exports.SubscriptionFeatureBaseSchema.extend({
|
|
30
|
-
type: zod_1.z.literal(constants_1.SUBSCRIPTION_FEATURE_TYPE.
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
21
|
+
type: zod_1.z.literal(constants_1.SUBSCRIPTION_FEATURE_TYPE.TEXT_GENERATION_QUOTA),
|
|
22
|
+
kind: zod_1.z.literal(constants_1.SUBSCRIPTION_FEATURE_KIND.TEXT),
|
|
23
|
+
value: zod_1.z.number(),
|
|
24
|
+
tooltip: zod_1.z.string().nullable(),
|
|
34
25
|
});
|
|
35
26
|
exports.MaxInputLengthFeatureSchema = exports.SubscriptionFeatureBaseSchema.extend({
|
|
36
27
|
type: zod_1.z.literal(constants_1.SUBSCRIPTION_FEATURE_TYPE.MAX_INPUT_LENGTH),
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
28
|
+
kind: zod_1.z.literal(constants_1.SUBSCRIPTION_FEATURE_KIND.TEXT),
|
|
29
|
+
tooltip: zod_1.z.string(),
|
|
30
|
+
value: zod_1.z.number(),
|
|
40
31
|
});
|
|
41
32
|
exports.WebSearchFeatureSchema = exports.SubscriptionFeatureBaseSchema.extend({
|
|
33
|
+
kind: zod_1.z.literal(constants_1.SUBSCRIPTION_FEATURE_KIND.TEXT),
|
|
42
34
|
type: zod_1.z.literal(constants_1.SUBSCRIPTION_FEATURE_TYPE.WEB_SEARCH),
|
|
35
|
+
isAvailable: zod_1.z.boolean(),
|
|
36
|
+
});
|
|
37
|
+
exports.AdvancedToolsAccessFeatureSchema = exports.SubscriptionFeatureBaseSchema.extend({
|
|
38
|
+
kind: zod_1.z.literal(constants_1.SUBSCRIPTION_FEATURE_KIND.TEXT),
|
|
39
|
+
type: zod_1.z.literal(constants_1.SUBSCRIPTION_FEATURE_TYPE.ADVANCED_TOOLS_ACCESS),
|
|
40
|
+
isAvailable: zod_1.z.boolean(),
|
|
41
|
+
});
|
|
42
|
+
exports.TtsModelAccessFeatureSchema = exports.SubscriptionFeatureBaseSchema.extend({
|
|
43
|
+
kind: zod_1.z.literal(constants_1.SUBSCRIPTION_FEATURE_KIND.TTS),
|
|
44
|
+
type: zod_1.z.literal(constants_1.SUBSCRIPTION_FEATURE_TYPE.TTS_MODEL_ACCESS),
|
|
45
|
+
isAvailable: zod_1.z.boolean(),
|
|
46
|
+
modelId: zod_1.z.string(),
|
|
47
|
+
});
|
|
48
|
+
exports.ImageGenerationQuotaFeatureSchema = exports.SubscriptionFeatureBaseSchema.extend({
|
|
49
|
+
kind: zod_1.z.literal(constants_1.SUBSCRIPTION_FEATURE_KIND.IMAGE),
|
|
50
|
+
type: zod_1.z.literal(constants_1.SUBSCRIPTION_FEATURE_TYPE.IMAGE_GENERATION_QUOTA),
|
|
51
|
+
value: zod_1.z.number(),
|
|
52
|
+
});
|
|
53
|
+
exports.TTSQuotaFeatureSchema = exports.SubscriptionFeatureBaseSchema.extend({
|
|
54
|
+
kind: zod_1.z.literal(constants_1.SUBSCRIPTION_FEATURE_KIND.TTS),
|
|
55
|
+
type: zod_1.z.literal(constants_1.SUBSCRIPTION_FEATURE_TYPE.TTS_QUOTA),
|
|
56
|
+
value: zod_1.z.number(),
|
|
57
|
+
});
|
|
58
|
+
exports.STTModelAccessFeatureSchema = exports.SubscriptionFeatureBaseSchema.extend({
|
|
59
|
+
kind: zod_1.z.literal(constants_1.SUBSCRIPTION_FEATURE_KIND.STT),
|
|
60
|
+
type: zod_1.z.literal(constants_1.SUBSCRIPTION_FEATURE_TYPE.STT_MODEL_ACCESS),
|
|
61
|
+
isAvailable: zod_1.z.boolean(),
|
|
62
|
+
modelId: zod_1.z.string(),
|
|
63
|
+
});
|
|
64
|
+
exports.STTQuotaFeatureSchema = exports.SubscriptionFeatureBaseSchema.extend({
|
|
65
|
+
kind: zod_1.z.literal(constants_1.SUBSCRIPTION_FEATURE_KIND.STT),
|
|
66
|
+
type: zod_1.z.literal(constants_1.SUBSCRIPTION_FEATURE_TYPE.STT_QUOTA),
|
|
67
|
+
value: zod_1.z.number(),
|
|
43
68
|
});
|
|
44
69
|
exports.SubscriptionFeatureSchema = zod_1.z.union([
|
|
45
70
|
exports.AiModelAccessFeatureSchema,
|
|
46
71
|
exports.RequestsQuotaFeatureSchema,
|
|
47
72
|
exports.MaxInputLengthFeatureSchema,
|
|
48
73
|
exports.WebSearchFeatureSchema,
|
|
74
|
+
exports.AdvancedToolsAccessFeatureSchema,
|
|
75
|
+
exports.TtsModelAccessFeatureSchema,
|
|
76
|
+
exports.ImageGenerationQuotaFeatureSchema,
|
|
77
|
+
exports.TTSQuotaFeatureSchema,
|
|
78
|
+
exports.STTModelAccessFeatureSchema,
|
|
79
|
+
exports.STTQuotaFeatureSchema,
|
|
49
80
|
]);
|
|
@@ -2,10 +2,13 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ParaphraseModelSchema = void 0;
|
|
4
4
|
const zod_1 = require("zod");
|
|
5
|
+
const unlocked_by_subscription_schema_1 = require("../../unlocked-by-subscription.schema");
|
|
5
6
|
exports.ParaphraseModelSchema = zod_1.z.object({
|
|
6
7
|
uuid: zod_1.z.string().uuid(),
|
|
7
8
|
title: zod_1.z.string(),
|
|
8
9
|
icon: zod_1.z.string(),
|
|
9
10
|
price: zod_1.z.number(),
|
|
10
11
|
order: zod_1.z.number(),
|
|
12
|
+
canUse: zod_1.z.boolean(),
|
|
13
|
+
unlockedBy: unlocked_by_subscription_schema_1.UnlockedBySchema.nullable(),
|
|
11
14
|
});
|
|
@@ -2,9 +2,12 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ParaphraseStyleSchema = void 0;
|
|
4
4
|
const zod_1 = require("zod");
|
|
5
|
+
const unlocked_by_subscription_schema_1 = require("../../unlocked-by-subscription.schema");
|
|
5
6
|
exports.ParaphraseStyleSchema = zod_1.z.object({
|
|
6
7
|
uuid: zod_1.z.string().uuid(),
|
|
7
8
|
title: zod_1.z.string(),
|
|
8
9
|
icon: zod_1.z.string(),
|
|
9
10
|
order: zod_1.z.number(),
|
|
11
|
+
canUse: zod_1.z.boolean(),
|
|
12
|
+
unlockedBy: unlocked_by_subscription_schema_1.UnlockedBySchema.nullable(),
|
|
10
13
|
});
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.STTModelSchema = void 0;
|
|
4
4
|
const zod_1 = require("zod");
|
|
5
5
|
const icon_variants_schema_1 = require("../../icon-variants.schema");
|
|
6
|
+
const unlocked_by_subscription_schema_1 = require("../../unlocked-by-subscription.schema");
|
|
6
7
|
exports.STTModelSchema = zod_1.z.object({
|
|
7
8
|
uuid: zod_1.z.string(),
|
|
8
9
|
title: zod_1.z.string(),
|
|
@@ -12,4 +13,6 @@ exports.STTModelSchema = zod_1.z.object({
|
|
|
12
13
|
icons: icon_variants_schema_1.IconVariantsSchema,
|
|
13
14
|
maxDurationSeconds: zod_1.z.number(),
|
|
14
15
|
maxSizeMB: zod_1.z.number(),
|
|
16
|
+
unlockedBy: unlocked_by_subscription_schema_1.UnlockedBySchema.nullable(),
|
|
17
|
+
canUse: zod_1.z.boolean(),
|
|
15
18
|
});
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.TTSModelSchema = exports.TTSModelParams = exports.TTSSliderSchema = exports.TTSVoiceSchema = void 0;
|
|
4
4
|
const zod_1 = require("zod");
|
|
5
5
|
const icon_variants_schema_1 = require("../../icon-variants.schema");
|
|
6
|
+
const unlocked_by_subscription_schema_1 = require("../../unlocked-by-subscription.schema");
|
|
6
7
|
exports.TTSVoiceSchema = zod_1.z.object({
|
|
7
8
|
id: zod_1.z.string(),
|
|
8
9
|
icon: zod_1.z.string(),
|
|
@@ -46,4 +47,6 @@ exports.TTSModelSchema = zod_1.z.object({
|
|
|
46
47
|
maxInputLength: zod_1.z.number(),
|
|
47
48
|
params: exports.TTSModelParams,
|
|
48
49
|
voices: zod_1.z.array(exports.TTSVoiceSchema),
|
|
50
|
+
unlockedBy: unlocked_by_subscription_schema_1.UnlockedBySchema.nullable(),
|
|
51
|
+
canUse: zod_1.z.boolean(),
|
|
49
52
|
});
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.UnlockedBySubscription = exports.UnlockedBySchema = void 0;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
exports.UnlockedBySchema = zod_1.z.object({
|
|
6
|
+
uuid: zod_1.z.string(),
|
|
7
|
+
name: zod_1.z.string(),
|
|
8
|
+
});
|
|
9
|
+
const UnlockedBySubscription = (schema) => schema.extend({
|
|
10
|
+
unlockedBy: exports.UnlockedBySchema.nullable(),
|
|
11
|
+
canUse: zod_1.z.boolean(),
|
|
12
|
+
});
|
|
13
|
+
exports.UnlockedBySubscription = UnlockedBySubscription;
|
|
@@ -1424,4 +1424,24 @@ export const ERRORS = {
|
|
|
1424
1424
|
message: 'Промпт категория не найдена',
|
|
1425
1425
|
httpCode: 404,
|
|
1426
1426
|
},
|
|
1427
|
+
PARAPHRASE_NO_ACCESS_TO_TYPE: {
|
|
1428
|
+
code: 'A307',
|
|
1429
|
+
message: 'Пользователь не имеет доступ к указанному типу инструмента для перефразирования',
|
|
1430
|
+
httpCode: 401,
|
|
1431
|
+
},
|
|
1432
|
+
PARAPHRASE_NO_ACCESS_TO_STYLE: {
|
|
1433
|
+
code: 'A308',
|
|
1434
|
+
message: 'Пользователь не имеет доступ к указанному стилю инструмента для перефразирования',
|
|
1435
|
+
httpCode: 401,
|
|
1436
|
+
},
|
|
1437
|
+
TTS_MODEL_NOT_AVAILABLE: {
|
|
1438
|
+
code: 'A309',
|
|
1439
|
+
message: 'Модель TTS не доступна на текущем тарифе',
|
|
1440
|
+
httpCode: 401,
|
|
1441
|
+
},
|
|
1442
|
+
SUBSCRIPTION_FEATURE_BUILD_ERROR: {
|
|
1443
|
+
code: 'A310',
|
|
1444
|
+
message: 'Произошла ошибка при построении списка функций подписки',
|
|
1445
|
+
httpCode: 500,
|
|
1446
|
+
},
|
|
1427
1447
|
};
|
|
@@ -1,7 +1,22 @@
|
|
|
1
1
|
export enum SUBSCRIPTION_FEATURE_TYPE {
|
|
2
|
-
|
|
2
|
+
TEXT_GENERATION_QUOTA = 'text_generation_quota',
|
|
3
3
|
AI_MODEL_ACCESS = 'ai_model_access',
|
|
4
4
|
MAX_INPUT_LENGTH = 'max_input_length',
|
|
5
5
|
INFO = 'info',
|
|
6
6
|
WEB_SEARCH = 'web_search',
|
|
7
|
+
ADVANCED_TOOLS_ACCESS = 'advanced_tools_access',
|
|
8
|
+
STT_MODEL_ACCESS = 'stt_model_access',
|
|
9
|
+
TTS_MODEL_ACCESS = 'tts_model_access',
|
|
10
|
+
IMAGE_GENERATION_QUOTA = 'image_generation_quota',
|
|
11
|
+
TTS_QUOTA = 'tts_quota',
|
|
12
|
+
STT_QUOTA = 'stt_quota',
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export enum SUBSCRIPTION_FEATURE_KIND {
|
|
16
|
+
TEXT = 'text',
|
|
17
|
+
AI_MODEL = 'ai_model',
|
|
18
|
+
IMAGE = 'image',
|
|
19
|
+
TTS = 'tts',
|
|
20
|
+
STT = 'stt',
|
|
21
|
+
PRESENTATIONS = 'presentations',
|
|
7
22
|
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export function calcBaseTextGenerationPrice({
|
|
2
|
+
symbolsInRequest,
|
|
3
|
+
defaultPrice,
|
|
4
|
+
config,
|
|
5
|
+
}: {
|
|
6
|
+
symbolsInRequest: number;
|
|
7
|
+
defaultPrice: number;
|
|
8
|
+
config: { stepSize: number; stepPrice: number } | null;
|
|
9
|
+
}) {
|
|
10
|
+
if (!config) {
|
|
11
|
+
return defaultPrice;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const { stepSize, stepPrice } = config;
|
|
15
|
+
|
|
16
|
+
if (symbolsInRequest <= stepSize) {
|
|
17
|
+
return defaultPrice;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const symbolsBeyondFirstStep = symbolsInRequest - stepSize;
|
|
21
|
+
const additionalSteps = Math.ceil(symbolsBeyondFirstStep / stepSize);
|
|
22
|
+
|
|
23
|
+
return defaultPrice + Math.ceil(additionalSteps * stepPrice);
|
|
24
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './calc-base-text-generation-price.helper';
|
package/helpers/index.ts
CHANGED
|
@@ -39,6 +39,13 @@ export const AiModelWebSearchParameter = z.object({
|
|
|
39
39
|
webSearchPrice: z.number(),
|
|
40
40
|
});
|
|
41
41
|
|
|
42
|
+
// EXTRA SYMBOLS PRICING
|
|
43
|
+
export const AiModelExtraSymbolsPricingParameter = z.object({
|
|
44
|
+
stepSize: z.number(),
|
|
45
|
+
stepPrice: z.number(),
|
|
46
|
+
isActive: z.boolean(),
|
|
47
|
+
});
|
|
48
|
+
|
|
42
49
|
// CONFIG
|
|
43
50
|
|
|
44
51
|
export const AiModelConfigSchema = z.object({
|
|
@@ -47,6 +54,8 @@ export const AiModelConfigSchema = z.object({
|
|
|
47
54
|
[AI_MODEL_CONFIG_PARAM.IMAGE_SIZE]: AiModelImageSizeParameter.optional(),
|
|
48
55
|
[AI_MODEL_CONFIG_PARAM.IMAGE_STYLE]: AiModelImageStyleParameter.optional(),
|
|
49
56
|
[AI_MODEL_CONFIG_PARAM.WEB_SEARCH]: AiModelWebSearchParameter.optional(),
|
|
57
|
+
[AI_MODEL_CONFIG_PARAM.EXTRA_SYMBOLS_PRICING]:
|
|
58
|
+
AiModelExtraSymbolsPricingParameter.optional(),
|
|
50
59
|
})
|
|
51
60
|
.strict(),
|
|
52
61
|
});
|
|
@@ -57,4 +66,7 @@ export type AiModelImageSizeParameter = z.infer<typeof AiModelImageSizeParameter
|
|
|
57
66
|
export type AiModelImageStyleOption = z.infer<typeof AiModelImageStyleOptionSchema>;
|
|
58
67
|
export type AiModelImageStyleParameter = z.infer<typeof AiModelImageStyleParameter>;
|
|
59
68
|
export type AiModelWebSeachParameter = z.infer<typeof AiModelWebSearchParameter>;
|
|
69
|
+
export type AiModelExtraSymbolsPricingParameter = z.infer<
|
|
70
|
+
typeof AiModelExtraSymbolsPricingParameter
|
|
71
|
+
>;
|
|
60
72
|
export type AiModelConfig = z.infer<typeof AiModelConfigSchema>;
|
package/models/index.ts
CHANGED
|
@@ -33,6 +33,7 @@ export * from './subscription.schema';
|
|
|
33
33
|
export * from './telegram-user-data.schema';
|
|
34
34
|
export * from './tool-job.schema';
|
|
35
35
|
export * from './tool.schema';
|
|
36
|
+
export * from './unlocked-by-subscription.schema';
|
|
36
37
|
export * from './unregistered-user.schema';
|
|
37
38
|
export * from './user-task.schema';
|
|
38
39
|
export * from './user-to-product.schema';
|
|
@@ -1,54 +1,106 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
AI_MODEL_CONTENT_TYPE,
|
|
3
|
+
SUBSCRIPTION_FEATURE_KIND,
|
|
4
|
+
SUBSCRIPTION_FEATURE_TYPE,
|
|
5
|
+
} from '../constants';
|
|
2
6
|
import { z } from 'zod';
|
|
3
7
|
|
|
4
8
|
export const SubscriptionFeatureBaseSchema = z.object({
|
|
5
|
-
|
|
6
|
-
iconVariants: z.object({
|
|
7
|
-
light: z.object({
|
|
8
|
-
svg: z.string(),
|
|
9
|
-
png: z.string(),
|
|
10
|
-
}),
|
|
11
|
-
dark: z.object({
|
|
12
|
-
svg: z.string(),
|
|
13
|
-
png: z.string(),
|
|
14
|
-
}),
|
|
15
|
-
}),
|
|
9
|
+
kind: z.nativeEnum(SUBSCRIPTION_FEATURE_KIND),
|
|
16
10
|
type: z.nativeEnum(SUBSCRIPTION_FEATURE_TYPE),
|
|
11
|
+
title: z.string(),
|
|
17
12
|
});
|
|
13
|
+
export type SubscriptionFeatureBase = z.infer<typeof SubscriptionFeatureBaseSchema>;
|
|
18
14
|
|
|
19
15
|
export const AiModelAccessFeatureSchema = SubscriptionFeatureBaseSchema.extend({
|
|
20
16
|
type: z.literal(SUBSCRIPTION_FEATURE_TYPE.AI_MODEL_ACCESS),
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
17
|
+
kind: z.literal(SUBSCRIPTION_FEATURE_KIND.AI_MODEL),
|
|
18
|
+
order: z.number(),
|
|
19
|
+
modelId: z.string(),
|
|
20
|
+
contentType: z.nativeEnum(AI_MODEL_CONTENT_TYPE),
|
|
21
|
+
isAvailable: z.boolean(),
|
|
22
|
+
maxInputLength: z.number(),
|
|
27
23
|
});
|
|
24
|
+
export type AiModelAccessFeature = z.infer<typeof AiModelAccessFeatureSchema>;
|
|
28
25
|
|
|
29
26
|
export const RequestsQuotaFeatureSchema = SubscriptionFeatureBaseSchema.extend({
|
|
30
|
-
type: z.literal(SUBSCRIPTION_FEATURE_TYPE.
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
27
|
+
type: z.literal(SUBSCRIPTION_FEATURE_TYPE.TEXT_GENERATION_QUOTA),
|
|
28
|
+
kind: z.literal(SUBSCRIPTION_FEATURE_KIND.TEXT),
|
|
29
|
+
value: z.number(),
|
|
30
|
+
tooltip: z.string().nullable(),
|
|
34
31
|
});
|
|
32
|
+
export type RequestsQuotaFeature = z.infer<typeof RequestsQuotaFeatureSchema>;
|
|
35
33
|
|
|
36
34
|
export const MaxInputLengthFeatureSchema = SubscriptionFeatureBaseSchema.extend({
|
|
37
35
|
type: z.literal(SUBSCRIPTION_FEATURE_TYPE.MAX_INPUT_LENGTH),
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
36
|
+
kind: z.literal(SUBSCRIPTION_FEATURE_KIND.TEXT),
|
|
37
|
+
tooltip: z.string(),
|
|
38
|
+
value: z.number(),
|
|
41
39
|
});
|
|
40
|
+
export type MaxInputLengthFeature = z.infer<typeof MaxInputLengthFeatureSchema>;
|
|
42
41
|
|
|
43
42
|
export const WebSearchFeatureSchema = SubscriptionFeatureBaseSchema.extend({
|
|
43
|
+
kind: z.literal(SUBSCRIPTION_FEATURE_KIND.TEXT),
|
|
44
44
|
type: z.literal(SUBSCRIPTION_FEATURE_TYPE.WEB_SEARCH),
|
|
45
|
+
isAvailable: z.boolean(),
|
|
46
|
+
});
|
|
47
|
+
export type WebSearchFeature = z.infer<typeof WebSearchFeatureSchema>;
|
|
48
|
+
|
|
49
|
+
export const AdvancedToolsAccessFeatureSchema = SubscriptionFeatureBaseSchema.extend({
|
|
50
|
+
kind: z.literal(SUBSCRIPTION_FEATURE_KIND.TEXT),
|
|
51
|
+
type: z.literal(SUBSCRIPTION_FEATURE_TYPE.ADVANCED_TOOLS_ACCESS),
|
|
52
|
+
isAvailable: z.boolean(),
|
|
53
|
+
});
|
|
54
|
+
export type AdvancedToolsAccessFeature = z.infer<typeof AdvancedToolsAccessFeatureSchema>;
|
|
55
|
+
|
|
56
|
+
export const TtsModelAccessFeatureSchema = SubscriptionFeatureBaseSchema.extend({
|
|
57
|
+
kind: z.literal(SUBSCRIPTION_FEATURE_KIND.TTS),
|
|
58
|
+
type: z.literal(SUBSCRIPTION_FEATURE_TYPE.TTS_MODEL_ACCESS),
|
|
59
|
+
isAvailable: z.boolean(),
|
|
60
|
+
modelId: z.string(),
|
|
61
|
+
});
|
|
62
|
+
export type TtsModelAccessFeature = z.infer<typeof TtsModelAccessFeatureSchema>;
|
|
63
|
+
|
|
64
|
+
export const ImageGenerationQuotaFeatureSchema = SubscriptionFeatureBaseSchema.extend({
|
|
65
|
+
kind: z.literal(SUBSCRIPTION_FEATURE_KIND.IMAGE),
|
|
66
|
+
type: z.literal(SUBSCRIPTION_FEATURE_TYPE.IMAGE_GENERATION_QUOTA),
|
|
67
|
+
value: z.number(),
|
|
68
|
+
});
|
|
69
|
+
export type ImageGenerationQuotaFeature = z.infer<typeof ImageGenerationQuotaFeatureSchema>;
|
|
70
|
+
|
|
71
|
+
export const TTSQuotaFeatureSchema = SubscriptionFeatureBaseSchema.extend({
|
|
72
|
+
kind: z.literal(SUBSCRIPTION_FEATURE_KIND.TTS),
|
|
73
|
+
type: z.literal(SUBSCRIPTION_FEATURE_TYPE.TTS_QUOTA),
|
|
74
|
+
value: z.number(),
|
|
75
|
+
});
|
|
76
|
+
export type TTSQuotaFeature = z.infer<typeof TTSQuotaFeatureSchema>;
|
|
77
|
+
|
|
78
|
+
export const STTModelAccessFeatureSchema = SubscriptionFeatureBaseSchema.extend({
|
|
79
|
+
kind: z.literal(SUBSCRIPTION_FEATURE_KIND.STT),
|
|
80
|
+
type: z.literal(SUBSCRIPTION_FEATURE_TYPE.STT_MODEL_ACCESS),
|
|
81
|
+
isAvailable: z.boolean(),
|
|
82
|
+
modelId: z.string(),
|
|
83
|
+
});
|
|
84
|
+
export type STTModelAccessFeature = z.infer<typeof STTModelAccessFeatureSchema>;
|
|
85
|
+
|
|
86
|
+
export const STTQuotaFeatureSchema = SubscriptionFeatureBaseSchema.extend({
|
|
87
|
+
kind: z.literal(SUBSCRIPTION_FEATURE_KIND.STT),
|
|
88
|
+
type: z.literal(SUBSCRIPTION_FEATURE_TYPE.STT_QUOTA),
|
|
89
|
+
value: z.number(),
|
|
45
90
|
});
|
|
91
|
+
export type STTQuotaFeature = z.infer<typeof STTQuotaFeatureSchema>;
|
|
46
92
|
|
|
47
93
|
export const SubscriptionFeatureSchema = z.union([
|
|
48
94
|
AiModelAccessFeatureSchema,
|
|
49
95
|
RequestsQuotaFeatureSchema,
|
|
50
96
|
MaxInputLengthFeatureSchema,
|
|
51
97
|
WebSearchFeatureSchema,
|
|
98
|
+
AdvancedToolsAccessFeatureSchema,
|
|
99
|
+
TtsModelAccessFeatureSchema,
|
|
100
|
+
ImageGenerationQuotaFeatureSchema,
|
|
101
|
+
TTSQuotaFeatureSchema,
|
|
102
|
+
STTModelAccessFeatureSchema,
|
|
103
|
+
STTQuotaFeatureSchema,
|
|
52
104
|
]);
|
|
53
105
|
|
|
54
106
|
export type SubscriptionFeature = z.infer<typeof SubscriptionFeatureSchema>;
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { ParaphraseStyleSchema } from './paraphrase-style.schema';
|
|
3
3
|
import { ParaphraseModelSchema } from './paraphrase-model.schema';
|
|
4
|
-
|
|
5
4
|
export const ParaphraseToolConfigSchema = z.object({
|
|
6
5
|
maxSymbols: z.number(),
|
|
7
6
|
styles: z.array(ParaphraseStyleSchema),
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
+
import { UnlockedBySchema } from '../../unlocked-by-subscription.schema';
|
|
2
3
|
|
|
3
4
|
export const ParaphraseModelSchema = z.object({
|
|
4
5
|
uuid: z.string().uuid(),
|
|
@@ -6,4 +7,6 @@ export const ParaphraseModelSchema = z.object({
|
|
|
6
7
|
icon: z.string(),
|
|
7
8
|
price: z.number(),
|
|
8
9
|
order: z.number(),
|
|
10
|
+
canUse: z.boolean(),
|
|
11
|
+
unlockedBy: UnlockedBySchema.nullable(),
|
|
9
12
|
});
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
+
import { UnlockedBySchema } from '../../unlocked-by-subscription.schema';
|
|
2
3
|
|
|
3
4
|
export const ParaphraseStyleSchema = z.object({
|
|
4
5
|
uuid: z.string().uuid(),
|
|
5
6
|
title: z.string(),
|
|
6
7
|
icon: z.string(),
|
|
7
8
|
order: z.number(),
|
|
9
|
+
canUse: z.boolean(),
|
|
10
|
+
unlockedBy: UnlockedBySchema.nullable(),
|
|
8
11
|
});
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { IconVariantsSchema } from '../../icon-variants.schema';
|
|
3
|
+
import { UnlockedBySchema } from '../../unlocked-by-subscription.schema';
|
|
3
4
|
|
|
4
5
|
export const STTModelSchema = z.object({
|
|
5
6
|
uuid: z.string(),
|
|
@@ -10,6 +11,8 @@ export const STTModelSchema = z.object({
|
|
|
10
11
|
icons: IconVariantsSchema,
|
|
11
12
|
maxDurationSeconds: z.number(),
|
|
12
13
|
maxSizeMB: z.number(),
|
|
14
|
+
unlockedBy: UnlockedBySchema.nullable(),
|
|
15
|
+
canUse: z.boolean(),
|
|
13
16
|
});
|
|
14
17
|
|
|
15
18
|
export type STTModel = z.infer<typeof STTModelSchema>;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { IconVariantsSchema } from '../../icon-variants.schema';
|
|
3
|
+
import { UnlockedBySchema } from '../../unlocked-by-subscription.schema';
|
|
3
4
|
|
|
4
5
|
export const TTSVoiceSchema = z.object({
|
|
5
6
|
id: z.string(),
|
|
@@ -49,4 +50,6 @@ export const TTSModelSchema = z.object({
|
|
|
49
50
|
maxInputLength: z.number(),
|
|
50
51
|
params: TTSModelParams,
|
|
51
52
|
voices: z.array(TTSVoiceSchema),
|
|
53
|
+
unlockedBy: UnlockedBySchema.nullable(),
|
|
54
|
+
canUse: z.boolean(),
|
|
52
55
|
});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
export const UnlockedBySchema = z.object({
|
|
4
|
+
uuid: z.string(),
|
|
5
|
+
name: z.string(),
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
export type UnlockedBy = z.infer<typeof UnlockedBySchema>;
|
|
9
|
+
|
|
10
|
+
export const UnlockedBySubscription = <T extends z.ZodObject<any>>(schema: T) =>
|
|
11
|
+
schema.extend({
|
|
12
|
+
unlockedBy: UnlockedBySchema.nullable(),
|
|
13
|
+
canUse: z.boolean(),
|
|
14
|
+
});
|