@casual-simulation/aux-records 3.4.6-alpha.14601027727 → 3.5.0-alpha.15117651144
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/AIController.js +835 -890
- package/AIController.js.map +1 -1
- package/AIHumeInterface.js +43 -54
- package/AIHumeInterface.js.map +1 -1
- package/AIOpenAIRealtimeInterface.js +60 -71
- package/AIOpenAIRealtimeInterface.js.map +1 -1
- package/AnthropicAIChatInterface.js +96 -142
- package/AnthropicAIChatInterface.js.map +1 -1
- package/AuthController.d.ts +3 -2
- package/AuthController.js +1907 -1933
- package/AuthController.js.map +1 -1
- package/AuthStore.d.ts +1 -10
- package/BlockadeLabsGenerateSkyboxInterface.js +57 -72
- package/BlockadeLabsGenerateSkyboxInterface.js.map +1 -1
- package/CachingConfigStore.js +30 -45
- package/CachingConfigStore.js.map +1 -1
- package/CachingPolicyStore.d.ts +8 -2
- package/CachingPolicyStore.js +108 -135
- package/CachingPolicyStore.js.map +1 -1
- package/ComIdConfig.d.ts +18 -18
- package/ComIdConfig.js.map +1 -1
- package/ConsoleAuthMessenger.js +7 -20
- package/ConsoleAuthMessenger.js.map +1 -1
- package/DataRecordsController.d.ts +2 -2
- package/DataRecordsController.js +369 -377
- package/DataRecordsController.js.map +1 -1
- package/DataRecordsStore.d.ts +1 -1
- package/DataRecordsStore.js +1 -1
- package/DataRecordsStore.js.map +1 -1
- package/EventRecordsController.js +226 -240
- package/EventRecordsController.js.map +1 -1
- package/FileRecordsController.d.ts +13 -2
- package/FileRecordsController.js +458 -450
- package/FileRecordsController.js.map +1 -1
- package/GoogleAIChatInterface.js +133 -179
- package/GoogleAIChatInterface.js.map +1 -1
- package/LivekitController.js +43 -54
- package/LivekitController.js.map +1 -1
- package/LoomController.js +64 -75
- package/LoomController.js.map +1 -1
- package/MemoryAuthMessenger.js +10 -23
- package/MemoryAuthMessenger.js.map +1 -1
- package/MemoryCache.js +18 -35
- package/MemoryCache.js.map +1 -1
- package/MemoryFileRecordsLookup.js +105 -125
- package/MemoryFileRecordsLookup.js.map +1 -1
- package/MemoryModerationJobProvider.js +17 -30
- package/MemoryModerationJobProvider.js.map +1 -1
- package/MemoryRateLimiter.js +12 -27
- package/MemoryRateLimiter.js.map +1 -1
- package/MemoryStore.d.ts +18 -6
- package/MemoryStore.js +1879 -1997
- package/MemoryStore.js.map +1 -1
- package/MetricsStore.d.ts +2 -2
- package/ModerationController.js +186 -200
- package/ModerationController.js.map +1 -1
- package/OpenAIChatInterface.js +105 -135
- package/OpenAIChatInterface.js.map +1 -1
- package/OpenAIImageInterface.js +57 -51
- package/OpenAIImageInterface.js.map +1 -1
- package/PolicyController.d.ts +150 -10
- package/PolicyController.js +1546 -1299
- package/PolicyController.js.map +1 -1
- package/PolicyStore.d.ts +110 -2
- package/PolicyStore.js +36 -1
- package/PolicyStore.js.map +1 -1
- package/PrivoClient.js +398 -435
- package/PrivoClient.js.map +1 -1
- package/RateLimitController.js +25 -36
- package/RateLimitController.js.map +1 -1
- package/RecordsClient.js +51 -74
- package/RecordsClient.js.map +1 -1
- package/RecordsController.d.ts +2 -42
- package/RecordsController.js +1026 -1182
- package/RecordsController.js.map +1 -1
- package/RecordsServer.d.ts +196 -27
- package/RecordsServer.js +1701 -1343
- package/RecordsServer.js.map +1 -1
- package/RecordsStore.d.ts +1 -10
- package/RecordsStore.js.map +1 -1
- package/ServerConfig.d.ts +339 -195
- package/ServerConfig.js +13 -0
- package/ServerConfig.js.map +1 -1
- package/SloydInterface.js +62 -75
- package/SloydInterface.js.map +1 -1
- package/StabilityAIImageInterface.js +150 -167
- package/StabilityAIImageInterface.js.map +1 -1
- package/SubscriptionConfigBuilder.d.ts +6 -1
- package/SubscriptionConfigBuilder.js +22 -0
- package/SubscriptionConfigBuilder.js.map +1 -1
- package/SubscriptionConfiguration.d.ts +266 -169
- package/SubscriptionConfiguration.js +101 -79
- package/SubscriptionConfiguration.js.map +1 -1
- package/SubscriptionController.d.ts +2 -1
- package/SubscriptionController.js +643 -650
- package/SubscriptionController.js.map +1 -1
- package/SystemNotificationMessenger.d.ts +21 -4
- package/SystemNotificationMessenger.js +36 -30
- package/SystemNotificationMessenger.js.map +1 -1
- package/TestUtils.d.ts +9 -1
- package/TestUtils.js +105 -129
- package/TestUtils.js.map +1 -1
- package/Utils.d.ts +2 -16
- package/Utils.js +21 -22
- package/Utils.js.map +1 -1
- package/crud/CrudHelpers.js +17 -26
- package/crud/CrudHelpers.js.map +1 -1
- package/crud/CrudRecordsController.d.ts +1 -1
- package/crud/CrudRecordsController.js +259 -267
- package/crud/CrudRecordsController.js.map +1 -1
- package/crud/CrudRecordsControllerTests.js +174 -185
- package/crud/CrudRecordsControllerTests.js.map +1 -1
- package/crud/CrudRecordsStore.d.ts +7 -3
- package/crud/MemoryCrudRecordsStore.d.ts +4 -4
- package/crud/MemoryCrudRecordsStore.js +98 -118
- package/crud/MemoryCrudRecordsStore.js.map +1 -1
- package/crud/sub/MemorySubCrudRecordsStore.d.ts +24 -0
- package/crud/sub/MemorySubCrudRecordsStore.js +146 -0
- package/crud/sub/MemorySubCrudRecordsStore.js.map +1 -0
- package/crud/sub/SubCrudRecordsController.d.ts +182 -0
- package/crud/sub/SubCrudRecordsController.js +360 -0
- package/crud/sub/SubCrudRecordsController.js.map +1 -0
- package/crud/sub/SubCrudRecordsControllerTests.d.ts +39 -0
- package/crud/sub/SubCrudRecordsControllerTests.js +821 -0
- package/crud/sub/SubCrudRecordsControllerTests.js.map +1 -0
- package/crud/sub/SubCrudRecordsStore.d.ts +95 -0
- package/{forms/index.js → crud/sub/SubCrudRecordsStore.js} +2 -2
- package/crud/sub/SubCrudRecordsStore.js.map +1 -0
- package/crud/sub/index.d.ts +3 -0
- package/crud/sub/index.js +20 -0
- package/{forms → crud/sub}/index.js.map +1 -1
- package/index.d.ts +1 -1
- package/index.js +1 -1
- package/index.js.map +1 -1
- package/notifications/MemoryNotificationRecordsStore.js +189 -198
- package/notifications/MemoryNotificationRecordsStore.js.map +1 -1
- package/notifications/NotificationRecordsController.js +438 -460
- package/notifications/NotificationRecordsController.js.map +1 -1
- package/notifications/NotificationRecordsStore.d.ts +2 -1
- package/notifications/WebPushInterface.d.ts +0 -1
- package/notifications/WebPushInterface.js +0 -1
- package/notifications/WebPushInterface.js.map +1 -1
- package/package.json +6 -6
- package/packages/MemoryPackageRecordsStore.d.ts +10 -0
- package/packages/MemoryPackageRecordsStore.js +38 -0
- package/packages/MemoryPackageRecordsStore.js.map +1 -0
- package/packages/PackageRecordsController.d.ts +26 -0
- package/packages/PackageRecordsController.js +49 -0
- package/packages/PackageRecordsController.js.map +1 -0
- package/packages/PackageRecordsStore.d.ts +32 -0
- package/packages/PackageRecordsStore.js +19 -0
- package/packages/PackageRecordsStore.js.map +1 -0
- package/packages/index.d.ts +4 -0
- package/packages/index.js +21 -0
- package/packages/index.js.map +1 -0
- package/packages/version/MemoryPackageVersionRecordsStore.d.ts +21 -0
- package/packages/version/MemoryPackageVersionRecordsStore.js +177 -0
- package/packages/version/MemoryPackageVersionRecordsStore.js.map +1 -0
- package/packages/version/PackageVersionRecordsController.d.ts +144 -0
- package/packages/version/PackageVersionRecordsController.js +656 -0
- package/packages/version/PackageVersionRecordsController.js.map +1 -0
- package/packages/version/PackageVersionRecordsStore.d.ts +342 -0
- package/packages/version/PackageVersionRecordsStore.js +126 -0
- package/packages/version/PackageVersionRecordsStore.js.map +1 -0
- package/packages/version/index.d.ts +4 -0
- package/packages/version/index.js +21 -0
- package/packages/version/index.js.map +1 -0
- package/tracing/TracingDecorators.js +31 -40
- package/tracing/TracingDecorators.js.map +1 -1
- package/webhooks/MemoryWebhookRecordsStore.js +56 -72
- package/webhooks/MemoryWebhookRecordsStore.js.map +1 -1
- package/webhooks/WebhookEnvironment.d.ts +3 -3
- package/webhooks/WebhookRecordsController.d.ts +2 -1
- package/webhooks/WebhookRecordsController.js +389 -382
- package/webhooks/WebhookRecordsController.js.map +1 -1
- package/webhooks/WebhookRecordsStore.d.ts +2 -1
- package/websockets/InstRecordsStore.d.ts +50 -0
- package/websockets/InstRecordsStore.js +17 -0
- package/websockets/InstRecordsStore.js.map +1 -1
- package/websockets/MemoryTempInstRecordsStore.d.ts +5 -0
- package/websockets/MemoryTempInstRecordsStore.js +168 -179
- package/websockets/MemoryTempInstRecordsStore.js.map +1 -1
- package/websockets/MemoryWebsocketConnectionStore.js +98 -135
- package/websockets/MemoryWebsocketConnectionStore.js.map +1 -1
- package/websockets/MemoryWebsocketMessenger.js +29 -48
- package/websockets/MemoryWebsocketMessenger.js.map +1 -1
- package/websockets/SplitInstRecordsStore.d.ts +4 -1
- package/websockets/SplitInstRecordsStore.js +167 -185
- package/websockets/SplitInstRecordsStore.js.map +1 -1
- package/websockets/TemporaryInstRecordsStore.d.ts +19 -1
- package/websockets/TemporaryInstRecordsStore.js +17 -0
- package/websockets/TemporaryInstRecordsStore.js.map +1 -1
- package/websockets/WebsocketController.d.ts +147 -3
- package/websockets/WebsocketController.js +1735 -1391
- package/websockets/WebsocketController.js.map +1 -1
- package/websockets/index.d.ts +0 -1
- package/websockets/index.js +0 -1
- package/websockets/index.js.map +1 -1
- package/AAGUID.d.ts +0 -11
- package/AAGUID.js +0 -116
- package/AAGUID.js.map +0 -1
- package/AuthUtils.d.ts +0 -162
- package/AuthUtils.js +0 -327
- package/AuthUtils.js.map +0 -1
- package/forms/FormError.d.ts +0 -43
- package/forms/FormError.js +0 -56
- package/forms/FormError.js.map +0 -1
- package/forms/index.d.ts +0 -2
- package/websockets/Utils.d.ts +0 -33
- package/websockets/Utils.js +0 -82
- package/websockets/Utils.js.map +0 -1
package/AIController.js
CHANGED
|
@@ -4,35 +4,6 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
4
4
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
5
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
6
|
};
|
|
7
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
8
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
9
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
10
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
11
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
12
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
13
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
14
|
-
});
|
|
15
|
-
};
|
|
16
|
-
var __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); }
|
|
17
|
-
var __asyncValues = (this && this.__asyncValues) || function (o) {
|
|
18
|
-
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
|
|
19
|
-
var m = o[Symbol.asyncIterator], i;
|
|
20
|
-
return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
|
|
21
|
-
function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
|
|
22
|
-
function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
|
|
23
|
-
};
|
|
24
|
-
var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) {
|
|
25
|
-
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
|
|
26
|
-
var g = generator.apply(thisArg, _arguments || []), i, q = [];
|
|
27
|
-
return i = {}, verb("next"), verb("throw"), verb("return", awaitReturn), i[Symbol.asyncIterator] = function () { return this; }, i;
|
|
28
|
-
function awaitReturn(f) { return function (v) { return Promise.resolve(v).then(f, reject); }; }
|
|
29
|
-
function verb(n, f) { if (g[n]) { i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; if (f) i[n] = f(i[n]); } }
|
|
30
|
-
function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }
|
|
31
|
-
function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }
|
|
32
|
-
function fulfill(value) { resume("next", value); }
|
|
33
|
-
function reject(value) { resume("throw", value); }
|
|
34
|
-
function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }
|
|
35
|
-
};
|
|
36
7
|
import { getHumeAiFeatures, getOpenAiFeatures, getSloydAiFeatures, getSubscriptionFeatures, } from './SubscriptionConfiguration';
|
|
37
8
|
import { traced } from './tracing/TracingDecorators';
|
|
38
9
|
import { SpanStatusCode, trace } from '@opentelemetry/api';
|
|
@@ -91,160 +62,158 @@ export class AIController {
|
|
|
91
62
|
this._policyStore = configuration.policies;
|
|
92
63
|
this._recordsStore = configuration.records;
|
|
93
64
|
}
|
|
94
|
-
chat(request) {
|
|
65
|
+
async chat(request) {
|
|
95
66
|
var _a, _b;
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
67
|
+
try {
|
|
68
|
+
if (!this._chatProviders) {
|
|
69
|
+
return {
|
|
70
|
+
success: false,
|
|
71
|
+
errorCode: 'not_supported',
|
|
72
|
+
errorMessage: 'This operation is not supported.',
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
if (!request.userId) {
|
|
76
|
+
return {
|
|
77
|
+
success: false,
|
|
78
|
+
errorCode: 'not_logged_in',
|
|
79
|
+
errorMessage: 'The user must be logged in. Please provide a sessionKey or a recordKey.',
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
if (!this._matchesSubscriptionTiers(request.userSubscriptionTier, this._allowedChatSubscriptionTiers)) {
|
|
83
|
+
if (!request.userSubscriptionTier) {
|
|
106
84
|
return {
|
|
107
85
|
success: false,
|
|
108
|
-
errorCode: '
|
|
109
|
-
errorMessage: 'The user must be
|
|
86
|
+
errorCode: 'not_subscribed',
|
|
87
|
+
errorMessage: 'The user must be subscribed in order to use this operation.',
|
|
88
|
+
allowedSubscriptionTiers: [
|
|
89
|
+
...this
|
|
90
|
+
._allowedChatSubscriptionTiers,
|
|
91
|
+
],
|
|
110
92
|
};
|
|
111
93
|
}
|
|
112
|
-
|
|
113
|
-
if (!request.userSubscriptionTier) {
|
|
114
|
-
return {
|
|
115
|
-
success: false,
|
|
116
|
-
errorCode: 'not_subscribed',
|
|
117
|
-
errorMessage: 'The user must be subscribed in order to use this operation.',
|
|
118
|
-
allowedSubscriptionTiers: [
|
|
119
|
-
...this
|
|
120
|
-
._allowedChatSubscriptionTiers,
|
|
121
|
-
],
|
|
122
|
-
};
|
|
123
|
-
}
|
|
124
|
-
else {
|
|
125
|
-
return {
|
|
126
|
-
success: false,
|
|
127
|
-
errorCode: 'invalid_subscription_tier',
|
|
128
|
-
errorMessage: 'This operation is not available to the user at their current subscription tier.',
|
|
129
|
-
allowedSubscriptionTiers: [
|
|
130
|
-
...this
|
|
131
|
-
._allowedChatSubscriptionTiers,
|
|
132
|
-
],
|
|
133
|
-
currentSubscriptionTier: request.userSubscriptionTier,
|
|
134
|
-
};
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
if (!!request.model &&
|
|
138
|
-
!this._allowedChatModels.has(request.model)) {
|
|
94
|
+
else {
|
|
139
95
|
return {
|
|
140
96
|
success: false,
|
|
141
|
-
errorCode: '
|
|
142
|
-
errorMessage:
|
|
97
|
+
errorCode: 'invalid_subscription_tier',
|
|
98
|
+
errorMessage: 'This operation is not available to the user at their current subscription tier.',
|
|
99
|
+
allowedSubscriptionTiers: [
|
|
100
|
+
...this
|
|
101
|
+
._allowedChatSubscriptionTiers,
|
|
102
|
+
],
|
|
103
|
+
currentSubscriptionTier: request.userSubscriptionTier,
|
|
143
104
|
};
|
|
144
105
|
}
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
106
|
+
}
|
|
107
|
+
if (!!request.model &&
|
|
108
|
+
!this._allowedChatModels.has(request.model)) {
|
|
109
|
+
return {
|
|
110
|
+
success: false,
|
|
111
|
+
errorCode: 'invalid_model',
|
|
112
|
+
errorMessage: `The given model is not allowed for chats.`,
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
const model = (_a = request.model) !== null && _a !== void 0 ? _a : this._chatOptions.defaultModel;
|
|
116
|
+
const provider = (_b = this._allowedChatModels.get(request.model)) !== null && _b !== void 0 ? _b : this._chatOptions.defaultModelProvider;
|
|
117
|
+
const chat = this._chatProviders[provider];
|
|
118
|
+
if (!chat) {
|
|
119
|
+
console.error('[AIController] No chat provider found for model:', model);
|
|
120
|
+
return {
|
|
121
|
+
success: false,
|
|
122
|
+
errorCode: 'not_supported',
|
|
123
|
+
errorMessage: 'The given model is not supported.',
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
console.log('[AIController] Using chat provider:', provider, 'for model:', model);
|
|
128
|
+
}
|
|
129
|
+
const metrics = await this._metrics.getSubscriptionAiChatMetrics({
|
|
130
|
+
ownerId: request.userId,
|
|
131
|
+
});
|
|
132
|
+
const config = await this._config.getSubscriptionConfiguration();
|
|
133
|
+
const allowedFeatures = getSubscriptionFeatures(config, metrics.subscriptionStatus, metrics.subscriptionId, 'user');
|
|
134
|
+
if (!allowedFeatures.ai.chat.allowed) {
|
|
135
|
+
return {
|
|
136
|
+
success: false,
|
|
137
|
+
errorCode: 'not_authorized',
|
|
138
|
+
errorMessage: 'The subscription does not permit AI Chat features.',
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
let maxTokens = undefined;
|
|
142
|
+
if (allowedFeatures.ai.chat.maxTokensPerPeriod) {
|
|
143
|
+
maxTokens =
|
|
144
|
+
allowedFeatures.ai.chat.maxTokensPerPeriod -
|
|
145
|
+
metrics.totalTokensInCurrentPeriod;
|
|
146
|
+
}
|
|
147
|
+
if (maxTokens <= 0) {
|
|
148
|
+
return {
|
|
149
|
+
success: false,
|
|
150
|
+
errorCode: 'subscription_limit_reached',
|
|
151
|
+
errorMessage: `The user has reached their limit for the current subscription period.`,
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
if (allowedFeatures.ai.chat.maxTokensPerRequest) {
|
|
155
|
+
if (maxTokens) {
|
|
156
|
+
maxTokens = Math.min(maxTokens, allowedFeatures.ai.chat.maxTokensPerRequest);
|
|
155
157
|
}
|
|
156
158
|
else {
|
|
157
|
-
|
|
159
|
+
maxTokens = allowedFeatures.ai.chat.maxTokensPerRequest;
|
|
158
160
|
}
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
const allowedFeatures = getSubscriptionFeatures(config, metrics.subscriptionStatus, metrics.subscriptionId, 'user');
|
|
164
|
-
if (!allowedFeatures.ai.chat.allowed) {
|
|
161
|
+
}
|
|
162
|
+
if (this._policyStore) {
|
|
163
|
+
const privacyFeatures = await this._policyStore.getUserPrivacyFeatures(request.userId);
|
|
164
|
+
if (!privacyFeatures.allowAI) {
|
|
165
165
|
return {
|
|
166
166
|
success: false,
|
|
167
167
|
errorCode: 'not_authorized',
|
|
168
|
-
errorMessage: '
|
|
168
|
+
errorMessage: 'AI Access is not allowed',
|
|
169
169
|
};
|
|
170
170
|
}
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
metrics.totalTokensInCurrentPeriod;
|
|
176
|
-
}
|
|
177
|
-
if (maxTokens <= 0) {
|
|
171
|
+
}
|
|
172
|
+
if (allowedFeatures.ai.chat.allowedModels) {
|
|
173
|
+
const allowedModels = allowedFeatures.ai.chat.allowedModels;
|
|
174
|
+
if (!allowedModels.includes(model)) {
|
|
178
175
|
return {
|
|
179
176
|
success: false,
|
|
180
|
-
errorCode: '
|
|
181
|
-
errorMessage:
|
|
177
|
+
errorCode: 'not_authorized',
|
|
178
|
+
errorMessage: 'The subscription does not permit the given model for AI Chat features.',
|
|
182
179
|
};
|
|
183
180
|
}
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
};
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
if (allowedFeatures.ai.chat.allowedModels) {
|
|
203
|
-
const allowedModels = allowedFeatures.ai.chat.allowedModels;
|
|
204
|
-
if (!allowedModels.includes(model)) {
|
|
205
|
-
return {
|
|
206
|
-
success: false,
|
|
207
|
-
errorCode: 'not_authorized',
|
|
208
|
-
errorMessage: 'The subscription does not permit the given model for AI Chat features.',
|
|
209
|
-
};
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
const result = yield chat.chat({
|
|
213
|
-
messages: request.messages,
|
|
214
|
-
model: model,
|
|
215
|
-
temperature: request.temperature,
|
|
216
|
-
topP: request.topP,
|
|
217
|
-
frequencyPenalty: request.frequencyPenalty,
|
|
218
|
-
presencePenalty: request.presencePenalty,
|
|
219
|
-
stopWords: request.stopWords,
|
|
181
|
+
}
|
|
182
|
+
const result = await chat.chat({
|
|
183
|
+
messages: request.messages,
|
|
184
|
+
model: model,
|
|
185
|
+
temperature: request.temperature,
|
|
186
|
+
topP: request.topP,
|
|
187
|
+
frequencyPenalty: request.frequencyPenalty,
|
|
188
|
+
presencePenalty: request.presencePenalty,
|
|
189
|
+
stopWords: request.stopWords,
|
|
190
|
+
userId: request.userId,
|
|
191
|
+
maxTokens,
|
|
192
|
+
});
|
|
193
|
+
if (result.totalTokens > 0) {
|
|
194
|
+
const adjustedTokens = this._calculateTokenCost(result, model);
|
|
195
|
+
await this._metrics.recordChatMetrics({
|
|
220
196
|
userId: request.userId,
|
|
221
|
-
|
|
197
|
+
createdAtMs: Date.now(),
|
|
198
|
+
tokens: adjustedTokens,
|
|
222
199
|
});
|
|
223
|
-
if (result.totalTokens > 0) {
|
|
224
|
-
const adjustedTokens = this._calculateTokenCost(result, model);
|
|
225
|
-
yield this._metrics.recordChatMetrics({
|
|
226
|
-
userId: request.userId,
|
|
227
|
-
createdAtMs: Date.now(),
|
|
228
|
-
tokens: adjustedTokens,
|
|
229
|
-
});
|
|
230
|
-
}
|
|
231
|
-
return {
|
|
232
|
-
success: true,
|
|
233
|
-
choices: result.choices,
|
|
234
|
-
};
|
|
235
200
|
}
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
201
|
+
return {
|
|
202
|
+
success: true,
|
|
203
|
+
choices: result.choices,
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
catch (err) {
|
|
207
|
+
const span = trace.getActiveSpan();
|
|
208
|
+
span === null || span === void 0 ? void 0 : span.recordException(err);
|
|
209
|
+
span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
|
|
210
|
+
console.error('[AIController] Error handling chat request:', err);
|
|
211
|
+
return {
|
|
212
|
+
success: false,
|
|
213
|
+
errorCode: 'server_error',
|
|
214
|
+
errorMessage: 'A server error occurred.',
|
|
215
|
+
};
|
|
216
|
+
}
|
|
248
217
|
}
|
|
249
218
|
_calculateTokenCost(result, model) {
|
|
250
219
|
var _a;
|
|
@@ -254,854 +223,830 @@ export class AIController {
|
|
|
254
223
|
const adjustedTokens = modifier * totalTokens;
|
|
255
224
|
return adjustedTokens;
|
|
256
225
|
}
|
|
257
|
-
chatStream(request) {
|
|
226
|
+
async *chatStream(request) {
|
|
258
227
|
var _a, _b;
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
errorMessage: 'This operation is not supported.',
|
|
267
|
-
});
|
|
268
|
-
}
|
|
269
|
-
if (!request.userId) {
|
|
270
|
-
return yield __await({
|
|
271
|
-
success: false,
|
|
272
|
-
errorCode: 'not_logged_in',
|
|
273
|
-
errorMessage: 'The user must be logged in. Please provide a sessionKey or a recordKey.',
|
|
274
|
-
});
|
|
275
|
-
}
|
|
276
|
-
if (!this._matchesSubscriptionTiers(request.userSubscriptionTier, this._allowedChatSubscriptionTiers)) {
|
|
277
|
-
if (!request.userSubscriptionTier) {
|
|
278
|
-
return yield __await({
|
|
279
|
-
success: false,
|
|
280
|
-
errorCode: 'not_subscribed',
|
|
281
|
-
errorMessage: 'The user must be subscribed in order to use this operation.',
|
|
282
|
-
allowedSubscriptionTiers: [
|
|
283
|
-
...this
|
|
284
|
-
._allowedChatSubscriptionTiers,
|
|
285
|
-
],
|
|
286
|
-
});
|
|
287
|
-
}
|
|
288
|
-
else {
|
|
289
|
-
return yield __await({
|
|
290
|
-
success: false,
|
|
291
|
-
errorCode: 'invalid_subscription_tier',
|
|
292
|
-
errorMessage: 'This operation is not available to the user at their current subscription tier.',
|
|
293
|
-
allowedSubscriptionTiers: [
|
|
294
|
-
...this
|
|
295
|
-
._allowedChatSubscriptionTiers,
|
|
296
|
-
],
|
|
297
|
-
currentSubscriptionTier: request.userSubscriptionTier,
|
|
298
|
-
});
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
|
-
if (!!request.model &&
|
|
302
|
-
!this._allowedChatModels.has(request.model)) {
|
|
303
|
-
return yield __await({
|
|
304
|
-
success: false,
|
|
305
|
-
errorCode: 'invalid_model',
|
|
306
|
-
errorMessage: `The given model is not allowed for chats.`,
|
|
307
|
-
});
|
|
308
|
-
}
|
|
309
|
-
const model = (_a = request.model) !== null && _a !== void 0 ? _a : this._chatOptions.defaultModel;
|
|
310
|
-
const provider = (_b = this._allowedChatModels.get(request.model)) !== null && _b !== void 0 ? _b : this._chatOptions.defaultModelProvider;
|
|
311
|
-
const chat = this._chatProviders[provider];
|
|
312
|
-
if (!chat) {
|
|
313
|
-
console.error('[AIController] No chat provider found for model:', model);
|
|
314
|
-
return yield __await({
|
|
315
|
-
success: false,
|
|
316
|
-
errorCode: 'not_supported',
|
|
317
|
-
errorMessage: 'The given model is not supported.',
|
|
318
|
-
});
|
|
319
|
-
}
|
|
320
|
-
else if (!chat.chatStream) {
|
|
321
|
-
console.error('[AIController] Chat provider does not support chatStream for model:', model);
|
|
322
|
-
return yield __await({
|
|
323
|
-
success: false,
|
|
324
|
-
errorCode: 'not_supported',
|
|
325
|
-
errorMessage: 'The given model does not support streaming.',
|
|
326
|
-
});
|
|
327
|
-
}
|
|
328
|
-
else {
|
|
329
|
-
console.log('[AIController] Using chat provider:', provider, 'for model:', model);
|
|
330
|
-
}
|
|
331
|
-
const metrics = yield __await(this._metrics.getSubscriptionAiChatMetrics({
|
|
332
|
-
ownerId: request.userId,
|
|
333
|
-
}));
|
|
334
|
-
const config = yield __await(this._config.getSubscriptionConfiguration());
|
|
335
|
-
const allowedFeatures = getSubscriptionFeatures(config, metrics.subscriptionStatus, metrics.subscriptionId, 'user');
|
|
336
|
-
if (!allowedFeatures.ai.chat.allowed) {
|
|
337
|
-
return yield __await({
|
|
338
|
-
success: false,
|
|
339
|
-
errorCode: 'not_authorized',
|
|
340
|
-
errorMessage: 'The subscription does not permit AI Chat features.',
|
|
341
|
-
});
|
|
342
|
-
}
|
|
343
|
-
if (allowedFeatures.ai.chat.allowedModels) {
|
|
344
|
-
const allowedModels = allowedFeatures.ai.chat.allowedModels;
|
|
345
|
-
if (!allowedModels.includes(model)) {
|
|
346
|
-
return yield __await({
|
|
347
|
-
success: false,
|
|
348
|
-
errorCode: 'not_authorized',
|
|
349
|
-
errorMessage: 'The subscription does not permit the given model for AI Chat features.',
|
|
350
|
-
});
|
|
351
|
-
}
|
|
352
|
-
}
|
|
353
|
-
let maxTokens = undefined;
|
|
354
|
-
if (allowedFeatures.ai.chat.maxTokensPerPeriod) {
|
|
355
|
-
maxTokens =
|
|
356
|
-
allowedFeatures.ai.chat.maxTokensPerPeriod -
|
|
357
|
-
metrics.totalTokensInCurrentPeriod;
|
|
358
|
-
}
|
|
359
|
-
if (maxTokens <= 0) {
|
|
360
|
-
return yield __await({
|
|
361
|
-
success: false,
|
|
362
|
-
errorCode: 'subscription_limit_reached',
|
|
363
|
-
errorMessage: `The user has reached their limit for the current subscription period.`,
|
|
364
|
-
});
|
|
365
|
-
}
|
|
366
|
-
if (allowedFeatures.ai.chat.maxTokensPerRequest) {
|
|
367
|
-
if (maxTokens) {
|
|
368
|
-
maxTokens = Math.min(maxTokens, allowedFeatures.ai.chat.maxTokensPerRequest);
|
|
369
|
-
}
|
|
370
|
-
else {
|
|
371
|
-
maxTokens = allowedFeatures.ai.chat.maxTokensPerRequest;
|
|
372
|
-
}
|
|
373
|
-
}
|
|
374
|
-
if (this._policyStore) {
|
|
375
|
-
const privacyFeatures = yield __await(this._policyStore.getUserPrivacyFeatures(request.userId));
|
|
376
|
-
if (!privacyFeatures.allowAI) {
|
|
377
|
-
return yield __await({
|
|
378
|
-
success: false,
|
|
379
|
-
errorCode: 'not_authorized',
|
|
380
|
-
errorMessage: 'AI Access is not allowed',
|
|
381
|
-
});
|
|
382
|
-
}
|
|
383
|
-
}
|
|
384
|
-
const result = chat.chatStream({
|
|
385
|
-
messages: request.messages,
|
|
386
|
-
model: model,
|
|
387
|
-
temperature: request.temperature,
|
|
388
|
-
topP: request.topP,
|
|
389
|
-
frequencyPenalty: request.frequencyPenalty,
|
|
390
|
-
presencePenalty: request.presencePenalty,
|
|
391
|
-
stopWords: request.stopWords,
|
|
392
|
-
userId: request.userId,
|
|
393
|
-
maxTokens,
|
|
394
|
-
});
|
|
395
|
-
try {
|
|
396
|
-
for (var _f = true, result_1 = __asyncValues(result), result_1_1; result_1_1 = yield __await(result_1.next()), _c = result_1_1.done, !_c; _f = true) {
|
|
397
|
-
_e = result_1_1.value;
|
|
398
|
-
_f = false;
|
|
399
|
-
let chunk = _e;
|
|
400
|
-
if (chunk.totalTokens > 0) {
|
|
401
|
-
const adjustedTokens = this._calculateTokenCost(chunk, model);
|
|
402
|
-
yield __await(this._metrics.recordChatMetrics({
|
|
403
|
-
userId: request.userId,
|
|
404
|
-
createdAtMs: Date.now(),
|
|
405
|
-
tokens: adjustedTokens,
|
|
406
|
-
}));
|
|
407
|
-
}
|
|
408
|
-
yield yield __await({
|
|
409
|
-
choices: chunk.choices,
|
|
410
|
-
});
|
|
411
|
-
}
|
|
412
|
-
}
|
|
413
|
-
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
414
|
-
finally {
|
|
415
|
-
try {
|
|
416
|
-
if (!_f && !_c && (_d = result_1.return)) yield __await(_d.call(result_1));
|
|
417
|
-
}
|
|
418
|
-
finally { if (e_1) throw e_1.error; }
|
|
419
|
-
}
|
|
420
|
-
return yield __await({
|
|
421
|
-
success: true,
|
|
422
|
-
});
|
|
228
|
+
try {
|
|
229
|
+
if (!this._chatProviders) {
|
|
230
|
+
return {
|
|
231
|
+
success: false,
|
|
232
|
+
errorCode: 'not_supported',
|
|
233
|
+
errorMessage: 'This operation is not supported.',
|
|
234
|
+
};
|
|
423
235
|
}
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
span === null || span === void 0 ? void 0 : span.recordException(err);
|
|
427
|
-
span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
|
|
428
|
-
console.error('[AIController] Error handling chat stream request:', err);
|
|
429
|
-
return yield __await({
|
|
236
|
+
if (!request.userId) {
|
|
237
|
+
return {
|
|
430
238
|
success: false,
|
|
431
|
-
errorCode: '
|
|
432
|
-
errorMessage: '
|
|
433
|
-
}
|
|
239
|
+
errorCode: 'not_logged_in',
|
|
240
|
+
errorMessage: 'The user must be logged in. Please provide a sessionKey or a recordKey.',
|
|
241
|
+
};
|
|
434
242
|
}
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
generateSkybox(request) {
|
|
438
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
439
|
-
try {
|
|
440
|
-
if (!this._generateSkybox) {
|
|
243
|
+
if (!this._matchesSubscriptionTiers(request.userSubscriptionTier, this._allowedChatSubscriptionTiers)) {
|
|
244
|
+
if (!request.userSubscriptionTier) {
|
|
441
245
|
return {
|
|
442
246
|
success: false,
|
|
443
|
-
errorCode: '
|
|
444
|
-
errorMessage: '
|
|
247
|
+
errorCode: 'not_subscribed',
|
|
248
|
+
errorMessage: 'The user must be subscribed in order to use this operation.',
|
|
249
|
+
allowedSubscriptionTiers: [
|
|
250
|
+
...this
|
|
251
|
+
._allowedChatSubscriptionTiers,
|
|
252
|
+
],
|
|
445
253
|
};
|
|
446
254
|
}
|
|
447
|
-
|
|
255
|
+
else {
|
|
448
256
|
return {
|
|
449
257
|
success: false,
|
|
450
|
-
errorCode: '
|
|
451
|
-
errorMessage: '
|
|
258
|
+
errorCode: 'invalid_subscription_tier',
|
|
259
|
+
errorMessage: 'This operation is not available to the user at their current subscription tier.',
|
|
260
|
+
allowedSubscriptionTiers: [
|
|
261
|
+
...this
|
|
262
|
+
._allowedChatSubscriptionTiers,
|
|
263
|
+
],
|
|
264
|
+
currentSubscriptionTier: request.userSubscriptionTier,
|
|
452
265
|
};
|
|
453
266
|
}
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
267
|
+
}
|
|
268
|
+
if (!!request.model &&
|
|
269
|
+
!this._allowedChatModels.has(request.model)) {
|
|
270
|
+
return {
|
|
271
|
+
success: false,
|
|
272
|
+
errorCode: 'invalid_model',
|
|
273
|
+
errorMessage: `The given model is not allowed for chats.`,
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
const model = (_a = request.model) !== null && _a !== void 0 ? _a : this._chatOptions.defaultModel;
|
|
277
|
+
const provider = (_b = this._allowedChatModels.get(request.model)) !== null && _b !== void 0 ? _b : this._chatOptions.defaultModelProvider;
|
|
278
|
+
const chat = this._chatProviders[provider];
|
|
279
|
+
if (!chat) {
|
|
280
|
+
console.error('[AIController] No chat provider found for model:', model);
|
|
281
|
+
return {
|
|
282
|
+
success: false,
|
|
283
|
+
errorCode: 'not_supported',
|
|
284
|
+
errorMessage: 'The given model is not supported.',
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
else if (!chat.chatStream) {
|
|
288
|
+
console.error('[AIController] Chat provider does not support chatStream for model:', model);
|
|
289
|
+
return {
|
|
290
|
+
success: false,
|
|
291
|
+
errorCode: 'not_supported',
|
|
292
|
+
errorMessage: 'The given model does not support streaming.',
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
else {
|
|
296
|
+
console.log('[AIController] Using chat provider:', provider, 'for model:', model);
|
|
297
|
+
}
|
|
298
|
+
const metrics = await this._metrics.getSubscriptionAiChatMetrics({
|
|
299
|
+
ownerId: request.userId,
|
|
300
|
+
});
|
|
301
|
+
const config = await this._config.getSubscriptionConfiguration();
|
|
302
|
+
const allowedFeatures = getSubscriptionFeatures(config, metrics.subscriptionStatus, metrics.subscriptionId, 'user');
|
|
303
|
+
if (!allowedFeatures.ai.chat.allowed) {
|
|
304
|
+
return {
|
|
305
|
+
success: false,
|
|
306
|
+
errorCode: 'not_authorized',
|
|
307
|
+
errorMessage: 'The subscription does not permit AI Chat features.',
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
if (allowedFeatures.ai.chat.allowedModels) {
|
|
311
|
+
const allowedModels = allowedFeatures.ai.chat.allowedModels;
|
|
312
|
+
if (!allowedModels.includes(model)) {
|
|
485
313
|
return {
|
|
486
314
|
success: false,
|
|
487
315
|
errorCode: 'not_authorized',
|
|
488
|
-
errorMessage: 'The subscription does not permit AI
|
|
316
|
+
errorMessage: 'The subscription does not permit the given model for AI Chat features.',
|
|
489
317
|
};
|
|
490
318
|
}
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
319
|
+
}
|
|
320
|
+
let maxTokens = undefined;
|
|
321
|
+
if (allowedFeatures.ai.chat.maxTokensPerPeriod) {
|
|
322
|
+
maxTokens =
|
|
323
|
+
allowedFeatures.ai.chat.maxTokensPerPeriod -
|
|
324
|
+
metrics.totalTokensInCurrentPeriod;
|
|
325
|
+
}
|
|
326
|
+
if (maxTokens <= 0) {
|
|
327
|
+
return {
|
|
328
|
+
success: false,
|
|
329
|
+
errorCode: 'subscription_limit_reached',
|
|
330
|
+
errorMessage: `The user has reached their limit for the current subscription period.`,
|
|
331
|
+
};
|
|
332
|
+
}
|
|
333
|
+
if (allowedFeatures.ai.chat.maxTokensPerRequest) {
|
|
334
|
+
if (maxTokens) {
|
|
335
|
+
maxTokens = Math.min(maxTokens, allowedFeatures.ai.chat.maxTokensPerRequest);
|
|
336
|
+
}
|
|
337
|
+
else {
|
|
338
|
+
maxTokens = allowedFeatures.ai.chat.maxTokensPerRequest;
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
if (this._policyStore) {
|
|
342
|
+
const privacyFeatures = await this._policyStore.getUserPrivacyFeatures(request.userId);
|
|
343
|
+
if (!privacyFeatures.allowAI) {
|
|
494
344
|
return {
|
|
495
345
|
success: false,
|
|
496
|
-
errorCode: '
|
|
497
|
-
errorMessage:
|
|
346
|
+
errorCode: 'not_authorized',
|
|
347
|
+
errorMessage: 'AI Access is not allowed',
|
|
498
348
|
};
|
|
499
349
|
}
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
yield this._metrics.recordSkyboxMetrics({
|
|
350
|
+
}
|
|
351
|
+
const result = chat.chatStream({
|
|
352
|
+
messages: request.messages,
|
|
353
|
+
model: model,
|
|
354
|
+
temperature: request.temperature,
|
|
355
|
+
topP: request.topP,
|
|
356
|
+
frequencyPenalty: request.frequencyPenalty,
|
|
357
|
+
presencePenalty: request.presencePenalty,
|
|
358
|
+
stopWords: request.stopWords,
|
|
359
|
+
userId: request.userId,
|
|
360
|
+
maxTokens,
|
|
361
|
+
});
|
|
362
|
+
for await (let chunk of result) {
|
|
363
|
+
if (chunk.totalTokens > 0) {
|
|
364
|
+
const adjustedTokens = this._calculateTokenCost(chunk, model);
|
|
365
|
+
await this._metrics.recordChatMetrics({
|
|
517
366
|
userId: request.userId,
|
|
518
367
|
createdAtMs: Date.now(),
|
|
519
|
-
|
|
368
|
+
tokens: adjustedTokens,
|
|
520
369
|
});
|
|
521
|
-
return {
|
|
522
|
-
success: true,
|
|
523
|
-
skyboxId: result.skyboxId,
|
|
524
|
-
};
|
|
525
|
-
}
|
|
526
|
-
else {
|
|
527
|
-
return result;
|
|
528
370
|
}
|
|
371
|
+
yield {
|
|
372
|
+
choices: chunk.choices,
|
|
373
|
+
};
|
|
529
374
|
}
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
375
|
+
return {
|
|
376
|
+
success: true,
|
|
377
|
+
};
|
|
378
|
+
}
|
|
379
|
+
catch (err) {
|
|
380
|
+
const span = trace.getActiveSpan();
|
|
381
|
+
span === null || span === void 0 ? void 0 : span.recordException(err);
|
|
382
|
+
span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
|
|
383
|
+
console.error('[AIController] Error handling chat stream request:', err);
|
|
384
|
+
return {
|
|
385
|
+
success: false,
|
|
386
|
+
errorCode: 'server_error',
|
|
387
|
+
errorMessage: 'A server error occurred.',
|
|
388
|
+
};
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
async generateSkybox(request) {
|
|
392
|
+
try {
|
|
393
|
+
if (!this._generateSkybox) {
|
|
535
394
|
return {
|
|
536
395
|
success: false,
|
|
537
|
-
errorCode: '
|
|
538
|
-
errorMessage: '
|
|
396
|
+
errorCode: 'not_supported',
|
|
397
|
+
errorMessage: 'This operation is not supported.',
|
|
539
398
|
};
|
|
540
399
|
}
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
400
|
+
if (!request.userId) {
|
|
401
|
+
return {
|
|
402
|
+
success: false,
|
|
403
|
+
errorCode: 'not_logged_in',
|
|
404
|
+
errorMessage: 'The user must be logged in. Please provide a sessionKey or a recordKey.',
|
|
405
|
+
};
|
|
406
|
+
}
|
|
407
|
+
if (!this._matchesSubscriptionTiers(request.userSubscriptionTier, this._allowedGenerateSkyboxSubscriptionTiers)) {
|
|
408
|
+
if (!request.userSubscriptionTier) {
|
|
547
409
|
return {
|
|
548
410
|
success: false,
|
|
549
|
-
errorCode: '
|
|
550
|
-
errorMessage: '
|
|
411
|
+
errorCode: 'not_subscribed',
|
|
412
|
+
errorMessage: 'The user must be subscribed in order to use this operation.',
|
|
413
|
+
allowedSubscriptionTiers: [
|
|
414
|
+
...this
|
|
415
|
+
._allowedGenerateSkyboxSubscriptionTiers,
|
|
416
|
+
],
|
|
551
417
|
};
|
|
552
418
|
}
|
|
553
|
-
|
|
419
|
+
else {
|
|
554
420
|
return {
|
|
555
421
|
success: false,
|
|
556
|
-
errorCode: '
|
|
557
|
-
errorMessage: '
|
|
422
|
+
errorCode: 'invalid_subscription_tier',
|
|
423
|
+
errorMessage: 'This operation is not available to the user at their current subscription tier.',
|
|
424
|
+
allowedSubscriptionTiers: [
|
|
425
|
+
...this
|
|
426
|
+
._allowedGenerateSkyboxSubscriptionTiers,
|
|
427
|
+
],
|
|
428
|
+
currentSubscriptionTier: request.userSubscriptionTier,
|
|
558
429
|
};
|
|
559
430
|
}
|
|
560
|
-
if (!this._matchesSubscriptionTiers(request.userSubscriptionTier, this._allowedGenerateSkyboxSubscriptionTiers)) {
|
|
561
|
-
if (!request.userSubscriptionTier) {
|
|
562
|
-
return {
|
|
563
|
-
success: false,
|
|
564
|
-
errorCode: 'not_subscribed',
|
|
565
|
-
errorMessage: 'The user must be subscribed in order to use this operation.',
|
|
566
|
-
allowedSubscriptionTiers: [
|
|
567
|
-
...this
|
|
568
|
-
._allowedGenerateSkyboxSubscriptionTiers,
|
|
569
|
-
],
|
|
570
|
-
};
|
|
571
|
-
}
|
|
572
|
-
else {
|
|
573
|
-
return {
|
|
574
|
-
success: false,
|
|
575
|
-
errorCode: 'invalid_subscription_tier',
|
|
576
|
-
errorMessage: 'This operation is not available to the user at their current subscription tier.',
|
|
577
|
-
allowedSubscriptionTiers: [
|
|
578
|
-
...this
|
|
579
|
-
._allowedGenerateSkyboxSubscriptionTiers,
|
|
580
|
-
],
|
|
581
|
-
currentSubscriptionTier: request.userSubscriptionTier,
|
|
582
|
-
};
|
|
583
|
-
}
|
|
584
|
-
}
|
|
585
|
-
if (this._policyStore) {
|
|
586
|
-
const privacyFeatures = yield this._policyStore.getUserPrivacyFeatures(request.userId);
|
|
587
|
-
if (!privacyFeatures.allowAI) {
|
|
588
|
-
return {
|
|
589
|
-
success: false,
|
|
590
|
-
errorCode: 'not_authorized',
|
|
591
|
-
errorMessage: 'AI Access is not allowed',
|
|
592
|
-
};
|
|
593
|
-
}
|
|
594
|
-
}
|
|
595
|
-
const result = yield this._generateSkybox.getSkybox(request.skyboxId);
|
|
596
|
-
if (result.success === true) {
|
|
597
|
-
return {
|
|
598
|
-
success: true,
|
|
599
|
-
status: result.status,
|
|
600
|
-
fileUrl: result.fileUrl,
|
|
601
|
-
thumbnailUrl: result.thumbnailUrl,
|
|
602
|
-
};
|
|
603
|
-
}
|
|
604
|
-
else {
|
|
605
|
-
return result;
|
|
606
|
-
}
|
|
607
431
|
}
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
432
|
+
const metrics = await this._metrics.getSubscriptionAiSkyboxMetrics({
|
|
433
|
+
ownerId: request.userId,
|
|
434
|
+
});
|
|
435
|
+
const config = await this._config.getSubscriptionConfiguration();
|
|
436
|
+
const allowedFeatures = getSubscriptionFeatures(config, metrics.subscriptionStatus, metrics.subscriptionId, 'user');
|
|
437
|
+
if (!allowedFeatures.ai.skyboxes.allowed) {
|
|
613
438
|
return {
|
|
614
439
|
success: false,
|
|
615
|
-
errorCode: '
|
|
616
|
-
errorMessage: '
|
|
440
|
+
errorCode: 'not_authorized',
|
|
441
|
+
errorMessage: 'The subscription does not permit AI Skybox features.',
|
|
617
442
|
};
|
|
618
443
|
}
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
}
|
|
632
|
-
if (!request.userId) {
|
|
633
|
-
return {
|
|
634
|
-
success: false,
|
|
635
|
-
errorCode: 'not_logged_in',
|
|
636
|
-
errorMessage: 'The user must be logged in. Please provide a sessionKey or a recordKey.',
|
|
637
|
-
};
|
|
638
|
-
}
|
|
639
|
-
if (!this._matchesSubscriptionTiers(request.userSubscriptionTier, this._allowedImageSubscriptionTiers)) {
|
|
640
|
-
if (!request.userSubscriptionTier) {
|
|
641
|
-
return {
|
|
642
|
-
success: false,
|
|
643
|
-
errorCode: 'not_subscribed',
|
|
644
|
-
errorMessage: 'The user must be subscribed in order to use this operation.',
|
|
645
|
-
allowedSubscriptionTiers: [
|
|
646
|
-
...this
|
|
647
|
-
._allowedImageSubscriptionTiers,
|
|
648
|
-
],
|
|
649
|
-
};
|
|
650
|
-
}
|
|
651
|
-
else {
|
|
652
|
-
return {
|
|
653
|
-
success: false,
|
|
654
|
-
errorCode: 'invalid_subscription_tier',
|
|
655
|
-
errorMessage: 'This operation is not available to the user at their current subscription tier.',
|
|
656
|
-
allowedSubscriptionTiers: [
|
|
657
|
-
...this
|
|
658
|
-
._allowedImageSubscriptionTiers,
|
|
659
|
-
],
|
|
660
|
-
currentSubscriptionTier: request.userSubscriptionTier,
|
|
661
|
-
};
|
|
662
|
-
}
|
|
663
|
-
}
|
|
664
|
-
const model = (_a = request.model) !== null && _a !== void 0 ? _a : this._imageOptions.defaultModel;
|
|
665
|
-
if (!this._allowedImageModels.has(model)) {
|
|
666
|
-
return {
|
|
667
|
-
success: false,
|
|
668
|
-
errorCode: 'invalid_model',
|
|
669
|
-
errorMessage: `The given model is not allowed for images.`,
|
|
670
|
-
};
|
|
671
|
-
}
|
|
672
|
-
const providerId = this._allowedImageModels.get(model);
|
|
673
|
-
const provider = this._imageProviders[providerId];
|
|
674
|
-
if (!provider) {
|
|
675
|
-
return {
|
|
676
|
-
success: false,
|
|
677
|
-
errorCode: 'invalid_model',
|
|
678
|
-
errorMessage: `The given model is not allowed for images.`,
|
|
679
|
-
};
|
|
680
|
-
}
|
|
681
|
-
const width = Math.min((_b = request.width) !== null && _b !== void 0 ? _b : this._imageOptions.defaultWidth, this._imageOptions.maxWidth);
|
|
682
|
-
const height = Math.min((_c = request.height) !== null && _c !== void 0 ? _c : this._imageOptions.defaultHeight, this._imageOptions.maxHeight);
|
|
683
|
-
const numberOfImages = Math.min((_d = request.numberOfImages) !== null && _d !== void 0 ? _d : 1, this._imageOptions.maxImages);
|
|
684
|
-
const totalPixels = Math.max(width, height) * numberOfImages;
|
|
685
|
-
const metrics = yield this._metrics.getSubscriptionAiImageMetrics({
|
|
686
|
-
ownerId: request.userId,
|
|
687
|
-
});
|
|
688
|
-
const config = yield this._config.getSubscriptionConfiguration();
|
|
689
|
-
const allowedFeatures = getSubscriptionFeatures(config, metrics.subscriptionStatus, metrics.subscriptionId, 'user');
|
|
690
|
-
if (!allowedFeatures.ai.images.allowed) {
|
|
444
|
+
if (allowedFeatures.ai.skyboxes.maxSkyboxesPerPeriod > 0 &&
|
|
445
|
+
metrics.totalSkyboxesInCurrentPeriod + 1 >
|
|
446
|
+
allowedFeatures.ai.skyboxes.maxSkyboxesPerPeriod) {
|
|
447
|
+
return {
|
|
448
|
+
success: false,
|
|
449
|
+
errorCode: 'subscription_limit_reached',
|
|
450
|
+
errorMessage: `The user has reached their limit for the current subscription period.`,
|
|
451
|
+
};
|
|
452
|
+
}
|
|
453
|
+
if (this._policyStore) {
|
|
454
|
+
const privacyFeatures = await this._policyStore.getUserPrivacyFeatures(request.userId);
|
|
455
|
+
if (!privacyFeatures.allowAI) {
|
|
691
456
|
return {
|
|
692
457
|
success: false,
|
|
693
458
|
errorCode: 'not_authorized',
|
|
694
|
-
errorMessage: '
|
|
695
|
-
};
|
|
696
|
-
}
|
|
697
|
-
if (allowedFeatures.ai.images.maxSquarePixelsPerRequest > 0 &&
|
|
698
|
-
totalPixels >
|
|
699
|
-
allowedFeatures.ai.images.maxSquarePixelsPerRequest) {
|
|
700
|
-
return {
|
|
701
|
-
success: false,
|
|
702
|
-
errorCode: 'subscription_limit_reached',
|
|
703
|
-
errorMessage: `The request exceeds allowed subscription limits.`,
|
|
704
|
-
};
|
|
705
|
-
}
|
|
706
|
-
if (allowedFeatures.ai.images.maxSquarePixelsPerPeriod > 0 &&
|
|
707
|
-
totalPixels + metrics.totalSquarePixelsInCurrentPeriod >
|
|
708
|
-
allowedFeatures.ai.images.maxSquarePixelsPerPeriod) {
|
|
709
|
-
return {
|
|
710
|
-
success: false,
|
|
711
|
-
errorCode: 'subscription_limit_reached',
|
|
712
|
-
errorMessage: `The user has reached their limit for the current subscription period.`,
|
|
459
|
+
errorMessage: 'AI Access is not allowed',
|
|
713
460
|
};
|
|
714
461
|
}
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
}
|
|
724
|
-
}
|
|
725
|
-
const result = yield provider.generateImage({
|
|
726
|
-
model: model,
|
|
727
|
-
prompt: request.prompt,
|
|
728
|
-
negativePrompt: request.negativePrompt,
|
|
729
|
-
width: width,
|
|
730
|
-
height: height,
|
|
731
|
-
numberOfImages: numberOfImages,
|
|
732
|
-
seed: request.seed,
|
|
733
|
-
steps: Math.min((_e = request.steps) !== null && _e !== void 0 ? _e : 30, this._imageOptions.maxSteps),
|
|
734
|
-
cfgScale: request.cfgScale,
|
|
735
|
-
sampler: request.sampler,
|
|
736
|
-
clipGuidancePreset: request.clipGuidancePreset,
|
|
737
|
-
stylePreset: request.stylePreset,
|
|
738
|
-
userId: request.userId,
|
|
739
|
-
});
|
|
740
|
-
if (!result.success) {
|
|
741
|
-
return result;
|
|
742
|
-
}
|
|
743
|
-
yield this._metrics.recordImageMetrics({
|
|
462
|
+
}
|
|
463
|
+
const result = await this._generateSkybox.generateSkybox({
|
|
464
|
+
prompt: request.prompt,
|
|
465
|
+
negativePrompt: request.negativePrompt,
|
|
466
|
+
blockadeLabs: request.blockadeLabs,
|
|
467
|
+
});
|
|
468
|
+
if (result.success === true) {
|
|
469
|
+
await this._metrics.recordSkyboxMetrics({
|
|
744
470
|
userId: request.userId,
|
|
745
471
|
createdAtMs: Date.now(),
|
|
746
|
-
|
|
472
|
+
skyboxes: 1,
|
|
747
473
|
});
|
|
748
474
|
return {
|
|
749
475
|
success: true,
|
|
750
|
-
|
|
476
|
+
skyboxId: result.skyboxId,
|
|
751
477
|
};
|
|
752
478
|
}
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
479
|
+
else {
|
|
480
|
+
return result;
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
catch (err) {
|
|
484
|
+
const span = trace.getActiveSpan();
|
|
485
|
+
span === null || span === void 0 ? void 0 : span.recordException(err);
|
|
486
|
+
span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
|
|
487
|
+
console.error('[AIController] Error handling generate skybox request:', err);
|
|
488
|
+
return {
|
|
489
|
+
success: false,
|
|
490
|
+
errorCode: 'server_error',
|
|
491
|
+
errorMessage: 'A server error occurred.',
|
|
492
|
+
};
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
async getSkybox(request) {
|
|
496
|
+
try {
|
|
497
|
+
if (!this._generateSkybox) {
|
|
758
498
|
return {
|
|
759
499
|
success: false,
|
|
760
|
-
errorCode: '
|
|
761
|
-
errorMessage: '
|
|
500
|
+
errorCode: 'not_supported',
|
|
501
|
+
errorMessage: 'This operation is not supported.',
|
|
762
502
|
};
|
|
763
503
|
}
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
errorCode: 'not_supported',
|
|
774
|
-
errorMessage: 'This operation is not supported.',
|
|
775
|
-
};
|
|
776
|
-
}
|
|
777
|
-
if (!request.userId) {
|
|
504
|
+
if (!request.userId) {
|
|
505
|
+
return {
|
|
506
|
+
success: false,
|
|
507
|
+
errorCode: 'not_logged_in',
|
|
508
|
+
errorMessage: 'The user must be logged in. Please provide a sessionKey or a recordKey.',
|
|
509
|
+
};
|
|
510
|
+
}
|
|
511
|
+
if (!this._matchesSubscriptionTiers(request.userSubscriptionTier, this._allowedGenerateSkyboxSubscriptionTiers)) {
|
|
512
|
+
if (!request.userSubscriptionTier) {
|
|
778
513
|
return {
|
|
779
514
|
success: false,
|
|
780
|
-
errorCode: '
|
|
781
|
-
errorMessage: 'The user must be
|
|
515
|
+
errorCode: 'not_subscribed',
|
|
516
|
+
errorMessage: 'The user must be subscribed in order to use this operation.',
|
|
517
|
+
allowedSubscriptionTiers: [
|
|
518
|
+
...this
|
|
519
|
+
._allowedGenerateSkyboxSubscriptionTiers,
|
|
520
|
+
],
|
|
782
521
|
};
|
|
783
522
|
}
|
|
784
|
-
const recordName = (_a = request.recordName) !== null && _a !== void 0 ? _a : request.userId;
|
|
785
|
-
const context = yield this._policies.constructAuthorizationContext({
|
|
786
|
-
recordKeyOrRecordName: recordName,
|
|
787
|
-
userId: request.userId,
|
|
788
|
-
});
|
|
789
|
-
if (context.success === false) {
|
|
790
|
-
return context;
|
|
791
|
-
}
|
|
792
|
-
const authResult = yield this._policies.authorizeSubjectUsingContext(context.context, {
|
|
793
|
-
resourceKind: 'ai.hume',
|
|
794
|
-
action: 'create',
|
|
795
|
-
markers: null,
|
|
796
|
-
subjectId: request.userId,
|
|
797
|
-
subjectType: 'user',
|
|
798
|
-
});
|
|
799
|
-
if (authResult.success === false) {
|
|
800
|
-
return authResult;
|
|
801
|
-
}
|
|
802
|
-
let metricsFilter = {};
|
|
803
|
-
if (context.context.recordStudioId) {
|
|
804
|
-
metricsFilter.studioId = context.context.recordStudioId;
|
|
805
|
-
}
|
|
806
523
|
else {
|
|
807
|
-
metricsFilter.ownerId = context.context.recordOwnerId;
|
|
808
|
-
}
|
|
809
|
-
const metrics = yield this._metrics.getSubscriptionRecordMetrics(metricsFilter);
|
|
810
|
-
const config = yield this._config.getSubscriptionConfiguration();
|
|
811
|
-
const features = getHumeAiFeatures(config, metrics.subscriptionStatus, metrics.subscriptionId, context.context.recordStudioId ? 'studio' : 'user');
|
|
812
|
-
if (!features.allowed) {
|
|
813
524
|
return {
|
|
814
525
|
success: false,
|
|
815
|
-
errorCode: '
|
|
816
|
-
errorMessage: '
|
|
526
|
+
errorCode: 'invalid_subscription_tier',
|
|
527
|
+
errorMessage: 'This operation is not available to the user at their current subscription tier.',
|
|
528
|
+
allowedSubscriptionTiers: [
|
|
529
|
+
...this
|
|
530
|
+
._allowedGenerateSkyboxSubscriptionTiers,
|
|
531
|
+
],
|
|
532
|
+
currentSubscriptionTier: request.userSubscriptionTier,
|
|
817
533
|
};
|
|
818
534
|
}
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
humeConfig !== null && humeConfig !== void 0 ? humeConfig : (humeConfig = this._humeConfig);
|
|
824
|
-
if (!humeConfig) {
|
|
825
|
-
if (context.context.recordStudioId) {
|
|
826
|
-
return {
|
|
827
|
-
success: false,
|
|
828
|
-
errorCode: 'invalid_request',
|
|
829
|
-
errorMessage: 'The studio does not have a Hume configuration.',
|
|
830
|
-
};
|
|
831
|
-
}
|
|
535
|
+
}
|
|
536
|
+
if (this._policyStore) {
|
|
537
|
+
const privacyFeatures = await this._policyStore.getUserPrivacyFeatures(request.userId);
|
|
538
|
+
if (!privacyFeatures.allowAI) {
|
|
832
539
|
return {
|
|
833
540
|
success: false,
|
|
834
541
|
errorCode: 'not_authorized',
|
|
835
|
-
errorMessage: '
|
|
542
|
+
errorMessage: 'AI Access is not allowed',
|
|
836
543
|
};
|
|
837
544
|
}
|
|
838
|
-
if (this._policyStore) {
|
|
839
|
-
const privacyFeatures = yield this._policyStore.getUserPrivacyFeatures(request.userId);
|
|
840
|
-
if (!privacyFeatures.allowAI) {
|
|
841
|
-
return {
|
|
842
|
-
success: false,
|
|
843
|
-
errorCode: 'not_authorized',
|
|
844
|
-
errorMessage: 'AI Access is not allowed',
|
|
845
|
-
};
|
|
846
|
-
}
|
|
847
|
-
}
|
|
848
|
-
const result = yield this._humeInterface.getAccessToken({
|
|
849
|
-
apiKey: humeConfig.apiKey,
|
|
850
|
-
secretKey: humeConfig.secretKey,
|
|
851
|
-
});
|
|
852
|
-
if (result.success) {
|
|
853
|
-
return {
|
|
854
|
-
success: true,
|
|
855
|
-
accessToken: result.accessToken,
|
|
856
|
-
expiresIn: result.expiresIn,
|
|
857
|
-
issuedAt: result.issuedAt,
|
|
858
|
-
tokenType: result.tokenType,
|
|
859
|
-
};
|
|
860
|
-
}
|
|
861
|
-
else {
|
|
862
|
-
return result;
|
|
863
|
-
}
|
|
864
545
|
}
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
span === null || span === void 0 ? void 0 : span.recordException(err);
|
|
868
|
-
span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
|
|
869
|
-
console.error('[AIController] Error handling get hume access token request:', err);
|
|
546
|
+
const result = await this._generateSkybox.getSkybox(request.skyboxId);
|
|
547
|
+
if (result.success === true) {
|
|
870
548
|
return {
|
|
871
|
-
success:
|
|
872
|
-
|
|
873
|
-
|
|
549
|
+
success: true,
|
|
550
|
+
status: result.status,
|
|
551
|
+
fileUrl: result.fileUrl,
|
|
552
|
+
thumbnailUrl: result.thumbnailUrl,
|
|
874
553
|
};
|
|
875
554
|
}
|
|
876
|
-
|
|
555
|
+
else {
|
|
556
|
+
return result;
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
catch (err) {
|
|
560
|
+
const span = trace.getActiveSpan();
|
|
561
|
+
span === null || span === void 0 ? void 0 : span.recordException(err);
|
|
562
|
+
span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
|
|
563
|
+
console.error('[AIController] Error handling get skybox request:', err);
|
|
564
|
+
return {
|
|
565
|
+
success: false,
|
|
566
|
+
errorCode: 'server_error',
|
|
567
|
+
errorMessage: 'A server error occurred.',
|
|
568
|
+
};
|
|
569
|
+
}
|
|
877
570
|
}
|
|
878
|
-
|
|
879
|
-
var _a, _b, _c, _d, _e
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
571
|
+
async generateImage(request) {
|
|
572
|
+
var _a, _b, _c, _d, _e;
|
|
573
|
+
try {
|
|
574
|
+
if (!this._imageProviders) {
|
|
575
|
+
return {
|
|
576
|
+
success: false,
|
|
577
|
+
errorCode: 'not_supported',
|
|
578
|
+
errorMessage: 'This operation is not supported.',
|
|
579
|
+
};
|
|
580
|
+
}
|
|
581
|
+
if (!request.userId) {
|
|
582
|
+
return {
|
|
583
|
+
success: false,
|
|
584
|
+
errorCode: 'not_logged_in',
|
|
585
|
+
errorMessage: 'The user must be logged in. Please provide a sessionKey or a recordKey.',
|
|
586
|
+
};
|
|
587
|
+
}
|
|
588
|
+
if (!this._matchesSubscriptionTiers(request.userSubscriptionTier, this._allowedImageSubscriptionTiers)) {
|
|
589
|
+
if (!request.userSubscriptionTier) {
|
|
890
590
|
return {
|
|
891
591
|
success: false,
|
|
892
|
-
errorCode: '
|
|
893
|
-
errorMessage: 'The user must be
|
|
592
|
+
errorCode: 'not_subscribed',
|
|
593
|
+
errorMessage: 'The user must be subscribed in order to use this operation.',
|
|
594
|
+
allowedSubscriptionTiers: [
|
|
595
|
+
...this
|
|
596
|
+
._allowedImageSubscriptionTiers,
|
|
597
|
+
],
|
|
894
598
|
};
|
|
895
599
|
}
|
|
896
|
-
const context = yield this._policies.constructAuthorizationContext({
|
|
897
|
-
recordKeyOrRecordName: request.recordName,
|
|
898
|
-
userId: request.userId,
|
|
899
|
-
});
|
|
900
|
-
if (context.success === false) {
|
|
901
|
-
return context;
|
|
902
|
-
}
|
|
903
|
-
const authResult = yield this._policies.authorizeSubjectUsingContext(context.context, {
|
|
904
|
-
resourceKind: 'ai.sloyd',
|
|
905
|
-
action: 'create',
|
|
906
|
-
markers: null,
|
|
907
|
-
subjectId: request.userId,
|
|
908
|
-
subjectType: 'user',
|
|
909
|
-
});
|
|
910
|
-
if (authResult.success === false) {
|
|
911
|
-
return authResult;
|
|
912
|
-
}
|
|
913
|
-
let metricsFilter = {};
|
|
914
|
-
if (context.context.recordStudioId) {
|
|
915
|
-
metricsFilter.studioId = context.context.recordStudioId;
|
|
916
|
-
}
|
|
917
600
|
else {
|
|
918
|
-
metricsFilter.ownerId = context.context.recordOwnerId;
|
|
919
|
-
}
|
|
920
|
-
const metrics = yield this._metrics.getSubscriptionAiSloydMetrics(metricsFilter);
|
|
921
|
-
const config = yield this._config.getSubscriptionConfiguration();
|
|
922
|
-
const features = getSloydAiFeatures(config, metrics.subscriptionStatus, metrics.subscriptionId, context.context.recordStudioId ? 'studio' : 'user');
|
|
923
|
-
if (!features.allowed) {
|
|
924
601
|
return {
|
|
925
602
|
success: false,
|
|
926
|
-
errorCode: '
|
|
927
|
-
errorMessage: '
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
features.maxModelsPerPeriod) {
|
|
934
|
-
return {
|
|
935
|
-
success: false,
|
|
936
|
-
errorCode: 'subscription_limit_reached',
|
|
937
|
-
errorMessage: `The request exceeds allowed subscription limits.`,
|
|
603
|
+
errorCode: 'invalid_subscription_tier',
|
|
604
|
+
errorMessage: 'This operation is not available to the user at their current subscription tier.',
|
|
605
|
+
allowedSubscriptionTiers: [
|
|
606
|
+
...this
|
|
607
|
+
._allowedImageSubscriptionTiers,
|
|
608
|
+
],
|
|
609
|
+
currentSubscriptionTier: request.userSubscriptionTier,
|
|
938
610
|
};
|
|
939
611
|
}
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
};
|
|
948
|
-
}
|
|
949
|
-
}
|
|
950
|
-
const result = yield (request.baseModelId
|
|
951
|
-
? this._sloydInterface.editModel({
|
|
952
|
-
prompt: request.prompt,
|
|
953
|
-
modelMimeType: request.outputMimeType,
|
|
954
|
-
levelOfDetail: request.levelOfDetail,
|
|
955
|
-
thumbnailPreviewExportType: (_a = request.thumbnail) === null || _a === void 0 ? void 0 : _a.type,
|
|
956
|
-
thumbnailPreviewSizeX: (_b = request.thumbnail) === null || _b === void 0 ? void 0 : _b.width,
|
|
957
|
-
thumbnailPreviewSizeY: (_c = request.thumbnail) === null || _c === void 0 ? void 0 : _c.height,
|
|
958
|
-
interactionId: request.baseModelId,
|
|
959
|
-
})
|
|
960
|
-
: this._sloydInterface.createModel({
|
|
961
|
-
prompt: request.prompt,
|
|
962
|
-
modelMimeType: request.outputMimeType,
|
|
963
|
-
levelOfDetail: request.levelOfDetail,
|
|
964
|
-
thumbnailPreviewExportType: (_d = request.thumbnail) === null || _d === void 0 ? void 0 : _d.type,
|
|
965
|
-
thumbnailPreviewSizeX: (_e = request.thumbnail) === null || _e === void 0 ? void 0 : _e.width,
|
|
966
|
-
thumbnailPreviewSizeY: (_f = request.thumbnail) === null || _f === void 0 ? void 0 : _f.height,
|
|
967
|
-
}));
|
|
968
|
-
if (result.success === false) {
|
|
969
|
-
return result;
|
|
970
|
-
}
|
|
971
|
-
const response = {
|
|
972
|
-
success: true,
|
|
973
|
-
modelId: result.interactionId,
|
|
974
|
-
mimeType: request.outputMimeType,
|
|
975
|
-
modelData: typeof result.modelData === 'string'
|
|
976
|
-
? result.modelData
|
|
977
|
-
: fromByteArray(result.modelData),
|
|
978
|
-
thumbnailBase64: result.previewImage,
|
|
612
|
+
}
|
|
613
|
+
const model = (_a = request.model) !== null && _a !== void 0 ? _a : this._imageOptions.defaultModel;
|
|
614
|
+
if (!this._allowedImageModels.has(model)) {
|
|
615
|
+
return {
|
|
616
|
+
success: false,
|
|
617
|
+
errorCode: 'invalid_model',
|
|
618
|
+
errorMessage: `The given model is not allowed for images.`,
|
|
979
619
|
};
|
|
980
|
-
if ('name' in result && typeof result.name === 'string') {
|
|
981
|
-
response.name = result.name;
|
|
982
|
-
response.confidence = result.confidenceScore;
|
|
983
|
-
}
|
|
984
|
-
yield this._metrics.recordSloydMetrics({
|
|
985
|
-
userId: (_g = context.context.recordOwnerId) !== null && _g !== void 0 ? _g : undefined,
|
|
986
|
-
studioId: (_h = context.context.recordStudioId) !== null && _h !== void 0 ? _h : undefined,
|
|
987
|
-
modelId: response.modelId,
|
|
988
|
-
confidence: response.confidence,
|
|
989
|
-
mimeType: response.mimeType,
|
|
990
|
-
modelData: response.modelData,
|
|
991
|
-
name: response.name,
|
|
992
|
-
thumbnailBase64: response.thumbnailBase64,
|
|
993
|
-
createdAtMs: Date.now(),
|
|
994
|
-
baseModelId: request.baseModelId,
|
|
995
|
-
modelsCreated: 1,
|
|
996
|
-
});
|
|
997
|
-
return response;
|
|
998
620
|
}
|
|
999
|
-
|
|
1000
|
-
|
|
621
|
+
const providerId = this._allowedImageModels.get(model);
|
|
622
|
+
const provider = this._imageProviders[providerId];
|
|
623
|
+
if (!provider) {
|
|
1001
624
|
return {
|
|
1002
625
|
success: false,
|
|
1003
|
-
errorCode: '
|
|
1004
|
-
errorMessage:
|
|
626
|
+
errorCode: 'invalid_model',
|
|
627
|
+
errorMessage: `The given model is not allowed for images.`,
|
|
1005
628
|
};
|
|
1006
629
|
}
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
630
|
+
const width = Math.min((_b = request.width) !== null && _b !== void 0 ? _b : this._imageOptions.defaultWidth, this._imageOptions.maxWidth);
|
|
631
|
+
const height = Math.min((_c = request.height) !== null && _c !== void 0 ? _c : this._imageOptions.defaultHeight, this._imageOptions.maxHeight);
|
|
632
|
+
const numberOfImages = Math.min((_d = request.numberOfImages) !== null && _d !== void 0 ? _d : 1, this._imageOptions.maxImages);
|
|
633
|
+
const totalPixels = Math.max(width, height) * numberOfImages;
|
|
634
|
+
const metrics = await this._metrics.getSubscriptionAiImageMetrics({
|
|
635
|
+
ownerId: request.userId,
|
|
636
|
+
});
|
|
637
|
+
const config = await this._config.getSubscriptionConfiguration();
|
|
638
|
+
const allowedFeatures = getSubscriptionFeatures(config, metrics.subscriptionStatus, metrics.subscriptionId, 'user');
|
|
639
|
+
if (!allowedFeatures.ai.images.allowed) {
|
|
640
|
+
return {
|
|
641
|
+
success: false,
|
|
642
|
+
errorCode: 'not_authorized',
|
|
643
|
+
errorMessage: 'The subscription does not permit AI Image features.',
|
|
644
|
+
};
|
|
645
|
+
}
|
|
646
|
+
if (allowedFeatures.ai.images.maxSquarePixelsPerRequest > 0 &&
|
|
647
|
+
totalPixels >
|
|
648
|
+
allowedFeatures.ai.images.maxSquarePixelsPerRequest) {
|
|
649
|
+
return {
|
|
650
|
+
success: false,
|
|
651
|
+
errorCode: 'subscription_limit_reached',
|
|
652
|
+
errorMessage: `The request exceeds allowed subscription limits.`,
|
|
653
|
+
};
|
|
654
|
+
}
|
|
655
|
+
if (allowedFeatures.ai.images.maxSquarePixelsPerPeriod > 0 &&
|
|
656
|
+
totalPixels + metrics.totalSquarePixelsInCurrentPeriod >
|
|
657
|
+
allowedFeatures.ai.images.maxSquarePixelsPerPeriod) {
|
|
658
|
+
return {
|
|
659
|
+
success: false,
|
|
660
|
+
errorCode: 'subscription_limit_reached',
|
|
661
|
+
errorMessage: `The user has reached their limit for the current subscription period.`,
|
|
662
|
+
};
|
|
663
|
+
}
|
|
664
|
+
if (this._policyStore) {
|
|
665
|
+
const privacyFeatures = await this._policyStore.getUserPrivacyFeatures(request.userId);
|
|
666
|
+
if (!privacyFeatures.allowAI) {
|
|
1021
667
|
return {
|
|
1022
668
|
success: false,
|
|
1023
|
-
errorCode: '
|
|
1024
|
-
errorMessage: '
|
|
669
|
+
errorCode: 'not_authorized',
|
|
670
|
+
errorMessage: 'AI Access is not allowed',
|
|
1025
671
|
};
|
|
1026
672
|
}
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
673
|
+
}
|
|
674
|
+
const result = await provider.generateImage({
|
|
675
|
+
model: model,
|
|
676
|
+
prompt: request.prompt,
|
|
677
|
+
negativePrompt: request.negativePrompt,
|
|
678
|
+
width: width,
|
|
679
|
+
height: height,
|
|
680
|
+
numberOfImages: numberOfImages,
|
|
681
|
+
seed: request.seed,
|
|
682
|
+
steps: Math.min((_e = request.steps) !== null && _e !== void 0 ? _e : 30, this._imageOptions.maxSteps),
|
|
683
|
+
cfgScale: request.cfgScale,
|
|
684
|
+
sampler: request.sampler,
|
|
685
|
+
clipGuidancePreset: request.clipGuidancePreset,
|
|
686
|
+
stylePreset: request.stylePreset,
|
|
687
|
+
userId: request.userId,
|
|
688
|
+
});
|
|
689
|
+
if (!result.success) {
|
|
690
|
+
return result;
|
|
691
|
+
}
|
|
692
|
+
await this._metrics.recordImageMetrics({
|
|
693
|
+
userId: request.userId,
|
|
694
|
+
createdAtMs: Date.now(),
|
|
695
|
+
squarePixels: totalPixels,
|
|
696
|
+
});
|
|
697
|
+
return {
|
|
698
|
+
success: true,
|
|
699
|
+
images: result.images,
|
|
700
|
+
};
|
|
701
|
+
}
|
|
702
|
+
catch (err) {
|
|
703
|
+
const span = trace.getActiveSpan();
|
|
704
|
+
span === null || span === void 0 ? void 0 : span.recordException(err);
|
|
705
|
+
span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
|
|
706
|
+
console.error('[AIController] Error handling generate image request:', err);
|
|
707
|
+
return {
|
|
708
|
+
success: false,
|
|
709
|
+
errorCode: 'server_error',
|
|
710
|
+
errorMessage: 'A server error occurred.',
|
|
711
|
+
};
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
async getHumeAccessToken(request) {
|
|
715
|
+
var _a;
|
|
716
|
+
try {
|
|
717
|
+
if (!this._humeInterface) {
|
|
718
|
+
return {
|
|
719
|
+
success: false,
|
|
720
|
+
errorCode: 'not_supported',
|
|
721
|
+
errorMessage: 'This operation is not supported.',
|
|
722
|
+
};
|
|
723
|
+
}
|
|
724
|
+
if (!request.userId) {
|
|
725
|
+
return {
|
|
726
|
+
success: false,
|
|
727
|
+
errorCode: 'not_logged_in',
|
|
728
|
+
errorMessage: 'The user must be logged in. Please provide a sessionKey.',
|
|
729
|
+
};
|
|
730
|
+
}
|
|
731
|
+
const recordName = (_a = request.recordName) !== null && _a !== void 0 ? _a : request.userId;
|
|
732
|
+
const context = await this._policies.constructAuthorizationContext({
|
|
733
|
+
recordKeyOrRecordName: recordName,
|
|
734
|
+
userId: request.userId,
|
|
735
|
+
});
|
|
736
|
+
if (context.success === false) {
|
|
737
|
+
return context;
|
|
738
|
+
}
|
|
739
|
+
const authResult = await this._policies.authorizeSubjectUsingContext(context.context, {
|
|
740
|
+
resourceKind: 'ai.hume',
|
|
741
|
+
action: 'create',
|
|
742
|
+
markers: null,
|
|
743
|
+
subjectId: request.userId,
|
|
744
|
+
subjectType: 'user',
|
|
745
|
+
});
|
|
746
|
+
if (authResult.success === false) {
|
|
747
|
+
return authResult;
|
|
748
|
+
}
|
|
749
|
+
let metricsFilter = {};
|
|
750
|
+
if (context.context.recordStudioId) {
|
|
751
|
+
metricsFilter.studioId = context.context.recordStudioId;
|
|
752
|
+
}
|
|
753
|
+
else {
|
|
754
|
+
metricsFilter.ownerId = context.context.recordOwnerId;
|
|
755
|
+
}
|
|
756
|
+
const metrics = await this._metrics.getSubscriptionRecordMetrics(metricsFilter);
|
|
757
|
+
const config = await this._config.getSubscriptionConfiguration();
|
|
758
|
+
const features = getHumeAiFeatures(config, metrics.subscriptionStatus, metrics.subscriptionId, context.context.recordStudioId ? 'studio' : 'user');
|
|
759
|
+
if (!features.allowed) {
|
|
760
|
+
return {
|
|
761
|
+
success: false,
|
|
762
|
+
errorCode: 'not_authorized',
|
|
763
|
+
errorMessage: 'The subscription does not permit Hume AI features.',
|
|
764
|
+
};
|
|
765
|
+
}
|
|
766
|
+
let humeConfig;
|
|
767
|
+
if (context.context.recordStudioId) {
|
|
768
|
+
humeConfig = await this._recordsStore.getStudioHumeConfig(context.context.recordStudioId);
|
|
769
|
+
}
|
|
770
|
+
humeConfig !== null && humeConfig !== void 0 ? humeConfig : (humeConfig = this._humeConfig);
|
|
771
|
+
if (!humeConfig) {
|
|
1045
772
|
if (context.context.recordStudioId) {
|
|
1046
|
-
metricsFilter.studioId = context.context.recordStudioId;
|
|
1047
|
-
}
|
|
1048
|
-
else {
|
|
1049
|
-
metricsFilter.ownerId = context.context.recordOwnerId;
|
|
1050
|
-
}
|
|
1051
|
-
const metrics = yield this._metrics.getSubscriptionAiOpenAIRealtimeMetrics(metricsFilter);
|
|
1052
|
-
const config = yield this._config.getSubscriptionConfiguration();
|
|
1053
|
-
const features = getOpenAiFeatures(config, metrics.subscriptionStatus, metrics.subscriptionId, context.context.recordStudioId ? 'studio' : 'user');
|
|
1054
|
-
if (!features.realtime.allowed) {
|
|
1055
773
|
return {
|
|
1056
774
|
success: false,
|
|
1057
|
-
errorCode: '
|
|
1058
|
-
errorMessage: 'The
|
|
775
|
+
errorCode: 'invalid_request',
|
|
776
|
+
errorMessage: 'The studio does not have a Hume configuration.',
|
|
1059
777
|
};
|
|
1060
778
|
}
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
779
|
+
return {
|
|
780
|
+
success: false,
|
|
781
|
+
errorCode: 'not_authorized',
|
|
782
|
+
errorMessage: 'The subscription does not permit Hume AI features.',
|
|
783
|
+
};
|
|
784
|
+
}
|
|
785
|
+
if (this._policyStore) {
|
|
786
|
+
const privacyFeatures = await this._policyStore.getUserPrivacyFeatures(request.userId);
|
|
787
|
+
if (!privacyFeatures.allowAI) {
|
|
1064
788
|
return {
|
|
1065
789
|
success: false,
|
|
1066
|
-
errorCode: '
|
|
1067
|
-
errorMessage:
|
|
790
|
+
errorCode: 'not_authorized',
|
|
791
|
+
errorMessage: 'AI Access is not allowed',
|
|
1068
792
|
};
|
|
1069
793
|
}
|
|
1070
|
-
|
|
1071
|
-
|
|
794
|
+
}
|
|
795
|
+
const result = await this._humeInterface.getAccessToken({
|
|
796
|
+
apiKey: humeConfig.apiKey,
|
|
797
|
+
secretKey: humeConfig.secretKey,
|
|
798
|
+
});
|
|
799
|
+
if (result.success) {
|
|
800
|
+
return {
|
|
801
|
+
success: true,
|
|
802
|
+
accessToken: result.accessToken,
|
|
803
|
+
expiresIn: result.expiresIn,
|
|
804
|
+
issuedAt: result.issuedAt,
|
|
805
|
+
tokenType: result.tokenType,
|
|
806
|
+
};
|
|
807
|
+
}
|
|
808
|
+
else {
|
|
809
|
+
return result;
|
|
810
|
+
}
|
|
811
|
+
}
|
|
812
|
+
catch (err) {
|
|
813
|
+
const span = trace.getActiveSpan();
|
|
814
|
+
span === null || span === void 0 ? void 0 : span.recordException(err);
|
|
815
|
+
span === null || span === void 0 ? void 0 : span.setStatus({ code: SpanStatusCode.ERROR });
|
|
816
|
+
console.error('[AIController] Error handling get hume access token request:', err);
|
|
817
|
+
return {
|
|
818
|
+
success: false,
|
|
819
|
+
errorCode: 'server_error',
|
|
820
|
+
errorMessage: 'A server error occurred.',
|
|
821
|
+
};
|
|
822
|
+
}
|
|
823
|
+
}
|
|
824
|
+
async sloydGenerateModel(request) {
|
|
825
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
826
|
+
try {
|
|
827
|
+
if (!this._sloydInterface) {
|
|
828
|
+
return {
|
|
829
|
+
success: false,
|
|
830
|
+
errorCode: 'not_supported',
|
|
831
|
+
errorMessage: 'This operation is not supported.',
|
|
832
|
+
};
|
|
833
|
+
}
|
|
834
|
+
if (!request.userId) {
|
|
835
|
+
return {
|
|
836
|
+
success: false,
|
|
837
|
+
errorCode: 'not_logged_in',
|
|
838
|
+
errorMessage: 'The user must be logged in. Please provide a sessionKey.',
|
|
839
|
+
};
|
|
840
|
+
}
|
|
841
|
+
const context = await this._policies.constructAuthorizationContext({
|
|
842
|
+
recordKeyOrRecordName: request.recordName,
|
|
843
|
+
userId: request.userId,
|
|
844
|
+
});
|
|
845
|
+
if (context.success === false) {
|
|
846
|
+
return context;
|
|
847
|
+
}
|
|
848
|
+
const authResult = await this._policies.authorizeSubjectUsingContext(context.context, {
|
|
849
|
+
resourceKind: 'ai.sloyd',
|
|
850
|
+
action: 'create',
|
|
851
|
+
markers: null,
|
|
852
|
+
subjectId: request.userId,
|
|
853
|
+
subjectType: 'user',
|
|
854
|
+
});
|
|
855
|
+
if (authResult.success === false) {
|
|
856
|
+
return authResult;
|
|
857
|
+
}
|
|
858
|
+
let metricsFilter = {};
|
|
859
|
+
if (context.context.recordStudioId) {
|
|
860
|
+
metricsFilter.studioId = context.context.recordStudioId;
|
|
861
|
+
}
|
|
862
|
+
else {
|
|
863
|
+
metricsFilter.ownerId = context.context.recordOwnerId;
|
|
864
|
+
}
|
|
865
|
+
const metrics = await this._metrics.getSubscriptionAiSloydMetrics(metricsFilter);
|
|
866
|
+
const config = await this._config.getSubscriptionConfiguration();
|
|
867
|
+
const features = getSloydAiFeatures(config, metrics.subscriptionStatus, metrics.subscriptionId, context.context.recordStudioId ? 'studio' : 'user');
|
|
868
|
+
if (!features.allowed) {
|
|
869
|
+
return {
|
|
870
|
+
success: false,
|
|
871
|
+
errorCode: 'not_authorized',
|
|
872
|
+
errorMessage: 'The subscription does not permit Sloyd AI features.',
|
|
873
|
+
};
|
|
874
|
+
}
|
|
875
|
+
console.log(`[AIController] [sloydGenerateModel] [maxModelsPerPeriod: ${features.maxModelsPerPeriod} totalModelsInCurrentPeriod: ${metrics.totalModelsInCurrentPeriod}]`);
|
|
876
|
+
if (typeof features.maxModelsPerPeriod === 'number' &&
|
|
877
|
+
metrics.totalModelsInCurrentPeriod >=
|
|
878
|
+
features.maxModelsPerPeriod) {
|
|
879
|
+
return {
|
|
880
|
+
success: false,
|
|
881
|
+
errorCode: 'subscription_limit_reached',
|
|
882
|
+
errorMessage: `The request exceeds allowed subscription limits.`,
|
|
883
|
+
};
|
|
884
|
+
}
|
|
885
|
+
if (this._policyStore) {
|
|
886
|
+
const privacyFeatures = await this._policyStore.getUserPrivacyFeatures(request.userId);
|
|
887
|
+
if (!privacyFeatures.allowAI) {
|
|
1072
888
|
return {
|
|
1073
889
|
success: false,
|
|
1074
|
-
errorCode: '
|
|
1075
|
-
errorMessage:
|
|
890
|
+
errorCode: 'not_authorized',
|
|
891
|
+
errorMessage: 'AI Access is not allowed',
|
|
1076
892
|
};
|
|
1077
893
|
}
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
894
|
+
}
|
|
895
|
+
const result = await (request.baseModelId
|
|
896
|
+
? this._sloydInterface.editModel({
|
|
897
|
+
prompt: request.prompt,
|
|
898
|
+
modelMimeType: request.outputMimeType,
|
|
899
|
+
levelOfDetail: request.levelOfDetail,
|
|
900
|
+
thumbnailPreviewExportType: (_a = request.thumbnail) === null || _a === void 0 ? void 0 : _a.type,
|
|
901
|
+
thumbnailPreviewSizeX: (_b = request.thumbnail) === null || _b === void 0 ? void 0 : _b.width,
|
|
902
|
+
thumbnailPreviewSizeY: (_c = request.thumbnail) === null || _c === void 0 ? void 0 : _c.height,
|
|
903
|
+
interactionId: request.baseModelId,
|
|
904
|
+
})
|
|
905
|
+
: this._sloydInterface.createModel({
|
|
906
|
+
prompt: request.prompt,
|
|
907
|
+
modelMimeType: request.outputMimeType,
|
|
908
|
+
levelOfDetail: request.levelOfDetail,
|
|
909
|
+
thumbnailPreviewExportType: (_d = request.thumbnail) === null || _d === void 0 ? void 0 : _d.type,
|
|
910
|
+
thumbnailPreviewSizeX: (_e = request.thumbnail) === null || _e === void 0 ? void 0 : _e.width,
|
|
911
|
+
thumbnailPreviewSizeY: (_f = request.thumbnail) === null || _f === void 0 ? void 0 : _f.height,
|
|
912
|
+
}));
|
|
913
|
+
if (result.success === false) {
|
|
914
|
+
return result;
|
|
915
|
+
}
|
|
916
|
+
const response = {
|
|
917
|
+
success: true,
|
|
918
|
+
modelId: result.interactionId,
|
|
919
|
+
mimeType: request.outputMimeType,
|
|
920
|
+
modelData: typeof result.modelData === 'string'
|
|
921
|
+
? result.modelData
|
|
922
|
+
: fromByteArray(result.modelData),
|
|
923
|
+
thumbnailBase64: result.previewImage,
|
|
924
|
+
};
|
|
925
|
+
if ('name' in result && typeof result.name === 'string') {
|
|
926
|
+
response.name = result.name;
|
|
927
|
+
response.confidence = result.confidenceScore;
|
|
928
|
+
}
|
|
929
|
+
await this._metrics.recordSloydMetrics({
|
|
930
|
+
userId: (_g = context.context.recordOwnerId) !== null && _g !== void 0 ? _g : undefined,
|
|
931
|
+
studioId: (_h = context.context.recordStudioId) !== null && _h !== void 0 ? _h : undefined,
|
|
932
|
+
modelId: response.modelId,
|
|
933
|
+
confidence: response.confidence,
|
|
934
|
+
mimeType: response.mimeType,
|
|
935
|
+
modelData: response.modelData,
|
|
936
|
+
name: response.name,
|
|
937
|
+
thumbnailBase64: response.thumbnailBase64,
|
|
938
|
+
createdAtMs: Date.now(),
|
|
939
|
+
baseModelId: request.baseModelId,
|
|
940
|
+
modelsCreated: 1,
|
|
941
|
+
});
|
|
942
|
+
return response;
|
|
943
|
+
}
|
|
944
|
+
catch (err) {
|
|
945
|
+
console.error('[AIController] Error handling sloyd create model request:', err);
|
|
946
|
+
return {
|
|
947
|
+
success: false,
|
|
948
|
+
errorCode: 'server_error',
|
|
949
|
+
errorMessage: 'A server error occurred.',
|
|
950
|
+
};
|
|
951
|
+
}
|
|
952
|
+
}
|
|
953
|
+
async createOpenAIRealtimeSessionToken(request) {
|
|
954
|
+
var _a, _b, _c, _d;
|
|
955
|
+
try {
|
|
956
|
+
if (!this._openAIRealtimeInterface) {
|
|
1090
957
|
return {
|
|
1091
|
-
success:
|
|
1092
|
-
|
|
1093
|
-
|
|
958
|
+
success: false,
|
|
959
|
+
errorCode: 'not_supported',
|
|
960
|
+
errorMessage: 'This operation is not supported.',
|
|
961
|
+
};
|
|
962
|
+
}
|
|
963
|
+
if (!request.userId) {
|
|
964
|
+
return {
|
|
965
|
+
success: false,
|
|
966
|
+
errorCode: 'not_logged_in',
|
|
967
|
+
errorMessage: 'The user must be logged in. Please provide a sessionKey.',
|
|
968
|
+
};
|
|
969
|
+
}
|
|
970
|
+
const context = await this._policies.constructAuthorizationContext({
|
|
971
|
+
recordKeyOrRecordName: request.recordName,
|
|
972
|
+
userId: request.userId,
|
|
973
|
+
});
|
|
974
|
+
if (context.success === false) {
|
|
975
|
+
return context;
|
|
976
|
+
}
|
|
977
|
+
const authResult = await this._policies.authorizeSubjectUsingContext(context.context, {
|
|
978
|
+
resourceKind: 'ai.openai.realtime',
|
|
979
|
+
action: 'create',
|
|
980
|
+
markers: null,
|
|
981
|
+
subjectId: request.userId,
|
|
982
|
+
subjectType: 'user',
|
|
983
|
+
});
|
|
984
|
+
if (authResult.success === false) {
|
|
985
|
+
return authResult;
|
|
986
|
+
}
|
|
987
|
+
let metricsFilter = {};
|
|
988
|
+
if (context.context.recordStudioId) {
|
|
989
|
+
metricsFilter.studioId = context.context.recordStudioId;
|
|
990
|
+
}
|
|
991
|
+
else {
|
|
992
|
+
metricsFilter.ownerId = context.context.recordOwnerId;
|
|
993
|
+
}
|
|
994
|
+
const metrics = await this._metrics.getSubscriptionAiOpenAIRealtimeMetrics(metricsFilter);
|
|
995
|
+
const config = await this._config.getSubscriptionConfiguration();
|
|
996
|
+
const features = getOpenAiFeatures(config, metrics.subscriptionStatus, metrics.subscriptionId, context.context.recordStudioId ? 'studio' : 'user');
|
|
997
|
+
if (!features.realtime.allowed) {
|
|
998
|
+
return {
|
|
999
|
+
success: false,
|
|
1000
|
+
errorCode: 'not_authorized',
|
|
1001
|
+
errorMessage: 'The subscription does not permit OpenAI Realtime features.',
|
|
1002
|
+
};
|
|
1003
|
+
}
|
|
1004
|
+
if (typeof features.realtime.maxSessionsPerPeriod === 'number' &&
|
|
1005
|
+
metrics.totalSessionsInCurrentPeriod >=
|
|
1006
|
+
features.realtime.maxSessionsPerPeriod) {
|
|
1007
|
+
return {
|
|
1008
|
+
success: false,
|
|
1009
|
+
errorCode: 'subscription_limit_reached',
|
|
1010
|
+
errorMessage: `The request exceeds allowed subscription limits.`,
|
|
1094
1011
|
};
|
|
1095
1012
|
}
|
|
1096
|
-
|
|
1097
|
-
|
|
1013
|
+
if (typeof features.realtime.allowedModels !== 'undefined' &&
|
|
1014
|
+
!features.realtime.allowedModels.includes(request.request.model)) {
|
|
1098
1015
|
return {
|
|
1099
1016
|
success: false,
|
|
1100
|
-
errorCode: '
|
|
1101
|
-
errorMessage: '
|
|
1017
|
+
errorCode: 'subscription_limit_reached',
|
|
1018
|
+
errorMessage: "The subscription doesn't support the given model.",
|
|
1102
1019
|
};
|
|
1103
1020
|
}
|
|
1104
|
-
|
|
1021
|
+
const tokenRequest = {
|
|
1022
|
+
...request.request,
|
|
1023
|
+
maxResponseOutputTokens: (_b = (_a = features.realtime.maxResponseOutputTokens) !== null && _a !== void 0 ? _a : request.request.maxResponseOutputTokens) !== null && _b !== void 0 ? _b : undefined,
|
|
1024
|
+
};
|
|
1025
|
+
const result = await this._openAIRealtimeInterface.createRealtimeSessionToken(tokenRequest);
|
|
1026
|
+
if (result.success === false) {
|
|
1027
|
+
return result;
|
|
1028
|
+
}
|
|
1029
|
+
await this._metrics.recordOpenAIRealtimeMetrics({
|
|
1030
|
+
userId: (_c = context.context.recordOwnerId) !== null && _c !== void 0 ? _c : undefined,
|
|
1031
|
+
studioId: (_d = context.context.recordStudioId) !== null && _d !== void 0 ? _d : undefined,
|
|
1032
|
+
sessionId: result.sessionId,
|
|
1033
|
+
createdAtMs: Date.now(),
|
|
1034
|
+
request: tokenRequest,
|
|
1035
|
+
});
|
|
1036
|
+
return {
|
|
1037
|
+
success: true,
|
|
1038
|
+
sessionId: result.sessionId,
|
|
1039
|
+
clientSecret: result.clientSecret,
|
|
1040
|
+
};
|
|
1041
|
+
}
|
|
1042
|
+
catch (err) {
|
|
1043
|
+
console.error('[AIController] Error handling createOpenAIRealtimeSessionToken request:', err);
|
|
1044
|
+
return {
|
|
1045
|
+
success: false,
|
|
1046
|
+
errorCode: 'server_error',
|
|
1047
|
+
errorMessage: 'A server error occurred.',
|
|
1048
|
+
};
|
|
1049
|
+
}
|
|
1105
1050
|
}
|
|
1106
1051
|
_matchesSubscriptionTiers(tier, allowedTiers) {
|
|
1107
1052
|
return allowedTiers === true || allowedTiers.has(tier);
|