@modelprofile.com/flexharness-providers 7.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist_ts_media_openai/image.d.ts +46 -0
- package/dist_ts_media_openai/image.js +110 -0
- package/dist_ts_media_openai/index.d.ts +10 -0
- package/dist_ts_media_openai/index.js +16 -0
- package/dist_ts_media_openai/plugins.d.ts +3 -0
- package/dist_ts_media_openai/plugins.js +4 -0
- package/dist_ts_openai_account/index.d.ts +6 -0
- package/dist_ts_openai_account/index.js +7 -0
- package/dist_ts_openai_account/plugins.d.ts +7 -0
- package/dist_ts_openai_account/plugins.js +6 -0
- package/dist_ts_openai_account/smartai.providers.credentials.d.ts +7 -0
- package/dist_ts_openai_account/smartai.providers.credentials.js +126 -0
- package/dist_ts_openai_account/smartai.providers.error.d.ts +11 -0
- package/dist_ts_openai_account/smartai.providers.error.js +30 -0
- package/dist_ts_openai_account/smartai.providers.interfaces.d.ts +161 -0
- package/dist_ts_openai_account/smartai.providers.interfaces.js +2 -0
- package/dist_ts_openai_account/smartai.providers.openai.d.ts +29 -0
- package/dist_ts_openai_account/smartai.providers.openai.js +1075 -0
- package/dist_ts_openai_account/smartai.providers.registry.d.ts +11 -0
- package/dist_ts_openai_account/smartai.providers.registry.js +53 -0
- package/dist_ts_openai_auth/index.d.ts +6 -0
- package/dist_ts_openai_auth/index.js +10 -0
- package/dist_ts_openai_auth/interfaces.d.ts +71 -0
- package/dist_ts_openai_auth/interfaces.js +2 -0
- package/dist_ts_openai_auth/smartai.auth.openai.d.ts +34 -0
- package/dist_ts_openai_auth/smartai.auth.openai.js +603 -0
- package/dist_ts_openai_auth/smartai.middleware.openai.d.ts +6 -0
- package/dist_ts_openai_auth/smartai.middleware.openai.js +47 -0
- package/dist_ts_openai_auth_files/index.d.ts +43 -0
- package/dist_ts_openai_auth_files/index.js +377 -0
- package/dist_ts_openai_auth_files/plugins.d.ts +9 -0
- package/dist_ts_openai_auth_files/plugins.js +10 -0
- package/dist_ts_providers/anthropic/index.d.ts +8 -0
- package/dist_ts_providers/anthropic/index.js +13 -0
- package/dist_ts_providers/anthropic/plugins.d.ts +4 -0
- package/dist_ts_providers/anthropic/plugins.js +4 -0
- package/dist_ts_providers/anthropic/smartai.middleware.anthropic.d.ts +8 -0
- package/dist_ts_providers/anthropic/smartai.middleware.anthropic.js +10 -0
- package/dist_ts_providers/google/index.d.ts +5 -0
- package/dist_ts_providers/google/index.js +6 -0
- package/dist_ts_providers/google/plugins.d.ts +3 -0
- package/dist_ts_providers/google/plugins.js +3 -0
- package/dist_ts_providers/groq/index.d.ts +5 -0
- package/dist_ts_providers/groq/index.js +6 -0
- package/dist_ts_providers/groq/plugins.d.ts +3 -0
- package/dist_ts_providers/groq/plugins.js +3 -0
- package/dist_ts_providers/index.d.ts +8 -0
- package/dist_ts_providers/index.js +9 -0
- package/dist_ts_providers/mistral/index.d.ts +5 -0
- package/dist_ts_providers/mistral/index.js +6 -0
- package/dist_ts_providers/mistral/plugins.d.ts +3 -0
- package/dist_ts_providers/mistral/plugins.js +3 -0
- package/dist_ts_providers/ollama/index.d.ts +6 -0
- package/dist_ts_providers/ollama/index.js +7 -0
- package/dist_ts_providers/ollama/interfaces.d.ts +26 -0
- package/dist_ts_providers/ollama/interfaces.js +2 -0
- package/dist_ts_providers/ollama/smartai.provider.ollama.d.ts +8 -0
- package/dist_ts_providers/ollama/smartai.provider.ollama.js +378 -0
- package/dist_ts_providers/openai/index.d.ts +15 -0
- package/dist_ts_providers/openai/index.js +14 -0
- package/dist_ts_providers/openai/plugins.d.ts +6 -0
- package/dist_ts_providers/openai/plugins.js +4 -0
- package/dist_ts_providers/perplexity/index.d.ts +5 -0
- package/dist_ts_providers/perplexity/index.js +6 -0
- package/dist_ts_providers/perplexity/plugins.d.ts +3 -0
- package/dist_ts_providers/perplexity/plugins.js +3 -0
- package/dist_ts_providers/xai/index.d.ts +5 -0
- package/dist_ts_providers/xai/index.js +6 -0
- package/dist_ts_providers/xai/plugins.d.ts +3 -0
- package/dist_ts_providers/xai/plugins.js +3 -0
- package/dist_ts_research/index.d.ts +19 -0
- package/dist_ts_research/index.js +98 -0
- package/dist_ts_research/plugins.d.ts +2 -0
- package/dist_ts_research/plugins.js +3 -0
- package/license.md +21 -0
- package/openai-codex-license.txt +201 -0
- package/package.json +105 -0
- package/readme.md +62 -0
- package/third-party-notices.md +19 -0
- package/ts_media_openai/image.ts +147 -0
- package/ts_media_openai/index.ts +26 -0
- package/ts_media_openai/plugins.ts +3 -0
- package/ts_media_openai/readme.md +37 -0
- package/ts_openai_account/index.ts +11 -0
- package/ts_openai_account/plugins.ts +9 -0
- package/ts_openai_account/readme.md +37 -0
- package/ts_openai_account/smartai.providers.credentials.ts +163 -0
- package/ts_openai_account/smartai.providers.error.ts +49 -0
- package/ts_openai_account/smartai.providers.interfaces.ts +222 -0
- package/ts_openai_account/smartai.providers.openai.ts +1209 -0
- package/ts_openai_account/smartai.providers.registry.ts +57 -0
- package/ts_openai_auth/index.ts +12 -0
- package/ts_openai_auth/interfaces.ts +89 -0
- package/ts_openai_auth/readme.md +37 -0
- package/ts_openai_auth/smartai.auth.openai.ts +789 -0
- package/ts_openai_auth/smartai.middleware.openai.ts +55 -0
- package/ts_openai_auth_files/index.ts +499 -0
- package/ts_openai_auth_files/plugins.ts +13 -0
- package/ts_openai_auth_files/readme.md +37 -0
- package/ts_providers/anthropic/index.ts +20 -0
- package/ts_providers/anthropic/plugins.ts +4 -0
- package/ts_providers/anthropic/readme.md +37 -0
- package/ts_providers/anthropic/smartai.middleware.anthropic.ts +12 -0
- package/ts_providers/google/index.ts +8 -0
- package/ts_providers/google/plugins.ts +3 -0
- package/ts_providers/google/readme.md +37 -0
- package/ts_providers/groq/index.ts +8 -0
- package/ts_providers/groq/plugins.ts +3 -0
- package/ts_providers/groq/readme.md +37 -0
- package/ts_providers/index.ts +8 -0
- package/ts_providers/mistral/index.ts +8 -0
- package/ts_providers/mistral/plugins.ts +3 -0
- package/ts_providers/mistral/readme.md +37 -0
- package/ts_providers/ollama/index.ts +8 -0
- package/ts_providers/ollama/interfaces.ts +28 -0
- package/ts_providers/ollama/readme.md +37 -0
- package/ts_providers/ollama/smartai.provider.ollama.ts +426 -0
- package/ts_providers/openai/index.ts +29 -0
- package/ts_providers/openai/plugins.ts +6 -0
- package/ts_providers/openai/readme.md +37 -0
- package/ts_providers/perplexity/index.ts +8 -0
- package/ts_providers/perplexity/plugins.ts +3 -0
- package/ts_providers/perplexity/readme.md +37 -0
- package/ts_providers/readme.md +62 -0
- package/ts_providers/xai/index.ts +8 -0
- package/ts_providers/xai/plugins.ts +3 -0
- package/ts_providers/xai/readme.md +37 -0
- package/ts_research/index.ts +120 -0
- package/ts_research/plugins.ts +2 -0
- package/ts_research/readme.md +37 -0
|
@@ -0,0 +1,1075 @@
|
|
|
1
|
+
// OpenAI protocol portions are adapted in TypeScript; see third-party-notices.md.
|
|
2
|
+
import * as plugins from './plugins.js';
|
|
3
|
+
import { OPENAI_CHATGPT_CODEX_BASE_URL, OPENAI_CHATGPT_DEFAULT_ORIGINATOR, completeOpenAiChatGptDeviceCodeLogin, createOpenAiChatGptBrowserAuthorization, exchangeOpenAiChatGptBrowserAuthorizationCode, parseOpenAiChatGptBrowserCallback, parseOpenAiChatGptTokenInfo, refreshOpenAiChatGptTokenData, requestOpenAiChatGptDeviceCode, revokeOpenAiChatGptToken, } from '@modelprofile.com/flexharness-providers/auth';
|
|
4
|
+
import { createSmartAiProviderError, SmartAiProviderError } from './smartai.providers.error.js';
|
|
5
|
+
const defaultBrowserLoginTimeoutMs = 11 * 60 * 1000;
|
|
6
|
+
const defaultDeviceLoginTimeoutMs = 15 * 60 * 1000;
|
|
7
|
+
const defaultOperationTimeoutMs = 30_000;
|
|
8
|
+
const maximumOperationTimeoutMs = 20 * 60 * 1000;
|
|
9
|
+
const maximumCatalogBytes = 2 * 1024 * 1024;
|
|
10
|
+
const maximumAccountRateLimitsBytes = 256 * 1024;
|
|
11
|
+
const maximumCatalogModels = 256;
|
|
12
|
+
const maximumAdditionalRateLimits = 128;
|
|
13
|
+
const maximumCursorBytes = 4096;
|
|
14
|
+
const maximumModelPageSize = 50;
|
|
15
|
+
const defaultClientVersion = '0.146.1';
|
|
16
|
+
const maximumHeaderBytes = 16 * 1024;
|
|
17
|
+
const maximumCallbackUrlBytes = 4096;
|
|
18
|
+
const accountRateLimitsUrl = 'https://chatgpt.com/backend-api/wham/usage';
|
|
19
|
+
class ModelHttpError extends Error {
|
|
20
|
+
status;
|
|
21
|
+
constructor(status) {
|
|
22
|
+
super('Model catalog request failed.');
|
|
23
|
+
this.status = status;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
class AccountRateLimitsHttpError extends Error {
|
|
27
|
+
status;
|
|
28
|
+
constructor(status) {
|
|
29
|
+
super('Account rate-limits request failed.');
|
|
30
|
+
this.status = status;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
const isRecord = (valueArg) => typeof valueArg === 'object' && valueArg !== null && !Array.isArray(valueArg);
|
|
34
|
+
const boundedString = (valueArg, maximumBytesArg, allowEmptyArg = false) => {
|
|
35
|
+
if (typeof valueArg !== 'string'
|
|
36
|
+
|| (!allowEmptyArg && valueArg.length === 0)
|
|
37
|
+
|| plugins.Buffer.byteLength(valueArg, 'utf8') > maximumBytesArg) {
|
|
38
|
+
throw createSmartAiProviderError('PROTOCOL_ERROR');
|
|
39
|
+
}
|
|
40
|
+
return valueArg;
|
|
41
|
+
};
|
|
42
|
+
const createOperation = (optionsArg, defaultTimeoutMsArg) => {
|
|
43
|
+
const timeoutMs = optionsArg.timeoutMs ?? defaultTimeoutMsArg;
|
|
44
|
+
if (!Number.isSafeInteger(timeoutMs) || timeoutMs < 1 || timeoutMs > maximumOperationTimeoutMs) {
|
|
45
|
+
throw createSmartAiProviderError('INVALID_ARGUMENT');
|
|
46
|
+
}
|
|
47
|
+
const controller = new AbortController();
|
|
48
|
+
let timedOut = false;
|
|
49
|
+
const onExternalAbort = () => controller.abort();
|
|
50
|
+
optionsArg.signal?.addEventListener('abort', onExternalAbort, { once: true });
|
|
51
|
+
if (optionsArg.signal?.aborted)
|
|
52
|
+
controller.abort();
|
|
53
|
+
const timer = setTimeout(() => {
|
|
54
|
+
timedOut = true;
|
|
55
|
+
controller.abort();
|
|
56
|
+
}, timeoutMs);
|
|
57
|
+
return {
|
|
58
|
+
controller,
|
|
59
|
+
signal: controller.signal,
|
|
60
|
+
get timedOut() {
|
|
61
|
+
return timedOut;
|
|
62
|
+
},
|
|
63
|
+
cleanup: () => {
|
|
64
|
+
clearTimeout(timer);
|
|
65
|
+
optionsArg.signal?.removeEventListener('abort', onExternalAbort);
|
|
66
|
+
},
|
|
67
|
+
};
|
|
68
|
+
};
|
|
69
|
+
const classifyOperationError = (errorArg, operationArg, fallbackArg) => {
|
|
70
|
+
if (operationArg.timedOut)
|
|
71
|
+
return 'TIMEOUT';
|
|
72
|
+
if (operationArg.signal.aborted)
|
|
73
|
+
return 'ABORTED';
|
|
74
|
+
if (errorArg instanceof SmartAiProviderError && errorArg.code === 'ABORTED')
|
|
75
|
+
return 'ABORTED';
|
|
76
|
+
if (errorArg instanceof SmartAiProviderError && errorArg.code === 'TIMEOUT')
|
|
77
|
+
return 'TIMEOUT';
|
|
78
|
+
return fallbackArg;
|
|
79
|
+
};
|
|
80
|
+
const toTokenData = (credentialArg) => {
|
|
81
|
+
if (credentialArg.kind !== 'chatgptOAuth'
|
|
82
|
+
|| credentialArg.providerId !== 'openai'
|
|
83
|
+
|| !credentialArg.accessToken
|
|
84
|
+
|| !credentialArg.refreshToken
|
|
85
|
+
|| !credentialArg.idToken) {
|
|
86
|
+
throw createSmartAiProviderError('CREDENTIAL_INVALID');
|
|
87
|
+
}
|
|
88
|
+
let tokenInfo;
|
|
89
|
+
try {
|
|
90
|
+
tokenInfo = parseOpenAiChatGptTokenInfo(credentialArg.idToken);
|
|
91
|
+
}
|
|
92
|
+
catch {
|
|
93
|
+
throw createSmartAiProviderError('CREDENTIAL_INVALID');
|
|
94
|
+
}
|
|
95
|
+
return {
|
|
96
|
+
accessToken: credentialArg.accessToken,
|
|
97
|
+
refreshToken: credentialArg.refreshToken,
|
|
98
|
+
idToken: credentialArg.idToken,
|
|
99
|
+
accountId: tokenInfo.chatgptAccountId,
|
|
100
|
+
tokenInfo,
|
|
101
|
+
};
|
|
102
|
+
};
|
|
103
|
+
const toCredential = (tokenDataArg, lastRefreshAtArg) => {
|
|
104
|
+
if (!tokenDataArg.idToken)
|
|
105
|
+
throw createSmartAiProviderError('CREDENTIAL_INVALID');
|
|
106
|
+
return {
|
|
107
|
+
kind: 'chatgptOAuth',
|
|
108
|
+
providerId: 'openai',
|
|
109
|
+
accessToken: tokenDataArg.accessToken,
|
|
110
|
+
refreshToken: tokenDataArg.refreshToken,
|
|
111
|
+
idToken: tokenDataArg.idToken,
|
|
112
|
+
...(lastRefreshAtArg === undefined ? {} : { lastRefreshAt: lastRefreshAtArg }),
|
|
113
|
+
};
|
|
114
|
+
};
|
|
115
|
+
const toSummary = (credentialArg) => {
|
|
116
|
+
const tokenData = toTokenData(credentialArg);
|
|
117
|
+
return {
|
|
118
|
+
providerId: 'openai',
|
|
119
|
+
authKind: 'chatgptOAuth',
|
|
120
|
+
...(tokenData.tokenInfo.chatgptAccountId
|
|
121
|
+
? { accountId: tokenData.tokenInfo.chatgptAccountId }
|
|
122
|
+
: {}),
|
|
123
|
+
...(tokenData.tokenInfo.email ? { email: tokenData.tokenInfo.email } : {}),
|
|
124
|
+
...(tokenData.tokenInfo.chatgptPlanType ? { plan: tokenData.tokenInfo.chatgptPlanType } : {}),
|
|
125
|
+
};
|
|
126
|
+
};
|
|
127
|
+
const closeServer = async (serverArg, socketsArg) => {
|
|
128
|
+
await new Promise((resolve, reject) => {
|
|
129
|
+
if (!serverArg.listening) {
|
|
130
|
+
resolve();
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
serverArg.close((errorArg) => {
|
|
134
|
+
if (errorArg?.code === 'ERR_SERVER_NOT_RUNNING') {
|
|
135
|
+
resolve();
|
|
136
|
+
}
|
|
137
|
+
else if (errorArg) {
|
|
138
|
+
reject(errorArg);
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
resolve();
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
for (const socket of socketsArg)
|
|
145
|
+
socket.destroy();
|
|
146
|
+
});
|
|
147
|
+
};
|
|
148
|
+
const bindBrowserCallbackServer = async (portsArg, signalArg) => {
|
|
149
|
+
if (portsArg.length === 0
|
|
150
|
+
|| portsArg.some((port) => !Number.isSafeInteger(port) || port < 1 || port > 65535)) {
|
|
151
|
+
throw createSmartAiProviderError('INVALID_ARGUMENT');
|
|
152
|
+
}
|
|
153
|
+
let lastError;
|
|
154
|
+
for (let index = 0; index < portsArg.length; index++) {
|
|
155
|
+
const port = portsArg[index];
|
|
156
|
+
const sockets = new Set();
|
|
157
|
+
let authorization;
|
|
158
|
+
let settled = false;
|
|
159
|
+
let resolveCallback;
|
|
160
|
+
let rejectCallback;
|
|
161
|
+
const callback = new Promise((resolve, reject) => {
|
|
162
|
+
resolveCallback = resolve;
|
|
163
|
+
rejectCallback = reject;
|
|
164
|
+
});
|
|
165
|
+
void callback.catch(() => undefined);
|
|
166
|
+
const server = plugins.http.createServer({ maxHeaderSize: maximumHeaderBytes }, (request, response) => {
|
|
167
|
+
const rejectRequest = (status) => {
|
|
168
|
+
response.writeHead(status, {
|
|
169
|
+
'Content-Type': 'text/plain; charset=utf-8',
|
|
170
|
+
'Cache-Control': 'no-store',
|
|
171
|
+
'X-Content-Type-Options': 'nosniff',
|
|
172
|
+
});
|
|
173
|
+
response.end('OpenAI login callback rejected.');
|
|
174
|
+
};
|
|
175
|
+
const host = request.headers.host;
|
|
176
|
+
const requestUrl = request.url;
|
|
177
|
+
const headerBytes = request.rawHeaders.reduce((total, entry) => total + plugins.Buffer.byteLength(entry, 'utf8'), 0);
|
|
178
|
+
if (settled
|
|
179
|
+
|| !authorization
|
|
180
|
+
|| request.method !== 'GET'
|
|
181
|
+
|| host !== `localhost:${port}`
|
|
182
|
+
|| typeof requestUrl !== 'string'
|
|
183
|
+
|| plugins.Buffer.byteLength(requestUrl, 'utf8') > maximumCallbackUrlBytes
|
|
184
|
+
|| headerBytes > maximumHeaderBytes) {
|
|
185
|
+
rejectRequest(settled ? 410 : 400);
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
const callbackUrl = `http://${host}${requestUrl}`;
|
|
189
|
+
let providerDenied = false;
|
|
190
|
+
try {
|
|
191
|
+
const callback = parseOpenAiChatGptBrowserCallback(callbackUrl, {
|
|
192
|
+
expectedState: authorization.state,
|
|
193
|
+
expectedRedirectUri: authorization.redirectUri,
|
|
194
|
+
});
|
|
195
|
+
providerDenied = 'providerError' in callback;
|
|
196
|
+
}
|
|
197
|
+
catch {
|
|
198
|
+
rejectRequest(400);
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
settled = true;
|
|
202
|
+
response.writeHead(200, {
|
|
203
|
+
'Content-Type': 'text/plain; charset=utf-8',
|
|
204
|
+
'Cache-Control': 'no-store',
|
|
205
|
+
'X-Content-Type-Options': 'nosniff',
|
|
206
|
+
});
|
|
207
|
+
response.end(providerDenied
|
|
208
|
+
? 'OpenAI login was not authorized. You may close this window.'
|
|
209
|
+
: 'OpenAI login completed. You may close this window.');
|
|
210
|
+
resolveCallback(callbackUrl);
|
|
211
|
+
});
|
|
212
|
+
server.on('connection', (socket) => {
|
|
213
|
+
sockets.add(socket);
|
|
214
|
+
socket.once('close', () => sockets.delete(socket));
|
|
215
|
+
});
|
|
216
|
+
let serverClosePromise;
|
|
217
|
+
const ensureServerClosed = () => {
|
|
218
|
+
if (!serverClosePromise) {
|
|
219
|
+
serverClosePromise = closeServer(server, sockets).finally(() => {
|
|
220
|
+
serverClosePromise = undefined;
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
return serverClosePromise;
|
|
224
|
+
};
|
|
225
|
+
const onAbort = () => {
|
|
226
|
+
if (!settled) {
|
|
227
|
+
settled = true;
|
|
228
|
+
rejectCallback(createSmartAiProviderError('ABORTED'));
|
|
229
|
+
}
|
|
230
|
+
void ensureServerClosed().catch(() => undefined);
|
|
231
|
+
};
|
|
232
|
+
signalArg.addEventListener('abort', onAbort, { once: true });
|
|
233
|
+
try {
|
|
234
|
+
await new Promise((resolve, reject) => {
|
|
235
|
+
const onError = (errorArg) => {
|
|
236
|
+
server.removeListener('listening', onListening);
|
|
237
|
+
reject(errorArg);
|
|
238
|
+
};
|
|
239
|
+
const onListening = () => {
|
|
240
|
+
server.removeListener('error', onError);
|
|
241
|
+
resolve();
|
|
242
|
+
};
|
|
243
|
+
server.once('error', onError);
|
|
244
|
+
server.once('listening', onListening);
|
|
245
|
+
server.listen(port, '127.0.0.1');
|
|
246
|
+
});
|
|
247
|
+
if (signalArg.aborted)
|
|
248
|
+
onAbort();
|
|
249
|
+
return {
|
|
250
|
+
port,
|
|
251
|
+
waitForCallback: async (authorizationArg) => {
|
|
252
|
+
authorization = authorizationArg;
|
|
253
|
+
return callback;
|
|
254
|
+
},
|
|
255
|
+
close: async () => {
|
|
256
|
+
signalArg.removeEventListener('abort', onAbort);
|
|
257
|
+
if (!settled) {
|
|
258
|
+
settled = true;
|
|
259
|
+
rejectCallback(createSmartAiProviderError('LOGIN_CANCELED'));
|
|
260
|
+
}
|
|
261
|
+
await ensureServerClosed();
|
|
262
|
+
},
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
catch (errorArg) {
|
|
266
|
+
signalArg.removeEventListener('abort', onAbort);
|
|
267
|
+
await ensureServerClosed().catch(() => undefined);
|
|
268
|
+
lastError = errorArg;
|
|
269
|
+
const code = errorArg.code;
|
|
270
|
+
if (code !== 'EADDRINUSE' || index === portsArg.length - 1)
|
|
271
|
+
break;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
throw createSmartAiProviderError(lastError?.code === 'EADDRINUSE'
|
|
275
|
+
? 'LOGIN_BUSY'
|
|
276
|
+
: 'LOGIN_FAILED');
|
|
277
|
+
};
|
|
278
|
+
class OpenAiProviderLoginHandle {
|
|
279
|
+
prompt;
|
|
280
|
+
abortController;
|
|
281
|
+
cleanup;
|
|
282
|
+
onDone;
|
|
283
|
+
completion;
|
|
284
|
+
closePromise;
|
|
285
|
+
done = false;
|
|
286
|
+
constructor(prompt, completionArg, abortController, cleanup, onDone) {
|
|
287
|
+
this.prompt = prompt;
|
|
288
|
+
this.abortController = abortController;
|
|
289
|
+
this.cleanup = cleanup;
|
|
290
|
+
this.onDone = onDone;
|
|
291
|
+
this.completion = completionArg.finally(async () => {
|
|
292
|
+
this.done = true;
|
|
293
|
+
try {
|
|
294
|
+
await this.cleanup();
|
|
295
|
+
}
|
|
296
|
+
finally {
|
|
297
|
+
this.onDone();
|
|
298
|
+
}
|
|
299
|
+
});
|
|
300
|
+
void this.completion.catch(() => undefined);
|
|
301
|
+
}
|
|
302
|
+
async cancel() {
|
|
303
|
+
if (this.done || this.abortController.signal.aborted)
|
|
304
|
+
return 'notFound';
|
|
305
|
+
this.abortController.abort();
|
|
306
|
+
return 'canceled';
|
|
307
|
+
}
|
|
308
|
+
async close() {
|
|
309
|
+
if (this.closePromise)
|
|
310
|
+
return this.closePromise;
|
|
311
|
+
const closeAttempt = (async () => {
|
|
312
|
+
await this.cancel();
|
|
313
|
+
await this.completion.catch(() => undefined);
|
|
314
|
+
await this.cleanup();
|
|
315
|
+
})();
|
|
316
|
+
this.closePromise = closeAttempt;
|
|
317
|
+
try {
|
|
318
|
+
await closeAttempt;
|
|
319
|
+
}
|
|
320
|
+
catch (error) {
|
|
321
|
+
this.closePromise = undefined;
|
|
322
|
+
throw error;
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
const normalizeModelListOptions = (optionsArg) => {
|
|
327
|
+
const limit = optionsArg.limit ?? maximumModelPageSize;
|
|
328
|
+
if (!Number.isSafeInteger(limit)
|
|
329
|
+
|| limit < 1
|
|
330
|
+
|| limit > maximumModelPageSize
|
|
331
|
+
|| (optionsArg.cursor !== undefined
|
|
332
|
+
&& (optionsArg.cursor.length === 0
|
|
333
|
+
|| plugins.Buffer.byteLength(optionsArg.cursor, 'utf8') > maximumCursorBytes))
|
|
334
|
+
|| (optionsArg.includeHidden !== undefined && typeof optionsArg.includeHidden !== 'boolean')) {
|
|
335
|
+
throw createSmartAiProviderError('INVALID_ARGUMENT');
|
|
336
|
+
}
|
|
337
|
+
return { ...optionsArg, limit, includeHidden: optionsArg.includeHidden ?? false };
|
|
338
|
+
};
|
|
339
|
+
const readBoundedJson = async (responseArg, signalArg, maximumBytesArg) => {
|
|
340
|
+
const declared = responseArg.headers.get('content-length');
|
|
341
|
+
if (declared !== null && (!/^\d+$/.test(declared) || Number(declared) > maximumBytesArg)) {
|
|
342
|
+
await responseArg.body?.cancel().catch(() => undefined);
|
|
343
|
+
throw createSmartAiProviderError('PROTOCOL_ERROR');
|
|
344
|
+
}
|
|
345
|
+
if (!responseArg.body)
|
|
346
|
+
throw createSmartAiProviderError('PROTOCOL_ERROR');
|
|
347
|
+
const reader = responseArg.body.getReader();
|
|
348
|
+
const chunks = [];
|
|
349
|
+
let size = 0;
|
|
350
|
+
let completed = false;
|
|
351
|
+
const onAbort = () => {
|
|
352
|
+
void reader.cancel().catch(() => undefined);
|
|
353
|
+
};
|
|
354
|
+
signalArg.addEventListener('abort', onAbort, { once: true });
|
|
355
|
+
if (signalArg.aborted)
|
|
356
|
+
onAbort();
|
|
357
|
+
try {
|
|
358
|
+
while (true) {
|
|
359
|
+
if (signalArg.aborted)
|
|
360
|
+
throw createSmartAiProviderError('ABORTED');
|
|
361
|
+
const { done, value } = await reader.read();
|
|
362
|
+
if (signalArg.aborted)
|
|
363
|
+
throw createSmartAiProviderError('ABORTED');
|
|
364
|
+
if (done)
|
|
365
|
+
break;
|
|
366
|
+
size += value.byteLength;
|
|
367
|
+
if (size > maximumBytesArg) {
|
|
368
|
+
await reader.cancel().catch(() => undefined);
|
|
369
|
+
throw createSmartAiProviderError('PROTOCOL_ERROR');
|
|
370
|
+
}
|
|
371
|
+
chunks.push(value);
|
|
372
|
+
}
|
|
373
|
+
completed = true;
|
|
374
|
+
}
|
|
375
|
+
finally {
|
|
376
|
+
signalArg.removeEventListener('abort', onAbort);
|
|
377
|
+
if (!completed)
|
|
378
|
+
void reader.cancel().catch(() => undefined);
|
|
379
|
+
reader.releaseLock();
|
|
380
|
+
}
|
|
381
|
+
const body = plugins.Buffer.allocUnsafe(size);
|
|
382
|
+
let offset = 0;
|
|
383
|
+
for (const chunk of chunks) {
|
|
384
|
+
body.set(chunk, offset);
|
|
385
|
+
offset += chunk.byteLength;
|
|
386
|
+
}
|
|
387
|
+
try {
|
|
388
|
+
return JSON.parse(body.toString('utf8'));
|
|
389
|
+
}
|
|
390
|
+
catch {
|
|
391
|
+
throw createSmartAiProviderError('PROTOCOL_ERROR');
|
|
392
|
+
}
|
|
393
|
+
};
|
|
394
|
+
const boundedInteger = (valueArg, minimumArg, maximumArg = Number.MAX_SAFE_INTEGER) => {
|
|
395
|
+
if (!Number.isSafeInteger(valueArg)
|
|
396
|
+
|| valueArg < minimumArg
|
|
397
|
+
|| valueArg > maximumArg) {
|
|
398
|
+
throw createSmartAiProviderError('PROTOCOL_ERROR');
|
|
399
|
+
}
|
|
400
|
+
return valueArg;
|
|
401
|
+
};
|
|
402
|
+
const projectRateLimitWindow = (valueArg) => {
|
|
403
|
+
if (!isRecord(valueArg))
|
|
404
|
+
throw createSmartAiProviderError('PROTOCOL_ERROR');
|
|
405
|
+
return {
|
|
406
|
+
usedPercent: boundedInteger(valueArg.used_percent, 0, 100),
|
|
407
|
+
limitWindowSeconds: boundedInteger(valueArg.limit_window_seconds, 1),
|
|
408
|
+
resetAfterSeconds: boundedInteger(valueArg.reset_after_seconds, 0),
|
|
409
|
+
resetsAt: boundedInteger(valueArg.reset_at, 0),
|
|
410
|
+
};
|
|
411
|
+
};
|
|
412
|
+
const projectRateLimitDetails = (valueArg) => {
|
|
413
|
+
if (!isRecord(valueArg)
|
|
414
|
+
|| typeof valueArg.allowed !== 'boolean'
|
|
415
|
+
|| typeof valueArg.limit_reached !== 'boolean') {
|
|
416
|
+
throw createSmartAiProviderError('PROTOCOL_ERROR');
|
|
417
|
+
}
|
|
418
|
+
return {
|
|
419
|
+
allowed: valueArg.allowed,
|
|
420
|
+
limitReached: valueArg.limit_reached,
|
|
421
|
+
...(valueArg.primary_window === null || valueArg.primary_window === undefined
|
|
422
|
+
? {}
|
|
423
|
+
: { primaryWindow: projectRateLimitWindow(valueArg.primary_window) }),
|
|
424
|
+
...(valueArg.secondary_window === null || valueArg.secondary_window === undefined
|
|
425
|
+
? {}
|
|
426
|
+
: { secondaryWindow: projectRateLimitWindow(valueArg.secondary_window) }),
|
|
427
|
+
};
|
|
428
|
+
};
|
|
429
|
+
const projectAccountRateLimits = (valueArg, observedAtArg) => {
|
|
430
|
+
if (!isRecord(valueArg))
|
|
431
|
+
throw createSmartAiProviderError('PROTOCOL_ERROR');
|
|
432
|
+
const rawAdditionalRateLimits = valueArg.additional_rate_limits ?? [];
|
|
433
|
+
if (!Array.isArray(rawAdditionalRateLimits)
|
|
434
|
+
|| rawAdditionalRateLimits.length > maximumAdditionalRateLimits) {
|
|
435
|
+
throw createSmartAiProviderError('PROTOCOL_ERROR');
|
|
436
|
+
}
|
|
437
|
+
const additionalRateLimits = rawAdditionalRateLimits.map((rawLimit) => {
|
|
438
|
+
if (!isRecord(rawLimit))
|
|
439
|
+
throw createSmartAiProviderError('PROTOCOL_ERROR');
|
|
440
|
+
return {
|
|
441
|
+
limitName: boundedString(rawLimit.limit_name, 256),
|
|
442
|
+
meteredFeature: boundedString(rawLimit.metered_feature, 256),
|
|
443
|
+
...(rawLimit.rate_limit === null || rawLimit.rate_limit === undefined
|
|
444
|
+
? {}
|
|
445
|
+
: { rateLimit: projectRateLimitDetails(rawLimit.rate_limit) }),
|
|
446
|
+
};
|
|
447
|
+
});
|
|
448
|
+
let rateLimitReachedType;
|
|
449
|
+
if (valueArg.rate_limit_reached_type !== null && valueArg.rate_limit_reached_type !== undefined) {
|
|
450
|
+
if (!isRecord(valueArg.rate_limit_reached_type)) {
|
|
451
|
+
throw createSmartAiProviderError('PROTOCOL_ERROR');
|
|
452
|
+
}
|
|
453
|
+
rateLimitReachedType = boundedString(valueArg.rate_limit_reached_type.type, 256);
|
|
454
|
+
}
|
|
455
|
+
let rateLimitResetCreditsAvailableCount;
|
|
456
|
+
if (valueArg.rate_limit_reset_credits !== null && valueArg.rate_limit_reset_credits !== undefined) {
|
|
457
|
+
if (!isRecord(valueArg.rate_limit_reset_credits)) {
|
|
458
|
+
throw createSmartAiProviderError('PROTOCOL_ERROR');
|
|
459
|
+
}
|
|
460
|
+
rateLimitResetCreditsAvailableCount = boundedInteger(valueArg.rate_limit_reset_credits.available_count, 0);
|
|
461
|
+
}
|
|
462
|
+
return {
|
|
463
|
+
providerId: 'openai',
|
|
464
|
+
plan: boundedString(valueArg.plan_type, 256),
|
|
465
|
+
observedAt: observedAtArg,
|
|
466
|
+
...(valueArg.rate_limit === null || valueArg.rate_limit === undefined
|
|
467
|
+
? {}
|
|
468
|
+
: { rateLimit: projectRateLimitDetails(valueArg.rate_limit) }),
|
|
469
|
+
additionalRateLimits,
|
|
470
|
+
...(rateLimitReachedType === undefined ? {} : { rateLimitReachedType }),
|
|
471
|
+
...(rateLimitResetCreditsAvailableCount === undefined
|
|
472
|
+
? {}
|
|
473
|
+
: { rateLimitResetCreditsAvailableCount }),
|
|
474
|
+
};
|
|
475
|
+
};
|
|
476
|
+
const projectCatalog = (valueArg) => {
|
|
477
|
+
if (!isRecord(valueArg) || !Array.isArray(valueArg.models) || valueArg.models.length > maximumCatalogModels) {
|
|
478
|
+
throw createSmartAiProviderError('PROTOCOL_ERROR');
|
|
479
|
+
}
|
|
480
|
+
const modelIds = new Set();
|
|
481
|
+
const entries = valueArg.models.map((rawModel, sourceIndex) => {
|
|
482
|
+
if (!isRecord(rawModel))
|
|
483
|
+
throw createSmartAiProviderError('PROTOCOL_ERROR');
|
|
484
|
+
const modelId = boundedString(rawModel.slug, 256);
|
|
485
|
+
if (modelIds.has(modelId))
|
|
486
|
+
throw createSmartAiProviderError('PROTOCOL_ERROR');
|
|
487
|
+
modelIds.add(modelId);
|
|
488
|
+
const visibility = rawModel.visibility;
|
|
489
|
+
if (visibility !== 'list' && visibility !== 'hide' && visibility !== 'none') {
|
|
490
|
+
throw createSmartAiProviderError('PROTOCOL_ERROR');
|
|
491
|
+
}
|
|
492
|
+
if (!Number.isSafeInteger(rawModel.priority))
|
|
493
|
+
throw createSmartAiProviderError('PROTOCOL_ERROR');
|
|
494
|
+
if (!Array.isArray(rawModel.supported_reasoning_levels) || rawModel.supported_reasoning_levels.length > 16) {
|
|
495
|
+
throw createSmartAiProviderError('PROTOCOL_ERROR');
|
|
496
|
+
}
|
|
497
|
+
const reasoningEfforts = rawModel.supported_reasoning_levels.map((rawEffort) => {
|
|
498
|
+
if (!isRecord(rawEffort))
|
|
499
|
+
throw createSmartAiProviderError('PROTOCOL_ERROR');
|
|
500
|
+
return {
|
|
501
|
+
effort: boundedString(rawEffort.effort, 128),
|
|
502
|
+
description: boundedString(rawEffort.description, 1024, true),
|
|
503
|
+
};
|
|
504
|
+
});
|
|
505
|
+
const modalities = rawModel.input_modalities ?? ['text', 'image'];
|
|
506
|
+
if (!Array.isArray(modalities)
|
|
507
|
+
|| modalities.length > 3
|
|
508
|
+
|| modalities.some((entry) => entry !== 'text' && entry !== 'image' && entry !== 'audio')
|
|
509
|
+
|| new Set(modalities).size !== modalities.length) {
|
|
510
|
+
throw createSmartAiProviderError('PROTOCOL_ERROR');
|
|
511
|
+
}
|
|
512
|
+
const rawServiceTiers = rawModel.service_tiers ?? [];
|
|
513
|
+
if (!Array.isArray(rawServiceTiers) || rawServiceTiers.length > 16) {
|
|
514
|
+
throw createSmartAiProviderError('PROTOCOL_ERROR');
|
|
515
|
+
}
|
|
516
|
+
const serviceTiers = rawServiceTiers.map((rawTier) => {
|
|
517
|
+
if (!isRecord(rawTier))
|
|
518
|
+
throw createSmartAiProviderError('PROTOCOL_ERROR');
|
|
519
|
+
return {
|
|
520
|
+
id: boundedString(rawTier.id, 128),
|
|
521
|
+
name: boundedString(rawTier.name, 256),
|
|
522
|
+
description: boundedString(rawTier.description, 1024, true),
|
|
523
|
+
};
|
|
524
|
+
});
|
|
525
|
+
const modelMessages = isRecord(rawModel.model_messages) ? rawModel.model_messages : undefined;
|
|
526
|
+
const variables = isRecord(modelMessages?.instructions_variables)
|
|
527
|
+
? modelMessages.instructions_variables
|
|
528
|
+
: undefined;
|
|
529
|
+
const supportsPersonality = typeof modelMessages?.instructions_template === 'string'
|
|
530
|
+
&& modelMessages.instructions_template.includes('{{ personality }}')
|
|
531
|
+
&& typeof variables?.personality_default === 'string'
|
|
532
|
+
&& typeof variables.personality_friendly === 'string'
|
|
533
|
+
&& typeof variables.personality_pragmatic === 'string';
|
|
534
|
+
return {
|
|
535
|
+
priority: rawModel.priority,
|
|
536
|
+
sourceIndex,
|
|
537
|
+
model: {
|
|
538
|
+
providerId: 'openai',
|
|
539
|
+
modelId,
|
|
540
|
+
wireModel: modelId,
|
|
541
|
+
displayName: boundedString(rawModel.display_name, 512),
|
|
542
|
+
description: rawModel.description === null || rawModel.description === undefined
|
|
543
|
+
? ''
|
|
544
|
+
: boundedString(rawModel.description, 4096, true),
|
|
545
|
+
hidden: visibility !== 'list',
|
|
546
|
+
reasoningEfforts,
|
|
547
|
+
defaultReasoningEffort: rawModel.default_reasoning_level === null
|
|
548
|
+
|| rawModel.default_reasoning_level === undefined
|
|
549
|
+
? 'none'
|
|
550
|
+
: boundedString(rawModel.default_reasoning_level, 128),
|
|
551
|
+
inputModalities: modalities,
|
|
552
|
+
supportsPersonality,
|
|
553
|
+
serviceTiers,
|
|
554
|
+
...(rawModel.default_service_tier === null || rawModel.default_service_tier === undefined
|
|
555
|
+
? {}
|
|
556
|
+
: { defaultServiceTier: boundedString(rawModel.default_service_tier, 128) }),
|
|
557
|
+
isDefault: false,
|
|
558
|
+
},
|
|
559
|
+
};
|
|
560
|
+
});
|
|
561
|
+
entries.sort((left, right) => left.priority - right.priority || left.sourceIndex - right.sourceIndex);
|
|
562
|
+
const models = entries.map((entry) => entry.model);
|
|
563
|
+
const defaultModel = models.find((model) => !model.hidden) ?? models[0];
|
|
564
|
+
if (defaultModel)
|
|
565
|
+
defaultModel.isDefault = true;
|
|
566
|
+
return models;
|
|
567
|
+
};
|
|
568
|
+
export class OpenAiProviderAdapter {
|
|
569
|
+
descriptor = {
|
|
570
|
+
providerId: 'openai',
|
|
571
|
+
displayName: 'OpenAI',
|
|
572
|
+
loginFlows: ['browser', 'device'],
|
|
573
|
+
supportsApiKey: true,
|
|
574
|
+
};
|
|
575
|
+
fetchImplementation;
|
|
576
|
+
originator;
|
|
577
|
+
now;
|
|
578
|
+
cursorKey = plugins.crypto.randomBytes(32);
|
|
579
|
+
handles = new Set();
|
|
580
|
+
operations = new Set();
|
|
581
|
+
refreshes = new Map();
|
|
582
|
+
closed = false;
|
|
583
|
+
disposePromise;
|
|
584
|
+
constructor(optionsArg = {}) {
|
|
585
|
+
this.fetchImplementation = optionsArg.fetch ?? globalThis.fetch;
|
|
586
|
+
if (!this.fetchImplementation)
|
|
587
|
+
throw createSmartAiProviderError('INVALID_ARGUMENT');
|
|
588
|
+
this.originator = optionsArg.originator ?? OPENAI_CHATGPT_DEFAULT_ORIGINATOR;
|
|
589
|
+
this.now = optionsArg.now ?? (() => new Date());
|
|
590
|
+
}
|
|
591
|
+
requireOpen() {
|
|
592
|
+
if (this.closed)
|
|
593
|
+
throw createSmartAiProviderError('CLOSED');
|
|
594
|
+
}
|
|
595
|
+
authOptions(signalArg) {
|
|
596
|
+
return {
|
|
597
|
+
fetch: this.fetchImplementation,
|
|
598
|
+
signal: signalArg,
|
|
599
|
+
safeErrors: true,
|
|
600
|
+
};
|
|
601
|
+
}
|
|
602
|
+
createApiKeyCredential(apiKeyArg) {
|
|
603
|
+
this.requireOpen();
|
|
604
|
+
if (typeof apiKeyArg !== 'string' || apiKeyArg.length === 0) {
|
|
605
|
+
throw createSmartAiProviderError('INVALID_ARGUMENT');
|
|
606
|
+
}
|
|
607
|
+
return { kind: 'apiKey', providerId: 'openai', apiKey: apiKeyArg };
|
|
608
|
+
}
|
|
609
|
+
inspectCredential(credentialArg) {
|
|
610
|
+
this.requireOpen();
|
|
611
|
+
if (credentialArg.kind === 'apiKey') {
|
|
612
|
+
if (credentialArg.providerId !== 'openai' || !credentialArg.apiKey) {
|
|
613
|
+
throw createSmartAiProviderError('CREDENTIAL_INVALID');
|
|
614
|
+
}
|
|
615
|
+
return { providerId: 'openai', authKind: 'apiKey' };
|
|
616
|
+
}
|
|
617
|
+
return toSummary(credentialArg);
|
|
618
|
+
}
|
|
619
|
+
async beginLogin(optionsArg) {
|
|
620
|
+
this.requireOpen();
|
|
621
|
+
if (optionsArg.flow !== 'browser' && optionsArg.flow !== 'device') {
|
|
622
|
+
throw createSmartAiProviderError('INVALID_ARGUMENT');
|
|
623
|
+
}
|
|
624
|
+
const defaultTimeoutMs = optionsArg.flow === 'browser'
|
|
625
|
+
? defaultBrowserLoginTimeoutMs
|
|
626
|
+
: defaultDeviceLoginTimeoutMs;
|
|
627
|
+
if (optionsArg.flow === 'device'
|
|
628
|
+
&& (optionsArg.timeoutMs ?? defaultTimeoutMs) > defaultDeviceLoginTimeoutMs) {
|
|
629
|
+
throw createSmartAiProviderError('INVALID_ARGUMENT');
|
|
630
|
+
}
|
|
631
|
+
const operation = createOperation(optionsArg, defaultTimeoutMs);
|
|
632
|
+
const abortController = operation.controller;
|
|
633
|
+
this.operations.add(abortController);
|
|
634
|
+
const timeoutMs = optionsArg.timeoutMs ?? defaultTimeoutMs;
|
|
635
|
+
let callbackServer;
|
|
636
|
+
const cleanup = async () => {
|
|
637
|
+
this.operations.delete(abortController);
|
|
638
|
+
operation.cleanup();
|
|
639
|
+
await callbackServer?.close();
|
|
640
|
+
};
|
|
641
|
+
try {
|
|
642
|
+
let prompt;
|
|
643
|
+
let completion;
|
|
644
|
+
if (optionsArg.flow === 'device') {
|
|
645
|
+
const deviceCode = await requestOpenAiChatGptDeviceCode(this.authOptions(abortController.signal));
|
|
646
|
+
prompt = {
|
|
647
|
+
flow: 'device',
|
|
648
|
+
verificationUrl: deviceCode.verificationUrl,
|
|
649
|
+
userCode: deviceCode.userCode,
|
|
650
|
+
};
|
|
651
|
+
completion = completeOpenAiChatGptDeviceCodeLogin(deviceCode, {
|
|
652
|
+
...this.authOptions(abortController.signal),
|
|
653
|
+
timeoutMs,
|
|
654
|
+
}).then((tokenData) => {
|
|
655
|
+
const credential = toCredential(tokenData);
|
|
656
|
+
return { credential, account: toSummary(credential) };
|
|
657
|
+
});
|
|
658
|
+
}
|
|
659
|
+
else {
|
|
660
|
+
callbackServer = await bindBrowserCallbackServer([1455, 1457], abortController.signal);
|
|
661
|
+
const authorization = await createOpenAiChatGptBrowserAuthorization({
|
|
662
|
+
...this.authOptions(abortController.signal),
|
|
663
|
+
redirectUri: `http://localhost:${callbackServer.port}/auth/callback`,
|
|
664
|
+
originator: this.originator,
|
|
665
|
+
});
|
|
666
|
+
prompt = { flow: 'browser', authUrl: authorization.authUrl };
|
|
667
|
+
completion = callbackServer.waitForCallback(authorization).then(async (callbackUrl) => {
|
|
668
|
+
const callback = parseOpenAiChatGptBrowserCallback(callbackUrl, {
|
|
669
|
+
expectedState: authorization.state,
|
|
670
|
+
expectedRedirectUri: authorization.redirectUri,
|
|
671
|
+
});
|
|
672
|
+
if ('providerError' in callback) {
|
|
673
|
+
throw createSmartAiProviderError('LOGIN_CANCELED');
|
|
674
|
+
}
|
|
675
|
+
const tokenData = await exchangeOpenAiChatGptBrowserAuthorizationCode(callback.authorizationCode, {
|
|
676
|
+
...this.authOptions(abortController.signal),
|
|
677
|
+
redirectUri: authorization.redirectUri,
|
|
678
|
+
codeVerifier: authorization.codeVerifier,
|
|
679
|
+
});
|
|
680
|
+
const credential = toCredential(tokenData);
|
|
681
|
+
return { credential, account: toSummary(credential) };
|
|
682
|
+
});
|
|
683
|
+
}
|
|
684
|
+
this.requireOpen();
|
|
685
|
+
if (abortController.signal.aborted)
|
|
686
|
+
throw createSmartAiProviderError('ABORTED');
|
|
687
|
+
const handle = new OpenAiProviderLoginHandle(prompt, completion.catch((errorArg) => {
|
|
688
|
+
if (operation.timedOut)
|
|
689
|
+
throw createSmartAiProviderError('TIMEOUT');
|
|
690
|
+
if (optionsArg.signal?.aborted)
|
|
691
|
+
throw createSmartAiProviderError('ABORTED');
|
|
692
|
+
if (abortController.signal.aborted)
|
|
693
|
+
throw createSmartAiProviderError('LOGIN_CANCELED');
|
|
694
|
+
if (errorArg instanceof SmartAiProviderError)
|
|
695
|
+
throw errorArg;
|
|
696
|
+
throw createSmartAiProviderError('LOGIN_FAILED');
|
|
697
|
+
}), abortController, cleanup, () => this.handles.delete(handle));
|
|
698
|
+
this.handles.add(handle);
|
|
699
|
+
return handle;
|
|
700
|
+
}
|
|
701
|
+
catch (errorArg) {
|
|
702
|
+
abortController.abort();
|
|
703
|
+
await cleanup().catch(() => undefined);
|
|
704
|
+
if (operation.timedOut)
|
|
705
|
+
throw createSmartAiProviderError('TIMEOUT');
|
|
706
|
+
if (optionsArg.signal?.aborted)
|
|
707
|
+
throw createSmartAiProviderError('ABORTED');
|
|
708
|
+
if (errorArg instanceof SmartAiProviderError)
|
|
709
|
+
throw errorArg;
|
|
710
|
+
throw createSmartAiProviderError('LOGIN_FAILED');
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
async refreshCredential(credentialArg, optionsArg = {}) {
|
|
714
|
+
this.requireOpen();
|
|
715
|
+
toTokenData(credentialArg);
|
|
716
|
+
const waitOperation = createOperation(optionsArg, defaultOperationTimeoutMs);
|
|
717
|
+
if (waitOperation.signal.aborted) {
|
|
718
|
+
const failure = {
|
|
719
|
+
success: false,
|
|
720
|
+
credential: credentialArg,
|
|
721
|
+
errorCode: waitOperation.timedOut ? 'TIMEOUT' : 'ABORTED',
|
|
722
|
+
};
|
|
723
|
+
waitOperation.cleanup();
|
|
724
|
+
return failure;
|
|
725
|
+
}
|
|
726
|
+
let sharedRefresh;
|
|
727
|
+
let joinedRefresh = false;
|
|
728
|
+
let onAbort;
|
|
729
|
+
try {
|
|
730
|
+
const refreshKey = plugins.crypto.createHash('sha256')
|
|
731
|
+
.update(credentialArg.refreshToken, 'utf8')
|
|
732
|
+
.digest('base64url');
|
|
733
|
+
sharedRefresh = this.refreshes.get(refreshKey);
|
|
734
|
+
if (!sharedRefresh) {
|
|
735
|
+
const controller = new AbortController();
|
|
736
|
+
let createdRefresh;
|
|
737
|
+
const promise = this.performRefreshCredential(credentialArg, {
|
|
738
|
+
signal: controller.signal,
|
|
739
|
+
}).finally(() => {
|
|
740
|
+
createdRefresh.settled = true;
|
|
741
|
+
if (this.refreshes.get(refreshKey) === createdRefresh) {
|
|
742
|
+
this.refreshes.delete(refreshKey);
|
|
743
|
+
}
|
|
744
|
+
});
|
|
745
|
+
createdRefresh = {
|
|
746
|
+
controller,
|
|
747
|
+
promise,
|
|
748
|
+
waiters: 0,
|
|
749
|
+
settled: false,
|
|
750
|
+
};
|
|
751
|
+
this.refreshes.set(refreshKey, createdRefresh);
|
|
752
|
+
sharedRefresh = createdRefresh;
|
|
753
|
+
}
|
|
754
|
+
sharedRefresh.waiters++;
|
|
755
|
+
joinedRefresh = true;
|
|
756
|
+
const aborted = new Promise((resolve) => {
|
|
757
|
+
onAbort = () => resolve({
|
|
758
|
+
success: false,
|
|
759
|
+
credential: credentialArg,
|
|
760
|
+
errorCode: waitOperation.timedOut ? 'TIMEOUT' : 'ABORTED',
|
|
761
|
+
});
|
|
762
|
+
waitOperation.signal.addEventListener('abort', onAbort, { once: true });
|
|
763
|
+
});
|
|
764
|
+
return await Promise.race([sharedRefresh.promise, aborted]);
|
|
765
|
+
}
|
|
766
|
+
finally {
|
|
767
|
+
if (onAbort)
|
|
768
|
+
waitOperation.signal.removeEventListener('abort', onAbort);
|
|
769
|
+
waitOperation.cleanup();
|
|
770
|
+
if (sharedRefresh && joinedRefresh)
|
|
771
|
+
sharedRefresh.waiters--;
|
|
772
|
+
if (sharedRefresh && joinedRefresh && sharedRefresh.waiters === 0 && !sharedRefresh.settled) {
|
|
773
|
+
sharedRefresh.controller.abort();
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
async performRefreshCredential(credentialArg, optionsArg) {
|
|
778
|
+
const input = toTokenData(credentialArg);
|
|
779
|
+
const operation = createOperation(optionsArg, defaultOperationTimeoutMs);
|
|
780
|
+
this.operations.add(operation.controller);
|
|
781
|
+
try {
|
|
782
|
+
const refreshed = await refreshOpenAiChatGptTokenData(input, this.authOptions(operation.signal));
|
|
783
|
+
const tokenChanged = refreshed.accessToken !== input.accessToken
|
|
784
|
+
|| refreshed.refreshToken !== input.refreshToken;
|
|
785
|
+
if (!tokenChanged || !refreshed.idToken) {
|
|
786
|
+
return { success: false, credential: credentialArg, errorCode: 'REFRESH_FAILED' };
|
|
787
|
+
}
|
|
788
|
+
const previous = credentialArg.lastRefreshAt === undefined
|
|
789
|
+
? 0
|
|
790
|
+
: Date.parse(credentialArg.lastRefreshAt);
|
|
791
|
+
const now = this.now().getTime();
|
|
792
|
+
const lastRefreshAt = new Date(Math.max(now, Number.isFinite(previous) ? previous + 1 : now))
|
|
793
|
+
.toISOString();
|
|
794
|
+
const credential = toCredential(refreshed, lastRefreshAt);
|
|
795
|
+
return { success: true, credential, account: toSummary(credential) };
|
|
796
|
+
}
|
|
797
|
+
catch (errorArg) {
|
|
798
|
+
return {
|
|
799
|
+
success: false,
|
|
800
|
+
credential: credentialArg,
|
|
801
|
+
errorCode: classifyOperationError(errorArg, operation, 'REFRESH_FAILED'),
|
|
802
|
+
};
|
|
803
|
+
}
|
|
804
|
+
finally {
|
|
805
|
+
this.operations.delete(operation.controller);
|
|
806
|
+
operation.cleanup();
|
|
807
|
+
}
|
|
808
|
+
}
|
|
809
|
+
async fetchCatalog(credentialArg, signalArg) {
|
|
810
|
+
const tokenData = toTokenData(credentialArg);
|
|
811
|
+
const accountId = tokenData.tokenInfo.chatgptAccountId;
|
|
812
|
+
const url = `${OPENAI_CHATGPT_CODEX_BASE_URL}/models?client_version=${encodeURIComponent(defaultClientVersion)}`;
|
|
813
|
+
let response;
|
|
814
|
+
let onAbort;
|
|
815
|
+
try {
|
|
816
|
+
const fetchPromise = this.fetchImplementation(url, {
|
|
817
|
+
method: 'GET',
|
|
818
|
+
redirect: 'error',
|
|
819
|
+
signal: signalArg,
|
|
820
|
+
headers: {
|
|
821
|
+
Accept: 'application/json',
|
|
822
|
+
Authorization: `Bearer ${credentialArg.accessToken}`,
|
|
823
|
+
...(accountId ? { 'ChatGPT-Account-ID': accountId } : {}),
|
|
824
|
+
...(tokenData.tokenInfo.chatgptAccountIsFedramp ? { 'X-OpenAI-Fedramp': 'true' } : {}),
|
|
825
|
+
originator: this.originator,
|
|
826
|
+
version: defaultClientVersion,
|
|
827
|
+
},
|
|
828
|
+
});
|
|
829
|
+
void fetchPromise.then((lateResponse) => {
|
|
830
|
+
if (signalArg.aborted)
|
|
831
|
+
void lateResponse.body?.cancel().catch(() => undefined);
|
|
832
|
+
}).catch(() => undefined);
|
|
833
|
+
const aborted = new Promise((_resolve, reject) => {
|
|
834
|
+
onAbort = () => reject(createSmartAiProviderError('ABORTED'));
|
|
835
|
+
signalArg.addEventListener('abort', onAbort, { once: true });
|
|
836
|
+
if (signalArg.aborted)
|
|
837
|
+
onAbort();
|
|
838
|
+
});
|
|
839
|
+
response = await Promise.race([fetchPromise, aborted]);
|
|
840
|
+
}
|
|
841
|
+
catch {
|
|
842
|
+
if (signalArg.aborted)
|
|
843
|
+
throw createSmartAiProviderError('ABORTED');
|
|
844
|
+
throw createSmartAiProviderError('NETWORK_FAILED');
|
|
845
|
+
}
|
|
846
|
+
finally {
|
|
847
|
+
if (onAbort)
|
|
848
|
+
signalArg.removeEventListener('abort', onAbort);
|
|
849
|
+
}
|
|
850
|
+
if (!response.ok) {
|
|
851
|
+
await response.body?.cancel().catch(() => undefined);
|
|
852
|
+
throw new ModelHttpError(response.status);
|
|
853
|
+
}
|
|
854
|
+
return projectCatalog(await readBoundedJson(response, signalArg, maximumCatalogBytes));
|
|
855
|
+
}
|
|
856
|
+
encodeCursor(payloadArg) {
|
|
857
|
+
const body = plugins.Buffer.from(JSON.stringify(payloadArg), 'utf8').toString('base64url');
|
|
858
|
+
const mac = plugins.crypto.createHmac('sha256', this.cursorKey).update(body, 'ascii').digest('base64url');
|
|
859
|
+
return `v1.${body}.${mac}`;
|
|
860
|
+
}
|
|
861
|
+
decodeCursor(cursorArg) {
|
|
862
|
+
const parts = cursorArg.split('.');
|
|
863
|
+
if (parts.length !== 3 || parts[0] !== 'v1') {
|
|
864
|
+
throw createSmartAiProviderError('INVALID_ARGUMENT');
|
|
865
|
+
}
|
|
866
|
+
const expectedMac = plugins.crypto.createHmac('sha256', this.cursorKey)
|
|
867
|
+
.update(parts[1], 'ascii')
|
|
868
|
+
.digest();
|
|
869
|
+
let actualMac;
|
|
870
|
+
let payload;
|
|
871
|
+
try {
|
|
872
|
+
actualMac = plugins.Buffer.from(parts[2], 'base64url');
|
|
873
|
+
payload = JSON.parse(plugins.Buffer.from(parts[1], 'base64url').toString('utf8'));
|
|
874
|
+
}
|
|
875
|
+
catch {
|
|
876
|
+
throw createSmartAiProviderError('INVALID_ARGUMENT');
|
|
877
|
+
}
|
|
878
|
+
if (actualMac.byteLength !== expectedMac.byteLength || !plugins.crypto.timingSafeEqual(actualMac, expectedMac)) {
|
|
879
|
+
throw createSmartAiProviderError('INVALID_ARGUMENT');
|
|
880
|
+
}
|
|
881
|
+
if (!isRecord(payload)
|
|
882
|
+
|| Object.keys(payload).length !== 5
|
|
883
|
+
|| payload.version !== 1
|
|
884
|
+
|| payload.projectionVersion !== 1
|
|
885
|
+
|| typeof payload.digest !== 'string'
|
|
886
|
+
|| !/^[A-Za-z0-9_-]{43}$/.test(payload.digest)
|
|
887
|
+
|| typeof payload.includeHidden !== 'boolean'
|
|
888
|
+
|| !Number.isSafeInteger(payload.offset)
|
|
889
|
+
|| payload.offset < 0) {
|
|
890
|
+
throw createSmartAiProviderError('INVALID_ARGUMENT');
|
|
891
|
+
}
|
|
892
|
+
return payload;
|
|
893
|
+
}
|
|
894
|
+
async listModels(credentialArg, optionsArg = {}) {
|
|
895
|
+
this.requireOpen();
|
|
896
|
+
toTokenData(credentialArg);
|
|
897
|
+
const options = normalizeModelListOptions(optionsArg);
|
|
898
|
+
const operation = createOperation(options, defaultOperationTimeoutMs);
|
|
899
|
+
this.operations.add(operation.controller);
|
|
900
|
+
try {
|
|
901
|
+
let catalog;
|
|
902
|
+
try {
|
|
903
|
+
catalog = await this.fetchCatalog(credentialArg, operation.signal);
|
|
904
|
+
}
|
|
905
|
+
catch (errorArg) {
|
|
906
|
+
if (!(errorArg instanceof ModelHttpError) || errorArg.status !== 401)
|
|
907
|
+
throw errorArg;
|
|
908
|
+
return { success: false, errorCode: 'CREDENTIAL_REFRESH_REQUIRED' };
|
|
909
|
+
}
|
|
910
|
+
const filtered = options.includeHidden ? catalog : catalog.filter((model) => !model.hidden);
|
|
911
|
+
const digest = plugins.crypto.createHash('sha256').update(JSON.stringify(filtered)).digest('base64url');
|
|
912
|
+
let offset = 0;
|
|
913
|
+
if (options.cursor !== undefined) {
|
|
914
|
+
const cursor = this.decodeCursor(options.cursor);
|
|
915
|
+
if (cursor.digest !== digest
|
|
916
|
+
|| cursor.includeHidden !== options.includeHidden
|
|
917
|
+
|| cursor.offset > filtered.length) {
|
|
918
|
+
throw createSmartAiProviderError('INVALID_ARGUMENT');
|
|
919
|
+
}
|
|
920
|
+
offset = cursor.offset;
|
|
921
|
+
}
|
|
922
|
+
const models = filtered.slice(offset, offset + options.limit);
|
|
923
|
+
const nextOffset = offset + models.length;
|
|
924
|
+
const nextCursor = nextOffset < filtered.length
|
|
925
|
+
? this.encodeCursor({
|
|
926
|
+
version: 1,
|
|
927
|
+
projectionVersion: 1,
|
|
928
|
+
digest,
|
|
929
|
+
includeHidden: options.includeHidden,
|
|
930
|
+
offset: nextOffset,
|
|
931
|
+
})
|
|
932
|
+
: undefined;
|
|
933
|
+
return {
|
|
934
|
+
success: true,
|
|
935
|
+
models,
|
|
936
|
+
...(nextCursor === undefined ? {} : { nextCursor }),
|
|
937
|
+
};
|
|
938
|
+
}
|
|
939
|
+
catch (errorArg) {
|
|
940
|
+
if (errorArg instanceof SmartAiProviderError && errorArg.code === 'INVALID_ARGUMENT') {
|
|
941
|
+
throw errorArg;
|
|
942
|
+
}
|
|
943
|
+
return {
|
|
944
|
+
success: false,
|
|
945
|
+
errorCode: classifyOperationError(errorArg, operation, 'MODEL_LIST_FAILED'),
|
|
946
|
+
};
|
|
947
|
+
}
|
|
948
|
+
finally {
|
|
949
|
+
this.operations.delete(operation.controller);
|
|
950
|
+
operation.cleanup();
|
|
951
|
+
}
|
|
952
|
+
}
|
|
953
|
+
async fetchAccountRateLimits(credentialArg, signalArg) {
|
|
954
|
+
const tokenData = toTokenData(credentialArg);
|
|
955
|
+
const accountId = tokenData.tokenInfo.chatgptAccountId;
|
|
956
|
+
let response;
|
|
957
|
+
let onAbort;
|
|
958
|
+
try {
|
|
959
|
+
const fetchPromise = this.fetchImplementation(accountRateLimitsUrl, {
|
|
960
|
+
method: 'GET',
|
|
961
|
+
redirect: 'error',
|
|
962
|
+
signal: signalArg,
|
|
963
|
+
headers: {
|
|
964
|
+
Accept: 'application/json',
|
|
965
|
+
Authorization: `Bearer ${credentialArg.accessToken}`,
|
|
966
|
+
...(accountId ? { 'ChatGPT-Account-Id': accountId } : {}),
|
|
967
|
+
...(tokenData.tokenInfo.chatgptAccountIsFedramp ? { 'X-OpenAI-Fedramp': 'true' } : {}),
|
|
968
|
+
'User-Agent': this.originator,
|
|
969
|
+
},
|
|
970
|
+
});
|
|
971
|
+
void fetchPromise.then((lateResponse) => {
|
|
972
|
+
if (signalArg.aborted)
|
|
973
|
+
void lateResponse.body?.cancel().catch(() => undefined);
|
|
974
|
+
}).catch(() => undefined);
|
|
975
|
+
const aborted = new Promise((_resolve, reject) => {
|
|
976
|
+
onAbort = () => reject(createSmartAiProviderError('ABORTED'));
|
|
977
|
+
signalArg.addEventListener('abort', onAbort, { once: true });
|
|
978
|
+
if (signalArg.aborted)
|
|
979
|
+
onAbort();
|
|
980
|
+
});
|
|
981
|
+
response = await Promise.race([fetchPromise, aborted]);
|
|
982
|
+
}
|
|
983
|
+
catch {
|
|
984
|
+
if (signalArg.aborted)
|
|
985
|
+
throw createSmartAiProviderError('ABORTED');
|
|
986
|
+
throw createSmartAiProviderError('NETWORK_FAILED');
|
|
987
|
+
}
|
|
988
|
+
finally {
|
|
989
|
+
if (onAbort)
|
|
990
|
+
signalArg.removeEventListener('abort', onAbort);
|
|
991
|
+
}
|
|
992
|
+
if (!response.ok) {
|
|
993
|
+
await response.body?.cancel().catch(() => undefined);
|
|
994
|
+
throw new AccountRateLimitsHttpError(response.status);
|
|
995
|
+
}
|
|
996
|
+
return projectAccountRateLimits(await readBoundedJson(response, signalArg, maximumAccountRateLimitsBytes), this.now().toISOString());
|
|
997
|
+
}
|
|
998
|
+
async getAccountRateLimits(credentialArg, optionsArg = {}) {
|
|
999
|
+
this.requireOpen();
|
|
1000
|
+
toTokenData(credentialArg);
|
|
1001
|
+
const operation = createOperation(optionsArg, defaultOperationTimeoutMs);
|
|
1002
|
+
this.operations.add(operation.controller);
|
|
1003
|
+
try {
|
|
1004
|
+
try {
|
|
1005
|
+
const rateLimits = await this.fetchAccountRateLimits(credentialArg, operation.signal);
|
|
1006
|
+
return { success: true, rateLimits };
|
|
1007
|
+
}
|
|
1008
|
+
catch (errorArg) {
|
|
1009
|
+
if (!(errorArg instanceof AccountRateLimitsHttpError) || errorArg.status !== 401) {
|
|
1010
|
+
throw errorArg;
|
|
1011
|
+
}
|
|
1012
|
+
return { success: false, errorCode: 'CREDENTIAL_REFRESH_REQUIRED' };
|
|
1013
|
+
}
|
|
1014
|
+
}
|
|
1015
|
+
catch (errorArg) {
|
|
1016
|
+
return {
|
|
1017
|
+
success: false,
|
|
1018
|
+
errorCode: classifyOperationError(errorArg, operation, 'ACCOUNT_RATE_LIMITS_FAILED'),
|
|
1019
|
+
};
|
|
1020
|
+
}
|
|
1021
|
+
finally {
|
|
1022
|
+
this.operations.delete(operation.controller);
|
|
1023
|
+
operation.cleanup();
|
|
1024
|
+
}
|
|
1025
|
+
}
|
|
1026
|
+
async logoutCredential(credentialArg, optionsArg = {}) {
|
|
1027
|
+
this.requireOpen();
|
|
1028
|
+
toTokenData(credentialArg);
|
|
1029
|
+
const operation = createOperation(optionsArg, defaultOperationTimeoutMs);
|
|
1030
|
+
this.operations.add(operation.controller);
|
|
1031
|
+
try {
|
|
1032
|
+
await revokeOpenAiChatGptToken(credentialArg.refreshToken, {
|
|
1033
|
+
...this.authOptions(operation.signal),
|
|
1034
|
+
tokenTypeHint: 'refresh_token',
|
|
1035
|
+
});
|
|
1036
|
+
}
|
|
1037
|
+
catch {
|
|
1038
|
+
throw createSmartAiProviderError(operation.timedOut ? 'TIMEOUT' : operation.signal.aborted ? 'ABORTED' : 'NETWORK_FAILED');
|
|
1039
|
+
}
|
|
1040
|
+
finally {
|
|
1041
|
+
this.operations.delete(operation.controller);
|
|
1042
|
+
operation.cleanup();
|
|
1043
|
+
}
|
|
1044
|
+
}
|
|
1045
|
+
async dispose() {
|
|
1046
|
+
if (this.disposePromise)
|
|
1047
|
+
return this.disposePromise;
|
|
1048
|
+
this.closed = true;
|
|
1049
|
+
const disposeAttempt = (async () => {
|
|
1050
|
+
for (const operation of this.operations)
|
|
1051
|
+
operation.abort();
|
|
1052
|
+
const results = await Promise.allSettled([...this.handles].map((handle) => handle.close()));
|
|
1053
|
+
const operationDeadline = Date.now() + 5_000;
|
|
1054
|
+
while (this.operations.size > 0 && Date.now() < operationDeadline) {
|
|
1055
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
1056
|
+
}
|
|
1057
|
+
if (results.some((result) => result.status === 'rejected')) {
|
|
1058
|
+
throw createSmartAiProviderError('CLOSED');
|
|
1059
|
+
}
|
|
1060
|
+
if (this.operations.size > 0)
|
|
1061
|
+
throw createSmartAiProviderError('CLOSED');
|
|
1062
|
+
this.handles.clear();
|
|
1063
|
+
this.cursorKey.fill(0);
|
|
1064
|
+
})();
|
|
1065
|
+
this.disposePromise = disposeAttempt;
|
|
1066
|
+
try {
|
|
1067
|
+
await disposeAttempt;
|
|
1068
|
+
}
|
|
1069
|
+
catch (error) {
|
|
1070
|
+
this.disposePromise = undefined;
|
|
1071
|
+
throw error;
|
|
1072
|
+
}
|
|
1073
|
+
}
|
|
1074
|
+
}
|
|
1075
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRhaS5wcm92aWRlcnMub3BlbmFpLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHNfb3BlbmFpX2FjY291bnQvc21hcnRhaS5wcm92aWRlcnMub3BlbmFpLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLGtGQUFrRjtBQUNsRixPQUFPLEtBQUssT0FBTyxNQUFNLGNBQWMsQ0FBQztBQUN4QyxPQUFPLEVBQ0wsNkJBQTZCLEVBQzdCLGlDQUFpQyxFQUNqQyxvQ0FBb0MsRUFDcEMsdUNBQXVDLEVBQ3ZDLDZDQUE2QyxFQUM3QyxpQ0FBaUMsRUFDakMsMkJBQTJCLEVBQzNCLDZCQUE2QixFQUM3Qiw4QkFBOEIsRUFDOUIsd0JBQXdCLEdBQ3pCLE1BQU0sOENBQThDLENBQUM7QUFDdEQsT0FBTyxFQUFFLDBCQUEwQixFQUFFLG9CQUFvQixFQUFFLE1BQU0sOEJBQThCLENBQUM7QUF5QmhHLE1BQU0sNEJBQTRCLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxJQUFJLENBQUM7QUFDcEQsTUFBTSwyQkFBMkIsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLElBQUksQ0FBQztBQUNuRCxNQUFNLHlCQUF5QixHQUFHLE1BQU0sQ0FBQztBQUN6QyxNQUFNLHlCQUF5QixHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsSUFBSSxDQUFDO0FBQ2pELE1BQU0sbUJBQW1CLEdBQUcsQ0FBQyxHQUFHLElBQUksR0FBRyxJQUFJLENBQUM7QUFDNUMsTUFBTSw2QkFBNkIsR0FBRyxHQUFHLEdBQUcsSUFBSSxDQUFDO0FBQ2pELE1BQU0sb0JBQW9CLEdBQUcsR0FBRyxDQUFDO0FBQ2pDLE1BQU0sMkJBQTJCLEdBQUcsR0FBRyxDQUFDO0FBQ3hDLE1BQU0sa0JBQWtCLEdBQUcsSUFBSSxDQUFDO0FBQ2hDLE1BQU0sb0JBQW9CLEdBQUcsRUFBRSxDQUFDO0FBQ2hDLE1BQU0sb0JBQW9CLEdBQUcsU0FBUyxDQUFDO0FBQ3ZDLE1BQU0sa0JBQWtCLEdBQUcsRUFB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
|