egaki 0.0.1 → 0.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/CHANGELOG.md +54 -0
- package/README.md +239 -0
- package/dist/antigravity-auth.d.ts +15 -0
- package/dist/antigravity-auth.d.ts.map +1 -0
- package/dist/antigravity-auth.js +544 -0
- package/dist/antigravity-image.d.ts +11 -0
- package/dist/antigravity-image.d.ts.map +1 -0
- package/dist/antigravity-image.js +285 -0
- package/dist/chatgpt-auth.js +294 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +666 -0
- package/dist/credentials.d.ts +18 -0
- package/dist/credentials.d.ts.map +1 -0
- package/dist/credentials.js +107 -0
- package/dist/gateway-model-candidates.generated.d.ts +11 -0
- package/dist/gateway-model-candidates.generated.d.ts.map +1 -0
- package/dist/gateway-model-candidates.generated.js +64 -0
- package/dist/login.d.ts +9 -0
- package/dist/login.d.ts.map +1 -0
- package/dist/login.js +112 -0
- package/dist/model-catalog.d.ts +42 -0
- package/dist/model-catalog.d.ts.map +1 -0
- package/dist/model-catalog.js +898 -0
- package/dist/models.d.ts +15 -0
- package/dist/models.d.ts.map +1 -0
- package/dist/models.js +196 -0
- package/dist/open-browser.d.ts +2 -0
- package/dist/open-browser.d.ts.map +1 -0
- package/dist/open-browser.js +37 -0
- package/dist/subscription.d.ts +5 -0
- package/dist/subscription.d.ts.map +1 -0
- package/dist/subscription.js +216 -0
- package/dist/video-model-catalog.d.ts +52 -0
- package/dist/video-model-catalog.d.ts.map +1 -0
- package/dist/video-model-catalog.js +245 -0
- package/package.json +68 -5
- package/src/cli.ts +998 -0
- package/src/credentials.ts +126 -0
- package/src/login.ts +163 -0
- package/src/model-catalog.ts +968 -0
- package/src/models.ts +258 -0
- package/src/open-browser.ts +48 -0
- package/src/subscription.ts +298 -0
- package/src/video-model-catalog.ts +302 -0
- package/index.js +0 -1
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
// Credential storage for egaki.
|
|
2
|
+
// Reads and writes API keys from ~/.config/egaki/credentials.json.
|
|
3
|
+
// Keys are stored per-provider and injected as env vars at runtime.
|
|
4
|
+
import fs from 'node:fs';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
import os from 'node:os';
|
|
7
|
+
// Maps provider names to their expected env var names.
|
|
8
|
+
// When a key is stored, we set the corresponding env var before
|
|
9
|
+
// calling the AI SDK so the provider picks it up automatically.
|
|
10
|
+
export const PROVIDERS = {
|
|
11
|
+
egaki: {
|
|
12
|
+
envVar: 'EGAKI_API_KEY',
|
|
13
|
+
label: 'Egaki (all models, one subscription)',
|
|
14
|
+
hint: 'Subscribe at https://egaki.org/buy or run: egaki subscribe',
|
|
15
|
+
},
|
|
16
|
+
google: {
|
|
17
|
+
envVar: 'GOOGLE_GENERATIVE_AI_API_KEY',
|
|
18
|
+
label: 'Google AI (Gemini, Imagen)',
|
|
19
|
+
hint: 'Get your key at https://aistudio.google.com/apikey',
|
|
20
|
+
},
|
|
21
|
+
openai: {
|
|
22
|
+
envVar: 'OPENAI_API_KEY',
|
|
23
|
+
label: 'OpenAI (DALL-E)',
|
|
24
|
+
hint: 'Get your key at https://platform.openai.com/api-keys',
|
|
25
|
+
},
|
|
26
|
+
replicate: {
|
|
27
|
+
envVar: 'REPLICATE_API_TOKEN',
|
|
28
|
+
label: 'Replicate (Flux, SDXL)',
|
|
29
|
+
hint: 'Get your token at https://replicate.com/account/api-tokens',
|
|
30
|
+
},
|
|
31
|
+
fal: {
|
|
32
|
+
envVar: 'FAL_KEY',
|
|
33
|
+
label: 'fal.ai (Flux, SDXL, Recraft)',
|
|
34
|
+
hint: 'Get your key at https://fal.ai/dashboard/keys',
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
export const EGAKI_GATEWAY_URL = 'https://egaki.org/v3/ai';
|
|
38
|
+
function getConfigDir() {
|
|
39
|
+
// XDG_CONFIG_HOME or ~/.config/egaki
|
|
40
|
+
const xdg = process.env['XDG_CONFIG_HOME'];
|
|
41
|
+
const base = xdg || path.join(os.homedir(), '.config');
|
|
42
|
+
return path.join(base, 'egaki');
|
|
43
|
+
}
|
|
44
|
+
function getCredentialsPath() {
|
|
45
|
+
return path.join(getConfigDir(), 'credentials.json');
|
|
46
|
+
}
|
|
47
|
+
export function readCredentials() {
|
|
48
|
+
const filePath = getCredentialsPath();
|
|
49
|
+
if (!fs.existsSync(filePath)) {
|
|
50
|
+
return {};
|
|
51
|
+
}
|
|
52
|
+
const raw = fs.readFileSync(filePath, 'utf-8');
|
|
53
|
+
return JSON.parse(raw);
|
|
54
|
+
}
|
|
55
|
+
export function writeCredentials(creds) {
|
|
56
|
+
const dir = getConfigDir();
|
|
57
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
58
|
+
const filePath = getCredentialsPath();
|
|
59
|
+
fs.writeFileSync(filePath, JSON.stringify(creds, null, 2) + '\n', {
|
|
60
|
+
mode: 0o600,
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
export function saveProviderKey(provider, key) {
|
|
64
|
+
const creds = readCredentials();
|
|
65
|
+
creds[provider] = key;
|
|
66
|
+
writeCredentials(creds);
|
|
67
|
+
}
|
|
68
|
+
export function removeProviderKey(provider) {
|
|
69
|
+
const creds = readCredentials();
|
|
70
|
+
delete creds[provider];
|
|
71
|
+
writeCredentials(creds);
|
|
72
|
+
}
|
|
73
|
+
export function getProviderKey(provider) {
|
|
74
|
+
const creds = readCredentials();
|
|
75
|
+
return creds[provider];
|
|
76
|
+
}
|
|
77
|
+
// Inject all stored credentials as env vars so the AI SDK
|
|
78
|
+
// providers pick them up automatically. Env vars already set
|
|
79
|
+
// by the user take precedence (we don't overwrite them).
|
|
80
|
+
export function injectCredentialsToEnv() {
|
|
81
|
+
const creds = readCredentials();
|
|
82
|
+
for (const [provider, key] of Object.entries(creds)) {
|
|
83
|
+
const info = PROVIDERS[provider];
|
|
84
|
+
if (!info) {
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
if (!process.env[info.envVar]) {
|
|
88
|
+
process.env[info.envVar] = key;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
// Check if a provider has a key available (from env or stored credentials).
|
|
93
|
+
// Returns the source of the key for display purposes.
|
|
94
|
+
export function getKeyStatus(provider) {
|
|
95
|
+
const info = PROVIDERS[provider];
|
|
96
|
+
if (!info) {
|
|
97
|
+
return { available: false, source: 'none' };
|
|
98
|
+
}
|
|
99
|
+
if (process.env[info.envVar]) {
|
|
100
|
+
return { available: true, source: 'env' };
|
|
101
|
+
}
|
|
102
|
+
const stored = getProviderKey(provider);
|
|
103
|
+
if (stored) {
|
|
104
|
+
return { available: true, source: 'stored' };
|
|
105
|
+
}
|
|
106
|
+
return { available: false, source: 'none' };
|
|
107
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export type GatewayModelCandidate = {
|
|
2
|
+
fullId: string;
|
|
3
|
+
provider: string;
|
|
4
|
+
modelId: string;
|
|
5
|
+
type: string;
|
|
6
|
+
tags: string[];
|
|
7
|
+
reason: 'type-image' | 'tag-image-generation';
|
|
8
|
+
};
|
|
9
|
+
export declare const GATEWAY_MODEL_CANDIDATES: GatewayModelCandidate[];
|
|
10
|
+
export declare const GATEWAY_MODEL_CANDIDATE_PROVIDERS: string[];
|
|
11
|
+
//# sourceMappingURL=gateway-model-candidates.generated.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gateway-model-candidates.generated.d.ts","sourceRoot":"","sources":["../src/gateway-model-candidates.generated.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,qBAAqB,GAAG;IAClC,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,CAAA;IAChB,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,EAAE,CAAA;IACd,MAAM,EAAE,YAAY,GAAG,sBAAsB,CAAA;CAC9C,CAAA;AAED,eAAO,MAAM,wBAAwB,EAAE,qBAAqB,EAwD3D,CAAA;AAED,eAAO,MAAM,iCAAiC,UAG7C,CAAA"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
// Generated by scripts/generate-gateway-model-candidates.ts
|
|
2
|
+
// Snapshot date: 2026-03-11T21:30:42.406Z
|
|
3
|
+
// Purpose: candidates available in Vercel AI Gateway but missing in src/model-catalog.ts
|
|
4
|
+
export const GATEWAY_MODEL_CANDIDATES = [
|
|
5
|
+
{
|
|
6
|
+
"fullId": "google/gemini-3-pro-image",
|
|
7
|
+
"provider": "google",
|
|
8
|
+
"modelId": "gemini-3-pro-image",
|
|
9
|
+
"type": "language",
|
|
10
|
+
"tags": [
|
|
11
|
+
"image-generation"
|
|
12
|
+
],
|
|
13
|
+
"reason": "tag-image-generation"
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
"fullId": "openai/gpt-5",
|
|
17
|
+
"provider": "openai",
|
|
18
|
+
"modelId": "gpt-5",
|
|
19
|
+
"type": "language",
|
|
20
|
+
"tags": [
|
|
21
|
+
"file-input",
|
|
22
|
+
"reasoning",
|
|
23
|
+
"tool-use",
|
|
24
|
+
"vision",
|
|
25
|
+
"image-generation",
|
|
26
|
+
"implicit-caching"
|
|
27
|
+
],
|
|
28
|
+
"reason": "tag-image-generation"
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"fullId": "openai/gpt-5-nano",
|
|
32
|
+
"provider": "openai",
|
|
33
|
+
"modelId": "gpt-5-nano",
|
|
34
|
+
"type": "language",
|
|
35
|
+
"tags": [
|
|
36
|
+
"file-input",
|
|
37
|
+
"reasoning",
|
|
38
|
+
"tool-use",
|
|
39
|
+
"vision",
|
|
40
|
+
"image-generation",
|
|
41
|
+
"implicit-caching"
|
|
42
|
+
],
|
|
43
|
+
"reason": "tag-image-generation"
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
"fullId": "openai/gpt-5-pro",
|
|
47
|
+
"provider": "openai",
|
|
48
|
+
"modelId": "gpt-5-pro",
|
|
49
|
+
"type": "language",
|
|
50
|
+
"tags": [
|
|
51
|
+
"file-input",
|
|
52
|
+
"implicit-caching",
|
|
53
|
+
"reasoning",
|
|
54
|
+
"tool-use",
|
|
55
|
+
"vision",
|
|
56
|
+
"image-generation"
|
|
57
|
+
],
|
|
58
|
+
"reason": "tag-image-generation"
|
|
59
|
+
}
|
|
60
|
+
];
|
|
61
|
+
export const GATEWAY_MODEL_CANDIDATE_PROVIDERS = [
|
|
62
|
+
"google",
|
|
63
|
+
"openai"
|
|
64
|
+
];
|
package/dist/login.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare function loginInteractive(): Promise<void>;
|
|
2
|
+
export declare function loginNonInteractive({ provider, key, }: {
|
|
3
|
+
provider: string;
|
|
4
|
+
key: string;
|
|
5
|
+
}): void;
|
|
6
|
+
export declare function showLoginStatus(): void;
|
|
7
|
+
export declare function removeLogin(provider: string): void;
|
|
8
|
+
export declare function readKeyFromStdin(): Promise<string>;
|
|
9
|
+
//# sourceMappingURL=login.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../src/login.ts"],"names":[],"mappings":"AAsBA,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC,CAqEtD;AAED,wBAAgB,mBAAmB,CAAC,EAClC,QAAQ,EACR,GAAG,GACJ,EAAE;IACD,QAAQ,EAAE,MAAM,CAAA;IAChB,GAAG,EAAE,MAAM,CAAA;CACZ,GAAG,IAAI,CAiBP;AAED,wBAAgB,eAAe,IAAI,IAAI,CAqBtC;AAED,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAYlD;AAGD,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,MAAM,CAAC,CAMxD"}
|
package/dist/login.js
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
// Login command — interactive and non-interactive API key management.
|
|
2
|
+
// Interactive mode uses clack prompts for provider selection and key input.
|
|
3
|
+
// Non-interactive mode supports --provider + --key flags and stdin piping.
|
|
4
|
+
import { intro, outro, select, password, isCancel, cancel, log, note, } from '@clack/prompts';
|
|
5
|
+
import pc from 'picocolors';
|
|
6
|
+
import { PROVIDERS, saveProviderKey, removeProviderKey, getKeyStatus, readCredentials, } from './credentials.js';
|
|
7
|
+
export async function loginInteractive() {
|
|
8
|
+
intro(pc.bold('egaki login'));
|
|
9
|
+
const providerOptions = Object.entries(PROVIDERS).map(([key, info]) => {
|
|
10
|
+
const status = getKeyStatus(key);
|
|
11
|
+
const statusLabel = (() => {
|
|
12
|
+
if (status.source === 'env') {
|
|
13
|
+
return pc.green('(set via env)');
|
|
14
|
+
}
|
|
15
|
+
if (status.source === 'stored') {
|
|
16
|
+
return pc.green('(saved)');
|
|
17
|
+
}
|
|
18
|
+
return pc.dim('(not configured)');
|
|
19
|
+
})();
|
|
20
|
+
// Highlight the egaki option as recommended
|
|
21
|
+
const label = key === 'egaki'
|
|
22
|
+
? `${pc.bold(info.label)} ${pc.cyan('← recommended')} ${statusLabel}`
|
|
23
|
+
: `${info.label} ${statusLabel}`;
|
|
24
|
+
return {
|
|
25
|
+
value: key,
|
|
26
|
+
label,
|
|
27
|
+
hint: info.hint,
|
|
28
|
+
};
|
|
29
|
+
});
|
|
30
|
+
const provider = await select({
|
|
31
|
+
message: 'Select a provider to configure',
|
|
32
|
+
options: providerOptions,
|
|
33
|
+
});
|
|
34
|
+
if (isCancel(provider)) {
|
|
35
|
+
cancel('Login cancelled.');
|
|
36
|
+
process.exit(0);
|
|
37
|
+
}
|
|
38
|
+
const info = PROVIDERS[provider];
|
|
39
|
+
if (!info) {
|
|
40
|
+
log.error(`Unknown provider: ${provider}`);
|
|
41
|
+
process.exit(1);
|
|
42
|
+
}
|
|
43
|
+
log.info(`${pc.dim('Env var:')} ${info.envVar} ${pc.dim('(also used by the CLI when set)')}`);
|
|
44
|
+
log.info(`${pc.dim('Get key:')} ${info.hint}`);
|
|
45
|
+
const key = await password({
|
|
46
|
+
message: `Paste your ${info.label} API key`,
|
|
47
|
+
validate: (value) => {
|
|
48
|
+
if (!value || value.trim().length === 0) {
|
|
49
|
+
return 'API key cannot be empty';
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
if (isCancel(key)) {
|
|
54
|
+
cancel('Login cancelled.');
|
|
55
|
+
process.exit(0);
|
|
56
|
+
}
|
|
57
|
+
saveProviderKey(provider, key.trim());
|
|
58
|
+
log.success(`${info.label} key saved`);
|
|
59
|
+
note(`You can also set ${pc.bold(info.envVar)} as an env var.\nThe CLI reads it automatically, so you can pass it inline too:\n ${pc.dim(`${info.envVar}=... egaki generate "prompt"`)}`, 'Tip');
|
|
60
|
+
outro('Done');
|
|
61
|
+
}
|
|
62
|
+
export function loginNonInteractive({ provider, key, }) {
|
|
63
|
+
const info = PROVIDERS[provider];
|
|
64
|
+
if (!info) {
|
|
65
|
+
const available = Object.keys(PROVIDERS).join(', ');
|
|
66
|
+
console.error(pc.red(`Unknown provider: ${provider}. Available: ${available}`));
|
|
67
|
+
process.exit(1);
|
|
68
|
+
}
|
|
69
|
+
if (!key || key.trim().length === 0) {
|
|
70
|
+
console.error(pc.red('API key cannot be empty'));
|
|
71
|
+
process.exit(1);
|
|
72
|
+
}
|
|
73
|
+
saveProviderKey(provider, key.trim());
|
|
74
|
+
console.log(pc.green(`${info.label} key saved`));
|
|
75
|
+
}
|
|
76
|
+
export function showLoginStatus() {
|
|
77
|
+
console.log(pc.bold('Configured providers:\n'));
|
|
78
|
+
for (const [key, info] of Object.entries(PROVIDERS)) {
|
|
79
|
+
const status = getKeyStatus(key);
|
|
80
|
+
const icon = status.available ? pc.green('*') : pc.dim('-');
|
|
81
|
+
const source = (() => {
|
|
82
|
+
if (status.source === 'env') {
|
|
83
|
+
return pc.cyan('(from env)');
|
|
84
|
+
}
|
|
85
|
+
if (status.source === 'stored') {
|
|
86
|
+
return pc.green('(saved)');
|
|
87
|
+
}
|
|
88
|
+
return pc.dim('(not set)');
|
|
89
|
+
})();
|
|
90
|
+
const envHint = pc.dim(` env: ${info.envVar} (set in shell or pass inline to CLI)`);
|
|
91
|
+
console.log(`${icon} ${info.label} ${source}`);
|
|
92
|
+
console.log(envHint);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
export function removeLogin(provider) {
|
|
96
|
+
const info = PROVIDERS[provider];
|
|
97
|
+
if (!info) {
|
|
98
|
+
const available = Object.keys(PROVIDERS).join(', ');
|
|
99
|
+
console.error(pc.red(`Unknown provider: ${provider}. Available: ${available}`));
|
|
100
|
+
process.exit(1);
|
|
101
|
+
}
|
|
102
|
+
removeProviderKey(provider);
|
|
103
|
+
console.log(pc.green(`${info.label} key removed`));
|
|
104
|
+
}
|
|
105
|
+
// Read API key from stdin (for piping: echo "sk-xxx" | egaki login --provider google)
|
|
106
|
+
export async function readKeyFromStdin() {
|
|
107
|
+
const chunks = [];
|
|
108
|
+
for await (const chunk of process.stdin) {
|
|
109
|
+
chunks.push(chunk);
|
|
110
|
+
}
|
|
111
|
+
return Buffer.concat(chunks).toString('utf-8').trim();
|
|
112
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export type PerImageCost = {
|
|
2
|
+
type: 'per-image';
|
|
3
|
+
/** USD per image at default quality/resolution */
|
|
4
|
+
perImage: number;
|
|
5
|
+
};
|
|
6
|
+
export type PerTokenCost = {
|
|
7
|
+
type: 'per-token';
|
|
8
|
+
/** USD per million input tokens */
|
|
9
|
+
inputPerM: number;
|
|
10
|
+
/** USD per million output tokens */
|
|
11
|
+
outputPerM: number;
|
|
12
|
+
};
|
|
13
|
+
export type ModelCost = PerImageCost | PerTokenCost;
|
|
14
|
+
export type ModelFeatures = {
|
|
15
|
+
/** supports input images for editing */
|
|
16
|
+
editing: boolean;
|
|
17
|
+
/** supports mask for inpainting */
|
|
18
|
+
inpainting: boolean;
|
|
19
|
+
/** supported aspect ratios */
|
|
20
|
+
aspectRatios: string[];
|
|
21
|
+
/** supported WIDTHxHEIGHT sizes (OpenAI models) */
|
|
22
|
+
sizes?: string[];
|
|
23
|
+
/** supports deterministic seed */
|
|
24
|
+
seed: boolean;
|
|
25
|
+
/** supports generating n > 1 images */
|
|
26
|
+
multipleImages: boolean;
|
|
27
|
+
};
|
|
28
|
+
export type ModelEntry = {
|
|
29
|
+
id: string;
|
|
30
|
+
name: string;
|
|
31
|
+
/** Optional longer description shown in `egaki models` output */
|
|
32
|
+
description?: string;
|
|
33
|
+
provider: string;
|
|
34
|
+
strategy: 'image' | 'text';
|
|
35
|
+
/** Release date in YYYY-MM-DD or YYYY-MM format */
|
|
36
|
+
released: string;
|
|
37
|
+
cost: ModelCost;
|
|
38
|
+
features: ModelFeatures;
|
|
39
|
+
};
|
|
40
|
+
export declare const CATALOG: ModelEntry[];
|
|
41
|
+
export declare function findModel(id: string): ModelEntry | undefined;
|
|
42
|
+
//# sourceMappingURL=model-catalog.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model-catalog.d.ts","sourceRoot":"","sources":["../src/model-catalog.ts"],"names":[],"mappings":"AAUA,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,EAAE,WAAW,CAAA;IACjB,kDAAkD;IAClD,QAAQ,EAAE,MAAM,CAAA;CACjB,CAAA;AAED,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,EAAE,WAAW,CAAA;IACjB,mCAAmC;IACnC,SAAS,EAAE,MAAM,CAAA;IACjB,oCAAoC;IACpC,UAAU,EAAE,MAAM,CAAA;CACnB,CAAA;AAED,MAAM,MAAM,SAAS,GAAG,YAAY,GAAG,YAAY,CAAA;AAEnD,MAAM,MAAM,aAAa,GAAG;IAC1B,wCAAwC;IACxC,OAAO,EAAE,OAAO,CAAA;IAChB,mCAAmC;IACnC,UAAU,EAAE,OAAO,CAAA;IACnB,8BAA8B;IAC9B,YAAY,EAAE,MAAM,EAAE,CAAA;IACtB,mDAAmD;IACnD,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;IAChB,kCAAkC;IAClC,IAAI,EAAE,OAAO,CAAA;IACb,uCAAuC;IACvC,cAAc,EAAE,OAAO,CAAA;CACxB,CAAA;AAED,MAAM,MAAM,UAAU,GAAG;IACvB,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,iEAAiE;IACjE,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,OAAO,GAAG,MAAM,CAAA;IAC1B,mDAAmD;IACnD,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,SAAS,CAAA;IACf,QAAQ,EAAE,aAAa,CAAA;CACxB,CAAA;AA+DD,eAAO,MAAM,OAAO,EAAE,UAAU,EA40B/B,CAAA;AAMD,wBAAgB,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CAE5D"}
|