opencode-add-dir 1.0.4 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +87 -195
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +15 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/utils.d.ts +4 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +67 -0
- package/dist/utils.js.map +1 -0
- package/package.json +1 -1
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAgHlD,QAAA,MAAM,YAAY,EAAE,MAgDnB,CAAC;AAEF,eAAe,YAAY,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,234 +1,126 @@
|
|
|
1
1
|
import { tool } from '@opencode-ai/plugin/tool';
|
|
2
2
|
import fs from 'fs';
|
|
3
3
|
import path from 'path';
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
'venv',
|
|
13
|
-
'env',
|
|
14
|
-
'.env',
|
|
15
|
-
'coverage',
|
|
16
|
-
'.nuxt',
|
|
17
|
-
'.output',
|
|
18
|
-
'tmp',
|
|
19
|
-
'temp',
|
|
20
|
-
'.turbo'
|
|
21
|
-
]);
|
|
22
|
-
const BINARY_EXTENSIONS = new Set([
|
|
23
|
-
'.png', '.jpg', '.jpeg', '.gif', '.bmp', '.ico', '.svg', '.webp',
|
|
24
|
-
'.pdf', '.doc', '.docx', '.xls', '.xlsx', '.ppt', '.pptx',
|
|
25
|
-
'.zip', '.tar', '.gz', '.rar', '.7z',
|
|
26
|
-
'.mp3', '.mp4', '.avi', '.mov', '.wav',
|
|
27
|
-
'.exe', '.dll', '.so', '.dylib', '.bin',
|
|
28
|
-
'.class', '.jar', '.war',
|
|
29
|
-
'.pyc', '.pyo',
|
|
30
|
-
'.db', '.sqlite', '.sqlite3',
|
|
31
|
-
'.lock', '.log'
|
|
32
|
-
]);
|
|
33
|
-
const MAX_FILE_SIZE_BYTES = 100 * 1024;
|
|
34
|
-
const MAX_FILES = 500;
|
|
35
|
-
const ADDED_DIRS_FILE = path.join(__dirname, '.added-dirs.json');
|
|
36
|
-
function getAddedDirectories() {
|
|
4
|
+
import { validateDirectory, countFiles } from './utils.js';
|
|
5
|
+
const SESSIONS_FILE = path.join(__dirname, '.sessions.json');
|
|
6
|
+
const MAX_SESSIONS = 50;
|
|
7
|
+
const SESSION_AGE_DAYS = 30;
|
|
8
|
+
const CLEANUP_INTERVAL_MS = 3600000;
|
|
9
|
+
const LAST_ACCESS_UPDATE_MS = 3600000;
|
|
10
|
+
let lastCleaned = 0;
|
|
11
|
+
function readSessions() {
|
|
37
12
|
try {
|
|
38
|
-
if (fs.existsSync(
|
|
39
|
-
|
|
40
|
-
const data = JSON.parse(content);
|
|
41
|
-
return new Set(data.directories);
|
|
13
|
+
if (fs.existsSync(SESSIONS_FILE)) {
|
|
14
|
+
return JSON.parse(fs.readFileSync(SESSIONS_FILE, 'utf-8'));
|
|
42
15
|
}
|
|
43
16
|
}
|
|
44
17
|
catch (error) {
|
|
45
|
-
console.error('Failed to read
|
|
18
|
+
console.error('Failed to read sessions:', error);
|
|
46
19
|
}
|
|
47
|
-
return
|
|
20
|
+
return {};
|
|
48
21
|
}
|
|
49
|
-
function
|
|
50
|
-
|
|
51
|
-
const normalizedPath = path.resolve(dirPath);
|
|
52
|
-
if (!added.has(normalizedPath)) {
|
|
53
|
-
added.add(normalizedPath);
|
|
54
|
-
const data = { directories: Array.from(added) };
|
|
55
|
-
fs.writeFileSync(ADDED_DIRS_FILE, JSON.stringify(data, null, 2));
|
|
56
|
-
}
|
|
22
|
+
function writeSessions(sessions) {
|
|
23
|
+
fs.writeFileSync(SESSIONS_FILE, JSON.stringify(sessions, null, 2));
|
|
57
24
|
}
|
|
58
|
-
function
|
|
59
|
-
const
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
const
|
|
63
|
-
if (
|
|
64
|
-
|
|
25
|
+
function getSessionDirs(sessionId) {
|
|
26
|
+
const sessions = readSessions();
|
|
27
|
+
const session = sessions[sessionId];
|
|
28
|
+
if (session) {
|
|
29
|
+
const now = Date.now();
|
|
30
|
+
if (now - session.lastAccessed > LAST_ACCESS_UPDATE_MS) {
|
|
31
|
+
session.lastAccessed = now;
|
|
32
|
+
writeSessions(sessions);
|
|
65
33
|
}
|
|
34
|
+
return session.dirs;
|
|
66
35
|
}
|
|
67
|
-
return
|
|
68
|
-
}
|
|
69
|
-
function isBinaryFile(filePath) {
|
|
70
|
-
const ext = path.extname(filePath).toLowerCase();
|
|
71
|
-
return BINARY_EXTENSIONS.has(ext);
|
|
36
|
+
return [];
|
|
72
37
|
}
|
|
73
|
-
function
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
if (a.isDirectory() && !b.isDirectory()) {
|
|
79
|
-
return -1;
|
|
80
|
-
}
|
|
81
|
-
if (!a.isDirectory() && b.isDirectory()) {
|
|
82
|
-
return 1;
|
|
83
|
-
}
|
|
84
|
-
return a.name.localeCompare(b.name);
|
|
85
|
-
});
|
|
86
|
-
}
|
|
87
|
-
function createTreeEntry(name, isDirectory, depth) {
|
|
88
|
-
const indent = ' '.repeat(depth);
|
|
89
|
-
const suffix = isDirectory ? '/' : '';
|
|
90
|
-
return `${indent}${name}${suffix}`;
|
|
91
|
-
}
|
|
92
|
-
function readFileContent(filePath, maxSize) {
|
|
93
|
-
try {
|
|
94
|
-
const content = fs.readFileSync(filePath, 'utf-8');
|
|
95
|
-
if (content.length > maxSize) {
|
|
96
|
-
return {
|
|
97
|
-
content: content.slice(0, maxSize),
|
|
98
|
-
isTruncated: true
|
|
99
|
-
};
|
|
100
|
-
}
|
|
101
|
-
return {
|
|
102
|
-
content,
|
|
103
|
-
isTruncated: false
|
|
104
|
-
};
|
|
38
|
+
function addSessionDir(sessionId, dirPath) {
|
|
39
|
+
const sessions = readSessions();
|
|
40
|
+
const normalized = path.resolve(dirPath);
|
|
41
|
+
if (!sessions[sessionId]) {
|
|
42
|
+
sessions[sessionId] = { dirs: [], lastAccessed: Date.now() };
|
|
105
43
|
}
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
};
|
|
44
|
+
if (!sessions[sessionId].dirs.includes(normalized)) {
|
|
45
|
+
sessions[sessionId].dirs.push(normalized);
|
|
46
|
+
sessions[sessionId].lastAccessed = Date.now();
|
|
47
|
+
writeSessions(sessions);
|
|
111
48
|
}
|
|
112
49
|
}
|
|
113
|
-
function
|
|
114
|
-
const
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
const
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
result.files = nestedResult.files;
|
|
122
|
-
result.tree = nestedResult.tree;
|
|
123
|
-
result.fileCount = nestedResult.fileCount;
|
|
124
|
-
result.skipped += nestedResult.skipped;
|
|
125
|
-
}
|
|
126
|
-
function processFile(fullPath, baseDir, depth, result) {
|
|
127
|
-
const relativePath = path.relative(baseDir, fullPath);
|
|
128
|
-
const fileName = path.basename(fullPath);
|
|
129
|
-
result.tree.push(createTreeEntry(fileName, false, depth));
|
|
130
|
-
const stats = fs.statSync(fullPath);
|
|
131
|
-
const contentResult = readFileContent(fullPath, MAX_FILE_SIZE_BYTES);
|
|
132
|
-
result.files.push({
|
|
133
|
-
path: relativePath,
|
|
134
|
-
size: stats.size,
|
|
135
|
-
content: contentResult.content,
|
|
136
|
-
isTruncated: contentResult.isTruncated
|
|
137
|
-
});
|
|
138
|
-
result.fileCount++;
|
|
139
|
-
}
|
|
140
|
-
function processEntry(entry, dirPath, baseDir, depth, result) {
|
|
141
|
-
if (result.fileCount >= MAX_FILES) {
|
|
142
|
-
return;
|
|
143
|
-
}
|
|
144
|
-
if (entry.isDirectory()) {
|
|
145
|
-
if (shouldIgnoreDirectory(entry.name)) {
|
|
146
|
-
result.skipped++;
|
|
50
|
+
function cleanOldSessions() {
|
|
51
|
+
const sessions = readSessions();
|
|
52
|
+
const now = Date.now();
|
|
53
|
+
const maxAge = SESSION_AGE_DAYS * 24 * 60 * 60 * 1000;
|
|
54
|
+
const entries = Object.entries(sessions);
|
|
55
|
+
const recentSessions = entries.filter(([, data]) => now - data.lastAccessed < maxAge);
|
|
56
|
+
if (recentSessions.length <= MAX_SESSIONS) {
|
|
57
|
+
if (recentSessions.length === entries.length) {
|
|
147
58
|
return;
|
|
148
59
|
}
|
|
149
|
-
processDirectory(entry, dirPath, baseDir, depth, result);
|
|
150
|
-
return;
|
|
151
|
-
}
|
|
152
|
-
if (!entry.isFile()) {
|
|
153
|
-
result.skipped++;
|
|
154
|
-
return;
|
|
155
60
|
}
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
61
|
+
else {
|
|
62
|
+
recentSessions.sort(([, a], [, b]) => b.lastAccessed - a.lastAccessed);
|
|
63
|
+
recentSessions.splice(MAX_SESSIONS);
|
|
159
64
|
}
|
|
160
|
-
const
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
processFile(fullPath, baseDir, depth, result);
|
|
65
|
+
const cleanedSessions = {};
|
|
66
|
+
recentSessions.forEach(([id, data]) => {
|
|
67
|
+
cleanedSessions[id] = data;
|
|
68
|
+
});
|
|
69
|
+
writeSessions(cleanedSessions);
|
|
166
70
|
}
|
|
167
|
-
function
|
|
168
|
-
const
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
for (const entry of sortedEntries) {
|
|
177
|
-
processEntry(entry, dirPath, baseDir, depth, result);
|
|
71
|
+
function isInSessionDirs(filePath, dirs) {
|
|
72
|
+
const normalizedFilePath = path.resolve(filePath);
|
|
73
|
+
for (const dir of dirs) {
|
|
74
|
+
const normalizedDir = path.resolve(dir);
|
|
75
|
+
const relative = path.relative(normalizedDir, normalizedFilePath);
|
|
76
|
+
const isInside = !relative.startsWith('..') && !path.isAbsolute(relative);
|
|
77
|
+
if (isInside) {
|
|
78
|
+
return true;
|
|
79
|
+
}
|
|
178
80
|
}
|
|
179
|
-
return
|
|
81
|
+
return false;
|
|
180
82
|
}
|
|
181
83
|
const addDirPlugin = async () => {
|
|
182
84
|
return {
|
|
183
85
|
tool: {
|
|
184
86
|
add_dir: tool({
|
|
185
|
-
description: 'Add
|
|
87
|
+
description: 'Add a directory to the workspace. Access is auto-approved for files in added directories.',
|
|
186
88
|
args: {
|
|
187
|
-
directory: tool.schema.string().describe('
|
|
89
|
+
directory: tool.schema.string().describe('Absolute path to the directory')
|
|
188
90
|
},
|
|
189
|
-
execute: async ({ directory }) => {
|
|
91
|
+
execute: async ({ directory }, context) => {
|
|
92
|
+
const sessionId = context.sessionID;
|
|
190
93
|
const resolvedPath = path.resolve(directory);
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
if (!fs.statSync(resolvedPath).isDirectory()) {
|
|
195
|
-
throw new Error(`Path is not a directory: ${resolvedPath}`);
|
|
196
|
-
}
|
|
197
|
-
try {
|
|
198
|
-
fs.accessSync(resolvedPath, fs.constants.R_OK);
|
|
199
|
-
}
|
|
200
|
-
catch (error) {
|
|
201
|
-
throw new Error(`Permission denied: Cannot read directory ${resolvedPath}`);
|
|
202
|
-
}
|
|
203
|
-
const scanResult = scanDirectory(resolvedPath, resolvedPath);
|
|
204
|
-
const totalFound = scanResult.fileCount + scanResult.skipped;
|
|
205
|
-
const filesTooLarge = scanResult.skipped;
|
|
206
|
-
const output = {
|
|
207
|
-
directory: resolvedPath,
|
|
208
|
-
totalFilesFound: totalFound,
|
|
209
|
-
filesProcessed: scanResult.fileCount,
|
|
210
|
-
filesSkipped: scanResult.skipped - filesTooLarge,
|
|
211
|
-
filesTooLarge,
|
|
212
|
-
tree: scanResult.tree,
|
|
213
|
-
files: scanResult.files
|
|
214
|
-
};
|
|
215
|
-
saveAddedDirectory(resolvedPath);
|
|
94
|
+
validateDirectory(resolvedPath);
|
|
95
|
+
addSessionDir(sessionId, resolvedPath);
|
|
96
|
+
const fileCount = countFiles(resolvedPath);
|
|
216
97
|
return JSON.stringify({
|
|
217
|
-
|
|
218
|
-
|
|
98
|
+
directory: resolvedPath,
|
|
99
|
+
status: 'added',
|
|
100
|
+
message: 'Directory added to workspace',
|
|
101
|
+
fileCount
|
|
219
102
|
}, null, 2);
|
|
220
103
|
}
|
|
221
104
|
})
|
|
222
105
|
},
|
|
106
|
+
'chat.message': async (context) => {
|
|
107
|
+
getSessionDirs(context.sessionID);
|
|
108
|
+
const now = Date.now();
|
|
109
|
+
if (now - lastCleaned > CLEANUP_INTERVAL_MS) {
|
|
110
|
+
cleanOldSessions();
|
|
111
|
+
lastCleaned = now;
|
|
112
|
+
}
|
|
113
|
+
},
|
|
223
114
|
'permission.ask': async (input, output) => {
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
115
|
+
const dirs = getSessionDirs(input.sessionID);
|
|
116
|
+
const check = (value) => typeof value === 'string' && isInSessionDirs(value, dirs);
|
|
117
|
+
const approved = [
|
|
118
|
+
check(input.title),
|
|
119
|
+
(input.pattern ? (Array.isArray(input.pattern) ? input.pattern : [input.pattern]) : []).some(check),
|
|
120
|
+
Object.values(input.metadata || {}).flat().some(check)
|
|
121
|
+
].some(Boolean);
|
|
122
|
+
if (approved) {
|
|
123
|
+
output.status = 'allow';
|
|
232
124
|
}
|
|
233
125
|
}
|
|
234
126
|
};
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,0BAA0B,CAAC;AAGhD,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export interface AddedDirectory {
|
|
2
|
+
directory: string;
|
|
3
|
+
addedAt: number;
|
|
4
|
+
}
|
|
5
|
+
export interface SessionDirectories {
|
|
6
|
+
sessionId: string;
|
|
7
|
+
directories: AddedDirectory[];
|
|
8
|
+
}
|
|
9
|
+
export interface AddDirResult {
|
|
10
|
+
directory: string;
|
|
11
|
+
status: 'added' | 'error';
|
|
12
|
+
message: string;
|
|
13
|
+
fileCount?: number;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,cAAc,EAAE,CAAC;CAC/B;AAED,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
package/dist/utils.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAsBA,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAE3D;AAED,wBAAgB,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CA+BpD;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAgBvD"}
|
package/dist/utils.js
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
const IGNORED_DIRECTORIES = new Set([
|
|
4
|
+
'node_modules',
|
|
5
|
+
'.git',
|
|
6
|
+
'dist',
|
|
7
|
+
'build',
|
|
8
|
+
'.next',
|
|
9
|
+
'__pycache__',
|
|
10
|
+
'.venv',
|
|
11
|
+
'venv',
|
|
12
|
+
'env',
|
|
13
|
+
'.env',
|
|
14
|
+
'coverage',
|
|
15
|
+
'.nuxt',
|
|
16
|
+
'.output',
|
|
17
|
+
'tmp',
|
|
18
|
+
'temp',
|
|
19
|
+
'.turbo'
|
|
20
|
+
]);
|
|
21
|
+
export function isIgnoredDirectory(dirName) {
|
|
22
|
+
return IGNORED_DIRECTORIES.has(dirName);
|
|
23
|
+
}
|
|
24
|
+
export function countFiles(directory) {
|
|
25
|
+
let fileCount = 0;
|
|
26
|
+
function scanDir(dir) {
|
|
27
|
+
try {
|
|
28
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
29
|
+
for (const entry of entries) {
|
|
30
|
+
if (isIgnoredDirectory(entry.name)) {
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
if (entry.isSymbolicLink()) {
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
const fullPath = path.join(dir, entry.name);
|
|
37
|
+
if (entry.isDirectory()) {
|
|
38
|
+
scanDir(fullPath);
|
|
39
|
+
}
|
|
40
|
+
else if (entry.isFile()) {
|
|
41
|
+
fileCount++;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
console.error(`Error scanning ${dir}:`, error);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
scanDir(directory);
|
|
50
|
+
return fileCount;
|
|
51
|
+
}
|
|
52
|
+
export function validateDirectory(dirPath) {
|
|
53
|
+
if (!fs.existsSync(dirPath)) {
|
|
54
|
+
throw new Error(`Directory does not exist: ${dirPath}`);
|
|
55
|
+
}
|
|
56
|
+
const stats = fs.statSync(dirPath);
|
|
57
|
+
if (!stats.isDirectory()) {
|
|
58
|
+
throw new Error(`Path is not a directory: ${dirPath}`);
|
|
59
|
+
}
|
|
60
|
+
try {
|
|
61
|
+
fs.accessSync(dirPath, fs.constants.R_OK);
|
|
62
|
+
}
|
|
63
|
+
catch (error) {
|
|
64
|
+
throw new Error(`Permission denied: Cannot read directory ${dirPath}`);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,MAAM,mBAAmB,GAAG,IAAI,GAAG,CAAC;IAClC,cAAc;IACd,MAAM;IACN,MAAM;IACN,OAAO;IACP,OAAO;IACP,aAAa;IACb,OAAO;IACP,MAAM;IACN,KAAK;IACL,MAAM;IACN,UAAU;IACV,OAAO;IACP,SAAS;IACT,KAAK;IACL,MAAM;IACN,QAAQ;CACT,CAAC,CAAC;AAEH,MAAM,UAAU,kBAAkB,CAAC,OAAe;IAChD,OAAO,mBAAmB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;AAC1C,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,SAAiB;IAC1C,IAAI,SAAS,GAAG,CAAC,CAAC;IAElB,SAAS,OAAO,CAAC,GAAW;QAC1B,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,EAAE,CAAC,WAAW,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;YAE7D,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;gBAC5B,IAAI,kBAAkB,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;oBACnC,SAAS;gBACX,CAAC;gBAED,IAAI,KAAK,CAAC,cAAc,EAAE,EAAE,CAAC;oBAC3B,SAAS;gBACX,CAAC;gBAED,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;gBAE5C,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;oBACxB,OAAO,CAAC,QAAQ,CAAC,CAAC;gBACpB,CAAC;qBAAM,IAAI,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC;oBAC1B,SAAS,EAAE,CAAC;gBACd,CAAC;YACH,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,kBAAkB,GAAG,GAAG,EAAE,KAAK,CAAC,CAAC;QACjD,CAAC;IACH,CAAC;IAED,OAAO,CAAC,SAAS,CAAC,CAAC;IACnB,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,OAAe;IAC/C,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CAAC,6BAA6B,OAAO,EAAE,CAAC,CAAC;IAC1D,CAAC;IAED,MAAM,KAAK,GAAG,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IAEnC,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;QACzB,MAAM,IAAI,KAAK,CAAC,4BAA4B,OAAO,EAAE,CAAC,CAAC;IACzD,CAAC;IAED,IAAI,CAAC;QACH,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IAC5C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,4CAA4C,OAAO,EAAE,CAAC,CAAC;IACzE,CAAC;AACH,CAAC"}
|