sessix-server 0.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.
Files changed (61) hide show
  1. package/dist/approval/ApprovalProxy.d.ts +86 -0
  2. package/dist/approval/ApprovalProxy.d.ts.map +1 -0
  3. package/dist/approval/ApprovalProxy.js +363 -0
  4. package/dist/approval/ApprovalProxy.js.map +1 -0
  5. package/dist/hooks/HookInstaller.d.ts +55 -0
  6. package/dist/hooks/HookInstaller.d.ts.map +1 -0
  7. package/dist/hooks/HookInstaller.js +215 -0
  8. package/dist/hooks/HookInstaller.js.map +1 -0
  9. package/dist/index.d.ts +2 -0
  10. package/dist/index.d.ts.map +1 -0
  11. package/dist/index.js +3115 -0
  12. package/dist/index.js.map +1 -0
  13. package/dist/mdns/MdnsService.d.ts +36 -0
  14. package/dist/mdns/MdnsService.d.ts.map +1 -0
  15. package/dist/mdns/MdnsService.js +66 -0
  16. package/dist/mdns/MdnsService.js.map +1 -0
  17. package/dist/notification/ActivityPushChannel.d.ts +54 -0
  18. package/dist/notification/ActivityPushChannel.d.ts.map +1 -0
  19. package/dist/notification/ActivityPushChannel.js +235 -0
  20. package/dist/notification/ActivityPushChannel.js.map +1 -0
  21. package/dist/notification/ExpoNotificationChannel.d.ts +17 -0
  22. package/dist/notification/ExpoNotificationChannel.d.ts.map +1 -0
  23. package/dist/notification/ExpoNotificationChannel.js +57 -0
  24. package/dist/notification/ExpoNotificationChannel.js.map +1 -0
  25. package/dist/notification/MacNotificationChannel.d.ts +22 -0
  26. package/dist/notification/MacNotificationChannel.d.ts.map +1 -0
  27. package/dist/notification/MacNotificationChannel.js +33 -0
  28. package/dist/notification/MacNotificationChannel.js.map +1 -0
  29. package/dist/notification/NotificationService.d.ts +50 -0
  30. package/dist/notification/NotificationService.d.ts.map +1 -0
  31. package/dist/notification/NotificationService.js +177 -0
  32. package/dist/notification/NotificationService.js.map +1 -0
  33. package/dist/providers/ExecutionProvider.d.ts +60 -0
  34. package/dist/providers/ExecutionProvider.d.ts.map +1 -0
  35. package/dist/providers/ExecutionProvider.js +3 -0
  36. package/dist/providers/ExecutionProvider.js.map +1 -0
  37. package/dist/providers/ProcessProvider.d.ts +117 -0
  38. package/dist/providers/ProcessProvider.d.ts.map +1 -0
  39. package/dist/providers/ProcessProvider.js +507 -0
  40. package/dist/providers/ProcessProvider.js.map +1 -0
  41. package/dist/server.d.ts +32 -0
  42. package/dist/server.d.ts.map +1 -0
  43. package/dist/server.js +3054 -0
  44. package/dist/server.js.map +1 -0
  45. package/dist/session/ProjectReader.d.ts +44 -0
  46. package/dist/session/ProjectReader.d.ts.map +1 -0
  47. package/dist/session/ProjectReader.js +471 -0
  48. package/dist/session/ProjectReader.js.map +1 -0
  49. package/dist/session/SessionFileWatcher.d.ts +35 -0
  50. package/dist/session/SessionFileWatcher.d.ts.map +1 -0
  51. package/dist/session/SessionFileWatcher.js +207 -0
  52. package/dist/session/SessionFileWatcher.js.map +1 -0
  53. package/dist/session/SessionManager.d.ts +114 -0
  54. package/dist/session/SessionManager.d.ts.map +1 -0
  55. package/dist/session/SessionManager.js +356 -0
  56. package/dist/session/SessionManager.js.map +1 -0
  57. package/dist/ws/WsBridge.d.ts +55 -0
  58. package/dist/ws/WsBridge.d.ts.map +1 -0
  59. package/dist/ws/WsBridge.js +220 -0
  60. package/dist/ws/WsBridge.js.map +1 -0
  61. package/package.json +38 -0
