@getvibeguard/cli 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +166 -0
- package/dashboard/dist/assets/Tableau10-B-NsZVaP.js +1 -0
- package/dashboard/dist/assets/arc-CZ1oDkm-.js +1 -0
- package/dashboard/dist/assets/array-BKyUJesY.js +1 -0
- package/dashboard/dist/assets/blockDiagram-c4efeb88-BLITAZDl.js +118 -0
- package/dashboard/dist/assets/c4Diagram-c83219d4-DErNj891.js +10 -0
- package/dashboard/dist/assets/channel-sWBGOq9p.js +1 -0
- package/dashboard/dist/assets/classDiagram-beda092f-Bj8IB6RW.js +2 -0
- package/dashboard/dist/assets/classDiagram-v2-2358418a-BZtd2g5W.js +2 -0
- package/dashboard/dist/assets/clone-DtEyH3ya.js +1 -0
- package/dashboard/dist/assets/createText-1719965b-DkNrTk-5.js +7 -0
- package/dashboard/dist/assets/edges-96097737-CYxl0j3g.js +4 -0
- package/dashboard/dist/assets/erDiagram-0228fc6a-ClEp9Atg.js +51 -0
- package/dashboard/dist/assets/flowDb-c6c81e3f-ClDJCJwu.js +10 -0
- package/dashboard/dist/assets/flowDiagram-50d868cf-DYxwClWS.js +4 -0
- package/dashboard/dist/assets/flowDiagram-v2-4f6560a1-D7vEnO1T.js +1 -0
- package/dashboard/dist/assets/flowchart-elk-definition-6af322e1-C-wX1mNx.js +139 -0
- package/dashboard/dist/assets/ganttDiagram-a2739b55-DTeLavAj.js +257 -0
- package/dashboard/dist/assets/gitGraphDiagram-82fe8481-ClxNoYya.js +70 -0
- package/dashboard/dist/assets/graph-CT-F3Got.js +1 -0
- package/dashboard/dist/assets/index-5325376f-C-jTCYZA.js +1 -0
- package/dashboard/dist/assets/index-CvYvquQR.js +283 -0
- package/dashboard/dist/assets/index-n43poL1x.css +1 -0
- package/dashboard/dist/assets/infoDiagram-8eee0895-Zljudo5L.js +7 -0
- package/dashboard/dist/assets/init-Gi6I4Gst.js +1 -0
- package/dashboard/dist/assets/journeyDiagram-c64418c1-DXzTbuum.js +139 -0
- package/dashboard/dist/assets/katex-Cu_Erd72.js +261 -0
- package/dashboard/dist/assets/layout-CVO3EizT.js +1 -0
- package/dashboard/dist/assets/line-CIgln-0z.js +1 -0
- package/dashboard/dist/assets/linear-bmIUMQqg.js +1 -0
- package/dashboard/dist/assets/mindmap-definition-8da855dc-BDLTNZYk.js +425 -0
- package/dashboard/dist/assets/ordinal-Cboi1Yqb.js +1 -0
- package/dashboard/dist/assets/path-CbwjOpE9.js +1 -0
- package/dashboard/dist/assets/pieDiagram-a8764435-DtcOKNPc.js +35 -0
- package/dashboard/dist/assets/quadrantDiagram-1e28029f-zoSI_Ltf.js +7 -0
- package/dashboard/dist/assets/requirementDiagram-08caed73-TsQZ9lTB.js +52 -0
- package/dashboard/dist/assets/sankeyDiagram-a04cb91d-DE5ciDwD.js +8 -0
- package/dashboard/dist/assets/sequenceDiagram-c5b8d532-DhabPb2n.js +122 -0
- package/dashboard/dist/assets/stateDiagram-1ecb1508-Bg2q_YNx.js +1 -0
- package/dashboard/dist/assets/stateDiagram-v2-c2b004d7-Bs5iRjYB.js +1 -0
- package/dashboard/dist/assets/styles-b4e223ce-DchmAmav.js +160 -0
- package/dashboard/dist/assets/styles-ca3715f6-Bu5zjaDx.js +207 -0
- package/dashboard/dist/assets/styles-d45a18b0-jCaD8baR.js +116 -0
- package/dashboard/dist/assets/svgDrawCommon-b86b1483-BrYVGY4c.js +1 -0
- package/dashboard/dist/assets/timeline-definition-faaaa080--sq0bTHe.js +61 -0
- package/dashboard/dist/assets/xychartDiagram-f5964ef8-ByvzN0uj.js +7 -0
- package/dashboard/dist/index.html +22 -0
- package/dist/cli.d.ts +4 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +641 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/dashboard.d.ts +2 -0
- package/dist/commands/dashboard.d.ts.map +1 -0
- package/dist/commands/dashboard.js +184 -0
- package/dist/commands/dashboard.js.map +1 -0
- package/dist/commands/init.d.ts +5 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +501 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +602 -0
- package/dist/index.js.map +1 -0
- package/dist/librarian/autofix.d.ts +34 -0
- package/dist/librarian/autofix.d.ts.map +1 -0
- package/dist/librarian/autofix.js +369 -0
- package/dist/librarian/autofix.js.map +1 -0
- package/dist/librarian/heartbeat.d.ts +38 -0
- package/dist/librarian/heartbeat.d.ts.map +1 -0
- package/dist/librarian/heartbeat.js +98 -0
- package/dist/librarian/heartbeat.js.map +1 -0
- package/dist/librarian/initializer.d.ts +41 -0
- package/dist/librarian/initializer.d.ts.map +1 -0
- package/dist/librarian/initializer.js +202 -0
- package/dist/librarian/initializer.js.map +1 -0
- package/dist/librarian/memory-manager.d.ts +37 -0
- package/dist/librarian/memory-manager.d.ts.map +1 -0
- package/dist/librarian/memory-manager.js +205 -0
- package/dist/librarian/memory-manager.js.map +1 -0
- package/dist/librarian/oracle.d.ts +51 -0
- package/dist/librarian/oracle.d.ts.map +1 -0
- package/dist/librarian/oracle.js +235 -0
- package/dist/librarian/oracle.js.map +1 -0
- package/dist/librarian/summarizer.d.ts +19 -0
- package/dist/librarian/summarizer.d.ts.map +1 -0
- package/dist/librarian/summarizer.js +175 -0
- package/dist/librarian/summarizer.js.map +1 -0
- package/dist/librarian/watcher.d.ts +51 -0
- package/dist/librarian/watcher.d.ts.map +1 -0
- package/dist/librarian/watcher.js +189 -0
- package/dist/librarian/watcher.js.map +1 -0
- package/dist/mcp-server.d.ts +10 -0
- package/dist/mcp-server.d.ts.map +1 -0
- package/dist/mcp-server.js +879 -0
- package/dist/mcp-server.js.map +1 -0
- package/dist/services/token-tracker.d.ts +58 -0
- package/dist/services/token-tracker.d.ts.map +1 -0
- package/dist/services/token-tracker.js +178 -0
- package/dist/services/token-tracker.js.map +1 -0
- package/dist/utils/chunker.d.ts +5 -0
- package/dist/utils/chunker.d.ts.map +1 -0
- package/dist/utils/chunker.js +121 -0
- package/dist/utils/chunker.js.map +1 -0
- package/dist/utils/config-manager.d.ts +65 -0
- package/dist/utils/config-manager.d.ts.map +1 -0
- package/dist/utils/config-manager.js +243 -0
- package/dist/utils/config-manager.js.map +1 -0
- package/dist/utils/config.d.ts +46 -0
- package/dist/utils/config.d.ts.map +1 -0
- package/dist/utils/config.js +171 -0
- package/dist/utils/config.js.map +1 -0
- package/dist/utils/diff-cleaner.d.ts +13 -0
- package/dist/utils/diff-cleaner.d.ts.map +1 -0
- package/dist/utils/diff-cleaner.js +80 -0
- package/dist/utils/diff-cleaner.js.map +1 -0
- package/dist/utils/git.d.ts +71 -0
- package/dist/utils/git.d.ts.map +1 -0
- package/dist/utils/git.js +285 -0
- package/dist/utils/git.js.map +1 -0
- package/dist/utils/llm.d.ts +30 -0
- package/dist/utils/llm.d.ts.map +1 -0
- package/dist/utils/llm.js +308 -0
- package/dist/utils/llm.js.map +1 -0
- package/dist/utils/pricing.d.ts +47 -0
- package/dist/utils/pricing.d.ts.map +1 -0
- package/dist/utils/pricing.js +171 -0
- package/dist/utils/pricing.js.map +1 -0
- package/package.json +45 -0
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
import * as fs from 'fs/promises';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
import * as os from 'os';
|
|
4
|
+
/**
|
|
5
|
+
* ConfigManager handles both global and local configuration
|
|
6
|
+
*/
|
|
7
|
+
export class ConfigManager {
|
|
8
|
+
static globalConfigPath;
|
|
9
|
+
static localConfigPath;
|
|
10
|
+
static {
|
|
11
|
+
// Initialize paths
|
|
12
|
+
const homeDir = os.homedir();
|
|
13
|
+
ConfigManager.globalConfigPath = path.join(homeDir, '.vibeguard', 'config.json');
|
|
14
|
+
const repoPath = process.cwd();
|
|
15
|
+
ConfigManager.localConfigPath = path.join(repoPath, '.vibeguard', 'settings.json');
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Get global config path
|
|
19
|
+
*/
|
|
20
|
+
static getGlobalConfigPath() {
|
|
21
|
+
return ConfigManager.globalConfigPath;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Get local config path
|
|
25
|
+
*/
|
|
26
|
+
static getLocalConfigPath() {
|
|
27
|
+
return ConfigManager.localConfigPath;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Load global config from ~/.vibeguard/config.json
|
|
31
|
+
*/
|
|
32
|
+
static async loadGlobalConfig() {
|
|
33
|
+
try {
|
|
34
|
+
const content = await fs.readFile(ConfigManager.globalConfigPath, 'utf-8');
|
|
35
|
+
return JSON.parse(content);
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
if (error.code === 'ENOENT') {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
throw error;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Save global config to ~/.vibeguard/config.json
|
|
46
|
+
*/
|
|
47
|
+
static async saveGlobalConfig(config) {
|
|
48
|
+
const configDir = path.dirname(ConfigManager.globalConfigPath);
|
|
49
|
+
// Ensure directory exists
|
|
50
|
+
try {
|
|
51
|
+
await fs.mkdir(configDir, { recursive: true });
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
// Ignore EEXIST (directory already exists) on Unix
|
|
55
|
+
// On Windows, check for EEXIST or if directory already exists
|
|
56
|
+
if (error.code !== 'EEXIST' && error.code !== 'EISDIR') {
|
|
57
|
+
// Verify the directory actually exists before throwing
|
|
58
|
+
try {
|
|
59
|
+
const stats = await fs.stat(configDir);
|
|
60
|
+
if (!stats.isDirectory()) {
|
|
61
|
+
throw error;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
// Directory doesn't exist, rethrow original error
|
|
66
|
+
throw new Error(`Failed to create config directory: ${configDir}. Error: ${error.message || error}`);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
try {
|
|
71
|
+
await fs.writeFile(ConfigManager.globalConfigPath, JSON.stringify(config, null, 2), 'utf-8');
|
|
72
|
+
}
|
|
73
|
+
catch (error) {
|
|
74
|
+
throw new Error(`Failed to write global config to ${ConfigManager.globalConfigPath}. Error: ${error.message || error}`);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Load local config from .vibeguard/settings.json
|
|
79
|
+
*/
|
|
80
|
+
static async loadLocalConfig() {
|
|
81
|
+
try {
|
|
82
|
+
const content = await fs.readFile(ConfigManager.localConfigPath, 'utf-8');
|
|
83
|
+
return JSON.parse(content);
|
|
84
|
+
}
|
|
85
|
+
catch (error) {
|
|
86
|
+
if (error.code === 'ENOENT') {
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
throw error;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Save local config to .vibeguard/settings.json
|
|
94
|
+
*/
|
|
95
|
+
static async saveLocalConfig(config) {
|
|
96
|
+
const configDir = path.dirname(ConfigManager.localConfigPath);
|
|
97
|
+
// Ensure directory exists
|
|
98
|
+
try {
|
|
99
|
+
await fs.mkdir(configDir, { recursive: true });
|
|
100
|
+
}
|
|
101
|
+
catch (error) {
|
|
102
|
+
if (error.code !== 'EEXIST') {
|
|
103
|
+
throw error;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
await fs.writeFile(ConfigManager.localConfigPath, JSON.stringify(config, null, 2), 'utf-8');
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Check if local config exists
|
|
110
|
+
*/
|
|
111
|
+
static async localConfigExists() {
|
|
112
|
+
try {
|
|
113
|
+
await fs.access(ConfigManager.localConfigPath);
|
|
114
|
+
return true;
|
|
115
|
+
}
|
|
116
|
+
catch {
|
|
117
|
+
return false;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Get API key for a specific provider
|
|
122
|
+
* Priority: 1. Environment variable, 2. Global config, 3. null
|
|
123
|
+
*/
|
|
124
|
+
static async getApiKey(provider) {
|
|
125
|
+
// Priority 1: Environment variables
|
|
126
|
+
if (provider === 'google' && process.env.GEMINI_API_KEY) {
|
|
127
|
+
return process.env.GEMINI_API_KEY;
|
|
128
|
+
}
|
|
129
|
+
if (provider === 'openai' && process.env.OPENAI_API_KEY) {
|
|
130
|
+
return process.env.OPENAI_API_KEY;
|
|
131
|
+
}
|
|
132
|
+
if (provider === 'anthropic' && process.env.ANTHROPIC_API_KEY) {
|
|
133
|
+
return process.env.ANTHROPIC_API_KEY;
|
|
134
|
+
}
|
|
135
|
+
// Priority 2: Global config
|
|
136
|
+
const globalConfig = await ConfigManager.loadGlobalConfig();
|
|
137
|
+
if (!globalConfig) {
|
|
138
|
+
return null;
|
|
139
|
+
}
|
|
140
|
+
switch (provider) {
|
|
141
|
+
case 'google':
|
|
142
|
+
return globalConfig.geminiApiKey || null;
|
|
143
|
+
case 'openai':
|
|
144
|
+
return globalConfig.openaiApiKey || null;
|
|
145
|
+
case 'anthropic':
|
|
146
|
+
return globalConfig.anthropicApiKey || null;
|
|
147
|
+
default:
|
|
148
|
+
return null;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Get model name based on provider and profile
|
|
153
|
+
*/
|
|
154
|
+
static getModelForProfile(provider, profile, thinkingLevel) {
|
|
155
|
+
if (profile === 'Economy') {
|
|
156
|
+
// Economy: Always use Flash models
|
|
157
|
+
switch (provider) {
|
|
158
|
+
case 'google':
|
|
159
|
+
return 'gemini-3-flash-preview';
|
|
160
|
+
case 'openai':
|
|
161
|
+
return 'gpt-4o-mini';
|
|
162
|
+
case 'anthropic':
|
|
163
|
+
return 'claude-3-haiku-20240307';
|
|
164
|
+
default:
|
|
165
|
+
return 'gemini-3-flash-preview';
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
else if (profile === 'Balanced') {
|
|
169
|
+
// Balanced: Flash for summaries, Pro for Oracle/Auto-Fix
|
|
170
|
+
if (thinkingLevel === 'flash') {
|
|
171
|
+
switch (provider) {
|
|
172
|
+
case 'google':
|
|
173
|
+
return 'gemini-3-flash-preview';
|
|
174
|
+
case 'openai':
|
|
175
|
+
return 'gpt-4o-mini';
|
|
176
|
+
case 'anthropic':
|
|
177
|
+
return 'claude-3-haiku-20240307';
|
|
178
|
+
default:
|
|
179
|
+
return 'gemini-3-flash-preview';
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
else {
|
|
183
|
+
switch (provider) {
|
|
184
|
+
case 'google':
|
|
185
|
+
return 'gemini-3-pro-preview';
|
|
186
|
+
case 'openai':
|
|
187
|
+
return 'gpt-4o';
|
|
188
|
+
case 'anthropic':
|
|
189
|
+
return 'claude-3-opus-20240229';
|
|
190
|
+
default:
|
|
191
|
+
return 'gemini-3-pro-preview';
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
else {
|
|
196
|
+
// High-IQ: Always use Pro models
|
|
197
|
+
switch (provider) {
|
|
198
|
+
case 'google':
|
|
199
|
+
return 'gemini-3-pro-preview';
|
|
200
|
+
case 'openai':
|
|
201
|
+
return 'gpt-4o';
|
|
202
|
+
case 'anthropic':
|
|
203
|
+
return 'claude-3-opus-20240229';
|
|
204
|
+
default:
|
|
205
|
+
return 'gemini-3-pro-preview';
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Get model display name for logging
|
|
211
|
+
*/
|
|
212
|
+
static getModelDisplayName(provider, modelName) {
|
|
213
|
+
if (provider === 'google') {
|
|
214
|
+
if (modelName.includes('flash')) {
|
|
215
|
+
return 'Gemini 3 Flash';
|
|
216
|
+
}
|
|
217
|
+
else if (modelName.includes('pro')) {
|
|
218
|
+
return 'Gemini 3 Pro';
|
|
219
|
+
}
|
|
220
|
+
return 'Gemini';
|
|
221
|
+
}
|
|
222
|
+
else if (provider === 'openai') {
|
|
223
|
+
if (modelName.includes('gpt-4o')) {
|
|
224
|
+
return modelName.includes('mini') ? 'GPT-4o Mini' : 'GPT-4o';
|
|
225
|
+
}
|
|
226
|
+
return 'OpenAI';
|
|
227
|
+
}
|
|
228
|
+
else if (provider === 'anthropic') {
|
|
229
|
+
if (modelName.includes('haiku')) {
|
|
230
|
+
return 'Claude 3 Haiku';
|
|
231
|
+
}
|
|
232
|
+
else if (modelName.includes('sonnet')) {
|
|
233
|
+
return 'Claude 3 Sonnet';
|
|
234
|
+
}
|
|
235
|
+
else if (modelName.includes('opus')) {
|
|
236
|
+
return 'Claude 3 Opus';
|
|
237
|
+
}
|
|
238
|
+
return 'Claude';
|
|
239
|
+
}
|
|
240
|
+
return modelName;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
//# sourceMappingURL=config-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-manager.js","sourceRoot":"","sources":["../../src/utils/config-manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
export interface GlobalConfig {
|
|
2
|
+
geminiApiKey?: string;
|
|
3
|
+
maxTokens?: number;
|
|
4
|
+
model?: string;
|
|
5
|
+
flashModel?: string;
|
|
6
|
+
proModel?: string;
|
|
7
|
+
scanDepth?: number;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Global constants for architectural scanning
|
|
11
|
+
*/
|
|
12
|
+
export declare const MAX_SCAN_DEPTH = 15;
|
|
13
|
+
/**
|
|
14
|
+
* Hybrid API key resolution with priority:
|
|
15
|
+
* 1. process.env.GEMINI_API_KEY (direct env var - CI/CD)
|
|
16
|
+
* 2. .env file in project root (via dotenv - Vibe Coding default)
|
|
17
|
+
* 3. New ConfigManager (checks local config for provider, then global config)
|
|
18
|
+
* 4. Legacy global config file (~/.config/vibeguard/config.json)
|
|
19
|
+
*/
|
|
20
|
+
export declare function getApiKey(): Promise<string>;
|
|
21
|
+
/**
|
|
22
|
+
* Load global config from ~/.vibeguard/config.json (new) or ~/.config/vibeguard/config.json (legacy)
|
|
23
|
+
*/
|
|
24
|
+
export declare function loadGlobalConfig(): Promise<GlobalConfig | null>;
|
|
25
|
+
/**
|
|
26
|
+
* Get max tokens from config (with fallback)
|
|
27
|
+
*/
|
|
28
|
+
export declare function getMaxTokens(): Promise<number>;
|
|
29
|
+
/**
|
|
30
|
+
* Get model name from config (with fallback)
|
|
31
|
+
* @deprecated Use getFlashModel() or getProModel() instead
|
|
32
|
+
*/
|
|
33
|
+
export declare function getModel(): Promise<string>;
|
|
34
|
+
/**
|
|
35
|
+
* Get Flash model name from config (with fallback)
|
|
36
|
+
*/
|
|
37
|
+
export declare function getFlashModel(): Promise<string>;
|
|
38
|
+
/**
|
|
39
|
+
* Get Pro model name from config (with fallback to Flash if not configured)
|
|
40
|
+
*/
|
|
41
|
+
export declare function getProModel(): Promise<string>;
|
|
42
|
+
/**
|
|
43
|
+
* Get the maximum directory depth for architectural scans
|
|
44
|
+
*/
|
|
45
|
+
export declare function getScanDepth(): Promise<number>;
|
|
46
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,YAAY;IAC3B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,eAAO,MAAM,cAAc,KAAK,CAAC;AAEjC;;;;;;GAMG;AACH,wBAAsB,SAAS,IAAI,OAAO,CAAC,MAAM,CAAC,CA4CjD;AAED;;GAEG;AACH,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAsBrE;AAED;;GAEG;AACH,wBAAsB,YAAY,IAAI,OAAO,CAAC,MAAM,CAAC,CAepD;AAED;;;GAGG;AACH,wBAAsB,QAAQ,IAAI,OAAO,CAAC,MAAM,CAAC,CAYhD;AAED;;GAEG;AACH,wBAAsB,aAAa,IAAI,OAAO,CAAC,MAAM,CAAC,CAuBrD;AAED;;GAEG;AACH,wBAAsB,WAAW,IAAI,OAAO,CAAC,MAAM,CAAC,CAanD;AAED;;GAEG;AACH,wBAAsB,YAAY,IAAI,OAAO,CAAC,MAAM,CAAC,CAepD"}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import * as fs from 'fs/promises';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
import * as os from 'os';
|
|
4
|
+
import { config } from 'dotenv';
|
|
5
|
+
import { ConfigManager } from './config-manager.js';
|
|
6
|
+
/**
|
|
7
|
+
* Global constants for architectural scanning
|
|
8
|
+
*/
|
|
9
|
+
export const MAX_SCAN_DEPTH = 15;
|
|
10
|
+
/**
|
|
11
|
+
* Hybrid API key resolution with priority:
|
|
12
|
+
* 1. process.env.GEMINI_API_KEY (direct env var - CI/CD)
|
|
13
|
+
* 2. .env file in project root (via dotenv - Vibe Coding default)
|
|
14
|
+
* 3. New ConfigManager (checks local config for provider, then global config)
|
|
15
|
+
* 4. Legacy global config file (~/.config/vibeguard/config.json)
|
|
16
|
+
*/
|
|
17
|
+
export async function getApiKey() {
|
|
18
|
+
// Priority 1: Direct environment variable
|
|
19
|
+
if (process.env.GEMINI_API_KEY) {
|
|
20
|
+
return process.env.GEMINI_API_KEY;
|
|
21
|
+
}
|
|
22
|
+
// Priority 2: .env file in project root
|
|
23
|
+
config(); // Load .env file
|
|
24
|
+
if (process.env.GEMINI_API_KEY) {
|
|
25
|
+
return process.env.GEMINI_API_KEY;
|
|
26
|
+
}
|
|
27
|
+
// Priority 3: New ConfigManager (if local config exists, use it)
|
|
28
|
+
try {
|
|
29
|
+
const localConfig = await ConfigManager.loadLocalConfig();
|
|
30
|
+
if (localConfig) {
|
|
31
|
+
const apiKey = await ConfigManager.getApiKey(localConfig.provider);
|
|
32
|
+
if (apiKey) {
|
|
33
|
+
return apiKey;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
// Try Google provider as fallback
|
|
38
|
+
const apiKey = await ConfigManager.getApiKey('google');
|
|
39
|
+
if (apiKey) {
|
|
40
|
+
return apiKey;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
// ConfigManager might not be set up yet, continue to legacy fallback
|
|
46
|
+
}
|
|
47
|
+
// Priority 4: Legacy global config file
|
|
48
|
+
const globalConfig = await loadGlobalConfig();
|
|
49
|
+
if (globalConfig?.geminiApiKey) {
|
|
50
|
+
return globalConfig.geminiApiKey;
|
|
51
|
+
}
|
|
52
|
+
throw new Error('GEMINI_API_KEY not found. Please set it in one of the following ways:\n' +
|
|
53
|
+
' 1. Environment variable: export GEMINI_API_KEY=your-key\n' +
|
|
54
|
+
' 2. .env file: Create .env in project root with GEMINI_API_KEY=your-key\n' +
|
|
55
|
+
' 3. Run `vibeguard init` to configure via interactive wizard\n' +
|
|
56
|
+
' 4. Global config: Create ~/.vibeguard/config.json with {"geminiApiKey": "your-key"}');
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Load global config from ~/.vibeguard/config.json (new) or ~/.config/vibeguard/config.json (legacy)
|
|
60
|
+
*/
|
|
61
|
+
export async function loadGlobalConfig() {
|
|
62
|
+
// Try new ConfigManager first
|
|
63
|
+
try {
|
|
64
|
+
const newConfig = await ConfigManager.loadGlobalConfig();
|
|
65
|
+
if (newConfig) {
|
|
66
|
+
return newConfig;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
// Continue to legacy path
|
|
71
|
+
}
|
|
72
|
+
// Legacy path: ~/.config/vibeguard/config.json
|
|
73
|
+
try {
|
|
74
|
+
const homeDir = os.homedir();
|
|
75
|
+
const configPath = path.join(homeDir, '.config', 'vibeguard', 'config.json');
|
|
76
|
+
const content = await fs.readFile(configPath, 'utf-8');
|
|
77
|
+
return JSON.parse(content);
|
|
78
|
+
}
|
|
79
|
+
catch (error) {
|
|
80
|
+
// File doesn't exist or is invalid - return null
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Get max tokens from config (with fallback)
|
|
86
|
+
*/
|
|
87
|
+
export async function getMaxTokens() {
|
|
88
|
+
const envValue = process.env.VIBEGUARD_MAX_TOKENS;
|
|
89
|
+
if (envValue) {
|
|
90
|
+
const parsed = parseInt(envValue, 10);
|
|
91
|
+
if (!isNaN(parsed)) {
|
|
92
|
+
return parsed;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
const globalConfig = await loadGlobalConfig();
|
|
96
|
+
if (globalConfig?.maxTokens) {
|
|
97
|
+
return globalConfig.maxTokens;
|
|
98
|
+
}
|
|
99
|
+
return 50000; // Default aligned with 18.01.2026 decision for Oracle reasoning
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Get model name from config (with fallback)
|
|
103
|
+
* @deprecated Use getFlashModel() or getProModel() instead
|
|
104
|
+
*/
|
|
105
|
+
export async function getModel() {
|
|
106
|
+
const envValue = process.env.VIBEGUARD_MODEL;
|
|
107
|
+
if (envValue) {
|
|
108
|
+
return envValue;
|
|
109
|
+
}
|
|
110
|
+
const globalConfig = await loadGlobalConfig();
|
|
111
|
+
if (globalConfig?.model) {
|
|
112
|
+
return globalConfig.model;
|
|
113
|
+
}
|
|
114
|
+
return 'gemini-3-flash-preview'; // Default
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Get Flash model name from config (with fallback)
|
|
118
|
+
*/
|
|
119
|
+
export async function getFlashModel() {
|
|
120
|
+
const envValue = process.env.VIBEGUARD_FLASH_MODEL;
|
|
121
|
+
if (envValue) {
|
|
122
|
+
return envValue;
|
|
123
|
+
}
|
|
124
|
+
const globalConfig = await loadGlobalConfig();
|
|
125
|
+
if (globalConfig?.flashModel) {
|
|
126
|
+
return globalConfig.flashModel;
|
|
127
|
+
}
|
|
128
|
+
// Fallback to legacy VIBEGUARD_MODEL if set
|
|
129
|
+
const legacyModel = process.env.VIBEGUARD_MODEL;
|
|
130
|
+
if (legacyModel) {
|
|
131
|
+
return legacyModel;
|
|
132
|
+
}
|
|
133
|
+
const legacyGlobalConfig = await loadGlobalConfig();
|
|
134
|
+
if (legacyGlobalConfig?.model) {
|
|
135
|
+
return legacyGlobalConfig.model;
|
|
136
|
+
}
|
|
137
|
+
return 'gemini-3-flash-preview'; // Default
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Get Pro model name from config (with fallback to Flash if not configured)
|
|
141
|
+
*/
|
|
142
|
+
export async function getProModel() {
|
|
143
|
+
const envValue = process.env.VIBEGUARD_PRO_MODEL;
|
|
144
|
+
if (envValue) {
|
|
145
|
+
return envValue;
|
|
146
|
+
}
|
|
147
|
+
const globalConfig = await loadGlobalConfig();
|
|
148
|
+
if (globalConfig?.proModel) {
|
|
149
|
+
return globalConfig.proModel;
|
|
150
|
+
}
|
|
151
|
+
// Fallback to Flash model if Pro is not configured
|
|
152
|
+
return await getFlashModel();
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Get the maximum directory depth for architectural scans
|
|
156
|
+
*/
|
|
157
|
+
export async function getScanDepth() {
|
|
158
|
+
const envValue = process.env.VIBEGUARD_SCAN_DEPTH;
|
|
159
|
+
if (envValue) {
|
|
160
|
+
const parsed = parseInt(envValue, 10);
|
|
161
|
+
if (!isNaN(parsed)) {
|
|
162
|
+
return parsed;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
const globalConfig = await loadGlobalConfig();
|
|
166
|
+
if (globalConfig?.scanDepth) {
|
|
167
|
+
return globalConfig.scanDepth;
|
|
168
|
+
}
|
|
169
|
+
return MAX_SCAN_DEPTH;
|
|
170
|
+
}
|
|
171
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pre-Shredder: Clean diffs before sending to LLM
|
|
3
|
+
* Removes bloat like lockfiles, build outputs, node_modules, etc.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Check if a file path should be ignored
|
|
7
|
+
*/
|
|
8
|
+
export declare function shouldIgnoreFile(filePath: string): boolean;
|
|
9
|
+
/**
|
|
10
|
+
* Clean diff by removing bloat (Pre-Shredder logic)
|
|
11
|
+
*/
|
|
12
|
+
export declare function cleanDiff(rawDiff: string): string;
|
|
13
|
+
//# sourceMappingURL=diff-cleaner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff-cleaner.d.ts","sourceRoot":"","sources":["../../src/utils/diff-cleaner.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAmB1D;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CA2DjD"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pre-Shredder: Clean diffs before sending to LLM
|
|
3
|
+
* Removes bloat like lockfiles, build outputs, node_modules, etc.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Check if a file path should be ignored
|
|
7
|
+
*/
|
|
8
|
+
export function shouldIgnoreFile(filePath) {
|
|
9
|
+
const normalized = filePath.replace(/\\/g, '/');
|
|
10
|
+
// Ignore patterns
|
|
11
|
+
const ignorePatterns = [
|
|
12
|
+
/node_modules\//,
|
|
13
|
+
/\.lock$/,
|
|
14
|
+
/\.log$/,
|
|
15
|
+
/^dist\//,
|
|
16
|
+
/^build\//,
|
|
17
|
+
/^\.next\//,
|
|
18
|
+
/^out\//,
|
|
19
|
+
/^\.git\//,
|
|
20
|
+
/^\.vibeguard\//,
|
|
21
|
+
/\.(png|jpg|jpeg|gif|svg|ico|woff|woff2|ttf|eot)$/i, // Binary assets
|
|
22
|
+
/\.(exe|dll|so|dylib)$/i, // Compiled binaries
|
|
23
|
+
];
|
|
24
|
+
return ignorePatterns.some(pattern => pattern.test(normalized));
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Clean diff by removing bloat (Pre-Shredder logic)
|
|
28
|
+
*/
|
|
29
|
+
export function cleanDiff(rawDiff) {
|
|
30
|
+
const lines = rawDiff.split('\n');
|
|
31
|
+
const cleaned = [];
|
|
32
|
+
let inIgnoredFile = false;
|
|
33
|
+
let currentFile = '';
|
|
34
|
+
for (let i = 0; i < lines.length; i++) {
|
|
35
|
+
const line = lines[i];
|
|
36
|
+
// Check if this line starts a new file section
|
|
37
|
+
if (line.startsWith('diff --git')) {
|
|
38
|
+
const match = line.match(/^diff --git a\/(.+?) b\/(.+)$/);
|
|
39
|
+
if (match) {
|
|
40
|
+
currentFile = match[2];
|
|
41
|
+
inIgnoredFile = shouldIgnoreFile(currentFile);
|
|
42
|
+
if (!inIgnoredFile) {
|
|
43
|
+
cleaned.push(line);
|
|
44
|
+
}
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
// If we're in an ignored file, skip all lines until next file
|
|
49
|
+
if (inIgnoredFile) {
|
|
50
|
+
// Check if we've moved to a new file
|
|
51
|
+
if (line.startsWith('diff --git')) {
|
|
52
|
+
const match = line.match(/^diff --git a\/(.+?) b\/(.+)$/);
|
|
53
|
+
if (match) {
|
|
54
|
+
currentFile = match[2];
|
|
55
|
+
inIgnoredFile = shouldIgnoreFile(currentFile);
|
|
56
|
+
if (!inIgnoredFile) {
|
|
57
|
+
cleaned.push(line);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
// Filter out specific patterns
|
|
64
|
+
if (line.match(/lockfile|package-lock\.json|dist\/|build\//)) {
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
// Remove binary file diffs
|
|
68
|
+
if (line.match(/Binary files/)) {
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
// Remove node_modules references
|
|
72
|
+
if (line.includes('node_modules/')) {
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
// Keep the line
|
|
76
|
+
cleaned.push(line);
|
|
77
|
+
}
|
|
78
|
+
return cleaned.join('\n');
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=diff-cleaner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff-cleaner.js","sourceRoot":"","sources":["../../src/utils/diff-cleaner.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,QAAgB;IAC/C,MAAM,UAAU,GAAG,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAEhD,kBAAkB;IAClB,MAAM,cAAc,GAAG;QACrB,gBAAgB;QAChB,SAAS;QACT,QAAQ;QACR,SAAS;QACT,UAAU;QACV,WAAW;QACX,QAAQ;QACR,UAAU;QACV,gBAAgB;QAChB,mDAAmD,EAAE,gBAAgB;QACrE,wBAAwB,EAAE,oBAAoB;KAC/C,CAAC;IAEF,OAAO,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;AAClE,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,SAAS,CAAC,OAAe;IACvC,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAClC,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,IAAI,aAAa,GAAG,KAAK,CAAC;IAC1B,IAAI,WAAW,GAAG,EAAE,CAAC;IAErB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QAEtB,+CAA+C;QAC/C,IAAI,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;YAClC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,+BAA+B,CAAC,CAAC;YAC1D,IAAI,KAAK,EAAE,CAAC;gBACV,WAAW,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;gBACvB,aAAa,GAAG,gBAAgB,CAAC,WAAW,CAAC,CAAC;gBAE9C,IAAI,CAAC,aAAa,EAAE,CAAC;oBACnB,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACrB,CAAC;gBACD,SAAS;YACX,CAAC;QACH,CAAC;QAED,8DAA8D;QAC9D,IAAI,aAAa,EAAE,CAAC;YAClB,qCAAqC;YACrC,IAAI,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;gBAClC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,+BAA+B,CAAC,CAAC;gBAC1D,IAAI,KAAK,EAAE,CAAC;oBACV,WAAW,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;oBACvB,aAAa,GAAG,gBAAgB,CAAC,WAAW,CAAC,CAAC;oBAC9C,IAAI,CAAC,aAAa,EAAE,CAAC;wBACnB,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;oBACrB,CAAC;gBACH,CAAC;YACH,CAAC;YACD,SAAS;QACX,CAAC;QAED,+BAA+B;QAC/B,IAAI,IAAI,CAAC,KAAK,CAAC,4CAA4C,CAAC,EAAE,CAAC;YAC7D,SAAS;QACX,CAAC;QAED,2BAA2B;QAC3B,IAAI,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,EAAE,CAAC;YAC/B,SAAS;QACX,CAAC;QAED,iCAAiC;QACjC,IAAI,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,EAAE,CAAC;YACnC,SAAS;QACX,CAAC;QAED,gBAAgB;QAChB,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACrB,CAAC;IAED,OAAO,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC5B,CAAC"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { LogResult } from 'simple-git';
|
|
2
|
+
export interface OnelineCommit {
|
|
3
|
+
hash: string;
|
|
4
|
+
message: string;
|
|
5
|
+
date: string;
|
|
6
|
+
}
|
|
7
|
+
export declare class GitUtils {
|
|
8
|
+
private git;
|
|
9
|
+
private repoPath;
|
|
10
|
+
constructor(repoPath?: string);
|
|
11
|
+
/**
|
|
12
|
+
* Get the latest N commits
|
|
13
|
+
*/
|
|
14
|
+
getLatestCommits(count: number): Promise<LogResult['all']>;
|
|
15
|
+
/**
|
|
16
|
+
* Get the diff for a specific commit
|
|
17
|
+
*/
|
|
18
|
+
getCommitDiff(commitHash: string): Promise<string>;
|
|
19
|
+
/**
|
|
20
|
+
* Get the diff between the last two commits (HEAD~1 and HEAD)
|
|
21
|
+
* This ensures we see the actual content of the most recent commit
|
|
22
|
+
*/
|
|
23
|
+
getLatestCommitDiff(): Promise<string>;
|
|
24
|
+
/**
|
|
25
|
+
* Get diff for a range of commits (from commit hash to HEAD)
|
|
26
|
+
* This handles cases where multiple commits happened and need to be processed together
|
|
27
|
+
*/
|
|
28
|
+
getCommitRangeDiff(fromCommit: string, toCommit: string): Promise<string>;
|
|
29
|
+
/**
|
|
30
|
+
* Get unstaged changes (working directory diff)
|
|
31
|
+
*/
|
|
32
|
+
getUnstagedDiff(): Promise<string>;
|
|
33
|
+
/**
|
|
34
|
+
* Get oneline log (last N commits or since date)
|
|
35
|
+
*/
|
|
36
|
+
getOnelineLog(limit: number, since?: string): Promise<OnelineCommit[]>;
|
|
37
|
+
/**
|
|
38
|
+
* Get current HEAD commit hash
|
|
39
|
+
*/
|
|
40
|
+
getHeadCommit(): Promise<string>;
|
|
41
|
+
/**
|
|
42
|
+
* Get current branch name
|
|
43
|
+
*/
|
|
44
|
+
getCurrentBranch(): Promise<string>;
|
|
45
|
+
/**
|
|
46
|
+
* Get file structure as a tree-like string
|
|
47
|
+
*/
|
|
48
|
+
getFileStructure(): Promise<string>;
|
|
49
|
+
/**
|
|
50
|
+
* Check if a file is in .gitignore
|
|
51
|
+
*/
|
|
52
|
+
isInGitignore(filePath: string): Promise<boolean>;
|
|
53
|
+
/**
|
|
54
|
+
* Remove a file pattern from .gitignore
|
|
55
|
+
*/
|
|
56
|
+
removeFromGitignore(filePath: string): Promise<void>;
|
|
57
|
+
/**
|
|
58
|
+
* Stage a file
|
|
59
|
+
* Automatically removes the file from .gitignore if it's currently ignored
|
|
60
|
+
*/
|
|
61
|
+
stageFile(filePath: string): Promise<void>;
|
|
62
|
+
/**
|
|
63
|
+
* Check if content has Git conflict markers
|
|
64
|
+
*/
|
|
65
|
+
hasConflictMarkers(content: string): boolean;
|
|
66
|
+
/**
|
|
67
|
+
* Read README.md if it exists
|
|
68
|
+
*/
|
|
69
|
+
readReadme(): Promise<string | null>;
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=git.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../../src/utils/git.ts"],"names":[],"mappings":"AAAA,OAAO,EAAwB,SAAS,EAAE,MAAM,YAAY,CAAC;AAI7D,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,qBAAa,QAAQ;IACnB,OAAO,CAAC,GAAG,CAAY;IACvB,OAAO,CAAC,QAAQ,CAAS;gBAEb,QAAQ,GAAE,MAAsB;IAK5C;;OAEG;IACG,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IAKhE;;OAEG;IACG,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IASxD;;;OAGG;IACG,mBAAmB,IAAI,OAAO,CAAC,MAAM,CAAC;IAa5C;;;OAGG;IACG,kBAAkB,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAU/E;;OAEG;IACG,eAAe,IAAI,OAAO,CAAC,MAAM,CAAC;IASxC;;OAEG;IACG,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC;IAyD5E;;OAEG;IACG,aAAa,IAAI,OAAO,CAAC,MAAM,CAAC;IAQtC;;OAEG;IACG,gBAAgB,IAAI,OAAO,CAAC,MAAM,CAAC;IAoBzC;;OAEG;IACG,gBAAgB,IAAI,OAAO,CAAC,MAAM,CAAC;IA0CzC;;OAEG;IACG,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IA0BvD;;OAEG;IACG,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAmB1D;;;OAGG;IACG,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAYhD;;OAEG;IACH,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAI5C;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;CAe3C"}
|