@dollhousemcp/mcp-server 1.4.0 → 1.4.2
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 +54 -9
- package/dist/config/updateConfig.d.ts +84 -0
- package/dist/config/updateConfig.d.ts.map +1 -0
- package/dist/config/updateConfig.js +148 -0
- package/dist/generated/version.d.ts +9 -0
- package/dist/generated/version.d.ts.map +1 -0
- package/dist/generated/version.js +9 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +34 -6
- package/dist/portfolio/DefaultElementProvider.d.ts +78 -0
- package/dist/portfolio/DefaultElementProvider.d.ts.map +1 -0
- package/dist/portfolio/DefaultElementProvider.js +398 -0
- package/dist/portfolio/PortfolioManager.d.ts +7 -0
- package/dist/portfolio/PortfolioManager.d.ts.map +1 -1
- package/dist/portfolio/PortfolioManager.js +44 -3
- package/dist/security/commandValidator.d.ts.map +1 -1
- package/dist/security/commandValidator.js +5 -2
- package/dist/security/securityMonitor.d.ts +2 -1
- package/dist/security/securityMonitor.d.ts.map +1 -1
- package/dist/security/securityMonitor.js +1 -1
- package/dist/server/tools/UpdateTools.d.ts.map +1 -1
- package/dist/server/tools/UpdateTools.js +22 -1
- package/dist/server/types.d.ts +1 -0
- package/dist/server/types.d.ts.map +1 -1
- package/dist/server/types.js +1 -1
- package/dist/update/BackupManager.d.ts +17 -0
- package/dist/update/BackupManager.d.ts.map +1 -1
- package/dist/update/BackupManager.js +112 -3
- package/dist/update/UpdateManager.d.ts +19 -0
- package/dist/update/UpdateManager.d.ts.map +1 -1
- package/dist/update/UpdateManager.js +485 -15
- package/dist/update/VersionManager.d.ts +1 -1
- package/dist/update/VersionManager.d.ts.map +1 -1
- package/dist/update/VersionManager.js +62 -15
- package/dist/utils/fileOperations.d.ts +83 -0
- package/dist/utils/fileOperations.d.ts.map +1 -0
- package/dist/utils/fileOperations.js +291 -0
- package/dist/utils/installation.d.ts +30 -0
- package/dist/utils/installation.d.ts.map +1 -0
- package/dist/utils/installation.js +160 -0
- package/package.json +3 -1
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DefaultElementProvider - Populates portfolio with default elements from bundled data
|
|
3
|
+
*
|
|
4
|
+
* This class handles copying default personas, skills, templates, and other elements
|
|
5
|
+
* from the NPM package or Git repository to the user's portfolio on first run.
|
|
6
|
+
* It ensures users have example content to work with immediately after installation.
|
|
7
|
+
*/
|
|
8
|
+
export declare const FILE_CONSTANTS: {
|
|
9
|
+
readonly ELEMENT_EXTENSION: ".md";
|
|
10
|
+
readonly YAML_EXTENSION: ".yaml";
|
|
11
|
+
readonly YML_EXTENSION: ".yml";
|
|
12
|
+
readonly JSON_EXTENSION: ".json";
|
|
13
|
+
readonly MAX_FILE_SIZE: number;
|
|
14
|
+
readonly CHECKSUM_ALGORITHM: "sha256";
|
|
15
|
+
readonly FILE_PERMISSIONS: 420;
|
|
16
|
+
readonly CHUNK_SIZE: number;
|
|
17
|
+
};
|
|
18
|
+
export interface DefaultElementProviderConfig {
|
|
19
|
+
/** Custom data directory paths to search (checked before default paths) */
|
|
20
|
+
customDataPaths?: string[];
|
|
21
|
+
/** Whether to use default search paths after custom paths */
|
|
22
|
+
useDefaultPaths?: boolean;
|
|
23
|
+
}
|
|
24
|
+
export declare class DefaultElementProvider {
|
|
25
|
+
private readonly __dirname;
|
|
26
|
+
private static cachedDataDir;
|
|
27
|
+
private static populateInProgress;
|
|
28
|
+
private readonly config;
|
|
29
|
+
constructor(config?: DefaultElementProviderConfig);
|
|
30
|
+
/**
|
|
31
|
+
* Search paths for bundled data directory
|
|
32
|
+
* Ordered by priority - custom paths first, then development/git, then NPM locations
|
|
33
|
+
*/
|
|
34
|
+
private get dataSearchPaths();
|
|
35
|
+
/**
|
|
36
|
+
* Find the bundled data directory by checking each search path
|
|
37
|
+
* Uses Promise.allSettled for better performance and caches the result
|
|
38
|
+
*/
|
|
39
|
+
private findDataDirectory;
|
|
40
|
+
/**
|
|
41
|
+
* Helper to check if a directory exists
|
|
42
|
+
*/
|
|
43
|
+
private directoryExists;
|
|
44
|
+
/**
|
|
45
|
+
* Copy all files from source directory to destination directory
|
|
46
|
+
* Skips files that already exist to preserve user modifications
|
|
47
|
+
*/
|
|
48
|
+
private copyElementFiles;
|
|
49
|
+
/**
|
|
50
|
+
* Copy a file with integrity verification
|
|
51
|
+
* Ensures the file was copied correctly by comparing sizes
|
|
52
|
+
*/
|
|
53
|
+
/**
|
|
54
|
+
* Calculate checksum of a file for integrity verification
|
|
55
|
+
* @param filePath Path to the file
|
|
56
|
+
* @returns Hex-encoded checksum
|
|
57
|
+
*/
|
|
58
|
+
private calculateChecksum;
|
|
59
|
+
/**
|
|
60
|
+
* Copy file with integrity verification and retry logic
|
|
61
|
+
* @param sourcePath Source file path
|
|
62
|
+
* @param destPath Destination file path
|
|
63
|
+
* @throws Error if copy fails after all retry attempts
|
|
64
|
+
*/
|
|
65
|
+
private copyFileWithVerification;
|
|
66
|
+
/**
|
|
67
|
+
* Populate the portfolio with default elements from bundled data
|
|
68
|
+
* This is called during portfolio initialization for new installations
|
|
69
|
+
* Protected against concurrent calls to prevent race conditions
|
|
70
|
+
*/
|
|
71
|
+
populateDefaults(portfolioBaseDir: string): Promise<void>;
|
|
72
|
+
/**
|
|
73
|
+
* Perform the actual population of default elements
|
|
74
|
+
* @param portfolioBaseDir Base directory of the portfolio
|
|
75
|
+
*/
|
|
76
|
+
private performPopulation;
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=DefaultElementProvider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DefaultElementProvider.d.ts","sourceRoot":"","sources":["../../src/portfolio/DefaultElementProvider.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAYH,eAAO,MAAM,cAAc;;;;;;;;;CASjB,CAAC;AAOX,MAAM,WAAW,4BAA4B;IAC3C,2EAA2E;IAC3E,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,6DAA6D;IAC7D,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,qBAAa,sBAAsB;IACjC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,MAAM,CAAC,aAAa,CAAuB;IACnD,OAAO,CAAC,MAAM,CAAC,kBAAkB,CAAyC;IAC1E,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA+B;gBAE1C,MAAM,CAAC,EAAE,4BAA4B;IASjD;;;OAGG;IACH,OAAO,KAAK,eAAe,GAmC1B;IAED;;;OAGG;YACW,iBAAiB;IAyC/B;;OAEG;YACW,eAAe;IAS7B;;;OAGG;YACW,gBAAgB;IAmG9B;;;OAGG;IACH;;;;OAIG;YACW,iBAAiB;IAuB/B;;;;;OAKG;YACW,wBAAwB;IA8EtC;;;;OAIG;IACU,gBAAgB,CAAC,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAsBtE;;;OAGG;YACW,iBAAiB;CAwFhC"}
|
|
@@ -0,0 +1,398 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DefaultElementProvider - Populates portfolio with default elements from bundled data
|
|
3
|
+
*
|
|
4
|
+
* This class handles copying default personas, skills, templates, and other elements
|
|
5
|
+
* from the NPM package or Git repository to the user's portfolio on first run.
|
|
6
|
+
* It ensures users have example content to work with immediately after installation.
|
|
7
|
+
*/
|
|
8
|
+
import * as fs from 'fs/promises';
|
|
9
|
+
import * as path from 'path';
|
|
10
|
+
import { fileURLToPath } from 'url';
|
|
11
|
+
import { createHash } from 'crypto';
|
|
12
|
+
import { logger } from '../utils/logger.js';
|
|
13
|
+
import { ElementType } from './types.js';
|
|
14
|
+
import { UnicodeValidator } from '../security/validators/unicodeValidator.js';
|
|
15
|
+
import { SecurityMonitor } from '../security/securityMonitor.js';
|
|
16
|
+
// File operation constants
|
|
17
|
+
export const FILE_CONSTANTS = {
|
|
18
|
+
ELEMENT_EXTENSION: '.md',
|
|
19
|
+
YAML_EXTENSION: '.yaml',
|
|
20
|
+
YML_EXTENSION: '.yml',
|
|
21
|
+
JSON_EXTENSION: '.json',
|
|
22
|
+
MAX_FILE_SIZE: 10 * 1024 * 1024, // 10MB max file size for safety
|
|
23
|
+
CHECKSUM_ALGORITHM: 'sha256',
|
|
24
|
+
FILE_PERMISSIONS: 0o644,
|
|
25
|
+
CHUNK_SIZE: 64 * 1024 // 64KB chunks for reading large files
|
|
26
|
+
};
|
|
27
|
+
// Internal constants
|
|
28
|
+
const DATA_DIR_CACHE_KEY = 'dollhouse_data_dir';
|
|
29
|
+
const COPY_RETRY_ATTEMPTS = 3;
|
|
30
|
+
const COPY_RETRY_DELAY = 100; // ms
|
|
31
|
+
export class DefaultElementProvider {
|
|
32
|
+
__dirname;
|
|
33
|
+
static cachedDataDir = null;
|
|
34
|
+
static populateInProgress = new Map();
|
|
35
|
+
config;
|
|
36
|
+
constructor(config) {
|
|
37
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
38
|
+
this.__dirname = path.dirname(__filename);
|
|
39
|
+
this.config = {
|
|
40
|
+
useDefaultPaths: true,
|
|
41
|
+
...config
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Search paths for bundled data directory
|
|
46
|
+
* Ordered by priority - custom paths first, then development/git, then NPM locations
|
|
47
|
+
*/
|
|
48
|
+
get dataSearchPaths() {
|
|
49
|
+
const paths = [];
|
|
50
|
+
// Add custom paths first (highest priority)
|
|
51
|
+
if (this.config.customDataPaths) {
|
|
52
|
+
paths.push(...this.config.customDataPaths);
|
|
53
|
+
}
|
|
54
|
+
// Add default paths if enabled
|
|
55
|
+
if (this.config.useDefaultPaths !== false) {
|
|
56
|
+
paths.push(
|
|
57
|
+
// Development/Git installation (relative to this file)
|
|
58
|
+
path.join(this.__dirname, '../../data'), path.join(this.__dirname, '../../../data'),
|
|
59
|
+
// NPM installations - macOS Homebrew
|
|
60
|
+
'/opt/homebrew/lib/node_modules/@dollhousemcp/mcp-server/data',
|
|
61
|
+
// NPM installations - standard Unix/Linux
|
|
62
|
+
'/usr/local/lib/node_modules/@dollhousemcp/mcp-server/data', '/usr/lib/node_modules/@dollhousemcp/mcp-server/data',
|
|
63
|
+
// NPM installations - Windows
|
|
64
|
+
'C:\\Program Files\\nodejs\\node_modules\\@dollhousemcp\\mcp-server\\data', 'C:\\Program Files (x86)\\nodejs\\node_modules\\@dollhousemcp\\mcp-server\\data',
|
|
65
|
+
// NPM installations - Windows with nvm
|
|
66
|
+
path.join(process.env.APPDATA || '', 'npm', 'node_modules', '@dollhousemcp', 'mcp-server', 'data'),
|
|
67
|
+
// Current working directory (last resort)
|
|
68
|
+
path.join(process.cwd(), 'data'));
|
|
69
|
+
}
|
|
70
|
+
return paths;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Find the bundled data directory by checking each search path
|
|
74
|
+
* Uses Promise.allSettled for better performance and caches the result
|
|
75
|
+
*/
|
|
76
|
+
async findDataDirectory() {
|
|
77
|
+
// Return cached value if available
|
|
78
|
+
if (DefaultElementProvider.cachedDataDir !== null) {
|
|
79
|
+
return DefaultElementProvider.cachedDataDir;
|
|
80
|
+
}
|
|
81
|
+
// Check all paths in parallel for better performance
|
|
82
|
+
const checkPromises = this.dataSearchPaths.map(async (searchPath) => {
|
|
83
|
+
try {
|
|
84
|
+
const stats = await fs.stat(searchPath);
|
|
85
|
+
if (stats.isDirectory()) {
|
|
86
|
+
// Verify it contains expected subdirectories
|
|
87
|
+
const hasPersonas = await this.directoryExists(path.join(searchPath, 'personas'));
|
|
88
|
+
const hasSkills = await this.directoryExists(path.join(searchPath, 'skills'));
|
|
89
|
+
if (hasPersonas || hasSkills) {
|
|
90
|
+
return searchPath;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
catch (error) {
|
|
95
|
+
// Directory doesn't exist or can't be accessed
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
return null;
|
|
99
|
+
});
|
|
100
|
+
const results = await Promise.allSettled(checkPromises);
|
|
101
|
+
// Find the first successful result
|
|
102
|
+
for (const result of results) {
|
|
103
|
+
if (result.status === 'fulfilled' && result.value !== null) {
|
|
104
|
+
logger.info(`[DefaultElementProvider] Found data directory at: ${result.value}`);
|
|
105
|
+
// Cache the result
|
|
106
|
+
DefaultElementProvider.cachedDataDir = result.value;
|
|
107
|
+
return result.value;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
logger.warn('[DefaultElementProvider] No bundled data directory found in any search path');
|
|
111
|
+
return null;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Helper to check if a directory exists
|
|
115
|
+
*/
|
|
116
|
+
async directoryExists(dirPath) {
|
|
117
|
+
try {
|
|
118
|
+
const stats = await fs.stat(dirPath);
|
|
119
|
+
return stats.isDirectory();
|
|
120
|
+
}
|
|
121
|
+
catch {
|
|
122
|
+
return false;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Copy all files from source directory to destination directory
|
|
127
|
+
* Skips files that already exist to preserve user modifications
|
|
128
|
+
*/
|
|
129
|
+
async copyElementFiles(sourceDir, destDir, elementType) {
|
|
130
|
+
let copiedCount = 0;
|
|
131
|
+
try {
|
|
132
|
+
// Ensure destination directory exists
|
|
133
|
+
await fs.mkdir(destDir, { recursive: true });
|
|
134
|
+
// Read source directory
|
|
135
|
+
const files = await fs.readdir(sourceDir);
|
|
136
|
+
for (const file of files) {
|
|
137
|
+
// Only copy markdown files
|
|
138
|
+
if (!file.endsWith(FILE_CONSTANTS.ELEMENT_EXTENSION)) {
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
// Normalize filename for security
|
|
142
|
+
const normalizedFile = UnicodeValidator.normalize(file);
|
|
143
|
+
if (!normalizedFile.isValid) {
|
|
144
|
+
logger.warn(`[DefaultElementProvider] Skipping file with invalid Unicode: ${file}`);
|
|
145
|
+
continue;
|
|
146
|
+
}
|
|
147
|
+
const sourcePath = path.join(sourceDir, normalizedFile.normalizedContent);
|
|
148
|
+
const destPath = path.join(destDir, normalizedFile.normalizedContent);
|
|
149
|
+
try {
|
|
150
|
+
// Check if destination file already exists
|
|
151
|
+
await fs.access(destPath);
|
|
152
|
+
logger.debug(`[DefaultElementProvider] Skipping existing file: ${normalizedFile.normalizedContent}`);
|
|
153
|
+
continue;
|
|
154
|
+
}
|
|
155
|
+
catch {
|
|
156
|
+
// File doesn't exist, proceed with copy
|
|
157
|
+
}
|
|
158
|
+
try {
|
|
159
|
+
// Validate source file before copying
|
|
160
|
+
const sourceStats = await fs.stat(sourcePath);
|
|
161
|
+
// Check file size limit
|
|
162
|
+
if (sourceStats.size > FILE_CONSTANTS.MAX_FILE_SIZE) {
|
|
163
|
+
logger.warn(`[DefaultElementProvider] Skipping oversized file ${normalizedFile.normalizedContent}: ` +
|
|
164
|
+
`${sourceStats.size} bytes (max: ${FILE_CONSTANTS.MAX_FILE_SIZE} bytes)`, {
|
|
165
|
+
file: normalizedFile.normalizedContent,
|
|
166
|
+
size: sourceStats.size,
|
|
167
|
+
maxSize: FILE_CONSTANTS.MAX_FILE_SIZE,
|
|
168
|
+
elementType
|
|
169
|
+
});
|
|
170
|
+
continue;
|
|
171
|
+
}
|
|
172
|
+
// Copy the file with verification
|
|
173
|
+
await this.copyFileWithVerification(sourcePath, destPath);
|
|
174
|
+
copiedCount++;
|
|
175
|
+
logger.debug(`[DefaultElementProvider] Copied ${elementType}: ${normalizedFile.normalizedContent}`);
|
|
176
|
+
// Log security event for each file copied
|
|
177
|
+
SecurityMonitor.logSecurityEvent({
|
|
178
|
+
type: 'FILE_COPIED',
|
|
179
|
+
severity: 'LOW',
|
|
180
|
+
source: 'DefaultElementProvider.copyElementFiles',
|
|
181
|
+
details: `Copied default ${elementType} file: ${normalizedFile.normalizedContent}`,
|
|
182
|
+
metadata: {
|
|
183
|
+
sourcePath,
|
|
184
|
+
destPath,
|
|
185
|
+
elementType,
|
|
186
|
+
fileSize: (await fs.stat(destPath)).size
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
catch (error) {
|
|
191
|
+
const err = error;
|
|
192
|
+
logger.error(`[DefaultElementProvider] Failed to copy ${normalizedFile.normalizedContent}`, {
|
|
193
|
+
error: err.message,
|
|
194
|
+
stack: err.stack,
|
|
195
|
+
sourcePath,
|
|
196
|
+
destPath,
|
|
197
|
+
elementType
|
|
198
|
+
});
|
|
199
|
+
// Continue with other files instead of failing completely
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
if (copiedCount > 0) {
|
|
203
|
+
logger.info(`[DefaultElementProvider] Copied ${copiedCount} ${elementType} file(s)`);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
catch (error) {
|
|
207
|
+
logger.error(`[DefaultElementProvider] Error copying ${elementType} files:`, error);
|
|
208
|
+
}
|
|
209
|
+
return copiedCount;
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Copy a file with integrity verification
|
|
213
|
+
* Ensures the file was copied correctly by comparing sizes
|
|
214
|
+
*/
|
|
215
|
+
/**
|
|
216
|
+
* Calculate checksum of a file for integrity verification
|
|
217
|
+
* @param filePath Path to the file
|
|
218
|
+
* @returns Hex-encoded checksum
|
|
219
|
+
*/
|
|
220
|
+
async calculateChecksum(filePath) {
|
|
221
|
+
const hash = createHash(FILE_CONSTANTS.CHECKSUM_ALGORITHM);
|
|
222
|
+
const stream = await fs.open(filePath, 'r');
|
|
223
|
+
try {
|
|
224
|
+
const buffer = Buffer.alloc(FILE_CONSTANTS.CHUNK_SIZE);
|
|
225
|
+
let bytesRead;
|
|
226
|
+
do {
|
|
227
|
+
const result = await stream.read(buffer, 0, FILE_CONSTANTS.CHUNK_SIZE);
|
|
228
|
+
bytesRead = result.bytesRead;
|
|
229
|
+
if (bytesRead > 0) {
|
|
230
|
+
hash.update(buffer.subarray(0, bytesRead));
|
|
231
|
+
}
|
|
232
|
+
} while (bytesRead > 0);
|
|
233
|
+
return hash.digest('hex');
|
|
234
|
+
}
|
|
235
|
+
finally {
|
|
236
|
+
await stream.close();
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Copy file with integrity verification and retry logic
|
|
241
|
+
* @param sourcePath Source file path
|
|
242
|
+
* @param destPath Destination file path
|
|
243
|
+
* @throws Error if copy fails after all retry attempts
|
|
244
|
+
*/
|
|
245
|
+
async copyFileWithVerification(sourcePath, destPath) {
|
|
246
|
+
let lastError = null;
|
|
247
|
+
for (let attempt = 1; attempt <= COPY_RETRY_ATTEMPTS; attempt++) {
|
|
248
|
+
try {
|
|
249
|
+
// Copy the file
|
|
250
|
+
await fs.copyFile(sourcePath, destPath);
|
|
251
|
+
// Verify size matches
|
|
252
|
+
const [sourceStats, destStats] = await Promise.all([
|
|
253
|
+
fs.stat(sourcePath),
|
|
254
|
+
fs.stat(destPath)
|
|
255
|
+
]);
|
|
256
|
+
if (sourceStats.size !== destStats.size) {
|
|
257
|
+
throw new Error(`Size mismatch after copy - source: ${sourceStats.size} bytes, ` +
|
|
258
|
+
`destination: ${destStats.size} bytes`);
|
|
259
|
+
}
|
|
260
|
+
// Verify checksum matches for complete integrity
|
|
261
|
+
const [sourceChecksum, destChecksum] = await Promise.all([
|
|
262
|
+
this.calculateChecksum(sourcePath),
|
|
263
|
+
this.calculateChecksum(destPath)
|
|
264
|
+
]);
|
|
265
|
+
if (sourceChecksum !== destChecksum) {
|
|
266
|
+
throw new Error(`Checksum mismatch after copy - source: ${sourceChecksum}, ` +
|
|
267
|
+
`destination: ${destChecksum}`);
|
|
268
|
+
}
|
|
269
|
+
// Set proper permissions
|
|
270
|
+
try {
|
|
271
|
+
await fs.chmod(destPath, FILE_CONSTANTS.FILE_PERMISSIONS);
|
|
272
|
+
}
|
|
273
|
+
catch (error) {
|
|
274
|
+
logger.debug(`[DefaultElementProvider] Could not set permissions on ${destPath}: ${error}`, { sourcePath, destPath, attempt });
|
|
275
|
+
}
|
|
276
|
+
// Success - file copied and verified
|
|
277
|
+
logger.debug(`[DefaultElementProvider] Successfully copied and verified: ${path.basename(sourcePath)}`, { size: sourceStats.size, checksum: sourceChecksum.substring(0, 8) });
|
|
278
|
+
return;
|
|
279
|
+
}
|
|
280
|
+
catch (error) {
|
|
281
|
+
lastError = error;
|
|
282
|
+
// Clean up failed copy
|
|
283
|
+
try {
|
|
284
|
+
await fs.unlink(destPath);
|
|
285
|
+
}
|
|
286
|
+
catch {
|
|
287
|
+
// Ignore cleanup errors
|
|
288
|
+
}
|
|
289
|
+
if (attempt < COPY_RETRY_ATTEMPTS) {
|
|
290
|
+
logger.debug(`[DefaultElementProvider] Copy attempt ${attempt} failed, retrying...`, { error: lastError.message, sourcePath, destPath });
|
|
291
|
+
await new Promise(resolve => setTimeout(resolve, COPY_RETRY_DELAY * attempt));
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
// All attempts failed
|
|
296
|
+
throw new Error(`Failed to copy ${path.basename(sourcePath)} after ${COPY_RETRY_ATTEMPTS} attempts: ` +
|
|
297
|
+
`${lastError?.message || 'Unknown error'}`);
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* Populate the portfolio with default elements from bundled data
|
|
301
|
+
* This is called during portfolio initialization for new installations
|
|
302
|
+
* Protected against concurrent calls to prevent race conditions
|
|
303
|
+
*/
|
|
304
|
+
async populateDefaults(portfolioBaseDir) {
|
|
305
|
+
// Check if population is already in progress for this portfolio
|
|
306
|
+
const existingPopulation = DefaultElementProvider.populateInProgress.get(portfolioBaseDir);
|
|
307
|
+
if (existingPopulation) {
|
|
308
|
+
logger.debug('[DefaultElementProvider] Population already in progress for portfolio, waiting...', { portfolioBaseDir });
|
|
309
|
+
return existingPopulation;
|
|
310
|
+
}
|
|
311
|
+
// Create new population promise
|
|
312
|
+
const populationPromise = this.performPopulation(portfolioBaseDir)
|
|
313
|
+
.finally(() => {
|
|
314
|
+
// Clean up when done
|
|
315
|
+
DefaultElementProvider.populateInProgress.delete(portfolioBaseDir);
|
|
316
|
+
});
|
|
317
|
+
DefaultElementProvider.populateInProgress.set(portfolioBaseDir, populationPromise);
|
|
318
|
+
return populationPromise;
|
|
319
|
+
}
|
|
320
|
+
/**
|
|
321
|
+
* Perform the actual population of default elements
|
|
322
|
+
* @param portfolioBaseDir Base directory of the portfolio
|
|
323
|
+
*/
|
|
324
|
+
async performPopulation(portfolioBaseDir) {
|
|
325
|
+
logger.info('[DefaultElementProvider] Starting default element population', { portfolioBaseDir });
|
|
326
|
+
// Log security event for portfolio initialization
|
|
327
|
+
SecurityMonitor.logSecurityEvent({
|
|
328
|
+
type: 'PORTFOLIO_INITIALIZATION',
|
|
329
|
+
severity: 'LOW',
|
|
330
|
+
source: 'DefaultElementProvider.performPopulation',
|
|
331
|
+
details: `Starting default element population for portfolio: ${portfolioBaseDir}`
|
|
332
|
+
});
|
|
333
|
+
// Find the bundled data directory
|
|
334
|
+
const dataDir = await this.findDataDirectory();
|
|
335
|
+
if (!dataDir) {
|
|
336
|
+
logger.warn('[DefaultElementProvider] No bundled data directory found - portfolio will start empty', {
|
|
337
|
+
searchPaths: this.dataSearchPaths.slice(0, 3), // Log first few paths for debugging
|
|
338
|
+
cwd: process.cwd(),
|
|
339
|
+
dirname: this.__dirname
|
|
340
|
+
});
|
|
341
|
+
return;
|
|
342
|
+
}
|
|
343
|
+
// Track total files copied
|
|
344
|
+
let totalCopied = 0;
|
|
345
|
+
const copiedCounts = {};
|
|
346
|
+
// Map of data subdirectory names (plural) to portfolio directory names (singular)
|
|
347
|
+
const elementMappings = {
|
|
348
|
+
'personas': ElementType.PERSONA,
|
|
349
|
+
'skills': ElementType.SKILL,
|
|
350
|
+
'templates': ElementType.TEMPLATE,
|
|
351
|
+
'agents': ElementType.AGENT,
|
|
352
|
+
'memories': ElementType.MEMORY,
|
|
353
|
+
'ensembles': ElementType.ENSEMBLE
|
|
354
|
+
};
|
|
355
|
+
// Copy each element type
|
|
356
|
+
for (const [dataSubdir, elementType] of Object.entries(elementMappings)) {
|
|
357
|
+
const sourceDir = path.join(dataDir, dataSubdir);
|
|
358
|
+
const destDir = path.join(portfolioBaseDir, elementType);
|
|
359
|
+
try {
|
|
360
|
+
// Check if source directory exists
|
|
361
|
+
await fs.access(sourceDir);
|
|
362
|
+
const copiedCount = await this.copyElementFiles(sourceDir, destDir, dataSubdir);
|
|
363
|
+
copiedCounts[dataSubdir] = copiedCount;
|
|
364
|
+
totalCopied += copiedCount;
|
|
365
|
+
}
|
|
366
|
+
catch (error) {
|
|
367
|
+
// Source directory doesn't exist, skip
|
|
368
|
+
logger.debug(`[DefaultElementProvider] No ${dataSubdir} directory in bundled data`);
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
if (totalCopied > 0) {
|
|
372
|
+
logger.info(`[DefaultElementProvider] Successfully populated portfolio with ${totalCopied} default element(s)`, {
|
|
373
|
+
portfolioBaseDir,
|
|
374
|
+
dataDir,
|
|
375
|
+
breakdown: Object.entries(elementMappings).reduce((acc, [dataDir, elementType]) => {
|
|
376
|
+
acc[elementType] = copiedCounts[dataDir] || 0;
|
|
377
|
+
return acc;
|
|
378
|
+
}, {})
|
|
379
|
+
});
|
|
380
|
+
// Log security event for successful population
|
|
381
|
+
SecurityMonitor.logSecurityEvent({
|
|
382
|
+
type: 'PORTFOLIO_POPULATED',
|
|
383
|
+
severity: 'LOW',
|
|
384
|
+
source: 'DefaultElementProvider.performPopulation',
|
|
385
|
+
details: `Successfully populated portfolio with ${totalCopied} default elements`,
|
|
386
|
+
metadata: {
|
|
387
|
+
portfolioBaseDir,
|
|
388
|
+
dataDir,
|
|
389
|
+
copiedCounts
|
|
390
|
+
}
|
|
391
|
+
});
|
|
392
|
+
}
|
|
393
|
+
else {
|
|
394
|
+
logger.info('[DefaultElementProvider] No new elements to copy - portfolio may already have content');
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiRGVmYXVsdEVsZW1lbnRQcm92aWRlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9wb3J0Zm9saW8vRGVmYXVsdEVsZW1lbnRQcm92aWRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7O0dBTUc7QUFFSCxPQUFPLEtBQUssRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUNsQyxPQUFPLEtBQUssSUFBSSxNQUFNLE1BQU0sQ0FBQztBQUM3QixPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sS0FBSyxDQUFDO0FBQ3BDLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxRQUFRLENBQUM7QUFDcEMsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQzVDLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxZQUFZLENBQUM7QUFDekMsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sNENBQTRDLENBQUM7QUFDOUUsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLGdDQUFnQyxDQUFDO0FBRWpFLDJCQUEyQjtBQUMzQixNQUFNLENBQUMsTUFBTSxjQUFjLEdBQUc7SUFDNUIsaUJBQWlCLEVBQUUsS0FBSztJQUN4QixjQUFjLEVBQUUsT0FBTztJQUN2QixhQUFhLEVBQUUsTUFBTTtJQUNyQixjQUFjLEVBQUUsT0FBTztJQUN2QixhQUFhLEVBQUUsRUFBRSxHQUFHLElBQUksR0FBRyxJQUFJLEVBQUUsZ0NBQWdDO0lBQ2pFLGtCQUFrQixFQUFFLFFBQVE7SUFDNUIsZ0JBQWdCLEVBQUUsS0FBSztJQUN2QixVQUFVLEVBQUUsRUFBRSxHQUFHLElBQUksQ0FBQyxzQ0FBc0M7Q0FDcEQsQ0FBQztBQUVYLHFCQUFxQjtBQUNyQixNQUFNLGtCQUFrQixHQUFHLG9CQUFvQixDQUFDO0FBQ2hELE1BQU0sbUJBQW1CLEdBQUcsQ0FBQyxDQUFDO0FBQzlCLE1BQU0sZ0JBQWdCLEdBQUcsR0FBRyxDQUFDLENBQUMsS0FBSztBQVNuQyxNQUFNLE9BQU8sc0JBQXNCO0lBQ2hCLFNBQVMsQ0FBUztJQUMzQixNQUFNLENBQUMsYUFBYSxHQUFrQixJQUFJLENBQUM7SUFDM0MsTUFBTSxDQUFDLGtCQUFrQixHQUErQixJQUFJLEdBQUcsRUFBRSxDQUFDO0lBQ3pELE1BQU0sQ0FBK0I7SUFFdEQsWUFBWSxNQUFxQztRQUMvQyxNQUFNLFVBQVUsR0FBRyxhQUFhLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUNsRCxJQUFJLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDLENBQUM7UUFDMUMsSUFBSSxDQUFDLE1BQU0sR0FBRztZQUNaLGVBQWUsRUFBRSxJQUFJO1lBQ3JCLEdBQUcsTUFBTTtTQUNWLENBQUM7SUFDSixDQUFDO0lBRUQ7OztPQUdHO0lBQ0gsSUFBWSxlQUFlO1FBQ3pCLE1BQU0sS0FBSyxHQUFhLEVBQUUsQ0FBQztRQUUzQiw0Q0FBNEM7UUFDNUMsSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLGVBQWUsRUFBRSxDQUFDO1lBQ2hDLEtBQUssQ0FBQyxJQUFJLENBQUMsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLGVBQWUsQ0FBQyxDQUFDO1FBQzdDLENBQUM7UUFFRCwrQkFBK0I7UUFDL0IsSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLGVBQWUsS0FBSyxLQUFLLEVBQUUsQ0FBQztZQUMxQyxLQUFLLENBQUMsSUFBSTtZQUNSLHVEQUF1RDtZQUN2RCxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsWUFBWSxDQUFDLEVBQ3ZDLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxlQUFlLENBQUM7WUFFMUMscUNBQXFDO1lBQ3JDLDhEQUE4RDtZQUU5RCwwQ0FBMEM7WUFDMUMsMkRBQTJELEVBQzNELHFEQUFxRDtZQUVyRCw4QkFBOEI7WUFDOUIsMEVBQTBFLEVBQzFFLGdGQUFnRjtZQUVoRix1Q0FBdUM7WUFDdkMsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLE9BQU8sSUFBSSxFQUFFLEVBQUUsS0FBSyxFQUFFLGNBQWMsRUFBRSxlQUFlLEVBQUUsWUFBWSxFQUFFLE1BQU0sQ0FBQztZQUVsRywwQ0FBMEM7WUFDMUMsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxFQUFFLEVBQUUsTUFBTSxDQUFDLENBQ2pDLENBQUM7UUFDSixDQUFDO1FBRUQsT0FBTyxLQUFLLENBQUM7SUFDZixDQUFDO0lBRUQ7OztPQUdHO0lBQ0ssS0FBSyxDQUFDLGlCQUFpQjtRQUM3QixtQ0FBbUM7UUFDbkMsSUFBSSxzQkFBc0IsQ0FBQyxhQUFhLEtBQUssSUFBSSxFQUFFLENBQUM7WUFDbEQsT0FBTyxzQkFBc0IsQ0FBQyxhQUFhLENBQUM7UUFDOUMsQ0FBQztRQUVELHFEQUFxRDtRQUNyRCxNQUFNLGFBQWEsR0FBRyxJQUFJLENBQUMsZUFBZSxDQUFDLEdBQUcsQ0FBQyxLQUFLLEVBQUUsVUFBVSxFQUFFLEVBQUU7WUFDbEUsSUFBSSxDQUFDO2dCQUNILE1BQU0sS0FBSyxHQUFHLE1BQU0sRUFBRSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQztnQkFDeEMsSUFBSSxLQUFLLENBQUMsV0FBVyxFQUFFLEVBQUUsQ0FBQztvQkFDeEIsNkNBQTZDO29CQUM3QyxNQUFNLFdBQVcsR0FBRyxNQUFNLElBQUksQ0FBQyxlQUFlLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxVQUFVLEVBQUUsVUFBVSxDQUFDLENBQUMsQ0FBQztvQkFDbEYsTUFBTSxTQUFTLEdBQUcsTUFBTSxJQUFJLENBQUMsZUFBZSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsVUFBVSxFQUFFLFFBQVEsQ0FBQyxDQUFDLENBQUM7b0JBQzlFLElBQUksV0FBVyxJQUFJLFNBQVMsRUFBRSxDQUFDO3dCQUM3QixPQUFPLFVBQVUsQ0FBQztvQkFDcEIsQ0FBQztnQkFDSCxDQUFDO1lBQ0gsQ0FBQztZQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7Z0JBQ2YsK0NBQStDO2dCQUMvQyxPQUFPLElBQUksQ0FBQztZQUNkLENBQUM7WUFDRCxPQUFPLElBQUksQ0FBQztRQUNkLENBQUMsQ0FBQyxDQUFDO1FBRUgsTUFBTSxPQUFPLEdBQUcsTUFBTSxPQUFPLENBQUMsVUFBVSxDQUFDLGFBQWEsQ0FBQyxDQUFDO1FBRXhELG1DQUFtQztRQUNuQyxLQUFLLE1BQU0sTUFBTSxJQUFJLE9BQU8sRUFBRSxDQUFDO1lBQzdCLElBQUksTUFBTSxDQUFDLE1BQU0sS0FBSyxXQUFXLElBQUksTUFBTSxDQUFDLEtBQUssS0FBSyxJQUFJLEVBQUUsQ0FBQztnQkFDM0QsTUFBTSxDQUFDLElBQUksQ0FBQyxxREFBcUQsTUFBTSxDQUFDLEtBQUssRUFBRSxDQUFDLENBQUM7Z0JBQ2pGLG1CQUFtQjtnQkFDbkIsc0JBQXNCLENBQUMsYUFBYSxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUM7Z0JBQ3BELE9BQU8sTUFBTSxDQUFDLEtBQUssQ0FBQztZQUN0QixDQUFDO1FBQ0gsQ0FBQztRQUVELE1BQU0sQ0FBQyxJQUFJLENBQUMsNkVBQTZFLENBQUMsQ0FBQztRQUMzRixPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7SUFFRDs7T0FFRztJQUNLLEtBQUssQ0FBQyxlQUFlLENBQUMsT0FBZTtRQUMzQyxJQUFJLENBQUM7WUFDSCxNQUFNLEtBQUssR0FBRyxNQUFNLEVBQUUsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7WUFDckMsT0FBTyxLQUFLLENBQUMsV0FBVyxFQUFFLENBQUM7UUFDN0IsQ0FBQztRQUFDLE1BQU0sQ0FBQztZQUNQLE9BQU8sS0FBSyxDQUFDO1FBQ2YsQ0FBQztJQUNILENBQUM7SUFFRDs7O09BR0c7SUFDSyxLQUFLLENBQUMsZ0JBQWdCLENBQUMsU0FBaUIsRUFBRSxPQUFlLEVBQUUsV0FBbUI7UUFDcEYsSUFBSSxXQUFXLEdBQUcsQ0FBQyxDQUFDO1FBRXBCLElBQUksQ0FBQztZQUNILHNDQUFzQztZQUN0QyxNQUFNLEVBQUUsQ0FBQyxLQUFLLENBQUMsT0FBTyxFQUFFLEVBQUUsU0FBUyxFQUFFLElBQUksRUFBRSxDQUFDLENBQUM7WUFFN0Msd0JBQXdCO1lBQ3hCLE1BQU0sS0FBSyxHQUFHLE1BQU0sRUFBRSxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0FBQztZQUUxQyxLQUFLLE1BQU0sSUFBSSxJQUFJLEtBQUssRUFBRSxDQUFDO2dCQUN6QiwyQkFBMkI7Z0JBQzNCLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLGNBQWMsQ0FBQyxpQkFBaUIsQ0FBQyxFQUFFLENBQUM7b0JBQ3JELFNBQVM7Z0JBQ1gsQ0FBQztnQkFFRCxrQ0FBa0M7Z0JBQ2xDLE1BQU0sY0FBYyxHQUFHLGdCQUFnQixDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsQ0FBQztnQkFDeEQsSUFBSSxDQUFDLGNBQWMsQ0FBQyxPQUFPLEVBQUUsQ0FBQztvQkFDNUIsTUFBTSxDQUFDLElBQUksQ0FBQyxnRUFBZ0UsSUFBSSxFQUFFLENBQUMsQ0FBQztvQkFDcEYsU0FBUztnQkFDWCxDQUFDO2dCQUVELE1BQU0sVUFBVSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLGNBQWMsQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO2dCQUMxRSxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxjQUFjLENBQUMsaUJBQWlCLENBQUMsQ0FBQztnQkFFdEUsSUFBSSxDQUFDO29CQUNILDJDQUEyQztvQkFDM0MsTUFBTSxFQUFFLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxDQUFDO29CQUMxQixNQUFNLENBQUMsS0FBSyxDQUFDLG9EQUFvRCxjQUFjLENBQUMsaUJBQWlCLEVBQUUsQ0FBQyxDQUFDO29CQUNyRyxTQUFTO2dCQUNYLENBQUM7Z0JBQUMsTUFBTSxDQUFDO29CQUNQLHdDQUF3QztnQkFDMUMsQ0FBQztnQkFFRCxJQUFJLENBQUM7b0JBQ0gsc0NBQXNDO29CQUN0QyxNQUFNLFdBQVcsR0FBRyxNQUFNLEVBQUUsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUM7b0JBRTlDLHdCQUF3QjtvQkFDeEIsSUFBSSxXQUFXLENBQUMsSUFBSSxHQUFHLGNBQWMsQ0FBQyxhQUFhLEVBQUUsQ0FBQzt3QkFDcEQsTUFBTSxDQUFDLElBQUksQ0FDVCxvREFBb0QsY0FBYyxDQUFDLGlCQUFpQixJQUFJOzRCQUN4RixHQUFHLFdBQVcsQ0FBQyxJQUFJLGdCQUFnQixjQUFjLENBQUMsYUFBYSxTQUFTLEVBQ3hFOzRCQUNFLElBQUksRUFBRSxjQUFjLENBQUMsaUJBQWlCOzRCQUN0QyxJQUFJLEVBQUUsV0FBVyxDQUFDLElBQUk7NEJBQ3RCLE9BQU8sRUFBRSxjQUFjLENBQUMsYUFBYTs0QkFDckMsV0FBVzt5QkFDWixDQUNGLENBQUM7d0JBQ0YsU0FBUztvQkFDWCxDQUFDO29CQUVELGtDQUFrQztvQkFDbEMsTUFBTSxJQUFJLENBQUMsd0JBQXdCLENBQUMsVUFBVSxFQUFFLFFBQVEsQ0FBQyxDQUFDO29CQUMxRCxXQUFXLEVBQUUsQ0FBQztvQkFDZCxNQUFNLENBQUMsS0FBSyxDQUFDLG1DQUFtQyxXQUFXLEtBQUssY0FBYyxDQUFDLGlCQUFpQixFQUFFLENBQUMsQ0FBQztvQkFFcEcsMENBQTBDO29CQUMxQyxlQUFlLENBQUMsZ0JBQWdCLENBQUM7d0JBQy9CLElBQUksRUFBRSxhQUFhO3dCQUNuQixRQUFRLEVBQUUsS0FBSzt3QkFDZixNQUFNLEVBQUUseUNBQXlDO3dCQUNqRCxPQUFPLEVBQUUsa0JBQWtCLFdBQVcsVUFBVSxjQUFjLENBQUMsaUJBQWlCLEVBQUU7d0JBQ2xGLFFBQVEsRUFBRTs0QkFDUixVQUFVOzRCQUNWLFFBQVE7NEJBQ1IsV0FBVzs0QkFDWCxRQUFRLEVBQUUsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxJQUFJO3lCQUN6QztxQkFDRixDQUFDLENBQUM7Z0JBQ0wsQ0FBQztnQkFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO29CQUNmLE1BQU0sR0FBRyxHQUFHLEtBQWMsQ0FBQztvQkFDM0IsTUFBTSxDQUFDLEtBQUssQ0FDViwyQ0FBMkMsY0FBYyxDQUFDLGlCQUFpQixFQUFFLEVBQzdFO3dCQUNFLEtBQUssRUFBRSxHQUFHLENBQUMsT0FBTzt3QkFDbEIsS0FBSyxFQUFFLEdBQUcsQ0FBQyxLQUFLO3dCQUNoQixVQUFVO3dCQUNWLFFBQVE7d0JBQ1IsV0FBVztxQkFDWixDQUNGLENBQUM7b0JBQ0YsMERBQTBEO2dCQUM1RCxDQUFDO1lBQ0gsQ0FBQztZQUVELElBQUksV0FBVyxHQUFHLENBQUMsRUFBRSxDQUFDO2dCQUNwQixNQUFNLENBQUMsSUFBSSxDQUFDLG1DQUFtQyxXQUFXLElBQUksV0FBVyxVQUFVLENBQUMsQ0FBQztZQUN2RixDQUFDO1FBRUgsQ0FBQztRQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7WUFDZixNQUFNLENBQUMsS0FBSyxDQUFDLDBDQUEwQyxXQUFXLFNBQVMsRUFBRSxLQUFLLENBQUMsQ0FBQztRQUN0RixDQUFDO1FBRUQsT0FBTyxXQUFXLENBQUM7SUFDckIsQ0FBQztJQUVEOzs7T0FHRztJQUNIOzs7O09BSUc7SUFDSyxLQUFLLENBQUMsaUJBQWlCLENBQUMsUUFBZ0I7UUFDOUMsTUFBTSxJQUFJLEdBQUcsVUFBVSxDQUFDLGNBQWMsQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO1FBQzNELE1BQU0sTUFBTSxHQUFHLE1BQU0sRUFBRSxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsR0FBRyxDQUFDLENBQUM7UUFFNUMsSUFBSSxDQUFDO1lBQ0gsTUFBTSxNQUFNLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQyxjQUFjLENBQUMsVUFBVSxDQUFDLENBQUM7WUFDdkQsSUFBSSxTQUFpQixDQUFDO1lBRXRCLEdBQUcsQ0FBQztnQkFDRixNQUFNLE1BQU0sR0FBRyxNQUFNLE1BQU0sQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRSxjQUFjLENBQUMsVUFBVSxDQUFDLENBQUM7Z0JBQ3ZFLFNBQVMsR0FBRyxNQUFNLENBQUMsU0FBUyxDQUFDO2dCQUU3QixJQUFJLFNBQVMsR0FBRyxDQUFDLEVBQUUsQ0FBQztvQkFDbEIsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUMsRUFBRSxTQUFTLENBQUMsQ0FBQyxDQUFDO2dCQUM3QyxDQUFDO1lBQ0gsQ0FBQyxRQUFRLFNBQVMsR0FBRyxDQUFDLEVBQUU7WUFFeEIsT0FBTyxJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQzVCLENBQUM7Z0JBQVMsQ0FBQztZQUNULE1BQU0sTUFBTSxDQUFDLEtBQUssRUFBRSxDQUFDO1FBQ3ZCLENBQUM7SUFDSCxDQUFDO0lBRUQ7Ozs7O09BS0c7SUFDSyxLQUFLLENBQUMsd0JBQXdCLENBQUMsVUFBa0IsRUFBRSxRQUFnQjtRQUN6RSxJQUFJLFNBQVMsR0FBaUIsSUFBSSxDQUFDO1FBRW5DLEtBQUssSUFBSSxPQUFPLEdBQUcsQ0FBQyxFQUFFLE9BQU8sSUFBSSxtQkFBbUIsRUFBRSxPQUFPLEVBQUUsRUFBRSxDQUFDO1lBQ2hFLElBQUksQ0FBQztnQkFDSCxnQkFBZ0I7Z0JBQ2hCLE1BQU0sRUFBRSxDQUFDLFFBQVEsQ0FBQyxVQUFVLEVBQUUsUUFBUSxDQUFDLENBQUM7Z0JBRXhDLHNCQUFzQjtnQkFDdEIsTUFBTSxDQUFDLFdBQVcsRUFBRSxTQUFTLENBQUMsR0FBRyxNQUFNLE9BQU8sQ0FBQyxHQUFHLENBQUM7b0JBQ2pELEVBQUUsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDO29CQUNuQixFQUFFLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQztpQkFDbEIsQ0FBQyxDQUFDO2dCQUVILElBQUksV0FBVyxDQUFDLElBQUksS0FBSyxTQUFTLENBQUMsSUFBSSxFQUFFLENBQUM7b0JBQ3hDLE1BQU0sSUFBSSxLQUFLLENBQ2Isc0NBQXNDLFdBQVcsQ0FBQyxJQUFJLFVBQVU7d0JBQ2hFLGdCQUFnQixTQUFTLENBQUMsSUFBSSxRQUFRLENBQ3ZDLENBQUM7Z0JBQ0osQ0FBQztnQkFFRCxpREFBaUQ7Z0JBQ2pELE1BQU0sQ0FBQyxjQUFjLEVBQUUsWUFBWSxDQUFDLEdBQUcsTUFBTSxPQUFPLENBQUMsR0FBRyxDQUFDO29CQUN2RCxJQUFJLENBQUMsaUJBQWlCLENBQUMsVUFBVSxDQUFDO29CQUNsQyxJQUFJLENBQUMsaUJBQWlCLENBQUMsUUFBUSxDQUFDO2lCQUNqQyxDQUFDLENBQUM7Z0JBRUgsSUFBSSxjQUFjLEtBQUssWUFBWSxFQUFFLENBQUM7b0JBQ3BDLE1BQU0sSUFBSSxLQUFLLENBQ2IsMENBQTBDLGNBQWMsSUFBSTt3QkFDNUQsZ0JBQWdCLFlBQVksRUFBRSxDQUMvQixDQUFDO2dCQUNKLENBQUM7Z0JBRUQseUJBQXlCO2dCQUN6QixJQUFJLENBQUM7b0JBQ0gsTUFBTSxFQUFFLENBQUMsS0FBSyxDQUFDLFFBQVEsRUFBRSxjQUFjLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztnQkFDNUQsQ0FBQztnQkFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO29CQUNmLE1BQU0sQ0FBQyxLQUFLLENBQ1YseURBQXlELFFBQVEsS0FBSyxLQUFLLEVBQUUsRUFDN0UsRUFBRSxVQUFVLEVBQUUsUUFBUSxFQUFFLE9BQU8sRUFBRSxDQUNsQyxDQUFDO2dCQUNKLENBQUM7Z0JBRUQscUNBQXFDO2dCQUNyQyxNQUFNLENBQUMsS0FBSyxDQUNWLDhEQUE4RCxJQUFJLENBQUMsUUFBUSxDQUFDLFVBQVUsQ0FBQyxFQUFFLEVBQ3pGLEVBQUUsSUFBSSxFQUFFLFdBQVcsQ0FBQyxJQUFJLEVBQUUsUUFBUSxFQUFFLGNBQWMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQ3JFLENBQUM7Z0JBQ0YsT0FBTztZQUVULENBQUM7WUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO2dCQUNmLFNBQVMsR0FBRyxLQUFjLENBQUM7Z0JBRTNCLHVCQUF1QjtnQkFDdkIsSUFBSSxDQUFDO29CQUNILE1BQU0sRUFBRSxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQztnQkFDNUIsQ0FBQztnQkFBQyxNQUFNLENBQUM7b0JBQ1Asd0JBQXdCO2dCQUMxQixDQUFDO2dCQUVELElBQUksT0FBTyxHQUFHLG1CQUFtQixFQUFFLENBQUM7b0JBQ2xDLE1BQU0sQ0FBQyxLQUFLLENBQ1YseUNBQXlDLE9BQU8sc0JBQXNCLEVBQ3RFLEVBQUUsS0FBSyxFQUFFLFNBQVMsQ0FBQyxPQUFPLEVBQUUsVUFBVSxFQUFFLFFBQVEsRUFBRSxDQUNuRCxDQUFDO29CQUNGLE1BQU0sSUFBSSxPQUFPLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQyxVQUFVLENBQUMsT0FBTyxFQUFFLGdCQUFnQixHQUFHLE9BQU8sQ0FBQyxDQUFDLENBQUM7Z0JBQ2hGLENBQUM7WUFDSCxDQUFDO1FBQ0gsQ0FBQztRQUVELHNCQUFzQjtRQUN0QixNQUFNLElBQUksS0FBSyxDQUNiLGtCQUFrQixJQUFJLENBQUMsUUFBUSxDQUFDLFVBQVUsQ0FBQyxVQUFVLG1CQUFtQixhQUFhO1lBQ3JGLEdBQUcsU0FBUyxFQUFFLE9BQU8sSUFBSSxlQUFlLEVBQUUsQ0FDM0MsQ0FBQztJQUNKLENBQUM7SUFFRDs7OztPQUlHO0lBQ0ksS0FBSyxDQUFDLGdCQUFnQixDQUFDLGdCQUF3QjtRQUNwRCxnRUFBZ0U7UUFDaEUsTUFBTSxrQkFBa0IsR0FBRyxzQkFBc0IsQ0FBQyxrQkFBa0IsQ0FBQyxHQUFHLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztRQUMzRixJQUFJLGtCQUFrQixFQUFFLENBQUM7WUFDdkIsTUFBTSxDQUFDLEtBQUssQ0FDVixtRkFBbUYsRUFDbkYsRUFBRSxnQkFBZ0IsRUFBRSxDQUNyQixDQUFDO1lBQ0YsT0FBTyxrQkFBa0IsQ0FBQztRQUM1QixDQUFDO1FBRUQsZ0NBQWdDO1FBQ2hDLE1BQU0saUJBQWlCLEdBQUcsSUFBSSxDQUFDLGlCQUFpQixDQUFDLGdCQUFnQixDQUFDO2FBQy9ELE9BQU8sQ0FBQyxHQUFHLEVBQUU7WUFDWixxQkFBcUI7WUFDckIsc0JBQXNCLENBQUMsa0JBQWtCLENBQUMsTUFBTSxDQUFDLGdCQUFnQixDQUFDLENBQUM7UUFDckUsQ0FBQyxDQUFDLENBQUM7UUFFTCxzQkFBc0IsQ0FBQyxrQkFBa0IsQ0FBQyxHQUFHLENBQUMsZ0JBQWdCLEVBQUUsaUJBQWlCLENBQUMsQ0FBQztRQUNuRixPQUFPLGlCQUFpQixDQUFDO0lBQzNCLENBQUM7SUFFRDs7O09BR0c7SUFDSyxLQUFLLENBQUMsaUJBQWlCLENBQUMsZ0JBQXdCO1FBQ3RELE1BQU0sQ0FBQyxJQUFJLENBQ1QsOERBQThELEVBQzlELEVBQUUsZ0JBQWdCLEVBQUUsQ0FDckIsQ0FBQztRQUVGLGtEQUFrRDtRQUNsRCxlQUFlLENBQUMsZ0JBQWdCLENBQUM7WUFDL0IsSUFBSSxFQUFFLDBCQUEwQjtZQUNoQyxRQUFRLEVBQUUsS0FBSztZQUNmLE1BQU0sRUFBRSwwQ0FBMEM7WUFDbEQsT0FBTyxFQUFFLHNEQUFzRCxnQkFBZ0IsRUFBRTtTQUNsRixDQUFDLENBQUM7UUFFSCxrQ0FBa0M7UUFDbEMsTUFBTSxPQUFPLEdBQUcsTUFBTSxJQUFJLENBQUMsaUJBQWlCLEVBQUUsQ0FBQztRQUMvQyxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7WUFDYixNQUFNLENBQUMsSUFBSSxDQUNULHVGQUF1RixFQUN2RjtnQkFDRSxXQUFXLEVBQUUsSUFBSSxDQUFDLGVBQWUsQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLG9DQUFvQztnQkFDbkYsR0FBRyxFQUFFLE9BQU8sQ0FBQyxHQUFHLEVBQUU7Z0JBQ2xCLE9BQU8sRUFBRSxJQUFJLENBQUMsU0FBUzthQUN4QixDQUNGLENBQUM7WUFDRixPQUFPO1FBQ1QsQ0FBQztRQUVELDJCQUEyQjtRQUMzQixJQUFJLFdBQVcsR0FBRyxDQUFDLENBQUM7UUFDcEIsTUFBTSxZQUFZLEdBQTJCLEVBQUUsQ0FBQztRQUVoRCxrRkFBa0Y7UUFDbEYsTUFBTSxlQUFlLEdBQWdDO1lBQ25ELFVBQVUsRUFBRSxXQUFXLENBQUMsT0FBTztZQUMvQixRQUFRLEVBQUUsV0FBVyxDQUFDLEtBQUs7WUFDM0IsV0FBVyxFQUFFLFdBQVcsQ0FBQyxRQUFRO1lBQ2pDLFFBQVEsRUFBRSxXQUFXLENBQUMsS0FBSztZQUMzQixVQUFVLEVBQUUsV0FBVyxDQUFDLE1BQU07WUFDOUIsV0FBVyxFQUFFLFdBQVcsQ0FBQyxRQUFRO1NBQ2xDLENBQUM7UUFFRix5QkFBeUI7UUFDekIsS0FBSyxNQUFNLENBQUMsVUFBVSxFQUFFLFdBQVcsQ0FBQyxJQUFJLE1BQU0sQ0FBQyxPQUFPLENBQUMsZUFBZSxDQUFDLEVBQUUsQ0FBQztZQUN4RSxNQUFNLFNBQVMsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxVQUFVLENBQUMsQ0FBQztZQUNqRCxNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLGdCQUFnQixFQUFFLFdBQVcsQ0FBQyxDQUFDO1lBRXpELElBQUksQ0FBQztnQkFDSCxtQ0FBbUM7Z0JBQ25DLE1BQU0sRUFBRSxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsQ0FBQztnQkFDM0IsTUFBTSxXQUFXLEdBQUcsTUFBTSxJQUFJLENBQUMsZ0JBQWdCLENBQUMsU0FBUyxFQUFFLE9BQU8sRUFBRSxVQUFVLENBQUMsQ0FBQztnQkFDaEYsWUFBWSxDQUFDLFVBQVUsQ0FBQyxHQUFHLFdBQVcsQ0FBQztnQkFDdkMsV0FBVyxJQUFJLFdBQVcsQ0FBQztZQUM3QixDQUFDO1lBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztnQkFDZix1Q0FBdUM7Z0JBQ3ZDLE1BQU0sQ0FBQyxLQUFLLENBQUMsK0JBQStCLFVBQVUsNEJBQTRCLENBQUMsQ0FBQztZQUN0RixDQUFDO1FBQ0gsQ0FBQztRQUVELElBQUksV0FBVyxHQUFHLENBQUMsRUFBRSxDQUFDO1lBQ3BCLE1BQU0sQ0FBQyxJQUFJLENBQ1Qsa0VBQWtFLFdBQVcscUJBQXFCLEVBQ2xHO2dCQUNFLGdCQUFnQjtnQkFDaEIsT0FBTztnQkFDUCxTQUFTLEVBQUUsTUFBTSxDQUFDLE9BQU8sQ0FBQyxlQUFlLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxPQUFPLEVBQUUsV0FBVyxDQUFDLEVBQUUsRUFBRTtvQkFDaEYsR0FBRyxDQUFDLFdBQVcsQ0FBQyxHQUFHLFlBQVksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUM7b0JBQzlDLE9BQU8sR0FBRyxDQUFDO2dCQUNiLENBQUMsRUFBRSxFQUE0QixDQUFDO2FBQ2pDLENBQ0YsQ0FBQztZQUVGLCtDQUErQztZQUMvQyxlQUFlLENBQUMsZ0JBQWdCLENBQUM7Z0JBQy9CLElBQUksRUFBRSxxQkFBcUI7Z0JBQzNCLFFBQVEsRUFBRSxLQUFLO2dCQUNmLE1BQU0sRUFBRSwwQ0FBMEM7Z0JBQ2xELE9BQU8sRUFBRSx5Q0FBeUMsV0FBVyxtQkFBbUI7Z0JBQ2hGLFFBQVEsRUFBRTtvQkFDUixnQkFBZ0I7b0JBQ2hCLE9BQU87b0JBQ1AsWUFBWTtpQkFDYjthQUNGLENBQUMsQ0FBQztRQUNMLENBQUM7YUFBTSxDQUFDO1lBQ04sTUFBTSxDQUFDLElBQUksQ0FBQyx1RkFBdUYsQ0FBQyxDQUFDO1FBQ3ZHLENBQUM7SUFDSCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBEZWZhdWx0RWxlbWVudFByb3ZpZGVyIC0gUG9wdWxhdGVzIHBvcnRmb2xpbyB3aXRoIGRlZmF1bHQgZWxlbWVudHMgZnJvbSBidW5kbGVkIGRhdGFcbiAqIFxuICogVGhpcyBjbGFzcyBoYW5kbGVzIGNvcHlpbmcgZGVmYXVsdCBwZXJzb25hcywgc2tpbGxzLCB0ZW1wbGF0ZXMsIGFuZCBvdGhlciBlbGVtZW50c1xuICogZnJvbSB0aGUgTlBNIHBhY2thZ2Ugb3IgR2l0IHJlcG9zaXRvcnkgdG8gdGhlIHVzZXIncyBwb3J0Zm9saW8gb24gZmlyc3QgcnVuLlxuICogSXQgZW5zdXJlcyB1c2VycyBoYXZlIGV4YW1wbGUgY29udGVudCB0byB3b3JrIHdpdGggaW1tZWRpYXRlbHkgYWZ0ZXIgaW5zdGFsbGF0aW9uLlxuICovXG5cbmltcG9ydCAqIGFzIGZzIGZyb20gJ2ZzL3Byb21pc2VzJztcbmltcG9ydCAqIGFzIHBhdGggZnJvbSAncGF0aCc7XG5pbXBvcnQgeyBmaWxlVVJMVG9QYXRoIH0gZnJvbSAndXJsJztcbmltcG9ydCB7IGNyZWF0ZUhhc2ggfSBmcm9tICdjcnlwdG8nO1xuaW1wb3J0IHsgbG9nZ2VyIH0gZnJvbSAnLi4vdXRpbHMvbG9nZ2VyLmpzJztcbmltcG9ydCB7IEVsZW1lbnRUeXBlIH0gZnJvbSAnLi90eXBlcy5qcyc7XG5pbXBvcnQgeyBVbmljb2RlVmFsaWRhdG9yIH0gZnJvbSAnLi4vc2VjdXJpdHkvdmFsaWRhdG9ycy91bmljb2RlVmFsaWRhdG9yLmpzJztcbmltcG9ydCB7IFNlY3VyaXR5TW9uaXRvciB9IGZyb20gJy4uL3NlY3VyaXR5L3NlY3VyaXR5TW9uaXRvci5qcyc7XG5cbi8vIEZpbGUgb3BlcmF0aW9uIGNvbnN0YW50c1xuZXhwb3J0IGNvbnN0IEZJTEVfQ09OU1RBTlRTID0ge1xuICBFTEVNRU5UX0VYVEVOU0lPTjogJy5tZCcsXG4gIFlBTUxfRVhURU5TSU9OOiAnLnlhbWwnLFxuICBZTUxfRVhURU5TSU9OOiAnLnltbCcsXG4gIEpTT05fRVhURU5TSU9OOiAnLmpzb24nLFxuICBNQVhfRklMRV9TSVpFOiAxMCAqIDEwMjQgKiAxMDI0LCAvLyAxME1CIG1heCBmaWxlIHNpemUgZm9yIHNhZmV0eVxuICBDSEVDS1NVTV9BTEdPUklUSE06ICdzaGEyNTYnLFxuICBGSUxFX1BFUk1JU1NJT05TOiAwbzY0NCxcbiAgQ0hVTktfU0laRTogNjQgKiAxMDI0IC8vIDY0S0IgY2h1bmtzIGZvciByZWFkaW5nIGxhcmdlIGZpbGVzXG59IGFzIGNvbnN0O1xuXG4vLyBJbnRlcm5hbCBjb25zdGFudHNcbmNvbnN0IERBVEFfRElSX0NBQ0hFX0tFWSA9ICdkb2xsaG91c2VfZGF0YV9kaXInO1xuY29uc3QgQ09QWV9SRVRSWV9BVFRFTVBUUyA9IDM7XG5jb25zdCBDT1BZX1JFVFJZX0RFTEFZID0gMTAwOyAvLyBtc1xuXG5leHBvcnQgaW50ZXJmYWNlIERlZmF1bHRFbGVtZW50UHJvdmlkZXJDb25maWcge1xuICAvKiogQ3VzdG9tIGRhdGEgZGlyZWN0b3J5IHBhdGhzIHRvIHNlYXJjaCAoY2hlY2tlZCBiZWZvcmUgZGVmYXVsdCBwYXRocykgKi9cbiAgY3VzdG9tRGF0YVBhdGhzPzogc3RyaW5nW107XG4gIC8qKiBXaGV0aGVyIHRvIHVzZSBkZWZhdWx0IHNlYXJjaCBwYXRocyBhZnRlciBjdXN0b20gcGF0aHMgKi9cbiAgdXNlRGVmYXVsdFBhdGhzPzogYm9vbGVhbjtcbn1cblxuZXhwb3J0IGNsYXNzIERlZmF1bHRFbGVtZW50UHJvdmlkZXIge1xuICBwcml2YXRlIHJlYWRvbmx5IF9fZGlybmFtZTogc3RyaW5nO1xuICBwcml2YXRlIHN0YXRpYyBjYWNoZWREYXRhRGlyOiBzdHJpbmcgfCBudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSBzdGF0aWMgcG9wdWxhdGVJblByb2dyZXNzOiBNYXA8c3RyaW5nLCBQcm9taXNlPHZvaWQ+PiA9IG5ldyBNYXAoKTtcbiAgcHJpdmF0ZSByZWFkb25seSBjb25maWc6IERlZmF1bHRFbGVtZW50UHJvdmlkZXJDb25maWc7XG4gIFxuICBjb25zdHJ1Y3Rvcihjb25maWc/OiBEZWZhdWx0RWxlbWVudFByb3ZpZGVyQ29uZmlnKSB7XG4gICAgY29uc3QgX19maWxlbmFtZSA9IGZpbGVVUkxUb1BhdGgoaW1wb3J0Lm1ldGEudXJsKTtcbiAgICB0aGlzLl9fZGlybmFtZSA9IHBhdGguZGlybmFtZShfX2ZpbGVuYW1lKTtcbiAgICB0aGlzLmNvbmZpZyA9IHtcbiAgICAgIHVzZURlZmF1bHRQYXRoczogdHJ1ZSxcbiAgICAgIC4uLmNvbmZpZ1xuICAgIH07XG4gIH1cbiAgXG4gIC8qKlxuICAgKiBTZWFyY2ggcGF0aHMgZm9yIGJ1bmRsZWQgZGF0YSBkaXJlY3RvcnlcbiAgICogT3JkZXJlZCBieSBwcmlvcml0eSAtIGN1c3RvbSBwYXRocyBmaXJzdCwgdGhlbiBkZXZlbG9wbWVudC9naXQsIHRoZW4gTlBNIGxvY2F0aW9uc1xuICAgKi9cbiAgcHJpdmF0ZSBnZXQgZGF0YVNlYXJjaFBhdGhzKCk6IHN0cmluZ1tdIHtcbiAgICBjb25zdCBwYXRoczogc3RyaW5nW10gPSBbXTtcbiAgICBcbiAgICAvLyBBZGQgY3VzdG9tIHBhdGhzIGZpcnN0IChoaWdoZXN0IHByaW9yaXR5KVxuICAgIGlmICh0aGlzLmNvbmZpZy5jdXN0b21EYXRhUGF0aHMpIHtcbiAgICAgIHBhdGhzLnB1c2goLi4udGhpcy5jb25maWcuY3VzdG9tRGF0YVBhdGhzKTtcbiAgICB9XG4gICAgXG4gICAgLy8gQWRkIGRlZmF1bHQgcGF0aHMgaWYgZW5hYmxlZFxuICAgIGlmICh0aGlzLmNvbmZpZy51c2VEZWZhdWx0UGF0aHMgIT09IGZhbHNlKSB7XG4gICAgICBwYXRocy5wdXNoKFxuICAgICAgICAvLyBEZXZlbG9wbWVudC9HaXQgaW5zdGFsbGF0aW9uIChyZWxhdGl2ZSB0byB0aGlzIGZpbGUpXG4gICAgICAgIHBhdGguam9pbih0aGlzLl9fZGlybmFtZSwgJy4uLy4uL2RhdGEnKSxcbiAgICAgICAgcGF0aC5qb2luKHRoaXMuX19kaXJuYW1lLCAnLi4vLi4vLi4vZGF0YScpLFxuICAgICAgICBcbiAgICAgICAgLy8gTlBNIGluc3RhbGxhdGlvbnMgLSBtYWNPUyBIb21lYnJld1xuICAgICAgICAnL29wdC9ob21lYnJldy9saWIvbm9kZV9tb2R1bGVzL0Bkb2xsaG91c2VtY3AvbWNwLXNlcnZlci9kYXRhJyxcbiAgICAgICAgXG4gICAgICAgIC8vIE5QTSBpbnN0YWxsYXRpb25zIC0gc3RhbmRhcmQgVW5peC9MaW51eFxuICAgICAgICAnL3Vzci9sb2NhbC9saWIvbm9kZV9tb2R1bGVzL0Bkb2xsaG91c2VtY3AvbWNwLXNlcnZlci9kYXRhJyxcbiAgICAgICAgJy91c3IvbGliL25vZGVfbW9kdWxlcy9AZG9sbGhvdXNlbWNwL21jcC1zZXJ2ZXIvZGF0YScsXG4gICAgICAgIFxuICAgICAgICAvLyBOUE0gaW5zdGFsbGF0aW9ucyAtIFdpbmRvd3NcbiAgICAgICAgJ0M6XFxcXFByb2dyYW0gRmlsZXNcXFxcbm9kZWpzXFxcXG5vZGVfbW9kdWxlc1xcXFxAZG9sbGhvdXNlbWNwXFxcXG1jcC1zZXJ2ZXJcXFxcZGF0YScsXG4gICAgICAgICdDOlxcXFxQcm9ncmFtIEZpbGVzICh4ODYpXFxcXG5vZGVqc1xcXFxub2RlX21vZHVsZXNcXFxcQGRvbGxob3VzZW1jcFxcXFxtY3Atc2VydmVyXFxcXGRhdGEnLFxuICAgICAgICBcbiAgICAgICAgLy8gTlBNIGluc3RhbGxhdGlvbnMgLSBXaW5kb3dzIHdpdGggbnZtXG4gICAgICAgIHBhdGguam9pbihwcm9jZXNzLmVudi5BUFBEQVRBIHx8ICcnLCAnbnBtJywgJ25vZGVfbW9kdWxlcycsICdAZG9sbGhvdXNlbWNwJywgJ21jcC1zZXJ2ZXInLCAnZGF0YScpLFxuICAgICAgICBcbiAgICAgICAgLy8gQ3VycmVudCB3b3JraW5nIGRpcmVjdG9yeSAobGFzdCByZXNvcnQpXG4gICAgICAgIHBhdGguam9pbihwcm9jZXNzLmN3ZCgpLCAnZGF0YScpXG4gICAgICApO1xuICAgIH1cbiAgICBcbiAgICByZXR1cm4gcGF0aHM7XG4gIH1cbiAgXG4gIC8qKlxuICAgKiBGaW5kIHRoZSBidW5kbGVkIGRhdGEgZGlyZWN0b3J5IGJ5IGNoZWNraW5nIGVhY2ggc2VhcmNoIHBhdGhcbiAgICogVXNlcyBQcm9taXNlLmFsbFNldHRsZWQgZm9yIGJldHRlciBwZXJmb3JtYW5jZSBhbmQgY2FjaGVzIHRoZSByZXN1bHRcbiAgICovXG4gIHByaXZhdGUgYXN5bmMgZmluZERhdGFEaXJlY3RvcnkoKTogUHJvbWlzZTxzdHJpbmcgfCBudWxsPiB7XG4gICAgLy8gUmV0dXJuIGNhY2hlZCB2YWx1ZSBpZiBhdmFpbGFibGVcbiAgICBpZiAoRGVmYXVsdEVsZW1lbnRQcm92aWRlci5jYWNoZWREYXRhRGlyICE9PSBudWxsKSB7XG4gICAgICByZXR1cm4gRGVmYXVsdEVsZW1lbnRQcm92aWRlci5jYWNoZWREYXRhRGlyO1xuICAgIH1cbiAgICBcbiAgICAvLyBDaGVjayBhbGwgcGF0aHMgaW4gcGFyYWxsZWwgZm9yIGJldHRlciBwZXJmb3JtYW5jZVxuICAgIGNvbnN0IGNoZWNrUHJvbWlzZXMgPSB0aGlzLmRhdGFTZWFyY2hQYXRocy5tYXAoYXN5bmMgKHNlYXJjaFBhdGgpID0+IHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IHN0YXRzID0gYXdhaXQgZnMuc3RhdChzZWFyY2hQYXRoKTtcbiAgICAgICAgaWYgKHN0YXRzLmlzRGlyZWN0b3J5KCkpIHtcbiAgICAgICAgICAvLyBWZXJpZnkgaXQgY29udGFpbnMgZXhwZWN0ZWQgc3ViZGlyZWN0b3JpZXNcbiAgICAgICAgICBjb25zdCBoYXNQZXJzb25hcyA9IGF3YWl0IHRoaXMuZGlyZWN0b3J5RXhpc3RzKHBhdGguam9pbihzZWFyY2hQYXRoLCAncGVyc29uYXMnKSk7XG4gICAgICAgICAgY29uc3QgaGFzU2tpbGxzID0gYXdhaXQgdGhpcy5kaXJlY3RvcnlFeGlzdHMocGF0aC5qb2luKHNlYXJjaFBhdGgsICdza2lsbHMnKSk7XG4gICAgICAgICAgaWYgKGhhc1BlcnNvbmFzIHx8IGhhc1NraWxscykge1xuICAgICAgICAgICAgcmV0dXJuIHNlYXJjaFBhdGg7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAvLyBEaXJlY3RvcnkgZG9lc24ndCBleGlzdCBvciBjYW4ndCBiZSBhY2Nlc3NlZFxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIH1cbiAgICAgIHJldHVybiBudWxsO1xuICAgIH0pO1xuICAgIFxuICAgIGNvbnN0IHJlc3VsdHMgPSBhd2FpdCBQcm9taXNlLmFsbFNldHRsZWQoY2hlY2tQcm9taXNlcyk7XG4gICAgXG4gICAgLy8gRmluZCB0aGUgZmlyc3Qgc3VjY2Vzc2Z1bCByZXN1bHRcbiAgICBmb3IgKGNvbnN0IHJlc3VsdCBvZiByZXN1bHRzKSB7XG4gICAgICBpZiAocmVzdWx0LnN0YXR1cyA9PT0gJ2Z1bGZpbGxlZCcgJiYgcmVzdWx0LnZhbHVlICE9PSBudWxsKSB7XG4gICAgICAgIGxvZ2dlci5pbmZvKGBbRGVmYXVsdEVsZW1lbnRQcm92aWRlcl0gRm91bmQgZGF0YSBkaXJlY3RvcnkgYXQ6ICR7cmVzdWx0LnZhbHVlfWApO1xuICAgICAgICAvLyBDYWNoZSB0aGUgcmVzdWx0XG4gICAgICAgIERlZmF1bHRFbGVtZW50UHJvdmlkZXIuY2FjaGVkRGF0YURpciA9IHJlc3VsdC52YWx1ZTtcbiAgICAgICAgcmV0dXJuIHJlc3VsdC52YWx1ZTtcbiAgICAgIH1cbiAgICB9XG4gICAgXG4gICAgbG9nZ2VyLndhcm4oJ1tEZWZhdWx0RWxlbWVudFByb3ZpZGVyXSBObyBidW5kbGVkIGRhdGEgZGlyZWN0b3J5IGZvdW5kIGluIGFueSBzZWFyY2ggcGF0aCcpO1xuICAgIHJldHVybiBudWxsO1xuICB9XG4gIFxuICAvKipcbiAgICogSGVscGVyIHRvIGNoZWNrIGlmIGEgZGlyZWN0b3J5IGV4aXN0c1xuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBkaXJlY3RvcnlFeGlzdHMoZGlyUGF0aDogc3RyaW5nKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHN0YXRzID0gYXdhaXQgZnMuc3RhdChkaXJQYXRoKTtcbiAgICAgIHJldHVybiBzdGF0cy5pc0RpcmVjdG9yeSgpO1xuICAgIH0gY2F0Y2gge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuICBcbiAgLyoqXG4gICAqIENvcHkgYWxsIGZpbGVzIGZyb20gc291cmNlIGRpcmVjdG9yeSB0byBkZXN0aW5hdGlvbiBkaXJlY3RvcnlcbiAgICogU2tpcHMgZmlsZXMgdGhhdCBhbHJlYWR5IGV4aXN0IHRvIHByZXNlcnZlIHVzZXIgbW9kaWZpY2F0aW9uc1xuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBjb3B5RWxlbWVudEZpbGVzKHNvdXJjZURpcjogc3RyaW5nLCBkZXN0RGlyOiBzdHJpbmcsIGVsZW1lbnRUeXBlOiBzdHJpbmcpOiBQcm9taXNlPG51bWJlcj4ge1xuICAgIGxldCBjb3BpZWRDb3VudCA9IDA7XG4gICAgXG4gICAgdHJ5IHtcbiAgICAgIC8vIEVuc3VyZSBkZXN0aW5hdGlvbiBkaXJlY3RvcnkgZXhpc3RzXG4gICAgICBhd2FpdCBmcy5ta2RpcihkZXN0RGlyLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KTtcbiAgICAgIFxuICAgICAgLy8gUmVhZCBzb3VyY2UgZGlyZWN0b3J5XG4gICAgICBjb25zdCBmaWxlcyA9IGF3YWl0IGZzLnJlYWRkaXIoc291cmNlRGlyKTtcbiAgICAgIFxuICAgICAgZm9yIChjb25zdCBmaWxlIG9mIGZpbGVzKSB7XG4gICAgICAgIC8vIE9ubHkgY29weSBtYXJrZG93biBmaWxlc1xuICAgICAgICBpZiAoIWZpbGUuZW5kc1dpdGgoRklMRV9DT05TVEFOVFMuRUxFTUVOVF9FWFRFTlNJT04pKSB7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgICAgXG4gICAgICAgIC8vIE5vcm1hbGl6ZSBmaWxlbmFtZSBmb3Igc2VjdXJpdHlcbiAgICAgICAgY29uc3Qgbm9ybWFsaXplZEZpbGUgPSBVbmljb2RlVmFsaWRhdG9yLm5vcm1hbGl6ZShmaWxlKTtcbiAgICAgICAgaWYgKCFub3JtYWxpemVkRmlsZS5pc1ZhbGlkKSB7XG4gICAgICAgICAgbG9nZ2VyLndhcm4oYFtEZWZhdWx0RWxlbWVudFByb3ZpZGVyXSBTa2lwcGluZyBmaWxlIHdpdGggaW52YWxpZCBVbmljb2RlOiAke2ZpbGV9YCk7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgICAgXG4gICAgICAgIGNvbnN0IHNvdXJjZVBhdGggPSBwYXRoLmpvaW4oc291cmNlRGlyLCBub3JtYWxpemVkRmlsZS5ub3JtYWxpemVkQ29udGVudCk7XG4gICAgICAgIGNvbnN0IGRlc3RQYXRoID0gcGF0aC5qb2luKGRlc3REaXIsIG5vcm1hbGl6ZWRGaWxlLm5vcm1hbGl6ZWRDb250ZW50KTtcbiAgICAgICAgXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgLy8gQ2hlY2sgaWYgZGVzdGluYXRpb24gZmlsZSBhbHJlYWR5IGV4aXN0c1xuICAgICAgICAgIGF3YWl0IGZzLmFjY2VzcyhkZXN0UGF0aCk7XG4gICAgICAgICAgbG9nZ2VyLmRlYnVnKGBbRGVmYXVsdEVsZW1lbnRQcm92aWRlcl0gU2tpcHBpbmcgZXhpc3RpbmcgZmlsZTogJHtub3JtYWxpemVkRmlsZS5ub3JtYWxpemVkQ29udGVudH1gKTtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfSBjYXRjaCB7XG4gICAgICAgICAgLy8gRmlsZSBkb2Vzbid0IGV4aXN0LCBwcm9jZWVkIHdpdGggY29weVxuICAgICAgICB9XG4gICAgICAgIFxuICAgICAgICB0cnkge1xuICAgICAgICAgIC8vIFZhbGlkYXRlIHNvdXJjZSBmaWxlIGJlZm9yZSBjb3B5aW5nXG4gICAgICAgICAgY29uc3Qgc291cmNlU3RhdHMgPSBhd2FpdCBmcy5zdGF0KHNvdXJjZVBhdGgpO1xuICAgICAgICAgIFxuICAgICAgICAgIC8vIENoZWNrIGZpbGUgc2l6ZSBsaW1pdFxuICAgICAgICAgIGlmIChzb3VyY2VTdGF0cy5zaXplID4gRklMRV9DT05TVEFOVFMuTUFYX0ZJTEVfU0laRSkge1xuICAgICAgICAgICAgbG9nZ2VyLndhcm4oXG4gICAgICAgICAgICAgIGBbRGVmYXVsdEVsZW1lbnRQcm92aWRlcl0gU2tpcHBpbmcgb3ZlcnNpemVkIGZpbGUgJHtub3JtYWxpemVkRmlsZS5ub3JtYWxpemVkQ29udGVudH06IGAgK1xuICAgICAgICAgICAgICBgJHtzb3VyY2VTdGF0cy5zaXplfSBieXRlcyAobWF4OiAke0ZJTEVfQ09OU1RBTlRTLk1BWF9GSUxFX1NJWkV9IGJ5dGVzKWAsXG4gICAgICAgICAgICAgIHsgXG4gICAgICAgICAgICAgICAgZmlsZTogbm9ybWFsaXplZEZpbGUubm9ybWFsaXplZENvbnRlbnQsIFxuICAgICAgICAgICAgICAgIHNpemU6IHNvdXJjZVN0YXRzLnNpemUsXG4gICAgICAgICAgICAgICAgbWF4U2l6ZTogRklMRV9DT05TVEFOVFMuTUFYX0ZJTEVfU0laRSxcbiAgICAgICAgICAgICAgICBlbGVtZW50VHlwZSBcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgIH1cbiAgICAgICAgICBcbiAgICAgICAgICAvLyBDb3B5IHRoZSBmaWxlIHdpdGggdmVyaWZpY2F0aW9uXG4gICAgICAgICAgYXdhaXQgdGhpcy5jb3B5RmlsZVdpdGhWZXJpZmljYXRpb24oc291cmNlUGF0aCwgZGVzdFBhdGgpO1xuICAgICAgICAgIGNvcGllZENvdW50Kys7XG4gICAgICAgICAgbG9nZ2VyLmRlYnVnKGBbRGVmYXVsdEVsZW1lbnRQcm92aWRlcl0gQ29waWVkICR7ZWxlbWVudFR5cGV9OiAke25vcm1hbGl6ZWRGaWxlLm5vcm1hbGl6ZWRDb250ZW50fWApO1xuICAgICAgICAgIFxuICAgICAgICAgIC8vIExvZyBzZWN1cml0eSBldmVudCBmb3IgZWFjaCBmaWxlIGNvcGllZFxuICAgICAgICAgIFNlY3VyaXR5TW9uaXRvci5sb2dTZWN1cml0eUV2ZW50KHtcbiAgICAgICAgICAgIHR5cGU6ICdGSUxFX0NPUElFRCcsXG4gICAgICAgICAgICBzZXZlcml0eTogJ0xPVycsXG4gICAgICAgICAgICBzb3VyY2U6ICdEZWZhdWx0RWxlbWVudFByb3ZpZGVyLmNvcHlFbGVtZW50RmlsZXMnLFxuICAgICAgICAgICAgZGV0YWlsczogYENvcGllZCBkZWZhdWx0ICR7ZWxlbWVudFR5cGV9IGZpbGU6ICR7bm9ybWFsaXplZEZpbGUubm9ybWFsaXplZENvbnRlbnR9YCxcbiAgICAgICAgICAgIG1ldGFkYXRhOiB7XG4gICAgICAgICAgICAgIHNvdXJjZVBhdGgsXG4gICAgICAgICAgICAgIGRlc3RQYXRoLFxuICAgICAgICAgICAgICBlbGVtZW50VHlwZSxcbiAgICAgICAgICAgICAgZmlsZVNpemU6IChhd2FpdCBmcy5zdGF0KGRlc3RQYXRoKSkuc2l6ZVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH0pO1xuICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgIGNvbnN0IGVyciA9IGVycm9yIGFzIEVycm9yO1xuICAgICAgICAgIGxvZ2dlci5lcnJvcihcbiAgICAgICAgICAgIGBbRGVmYXVsdEVsZW1lbnRQcm92aWRlcl0gRmFpbGVkIHRvIGNvcHkgJHtub3JtYWxpemVkRmlsZS5ub3JtYWxpemVkQ29udGVudH1gLFxuICAgICAgICAgICAgeyBcbiAgICAgICAgICAgICAgZXJyb3I6IGVyci5tZXNzYWdlLFxuICAgICAgICAgICAgICBzdGFjazogZXJyLnN0YWNrLFxuICAgICAgICAgICAgICBzb3VyY2VQYXRoLFxuICAgICAgICAgICAgICBkZXN0UGF0aCxcbiAgICAgICAgICAgICAgZWxlbWVudFR5cGVcbiAgICAgICAgICAgIH1cbiAgICAgICAgICApO1xuICAgICAgICAgIC8vIENvbnRpbnVlIHdpdGggb3RoZXIgZmlsZXMgaW5zdGVhZCBvZiBmYWlsaW5nIGNvbXBsZXRlbHlcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgXG4gICAgICBpZiAoY29waWVkQ291bnQgPiAwKSB7XG4gICAgICAgIGxvZ2dlci5pbmZvKGBbRGVmYXVsdEVsZW1lbnRQcm92aWRlcl0gQ29waWVkICR7Y29waWVkQ291bnR9ICR7ZWxlbWVudFR5cGV9IGZpbGUocylgKTtcbiAgICAgIH1cbiAgICAgIFxuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBsb2dnZXIuZXJyb3IoYFtEZWZhdWx0RWxlbWVudFByb3ZpZGVyXSBFcnJvciBjb3B5aW5nICR7ZWxlbWVudFR5cGV9IGZpbGVzOmAsIGVycm9yKTtcbiAgICB9XG4gICAgXG4gICAgcmV0dXJuIGNvcGllZENvdW50O1xuICB9XG4gIFxuICAvKipcbiAgICogQ29weSBhIGZpbGUgd2l0aCBpbnRlZ3JpdHkgdmVyaWZpY2F0aW9uXG4gICAqIEVuc3VyZXMgdGhlIGZpbGUgd2FzIGNvcGllZCBjb3JyZWN0bHkgYnkgY29tcGFyaW5nIHNpemVzXG4gICAqL1xuICAvKipcbiAgICogQ2FsY3VsYXRlIGNoZWNrc3VtIG9mIGEgZmlsZSBmb3IgaW50ZWdyaXR5IHZlcmlmaWNhdGlvblxuICAgKiBAcGFyYW0gZmlsZVBhdGggUGF0aCB0byB0aGUgZmlsZVxuICAgKiBAcmV0dXJucyBIZXgtZW5jb2RlZCBjaGVja3N1bVxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBjYWxjdWxhdGVDaGVja3N1bShmaWxlUGF0aDogc3RyaW5nKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICBjb25zdCBoYXNoID0gY3JlYXRlSGFzaChGSUxFX0NPTlNUQU5UUy5DSEVDS1NVTV9BTEdPUklUSE0pO1xuICAgIGNvbnN0IHN0cmVhbSA9IGF3YWl0IGZzLm9wZW4oZmlsZVBhdGgsICdyJyk7XG4gICAgXG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IGJ1ZmZlciA9IEJ1ZmZlci5hbGxvYyhGSUxFX0NPTlNUQU5UUy5DSFVOS19TSVpFKTtcbiAgICAgIGxldCBieXRlc1JlYWQ6IG51bWJlcjtcbiAgICAgIFxuICAgICAgZG8ge1xuICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBzdHJlYW0ucmVhZChidWZmZXIsIDAsIEZJTEVfQ09OU1RBTlRTLkNIVU5LX1NJWkUpO1xuICAgICAgICBieXRlc1JlYWQgPSByZXN1bHQuYnl0ZXNSZWFkO1xuICAgICAgICBcbiAgICAgICAgaWYgKGJ5dGVzUmVhZCA+IDApIHtcbiAgICAgICAgICBoYXNoLnVwZGF0ZShidWZmZXIuc3ViYXJyYXkoMCwgYnl0ZXNSZWFkKSk7XG4gICAgICAgIH1cbiAgICAgIH0gd2hpbGUgKGJ5dGVzUmVhZCA+IDApO1xuICAgICAgXG4gICAgICByZXR1cm4gaGFzaC5kaWdlc3QoJ2hleCcpO1xuICAgIH0gZmluYWxseSB7XG4gICAgICBhd2FpdCBzdHJlYW0uY2xvc2UoKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQ29weSBmaWxlIHdpdGggaW50ZWdyaXR5IHZlcmlmaWNhdGlvbiBhbmQgcmV0cnkgbG9naWNcbiAgICogQHBhcmFtIHNvdXJjZVBhdGggU291cmNlIGZpbGUgcGF0aFxuICAgKiBAcGFyYW0gZGVzdFBhdGggRGVzdGluYXRpb24gZmlsZSBwYXRoXG4gICAqIEB0aHJvd3MgRXJyb3IgaWYgY29weSBmYWlscyBhZnRlciBhbGwgcmV0cnkgYXR0ZW1wdHNcbiAgICovXG4gIHByaXZhdGUgYXN5bmMgY29weUZpbGVXaXRoVmVyaWZpY2F0aW9uKHNvdXJjZVBhdGg6IHN0cmluZywgZGVzdFBhdGg6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGxldCBsYXN0RXJyb3I6IEVycm9yIHwgbnVsbCA9IG51bGw7XG4gICAgXG4gICAgZm9yIChsZXQgYXR0ZW1wdCA9IDE7IGF0dGVtcHQgPD0gQ09QWV9SRVRSWV9BVFRFTVBUUzsgYXR0ZW1wdCsrKSB7XG4gICAgICB0cnkge1xuICAgICAgICAvLyBDb3B5IHRoZSBmaWxlXG4gICAgICAgIGF3YWl0IGZzLmNvcHlGaWxlKHNvdXJjZVBhdGgsIGRlc3RQYXRoKTtcbiAgICAgICAgXG4gICAgICAgIC8vIFZlcmlmeSBzaXplIG1hdGNoZXNcbiAgICAgICAgY29uc3QgW3NvdXJjZVN0YXRzLCBkZXN0U3RhdHNdID0gYXdhaXQgUHJvbWlzZS5hbGwoW1xuICAgICAgICAgIGZzLnN0YXQoc291cmNlUGF0aCksXG4gICAgICAgICAgZnMuc3RhdChkZXN0UGF0aClcbiAgICAgICAgXSk7XG4gICAgICAgIFxuICAgICAgICBpZiAoc291cmNlU3RhdHMuc2l6ZSAhPT0gZGVzdFN0YXRzLnNpemUpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgICBgU2l6ZSBtaXNtYXRjaCBhZnRlciBjb3B5IC0gc291cmNlOiAke3NvdXJjZVN0YXRzLnNpemV9IGJ5dGVzLCBgICtcbiAgICAgICAgICAgIGBkZXN0aW5hdGlvbjogJHtkZXN0U3RhdHMuc2l6ZX0gYnl0ZXNgXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgICBcbiAgICAgICAgLy8gVmVyaWZ5IGNoZWNrc3VtIG1hdGNoZXMgZm9yIGNvbXBsZXRlIGludGVncml0eVxuICAgICAgICBjb25zdCBbc291cmNlQ2hlY2tzdW0sIGRlc3RDaGVja3N1bV0gPSBhd2FpdCBQcm9taXNlLmFsbChbXG4gICAgICAgICAgdGhpcy5jYWxjdWxhdGVDaGVja3N1bShzb3VyY2VQYXRoKSxcbiAgICAgICAgICB0aGlzLmNhbGN1bGF0ZUNoZWNrc3VtKGRlc3RQYXRoKVxuICAgICAgICBdKTtcbiAgICAgICAgXG4gICAgICAgIGlmIChzb3VyY2VDaGVja3N1bSAhPT0gZGVzdENoZWNrc3VtKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgICAgYENoZWNrc3VtIG1pc21hdGNoIGFmdGVyIGNvcHkgLSBzb3VyY2U6ICR7c291cmNlQ2hlY2tzdW19LCBgICtcbiAgICAgICAgICAgIGBkZXN0aW5hdGlvbjogJHtkZXN0Q2hlY2tzdW19YFxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgICAgXG4gICAgICAgIC8vIFNldCBwcm9wZXIgcGVybWlzc2lvbnNcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBhd2FpdCBmcy5jaG1vZChkZXN0UGF0aCwgRklMRV9DT05TVEFOVFMuRklMRV9QRVJNSVNTSU9OUyk7XG4gICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgbG9nZ2VyLmRlYnVnKFxuICAgICAgICAgICAgYFtEZWZhdWx0RWxlbWVudFByb3ZpZGVyXSBDb3VsZCBub3Qgc2V0IHBlcm1pc3Npb25zIG9uICR7ZGVzdFBhdGh9OiAke2Vycm9yfWAsXG4gICAgICAgICAgICB7IHNvdXJjZVBhdGgsIGRlc3RQYXRoLCBhdHRlbXB0IH1cbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICAgIFxuICAgICAgICAvLyBTdWNjZXNzIC0gZmlsZSBjb3BpZWQgYW5kIHZlcmlmaWVkXG4gICAgICAgIGxvZ2dlci5kZWJ1ZyhcbiAgICAgICAgICBgW0RlZmF1bHRFbGVtZW50UHJvdmlkZXJdIFN1Y2Nlc3NmdWxseSBjb3BpZWQgYW5kIHZlcmlmaWVkOiAke3BhdGguYmFzZW5hbWUoc291cmNlUGF0aCl9YCxcbiAgICAgICAgICB7IHNpemU6IHNvdXJjZVN0YXRzLnNpemUsIGNoZWNrc3VtOiBzb3VyY2VDaGVja3N1bS5zdWJzdHJpbmcoMCwgOCkgfVxuICAgICAgICApO1xuICAgICAgICByZXR1cm47XG4gICAgICAgIFxuICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgbGFzdEVycm9yID0gZXJyb3IgYXMgRXJyb3I7XG4gICAgICAgIFxuICAgICAgICAvLyBDbGVhbiB1cCBmYWlsZWQgY29weVxuICAgICAgICB0cnkge1xuICAgICAgICAgIGF3YWl0IGZzLnVubGluayhkZXN0UGF0aCk7XG4gICAgICAgIH0gY2F0Y2gge1xuICAgICAgICAgIC8vIElnbm9yZSBjbGVhbnVwIGVycm9yc1xuICAgICAgICB9XG4gICAgICAgIFxuICAgICAgICBpZiAoYXR0ZW1wdCA8IENPUFlfUkVUUllfQVRURU1QVFMpIHtcbiAgICAgICAgICBsb2dnZXIuZGVidWcoXG4gICAgICAgICAgICBgW0RlZmF1bHRFbGVtZW50UHJvdmlkZXJdIENvcHkgYXR0ZW1wdCAke2F0dGVtcHR9IGZhaWxlZCwgcmV0cnlpbmcuLi5gLFxuICAgICAgICAgICAgeyBlcnJvcjogbGFzdEVycm9yLm1lc3NhZ2UsIHNvdXJjZVBhdGgsIGRlc3RQYXRoIH1cbiAgICAgICAgICApO1xuICAgICAgICAgIGF3YWl0IG5ldyBQcm9taXNlKHJlc29sdmUgPT4gc2V0VGltZW91dChyZXNvbHZlLCBDT1BZX1JFVFJZX0RFTEFZICogYXR0ZW1wdCkpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIFxuICAgIC8vIEFsbCBhdHRlbXB0cyBmYWlsZWRcbiAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICBgRmFpbGVkIHRvIGNvcHkgJHtwYXRoLmJhc2VuYW1lKHNvdXJjZVBhdGgpfSBhZnRlciAke0NPUFlfUkVUUllfQVRURU1QVFN9IGF0dGVtcHRzOiBgICtcbiAgICAgIGAke2xhc3RFcnJvcj8ubWVzc2FnZSB8fCAnVW5rbm93biBlcnJvcid9YFxuICAgICk7XG4gIH1cbiAgXG4gIC8qKlxuICAgKiBQb3B1bGF0ZSB0aGUgcG9ydGZvbGlvIHdpdGggZGVmYXVsdCBlbGVtZW50cyBmcm9tIGJ1bmRsZWQgZGF0YVxuICAgKiBUaGlzIGlzIGNhbGxlZCBkdXJpbmcgcG9ydGZvbGlvIGluaXRpYWxpemF0aW9uIGZvciBuZXcgaW5zdGFsbGF0aW9uc1xuICAgKiBQcm90ZWN0ZWQgYWdhaW5zdCBjb25jdXJyZW50IGNhbGxzIHRvIHByZXZlbnQgcmFjZSBjb25kaXRpb25zXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgcG9wdWxhdGVEZWZhdWx0cyhwb3J0Zm9saW9CYXNlRGlyOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAvLyBDaGVjayBpZiBwb3B1bGF0aW9uIGlzIGFscmVhZHkgaW4gcHJvZ3Jlc3MgZm9yIHRoaXMgcG9ydGZvbGlvXG4gICAgY29uc3QgZXhpc3RpbmdQb3B1bGF0aW9uID0gRGVmYXVsdEVsZW1lbnRQcm92aWRlci5wb3B1bGF0ZUluUHJvZ3Jlc3MuZ2V0KHBvcnRmb2xpb0Jhc2VEaXIpO1xuICAgIGlmIChleGlzdGluZ1BvcHVsYXRpb24pIHtcbiAgICAgIGxvZ2dlci5kZWJ1ZyhcbiAgICAgICAgJ1tEZWZhdWx0RWxlbWVudFByb3ZpZGVyXSBQb3B1bGF0aW9uIGFscmVhZHkgaW4gcHJvZ3Jlc3MgZm9yIHBvcnRmb2xpbywgd2FpdGluZy4uLicsXG4gICAgICAgIHsgcG9ydGZvbGlvQmFzZURpciB9XG4gICAgICApO1xuICAgICAgcmV0dXJuIGV4aXN0aW5nUG9wdWxhdGlvbjtcbiAgICB9XG4gICAgXG4gICAgLy8gQ3JlYXRlIG5ldyBwb3B1bGF0aW9uIHByb21pc2VcbiAgICBjb25zdCBwb3B1bGF0aW9uUHJvbWlzZSA9IHRoaXMucGVyZm9ybVBvcHVsYXRpb24ocG9ydGZvbGlvQmFzZURpcilcbiAgICAgIC5maW5hbGx5KCgpID0+IHtcbiAgICAgICAgLy8gQ2xlYW4gdXAgd2hlbiBkb25lXG4gICAgICAgIERlZmF1bHRFbGVtZW50UHJvdmlkZXIucG9wdWxhdGVJblByb2dyZXNzLmRlbGV0ZShwb3J0Zm9saW9CYXNlRGlyKTtcbiAgICAgIH0pO1xuICAgIFxuICAgIERlZmF1bHRFbGVtZW50UHJvdmlkZXIucG9wdWxhdGVJblByb2dyZXNzLnNldChwb3J0Zm9saW9CYXNlRGlyLCBwb3B1bGF0aW9uUHJvbWlzZSk7XG4gICAgcmV0dXJuIHBvcHVsYXRpb25Qcm9taXNlO1xuICB9XG4gIFxuICAvKipcbiAgICogUGVyZm9ybSB0aGUgYWN0dWFsIHBvcHVsYXRpb24gb2YgZGVmYXVsdCBlbGVtZW50c1xuICAgKiBAcGFyYW0gcG9ydGZvbGlvQmFzZURpciBCYXNlIGRpcmVjdG9yeSBvZiB0aGUgcG9ydGZvbGlvXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIHBlcmZvcm1Qb3B1bGF0aW9uKHBvcnRmb2xpb0Jhc2VEaXI6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGxvZ2dlci5pbmZvKFxuICAgICAgJ1tEZWZhdWx0RWxlbWVudFByb3ZpZGVyXSBTdGFydGluZyBkZWZhdWx0IGVsZW1lbnQgcG9wdWxhdGlvbicsXG4gICAgICB7IHBvcnRmb2xpb0Jhc2VEaXIgfVxuICAgICk7XG4gICAgXG4gICAgLy8gTG9nIHNlY3VyaXR5IGV2ZW50IGZvciBwb3J0Zm9saW8gaW5pdGlhbGl6YXRpb25cbiAgICBTZWN1cml0eU1vbml0b3IubG9nU2VjdXJpdHlFdmVudCh7XG4gICAgICB0eXBlOiAnUE9SVEZPTElPX0lOSVRJQUxJWkFUSU9OJyxcbiAgICAgIHNldmVyaXR5OiAnTE9XJyxcbiAgICAgIHNvdXJjZTogJ0RlZmF1bHRFbGVtZW50UHJvdmlkZXIucGVyZm9ybVBvcHVsYXRpb24nLFxuICAgICAgZGV0YWlsczogYFN0YXJ0aW5nIGRlZmF1bHQgZWxlbWVudCBwb3B1bGF0aW9uIGZvciBwb3J0Zm9saW86ICR7cG9ydGZvbGlvQmFzZURpcn1gXG4gICAgfSk7XG4gICAgXG4gICAgLy8gRmluZCB0aGUgYnVuZGxlZCBkYXRhIGRpcmVjdG9yeVxuICAgIGNvbnN0IGRhdGFEaXIgPSBhd2FpdCB0aGlzLmZpbmREYXRhRGlyZWN0b3J5KCk7XG4gICAgaWYgKCFkYXRhRGlyKSB7XG4gICAgICBsb2dnZXIud2FybihcbiAgICAgICAgJ1tEZWZhdWx0RWxlbWVudFByb3ZpZGVyXSBObyBidW5kbGVkIGRhdGEgZGlyZWN0b3J5IGZvdW5kIC0gcG9ydGZvbGlvIHdpbGwgc3RhcnQgZW1wdHknLFxuICAgICAgICB7IFxuICAgICAgICAgIHNlYXJjaFBhdGhzOiB0aGlzLmRhdGFTZWFyY2hQYXRocy5zbGljZSgwLCAzKSwgLy8gTG9nIGZpcnN0IGZldyBwYXRocyBmb3IgZGVidWdnaW5nXG4gICAgICAgICAgY3dkOiBwcm9jZXNzLmN3ZCgpLFxuICAgICAgICAgIGRpcm5hbWU6IHRoaXMuX19kaXJuYW1lXG4gICAgICAgIH1cbiAgICAgICk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIFxuICAgIC8vIFRyYWNrIHRvdGFsIGZpbGVzIGNvcGllZFxuICAgIGxldCB0b3RhbENvcGllZCA9IDA7XG4gICAgY29uc3QgY29waWVkQ291bnRzOiBSZWNvcmQ8c3RyaW5nLCBudW1iZXI+ID0ge307XG4gICAgXG4gICAgLy8gTWFwIG9mIGRhdGEgc3ViZGlyZWN0b3J5IG5hbWVzIChwbHVyYWwpIHRvIHBvcnRmb2xpbyBkaXJlY3RvcnkgbmFtZXMgKHNpbmd1bGFyKVxuICAgIGNvbnN0IGVsZW1lbnRNYXBwaW5nczogUmVjb3JkPHN0cmluZywgRWxlbWVudFR5cGU+ID0ge1xuICAgICAgJ3BlcnNvbmFzJzogRWxlbWVudFR5cGUuUEVSU09OQSxcbiAgICAgICdza2lsbHMnOiBFbGVtZW50VHlwZS5TS0lMTCxcbiAgICAgICd0ZW1wbGF0ZXMnOiBFbGVtZW50VHlwZS5URU1QTEFURSxcbiAgICAgICdhZ2VudHMnOiBFbGVtZW50VHlwZS5BR0VOVCxcbiAgICAgICdtZW1vcmllcyc6IEVsZW1lbnRUeXBlLk1FTU9SWSxcbiAgICAgICdlbnNlbWJsZXMnOiBFbGVtZW50VHlwZS5FTlNFTUJMRVxuICAgIH07XG4gICAgXG4gICAgLy8gQ29weSBlYWNoIGVsZW1lbnQgdHlwZVxuICAgIGZvciAoY29uc3QgW2RhdGFTdWJkaXIsIGVsZW1lbnRUeXBlXSBvZiBPYmplY3QuZW50cmllcyhlbGVtZW50TWFwcGluZ3MpKSB7XG4gICAgICBjb25zdCBzb3VyY2VEaXIgPSBwYXRoLmpvaW4oZGF0YURpciwgZGF0YVN1YmRpcik7XG4gICAgICBjb25zdCBkZXN0RGlyID0gcGF0aC5qb2luKHBvcnRmb2xpb0Jhc2VEaXIsIGVsZW1lbnRUeXBlKTtcbiAgICAgIFxuICAgICAgdHJ5IHtcbiAgICAgICAgLy8gQ2hlY2sgaWYgc291cmNlIGRpcmVjdG9yeSBleGlzdHNcbiAgICAgICAgYXdhaXQgZnMuYWNjZXNzKHNvdXJjZURpcik7XG4gICAgICAgIGNvbnN0IGNvcGllZENvdW50ID0gYXdhaXQgdGhpcy5jb3B5RWxlbWVudEZpbGVzKHNvdXJjZURpciwgZGVzdERpciwgZGF0YVN1YmRpcik7XG4gICAgICAgIGNvcGllZENvdW50c1tkYXRhU3ViZGlyXSA9IGNvcGllZENvdW50O1xuICAgICAgICB0b3RhbENvcGllZCArPSBjb3BpZWRDb3VudDtcbiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgIC8vIFNvdXJjZSBkaXJlY3RvcnkgZG9lc24ndCBleGlzdCwgc2tpcFxuICAgICAgICBsb2dnZXIuZGVidWcoYFtEZWZhdWx0RWxlbWVudFByb3ZpZGVyXSBObyAke2RhdGFTdWJkaXJ9IGRpcmVjdG9yeSBpbiBidW5kbGVkIGRhdGFgKTtcbiAgICAgIH1cbiAgICB9XG4gICAgXG4gICAgaWYgKHRvdGFsQ29waWVkID4gMCkge1xuICAgICAgbG9nZ2VyLmluZm8oXG4gICAgICAgIGBbRGVmYXVsdEVsZW1lbnRQcm92aWRlcl0gU3VjY2Vzc2Z1bGx5IHBvcHVsYXRlZCBwb3J0Zm9saW8gd2l0aCAke3RvdGFsQ29waWVkfSBkZWZhdWx0IGVsZW1lbnQocylgLFxuICAgICAgICB7XG4gICAgICAgICAgcG9ydGZvbGlvQmFzZURpcixcbiAgICAgICAgICBkYXRhRGlyLFxuICAgICAgICAgIGJyZWFrZG93bjogT2JqZWN0LmVudHJpZXMoZWxlbWVudE1hcHBpbmdzKS5yZWR1Y2UoKGFjYywgW2RhdGFEaXIsIGVsZW1lbnRUeXBlXSkgPT4ge1xuICAgICAgICAgICAgYWNjW2VsZW1lbnRUeXBlXSA9IGNvcGllZENvdW50c1tkYXRhRGlyXSB8fCAwO1xuICAgICAgICAgICAgcmV0dXJuIGFjYztcbiAgICAgICAgICB9LCB7fSBhcyBSZWNvcmQ8c3RyaW5nLCBudW1iZXI+KVxuICAgICAgICB9XG4gICAgICApO1xuICAgICAgXG4gICAgICAvLyBMb2cgc2VjdXJpdHkgZXZlbnQgZm9yIHN1Y2Nlc3NmdWwgcG9wdWxhdGlvblxuICAgICAgU2VjdXJpdHlNb25pdG9yLmxvZ1NlY3VyaXR5RXZlbnQoe1xuICAgICAgICB0eXBlOiAnUE9SVEZPTElPX1BPUFVMQVRFRCcsXG4gICAgICAgIHNldmVyaXR5OiAnTE9XJyxcbiAgICAgICAgc291cmNlOiAnRGVmYXVsdEVsZW1lbnRQcm92aWRlci5wZXJmb3JtUG9wdWxhdGlvbicsXG4gICAgICAgIGRldGFpbHM6IGBTdWNjZXNzZnVsbHkgcG9wdWxhdGVkIHBvcnRmb2xpbyB3aXRoICR7dG90YWxDb3BpZWR9IGRlZmF1bHQgZWxlbWVudHNgLFxuICAgICAgICBtZXRhZGF0YToge1xuICAgICAgICAgIHBvcnRmb2xpb0Jhc2VEaXIsXG4gICAgICAgICAgZGF0YURpcixcbiAgICAgICAgICBjb3BpZWRDb3VudHNcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGxvZ2dlci5pbmZvKCdbRGVmYXVsdEVsZW1lbnRQcm92aWRlcl0gTm8gbmV3IGVsZW1lbnRzIHRvIGNvcHkgLSBwb3J0Zm9saW8gbWF5IGFscmVhZHkgaGF2ZSBjb250ZW50Jyk7XG4gICAgfVxuICB9XG59Il19
|
|
@@ -7,6 +7,8 @@ export type { PortfolioConfig };
|
|
|
7
7
|
export declare class PortfolioManager {
|
|
8
8
|
private static instance;
|
|
9
9
|
private static instanceLock;
|
|
10
|
+
private static initializationLock;
|
|
11
|
+
private static initializationPromise;
|
|
10
12
|
private baseDir;
|
|
11
13
|
private constructor();
|
|
12
14
|
static getInstance(config?: PortfolioConfig): PortfolioManager;
|
|
@@ -20,8 +22,13 @@ export declare class PortfolioManager {
|
|
|
20
22
|
getElementDir(type: ElementType): string;
|
|
21
23
|
/**
|
|
22
24
|
* Initialize the portfolio directory structure
|
|
25
|
+
* Uses locking to prevent race conditions during concurrent initialization
|
|
23
26
|
*/
|
|
24
27
|
initialize(): Promise<void>;
|
|
28
|
+
/**
|
|
29
|
+
* Perform the actual initialization - should only be called once
|
|
30
|
+
*/
|
|
31
|
+
private performInitialization;
|
|
25
32
|
/**
|
|
26
33
|
* Check if portfolio directory exists
|
|
27
34
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PortfolioManager.d.ts","sourceRoot":"","sources":["../../src/portfolio/PortfolioManager.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"PortfolioManager.d.ts","sourceRoot":"","sources":["../../src/portfolio/PortfolioManager.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAO1D,OAAO,EAAE,WAAW,EAAE,CAAC;AACvB,YAAY,EAAE,eAAe,EAAE,CAAC;AAEhC,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAmB;IAC1C,OAAO,CAAC,MAAM,CAAC,YAAY,CAAS;IACpC,OAAO,CAAC,MAAM,CAAC,kBAAkB,CAAS;IAC1C,OAAO,CAAC,MAAM,CAAC,qBAAqB,CAA8B;IAClE,OAAO,CAAC,OAAO,CAAS;IAExB,OAAO;WA4BO,WAAW,CAAC,MAAM,CAAC,EAAE,eAAe,GAAG,gBAAgB;IAiBrE;;OAEG;IACI,UAAU,IAAI,MAAM;IAI3B;;OAEG;IACI,aAAa,CAAC,IAAI,EAAE,WAAW,GAAG,MAAM;IAI/C;;;OAGG;IACU,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAuBxC;;OAEG;YACW,qBAAqB;IAgCnC;;OAEG;IACU,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC;IASvC;;OAEG;IACU,YAAY,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IA4C/D;;OAEG;IACI,cAAc,CAAC,IAAI,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM;IA0ClE;;OAEG;IACU,aAAa,CAAC,IAAI,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IASjF;;OAEG;IACI,oBAAoB,IAAI,MAAM;IAIrC;;OAEG;IACU,iBAAiB,IAAI,OAAO,CAAC,OAAO,CAAC;IAUlD;;OAEG;IACU,aAAa,IAAI,OAAO,CAAC,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;CAUnE"}
|