opencode-mem 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 +588 -0
- package/dist/config.d.ts +33 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +258 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +618 -0
- package/dist/plugin.d.ts +5 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +15 -0
- package/dist/services/api-handlers.d.ts +102 -0
- package/dist/services/api-handlers.d.ts.map +1 -0
- package/dist/services/api-handlers.js +494 -0
- package/dist/services/auto-capture.d.ts +32 -0
- package/dist/services/auto-capture.d.ts.map +1 -0
- package/dist/services/auto-capture.js +451 -0
- package/dist/services/cleanup-service.d.ts +20 -0
- package/dist/services/cleanup-service.d.ts.map +1 -0
- package/dist/services/cleanup-service.js +88 -0
- package/dist/services/client.d.ts +104 -0
- package/dist/services/client.d.ts.map +1 -0
- package/dist/services/client.js +251 -0
- package/dist/services/compaction.d.ts +92 -0
- package/dist/services/compaction.d.ts.map +1 -0
- package/dist/services/compaction.js +421 -0
- package/dist/services/context.d.ts +17 -0
- package/dist/services/context.d.ts.map +1 -0
- package/dist/services/context.js +41 -0
- package/dist/services/deduplication-service.d.ts +30 -0
- package/dist/services/deduplication-service.d.ts.map +1 -0
- package/dist/services/deduplication-service.js +131 -0
- package/dist/services/embedding.d.ts +10 -0
- package/dist/services/embedding.d.ts.map +1 -0
- package/dist/services/embedding.js +77 -0
- package/dist/services/jsonc.d.ts +7 -0
- package/dist/services/jsonc.d.ts.map +1 -0
- package/dist/services/jsonc.js +76 -0
- package/dist/services/logger.d.ts +2 -0
- package/dist/services/logger.d.ts.map +1 -0
- package/dist/services/logger.js +16 -0
- package/dist/services/migration-service.d.ts +42 -0
- package/dist/services/migration-service.d.ts.map +1 -0
- package/dist/services/migration-service.js +258 -0
- package/dist/services/privacy.d.ts +4 -0
- package/dist/services/privacy.d.ts.map +1 -0
- package/dist/services/privacy.js +10 -0
- package/dist/services/sqlite/connection-manager.d.ts +10 -0
- package/dist/services/sqlite/connection-manager.d.ts.map +1 -0
- package/dist/services/sqlite/connection-manager.js +45 -0
- package/dist/services/sqlite/shard-manager.d.ts +20 -0
- package/dist/services/sqlite/shard-manager.d.ts.map +1 -0
- package/dist/services/sqlite/shard-manager.js +221 -0
- package/dist/services/sqlite/types.d.ts +39 -0
- package/dist/services/sqlite/types.d.ts.map +1 -0
- package/dist/services/sqlite/types.js +1 -0
- package/dist/services/sqlite/vector-search.d.ts +18 -0
- package/dist/services/sqlite/vector-search.d.ts.map +1 -0
- package/dist/services/sqlite/vector-search.js +129 -0
- package/dist/services/sqlite-client.d.ts +116 -0
- package/dist/services/sqlite-client.d.ts.map +1 -0
- package/dist/services/sqlite-client.js +284 -0
- package/dist/services/tags.d.ts +20 -0
- package/dist/services/tags.d.ts.map +1 -0
- package/dist/services/tags.js +76 -0
- package/dist/services/web-server-lock.d.ts +12 -0
- package/dist/services/web-server-lock.d.ts.map +1 -0
- package/dist/services/web-server-lock.js +157 -0
- package/dist/services/web-server-worker.d.ts +2 -0
- package/dist/services/web-server-worker.d.ts.map +1 -0
- package/dist/services/web-server-worker.js +221 -0
- package/dist/services/web-server.d.ts +22 -0
- package/dist/services/web-server.d.ts.map +1 -0
- package/dist/services/web-server.js +134 -0
- package/dist/types/index.d.ts +48 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +1 -0
- package/dist/web/app.d.ts +2 -0
- package/dist/web/app.d.ts.map +1 -0
- package/dist/web/app.js +691 -0
- package/dist/web/favicon.ico +0 -0
- package/dist/web/favicon.svg +14 -0
- package/dist/web/index.html +202 -0
- package/dist/web/styles.css +851 -0
- package/package.json +52 -0
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
import { embeddingService } from "./embedding.js";
|
|
2
|
+
import { shardManager } from "./sqlite/shard-manager.js";
|
|
3
|
+
import { vectorSearch } from "./sqlite/vector-search.js";
|
|
4
|
+
import { connectionManager } from "./sqlite/connection-manager.js";
|
|
5
|
+
import { CONFIG } from "../config.js";
|
|
6
|
+
import { log } from "./logger.js";
|
|
7
|
+
function safeToISOString(timestamp) {
|
|
8
|
+
try {
|
|
9
|
+
if (timestamp === null || timestamp === undefined) {
|
|
10
|
+
return new Date().toISOString();
|
|
11
|
+
}
|
|
12
|
+
const numValue = typeof timestamp === "bigint" ? Number(timestamp) : Number(timestamp);
|
|
13
|
+
if (isNaN(numValue) || numValue < 0) {
|
|
14
|
+
return new Date().toISOString();
|
|
15
|
+
}
|
|
16
|
+
return new Date(numValue).toISOString();
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
return new Date().toISOString();
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
function safeJSONParse(jsonString) {
|
|
23
|
+
if (!jsonString || typeof jsonString !== "string") {
|
|
24
|
+
return undefined;
|
|
25
|
+
}
|
|
26
|
+
try {
|
|
27
|
+
return JSON.parse(jsonString);
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return undefined;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
function extractScopeFromContainerTag(containerTag) {
|
|
34
|
+
const parts = containerTag.split("_");
|
|
35
|
+
if (parts.length >= 3) {
|
|
36
|
+
const scope = parts[1];
|
|
37
|
+
const hash = parts.slice(2).join("_");
|
|
38
|
+
return { scope, hash };
|
|
39
|
+
}
|
|
40
|
+
return { scope: "user", hash: containerTag };
|
|
41
|
+
}
|
|
42
|
+
export class LocalMemoryClient {
|
|
43
|
+
initPromise = null;
|
|
44
|
+
isInitialized = false;
|
|
45
|
+
constructor() { }
|
|
46
|
+
async initialize() {
|
|
47
|
+
if (this.isInitialized)
|
|
48
|
+
return;
|
|
49
|
+
if (this.initPromise)
|
|
50
|
+
return this.initPromise;
|
|
51
|
+
this.initPromise = (async () => {
|
|
52
|
+
try {
|
|
53
|
+
this.isInitialized = true;
|
|
54
|
+
log("SQLite memory client initialized");
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
this.initPromise = null;
|
|
58
|
+
log("SQLite initialization failed", { error: String(error) });
|
|
59
|
+
throw error;
|
|
60
|
+
}
|
|
61
|
+
})();
|
|
62
|
+
return this.initPromise;
|
|
63
|
+
}
|
|
64
|
+
async warmup(progressCallback) {
|
|
65
|
+
await this.initialize();
|
|
66
|
+
await embeddingService.warmup(progressCallback);
|
|
67
|
+
}
|
|
68
|
+
async isReady() {
|
|
69
|
+
return this.isInitialized && embeddingService.isWarmedUp;
|
|
70
|
+
}
|
|
71
|
+
getStatus() {
|
|
72
|
+
return {
|
|
73
|
+
dbConnected: this.isInitialized,
|
|
74
|
+
modelLoaded: embeddingService.isWarmedUp,
|
|
75
|
+
ready: this.isInitialized && embeddingService.isWarmedUp,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
async searchMemories(query, containerTag) {
|
|
79
|
+
log("searchMemories: start", { containerTag });
|
|
80
|
+
try {
|
|
81
|
+
await this.initialize();
|
|
82
|
+
const queryVector = await embeddingService.embedWithTimeout(query);
|
|
83
|
+
const { scope, hash } = extractScopeFromContainerTag(containerTag);
|
|
84
|
+
const shards = shardManager.getAllShards(scope, hash);
|
|
85
|
+
if (shards.length === 0) {
|
|
86
|
+
log("searchMemories: no shards found", { containerTag });
|
|
87
|
+
return { success: true, results: [], total: 0, timing: 0 };
|
|
88
|
+
}
|
|
89
|
+
const results = await vectorSearch.searchAcrossShards(shards, queryVector, containerTag, CONFIG.maxMemories, CONFIG.similarityThreshold);
|
|
90
|
+
log("searchMemories: success", { count: results.length });
|
|
91
|
+
return { success: true, results, total: results.length, timing: 0 };
|
|
92
|
+
}
|
|
93
|
+
catch (error) {
|
|
94
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
95
|
+
log("searchMemories: error", { error: errorMessage });
|
|
96
|
+
return { success: false, error: errorMessage, results: [], total: 0, timing: 0 };
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
async getProfile(containerTag, query) {
|
|
100
|
+
log("getProfile: start", { containerTag });
|
|
101
|
+
try {
|
|
102
|
+
await this.initialize();
|
|
103
|
+
const { scope, hash } = extractScopeFromContainerTag(containerTag);
|
|
104
|
+
const shards = shardManager.getAllShards(scope, hash);
|
|
105
|
+
if (shards.length === 0) {
|
|
106
|
+
log("getProfile: no shards found", { containerTag });
|
|
107
|
+
return { success: true, profile: { static: [], dynamic: [] } };
|
|
108
|
+
}
|
|
109
|
+
const staticFacts = [];
|
|
110
|
+
const dynamicFacts = [];
|
|
111
|
+
for (const shard of shards) {
|
|
112
|
+
const db = connectionManager.getConnection(shard.dbPath);
|
|
113
|
+
const memories = vectorSearch.listMemories(db, containerTag, CONFIG.maxProfileItems * 2);
|
|
114
|
+
for (const m of memories) {
|
|
115
|
+
if (m.type === "preference") {
|
|
116
|
+
staticFacts.push(m.content);
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
dynamicFacts.push(m.content);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
const profile = {
|
|
124
|
+
static: staticFacts.slice(0, CONFIG.maxProfileItems),
|
|
125
|
+
dynamic: dynamicFacts.slice(0, CONFIG.maxProfileItems),
|
|
126
|
+
};
|
|
127
|
+
log("getProfile: success", { hasProfile: true });
|
|
128
|
+
return { success: true, profile };
|
|
129
|
+
}
|
|
130
|
+
catch (error) {
|
|
131
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
132
|
+
log("getProfile: error", { error: errorMessage });
|
|
133
|
+
return { success: false, error: errorMessage, profile: null };
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
async addMemory(content, containerTag, metadata) {
|
|
137
|
+
log("addMemory: start", { containerTag, contentLength: content.length });
|
|
138
|
+
try {
|
|
139
|
+
await this.initialize();
|
|
140
|
+
const vector = await embeddingService.embedWithTimeout(content);
|
|
141
|
+
const { scope, hash } = extractScopeFromContainerTag(containerTag);
|
|
142
|
+
const shard = shardManager.getWriteShard(scope, hash);
|
|
143
|
+
const id = `mem_${Date.now()}_${Math.random().toString(36).substring(2, 11)}`;
|
|
144
|
+
const now = Date.now();
|
|
145
|
+
const { displayName, userName, userEmail, projectPath, projectName, gitRepoUrl, type, ...dynamicMetadata } = metadata || {};
|
|
146
|
+
const record = {
|
|
147
|
+
id,
|
|
148
|
+
content,
|
|
149
|
+
vector,
|
|
150
|
+
containerTag,
|
|
151
|
+
type,
|
|
152
|
+
createdAt: now,
|
|
153
|
+
updatedAt: now,
|
|
154
|
+
displayName,
|
|
155
|
+
userName,
|
|
156
|
+
userEmail,
|
|
157
|
+
projectPath,
|
|
158
|
+
projectName,
|
|
159
|
+
gitRepoUrl,
|
|
160
|
+
metadata: Object.keys(dynamicMetadata).length > 0 ? JSON.stringify(dynamicMetadata) : undefined,
|
|
161
|
+
};
|
|
162
|
+
const db = connectionManager.getConnection(shard.dbPath);
|
|
163
|
+
vectorSearch.insertVector(db, record);
|
|
164
|
+
shardManager.incrementVectorCount(shard.id);
|
|
165
|
+
log("addMemory: success", { id, shardId: shard.id });
|
|
166
|
+
return { success: true, id };
|
|
167
|
+
}
|
|
168
|
+
catch (error) {
|
|
169
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
170
|
+
log("addMemory: error", { error: errorMessage });
|
|
171
|
+
return { success: false, error: errorMessage };
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
async deleteMemory(memoryId) {
|
|
175
|
+
log("deleteMemory: start", { memoryId });
|
|
176
|
+
try {
|
|
177
|
+
await this.initialize();
|
|
178
|
+
const { scope, hash } = extractScopeFromContainerTag(memoryId);
|
|
179
|
+
const shards = shardManager.getAllShards(scope, hash);
|
|
180
|
+
for (const shard of shards) {
|
|
181
|
+
const db = connectionManager.getConnection(shard.dbPath);
|
|
182
|
+
const memory = vectorSearch.getMemoryById(db, memoryId);
|
|
183
|
+
if (memory) {
|
|
184
|
+
vectorSearch.deleteVector(db, memoryId);
|
|
185
|
+
shardManager.decrementVectorCount(shard.id);
|
|
186
|
+
log("deleteMemory: success", { memoryId, shardId: shard.id });
|
|
187
|
+
return { success: true };
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
log("deleteMemory: not found", { memoryId });
|
|
191
|
+
return { success: false, error: "Memory not found" };
|
|
192
|
+
}
|
|
193
|
+
catch (error) {
|
|
194
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
195
|
+
log("deleteMemory: error", { memoryId, error: errorMessage });
|
|
196
|
+
return { success: false, error: errorMessage };
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
async listMemories(containerTag, limit = 20) {
|
|
200
|
+
log("listMemories: start", { containerTag, limit });
|
|
201
|
+
try {
|
|
202
|
+
await this.initialize();
|
|
203
|
+
const { scope, hash } = extractScopeFromContainerTag(containerTag);
|
|
204
|
+
const shards = shardManager.getAllShards(scope, hash);
|
|
205
|
+
if (shards.length === 0) {
|
|
206
|
+
log("listMemories: no shards found", { containerTag });
|
|
207
|
+
return {
|
|
208
|
+
success: true,
|
|
209
|
+
memories: [],
|
|
210
|
+
pagination: { currentPage: 1, totalItems: 0, totalPages: 0 },
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
const allMemories = [];
|
|
214
|
+
for (const shard of shards) {
|
|
215
|
+
const db = connectionManager.getConnection(shard.dbPath);
|
|
216
|
+
const memories = vectorSearch.listMemories(db, containerTag, limit);
|
|
217
|
+
allMemories.push(...memories);
|
|
218
|
+
}
|
|
219
|
+
allMemories.sort((a, b) => Number(b.created_at) - Number(a.created_at));
|
|
220
|
+
const memories = allMemories.slice(0, limit).map((r) => ({
|
|
221
|
+
id: r.id,
|
|
222
|
+
summary: r.content,
|
|
223
|
+
createdAt: safeToISOString(r.created_at),
|
|
224
|
+
metadata: safeJSONParse(r.metadata),
|
|
225
|
+
displayName: r.display_name,
|
|
226
|
+
userName: r.user_name,
|
|
227
|
+
userEmail: r.user_email,
|
|
228
|
+
projectPath: r.project_path,
|
|
229
|
+
projectName: r.project_name,
|
|
230
|
+
gitRepoUrl: r.git_repo_url,
|
|
231
|
+
}));
|
|
232
|
+
log("listMemories: success", { count: memories.length });
|
|
233
|
+
return {
|
|
234
|
+
success: true,
|
|
235
|
+
memories,
|
|
236
|
+
pagination: { currentPage: 1, totalItems: memories.length, totalPages: 1 },
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
catch (error) {
|
|
240
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
241
|
+
log("listMemories: error", { error: errorMessage });
|
|
242
|
+
return {
|
|
243
|
+
success: false,
|
|
244
|
+
error: errorMessage,
|
|
245
|
+
memories: [],
|
|
246
|
+
pagination: { currentPage: 1, totalItems: 0, totalPages: 0 },
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
export const memoryClient = new LocalMemoryClient();
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
interface TokenInfo {
|
|
2
|
+
input: number;
|
|
3
|
+
output: number;
|
|
4
|
+
cache: {
|
|
5
|
+
read: number;
|
|
6
|
+
write: number;
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
interface MessageInfo {
|
|
10
|
+
id: string;
|
|
11
|
+
role: string;
|
|
12
|
+
sessionID: string;
|
|
13
|
+
providerID?: string;
|
|
14
|
+
modelID?: string;
|
|
15
|
+
tokens?: TokenInfo;
|
|
16
|
+
summary?: boolean;
|
|
17
|
+
finish?: boolean;
|
|
18
|
+
}
|
|
19
|
+
export interface CompactionOptions {
|
|
20
|
+
threshold?: number;
|
|
21
|
+
getModelLimit?: (providerID: string, modelID: string) => number | undefined;
|
|
22
|
+
}
|
|
23
|
+
export interface CompactionContext {
|
|
24
|
+
directory: string;
|
|
25
|
+
client: {
|
|
26
|
+
session: {
|
|
27
|
+
summarize: (params: {
|
|
28
|
+
path: {
|
|
29
|
+
id: string;
|
|
30
|
+
};
|
|
31
|
+
body: {
|
|
32
|
+
providerID: string;
|
|
33
|
+
modelID: string;
|
|
34
|
+
};
|
|
35
|
+
query: {
|
|
36
|
+
directory: string;
|
|
37
|
+
};
|
|
38
|
+
}) => Promise<unknown>;
|
|
39
|
+
messages: (params: {
|
|
40
|
+
path: {
|
|
41
|
+
id: string;
|
|
42
|
+
};
|
|
43
|
+
query: {
|
|
44
|
+
directory: string;
|
|
45
|
+
};
|
|
46
|
+
}) => Promise<{
|
|
47
|
+
data?: Array<{
|
|
48
|
+
info: MessageInfo;
|
|
49
|
+
}>;
|
|
50
|
+
}>;
|
|
51
|
+
promptAsync: (params: {
|
|
52
|
+
path: {
|
|
53
|
+
id: string;
|
|
54
|
+
};
|
|
55
|
+
body: {
|
|
56
|
+
agent?: string;
|
|
57
|
+
parts: Array<{
|
|
58
|
+
type: string;
|
|
59
|
+
text: string;
|
|
60
|
+
}>;
|
|
61
|
+
};
|
|
62
|
+
query: {
|
|
63
|
+
directory: string;
|
|
64
|
+
};
|
|
65
|
+
}) => Promise<unknown>;
|
|
66
|
+
};
|
|
67
|
+
tui: {
|
|
68
|
+
showToast: (params: {
|
|
69
|
+
body: {
|
|
70
|
+
title: string;
|
|
71
|
+
message: string;
|
|
72
|
+
variant: string;
|
|
73
|
+
duration: number;
|
|
74
|
+
};
|
|
75
|
+
}) => Promise<unknown>;
|
|
76
|
+
};
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
export declare function createCompactionHook(ctx: CompactionContext, tags: {
|
|
80
|
+
user: string;
|
|
81
|
+
project: string;
|
|
82
|
+
}, options?: CompactionOptions): {
|
|
83
|
+
compactionTracker: Map<string, number>;
|
|
84
|
+
event({ event }: {
|
|
85
|
+
event: {
|
|
86
|
+
type: string;
|
|
87
|
+
properties?: unknown;
|
|
88
|
+
};
|
|
89
|
+
}): Promise<void>;
|
|
90
|
+
};
|
|
91
|
+
export {};
|
|
92
|
+
//# sourceMappingURL=compaction.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compaction.d.ts","sourceRoot":"","sources":["../../src/services/compaction.ts"],"names":[],"mappings":"AAsBA,UAAU,SAAS;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;CACxC;AAED,UAAU,WAAW;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAgBD,MAAM,WAAW,iBAAiB;IAChC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;CAC7E;AAuLD,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE;QACN,OAAO,EAAE;YACP,SAAS,EAAE,CAAC,MAAM,EAAE;gBAAE,IAAI,EAAE;oBAAE,EAAE,EAAE,MAAM,CAAA;iBAAE,CAAC;gBAAC,IAAI,EAAE;oBAAE,UAAU,EAAE,MAAM,CAAC;oBAAC,OAAO,EAAE,MAAM,CAAA;iBAAE,CAAC;gBAAC,KAAK,EAAE;oBAAE,SAAS,EAAE,MAAM,CAAA;iBAAE,CAAA;aAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;YAC/I,QAAQ,EAAE,CAAC,MAAM,EAAE;gBAAE,IAAI,EAAE;oBAAE,EAAE,EAAE,MAAM,CAAA;iBAAE,CAAC;gBAAC,KAAK,EAAE;oBAAE,SAAS,EAAE,MAAM,CAAA;iBAAE,CAAA;aAAE,KAAK,OAAO,CAAC;gBAAE,IAAI,CAAC,EAAE,KAAK,CAAC;oBAAE,IAAI,EAAE,WAAW,CAAA;iBAAE,CAAC,CAAA;aAAE,CAAC,CAAC;YAC/H,WAAW,EAAE,CAAC,MAAM,EAAE;gBAAE,IAAI,EAAE;oBAAE,EAAE,EAAE,MAAM,CAAA;iBAAE,CAAC;gBAAC,IAAI,EAAE;oBAAE,KAAK,CAAC,EAAE,MAAM,CAAC;oBAAC,KAAK,EAAE,KAAK,CAAC;wBAAE,IAAI,EAAE,MAAM,CAAC;wBAAC,IAAI,EAAE,MAAM,CAAA;qBAAE,CAAC,CAAA;iBAAE,CAAC;gBAAC,KAAK,EAAE;oBAAE,SAAS,EAAE,MAAM,CAAA;iBAAE,CAAA;aAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;SAC3K,CAAC;QACF,GAAG,EAAE;YACH,SAAS,EAAE,CAAC,MAAM,EAAE;gBAAE,IAAI,EAAE;oBAAE,KAAK,EAAE,MAAM,CAAC;oBAAC,OAAO,EAAE,MAAM,CAAC;oBAAC,OAAO,EAAE,MAAM,CAAC;oBAAC,QAAQ,EAAE,MAAM,CAAA;iBAAE,CAAA;aAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;SAC1H,CAAC;KACH,CAAC;CACH;AAED,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,iBAAiB,EACtB,IAAI,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,EACvC,OAAO,CAAC,EAAE,iBAAiB;;qBAsOF;QAAE,KAAK,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,UAAU,CAAC,EAAE,OAAO,CAAA;SAAE,CAAA;KAAE;EAgE3E"}
|