@framers/agentos 0.1.41 → 0.1.42
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.
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @fileoverview OpenAI OAuth
|
|
2
|
+
* @fileoverview OpenAI OAuth PKCE flow — browser-based, like the Codex CLI.
|
|
3
3
|
*
|
|
4
4
|
* Uses the same public client ID and endpoints as the Codex CLI to obtain
|
|
5
5
|
* API access tokens from OpenAI consumer subscriptions (ChatGPT Plus/Pro).
|
|
6
6
|
*
|
|
7
|
-
* Flow:
|
|
8
|
-
* 1.
|
|
9
|
-
* 2.
|
|
10
|
-
* 3.
|
|
11
|
-
* 4.
|
|
7
|
+
* Flow (browser-based PKCE — bypasses Cloudflare challenges):
|
|
8
|
+
* 1. Generate PKCE code_verifier + code_challenge
|
|
9
|
+
* 2. Start a local HTTP server on localhost:1455
|
|
10
|
+
* 3. Open the user's browser to OpenAI's /authorize endpoint
|
|
11
|
+
* 4. User logs in via browser → OpenAI redirects to localhost:1455/auth/callback
|
|
12
|
+
* 5. Exchange authorization_code + code_verifier for tokens via /oauth/token
|
|
12
13
|
*
|
|
13
14
|
* @module agentos/core/llm/auth/OpenAIOAuthFlow
|
|
14
15
|
*/
|
|
@@ -16,19 +17,19 @@ import type { IOAuthFlow, IOAuthTokenStore, OAuthTokenSet } from './types.js';
|
|
|
16
17
|
export interface OpenAIOAuthFlowOptions {
|
|
17
18
|
tokenStore?: IOAuthTokenStore;
|
|
18
19
|
clientId?: string;
|
|
19
|
-
/** Called when the
|
|
20
|
-
|
|
20
|
+
/** Called when the browser is about to open. */
|
|
21
|
+
onBrowserOpen?: (authUrl: string) => void;
|
|
21
22
|
}
|
|
22
23
|
export declare class OpenAIOAuthFlow implements IOAuthFlow {
|
|
23
24
|
readonly providerId = "openai";
|
|
24
25
|
private readonly store;
|
|
25
26
|
private readonly clientId;
|
|
26
|
-
private readonly
|
|
27
|
+
private readonly onBrowserOpen;
|
|
27
28
|
private refreshPromise;
|
|
28
29
|
constructor(opts?: OpenAIOAuthFlowOptions);
|
|
29
30
|
/**
|
|
30
|
-
* Run the
|
|
31
|
-
*
|
|
31
|
+
* Run the browser-based PKCE OAuth flow.
|
|
32
|
+
* Opens the user's browser, waits for the callback, exchanges for tokens.
|
|
32
33
|
*/
|
|
33
34
|
authenticate(): Promise<OAuthTokenSet>;
|
|
34
35
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OpenAIOAuthFlow.d.ts","sourceRoot":"","sources":["../../../../src/core/llm/auth/OpenAIOAuthFlow.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"OpenAIOAuthFlow.d.ts","sourceRoot":"","sources":["../../../../src/core/llm/auth/OpenAIOAuthFlow.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,OAAO,KAAK,EACV,UAAU,EACV,gBAAgB,EAChB,aAAa,EACd,MAAM,YAAY,CAAC;AA2BpB,MAAM,WAAW,sBAAsB;IACrC,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gDAAgD;IAChD,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CAC3C;AAED,qBAAa,eAAgB,YAAW,UAAU;IAChD,QAAQ,CAAC,UAAU,YAAY;IAC/B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAmB;IACzC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAA4B;IAC1D,OAAO,CAAC,cAAc,CAAuC;gBAEjD,IAAI,CAAC,EAAE,sBAAsB;IAMzC;;;OAGG;IACG,YAAY,IAAI,OAAO,CAAC,aAAa,CAAC;IA+D5C;;OAEG;IACG,OAAO,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC;IAoC5D;;OAEG;IACH,OAAO,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO;IAIvC;;;OAGG;IACG,cAAc,IAAI,OAAO,CAAC,MAAM,CAAC;CAsBxC"}
|
|
@@ -1,119 +1,99 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @fileoverview OpenAI OAuth
|
|
2
|
+
* @fileoverview OpenAI OAuth PKCE flow — browser-based, like the Codex CLI.
|
|
3
3
|
*
|
|
4
4
|
* Uses the same public client ID and endpoints as the Codex CLI to obtain
|
|
5
5
|
* API access tokens from OpenAI consumer subscriptions (ChatGPT Plus/Pro).
|
|
6
6
|
*
|
|
7
|
-
* Flow:
|
|
8
|
-
* 1.
|
|
9
|
-
* 2.
|
|
10
|
-
* 3.
|
|
11
|
-
* 4.
|
|
7
|
+
* Flow (browser-based PKCE — bypasses Cloudflare challenges):
|
|
8
|
+
* 1. Generate PKCE code_verifier + code_challenge
|
|
9
|
+
* 2. Start a local HTTP server on localhost:1455
|
|
10
|
+
* 3. Open the user's browser to OpenAI's /authorize endpoint
|
|
11
|
+
* 4. User logs in via browser → OpenAI redirects to localhost:1455/auth/callback
|
|
12
|
+
* 5. Exchange authorization_code + code_verifier for tokens via /oauth/token
|
|
12
13
|
*
|
|
13
14
|
* @module agentos/core/llm/auth/OpenAIOAuthFlow
|
|
14
15
|
*/
|
|
16
|
+
import { createServer } from 'node:http';
|
|
17
|
+
import { randomBytes, createHash } from 'node:crypto';
|
|
15
18
|
import { FileTokenStore } from './FileTokenStore.js';
|
|
16
19
|
/** OpenAI's public Codex CLI client ID. */
|
|
17
20
|
const OPENAI_CLIENT_ID = 'app_EMoamEEZ73f0CkXaXp7hrann';
|
|
18
21
|
/** OpenAI auth base URL. */
|
|
19
22
|
const AUTH_BASE_URL = 'https://auth.openai.com';
|
|
20
|
-
/**
|
|
21
|
-
const
|
|
22
|
-
/**
|
|
23
|
-
const
|
|
24
|
-
/** Common headers for
|
|
23
|
+
/** Local callback server port (same as Codex CLI). */
|
|
24
|
+
const CALLBACK_PORT = 1455;
|
|
25
|
+
/** Redirect URI — must match what OpenAI expects for this client ID. */
|
|
26
|
+
const REDIRECT_URI = `http://localhost:${CALLBACK_PORT}/auth/callback`;
|
|
27
|
+
/** Common headers for token exchange requests. */
|
|
25
28
|
const AUTH_HEADERS = {
|
|
26
29
|
'User-Agent': 'wunderland-cli/1.0 (OpenAI OAuth; +https://wunderland.sh)',
|
|
27
30
|
'Accept': 'application/json',
|
|
28
31
|
};
|
|
29
32
|
/** Buffer in ms before expiry to trigger refresh (5 minutes). */
|
|
30
33
|
const REFRESH_BUFFER_MS = 5 * 60 * 1000;
|
|
31
|
-
/** Maximum time to wait for user to authorize (
|
|
32
|
-
const
|
|
34
|
+
/** Maximum time to wait for user to authorize (10 minutes). */
|
|
35
|
+
const MAX_AUTH_TIMEOUT_MS = 10 * 60 * 1000;
|
|
33
36
|
export class OpenAIOAuthFlow {
|
|
34
37
|
constructor(opts) {
|
|
35
38
|
this.providerId = 'openai';
|
|
36
39
|
this.refreshPromise = null;
|
|
37
40
|
this.store = opts?.tokenStore ?? new FileTokenStore();
|
|
38
41
|
this.clientId = opts?.clientId ?? OPENAI_CLIENT_ID;
|
|
39
|
-
this.
|
|
42
|
+
this.onBrowserOpen = opts?.onBrowserOpen ?? (() => { });
|
|
40
43
|
}
|
|
41
44
|
/**
|
|
42
|
-
* Run the
|
|
43
|
-
*
|
|
45
|
+
* Run the browser-based PKCE OAuth flow.
|
|
46
|
+
* Opens the user's browser, waits for the callback, exchanges for tokens.
|
|
44
47
|
*/
|
|
45
48
|
async authenticate() {
|
|
46
|
-
// Step 1:
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
await
|
|
67
|
-
const pollRes = await fetch(`${AUTH_BASE_URL}/deviceauth/token`, {
|
|
49
|
+
// Step 1: Generate PKCE pair
|
|
50
|
+
const codeVerifier = generateCodeVerifier();
|
|
51
|
+
const codeChallenge = generateCodeChallenge(codeVerifier);
|
|
52
|
+
const state = randomBytes(16).toString('hex');
|
|
53
|
+
// Step 2: Start local callback server
|
|
54
|
+
const { promise: callbackPromise, server } = startCallbackServer(state);
|
|
55
|
+
try {
|
|
56
|
+
// Step 3: Build authorization URL and open browser
|
|
57
|
+
const authUrl = buildAuthUrl(this.clientId, codeChallenge, state);
|
|
58
|
+
this.onBrowserOpen(authUrl);
|
|
59
|
+
// Open the system browser
|
|
60
|
+
await openBrowser(authUrl);
|
|
61
|
+
// Step 4: Wait for the callback with auth code
|
|
62
|
+
const authCode = await Promise.race([
|
|
63
|
+
callbackPromise,
|
|
64
|
+
timeout(MAX_AUTH_TIMEOUT_MS).then(() => {
|
|
65
|
+
throw new Error('OAuth authorization timed out. Please try again.');
|
|
66
|
+
}),
|
|
67
|
+
]);
|
|
68
|
+
// Step 5: Exchange authorization code for tokens
|
|
69
|
+
const tokenRes = await fetch(`${AUTH_BASE_URL}/oauth/token`, {
|
|
68
70
|
method: 'POST',
|
|
69
|
-
headers: { ...AUTH_HEADERS, 'Content-Type': 'application/
|
|
70
|
-
body:
|
|
71
|
+
headers: { ...AUTH_HEADERS, 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
72
|
+
body: new URLSearchParams({
|
|
73
|
+
grant_type: 'authorization_code',
|
|
74
|
+
code: authCode,
|
|
75
|
+
redirect_uri: REDIRECT_URI,
|
|
76
|
+
client_id: this.clientId,
|
|
77
|
+
code_verifier: codeVerifier,
|
|
78
|
+
}).toString(),
|
|
71
79
|
});
|
|
72
|
-
if (
|
|
73
|
-
const
|
|
74
|
-
|
|
75
|
-
authCode = pollData.authorization_code;
|
|
76
|
-
codeVerifier = pollData.code_verifier;
|
|
77
|
-
break;
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
// 403/428 means "authorization_pending" — keep polling
|
|
81
|
-
if (pollRes.status === 403 || pollRes.status === 428) {
|
|
82
|
-
continue;
|
|
83
|
-
}
|
|
84
|
-
// Other errors are fatal
|
|
85
|
-
if (!pollRes.ok) {
|
|
86
|
-
const body = await pollRes.text();
|
|
87
|
-
throw new Error(`Device auth poll failed: ${pollRes.status} ${body}`);
|
|
80
|
+
if (!tokenRes.ok) {
|
|
81
|
+
const body = await tokenRes.text();
|
|
82
|
+
throw new Error(`Token exchange failed: ${tokenRes.status} ${body}`);
|
|
88
83
|
}
|
|
84
|
+
const tokenData = await tokenRes.json();
|
|
85
|
+
const tokens = {
|
|
86
|
+
accessToken: tokenData.access_token,
|
|
87
|
+
refreshToken: tokenData.refresh_token,
|
|
88
|
+
expiresAt: Date.now() + (tokenData.expires_in ?? 3600) * 1000,
|
|
89
|
+
};
|
|
90
|
+
await this.store.save(this.providerId, tokens);
|
|
91
|
+
return tokens;
|
|
89
92
|
}
|
|
90
|
-
|
|
91
|
-
|
|
93
|
+
finally {
|
|
94
|
+
// Always shut down the callback server
|
|
95
|
+
server.close();
|
|
92
96
|
}
|
|
93
|
-
// Step 3: Exchange authorization code for tokens
|
|
94
|
-
const tokenRes = await fetch(`${AUTH_BASE_URL}/oauth/token`, {
|
|
95
|
-
method: 'POST',
|
|
96
|
-
headers: { ...AUTH_HEADERS, 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
97
|
-
body: new URLSearchParams({
|
|
98
|
-
grant_type: 'authorization_code',
|
|
99
|
-
code: authCode,
|
|
100
|
-
redirect_uri: REDIRECT_URI,
|
|
101
|
-
client_id: this.clientId,
|
|
102
|
-
...(codeVerifier ? { code_verifier: codeVerifier } : {}),
|
|
103
|
-
}).toString(),
|
|
104
|
-
});
|
|
105
|
-
if (!tokenRes.ok) {
|
|
106
|
-
const body = await tokenRes.text();
|
|
107
|
-
throw new Error(`Token exchange failed: ${tokenRes.status} ${body}`);
|
|
108
|
-
}
|
|
109
|
-
const tokenData = await tokenRes.json();
|
|
110
|
-
const tokens = {
|
|
111
|
-
accessToken: tokenData.access_token,
|
|
112
|
-
refreshToken: tokenData.refresh_token,
|
|
113
|
-
expiresAt: Date.now() + (tokenData.expires_in ?? 3600) * 1000,
|
|
114
|
-
};
|
|
115
|
-
await this.store.save(this.providerId, tokens);
|
|
116
|
-
return tokens;
|
|
117
97
|
}
|
|
118
98
|
/**
|
|
119
99
|
* Refresh an expired access token using the refresh token.
|
|
@@ -172,16 +152,98 @@ export class OpenAIOAuthFlow {
|
|
|
172
152
|
return refreshed.accessToken;
|
|
173
153
|
}
|
|
174
154
|
}
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
155
|
+
// ── PKCE helpers ────────────────────────────────────────────────────────────
|
|
156
|
+
function generateCodeVerifier() {
|
|
157
|
+
return randomBytes(32).toString('base64url');
|
|
158
|
+
}
|
|
159
|
+
function generateCodeChallenge(verifier) {
|
|
160
|
+
return createHash('sha256').update(verifier).digest('base64url');
|
|
161
|
+
}
|
|
162
|
+
// ── Authorization URL builder ───────────────────────────────────────────────
|
|
163
|
+
function buildAuthUrl(clientId, codeChallenge, state) {
|
|
164
|
+
const params = new URLSearchParams({
|
|
165
|
+
response_type: 'code',
|
|
166
|
+
client_id: clientId,
|
|
167
|
+
redirect_uri: REDIRECT_URI,
|
|
168
|
+
scope: 'openid profile email offline_access',
|
|
169
|
+
state,
|
|
170
|
+
code_challenge: codeChallenge,
|
|
171
|
+
code_challenge_method: 'S256',
|
|
172
|
+
});
|
|
173
|
+
return `${AUTH_BASE_URL}/authorize?${params.toString()}`;
|
|
174
|
+
}
|
|
175
|
+
// ── Local callback server ───────────────────────────────────────────────────
|
|
176
|
+
const SUCCESS_HTML = `<!DOCTYPE html><html><head><title>Wunderland — Authenticated</title>
|
|
177
|
+
<style>body{font-family:system-ui,-apple-system,sans-serif;display:flex;align-items:center;justify-content:center;min-height:100vh;margin:0;background:#0a0a0f;color:#c9d1d9}
|
|
178
|
+
.card{text-align:center;padding:3rem;border:1px solid #a855f7;border-radius:16px;max-width:420px}
|
|
179
|
+
h1{color:#a855f7;margin:0 0 1rem}p{color:#6b7280;line-height:1.6}
|
|
180
|
+
.check{font-size:3rem;margin-bottom:1rem}</style></head>
|
|
181
|
+
<body><div class="card"><div class="check">✓</div><h1>Authenticated</h1>
|
|
182
|
+
<p>You can close this tab and return to your terminal.</p></div></body></html>`;
|
|
183
|
+
const ERROR_HTML = (msg) => `<!DOCTYPE html><html><head><title>Wunderland — Error</title>
|
|
184
|
+
<style>body{font-family:system-ui,-apple-system,sans-serif;display:flex;align-items:center;justify-content:center;min-height:100vh;margin:0;background:#0a0a0f;color:#c9d1d9}
|
|
185
|
+
.card{text-align:center;padding:3rem;border:1px solid #ef4444;border-radius:16px;max-width:420px}
|
|
186
|
+
h1{color:#ef4444;margin:0 0 1rem}p{color:#6b7280;line-height:1.6}</style></head>
|
|
187
|
+
<body><div class="card"><h1>Authentication Failed</h1><p>${msg}</p></div></body></html>`;
|
|
188
|
+
function startCallbackServer(expectedState) {
|
|
189
|
+
let resolveCode;
|
|
190
|
+
let rejectCode;
|
|
191
|
+
const promise = new Promise((resolve, reject) => {
|
|
192
|
+
resolveCode = resolve;
|
|
193
|
+
rejectCode = reject;
|
|
194
|
+
});
|
|
195
|
+
const server = createServer((req, res) => {
|
|
196
|
+
const url = new URL(req.url ?? '/', `http://localhost:${CALLBACK_PORT}`);
|
|
197
|
+
if (url.pathname !== '/auth/callback') {
|
|
198
|
+
res.writeHead(404, { 'Content-Type': 'text/plain' });
|
|
199
|
+
res.end('Not found');
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
const code = url.searchParams.get('code');
|
|
203
|
+
const state = url.searchParams.get('state');
|
|
204
|
+
const error = url.searchParams.get('error');
|
|
205
|
+
const errorDescription = url.searchParams.get('error_description');
|
|
206
|
+
if (error) {
|
|
207
|
+
res.writeHead(200, { 'Content-Type': 'text/html' });
|
|
208
|
+
res.end(ERROR_HTML(errorDescription || error));
|
|
209
|
+
rejectCode(new Error(`OAuth error: ${error} — ${errorDescription || 'unknown'}`));
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
if (!code) {
|
|
213
|
+
res.writeHead(400, { 'Content-Type': 'text/html' });
|
|
214
|
+
res.end(ERROR_HTML('No authorization code received.'));
|
|
215
|
+
rejectCode(new Error('No authorization code in callback'));
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
if (state !== expectedState) {
|
|
219
|
+
res.writeHead(400, { 'Content-Type': 'text/html' });
|
|
220
|
+
res.end(ERROR_HTML('State mismatch — possible CSRF attack.'));
|
|
221
|
+
rejectCode(new Error('OAuth state mismatch'));
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
// Success
|
|
225
|
+
res.writeHead(200, { 'Content-Type': 'text/html' });
|
|
226
|
+
res.end(SUCCESS_HTML);
|
|
227
|
+
resolveCode(code);
|
|
228
|
+
});
|
|
229
|
+
server.listen(CALLBACK_PORT, '127.0.0.1');
|
|
230
|
+
return { promise, server };
|
|
231
|
+
}
|
|
232
|
+
// ── Browser opener ──────────────────────────────────────────────────────────
|
|
233
|
+
async function openBrowser(url) {
|
|
234
|
+
const { exec } = await import('node:child_process');
|
|
235
|
+
const { platform } = await import('node:os');
|
|
236
|
+
const cmd = platform() === 'darwin'
|
|
237
|
+
? `open "${url}"`
|
|
238
|
+
: platform() === 'win32'
|
|
239
|
+
? `start "" "${url}"`
|
|
240
|
+
: `xdg-open "${url}"`;
|
|
241
|
+
return new Promise((resolve) => {
|
|
242
|
+
exec(cmd, () => resolve());
|
|
243
|
+
});
|
|
183
244
|
}
|
|
184
|
-
|
|
245
|
+
// ── Utilities ───────────────────────────────────────────────────────────────
|
|
246
|
+
function timeout(ms) {
|
|
185
247
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
186
248
|
}
|
|
187
249
|
//# sourceMappingURL=OpenAIOAuthFlow.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OpenAIOAuthFlow.js","sourceRoot":"","sources":["../../../../src/core/llm/auth/OpenAIOAuthFlow.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"OpenAIOAuthFlow.js","sourceRoot":"","sources":["../../../../src/core/llm/auth/OpenAIOAuthFlow.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,YAAY,EAA0D,MAAM,WAAW,CAAC;AACjG,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAMtD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAErD,2CAA2C;AAC3C,MAAM,gBAAgB,GAAG,8BAA8B,CAAC;AAExD,4BAA4B;AAC5B,MAAM,aAAa,GAAG,yBAAyB,CAAC;AAEhD,sDAAsD;AACtD,MAAM,aAAa,GAAG,IAAI,CAAC;AAE3B,wEAAwE;AACxE,MAAM,YAAY,GAAG,oBAAoB,aAAa,gBAAgB,CAAC;AAEvE,kDAAkD;AAClD,MAAM,YAAY,GAAG;IACnB,YAAY,EAAE,2DAA2D;IACzE,QAAQ,EAAE,kBAAkB;CAC7B,CAAC;AAEF,iEAAiE;AACjE,MAAM,iBAAiB,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;AAExC,+DAA+D;AAC/D,MAAM,mBAAmB,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;AAS3C,MAAM,OAAO,eAAe;IAO1B,YAAY,IAA6B;QANhC,eAAU,GAAG,QAAQ,CAAC;QAIvB,mBAAc,GAAkC,IAAI,CAAC;QAG3D,IAAI,CAAC,KAAK,GAAG,IAAI,EAAE,UAAU,IAAI,IAAI,cAAc,EAAE,CAAC;QACtD,IAAI,CAAC,QAAQ,GAAG,IAAI,EAAE,QAAQ,IAAI,gBAAgB,CAAC;QACnD,IAAI,CAAC,aAAa,GAAG,IAAI,EAAE,aAAa,IAAI,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IACzD,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,YAAY;QAChB,6BAA6B;QAC7B,MAAM,YAAY,GAAG,oBAAoB,EAAE,CAAC;QAC5C,MAAM,aAAa,GAAG,qBAAqB,CAAC,YAAY,CAAC,CAAC;QAC1D,MAAM,KAAK,GAAG,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QAE9C,sCAAsC;QACtC,MAAM,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,EAAE,GAAG,mBAAmB,CAAC,KAAK,CAAC,CAAC;QAExE,IAAI,CAAC;YACH,mDAAmD;YACnD,MAAM,OAAO,GAAG,YAAY,CAAC,IAAI,CAAC,QAAQ,EAAE,aAAa,EAAE,KAAK,CAAC,CAAC;YAClE,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;YAE5B,0BAA0B;YAC1B,MAAM,WAAW,CAAC,OAAO,CAAC,CAAC;YAE3B,+CAA+C;YAC/C,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC;gBAClC,eAAe;gBACf,OAAO,CAAC,mBAAmB,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE;oBACrC,MAAM,IAAI,KAAK,CAAC,kDAAkD,CAAC,CAAC;gBACtE,CAAC,CAAC;aACH,CAAC,CAAC;YAEH,iDAAiD;YACjD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,aAAa,cAAc,EAAE;gBAC3D,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE,EAAE,GAAG,YAAY,EAAE,cAAc,EAAE,mCAAmC,EAAE;gBACjF,IAAI,EAAE,IAAI,eAAe,CAAC;oBACxB,UAAU,EAAE,oBAAoB;oBAChC,IAAI,EAAE,QAAQ;oBACd,YAAY,EAAE,YAAY;oBAC1B,SAAS,EAAE,IAAI,CAAC,QAAQ;oBACxB,aAAa,EAAE,YAAY;iBAC5B,CAAC,CAAC,QAAQ,EAAE;aACd,CAAC,CAAC;YAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACjB,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;gBACnC,MAAM,IAAI,KAAK,CAAC,0BAA0B,QAAQ,CAAC,MAAM,IAAI,IAAI,EAAE,CAAC,CAAC;YACvE,CAAC;YAED,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC,IAAI,EAIpC,CAAC;YAEF,MAAM,MAAM,GAAkB;gBAC5B,WAAW,EAAE,SAAS,CAAC,YAAY;gBACnC,YAAY,EAAE,SAAS,CAAC,aAAa;gBACrC,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,SAAS,CAAC,UAAU,IAAI,IAAI,CAAC,GAAG,IAAI;aAC9D,CAAC;YAEF,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;YAC/C,OAAO,MAAM,CAAC;QAChB,CAAC;gBAAS,CAAC;YACT,uCAAuC;YACvC,MAAM,CAAC,KAAK,EAAE,CAAC;QACjB,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,OAAO,CAAC,MAAqB;QACjC,IAAI,CAAC,MAAM,CAAC,YAAY,EAAE,CAAC;YACzB,MAAM,IAAI,KAAK,CAAC,8DAA8D,CAAC,CAAC;QAClF,CAAC;QAED,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,aAAa,cAAc,EAAE;YACtD,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,GAAG,YAAY,EAAE,cAAc,EAAE,mCAAmC,EAAE;YACjF,IAAI,EAAE,IAAI,eAAe,CAAC;gBACxB,UAAU,EAAE,eAAe;gBAC3B,aAAa,EAAE,MAAM,CAAC,YAAY;gBAClC,SAAS,EAAE,IAAI,CAAC,QAAQ;aACzB,CAAC,CAAC,QAAQ,EAAE;SACd,CAAC,CAAC;QAEH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;YAC9B,MAAM,IAAI,KAAK,CAAC,yBAAyB,GAAG,CAAC,MAAM,IAAI,IAAI,EAAE,CAAC,CAAC;QACjE,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAI1B,CAAC;QAEF,MAAM,SAAS,GAAkB;YAC/B,WAAW,EAAE,IAAI,CAAC,YAAY;YAC9B,YAAY,EAAE,IAAI,CAAC,aAAa,IAAI,MAAM,CAAC,YAAY;YACvD,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,GAAG,IAAI;SACzD,CAAC;QAEF,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;QAClD,OAAO,SAAS,CAAC;IACnB,CAAC;IAED;;OAEG;IACH,OAAO,CAAC,MAAqB;QAC3B,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,MAAM,CAAC,SAAS,GAAG,iBAAiB,CAAC;IAC3D,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,cAAc;QAClB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACtD,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CACb,qGAAqG,CACtG,CAAC;QACJ,CAAC;QAED,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YACzB,OAAO,MAAM,CAAC,WAAW,CAAC;QAC5B,CAAC;QAED,2DAA2D;QAC3D,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC;YACzB,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE;gBACtD,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC;YAC7B,CAAC,CAAC,CAAC;QACL,CAAC;QAED,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC;QAC5C,OAAO,SAAS,CAAC,WAAW,CAAC;IAC/B,CAAC;CACF;AAED,+EAA+E;AAE/E,SAAS,oBAAoB;IAC3B,OAAO,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;AAC/C,CAAC;AAED,SAAS,qBAAqB,CAAC,QAAgB;IAC7C,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;AACnE,CAAC;AAED,+EAA+E;AAE/E,SAAS,YAAY,CAAC,QAAgB,EAAE,aAAqB,EAAE,KAAa;IAC1E,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC;QACjC,aAAa,EAAE,MAAM;QACrB,SAAS,EAAE,QAAQ;QACnB,YAAY,EAAE,YAAY;QAC1B,KAAK,EAAE,qCAAqC;QAC5C,KAAK;QACL,cAAc,EAAE,aAAa;QAC7B,qBAAqB,EAAE,MAAM;KAC9B,CAAC,CAAC;IACH,OAAO,GAAG,aAAa,cAAc,MAAM,CAAC,QAAQ,EAAE,EAAE,CAAC;AAC3D,CAAC;AAED,+EAA+E;AAE/E,MAAM,YAAY,GAAG;;;;;;+EAM0D,CAAC;AAEhF,MAAM,UAAU,GAAG,CAAC,GAAW,EAAE,EAAE,CAAC;;;;2DAIuB,GAAG,0BAA0B,CAAC;AAEzF,SAAS,mBAAmB,CAAC,aAAqB;IAChD,IAAI,WAAmC,CAAC;IACxC,IAAI,UAAgC,CAAC;IAErC,MAAM,OAAO,GAAG,IAAI,OAAO,CAAS,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACtD,WAAW,GAAG,OAAO,CAAC;QACtB,UAAU,GAAG,MAAM,CAAC;IACtB,CAAC,CAAC,CAAC;IAEH,MAAM,MAAM,GAAG,YAAY,CAAC,CAAC,GAAoB,EAAE,GAAmB,EAAE,EAAE;QACxE,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,GAAG,EAAE,oBAAoB,aAAa,EAAE,CAAC,CAAC;QAEzE,IAAI,GAAG,CAAC,QAAQ,KAAK,gBAAgB,EAAE,CAAC;YACtC,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,YAAY,EAAE,CAAC,CAAC;YACrD,GAAG,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;YACrB,OAAO;QACT,CAAC;QAED,MAAM,IAAI,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAC1C,MAAM,KAAK,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAC5C,MAAM,KAAK,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAC5C,MAAM,gBAAgB,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;QAEnE,IAAI,KAAK,EAAE,CAAC;YACV,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,WAAW,EAAE,CAAC,CAAC;YACpD,GAAG,CAAC,GAAG,CAAC,UAAU,CAAC,gBAAgB,IAAI,KAAK,CAAC,CAAC,CAAC;YAC/C,UAAU,CAAC,IAAI,KAAK,CAAC,gBAAgB,KAAK,MAAM,gBAAgB,IAAI,SAAS,EAAE,CAAC,CAAC,CAAC;YAClF,OAAO;QACT,CAAC;QAED,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,WAAW,EAAE,CAAC,CAAC;YACpD,GAAG,CAAC,GAAG,CAAC,UAAU,CAAC,iCAAiC,CAAC,CAAC,CAAC;YACvD,UAAU,CAAC,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC,CAAC;YAC3D,OAAO;QACT,CAAC;QAED,IAAI,KAAK,KAAK,aAAa,EAAE,CAAC;YAC5B,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,WAAW,EAAE,CAAC,CAAC;YACpD,GAAG,CAAC,GAAG,CAAC,UAAU,CAAC,wCAAwC,CAAC,CAAC,CAAC;YAC9D,UAAU,CAAC,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAC,CAAC;YAC9C,OAAO;QACT,CAAC;QAED,UAAU;QACV,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,WAAW,EAAE,CAAC,CAAC;QACpD,GAAG,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;QACtB,WAAW,CAAC,IAAI,CAAC,CAAC;IACpB,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,MAAM,CAAC,aAAa,EAAE,WAAW,CAAC,CAAC;IAE1C,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;AAC7B,CAAC;AAED,+EAA+E;AAE/E,KAAK,UAAU,WAAW,CAAC,GAAW;IACpC,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,MAAM,CAAC,oBAAoB,CAAC,CAAC;IACpD,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,CAAC;IAE7C,MAAM,GAAG,GAAG,QAAQ,EAAE,KAAK,QAAQ;QACjC,CAAC,CAAC,SAAS,GAAG,GAAG;QACjB,CAAC,CAAC,QAAQ,EAAE,KAAK,OAAO;YACtB,CAAC,CAAC,aAAa,GAAG,GAAG;YACrB,CAAC,CAAC,aAAa,GAAG,GAAG,CAAC;IAE1B,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC;IAC7B,CAAC,CAAC,CAAC;AACL,CAAC;AAED,+EAA+E;AAE/E,SAAS,OAAO,CAAC,EAAU;IACzB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;AAC3D,CAAC"}
|