@@ -0,0 +1,177 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.NotificationService = void 0;
4
+ const node_path_1 = require("node:path");
5
+ /**
6
+ * 通知服务
7
+ *
8
+ * 订阅 SessionManager 事件,根据事件类型构造通知内容,
9
+ * 并分发到所有已注册的通知渠道(Mac 本地通知、Expo Push 等)。
10
+ * 同时支持通过 ActivityPushChannel 更新 Live Activity。
11
+ */
12
+ class NotificationService {
13
+ sessionManager;
14
+ expoChannel;
15
+ channelMap = new Map();
16
+ unsubscribe = null;
17
+ activityPushChannel = null;
18
+ /** YOLO 模式状态映射:sessionId -> isYoloMode */
19
+ yoloModeState = new Map();
20
+ constructor(sessionManager, expoChannel = null) {
21
+ this.sessionManager = sessionManager;
22
+ this.expoChannel = expoChannel;
23
+ this.unsubscribe = sessionManager.onEvent((event) => this.handleEvent(event));
24
+ if (expoChannel) {
25
+ this.channelMap.set('expo', { channel: expoChannel, enabled: true });
26
+ }
27
+ }
28
+ /** 添加通知渠道(id 唯一,可用于后续动态开关) */
29
+ addChannel(id, channel, enabled = true) {
30
+ this.channelMap.set(id, { channel, enabled });
31
+ }
32
+ /** 运行时切换指定渠道的启用状态 */
33
+ setChannelEnabled(id, enabled) {
34
+ const entry = this.channelMap.get(id);
35
+ if (entry)
36
+ entry.enabled = enabled;
37
+ }
38
+ /** 注册手机 push token(连接建立时由 WsBridge 调用) */
39
+ addPushToken(token) {
40
+ this.expoChannel?.addToken(token);
41
+ }
42
+ /** 移除手机 push token(断线时或手机主动注销时调用) */
43
+ removePushToken(token) {
44
+ this.expoChannel?.removeToken(token);
45
+ }
46
+ /** 设置 ActivityKit Push 渠道(可选,需要 APNs 认证配置) */
47
+ setActivityPushChannel(channel) {
48
+ this.activityPushChannel = channel;
49
+ }
50
+ /** 注册 ActivityKit push token(由手机端启动 Live Activity 后上报) */
51
+ addActivityPushToken(sessionId, token) {
52
+ this.activityPushChannel?.addToken(sessionId, token);
53
+ }
54
+ /** 移除 ActivityKit push token */
55
+ removeActivityPushToken(sessionId) {
56
+ this.activityPushChannel?.removeToken(sessionId);
57
+ }
58
+ /** 更新会话的 YOLO 模式状态 */
59
+ setYoloMode(sessionId, enabled) {
60
+ this.yoloModeState.set(sessionId, enabled);
61
+ }
62
+ /** 直接触发审批通知(由 ApprovalProxy 回调调用) */
63
+ notifyApproval(request) {
64
+ // YOLO 模式:客户端会自动批准,不发推送
65
+ if (this.yoloModeState.get(request.sessionId))
66
+ return;
67
+ const projectName = this.getProjectName(request.sessionId);
68
+ this.notify({
69
+ title: `需要授权 — ${projectName}`,
70
+ body: `${request.toolName}: ${request.description}`,
71
+ sound: 'Funk',
72
+ data: {
73
+ type: 'approval_request',
74
+ sessionId: request.sessionId,
75
+ requestId: request.id,
76
+ },
77
+ });
78
+ // 通过 APNs 更新 Live Activity(显示审批请求)
79
+ if (this.activityPushChannel?.hasToken(request.sessionId)) {
80
+ const dangerLevel = this.getDangerLevel(request.toolName);
81
+ const isYoloMode = this.getYoloMode(request.sessionId);
82
+ this.activityPushChannel.updateActivityWithAlert(request.sessionId, {
83
+ status: 'waitingApproval',
84
+ latestMessage: `${request.toolName}: ${request.description}`,
85
+ approvalInfo: {
86
+ requestId: request.id,
87
+ toolName: request.toolName,
88
+ description: request.description.slice(0, 80),
89
+ dangerLevel,
90
+ },
91
+ isYoloMode,
92
+ updatedAt: Date.now(),
93
+ }, {
94
+ title: `需要授权 — ${projectName}`,
95
+ body: `${request.toolName}: ${request.description}`,
96
+ });
97
+ }
98
+ }
99
+ /** 简单的工具危险等级判断 */
100
+ getDangerLevel(toolName) {
101
+ if (toolName === 'Bash')
102
+ return 'danger';
103
+ if (['Write', 'Edit', 'NotebookEdit'].includes(toolName))
104
+ return 'write';
105
+ return 'safe';
106
+ }
107
+ /** 清理资源 */
108
+ destroy() {
109
+ this.unsubscribe?.();
110
+ this.unsubscribe = null;
111
+ this.yoloModeState.clear();
112
+ }
113
+ // ============================================
114
+ // 内部方法
115
+ // ============================================
116
+ handleEvent(event) {
117
+ switch (event.type) {
118
+ case 'status_change': {
119
+ if (event.status === 'idle') {
120
+ const projectName = this.getProjectName(event.sessionId);
121
+ const isYoloMode = this.getYoloMode(event.sessionId);
122
+ this.notify({
123
+ title: `任务完成 — ${projectName}`,
124
+ body: '已完成,等待下一步指令',
125
+ sound: 'Glass',
126
+ data: { type: 'task_complete', sessionId: event.sessionId },
127
+ });
128
+ // 通过 APNs 结束 Live Activity
129
+ this.activityPushChannel?.endActivity(event.sessionId, {
130
+ status: 'idle',
131
+ latestMessage: '已完成,等待下一步指令',
132
+ isYoloMode,
133
+ updatedAt: Date.now(),
134
+ });
135
+ }
136
+ else if (event.status === 'error') {
137
+ const projectName = this.getProjectName(event.sessionId);
138
+ const isYoloMode = this.getYoloMode(event.sessionId);
139
+ this.notify({
140
+ title: `出错了 — ${projectName}`,
141
+ body: '执行出错,请查看详情',
142
+ sound: 'Basso',
143
+ data: { type: 'task_error', sessionId: event.sessionId },
144
+ });
145
+ // 通过 APNs 结束 Live Activity
146
+ this.activityPushChannel?.endActivity(event.sessionId, {
147
+ status: 'error',
148
+ latestMessage: '执行出错,请查看详情',
149
+ isYoloMode,
150
+ updatedAt: Date.now(),
151
+ });
152
+ }
153
+ break;
154
+ }
155
+ // 其他事件不发通知
156
+ }
157
+ }
158
+ notify(payload) {
159
+ for (const { channel, enabled } of this.channelMap.values()) {
160
+ if (!enabled)
161
+ continue;
162
+ channel.send(payload).catch((err) => {
163
+ console.error('[NotificationService] 通知发送失败:', err);
164
+ });
165
+ }
166
+ }
167
+ getProjectName(sessionId) {
168
+ const session = this.sessionManager.getActiveSessions().find((s) => s.id === sessionId);
169
+ return session ? (0, node_path_1.basename)(session.projectPath) : 'Unknown';
170
+ }
171
+ /** 获取会话的 YOLO 模式状态 */
172
+ getYoloMode(sessionId) {
173
+ return this.yoloModeState.get(sessionId) ?? false;
174
+ }
175
+ }
176
+ exports.NotificationService = NotificationService;
177
+ //# sourceMappingURL=NotificationService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NotificationService.js","sourceRoot":"","sources":["../../src/notification/NotificationService.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,60 @@
1
+ import type { Session, ClaudeStreamEvent } from '@sessix/shared';
2
+ /** 启动会话的选项 */
3
+ export interface StartSessionOptions {
4
+ /** 项目的绝对路径 */
5
+ projectPath: string;
6
+ /** 发送给 Claude 的消息 */
7
+ message: string;
8
+ /** 恢复已有会话时传入该会话的 ID(使用 --resume) */
9
+ sessionId?: string;
10
+ /** true = --resume(恢复);false = --session-id(新建但指定 ID);默认跟随 sessionId 是否存在 */
11
+ resume?: boolean;
12
+ /** 使用的模型别名(haiku / sonnet / opus),不传则用 claude 默认 */
13
+ model?: string;
14
+ }
15
+ /**
16
+ * 执行提供者接口
17
+ *
18
+ * 所有控制 Claude CLI 进程的操作必须通过此接口,
19
+ * 当前实现为 ProcessProvider(直接 spawn 进程),
20
+ * 未来可替换为 DockerProvider 等其他实现。
21
+ */
22
+ export interface ExecutionProvider {
23
+ /** 启动新会话或恢复已有会话 */
24
+ startSession(opts: StartSessionOptions): Promise<Session>;
25
+ /** 终止指定会话 */
26
+ killSession(sessionId: string): Promise<void>;
27
+ /** 向已有会话发送新消息(会重启进程并携带相同 session-id) */
28
+ sendMessage(sessionId: string, message: string): Promise<void>;
29
+ /** 订阅指定会话的 Claude 事件流,返回取消订阅函数 */
30
+ onEvent(sessionId: string, callback: (event: ClaudeStreamEvent) => void): () => void;
31
+ /** 获取当前所有活跃会话列表 */
32
+ getActiveSessions(): Session[];
33
+ /**
34
+ * 根据对话上下文生成下一步建议指令(一次性调用,不关联任何会话)
35
+ *
36
+ * @param context 最近的对话内容(格式化为纯文本)
37
+ * @returns 建议的指令文本
38
+ */
39
+ generateSuggestion(context: string): Promise<string>;
40
+ /**
41
+ * 向正在等待中的 AskUserQuestion 提供答案
42
+ *
43
+ * 通过 stdin 写入 tool_result 让 Claude 继续执行。
44
+ * @param sessionId 会话 ID
45
+ * @param toolUseId AskUserQuestion tool_use 块的 id
46
+ * @param answer 用户的答案文本
47
+ */
48
+ answerQuestion(sessionId: string, toolUseId: string, answer: string): Promise<void>;
49
+ /**
50
+ * 订阅指定会话的 AskUserQuestion 事件
51
+ *
52
+ * @returns 取消订阅函数
53
+ */
54
+ onQuestion(sessionId: string, callback: (data: {
55
+ toolUseId: string;
56
+ question: string;
57
+ options?: string[];
58
+ }) => void): () => void;
59
+ }
60
+ //# sourceMappingURL=ExecutionProvider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ExecutionProvider.d.ts","sourceRoot":"","sources":["../../src/providers/ExecutionProvider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAA;AAMhE,cAAc;AACd,MAAM,WAAW,mBAAmB;IAClC,cAAc;IACd,WAAW,EAAE,MAAM,CAAA;IACnB,qBAAqB;IACrB,OAAO,EAAE,MAAM,CAAA;IACf,oCAAoC;IACpC,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,6EAA6E;IAC7E,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,oDAAoD;IACpD,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED;;;;;;GAMG;AACH,MAAM,WAAW,iBAAiB;IAChC,mBAAmB;IACnB,YAAY,CAAC,IAAI,EAAE,mBAAmB,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;IAEzD,aAAa;IACb,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAE7C,wCAAwC;IACxC,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAE9D,kCAAkC;IAClC,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,IAAI,GAAG,MAAM,IAAI,CAAA;IAEpF,mBAAmB;IACnB,iBAAiB,IAAI,OAAO,EAAE,CAAA;IAE9B;;;;;OAKG;IACH,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;IAEpD;;;;;;;OAOG;IACH,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAEnF;;;;OAIG;IACH,UAAU,CACR,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,CAAC,IAAI,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,KAAK,IAAI,GACpF,MAAM,IAAI,CAAA;CACd"}
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=ExecutionProvider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ExecutionProvider.js","sourceRoot":"","sources":["../../src/providers/ExecutionProvider.ts"],"names":[],"mappings":""}
@@ -0,0 +1,117 @@
1
+ import type { Session, ClaudeStreamEvent } from '@sessix/shared';
2
+ import type { ExecutionProvider, StartSessionOptions } from './ExecutionProvider.js';
3
+ /**
4
+ * 基于 child_process.spawn 的 ExecutionProvider 实现
5
+ *
6
+ * 直接在本机通过 spawn 启动 `claude` CLI 进程,
7
+ * 从 stdout 逐行读取 NDJSON 格式的 stream-json 事件。
8
+ */
9
+ export declare class ProcessProvider implements ExecutionProvider {
10
+ /** 活跃会话映射表:sessionId -> { session, process } */
11
+ private activeSessions;
12
+ /** 事件发射器,用于分发 Claude 事件流 */
13
+ private emitter;
14
+ /**
15
+ * 启动新会话或恢复已有会话
16
+ *
17
+ * 会 spawn 一个 `claude` CLI 进程,设置工作目录和环境变量,
18
+ * 并开始监听 stdout 的 NDJSON 输出。
19
+ */
20
+ startSession(opts: StartSessionOptions): Promise<Session>;
21
+ /**
22
+ * 终止指定会话
23
+ *
24
+ * kill 进程并从活跃映射中移除。
25
+ */
26
+ killSession(sessionId: string): Promise<void>;
27
+ /**
28
+ * 向已有会话发送新消息
29
+ *
30
+ * 快速路径:进程存活时直接写 stdin(毫秒级响应)。
31
+ * 慢速路径:进程已退出时 respawn 并 --resume。
32
+ */
33
+ sendMessage(sessionId: string, message: string): Promise<void>;
34
+ /**
35
+ * 订阅指定会话的 Claude 事件流
36
+ *
37
+ * @returns 取消订阅函数
38
+ */
39
+ onEvent(sessionId: string, callback: (event: ClaudeStreamEvent) => void): () => void;
40
+ /**
41
+ * 获取当前所有活跃会话列表
42
+ */
43
+ getActiveSessions(): Session[];
44
+ /**
45
+ * 启动 claude CLI 进程(持久模式,stdin 保持开放接收多条消息)
46
+ */
47
+ private spawnClaudeProcess;
48
+ /**
49
+ * 向持久进程的 stdin 写入一条用户消息(NDJSON 格式)
50
+ *
51
+ * 写入失败时合成 error result 事件,确保 SessionManager 能感知到失败。
52
+ */
53
+ private writeUserMessage;
54
+ /**
55
+ * 发出写入失败的合成错误事件
56
+ */
57
+ private emitWriteError;
58
+ /**
59
+ * 挂载 stdout 监听器,逐行解析 NDJSON
60
+ */
61
+ private attachStdoutListener;
62
+ /**
63
+ * 挂载 stderr 监听器,记录日志
64
+ */
65
+ private attachStderrListener;
66
+ /**
67
+ * 挂载进程退出监听器
68
+ *
69
+ * 当进程退出时发出合成的 result 事件,确保 SessionManager 能感知到退出。
70
+ * 正常退出时 Claude 会先通过 stdout 发送真实 result 事件,
71
+ * updateSessionStatus 会将 session.status 更新为 idle/error。
72
+ * 此时合成事件会重复触发,导致手机端出现两张总结卡。
73
+ * 修复:已收到真实 result(status 已为 idle/error)时跳过合成事件。
74
+ * 异常退出时(crash/OOM/killed)没有真实 result 事件,合成事件确保状态正确广播。
75
+ */
76
+ private attachExitListener;
77
+ /**
78
+ * 解析一行 NDJSON 文本为 ClaudeStreamEvent
79
+ */
80
+ private parseLine;
81
+ /**
82
+ * 根据 Claude 事件更新会话状态
83
+ */
84
+ private updateSessionStatus;
85
+ /**
86
+ * 根据对话上下文生成下一步建议指令
87
+ *
88
+ * 使用 --output-format text 做一次性调用,返回纯文本结果。
89
+ */
90
+ generateSuggestion(context: string): Promise<string>;
91
+ /**
92
+ * 向正在等待中的 AskUserQuestion 提供答案
93
+ *
94
+ * 将答案写入 Claude 进程的 stdin(作为 tool_result),
95
+ * Claude 收到后继续执行。
96
+ */
97
+ answerQuestion(sessionId: string, toolUseId: string, answer: string): Promise<void>;
98
+ /**
99
+ * 订阅指定会话的 AskUserQuestion 事件
100
+ *
101
+ * @returns 取消订阅函数
102
+ */
103
+ onQuestion(sessionId: string, callback: (data: {
104
+ toolUseId: string;
105
+ question: string;
106
+ options?: string[];
107
+ }) => void): () => void;
108
+ /**
109
+ * 生成事件名称
110
+ */
111
+ private getEventName;
112
+ /**
113
+ * 生成 AskUserQuestion 内部事件名称
114
+ */
115
+ private getQuestionEventName;
116
+ }
117
+ //# sourceMappingURL=ProcessProvider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ProcessProvider.d.ts","sourceRoot":"","sources":["../../src/providers/ProcessProvider.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,OAAO,EAAE,iBAAiB,EAAU,MAAM,gBAAgB,CAAA;AACxE,OAAO,KAAK,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAA;AA0CpF;;;;;GAKG;AACH,qBAAa,eAAgB,YAAW,iBAAiB;IACvD,gDAAgD;IAChD,OAAO,CAAC,cAAc,CAA6C;IAEnE,4BAA4B;IAC5B,OAAO,CAAC,OAAO,CAAmC;IAElD;;;;;OAKG;IACG,YAAY,CAAC,IAAI,EAAE,mBAAmB,GAAG,OAAO,CAAC,OAAO,CAAC;IA+D/D;;;;OAIG;IACG,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAiCnD;;;;;OAKG;IACG,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAgDpE;;;;OAIG;IACH,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,IAAI,GAAG,MAAM,IAAI;IAUpF;;OAEG;IACH,iBAAiB,IAAI,OAAO,EAAE;IAQ9B;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAuC1B;;;;OAIG;IACH,OAAO,CAAC,gBAAgB;IAwBxB;;OAEG;IACH,OAAO,CAAC,cAAc;IAatB;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAgD5B;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAW5B;;;;;;;;;OASG;IACH,OAAO,CAAC,kBAAkB;IA0C1B;;OAEG;IACH,OAAO,CAAC,SAAS;IAYjB;;OAEG;IACH,OAAO,CAAC,mBAAmB;IA0B3B;;;;OAIG;IACG,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAgC1D;;;;;OAKG;IACG,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA2BzF;;;;OAIG;IACH,UAAU,CACR,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,CAAC,IAAI,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,KAAK,IAAI,GACpF,MAAM,IAAI;IAQb;;OAEG;IACH,OAAO,CAAC,YAAY;IAIpB;;OAEG;IACH,OAAO,CAAC,oBAAoB;CAG7B"}