@modelprofile.com/authswitch-signin 10.4.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.
@@ -0,0 +1,397 @@
1
+ // OpenAI protocol portions are adapted in TypeScript from OpenAI Codex (Apache-2.0) and modified by Task Venture Capital GmbH; see third-party-notices.md.
2
+ /**
3
+ * The ChatGPT sign-in protocol Codex uses (`codex-rs/login`: `device_code_auth.rs`, `auth/manager.rs`,
4
+ * `auth/revoke.rs`, `oauth/client.rs`), for the one party that signs an account in and refreshes it: the device
5
+ * code, its poll, the authorization-code exchange, the refresh-token grant, the revocation and the claims of the
6
+ * tokens. Every failure is a fixed message: no response body, token or header crosses an error.
7
+ */
8
+ export const OPENAI_AUTH_ISSUER = 'https://auth.openai.com';
9
+ export const OPENAI_AUTH_CLIENT_ID = 'app_EMoamEEZ73f0CkXaXp7hrann';
10
+ /** How long a device code lives: Codex polls it for fifteen minutes and tells the person it expires then. */
11
+ export const OPENAI_DEVICE_CODE_LIFETIME_MS = 15 * 60 * 1000;
12
+ const DEVICE_CODE_TIMEOUT_MS = OPENAI_DEVICE_CODE_LIFETIME_MS;
13
+ /** Codex's `REVOKE_HTTP_TIMEOUT`. */
14
+ const REVOKE_TIMEOUT_MS = 10_000;
15
+ const MAX_RESPONSE_BYTES = 64 * 1024;
16
+ const MAX_TOKEN_BYTES = 16 * 1024;
17
+ const MAX_AUTHORIZATION_CODE_BYTES = 8 * 1024;
18
+ const MAX_IDENTIFIER_BYTES = 1024;
19
+ const REQUEST_TIMEOUT_MS = 30_000;
20
+ const textEncoder = new TextEncoder();
21
+ const textDecoder = new TextDecoder();
22
+ const utf8ByteLength = (valueArg) => textEncoder.encode(valueArg).byteLength;
23
+ export class OpenAiAuthError extends Error {
24
+ status;
25
+ requestOutcome;
26
+ retryAfterMs;
27
+ constructor(message, options = {}) {
28
+ super(message);
29
+ this.name = 'OpenAiAuthError';
30
+ this.status = options.status;
31
+ this.requestOutcome = options.requestOutcome;
32
+ this.retryAfterMs = options.retryAfterMs;
33
+ }
34
+ }
35
+ const getFetch = (options) => {
36
+ const fetchFunction = options.fetch ?? globalThis.fetch;
37
+ if (!fetchFunction)
38
+ throw new OpenAiAuthError('fetch is not available for OpenAI authentication.');
39
+ return fetchFunction;
40
+ };
41
+ const throwIfAborted = (options) => {
42
+ if (options.signal?.aborted)
43
+ throw new OpenAiAuthError('OpenAI authentication was aborted.');
44
+ };
45
+ const asString = (value, name, maximumBytes = MAX_IDENTIFIER_BYTES) => {
46
+ if (typeof value !== 'string' || value.length === 0) {
47
+ throw new OpenAiAuthError(`OpenAI auth response is missing ${name}.`);
48
+ }
49
+ if (utf8ByteLength(value) > maximumBytes)
50
+ throw new OpenAiAuthError(`OpenAI auth response contains an invalid ${name}.`);
51
+ return value;
52
+ };
53
+ const asOptionalString = (value, maximumBytes = MAX_IDENTIFIER_BYTES) => {
54
+ if (typeof value !== 'string' || value.length === 0)
55
+ return undefined;
56
+ if (utf8ByteLength(value) > maximumBytes)
57
+ throw new OpenAiAuthError('OpenAI auth response contains an oversized string.');
58
+ return value;
59
+ };
60
+ /** Codex reads the interval as a string (`deserialize_interval`); both a number and a numeric string are taken. */
61
+ const asIntervalSeconds = (value) => {
62
+ const interval = typeof value === 'number' ? value : Number.parseInt(String(value ?? ''), 10);
63
+ if (!Number.isFinite(interval) || interval <= 0 || interval > 300) {
64
+ throw new OpenAiAuthError('OpenAI device-code response has an invalid interval.');
65
+ }
66
+ return interval;
67
+ };
68
+ const readResponseText = async (response, options) => {
69
+ const contentLength = response.headers.get('content-length');
70
+ if (contentLength !== null && (!/^\d+$/.test(contentLength) || Number(contentLength) > MAX_RESPONSE_BYTES)) {
71
+ await response.body?.cancel().catch(() => undefined);
72
+ throw new OpenAiAuthError('OpenAI auth response exceeded its size limit.', { status: response.status });
73
+ }
74
+ if (!response.body)
75
+ return '';
76
+ const reader = response.body.getReader();
77
+ const chunks = [];
78
+ let byteLength = 0;
79
+ let completed = false;
80
+ const onAbort = () => { void reader.cancel().catch(() => undefined); };
81
+ options.signal?.addEventListener('abort', onAbort, { once: true });
82
+ if (options.signal?.aborted)
83
+ onAbort();
84
+ try {
85
+ while (true) {
86
+ throwIfAborted(options);
87
+ const { done, value } = await reader.read();
88
+ throwIfAborted(options);
89
+ if (done)
90
+ break;
91
+ byteLength += value.byteLength;
92
+ if (byteLength > MAX_RESPONSE_BYTES) {
93
+ await reader.cancel().catch(() => undefined);
94
+ throw new OpenAiAuthError('OpenAI auth response exceeded its size limit.', { status: response.status });
95
+ }
96
+ chunks.push(value);
97
+ }
98
+ completed = true;
99
+ }
100
+ finally {
101
+ options.signal?.removeEventListener('abort', onAbort);
102
+ if (!completed)
103
+ void reader.cancel().catch(() => undefined);
104
+ reader.releaseLock();
105
+ }
106
+ const bytes = new Uint8Array(byteLength);
107
+ let offset = 0;
108
+ for (const chunk of chunks) {
109
+ bytes.set(chunk, offset);
110
+ offset += chunk.byteLength;
111
+ }
112
+ return textDecoder.decode(bytes);
113
+ };
114
+ const readJson = async (response, context, options) => {
115
+ const body = await readResponseText(response, options);
116
+ if (!response.ok)
117
+ throw new OpenAiAuthError(`${context} failed with status ${response.status}.`, { status: response.status });
118
+ try {
119
+ return body ? JSON.parse(body) : {};
120
+ }
121
+ catch {
122
+ throw new OpenAiAuthError(`${context} returned invalid JSON.`, { status: response.status });
123
+ }
124
+ };
125
+ const parseRetryAfterMs = (header) => {
126
+ if (!header || header.length > 128)
127
+ return undefined;
128
+ const maximumDelayMs = 24 * 60 * 60 * 1000;
129
+ if (/^\d{1,10}$/.test(header))
130
+ return Math.min(Number(header) * 1000, maximumDelayMs);
131
+ const retryAt = Date.parse(header);
132
+ if (!Number.isFinite(retryAt))
133
+ return undefined;
134
+ return Math.min(Math.max(0, retryAt - Date.now()), maximumDelayMs);
135
+ };
136
+ /**
137
+ * One bounded request. Its failure says whether the request was handed to fetch at all: a refresh whose outcome
138
+ * is `outcomeUnknown` may have rotated the grant and is never sent again.
139
+ */
140
+ const runFetch = async (url, init, options, handle, timeoutMs = REQUEST_TIMEOUT_MS) => {
141
+ if (options.signal?.aborted) {
142
+ throw new OpenAiAuthError('OpenAI authentication was aborted.', { requestOutcome: 'notSent' });
143
+ }
144
+ const controller = new AbortController();
145
+ let response;
146
+ let requestStarted = false;
147
+ const onExternalAbort = () => controller.abort();
148
+ const onRequestAbort = () => { void response?.body?.cancel().catch(() => undefined); };
149
+ options.signal?.addEventListener('abort', onExternalAbort, { once: true });
150
+ let rejectOnAbort;
151
+ const aborted = new Promise((_resolve, reject) => {
152
+ rejectOnAbort = () => reject(new Error('OpenAI authentication request aborted.'));
153
+ controller.signal.addEventListener('abort', rejectOnAbort, { once: true });
154
+ });
155
+ controller.signal.addEventListener('abort', onRequestAbort, { once: true });
156
+ if (options.signal?.aborted)
157
+ controller.abort();
158
+ const timer = setTimeout(() => controller.abort(), Math.min(timeoutMs, REQUEST_TIMEOUT_MS));
159
+ const requestOptions = { ...options, signal: controller.signal };
160
+ try {
161
+ return await Promise.race([
162
+ (async () => {
163
+ const fetchImplementation = getFetch(options);
164
+ requestStarted = true;
165
+ response = await fetchImplementation(url, { ...init, redirect: 'error', signal: controller.signal });
166
+ if (controller.signal.aborted)
167
+ await response.body?.cancel().catch(() => undefined);
168
+ throwIfAborted(requestOptions);
169
+ return handle(response, requestOptions);
170
+ })(),
171
+ aborted,
172
+ ]);
173
+ }
174
+ catch (error) {
175
+ const requestOutcome = requestStarted ? 'outcomeUnknown' : 'notSent';
176
+ const retryAfterMs = response ? parseRetryAfterMs(response.headers.get('retry-after')) : undefined;
177
+ const status = error instanceof OpenAiAuthError && error.status !== undefined ? error.status : response?.status;
178
+ throw new OpenAiAuthError(error instanceof OpenAiAuthError ? error.message
179
+ : options.signal?.aborted ? 'OpenAI authentication was aborted.' : 'OpenAI authentication request failed.', {
180
+ requestOutcome,
181
+ ...(status !== undefined ? { status } : {}),
182
+ ...(retryAfterMs !== undefined ? { retryAfterMs } : {}),
183
+ });
184
+ }
185
+ finally {
186
+ clearTimeout(timer);
187
+ options.signal?.removeEventListener('abort', onExternalAbort);
188
+ controller.signal.removeEventListener('abort', rejectOnAbort);
189
+ controller.signal.removeEventListener('abort', onRequestAbort);
190
+ }
191
+ };
192
+ const postJson = (url, body, options) => runFetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body) }, options, (response, requestOptions) => readJson(response, `POST ${url}`, requestOptions));
193
+ const postForm = (url, body, options) => runFetch(url, { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: body.toString() }, options, (response, requestOptions) => readJson(response, `POST ${url}`, requestOptions));
194
+ const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));
195
+ const sleepWithAbort = async (milliseconds, options) => {
196
+ throwIfAborted(options);
197
+ const signal = options.signal;
198
+ if (!signal) {
199
+ await (options.sleep ?? sleep)(milliseconds);
200
+ return;
201
+ }
202
+ let abortListener;
203
+ let timer;
204
+ try {
205
+ await Promise.race([
206
+ options.sleep ? options.sleep(milliseconds) : new Promise(resolve => { timer = setTimeout(resolve, milliseconds); }),
207
+ new Promise((_resolve, reject) => {
208
+ abortListener = () => reject(new OpenAiAuthError('OpenAI authentication was aborted.'));
209
+ signal.addEventListener('abort', abortListener, { once: true });
210
+ if (signal.aborted)
211
+ abortListener();
212
+ }),
213
+ ]);
214
+ }
215
+ finally {
216
+ if (timer)
217
+ clearTimeout(timer);
218
+ if (abortListener)
219
+ signal.removeEventListener('abort', abortListener);
220
+ }
221
+ };
222
+ const parseJwtPayload = (jwt) => {
223
+ const parts = jwt.split('.');
224
+ if (parts.length !== 3 || !parts[1])
225
+ throw new OpenAiAuthError('OpenAI auth returned an invalid token.');
226
+ try {
227
+ const base64 = parts[1].replace(/-/g, '+').replace(/_/g, '/');
228
+ const binary = atob(base64.padEnd(Math.ceil(base64.length / 4) * 4, '='));
229
+ const value = JSON.parse(textDecoder.decode(Uint8Array.from(binary, character => character.charCodeAt(0))));
230
+ if (value === null || typeof value !== 'object' || Array.isArray(value))
231
+ throw new Error();
232
+ return value;
233
+ }
234
+ catch {
235
+ throw new OpenAiAuthError('OpenAI token claims could not be parsed.');
236
+ }
237
+ };
238
+ const claimRecord = (value) => value !== null && typeof value === 'object' && !Array.isArray(value) ? value : undefined;
239
+ /** Reads the account claims of a ChatGPT ID or access token. Throws `OpenAiAuthError` for anything but a JWT. */
240
+ export const parseOpenAiTokenClaims = (token) => {
241
+ const claims = parseJwtPayload(token);
242
+ const profile = claimRecord(claims['https://api.openai.com/profile']);
243
+ const auth = claimRecord(claims['https://api.openai.com/auth']);
244
+ const expiresAtSeconds = typeof claims.exp === 'number' ? claims.exp : undefined;
245
+ return {
246
+ email: asOptionalString(claims.email) ?? asOptionalString(profile?.email),
247
+ chatgptPlanType: asOptionalString(auth?.chatgpt_plan_type),
248
+ chatgptUserId: asOptionalString(auth?.chatgpt_user_id) ?? asOptionalString(auth?.user_id),
249
+ chatgptAccountId: asOptionalString(auth?.chatgpt_account_id),
250
+ chatgptAccountIsFedramp: auth?.chatgpt_account_is_fedramp === true,
251
+ expiresAt: expiresAtSeconds !== undefined ? new Date(expiresAtSeconds * 1000).toISOString() : undefined,
252
+ };
253
+ };
254
+ const createTokenSet = (response, existing) => {
255
+ const accessToken = asOptionalString(response.access_token, MAX_TOKEN_BYTES) ?? existing?.accessToken;
256
+ const refreshToken = asOptionalString(response.refresh_token, MAX_TOKEN_BYTES) ?? existing?.refreshToken;
257
+ const idToken = asOptionalString(response.id_token, MAX_TOKEN_BYTES) ?? existing?.idToken;
258
+ if (!accessToken)
259
+ throw new OpenAiAuthError('OpenAI auth response is missing access_token.');
260
+ if (!refreshToken)
261
+ throw new OpenAiAuthError('OpenAI auth response is missing refresh_token.');
262
+ let claims;
263
+ try {
264
+ claims = parseOpenAiTokenClaims(idToken ?? accessToken);
265
+ }
266
+ catch {
267
+ throw new OpenAiAuthError('OpenAI auth returned an invalid token.');
268
+ }
269
+ return { accessToken, refreshToken, ...(idToken ? { idToken } : {}), claims };
270
+ };
271
+ /** Starts a device sign-in (`POST {issuer}/api/accounts/deviceauth/usercode`). */
272
+ export const requestOpenAiDeviceCode = async (options = {}) => {
273
+ const response = await postJson(`${OPENAI_AUTH_ISSUER}/api/accounts/deviceauth/usercode`, { client_id: OPENAI_AUTH_CLIENT_ID }, options);
274
+ return {
275
+ verificationUrl: `${OPENAI_AUTH_ISSUER}/codex/device`,
276
+ userCode: asString(response.user_code ?? response.usercode, 'user_code'),
277
+ deviceAuthId: asString(response.device_auth_id, 'device_auth_id'),
278
+ intervalSeconds: asIntervalSeconds(response.interval),
279
+ };
280
+ };
281
+ const assertDeviceCode = (deviceCode) => {
282
+ if (deviceCode === null || typeof deviceCode !== 'object'
283
+ || typeof deviceCode.deviceAuthId !== 'string' || !deviceCode.deviceAuthId
284
+ || typeof deviceCode.userCode !== 'string' || !deviceCode.userCode
285
+ || utf8ByteLength(deviceCode.deviceAuthId) > MAX_IDENTIFIER_BYTES
286
+ || utf8ByteLength(deviceCode.userCode) > MAX_IDENTIFIER_BYTES
287
+ || !Number.isSafeInteger(deviceCode.intervalSeconds) || deviceCode.intervalSeconds < 1
288
+ || deviceCode.intervalSeconds > 300) {
289
+ throw new OpenAiAuthError('OpenAI device-code input is invalid.', { requestOutcome: 'notSent' });
290
+ }
291
+ };
292
+ /**
293
+ * Asks once whether the person approved the sign-in (`POST {issuer}/api/accounts/deviceauth/token`): 403 and 404
294
+ * mean pending, as in Codex. `timeoutMs` bounds the one request (at most thirty seconds). The authorization it
295
+ * answers is single-use, so one sign-in is polled by one caller at a time.
296
+ */
297
+ export const pollOpenAiDeviceCodeOnce = async (deviceCode, options = {}) => {
298
+ assertDeviceCode(deviceCode);
299
+ const timeoutMs = options.timeoutMs ?? REQUEST_TIMEOUT_MS;
300
+ if (!Number.isSafeInteger(timeoutMs) || timeoutMs < 1) {
301
+ throw new OpenAiAuthError('OpenAI device-code timeout is invalid.', { requestOutcome: 'notSent' });
302
+ }
303
+ const pollUrl = `${OPENAI_AUTH_ISSUER}/api/accounts/deviceauth/token`;
304
+ const pollResult = await runFetch(pollUrl, {
305
+ method: 'POST',
306
+ headers: { 'Content-Type': 'application/json' },
307
+ body: JSON.stringify({ device_auth_id: deviceCode.deviceAuthId, user_code: deviceCode.userCode }),
308
+ }, options, async (response, requestOptions) => {
309
+ if (response.ok) {
310
+ return { status: 'complete',
311
+ body: await readJson(response, `POST ${pollUrl}`, requestOptions) };
312
+ }
313
+ await readResponseText(response, requestOptions);
314
+ if (response.status !== 403 && response.status !== 404) {
315
+ throw new OpenAiAuthError(`OpenAI device-code polling failed with status ${response.status}.`, { status: response.status });
316
+ }
317
+ return { status: 'pending' };
318
+ }, timeoutMs);
319
+ if (pollResult.status === 'pending')
320
+ return { status: 'pending' };
321
+ return {
322
+ status: 'approved',
323
+ authorization: {
324
+ authorizationCode: asString(pollResult.body.authorization_code, 'authorization_code', MAX_AUTHORIZATION_CODE_BYTES),
325
+ codeChallenge: asString(pollResult.body.code_challenge, 'code_challenge'),
326
+ codeVerifier: asString(pollResult.body.code_verifier, 'code_verifier'),
327
+ },
328
+ };
329
+ };
330
+ /**
331
+ * Polls until the person approved the sign-in, at the interval the service asked for, and gives up after at most
332
+ * fifteen minutes, as Codex does.
333
+ */
334
+ export const pollOpenAiDeviceCode = async (deviceCode, options = {}) => {
335
+ const timeoutMs = options.timeoutMs ?? DEVICE_CODE_TIMEOUT_MS;
336
+ if (!Number.isSafeInteger(timeoutMs) || timeoutMs < 1 || timeoutMs > DEVICE_CODE_TIMEOUT_MS) {
337
+ throw new OpenAiAuthError('OpenAI device-code timeout is invalid.');
338
+ }
339
+ assertDeviceCode(deviceCode);
340
+ const startedAt = Date.now();
341
+ while (Date.now() - startedAt < timeoutMs) {
342
+ const remainingBeforeRequest = timeoutMs - (Date.now() - startedAt);
343
+ const poll = await pollOpenAiDeviceCodeOnce(deviceCode, { ...options, timeoutMs: Math.max(remainingBeforeRequest, 1) });
344
+ if (poll.status === 'approved')
345
+ return poll.authorization;
346
+ const remaining = timeoutMs - (Date.now() - startedAt);
347
+ await sleepWithAbort(Math.min(deviceCode.intervalSeconds * 1000, Math.max(remaining, 0)), options);
348
+ }
349
+ throw new OpenAiAuthError('OpenAI device-code login timed out.');
350
+ };
351
+ /** Exchanges an approved device sign-in for tokens (`POST {issuer}/oauth/token`, PKCE, form-encoded). */
352
+ export const exchangeOpenAiDeviceAuthorization = async (authorization, options = {}) => {
353
+ const response = await postForm(`${OPENAI_AUTH_ISSUER}/oauth/token`, new URLSearchParams({
354
+ grant_type: 'authorization_code',
355
+ code: authorization.authorizationCode,
356
+ redirect_uri: `${OPENAI_AUTH_ISSUER}/deviceauth/callback`,
357
+ client_id: OPENAI_AUTH_CLIENT_ID,
358
+ code_verifier: authorization.codeVerifier,
359
+ }), options);
360
+ return createTokenSet(response);
361
+ };
362
+ /**
363
+ * Sends one refresh-token grant (`POST {issuer}/oauth/token`, JSON). A response without a new refresh token keeps
364
+ * the one that was sent, as Codex does.
365
+ */
366
+ export const refreshOpenAiTokens = async (tokens, options = {}) => {
367
+ const response = await postJson(`${OPENAI_AUTH_ISSUER}/oauth/token`, {
368
+ client_id: OPENAI_AUTH_CLIENT_ID,
369
+ grant_type: 'refresh_token',
370
+ refresh_token: tokens.refreshToken,
371
+ }, options);
372
+ return createTokenSet({
373
+ id_token: response.id_token ?? tokens.idToken,
374
+ access_token: response.access_token ?? tokens.accessToken,
375
+ refresh_token: response.refresh_token ?? tokens.refreshToken,
376
+ }, tokens);
377
+ };
378
+ /**
379
+ * Revokes a refresh token (`POST {issuer}/oauth/revoke`, JSON), as Codex does when it logs out: the grant then
380
+ * refreshes nothing anywhere. It resolves only once the service accepted the revocation.
381
+ */
382
+ export const revokeOpenAiRefreshToken = async (refreshToken, options = {}) => {
383
+ if (typeof refreshToken !== 'string' || !refreshToken || utf8ByteLength(refreshToken) > MAX_TOKEN_BYTES) {
384
+ throw new OpenAiAuthError('OpenAI revocation input is invalid.', { requestOutcome: 'notSent' });
385
+ }
386
+ const url = `${OPENAI_AUTH_ISSUER}/oauth/revoke`;
387
+ await runFetch(url, {
388
+ method: 'POST',
389
+ headers: { 'Content-Type': 'application/json' },
390
+ body: JSON.stringify({ token: refreshToken, token_type_hint: 'refresh_token', client_id: OPENAI_AUTH_CLIENT_ID }),
391
+ }, options, async (response, requestOptions) => {
392
+ await readResponseText(response, requestOptions);
393
+ if (!response.ok)
394
+ throw new OpenAiAuthError(`POST ${url} failed with status ${response.status}.`, { status: response.status });
395
+ }, REVOKE_TIMEOUT_MS);
396
+ };
397
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2lnbmluLnByb3RvY29sLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHNfc2lnbmluL3NpZ25pbi5wcm90b2NvbC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSwySkFBMko7QUFJM0o7Ozs7O0dBS0c7QUFFSCxNQUFNLENBQUMsTUFBTSxrQkFBa0IsR0FBRyx5QkFBeUIsQ0FBQztBQUM1RCxNQUFNLENBQUMsTUFBTSxxQkFBcUIsR0FBRyw4QkFBOEIsQ0FBQztBQUVwRSw2R0FBNkc7QUFDN0csTUFBTSxDQUFDLE1BQU0sOEJBQThCLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxJQUFJLENBQUM7QUFDN0QsTUFBTSxzQkFBc0IsR0FBRyw4QkFBOEIsQ0FBQztBQUM5RCxxQ0FBcUM7QUFDckMsTUFBTSxpQkFBaUIsR0FBRyxNQUFNLENBQUM7QUFDakMsTUFBTSxrQkFBa0IsR0FBRyxFQUFFLEdBQUcsSUFBSSxDQUFDO0FBQ3JDLE1BQU0sZUFBZSxHQUFHLEVBQUUsR0FBRyxJQUFJLENBQUM7QUFDbEMsTUFBTSw0QkFBNEIsR0FBRyxDQUFDLEdBQUcsSUFBSSxDQUFDO0FBQzlDLE1BQU0sb0JBQW9CLEdBQUcsSUFBSSxDQUFDO0FBQ2xDLE1BQU0sa0JBQWtCLEdBQUcsTUFBTSxDQUFDO0FBQ2xDLE1BQU0sV0FBVyxHQUFHLElBQUksV0FBVyxFQUFFLENBQUM7QUFDdEMsTUFBTSxXQUFXLEdBQUcsSUFBSSxXQUFXLEVBQUUsQ0FBQztBQUN0QyxNQUFNLGNBQWMsR0FBRyxDQUFDLFFBQWdCLEVBQVUsRUFBRSxDQUFDLFdBQVcsQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUMsVUFBVSxDQUFDO0FBRTdGLE1BQU0sT0FBTyxlQUFnQixTQUFRLEtBQUs7SUFDeEIsTUFBTSxDQUFVO0lBQ2hCLGNBQWMsQ0FBeUI7SUFDdkMsWUFBWSxDQUFVO0lBRXRDLFlBQVksT0FBZSxFQUFFLFVBQ0QsRUFBRTtRQUM1QixLQUFLLENBQUMsT0FBTyxD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
package/license.md ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2026 Task Venture Capital GmbH
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.