page-action-cache 1.0.1

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.
Files changed (73) hide show
  1. package/dist/actions-executor.d.ts +62 -0
  2. package/dist/actions-executor.d.ts.map +1 -0
  3. package/dist/actions-executor.js +339 -0
  4. package/dist/actions-executor.js.map +1 -0
  5. package/dist/cache-invalidator.d.ts +70 -0
  6. package/dist/cache-invalidator.d.ts.map +1 -0
  7. package/dist/cache-invalidator.js +212 -0
  8. package/dist/cache-invalidator.js.map +1 -0
  9. package/dist/cache-store.d.ts +80 -0
  10. package/dist/cache-store.d.ts.map +1 -0
  11. package/dist/cache-store.js +361 -0
  12. package/dist/cache-store.js.map +1 -0
  13. package/dist/cache-strategy.d.ts +65 -0
  14. package/dist/cache-strategy.d.ts.map +1 -0
  15. package/dist/cache-strategy.js +237 -0
  16. package/dist/cache-strategy.js.map +1 -0
  17. package/dist/hooks-entry.d.ts +18 -0
  18. package/dist/hooks-entry.d.ts.map +1 -0
  19. package/dist/hooks-entry.js +27 -0
  20. package/dist/hooks-entry.js.map +1 -0
  21. package/dist/hooks.d.ts +10 -0
  22. package/dist/hooks.d.ts.map +1 -0
  23. package/dist/hooks.js +277 -0
  24. package/dist/hooks.js.map +1 -0
  25. package/dist/index.d.ts +24 -0
  26. package/dist/index.d.ts.map +1 -0
  27. package/dist/index.js +34 -0
  28. package/dist/index.js.map +1 -0
  29. package/dist/scenario-recognizer.d.ts +45 -0
  30. package/dist/scenario-recognizer.d.ts.map +1 -0
  31. package/dist/scenario-recognizer.js +213 -0
  32. package/dist/scenario-recognizer.js.map +1 -0
  33. package/dist/security-policy.d.ts +62 -0
  34. package/dist/security-policy.d.ts.map +1 -0
  35. package/dist/security-policy.js +219 -0
  36. package/dist/security-policy.js.map +1 -0
  37. package/dist/tools.d.ts +209 -0
  38. package/dist/tools.d.ts.map +1 -0
  39. package/dist/tools.js +383 -0
  40. package/dist/tools.js.map +1 -0
  41. package/dist/types.d.ts +336 -0
  42. package/dist/types.d.ts.map +1 -0
  43. package/dist/types.js +8 -0
  44. package/dist/types.js.map +1 -0
  45. package/dist/ux-enhancer.d.ts +60 -0
  46. package/dist/ux-enhancer.d.ts.map +1 -0
  47. package/dist/ux-enhancer.js +218 -0
  48. package/dist/ux-enhancer.js.map +1 -0
  49. package/dist/variable-resolver.d.ts +28 -0
  50. package/dist/variable-resolver.d.ts.map +1 -0
  51. package/dist/variable-resolver.js +201 -0
  52. package/dist/variable-resolver.js.map +1 -0
  53. package/docs/API.md +555 -0
  54. package/docs/IMPLEMENTATION.md +1792 -0
  55. package/docs/INTEGRATION.md +387 -0
  56. package/docs/README.md +183 -0
  57. package/index.ts +118 -0
  58. package/openclaw.plugin.json +208 -0
  59. package/package.json +76 -0
  60. package/skills/page-action-cache/SKILL.md +216 -0
  61. package/src/actions-executor.ts +441 -0
  62. package/src/cache-invalidator.ts +271 -0
  63. package/src/cache-store.ts +457 -0
  64. package/src/cache-strategy.ts +327 -0
  65. package/src/hooks-entry.ts +114 -0
  66. package/src/hooks.ts +332 -0
  67. package/src/index.ts +104 -0
  68. package/src/scenario-recognizer.ts +259 -0
  69. package/src/security-policy.ts +268 -0
  70. package/src/tools.ts +437 -0
  71. package/src/types.ts +482 -0
  72. package/src/ux-enhancer.ts +266 -0
  73. package/src/variable-resolver.ts +258 -0
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Actions Executor
3
+ * 操作执行器 - 执行缓存的原子化操作
4
+ */
5
+ import type { AtomicAction, ExecutionResult, PwAi, VariableMap } from "./types.js";
6
+ /**
7
+ * 操作执行器
8
+ */
9
+ export declare class ActionsExecutor {
10
+ private pw;
11
+ private cdpUrl;
12
+ constructor(cdpUrl?: string);
13
+ /**
14
+ * 设置 Playwright 客户端
15
+ */
16
+ setPlaywrightClient(pw: PwAi): void;
17
+ /**
18
+ * 设置 CDP URL
19
+ */
20
+ setCdpUrl(cdpUrl: string): void;
21
+ /**
22
+ * 执行单个操作
23
+ */
24
+ execute(action: AtomicAction, variables?: VariableMap): Promise<ExecutionResult>;
25
+ /**
26
+ * 批量执行操作
27
+ */
28
+ executeBatch(actions: AtomicAction[], variables?: VariableMap, options?: {
29
+ fromIndex?: number;
30
+ toIndex?: number;
31
+ atomic?: boolean;
32
+ }): Promise<ExecutionResult[]>;
33
+ private executeNavigate;
34
+ private executeClick;
35
+ private executeType;
36
+ private executePress;
37
+ private executeHover;
38
+ private executeScreenshot;
39
+ private executeEvaluate;
40
+ /**
41
+ * 应用变量到操作
42
+ */
43
+ private applyVariables;
44
+ /**
45
+ * 替换操作中的模板变量
46
+ */
47
+ private replaceTemplateVariables;
48
+ /**
49
+ * 格式化操作列表
50
+ */
51
+ formatActions(actions: AtomicAction[]): string;
52
+ /**
53
+ * 格式化单个操作
54
+ */
55
+ private formatAction;
56
+ /**
57
+ * 格式化执行结果
58
+ */
59
+ formatExecutionResults(results: ExecutionResult[]): string;
60
+ }
61
+ export declare function getActionsExecutor(cdpUrl?: string): ActionsExecutor;
62
+ //# sourceMappingURL=actions-executor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"actions-executor.d.ts","sourceRoot":"","sources":["../src/actions-executor.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EACV,YAAY,EACZ,eAAe,EACf,IAAI,EACJ,WAAW,EAQZ,MAAM,YAAY,CAAC;AAMpB;;GAEG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,EAAE,CAAqB;IAC/B,OAAO,CAAC,MAAM,CAAc;gBAEhB,MAAM,CAAC,EAAE,MAAM;IAM3B;;OAEG;IACH,mBAAmB,CAAC,EAAE,EAAE,IAAI,GAAG,IAAI;IAInC;;OAEG;IACH,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAI/B;;OAEG;IACG,OAAO,CACX,MAAM,EAAE,YAAY,EACpB,SAAS,CAAC,EAAE,WAAW,GACtB,OAAO,CAAC,eAAe,CAAC;IAiE3B;;OAEG;IACG,YAAY,CAChB,OAAO,EAAE,YAAY,EAAE,EACvB,SAAS,CAAC,EAAE,WAAW,EACvB,OAAO,CAAC,EAAE;QACR,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,MAAM,CAAC,EAAE,OAAO,CAAC;KAClB,GACA,OAAO,CAAC,eAAe,EAAE,CAAC;YA0Bf,eAAe;YAcf,YAAY;YAgBZ,WAAW;YAgBX,YAAY;YAaZ,YAAY;YAaZ,iBAAiB;YAWjB,eAAe;IAiB7B;;OAEG;IACH,OAAO,CAAC,cAAc;IAuCtB;;OAEG;IACH,OAAO,CAAC,wBAAwB;IAmChC;;OAEG;IACH,aAAa,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,MAAM;IAM9C;;OAEG;IACH,OAAO,CAAC,YAAY;IA+DpB;;OAEG;IACH,sBAAsB,CAAC,OAAO,EAAE,eAAe,EAAE,GAAG,MAAM;CAW3D;AAQD,wBAAgB,kBAAkB,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,eAAe,CAKnE"}
@@ -0,0 +1,339 @@
1
+ /**
2
+ * Actions Executor
3
+ * 操作执行器 - 执行缓存的原子化操作
4
+ */
5
+ // ============================================================================
6
+ // Actions Executor 类
7
+ // ============================================================================
8
+ /**
9
+ * 操作执行器
10
+ */
11
+ export class ActionsExecutor {
12
+ pw = null;
13
+ cdpUrl = "";
14
+ constructor(cdpUrl) {
15
+ if (cdpUrl) {
16
+ this.cdpUrl = cdpUrl;
17
+ }
18
+ }
19
+ /**
20
+ * 设置 Playwright 客户端
21
+ */
22
+ setPlaywrightClient(pw) {
23
+ this.pw = pw;
24
+ }
25
+ /**
26
+ * 设置 CDP URL
27
+ */
28
+ setCdpUrl(cdpUrl) {
29
+ this.cdpUrl = cdpUrl;
30
+ }
31
+ /**
32
+ * 执行单个操作
33
+ */
34
+ async execute(action, variables) {
35
+ const startTime = Date.now();
36
+ try {
37
+ // 应用变量
38
+ const resolvedAction = this.applyVariables(action, variables);
39
+ // 根据操作类型执行
40
+ switch (resolvedAction.type) {
41
+ case "navigate":
42
+ await this.executeNavigate(resolvedAction);
43
+ break;
44
+ case "click":
45
+ await this.executeClick(resolvedAction);
46
+ break;
47
+ case "type":
48
+ await this.executeType(resolvedAction);
49
+ break;
50
+ case "press":
51
+ await this.executePress(resolvedAction);
52
+ break;
53
+ case "hover":
54
+ await this.executeHover(resolvedAction);
55
+ break;
56
+ case "screenshot":
57
+ await this.executeScreenshot(resolvedAction);
58
+ break;
59
+ case "scroll":
60
+ case "wait":
61
+ case "select":
62
+ case "focus":
63
+ case "drag":
64
+ case "upload":
65
+ await this.executeEvaluate(resolvedAction);
66
+ break;
67
+ case "composite":
68
+ // 复合操作暂不实现
69
+ throw new Error("Composite actions not yet implemented");
70
+ default:
71
+ throw new Error(`Unsupported action type: ${action.type}`);
72
+ }
73
+ return {
74
+ action: action.type,
75
+ success: true,
76
+ duration: Date.now() - startTime,
77
+ };
78
+ }
79
+ catch (error) {
80
+ return {
81
+ action: action.type,
82
+ success: false,
83
+ error: error instanceof Error ? error.message : String(error),
84
+ duration: Date.now() - startTime,
85
+ };
86
+ }
87
+ }
88
+ /**
89
+ * 批量执行操作
90
+ */
91
+ async executeBatch(actions, variables, options) {
92
+ const from = options?.fromIndex ?? 0;
93
+ const to = options?.toIndex !== undefined ? options.toIndex + 1 : actions.length;
94
+ const atomic = options?.atomic ?? false;
95
+ const results = [];
96
+ const actionsToExecute = actions.slice(from, to);
97
+ for (const action of actionsToExecute) {
98
+ const result = await this.execute(action, variables);
99
+ results.push(result);
100
+ // 原子执行:失败则停止
101
+ if (atomic && !result.success) {
102
+ break;
103
+ }
104
+ }
105
+ return results;
106
+ }
107
+ // -------------------------------------------------------------------------
108
+ // 具体操作实现
109
+ // -------------------------------------------------------------------------
110
+ async executeNavigate(action) {
111
+ if (!this.pw) {
112
+ throw new Error("Playwright client not set");
113
+ }
114
+ await this.pw.navigateViaPlaywright({
115
+ cdpUrl: action.cdpUrl || this.cdpUrl,
116
+ targetId: action.targetId,
117
+ url: action.url,
118
+ waitUntil: action.navigationPolicy?.waitUntil || "domcontentloaded",
119
+ timeout: action.navigationPolicy?.timeout,
120
+ });
121
+ }
122
+ async executeClick(action) {
123
+ if (!this.pw) {
124
+ throw new Error("Playwright client not set");
125
+ }
126
+ await this.pw.clickViaPlaywright({
127
+ cdpUrl: action.cdpUrl || this.cdpUrl,
128
+ targetId: action.targetId,
129
+ ref: action.ref,
130
+ doubleClick: action.doubleClick,
131
+ button: action.button || "left",
132
+ modifiers: action.modifiers,
133
+ timeoutMs: action.timeoutMs,
134
+ });
135
+ }
136
+ async executeType(action) {
137
+ if (!this.pw) {
138
+ throw new Error("Playwright client not set");
139
+ }
140
+ await this.pw.typeViaPlaywright({
141
+ cdpUrl: action.cdpUrl || this.cdpUrl,
142
+ targetId: action.targetId,
143
+ ref: action.ref,
144
+ text: action.text,
145
+ submit: action.submit,
146
+ slowly: action.slowly,
147
+ timeoutMs: action.timeoutMs,
148
+ });
149
+ }
150
+ async executePress(action) {
151
+ if (!this.pw) {
152
+ throw new Error("Playwright client not set");
153
+ }
154
+ await this.pw.pressKeyViaPlaywright({
155
+ cdpUrl: action.cdpUrl || this.cdpUrl,
156
+ targetId: action.targetId,
157
+ key: action.key,
158
+ delayMs: action.delayMs,
159
+ });
160
+ }
161
+ async executeHover(action) {
162
+ if (!this.pw) {
163
+ throw new Error("Playwright client not set");
164
+ }
165
+ await this.pw.hoverViaPlaywright({
166
+ cdpUrl: action.cdpUrl || this.cdpUrl,
167
+ targetId: action.targetId,
168
+ ref: action.ref,
169
+ timeoutMs: action.timeoutMs,
170
+ });
171
+ }
172
+ async executeScreenshot(action) {
173
+ if (!this.pw) {
174
+ throw new Error("Playwright client not set");
175
+ }
176
+ return this.pw.screenshotViaPlaywright({
177
+ cdpUrl: action.cdpUrl || this.cdpUrl,
178
+ targetId: action.targetId,
179
+ });
180
+ }
181
+ async executeEvaluate(action) {
182
+ if (!this.pw) {
183
+ throw new Error("Playwright client not set");
184
+ }
185
+ return this.pw.evaluateViaPlaywright({
186
+ cdpUrl: action.cdpUrl || this.cdpUrl,
187
+ targetId: action.targetId,
188
+ code: action.evaluate.code,
189
+ args: action.evaluate.args,
190
+ });
191
+ }
192
+ // -------------------------------------------------------------------------
193
+ // 变量替换
194
+ // -------------------------------------------------------------------------
195
+ /**
196
+ * 应用变量到操作
197
+ */
198
+ applyVariables(action, variables) {
199
+ if (!variables) {
200
+ return action;
201
+ }
202
+ // 检查是否需要变量替换
203
+ if (!action.variable) {
204
+ return action;
205
+ }
206
+ // 获取变量值
207
+ const value = variables[action.variable];
208
+ if (value === undefined) {
209
+ // 变量未定义,返回原操作
210
+ return action;
211
+ }
212
+ // 根据操作类型设置正确的参数
213
+ const actionType = action.type;
214
+ if (actionType === "type") {
215
+ return { ...action, text: value };
216
+ }
217
+ else if (actionType === "press") {
218
+ return { ...action, key: value };
219
+ }
220
+ else if (actionType === "navigate") {
221
+ return { ...action, url: value };
222
+ }
223
+ else if (actionType === "scroll" || actionType === "wait" ||
224
+ actionType === "select" || actionType === "focus" ||
225
+ actionType === "drag" || actionType === "upload") {
226
+ // evaluate 操作替换模板变量
227
+ return this.replaceTemplateVariables(action, variables);
228
+ }
229
+ else {
230
+ // 其他操作替换所有字符串参数中的模板变量
231
+ return this.replaceTemplateVariables(action, variables);
232
+ }
233
+ }
234
+ /**
235
+ * 替换操作中的模板变量
236
+ */
237
+ replaceTemplateVariables(action, variables) {
238
+ const result = { ...action };
239
+ // 替换字符串类型参数中的 ${variable}
240
+ for (const key of Object.keys(action)) {
241
+ const value = action[key];
242
+ if (typeof value === "string") {
243
+ result[key] = value.replace(/\$\{([^}]+)\}/g, (match, varName) => {
244
+ const replacement = variables[varName];
245
+ return replacement !== undefined ? replacement : match;
246
+ });
247
+ }
248
+ }
249
+ // 特殊处理 evaluate.code(如果存在)
250
+ if (result.evaluate?.code && typeof result.evaluate.code === "string") {
251
+ result.evaluate.code = result.evaluate.code.replace(/\$\{([^}]+)\}/g, (match, varName) => {
252
+ const replacement = variables[varName];
253
+ return replacement !== undefined ? replacement : match;
254
+ });
255
+ }
256
+ return result;
257
+ }
258
+ // -------------------------------------------------------------------------
259
+ // 格式化输出
260
+ // -------------------------------------------------------------------------
261
+ /**
262
+ * 格式化操作列表
263
+ */
264
+ formatActions(actions) {
265
+ return actions
266
+ .map((action, i) => this.formatAction(action, i + 1))
267
+ .join("\n");
268
+ }
269
+ /**
270
+ * 格式化单个操作
271
+ */
272
+ formatAction(action, index) {
273
+ switch (action.type) {
274
+ case "navigate":
275
+ return `${index}. 导航到:${action.url}`;
276
+ case "screenshot":
277
+ return `${index}. 截图`;
278
+ case "click":
279
+ const btn = action.button || "left";
280
+ const dbl = action.doubleClick ? "双击" : "";
281
+ const mod = action.modifiers?.length
282
+ ? `+${action.modifiers.join("+")}`
283
+ : "";
284
+ return `${index}. ${dbl}点击(${btn}${mod}):${action.ref}`;
285
+ case "type":
286
+ const txt = action.text
287
+ ? `="${action.text}"`
288
+ : "";
289
+ const sub = action.submit ? " [提交]" : "";
290
+ const slow = action.slowly ? " [慢速]" : "";
291
+ return `${index}. 输入:${action.ref}${txt}${sub}${slow}`;
292
+ case "press":
293
+ const delay = action.delayMs
294
+ ? `(${action.delayMs}ms)`
295
+ : "";
296
+ return `${index}. 按键:${action.key}${delay}${action.ref ? ` @ ${action.ref}` : ""}`;
297
+ case "hover":
298
+ return `${index}. 悬停:${action.ref}`;
299
+ case "scroll":
300
+ return `${index}. 滚动:${action.evaluate?.code || "向下滚动"}`;
301
+ case "wait":
302
+ const waitDelay = action.delay ? `(${action.delay}ms)` : "";
303
+ return `${index}. 等待:${action.evaluate?.code || "默认等待"}${waitDelay}`;
304
+ case "select":
305
+ return `${index}. 选择:${action.ref}`;
306
+ case "focus":
307
+ return `${index}. 聚焦:${action.ref}`;
308
+ case "drag":
309
+ return `${index}. 拖拽:${action.ref}`;
310
+ case "upload":
311
+ return `${index}. 上传:${action.ref}`;
312
+ default:
313
+ return `${index}. ${action.type}:${action.ref || ""}`;
314
+ }
315
+ }
316
+ /**
317
+ * 格式化执行结果
318
+ */
319
+ formatExecutionResults(results) {
320
+ return results
321
+ .map((r, i) => {
322
+ const icon = r.success ? "✅" : "❌";
323
+ const time = r.duration ? `(${r.duration}ms)` : "";
324
+ return `${icon} 操作 ${i + 1}: ${r.action} ${time}${r.error ? ` - ${r.error}` : ""}`;
325
+ })
326
+ .join("\n");
327
+ }
328
+ }
329
+ // ============================================================================
330
+ // 单例
331
+ // ============================================================================
332
+ let actionsExecutorInstance = null;
333
+ export function getActionsExecutor(cdpUrl) {
334
+ if (!actionsExecutorInstance) {
335
+ actionsExecutorInstance = new ActionsExecutor(cdpUrl);
336
+ }
337
+ return actionsExecutorInstance;
338
+ }
339
+ //# sourceMappingURL=actions-executor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"actions-executor.js","sourceRoot":"","sources":["../src/actions-executor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Cache Invalidator
3
+ * 缓存失效检测器 - 检测页面变化并失效缓存
4
+ */
5
+ import type { PageViewport, PageChangeDetection, PageActionCacheEntry } from "./types.js";
6
+ /**
7
+ * 缓存失效检测器
8
+ */
9
+ export declare class CacheInvalidator {
10
+ /**
11
+ * 检测页面是否发生变化
12
+ */
13
+ detectPageChange(html: string, _url: string, _viewport: PageViewport, cachedEntry?: PageActionCacheEntry): Promise<PageChangeDetection>;
14
+ /**
15
+ * 计算 DOM hash
16
+ */
17
+ calculateDOMHash(html: string): string;
18
+ /**
19
+ * 提取 DOM 特征
20
+ */
21
+ private extractDOMFeatures;
22
+ /**
23
+ * 计算元素数量
24
+ */
25
+ private countElements;
26
+ /**
27
+ * 组合特征为 hash
28
+ */
29
+ private combineFeaturesHash;
30
+ /**
31
+ * 检测结构变化
32
+ */
33
+ private detectStructureChange;
34
+ /**
35
+ * 检测内容变化
36
+ */
37
+ private detectContentChange;
38
+ /**
39
+ * 判断是否应该失效缓存
40
+ */
41
+ shouldInvalidate(entry: PageActionCacheEntry, changeResult: PageChangeDetection, threshold?: number): boolean;
42
+ /**
43
+ * 创建渐进式失效器
44
+ */
45
+ createProgressiveInvalidator(): ProgressiveInvalidator;
46
+ }
47
+ /**
48
+ * 渐进式失效:保留多版本
49
+ */
50
+ export declare class ProgressiveInvalidator {
51
+ private versions;
52
+ /**
53
+ * 添加版本
54
+ */
55
+ addVersion(entry: PageActionCacheEntry, versionId: string): void;
56
+ /**
57
+ * 获取版本列表
58
+ */
59
+ getVersions(key: string): string[];
60
+ /**
61
+ * 生成版本标识
62
+ */
63
+ generateVersion(entry: PageActionCacheEntry): string;
64
+ /**
65
+ * 清理旧版本
66
+ */
67
+ cleanupOldVersions(key: string, maxVersions?: number): void;
68
+ }
69
+ export declare function getCacheInvalidator(): CacheInvalidator;
70
+ //# sourceMappingURL=cache-invalidator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache-invalidator.d.ts","sourceRoot":"","sources":["../src/cache-invalidator.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EACV,YAAY,EACZ,mBAAmB,EACnB,oBAAoB,EAErB,MAAM,YAAY,CAAC;AAMpB;;GAEG;AACH,qBAAa,gBAAgB;IAC3B;;OAEG;IACG,gBAAgB,CACpB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,YAAY,EACvB,WAAW,CAAC,EAAE,oBAAoB,GACjC,OAAO,CAAC,mBAAmB,CAAC;IA0D/B;;OAEG;IACH,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAKtC;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAa1B;;OAEG;IACH,OAAO,CAAC,aAAa;IAKrB;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAiB3B;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAW7B;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAU3B;;OAEG;IACH,gBAAgB,CACd,KAAK,EAAE,oBAAoB,EAC3B,YAAY,EAAE,mBAAmB,EACjC,SAAS,GAAE,MAAW,GACrB,OAAO;IAoBV;;OAEG;IACH,4BAA4B,IAAI,sBAAsB;CAGvD;AAMD;;GAEG;AACH,qBAAa,sBAAsB;IACjC,OAAO,CAAC,QAAQ,CAAoC;IAEpD;;OAEG;IACH,UAAU,CAAC,KAAK,EAAE,oBAAoB,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI;IAgBhE;;OAEG;IACH,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE;IAIlC;;OAEG;IACH,eAAe,CAAC,KAAK,EAAE,oBAAoB,GAAG,MAAM;IAOpD;;OAEG;IACH,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,WAAW,GAAE,MAAU,GAAG,IAAI;CAQ/D;AAQD,wBAAgB,mBAAmB,IAAI,gBAAgB,CAKtD"}