sema-core 2.0.11 → 2.0.13

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 (80) hide show
  1. package/dist/core/RunTools.d.ts.map +1 -1
  2. package/dist/core/RunTools.js +48 -2
  3. package/dist/core/RunTools.js.map +1 -1
  4. package/dist/core/SemaCore.d.ts +2 -0
  5. package/dist/core/SemaCore.d.ts.map +1 -1
  6. package/dist/core/SemaCore.js +7 -1
  7. package/dist/core/SemaCore.js.map +1 -1
  8. package/dist/core/SemaEngine.d.ts +2 -0
  9. package/dist/core/SemaEngine.d.ts.map +1 -1
  10. package/dist/core/SemaEngine.js +81 -5
  11. package/dist/core/SemaEngine.js.map +1 -1
  12. package/dist/events/types.d.ts +13 -0
  13. package/dist/events/types.d.ts.map +1 -1
  14. package/dist/manager/CronManager.d.ts +1 -1
  15. package/dist/manager/CronManager.d.ts.map +1 -1
  16. package/dist/manager/CronManager.js +4 -14
  17. package/dist/manager/CronManager.js.map +1 -1
  18. package/dist/manager/PermissionManager.d.ts.map +1 -1
  19. package/dist/manager/PermissionManager.js +22 -2
  20. package/dist/manager/PermissionManager.js.map +1 -1
  21. package/dist/manager/TaskManager.d.ts.map +1 -1
  22. package/dist/manager/TaskManager.js +2 -1
  23. package/dist/manager/TaskManager.js.map +1 -1
  24. package/dist/prompt/toolAliases.d.ts +4 -0
  25. package/dist/prompt/toolAliases.d.ts.map +1 -1
  26. package/dist/prompt/toolAliases.js +14 -0
  27. package/dist/prompt/toolAliases.js.map +1 -1
  28. package/dist/services/api/adapt/anthropic.js +1 -1
  29. package/dist/services/api/adapt/anthropic.js.map +1 -1
  30. package/dist/services/api/adapt/openai.js +1 -1
  31. package/dist/services/api/adapt/openai.js.map +1 -1
  32. package/dist/services/api/adapt/util.js +4 -4
  33. package/dist/services/api/adapt/util.js.map +1 -1
  34. package/dist/services/hooks/hookRunner.d.ts +21 -0
  35. package/dist/services/hooks/hookRunner.d.ts.map +1 -0
  36. package/dist/services/hooks/hookRunner.js +253 -0
  37. package/dist/services/hooks/hookRunner.js.map +1 -0
  38. package/dist/services/hooks/hookTriggers.d.ts +65 -0
  39. package/dist/services/hooks/hookTriggers.d.ts.map +1 -0
  40. package/dist/services/hooks/hookTriggers.js +295 -0
  41. package/dist/services/hooks/hookTriggers.js.map +1 -0
  42. package/dist/services/hooks/hooksManager.d.ts +64 -0
  43. package/dist/services/hooks/hooksManager.d.ts.map +1 -0
  44. package/dist/services/hooks/hooksManager.js +346 -0
  45. package/dist/services/hooks/hooksManager.js.map +1 -0
  46. package/dist/services/mcp/MCPManager.d.ts +0 -1
  47. package/dist/services/mcp/MCPManager.d.ts.map +1 -1
  48. package/dist/services/mcp/MCPManager.js +3 -19
  49. package/dist/services/mcp/MCPManager.js.map +1 -1
  50. package/dist/services/plugins/pluginsManager.d.ts.map +1 -1
  51. package/dist/services/plugins/pluginsManager.js +4 -18
  52. package/dist/services/plugins/pluginsManager.js.map +1 -1
  53. package/dist/services/settings/settingsLoader.d.ts +29 -0
  54. package/dist/services/settings/settingsLoader.d.ts.map +1 -0
  55. package/dist/services/settings/settingsLoader.js +143 -0
  56. package/dist/services/settings/settingsLoader.js.map +1 -0
  57. package/dist/types/hook.d.ts +76 -0
  58. package/dist/types/hook.d.ts.map +1 -0
  59. package/dist/types/hook.js +28 -0
  60. package/dist/types/hook.js.map +1 -0
  61. package/dist/types/index.d.ts +1 -0
  62. package/dist/types/index.d.ts.map +1 -1
  63. package/dist/types/settings.d.ts +23 -0
  64. package/dist/types/settings.d.ts.map +1 -0
  65. package/dist/types/settings.js +3 -0
  66. package/dist/types/settings.js.map +1 -0
  67. package/dist/util/file.d.ts +8 -0
  68. package/dist/util/file.d.ts.map +1 -1
  69. package/dist/util/file.js +39 -0
  70. package/dist/util/file.js.map +1 -1
  71. package/dist/util/history.d.ts +1 -1
  72. package/dist/util/history.d.ts.map +1 -1
  73. package/dist/util/history.js +23 -2
  74. package/dist/util/history.js.map +1 -1
  75. package/dist/util/logLLM.js +2 -2
  76. package/dist/util/logLLM.js.map +1 -1
  77. package/dist/util/shell.d.ts.map +1 -1
  78. package/dist/util/shell.js +3 -2
  79. package/dist/util/shell.js.map +1 -1
  80. package/package.json +1 -1
