@cortexkit/opencode-antigravity-auth 2.0.0 → 2.1.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/README.md +3 -8
- package/dist/cli.js +330 -83
- package/dist/cli.js.map +4 -4
- package/dist/index.js +17039 -15773
- package/dist/index.js.map +4 -4
- package/dist/src/plugin/account-command-oauth.d.ts +34 -0
- package/dist/src/plugin/account-command-oauth.d.ts.map +1 -0
- package/dist/src/plugin/account-command-oauth.js +156 -0
- package/dist/src/plugin/account-command-oauth.js.map +1 -0
- package/dist/src/plugin/auth-loader.d.ts +16 -1
- package/dist/src/plugin/auth-loader.d.ts.map +1 -1
- package/dist/src/plugin/auth-loader.js +113 -32
- package/dist/src/plugin/auth-loader.js.map +1 -1
- package/dist/src/plugin/background-quota-refresh.d.ts +146 -0
- package/dist/src/plugin/background-quota-refresh.d.ts.map +1 -0
- package/dist/src/plugin/background-quota-refresh.js +347 -0
- package/dist/src/plugin/background-quota-refresh.js.map +1 -0
- package/dist/src/plugin/command-data.d.ts +61 -8
- package/dist/src/plugin/command-data.d.ts.map +1 -1
- package/dist/src/plugin/command-data.js +231 -39
- package/dist/src/plugin/command-data.js.map +1 -1
- package/dist/src/plugin/commands.d.ts +12 -9
- package/dist/src/plugin/commands.d.ts.map +1 -1
- package/dist/src/plugin/commands.js +140 -33
- package/dist/src/plugin/commands.js.map +1 -1
- package/dist/src/plugin/config/schema.d.ts +2 -0
- package/dist/src/plugin/config/schema.d.ts.map +1 -1
- package/dist/src/plugin/config/schema.js +24 -0
- package/dist/src/plugin/config/schema.js.map +1 -1
- package/dist/src/plugin/debug.d.ts +7 -0
- package/dist/src/plugin/debug.d.ts.map +1 -1
- package/dist/src/plugin/debug.js +25 -0
- package/dist/src/plugin/debug.js.map +1 -1
- package/dist/src/plugin/fetch-interceptor.d.ts.map +1 -1
- package/dist/src/plugin/fetch-interceptor.js +13 -1
- package/dist/src/plugin/fetch-interceptor.js.map +1 -1
- package/dist/src/plugin/index.d.ts +7 -0
- package/dist/src/plugin/index.d.ts.map +1 -1
- package/dist/src/plugin/index.js +127 -24
- package/dist/src/plugin/index.js.map +1 -1
- package/dist/src/plugin/killswitch.d.ts.map +1 -1
- package/dist/src/plugin/killswitch.js +12 -9
- package/dist/src/plugin/killswitch.js.map +1 -1
- package/dist/src/plugin/oauth-methods.d.ts.map +1 -1
- package/dist/src/plugin/oauth-methods.js +2 -10
- package/dist/src/plugin/oauth-methods.js.map +1 -1
- package/dist/src/plugin/quota.d.ts +42 -1
- package/dist/src/plugin/quota.d.ts.map +1 -1
- package/dist/src/plugin/quota.js +185 -41
- package/dist/src/plugin/quota.js.map +1 -1
- package/dist/src/plugin/request.d.ts.map +1 -1
- package/dist/src/plugin/request.js +6 -2
- package/dist/src/plugin/request.js.map +1 -1
- package/dist/src/plugin/ui/auth-menu.d.ts.map +1 -1
- package/dist/src/plugin/ui/auth-menu.js +2 -4
- package/dist/src/plugin/ui/auth-menu.js.map +1 -1
- package/dist/src/plugin/ui/quota-status.d.ts.map +1 -1
- package/dist/src/plugin/ui/quota-status.js +3 -5
- package/dist/src/plugin/ui/quota-status.js.map +1 -1
- package/dist/src/sidebar-state.d.ts +126 -9
- package/dist/src/sidebar-state.d.ts.map +1 -1
- package/dist/src/sidebar-state.js +185 -25
- package/dist/src/sidebar-state.js.map +1 -1
- package/dist/src/tui/command-dialogs.js +101 -3
- package/dist/src/tui/command-dialogs.js.map +1 -1
- package/dist/src/tui.d.ts.map +1 -1
- package/dist/src/tui.js +55 -20
- package/dist/src/tui.js.map +1 -1
- package/package.json +6 -6
- package/src/plugin/command-data.ts +331 -51
- package/src/sidebar-state.ts +306 -32
- package/src/tui/command-dialogs.tsx +136 -3
- package/src/tui-compiled/plugin/command-data.ts +331 -51
- package/src/tui-compiled/sidebar-state.ts +306 -32
- package/src/tui-compiled/tui/command-dialogs.tsx +189 -69
- package/src/tui-compiled/tui.tsx +73 -30
- package/src/tui.tsx +82 -28
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { AntigravityAuthorization, AntigravityTokenExchangeResult } from '../antigravity/oauth';
|
|
2
|
+
import type { CommandAccountRow } from './command-data';
|
|
3
|
+
type OAuthSuccess = Extract<AntigravityTokenExchangeResult, {
|
|
4
|
+
type: 'success';
|
|
5
|
+
}>;
|
|
6
|
+
export interface AccountCommandOAuthServiceOptions {
|
|
7
|
+
authorize: () => Promise<AntigravityAuthorization>;
|
|
8
|
+
exchange: (code: string, state: string) => Promise<AntigravityTokenExchangeResult>;
|
|
9
|
+
persist: (result: OAuthSuccess) => Promise<void>;
|
|
10
|
+
listAccounts: () => Promise<CommandAccountRow[]>;
|
|
11
|
+
/**
|
|
12
|
+
* Optional hook invoked AFTER persist completes successfully. The plugin
|
|
13
|
+
* uses it to refresh the live AccountManager so the new account is
|
|
14
|
+
* visible to routing immediately, without waiting for an auth reload.
|
|
15
|
+
* Failures are swallowed — the OAuth flow still reports success and the
|
|
16
|
+
* next periodic AccountManager reload picks up the new account.
|
|
17
|
+
*/
|
|
18
|
+
onAfterPersist?: (result: OAuthSuccess) => Promise<void> | void;
|
|
19
|
+
now?: () => number;
|
|
20
|
+
}
|
|
21
|
+
export interface AccountCommandOAuthService {
|
|
22
|
+
start(sessionId: string): Promise<{
|
|
23
|
+
url: string;
|
|
24
|
+
accounts: CommandAccountRow[];
|
|
25
|
+
}>;
|
|
26
|
+
finish(sessionId: string, callbackInput: string, label?: string): Promise<{
|
|
27
|
+
text: string;
|
|
28
|
+
accounts: CommandAccountRow[];
|
|
29
|
+
}>;
|
|
30
|
+
dispose(): void;
|
|
31
|
+
}
|
|
32
|
+
export declare function createAccountCommandOAuthService(options: AccountCommandOAuthServiceOptions): AccountCommandOAuthService;
|
|
33
|
+
export {};
|
|
34
|
+
//# sourceMappingURL=account-command-oauth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"account-command-oauth.d.ts","sourceRoot":"","sources":["../../../src/plugin/account-command-oauth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,wBAAwB,EACxB,8BAA8B,EAC/B,MAAM,sBAAsB,CAAA;AAC7B,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAA;AAGvD,KAAK,YAAY,GAAG,OAAO,CAAC,8BAA8B,EAAE;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,CAAC,CAAA;AAShF,MAAM,WAAW,iCAAiC;IAChD,SAAS,EAAE,MAAM,OAAO,CAAC,wBAAwB,CAAC,CAAA;IAClD,QAAQ,EAAE,CACR,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,KACV,OAAO,CAAC,8BAA8B,CAAC,CAAA;IAC5C,OAAO,EAAE,CAAC,MAAM,EAAE,YAAY,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAChD,YAAY,EAAE,MAAM,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAAA;IAChD;;;;;;OAMG;IACH,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,YAAY,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;IAC/D,GAAG,CAAC,EAAE,MAAM,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,0BAA0B;IACzC,KAAK,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC;QAChC,GAAG,EAAE,MAAM,CAAA;QACX,QAAQ,EAAE,iBAAiB,EAAE,CAAA;KAC9B,CAAC,CAAA;IACF,MAAM,CACJ,SAAS,EAAE,MAAM,EACjB,aAAa,EAAE,MAAM,EACrB,KAAK,CAAC,EAAE,MAAM,GACb,OAAO,CAAC;QACT,IAAI,EAAE,MAAM,CAAA;QACZ,QAAQ,EAAE,iBAAiB,EAAE,CAAA;KAC9B,CAAC,CAAA;IACF,OAAO,IAAI,IAAI,CAAA;CAChB;AAKD,wBAAgB,gCAAgC,CAC9C,OAAO,EAAE,iCAAiC,GACzC,0BAA0B,CAgK5B"}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import { parseOAuthCallbackInput } from './oauth-methods';
|
|
2
|
+
const OAUTH_PENDING_TTL_MS = 10 * 60 * 1_000;
|
|
3
|
+
const OAUTH_PENDING_CAP = 50;
|
|
4
|
+
export function createAccountCommandOAuthService(options) {
|
|
5
|
+
const pendingBySession = new Map();
|
|
6
|
+
const now = options.now ?? (() => Date.now());
|
|
7
|
+
const cleanupExpired = () => {
|
|
8
|
+
const current = now();
|
|
9
|
+
for (const [sessionId, entry] of pendingBySession) {
|
|
10
|
+
if (current - entry.createdAt > OAUTH_PENDING_TTL_MS) {
|
|
11
|
+
pendingBySession.delete(sessionId);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
const takePending = (sessionId) => {
|
|
16
|
+
cleanupExpired();
|
|
17
|
+
const entry = pendingBySession.get(sessionId);
|
|
18
|
+
if (!entry || now() - entry.createdAt > OAUTH_PENDING_TTL_MS) {
|
|
19
|
+
pendingBySession.delete(sessionId);
|
|
20
|
+
return undefined;
|
|
21
|
+
}
|
|
22
|
+
// Consume the entry atomically with the take. A second concurrent
|
|
23
|
+
// `add-oauth-finish` call must observe "no pending entry" even
|
|
24
|
+
// before the first call's exchange completes — the previous
|
|
25
|
+
// peek-then-finally pattern allowed two finish() calls to both
|
|
26
|
+
// exchange and persist the same auth code.
|
|
27
|
+
pendingBySession.delete(sessionId);
|
|
28
|
+
return entry;
|
|
29
|
+
};
|
|
30
|
+
// Wrap listAccounts so a lock-contention or I/O failure in the error
|
|
31
|
+
// branches below does not replace the real OAuth failure text with a
|
|
32
|
+
// generic apply-error message. Mirrors the stage-4 guarded pattern.
|
|
33
|
+
const safeListAccounts = async () => {
|
|
34
|
+
try {
|
|
35
|
+
return await options.listAccounts();
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
return [];
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
return {
|
|
42
|
+
async start(sessionId) {
|
|
43
|
+
const authorization = await options.authorize();
|
|
44
|
+
const url = new URL(authorization.url);
|
|
45
|
+
const state = url.searchParams.get('state');
|
|
46
|
+
const redirectUri = url.searchParams.get('redirect_uri');
|
|
47
|
+
if (!state || !redirectUri) {
|
|
48
|
+
throw new Error('OAuth authorization URL is missing required state');
|
|
49
|
+
}
|
|
50
|
+
cleanupExpired();
|
|
51
|
+
if (pendingBySession.size >= OAUTH_PENDING_CAP) {
|
|
52
|
+
const oldest = [...pendingBySession.entries()].reduce((previous, current) => current[1].createdAt < previous[1].createdAt ? current : previous);
|
|
53
|
+
pendingBySession.delete(oldest[0]);
|
|
54
|
+
}
|
|
55
|
+
pendingBySession.set(sessionId, {
|
|
56
|
+
state,
|
|
57
|
+
verifier: authorization.verifier,
|
|
58
|
+
redirectUri,
|
|
59
|
+
createdAt: now(),
|
|
60
|
+
});
|
|
61
|
+
return { url: authorization.url, accounts: await safeListAccounts() };
|
|
62
|
+
},
|
|
63
|
+
async finish(sessionId, callbackInput, label) {
|
|
64
|
+
const pending = takePending(sessionId);
|
|
65
|
+
if (!pending) {
|
|
66
|
+
return {
|
|
67
|
+
text: 'OAuth session expired. Please start again.',
|
|
68
|
+
accounts: await safeListAccounts(),
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
// Stage 1: parse the callback URL/code. Failures here mean the
|
|
72
|
+
// user pasted a malformed callback — exchange has not started.
|
|
73
|
+
let callback;
|
|
74
|
+
try {
|
|
75
|
+
callback = parseOAuthCallbackInput(callbackInput, pending.state);
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
return {
|
|
79
|
+
text: 'OAuth authentication failed: could not parse the callback. Please start a new OAuth flow.',
|
|
80
|
+
accounts: await safeListAccounts(),
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
if ('error' in callback) {
|
|
84
|
+
return {
|
|
85
|
+
text: `OAuth authentication failed: ${callback.error}. Please start a new OAuth flow.`,
|
|
86
|
+
accounts: await safeListAccounts(),
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
// Stage 2: exchange the auth code with Google. Failures here mean
|
|
90
|
+
// the network or token endpoint rejected the code — nothing has
|
|
91
|
+
// been persisted yet.
|
|
92
|
+
let result;
|
|
93
|
+
try {
|
|
94
|
+
result = await options.exchange(callback.code, callback.state);
|
|
95
|
+
}
|
|
96
|
+
catch {
|
|
97
|
+
return {
|
|
98
|
+
text: 'OAuth exchange failed due to a network error. Please start a new OAuth flow.',
|
|
99
|
+
accounts: await safeListAccounts(),
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
if (result.type === 'failed') {
|
|
103
|
+
return {
|
|
104
|
+
text: 'OAuth authentication failed. Please start a new OAuth flow and try again.',
|
|
105
|
+
accounts: await safeListAccounts(),
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
// Stage 3: persist the new account to disk. A failure here means
|
|
109
|
+
// the account is NOT stored — surface the stage so the operator
|
|
110
|
+
// can retry without thinking the previous error already landed it.
|
|
111
|
+
const persisted = {
|
|
112
|
+
...result,
|
|
113
|
+
label: label || result.label,
|
|
114
|
+
};
|
|
115
|
+
try {
|
|
116
|
+
await options.persist(persisted);
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
return {
|
|
120
|
+
text: 'OAuth account could not be saved to disk. Please start a new OAuth flow.',
|
|
121
|
+
accounts: await safeListAccounts(),
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
// Refresh the live AccountManager so routing sees the new account
|
|
125
|
+
// immediately instead of waiting for the next auth reload. Errors
|
|
126
|
+
// here are non-fatal — the on-disk write already landed.
|
|
127
|
+
try {
|
|
128
|
+
await options.onAfterPersist?.(persisted);
|
|
129
|
+
}
|
|
130
|
+
catch {
|
|
131
|
+
// Best-effort refresh; swallow failures.
|
|
132
|
+
}
|
|
133
|
+
// Stage 4: re-list the account pool. If the post-persist read
|
|
134
|
+
// fails for any reason (lock contention, I/O) we still report the
|
|
135
|
+
// successful add — the dialog will refresh on its next open.
|
|
136
|
+
let accounts;
|
|
137
|
+
try {
|
|
138
|
+
accounts = await options.listAccounts();
|
|
139
|
+
}
|
|
140
|
+
catch {
|
|
141
|
+
return {
|
|
142
|
+
text: 'OAuth account added.',
|
|
143
|
+
accounts: [],
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
return {
|
|
147
|
+
text: 'OAuth account added.',
|
|
148
|
+
accounts,
|
|
149
|
+
};
|
|
150
|
+
},
|
|
151
|
+
dispose() {
|
|
152
|
+
pendingBySession.clear();
|
|
153
|
+
},
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
//# sourceMappingURL=account-command-oauth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"account-command-oauth.js","sourceRoot":"","sources":["../../../src/plugin/account-command-oauth.ts"],"names":[],"mappings":"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"}
|
|
@@ -13,6 +13,21 @@ export type CreateAuthFetch = (input: {
|
|
|
13
13
|
accountManager: AccountManager;
|
|
14
14
|
getAuth: GetAuth;
|
|
15
15
|
}) => AuthFetchRuntime;
|
|
16
|
+
/**
|
|
17
|
+
* Loader returned by `createAuthLoader`. The function loads the
|
|
18
|
+
* account pool from disk and installs the runtime.
|
|
19
|
+
*/
|
|
20
|
+
export type LoadAndInstallRuntime = (getAuth: GetAuth, provider: Provider) => Promise<LoaderResult | Record<string, unknown>>;
|
|
21
|
+
/**
|
|
22
|
+
* Reload the live AccountManager + fetch runtime without going through
|
|
23
|
+
* the full startup loader. Used by the OAuth add flow so the new account
|
|
24
|
+
* is visible to routing immediately after `persistAccountPool`.
|
|
25
|
+
*/
|
|
26
|
+
export type ReloadAccountRuntime = (getAuth: GetAuth) => Promise<void>;
|
|
27
|
+
export interface AuthLoaderHandle {
|
|
28
|
+
load: LoadAndInstallRuntime;
|
|
29
|
+
reload: ReloadAccountRuntime;
|
|
30
|
+
}
|
|
16
31
|
interface AuthLoaderDependencies {
|
|
17
32
|
loadAccounts: typeof loadAccounts;
|
|
18
33
|
clearAccounts: typeof clearAccounts;
|
|
@@ -30,6 +45,6 @@ interface CreateAuthLoaderOptions {
|
|
|
30
45
|
onGetAuth?(getAuth: GetAuth): void;
|
|
31
46
|
dependencies?: Partial<AuthLoaderDependencies>;
|
|
32
47
|
}
|
|
33
|
-
export declare function createAuthLoader({ client, providerId, config, lifecycle, createFetch, onGetAuth, dependencies, }: CreateAuthLoaderOptions):
|
|
48
|
+
export declare function createAuthLoader({ client, providerId, config, lifecycle, createFetch, onGetAuth, dependencies, }: CreateAuthLoaderOptions): LoadAndInstallRuntime & AuthLoaderHandle;
|
|
34
49
|
export {};
|
|
35
50
|
//# sourceMappingURL=auth-loader.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth-loader.d.ts","sourceRoot":"","sources":["../../../src/plugin/auth-loader.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"auth-loader.d.ts","sourceRoot":"","sources":["../../../src/plugin/auth-loader.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAM3C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAA;AACjD,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AACxD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAElD,OAAO,EACL,2BAA2B,EAE5B,MAAM,iBAAiB,CAAA;AACxB,OAAO,EAEL,aAAa,EACb,YAAY,EACb,MAAM,WAAW,CAAA;AAClB,OAAO,KAAK,EACV,OAAO,EACP,YAAY,EACZ,YAAY,EACZ,QAAQ,EAET,MAAM,SAAS,CAAA;AAgBhB,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,YAAY,CAAC,OAAO,CAAC,CAAA;IAC5B,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;CAChC;AAED,MAAM,MAAM,eAAe,GAAG,CAAC,KAAK,EAAE;IACpC,cAAc,EAAE,cAAc,CAAA;IAC9B,OAAO,EAAE,OAAO,CAAA;CACjB,KAAK,gBAAgB,CAAA;AAEtB;;;GAGG;AACH,MAAM,MAAM,qBAAqB,GAAG,CAClC,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,QAAQ,KACf,OAAO,CAAC,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;AAEpD;;;;GAIG;AACH,MAAM,MAAM,oBAAoB,GAAG,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;AAEtE,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,qBAAqB,CAAA;IAC3B,MAAM,EAAE,oBAAoB,CAAA;CAC7B;AAED,UAAU,sBAAsB;IAC9B,YAAY,EAAE,OAAO,YAAY,CAAA;IACjC,aAAa,EAAE,OAAO,aAAa,CAAA;IACnC,kBAAkB,CAChB,IAAI,EAAE,UAAU,CAAC,OAAO,cAAc,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,GACtD,OAAO,CAAC,cAAc,CAAC,CAAA;IAC1B,kBAAkB,EAAE,OAAO,2BAA2B,CAAA;IACtD,cAAc,EAAE,OAAO,cAAc,CAAA;IACrC,cAAc,EAAE,OAAO,cAAc,CAAA;CACtC;AAED,UAAU,uBAAuB;IAC/B,MAAM,EAAE,YAAY,CAAA;IACpB,UAAU,EAAE,MAAM,CAAA;IAClB,MAAM,EAAE,iBAAiB,CAAA;IACzB,SAAS,EAAE,eAAe,CAAA;IAC1B,WAAW,EAAE,eAAe,CAAA;IAC5B,SAAS,CAAC,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAA;IAClC,YAAY,CAAC,EAAE,OAAO,CAAC,sBAAsB,CAAC,CAAA;CAC/C;AAED,wBAAgB,gBAAgB,CAAC,EAC/B,MAAM,EACN,UAAU,EACV,MAAM,EACN,SAAS,EACT,WAAW,EACX,SAAS,EACT,YAAY,GACb,EAAE,uBAAuB,GAAG,qBAAqB,GAAG,gBAAgB,CA2OpE"}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { getHealthTracker } from '@cortexkit/antigravity-auth-core';
|
|
3
|
+
import { buildSidebarMachineStateFromAccounts, isAccountCurrent, setSidebarMachineState, toCapturedTier, } from '../sidebar-state';
|
|
2
4
|
import { AccountManager } from './accounts';
|
|
3
5
|
import { isOAuthAuth } from './auth';
|
|
4
6
|
import { buildAuthFromStoredAccount, detectAuthStorageDrift, } from './auth-drift';
|
|
@@ -7,6 +9,17 @@ import { createLogger } from './logger';
|
|
|
7
9
|
import { createProactiveRefreshQueue, } from './refresh-queue';
|
|
8
10
|
import { AccountStorageUnreadableError, clearAccounts, loadAccounts, } from './storage';
|
|
9
11
|
const log = createLogger('auth-loader');
|
|
12
|
+
/**
|
|
13
|
+
* Opaque identity derived from a refresh token. Mirrors the local
|
|
14
|
+
* helper in `account-manager.ts` and `command-data.ts` — the auth-loader
|
|
15
|
+
* stays independent because it ships in the plugin's import graph and
|
|
16
|
+
* can't reach into the core barrel for `quotaAccountIdentity`. The
|
|
17
|
+
* sidebar projection uses this hash to detect a stale quota snapshot
|
|
18
|
+
* captured for a different account after an index shift.
|
|
19
|
+
*/
|
|
20
|
+
function refreshTokenIdentity(refreshToken) {
|
|
21
|
+
return createHash('sha256').update(refreshToken).digest('hex').slice(0, 16);
|
|
22
|
+
}
|
|
10
23
|
export function createAuthLoader({ client, providerId, config, lifecycle, createFetch, onGetAuth, dependencies, }) {
|
|
11
24
|
const deps = {
|
|
12
25
|
loadAccounts: dependencies?.loadAccounts ?? loadAccounts,
|
|
@@ -18,6 +31,13 @@ export function createAuthLoader({ client, providerId, config, lifecycle, create
|
|
|
18
31
|
getLogFilePath: dependencies?.getLogFilePath ?? getLogFilePath,
|
|
19
32
|
};
|
|
20
33
|
let fetchRuntime = null;
|
|
34
|
+
// Reload chain — `installRuntime` swaps the fetch runtime and
|
|
35
|
+
// (previously) discarded the previous runtime's dispose with `void`,
|
|
36
|
+
// so two overlapping reloads could interleave teardown. Serialize
|
|
37
|
+
// reloads through a single shared promise so each new install waits
|
|
38
|
+
// for the previous one to fully settle (including its dispose)
|
|
39
|
+
// before tearing down the runtime it depends on.
|
|
40
|
+
let reloadChain = Promise.resolve();
|
|
21
41
|
lifecycle.register({
|
|
22
42
|
async dispose() {
|
|
23
43
|
const runtime = fetchRuntime;
|
|
@@ -25,7 +45,60 @@ export function createAuthLoader({ client, providerId, config, lifecycle, create
|
|
|
25
45
|
await runtime?.dispose();
|
|
26
46
|
},
|
|
27
47
|
}, 'producer');
|
|
28
|
-
|
|
48
|
+
// Reload hook: invoked after out-of-band storage mutations (e.g.
|
|
49
|
+
// OAuth add) so the live AccountManager + fetch interceptor see the
|
|
50
|
+
// newly-persisted account without waiting for a plugin restart. The
|
|
51
|
+
// handle returned below wires this through to the OAuth finish flow.
|
|
52
|
+
let reloadRuntime = async () => { };
|
|
53
|
+
const installRuntime = async (accountManager, getAuth) => {
|
|
54
|
+
if (accountManager.getAccountCount() > 0) {
|
|
55
|
+
accountManager.requestSaveToDisk();
|
|
56
|
+
}
|
|
57
|
+
let refreshQueue = null;
|
|
58
|
+
if (config.proactive_token_refresh &&
|
|
59
|
+
accountManager.getAccountCount() > 0) {
|
|
60
|
+
refreshQueue = deps.createRefreshQueue(client, providerId, {
|
|
61
|
+
enabled: config.proactive_token_refresh,
|
|
62
|
+
bufferSeconds: config.proactive_refresh_buffer_seconds,
|
|
63
|
+
checkIntervalSeconds: config.proactive_refresh_check_interval_seconds,
|
|
64
|
+
});
|
|
65
|
+
refreshQueue.setAccountManager(accountManager);
|
|
66
|
+
}
|
|
67
|
+
await lifecycle.replaceAccountRuntime(accountManager, refreshQueue);
|
|
68
|
+
refreshQueue?.start();
|
|
69
|
+
// Swap the fetch runtime FIRST so the host's captured fetch
|
|
70
|
+
// reference (a call-time delegating wrapper below) immediately
|
|
71
|
+
// routes through the new interceptor, then await the previous
|
|
72
|
+
// runtime's dispose. The swap-then-dispose order guarantees there
|
|
73
|
+
// is no fetch gap between the old and new runtimes.
|
|
74
|
+
const previousRuntime = fetchRuntime;
|
|
75
|
+
fetchRuntime = createFetch({ accountManager, getAuth });
|
|
76
|
+
await previousRuntime?.dispose();
|
|
77
|
+
// Push the freshly materialized account pool into the sidebar so the
|
|
78
|
+
// TUI's next poll renders the labels / health / cooldown it needs
|
|
79
|
+
// without waiting for the first fetch to complete.
|
|
80
|
+
await setSidebarMachineState(buildSidebarMachineStateFromAccounts(accountManager.getAccounts().map((entry) => {
|
|
81
|
+
const activeByFamily = accountManager.getActiveIndexByFamily();
|
|
82
|
+
return {
|
|
83
|
+
index: entry.index,
|
|
84
|
+
label: entry.label,
|
|
85
|
+
enabled: entry.enabled,
|
|
86
|
+
current: isAccountCurrent(entry.index, activeByFamily),
|
|
87
|
+
coolingDownUntil: entry.coolingDownUntil,
|
|
88
|
+
healthScore: getHealthTracker().getScore(entry.index),
|
|
89
|
+
cachedQuota: entry.cachedQuota,
|
|
90
|
+
// Stamp the sidebar snapshot so the projection can detect a
|
|
91
|
+
// stale cache that landed on the wrong account (the manager's
|
|
92
|
+
// `cachedQuotaAccountId` is keyed to whatever account actually
|
|
93
|
+
// produced the snapshot — the live refresh-token hash is the
|
|
94
|
+
// expected identity at this slot).
|
|
95
|
+
cachedQuotaAccountId: entry.cachedQuotaAccountId,
|
|
96
|
+
currentQuotaAccountId: refreshTokenIdentity(entry.parts.refreshToken),
|
|
97
|
+
tier: toCapturedTier(entry),
|
|
98
|
+
};
|
|
99
|
+
})));
|
|
100
|
+
};
|
|
101
|
+
async function runLoader(getAuth, provider) {
|
|
29
102
|
onGetAuth?.(getAuth);
|
|
30
103
|
let auth = await getAuth();
|
|
31
104
|
if (!isOAuthAuth(auth)) {
|
|
@@ -89,35 +162,7 @@ export function createAuthLoader({ client, providerId, config, lifecycle, create
|
|
|
89
162
|
return {};
|
|
90
163
|
}
|
|
91
164
|
const accountManager = await deps.loadAccountManager(auth);
|
|
92
|
-
|
|
93
|
-
accountManager.requestSaveToDisk();
|
|
94
|
-
}
|
|
95
|
-
let refreshQueue = null;
|
|
96
|
-
if (config.proactive_token_refresh &&
|
|
97
|
-
accountManager.getAccountCount() > 0) {
|
|
98
|
-
refreshQueue = deps.createRefreshQueue(client, providerId, {
|
|
99
|
-
enabled: config.proactive_token_refresh,
|
|
100
|
-
bufferSeconds: config.proactive_refresh_buffer_seconds,
|
|
101
|
-
checkIntervalSeconds: config.proactive_refresh_check_interval_seconds,
|
|
102
|
-
});
|
|
103
|
-
refreshQueue.setAccountManager(accountManager);
|
|
104
|
-
}
|
|
105
|
-
await lifecycle.replaceAccountRuntime(accountManager, refreshQueue);
|
|
106
|
-
refreshQueue?.start();
|
|
107
|
-
const previousRuntime = fetchRuntime;
|
|
108
|
-
fetchRuntime = createFetch({ accountManager, getAuth });
|
|
109
|
-
await previousRuntime?.dispose();
|
|
110
|
-
// Push the freshly materialized account pool into the sidebar so the
|
|
111
|
-
// TUI's next poll renders the labels / health / cooldown it needs
|
|
112
|
-
// without waiting for the first fetch to complete.
|
|
113
|
-
await setSidebarMachineState(buildSidebarMachineStateFromAccounts(accountManager.getAccounts().map((entry) => ({
|
|
114
|
-
index: entry.index,
|
|
115
|
-
label: entry.label,
|
|
116
|
-
enabled: entry.enabled,
|
|
117
|
-
current: false,
|
|
118
|
-
coolingDownUntil: entry.coolingDownUntil,
|
|
119
|
-
cachedQuota: entry.cachedQuota,
|
|
120
|
-
}))));
|
|
165
|
+
await installRuntime(accountManager, getAuth);
|
|
121
166
|
if (deps.isDebugEnabled()) {
|
|
122
167
|
const logPath = deps.getLogFilePath();
|
|
123
168
|
if (logPath) {
|
|
@@ -137,8 +182,44 @@ export function createAuthLoader({ client, providerId, config, lifecycle, create
|
|
|
137
182
|
}
|
|
138
183
|
return {
|
|
139
184
|
apiKey: '',
|
|
140
|
-
|
|
185
|
+
// Return a stable delegating wrapper that reads `fetchRuntime`
|
|
186
|
+
// at CALL time. A direct `fetchRuntime!.fetch` reference would
|
|
187
|
+
// capture the current runtime; the host keeps that reference
|
|
188
|
+
// across `reload()` calls, so a captured fetch would still route
|
|
189
|
+
// through the OLD interceptor after an OAuth add. The wrapper
|
|
190
|
+
// matches the host's `LoaderResult.fetch` signature exactly
|
|
191
|
+
// (no `this` binding) so behavior is preserved.
|
|
192
|
+
fetch: (input, init) => fetchRuntime.fetch(input, init),
|
|
141
193
|
};
|
|
194
|
+
}
|
|
195
|
+
reloadRuntime = async (getAuth) => {
|
|
196
|
+
const auth = await getAuth();
|
|
197
|
+
if (!isOAuthAuth(auth))
|
|
198
|
+
return;
|
|
199
|
+
const nextManager = await deps.loadAccountManager(auth);
|
|
200
|
+
await installRuntime(nextManager, getAuth);
|
|
142
201
|
};
|
|
202
|
+
// Return a callable object: `plugin.auth.loader` is invoked with
|
|
203
|
+
// `(getAuth, provider)` (host contract), and `authLoader.reload(...)`
|
|
204
|
+
// rebuilds the runtime after out-of-band storage mutations (OAuth add).
|
|
205
|
+
// The callable closes over `runLoader` directly so the `this`-context
|
|
206
|
+
// binding stays unbound.
|
|
207
|
+
async function authLoaderCallable(getAuth, provider) {
|
|
208
|
+
return runLoader(getAuth, provider);
|
|
209
|
+
}
|
|
210
|
+
async function reload(getAuth) {
|
|
211
|
+
const next = reloadChain.then(() => reloadRuntime(getAuth));
|
|
212
|
+
reloadChain = next.catch(() => { });
|
|
213
|
+
return next;
|
|
214
|
+
}
|
|
215
|
+
// `load` mirrors the authLoaderCallable so the public handle
|
|
216
|
+
// (`AuthLoaderHandle.load`) exposes the same entry point the host
|
|
217
|
+
// invokes. Without this assignment, contract consumers read
|
|
218
|
+
// `.load` as undefined and the documented type would lie.
|
|
219
|
+
const authLoader = Object.assign(authLoaderCallable, {
|
|
220
|
+
reload,
|
|
221
|
+
load: authLoaderCallable,
|
|
222
|
+
});
|
|
223
|
+
return authLoader;
|
|
143
224
|
}
|
|
144
225
|
//# sourceMappingURL=auth-loader.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth-loader.js","sourceRoot":"","sources":["../../../src/plugin/auth-loader.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,oCAAoC,EACpC,sBAAsB,
|
|
1
|
+
{"version":3,"file":"auth-loader.js","sourceRoot":"","sources":["../../../src/plugin/auth-loader.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Background quota poller.
|
|
3
|
+
*
|
|
4
|
+
* Runs a jittered, `unref()`'d timer that periodically refreshes quota for
|
|
5
|
+
* all accounts and pushes ONE sidebar snapshot per tick. Three-layer
|
|
6
|
+
* cross-process dedup:
|
|
7
|
+
*
|
|
8
|
+
* 1. Freshness gate — the only hard correctness bound for quota snapshots.
|
|
9
|
+
* Reads `checkedAt` from the on-disk sidebar state; skips quota work when
|
|
10
|
+
* it is fresher than
|
|
11
|
+
* `max(intervalMs − 60_000, floor(intervalMs / 2))`. The /2 floor
|
|
12
|
+
* ensures the gate still fires at the 1-minute minimum interval.
|
|
13
|
+
*
|
|
14
|
+
* 2. Advisory fenced lock — an optimization that lets a single process do
|
|
15
|
+
* the network work when several wake up simultaneously. Held → skip.
|
|
16
|
+
*
|
|
17
|
+
* 3. Lock throws → FAIL CLOSED (skip this tick, add jitter to next). A
|
|
18
|
+
* fallback mutex is NOT used here. The correct reasoning is: the
|
|
19
|
+
* freshness gate (layer 1) already bounds how many refreshes can land;
|
|
20
|
+
* a secondary "claim marker" file is just a worse re-implementation of
|
|
21
|
+
* the fenced lock we just failed to acquire — it replicates the same
|
|
22
|
+
* ownership problem without the protocol guarantees, and any transient
|
|
23
|
+
* I/O error that made the lock throw will likely affect a claim file
|
|
24
|
+
* too. The previous poller attempt fell into this trap across three
|
|
25
|
+
* review rounds; this comment exists so a future reviewer stops
|
|
26
|
+
* re-litigating it.
|
|
27
|
+
*/
|
|
28
|
+
import type { AccountMetadataV3, QuotaGroup, QuotaGroupSummary } from '@cortexkit/antigravity-auth-core';
|
|
29
|
+
import { acquireFencedFileLock } from '@cortexkit/antigravity-auth-core/file-lock';
|
|
30
|
+
import type { QuotaManager } from './quota';
|
|
31
|
+
/**
|
|
32
|
+
* The subset of AccountManager that the poller needs. Using a narrow
|
|
33
|
+
* interface keeps the module decoupled from the large concrete class and
|
|
34
|
+
* lets tests pass minimal stubs without satisfying 90+ methods.
|
|
35
|
+
*/
|
|
36
|
+
export interface PollerAccountView {
|
|
37
|
+
getAccounts(): Array<{
|
|
38
|
+
index: number;
|
|
39
|
+
label?: string;
|
|
40
|
+
enabled?: boolean;
|
|
41
|
+
parts: {
|
|
42
|
+
refreshToken: string;
|
|
43
|
+
};
|
|
44
|
+
cachedQuota?: Partial<Record<QuotaGroup, QuotaGroupSummary>>;
|
|
45
|
+
cachedQuotaAccountId?: string;
|
|
46
|
+
coolingDownUntil?: number;
|
|
47
|
+
/** Captured plan tier ID (raw upstream string). */
|
|
48
|
+
capturedTierId?: string;
|
|
49
|
+
/** Captured paid-tier ID (raw upstream string). */
|
|
50
|
+
capturedPaidTierId?: string;
|
|
51
|
+
/** Epoch ms when capturedTierId was last recorded. */
|
|
52
|
+
capturedTierAt?: number;
|
|
53
|
+
/** Schema version of the most recent tier capture. */
|
|
54
|
+
capturedTierSchemaVersion?: number;
|
|
55
|
+
}>;
|
|
56
|
+
/** Must return the full AccountMetadataV3 shape so the quota manager
|
|
57
|
+
* can use token-refresh and project-context fields inside each fetch. */
|
|
58
|
+
getAccountsForQuotaCheck(): AccountMetadataV3[];
|
|
59
|
+
updateQuotaCache(accountIndex: number, quotaGroups: Partial<Record<QuotaGroup, QuotaGroupSummary>>, expectedRefreshToken?: string): void;
|
|
60
|
+
/**
|
|
61
|
+
* Apply a subset of quota-result fields (e.g. captured tier) onto the
|
|
62
|
+
* in-memory account record without touching the quota cache itself.
|
|
63
|
+
*/
|
|
64
|
+
applyUpdatedAccount(accountIndex: number, patch: {
|
|
65
|
+
capturedTierId?: string;
|
|
66
|
+
capturedPaidTierId?: string;
|
|
67
|
+
capturedTierAt?: number;
|
|
68
|
+
capturedTierSchemaVersion?: number;
|
|
69
|
+
}, expectedRefreshToken?: string): void;
|
|
70
|
+
requestSaveToDisk(): void;
|
|
71
|
+
/**
|
|
72
|
+
* Returns the active account index per model family so the sidebar
|
|
73
|
+
* snapshot can stamp the `current` flag on the right account.
|
|
74
|
+
*/
|
|
75
|
+
getActiveIndexByFamily(): {
|
|
76
|
+
claude: number;
|
|
77
|
+
gemini: number;
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
export interface BackgroundQuotaRefreshOptions {
|
|
81
|
+
intervalMs: number;
|
|
82
|
+
sidebarStateFile: string;
|
|
83
|
+
/**
|
|
84
|
+
* Supplier for the live account pool. Called inside each locked phase, so it
|
|
85
|
+
* observes any concurrent add/remove that completed while waiting for the
|
|
86
|
+
* lock.
|
|
87
|
+
*/
|
|
88
|
+
getAccountManager: () => PollerAccountView | null;
|
|
89
|
+
quotaManager: QuotaManager;
|
|
90
|
+
/**
|
|
91
|
+
* Optional tier-refresh callback. When provided, the poller calls this
|
|
92
|
+
* once per tick for the account whose capturedTierAt is missing or older
|
|
93
|
+
* than TIER_STALENESS_TTL_MS. The callback handles its own token-refresh
|
|
94
|
+
* and must resolve to a tier object (or null on failure / nothing to
|
|
95
|
+
* report) -- failure must never reject, since tier is best-effort.
|
|
96
|
+
*
|
|
97
|
+
* Wired in index.ts through the same agyTransport seam the quota manager
|
|
98
|
+
* uses, so e2e tests can inject a mock alongside the mock quota fetch.
|
|
99
|
+
*/
|
|
100
|
+
loadAccountTier?: (account: AccountMetadataV3) => Promise<{
|
|
101
|
+
id: string;
|
|
102
|
+
paidId?: string;
|
|
103
|
+
capturedAt: number;
|
|
104
|
+
} | null>;
|
|
105
|
+
/**
|
|
106
|
+
* Clock / randomness seam. Defaults to the system clock.
|
|
107
|
+
*/
|
|
108
|
+
now?: () => number;
|
|
109
|
+
random?: () => number;
|
|
110
|
+
/** Lock acquisition seam used by deterministic concurrency tests. */
|
|
111
|
+
acquireLock?: typeof acquireFencedFileLock;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Per-loader-instance background quota poller.
|
|
115
|
+
*
|
|
116
|
+
* Must be created after the plugin has initialised (so `getAccountManager()`
|
|
117
|
+
* is populated) and disposed via the producer lifecycle phase.
|
|
118
|
+
*/
|
|
119
|
+
export declare class BackgroundQuotaRefresh {
|
|
120
|
+
private readonly intervalMs;
|
|
121
|
+
private readonly sidebarStateFile;
|
|
122
|
+
private readonly getAccountManager;
|
|
123
|
+
private readonly quotaManager;
|
|
124
|
+
private readonly loadAccountTier?;
|
|
125
|
+
private readonly now;
|
|
126
|
+
private readonly random;
|
|
127
|
+
private readonly acquireLock;
|
|
128
|
+
private timer;
|
|
129
|
+
/** Resolves when the currently-running tick completes (or immediately if none). */
|
|
130
|
+
private inFlight;
|
|
131
|
+
private disposed;
|
|
132
|
+
constructor(options: BackgroundQuotaRefreshOptions);
|
|
133
|
+
/** Start the background timer. Idempotent: a second call is a no-op. */
|
|
134
|
+
start(): void;
|
|
135
|
+
/** Stop the timer and await any in-flight tick. */
|
|
136
|
+
dispose(): Promise<void>;
|
|
137
|
+
private jitteredStartDelay;
|
|
138
|
+
private jitteredInterval;
|
|
139
|
+
private scheduleNext;
|
|
140
|
+
private runTick;
|
|
141
|
+
private refresh;
|
|
142
|
+
private refreshQuota;
|
|
143
|
+
private refreshTierSlot;
|
|
144
|
+
private pushSnapshot;
|
|
145
|
+
}
|
|
146
|
+
//# sourceMappingURL=background-quota-refresh.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"background-quota-refresh.d.ts","sourceRoot":"","sources":["../../../src/plugin/background-quota-refresh.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAGH,OAAO,KAAK,EACV,iBAAiB,EACjB,UAAU,EACV,iBAAiB,EAClB,MAAM,kCAAkC,CAAA;AACzC,OAAO,EACL,qBAAqB,EAEtB,MAAM,4CAA4C,CAAA;AAGnD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAG3C;;;;GAIG;AACH,MAAM,WAAW,iBAAiB;IAChC,WAAW,IAAI,KAAK,CAAC;QACnB,KAAK,EAAE,MAAM,CAAA;QACb,KAAK,CAAC,EAAE,MAAM,CAAA;QACd,OAAO,CAAC,EAAE,OAAO,CAAA;QACjB,KAAK,EAAE;YAAE,YAAY,EAAE,MAAM,CAAA;SAAE,CAAA;QAC/B,WAAW,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,UAAU,EAAE,iBAAiB,CAAC,CAAC,CAAA;QAC5D,oBAAoB,CAAC,EAAE,MAAM,CAAA;QAC7B,gBAAgB,CAAC,EAAE,MAAM,CAAA;QACzB,mDAAmD;QACnD,cAAc,CAAC,EAAE,MAAM,CAAA;QACvB,mDAAmD;QACnD,kBAAkB,CAAC,EAAE,MAAM,CAAA;QAC3B,sDAAsD;QACtD,cAAc,CAAC,EAAE,MAAM,CAAA;QACvB,sDAAsD;QACtD,yBAAyB,CAAC,EAAE,MAAM,CAAA;KACnC,CAAC,CAAA;IACF;8EAC0E;IAC1E,wBAAwB,IAAI,iBAAiB,EAAE,CAAA;IAC/C,gBAAgB,CACd,YAAY,EAAE,MAAM,EACpB,WAAW,EAAE,OAAO,CAAC,MAAM,CAAC,UAAU,EAAE,iBAAiB,CAAC,CAAC,EAC3D,oBAAoB,CAAC,EAAE,MAAM,GAC5B,IAAI,CAAA;IACP;;;OAGG;IACH,mBAAmB,CACjB,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE;QACL,cAAc,CAAC,EAAE,MAAM,CAAA;QACvB,kBAAkB,CAAC,EAAE,MAAM,CAAA;QAC3B,cAAc,CAAC,EAAE,MAAM,CAAA;QACvB,yBAAyB,CAAC,EAAE,MAAM,CAAA;KACnC,EACD,oBAAoB,CAAC,EAAE,MAAM,GAC5B,IAAI,CAAA;IACP,iBAAiB,IAAI,IAAI,CAAA;IACzB;;;OAGG;IACH,sBAAsB,IAAI;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAA;CAC7D;AA8BD,MAAM,WAAW,6BAA6B;IAC5C,UAAU,EAAE,MAAM,CAAA;IAClB,gBAAgB,EAAE,MAAM,CAAA;IACxB;;;;OAIG;IACH,iBAAiB,EAAE,MAAM,iBAAiB,GAAG,IAAI,CAAA;IACjD,YAAY,EAAE,YAAY,CAAA;IAC1B;;;;;;;;;OASG;IACH,eAAe,CAAC,EAAE,CAChB,OAAO,EAAE,iBAAiB,KACvB,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC,CAAA;IACxE;;OAEG;IACH,GAAG,CAAC,EAAE,MAAM,MAAM,CAAA;IAClB,MAAM,CAAC,EAAE,MAAM,MAAM,CAAA;IACrB,qEAAqE;IACrE,WAAW,CAAC,EAAE,OAAO,qBAAqB,CAAA;CAC3C;AAED;;;;;GAKG;AACH,qBAAa,sBAAsB;IACjC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAQ;IACnC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAQ;IACzC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAgC;IAClE,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAc;IAC3C,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAC,CAEuC;IACxE,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAc;IAClC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAc;IACrC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA8B;IAE1D,OAAO,CAAC,KAAK,CAA6C;IAC1D,mFAAmF;IACnF,OAAO,CAAC,QAAQ,CAA6B;IAC7C,OAAO,CAAC,QAAQ,CAAQ;gBAEZ,OAAO,EAAE,6BAA6B;IAWlD,wEAAwE;IACxE,KAAK,IAAI,IAAI;IAKb,mDAAmD;IAC7C,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAY9B,OAAO,CAAC,kBAAkB;IAI1B,OAAO,CAAC,gBAAgB;IAMxB,OAAO,CAAC,YAAY;YA2BN,OAAO;YAqDP,OAAO;YAMP,YAAY;YAyEZ,eAAe;YA6Df,YAAY;CAoC3B"}
|