@@ -0,0 +1,295 @@
1
+ "use strict";
2
+ /**
3
+ * Hook 埋点入口
4
+ *
5
+ * 核心链路仅 import 本模块。埋点稳定性硬约束:
6
+ * ① 无匹配条目零开销早退;② 整体 try/catch fail-open,
7
+ * 内部任何错误只记日志不上抛——未配置 hooks 的现有用户零影响。
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.fireSessionStart = fireSessionStart;
11
+ exports.fireUserPromptSubmit = fireUserPromptSubmit;
12
+ exports.firePreToolUse = firePreToolUse;
13
+ exports.firePostToolUse = firePostToolUse;
14
+ exports.firePostToolUseFailure = firePostToolUseFailure;
15
+ exports.firePermissionRequest = firePermissionRequest;
16
+ exports.fireStop = fireStop;
17
+ exports.fireSessionEnd = fireSessionEnd;
18
+ const EventSystem_1 = require("../../events/EventSystem");
19
+ const toolAliases_1 = require("../../prompt/toolAliases");
20
+ const cwd_1 = require("../../util/cwd");
21
+ const log_1 = require("../../util/log");
22
+ const hooksManager_1 = require("./hooksManager");
23
+ const hookRunner_1 = require("./hookRunner");
24
+ const MAIN_AGENT = 'main';
25
+ function neutralAggregate() {
26
+ return { ran: false, blocked: false, decision: 'none', additionalContext: [] };
27
+ }
28
+ /**
29
+ * fail-open 总兜底:入口全部逻辑(含单例获取、开关读取)都在其中执行,
30
+ * 任何异常只记日志并返回中性结果,绝不上抛到核心链路
31
+ */
32
+ async function safeRun(neutral, fn) {
33
+ try {
34
+ return await fn();
35
+ }
36
+ catch (error) {
37
+ (0, log_1.logWarn)(`[Hook] 内部错误(fail-open): ${error}`);
38
+ return neutral;
39
+ }
40
+ }
41
+ function emitNotice(sessionId, data) {
42
+ (0, EventSystem_1.getEventBus)().emit('hook:notice', data, sessionId);
43
+ }
44
+ /**
45
+ * 顺序执行单个事件下的全部命中条目并聚合结果
46
+ * - 第一个阻断(block / deny)立即停止后续条目
47
+ * - 聚合优先级:deny > ask > allow > none(ask 保守优先于 allow)
48
+ */
49
+ async function runEventHooks(event, sessionId, payload, entries, signal) {
50
+ const aggregate = { ran: true, blocked: false, decision: 'none', additionalContext: [] };
51
+ const payloadJson = JSON.stringify(payload);
52
+ for (const entry of entries) {
53
+ // 中断后短路剩余条目,避免逐个 spawn 出立即被 kill 的进程
54
+ if (signal?.aborted)
55
+ break;
56
+ const exec = await (0, hookRunner_1.executeHookCommand)(entry.command, payloadJson, entry.timeoutMs, signal);
57
+ const outcome = (0, hookRunner_1.parseHookOutput)(event, exec);
58
+ // 审计日志(PreToolUse / PermissionRequest 的 allow 等于把权限决策交给 hook 脚本,日志不可省)
59
+ (0, log_1.logInfo)(`[Hook][audit] event=${event} agent=${String(payload.agent_id ?? MAIN_AGENT)} ` +
60
+ `source=${entry.source} command="${entry.command}" timeoutMs=${entry.timeoutMs} ` +
61
+ `exit=${exec.exitCode} timedOut=${exec.timedOut} kind=${outcome.kind} ` +
62
+ `decision=${outcome.decision ?? '-'} duration=${exec.durationMs}ms`);
63
+ if (exec.timedOut) {
64
+ emitNotice(sessionId, {
65
+ kind: 'warning',
66
+ hookEvent: event,
67
+ message: `hook 执行超时(${entry.timeoutMs / 1000}s)已终止: ${entry.command}`,
68
+ command: entry.command,
69
+ source: entry.source,
70
+ });
71
+ }
72
+ // 不可阻断事件上的 block 输出被忽略:告警而非静默,
73
+ // 避免用户从其他工具迁移来的续驱配置(Stop + exit 2)看似生效实则无效
74
+ if (outcome.blockIgnored) {
75
+ emitNotice(sessionId, {
76
+ kind: 'warning',
77
+ hookEvent: event,
78
+ message: `${event} 事件不支持阻断,hook 的 block 输出已忽略: ${entry.command}`,
79
+ command: entry.command,
80
+ source: entry.source,
81
+ });
82
+ }
83
+ if (outcome.systemMessage) {
84
+ emitNotice(sessionId, {
85
+ kind: 'systemMessage',
86
+ hookEvent: event,
87
+ message: outcome.systemMessage,
88
+ command: entry.command,
89
+ source: entry.source,
90
+ });
91
+ }
92
+ if (outcome.additionalContext) {
93
+ aggregate.additionalContext.push(outcome.additionalContext);
94
+ }
95
+ // fail-closed 条目:hook 执行失败按阻断处理
96
+ const effectiveKind = outcome.kind === 'error' && entry.failClosed ? 'block' : outcome.kind;
97
+ if (effectiveKind === 'block') {
98
+ aggregate.blocked = true;
99
+ aggregate.blockReason =
100
+ outcome.kind === 'error'
101
+ ? `hook failed (fail-closed): ${entry.command}`
102
+ : outcome.reason;
103
+ break;
104
+ }
105
+ if (outcome.decision === 'deny') {
106
+ aggregate.decision = 'deny';
107
+ aggregate.decisionReason = outcome.reason;
108
+ break;
109
+ }
110
+ if (outcome.decision === 'ask') {
111
+ aggregate.decision = 'ask';
112
+ if (outcome.reason)
113
+ aggregate.decisionReason = outcome.reason;
114
+ }
115
+ else if (outcome.decision === 'allow' && aggregate.decision === 'none') {
116
+ aggregate.decision = 'allow';
117
+ if (outcome.reason)
118
+ aggregate.decisionReason = outcome.reason;
119
+ }
120
+ }
121
+ // 聚合后总量再做一次截断
122
+ const total = aggregate.additionalContext.join('\n\n');
123
+ if (total.length > hookRunner_1.MAX_ADDITIONAL_CONTEXT_CHARS) {
124
+ aggregate.additionalContext = [(0, hookRunner_1.truncateContext)(total)];
125
+ }
126
+ return aggregate;
127
+ }
128
+ function buildCommonPayload(event, sessionId, agentId) {
129
+ return {
130
+ session_id: sessionId,
131
+ cwd: (0, cwd_1.readInitialCwd)(),
132
+ hook_event_name: event,
133
+ agent_id: agentId,
134
+ };
135
+ }
136
+ /**
137
+ * 工具类事件的统一触发(PreToolUse / PostToolUse / PostToolUseFailure / PermissionRequest)
138
+ */
139
+ async function runToolEventHooks(event, sessionId, agentId, semaToolName, extraPayload, signal) {
140
+ // ran 在 safeRun 外持有:条目进入执行链路后即置位,
141
+ // 后续执行失败/被中断(fail-open 返回中性结果)时 ran 仍为 true
142
+ let ran = false;
143
+ const result = await safeRun(neutralAggregate(), async () => {
144
+ const manager = (0, hooksManager_1.getHooksManager)();
145
+ await manager.ready();
146
+ const genericToolName = (0, toolAliases_1.toGenericToolName)(semaToolName);
147
+ const entries = manager.getMatchedEntries(event, genericToolName, semaToolName);
148
+ if (entries.length === 0)
149
+ return neutralAggregate();
150
+ ran = true;
151
+ const payload = {
152
+ ...buildCommonPayload(event, sessionId, agentId),
153
+ tool_name: genericToolName,
154
+ sema_tool_name: semaToolName,
155
+ ...extraPayload,
156
+ };
157
+ return runEventHooks(event, sessionId, payload, entries, signal);
158
+ });
159
+ return { ...result, ran };
160
+ }
161
+ // ==================== 8 个事件入口 ====================
162
+ /**
163
+ * SessionStart:engine session 初始化成功后触发;不可阻断
164
+ * @returns 注入模型上下文的 additionalContext,无则 null
165
+ */
166
+ async function fireSessionStart(sessionId) {
167
+ return safeRun(null, async () => {
168
+ const manager = (0, hooksManager_1.getHooksManager)();
169
+ await manager.ready();
170
+ const entries = manager.getMatchedEntries('SessionStart');
171
+ if (entries.length === 0)
172
+ return null;
173
+ const payload = { ...buildCommonPayload('SessionStart', sessionId, MAIN_AGENT), source: 'startup' };
174
+ const aggregate = await runEventHooks('SessionStart', sessionId, payload, entries);
175
+ return aggregate.additionalContext.length > 0 ? aggregate.additionalContext.join('\n\n') : null;
176
+ });
177
+ }
178
+ /**
179
+ * UserPromptSubmit:用户输入进入命令处理或模型处理前触发
180
+ * block → 丢弃本次输入(原因经 hook:notice 展示给用户,由调用方发出)
181
+ */
182
+ async function fireUserPromptSubmit(sessionId, prompt, signal) {
183
+ const neutral = { blocked: false };
184
+ let ran = false;
185
+ const result = await safeRun(neutral, async () => {
186
+ const manager = (0, hooksManager_1.getHooksManager)();
187
+ await manager.ready();
188
+ const entries = manager.getMatchedEntries('UserPromptSubmit');
189
+ if (entries.length === 0)
190
+ return neutral;
191
+ ran = true;
192
+ const payload = { ...buildCommonPayload('UserPromptSubmit', sessionId, MAIN_AGENT), prompt };
193
+ const aggregate = await runEventHooks('UserPromptSubmit', sessionId, payload, entries, signal);
194
+ return {
195
+ blocked: aggregate.blocked,
196
+ reason: aggregate.blockReason,
197
+ additionalContext: aggregate.additionalContext.length > 0 ? aggregate.additionalContext.join('\n\n') : undefined,
198
+ };
199
+ });
200
+ return { ...result, ran };
201
+ }
202
+ /**
203
+ * PreToolUse:工具执行前触发
204
+ * deny → 工具不执行,原因以 is_error tool_result 回给模型(exit 2 等价 deny)
205
+ * allow → 跳过权限询问直接执行;ask/无输出 → 走原权限流程
206
+ */
207
+ async function firePreToolUse(sessionId, agentId, semaToolName, input, signal) {
208
+ const aggregate = await runToolEventHooks('PreToolUse', sessionId, agentId, semaToolName, { tool_input: input }, signal);
209
+ if (aggregate.blocked) {
210
+ return { decision: 'deny', reason: aggregate.blockReason, ran: aggregate.ran };
211
+ }
212
+ if (aggregate.decision === 'allow' || aggregate.decision === 'deny') {
213
+ return { decision: aggregate.decision, reason: aggregate.decisionReason, ran: aggregate.ran };
214
+ }
215
+ return { decision: 'none', ran: aggregate.ran };
216
+ }
217
+ /**
218
+ * PostToolUse:工具执行成功后触发
219
+ * @returns contextBlocks 注入模型上下文的文本块(exit 2 的 stderr 与 additionalContext)
220
+ */
221
+ async function firePostToolUse(sessionId, agentId, semaToolName, input, response, signal) {
222
+ const aggregate = await runToolEventHooks('PostToolUse', sessionId, agentId, semaToolName, { tool_input: input, tool_response: response }, signal);
223
+ const contextBlocks = [...aggregate.additionalContext];
224
+ if (aggregate.blocked && aggregate.blockReason) {
225
+ // 工具已执行完,无法撤销,stderr 仅回灌模型
226
+ contextBlocks.push(`[PostToolUse hook] ${aggregate.blockReason}`);
227
+ }
228
+ return { contextBlocks };
229
+ }
230
+ /**
231
+ * PostToolUseFailure:工具执行抛错后触发(可注入纠错提示)
232
+ */
233
+ async function firePostToolUseFailure(sessionId, agentId, semaToolName, input, error, signal) {
234
+ const aggregate = await runToolEventHooks('PostToolUseFailure', sessionId, agentId, semaToolName, { tool_input: input, error }, signal);
235
+ const contextBlocks = [...aggregate.additionalContext];
236
+ if (aggregate.blocked && aggregate.blockReason) {
237
+ contextBlocks.push(`[PostToolUseFailure hook] ${aggregate.blockReason}`);
238
+ }
239
+ return { contextBlocks };
240
+ }
241
+ /**
242
+ * PermissionRequest:权限系统即将向用户发起询问前触发
243
+ * allow → 批准(等价用户 agree,不产生永久授权);deny → 拒绝(exit 2 等价 deny);
244
+ * ask/无输出 → 保持正常询问流程
245
+ */
246
+ async function firePermissionRequest(sessionId, agentId, semaToolName, input, signal) {
247
+ const aggregate = await runToolEventHooks('PermissionRequest', sessionId, agentId, semaToolName, { tool_input: input }, signal);
248
+ if (aggregate.blocked) {
249
+ return { decision: 'deny', reason: aggregate.blockReason };
250
+ }
251
+ if (aggregate.decision === 'allow' || aggregate.decision === 'deny') {
252
+ return { decision: aggregate.decision, reason: aggregate.decisionReason };
253
+ }
254
+ return { decision: 'none' };
255
+ }
256
+ /**
257
+ * Stop:主链路一轮处理自然完成并转入 idle 时触发,fire-and-forget(观察型埋点)。
258
+ * 不可阻断(暂不支持续驱,block 输出忽略并告警)、不注入上下文;
259
+ * systemMessage 照常经 hook:notice 展示。中断的轮次与排队输入接续的轮次不触发。
260
+ */
261
+ function fireStop(sessionId) {
262
+ void safeRun(null, async () => {
263
+ const manager = (0, hooksManager_1.getHooksManager)();
264
+ await manager.ready();
265
+ const entries = manager.getMatchedEntries('Stop');
266
+ if (entries.length === 0)
267
+ return null;
268
+ // stop_hook_active 对齐通用 hooks 字段形状(无续驱恒为 false),方便脚本跨端复用
269
+ const payload = { ...buildCommonPayload('Stop', sessionId, MAIN_AGENT), stop_hook_active: false };
270
+ await runEventHooks('Stop', sessionId, payload, entries);
271
+ return null;
272
+ });
273
+ }
274
+ /**
275
+ * SessionEnd:会话关闭时触发,fire-and-forget(不可阻断,输出忽略)
276
+ */
277
+ function fireSessionEnd(sessionId) {
278
+ void safeRun(null, async () => {
279
+ // async 函数体在首个 await 前同步执行:缓存就绪时条目在本调用返回前即被同步捕获,
280
+ // 不受 SemaCore.dispose 同步链路随后清空 hooksManager 缓存的影响(捕获的是过滤后的新数组)。
281
+ // 缓存未就绪(会话刚创建即销毁的窄窗口)走异步加载兜底,此时仍可能因 dispose 竞态跳过——
282
+ // SessionEnd 本为 best-effort(宿主进程随即退出也可能截断 hook 执行),该残余可接受
283
+ const manager = (0, hooksManager_1.getHooksManager)();
284
+ if (!manager.isReady()) {
285
+ await manager.ready();
286
+ }
287
+ const entries = manager.getMatchedEntries('SessionEnd');
288
+ if (entries.length === 0)
289
+ return null;
290
+ const payload = { ...buildCommonPayload('SessionEnd', sessionId, MAIN_AGENT), reason: 'dispose' };
291
+ await runEventHooks('SessionEnd', sessionId, payload, entries);
292
+ return null;
293
+ });
294
+ }
295
+ //# sourceMappingURL=hookTriggers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hookTriggers.js","sourceRoot":"","sources":["../../../src/services/hooks/hookTriggers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Hooks 管理器
3
+ *
4
+ * 负责 hooks.json 的加载、合并、校验、缓存与 matcher 匹配。
5
+ * 加载顺序:用户级(~/.sema/hooks/hooks.json) → 项目级(<workingDir>/.sema/hooks/hooks.json),
6
+ * 同一事件的条目按加载顺序追加(不覆盖)。
7
+ */
8
+ import { HooksInfo, LoadedHookEntry } from '../../types/hook';
9
+ declare class HooksManager {
10
+ private userConfigPath;
11
+ private projectConfigPath;
12
+ private entriesByEvent;
13
+ private infoCache;
14
+ private loadingPromise;
15
+ private matcherCache;
16
+ constructor();
17
+ /**
18
+ * 发起一次加载(single-flight:并发调用共享同一个在飞 promise,避免重复文件 IO)
19
+ */
20
+ private startLoad;
21
+ /**
22
+ * 等待配置缓存就绪(就绪后近零开销)
23
+ */
24
+ ready(): Promise<void>;
25
+ /**
26
+ * 配置缓存是否已就绪(同步判断,供需要同步捕获条目的调用方使用)
27
+ */
28
+ isReady(): boolean;
29
+ /**
30
+ * 返回指定事件下 matcher 命中的可执行条目(仅 status === 'ok')
31
+ * 工具类事件按通用工具名 / 内置名匹配;其他事件忽略 matcher 总是触发
32
+ */
33
+ getMatchedEntries(event: string, genericToolName?: string, semaToolName?: string): LoadedHookEntry[];
34
+ /**
35
+ * 获取合并后的配置视图
36
+ * @param refresh true 时重新加载配置,下一次 hook 触发即生效
37
+ */
38
+ getHooksInfo(refresh?: boolean): Promise<HooksInfo>;
39
+ private invalidateCache;
40
+ /**
41
+ * 加载并缓存配置。保证不抛错且总是落缓存:任何异常兜底为空配置,
42
+ * 避免缓存留 null 导致后续每次 hook 触发都重试文件 IO
43
+ */
44
+ private loadAndCache;
45
+ /**
46
+ * 解析单个 hooks.json 内容为条目列表(校验只标 status,不抛错)
47
+ */
48
+ private parseHooksFile;
49
+ private clampTimeoutMs;
50
+ /**
51
+ * matcher 编译(结果按 matcher 字符串缓存):
52
+ * 1. 缺失/空串/'*' → 全匹配
53
+ * 2. 按 '|' 分段后每段均为简单名 → 精确集合匹配(通用工具名和内置名均可命中)
54
+ * 3. 否则整串按正则匹配通用工具名;编译失败 logWarn 一次且该条永不匹配
55
+ */
56
+ private compileMatcher;
57
+ dispose(): void;
58
+ }
59
+ /**
60
+ * 获取 Hooks Manager 实例(单例模式)
61
+ */
62
+ export declare function getHooksManager(): HooksManager;
63
+ export { HooksManager };
64
+ //# sourceMappingURL=hooksManager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hooksManager.d.ts","sourceRoot":"","sources":["../../../src/services/hooks/hooksManager.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AASH,OAAO,EAIL,SAAS,EACT,eAAe,EAEhB,MAAM,kBAAkB,CAAA;AAazB,cAAM,YAAY;IAChB,OAAO,CAAC,cAAc,CAAQ;IAC9B,OAAO,CAAC,iBAAiB,CAAQ;IAEjC,OAAO,CAAC,cAAc,CAA8C;IACpE,OAAO,CAAC,SAAS,CAAyB;IAC1C,OAAO,CAAC,cAAc,CAA6B;IACnD,OAAO,CAAC,YAAY,CAAsC;;IAU1D;;OAEG;IACH,OAAO,CAAC,SAAS;IASjB;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAK5B;;OAEG;IACH,OAAO,IAAI,OAAO;IAIlB;;;OAGG;IACH,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,eAAe,CAAC,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,eAAe,EAAE;IAYpG;;;OAGG;IACG,YAAY,CAAC,OAAO,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,SAAS,CAAC;IAYzD,OAAO,CAAC,eAAe;IAMvB;;;OAGG;YACW,YAAY;IAqF1B;;OAEG;IACH,OAAO,CAAC,cAAc;IA0DtB,OAAO,CAAC,cAAc;IAUtB;;;;;OAKG;IACH,OAAO,CAAC,cAAc;IA+BtB,OAAO,IAAI,IAAI;CAGhB;AAMD;;GAEG;AACH,wBAAgB,eAAe,IAAI,YAAY,CAK9C;AAED,OAAO,EAAE,YAAY,EAAE,CAAA"}