@xgjktech/xg_cwork_im 1.11.3 → 1.11.4

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 (51) hide show
  1. package/README.md +10 -10
  2. package/dist/index.d.ts +10 -0
  3. package/dist/index.d.ts.map +1 -0
  4. package/{index.ts → dist/index.js} +5 -9
  5. package/dist/index.js.map +1 -0
  6. package/dist/src/auth.d.ts +25 -0
  7. package/dist/src/auth.d.ts.map +1 -0
  8. package/{src/auth.ts → dist/src/auth.js} +55 -79
  9. package/dist/src/auth.js.map +1 -0
  10. package/dist/src/channel.d.ts +13 -0
  11. package/dist/src/channel.d.ts.map +1 -0
  12. package/{src/channel.ts → dist/src/channel.js} +180 -385
  13. package/dist/src/channel.js.map +1 -0
  14. package/dist/src/connection.d.ts +51 -0
  15. package/dist/src/connection.d.ts.map +1 -0
  16. package/{src/connection.ts → dist/src/connection.js} +45 -122
  17. package/dist/src/connection.js.map +1 -0
  18. package/dist/src/group-history-tool.d.ts +23 -0
  19. package/dist/src/group-history-tool.d.ts.map +1 -0
  20. package/{src/group-history-tool.ts → dist/src/group-history-tool.js} +168 -204
  21. package/dist/src/group-history-tool.js.map +1 -0
  22. package/dist/src/inbound-media-local.d.ts +40 -0
  23. package/dist/src/inbound-media-local.d.ts.map +1 -0
  24. package/{src/inbound-media-local.ts → dist/src/inbound-media-local.js} +52 -90
  25. package/dist/src/inbound-media-local.js.map +1 -0
  26. package/dist/src/recommended-system-prompt.d.ts +3 -0
  27. package/dist/src/recommended-system-prompt.d.ts.map +1 -0
  28. package/dist/src/recommended-system-prompt.js +3 -0
  29. package/dist/src/recommended-system-prompt.js.map +1 -0
  30. package/dist/src/resource-file.d.ts +65 -0
  31. package/dist/src/resource-file.d.ts.map +1 -0
  32. package/{src/resource-file.ts → dist/src/resource-file.js} +77 -99
  33. package/dist/src/resource-file.js.map +1 -0
  34. package/dist/src/send-group-message-tool.d.ts +16 -0
  35. package/dist/src/send-group-message-tool.d.ts.map +1 -0
  36. package/{src/send-group-message-tool.ts → dist/src/send-group-message-tool.js} +17 -34
  37. package/dist/src/send-group-message-tool.js.map +1 -0
  38. package/dist/src/send-service.d.ts +34 -0
  39. package/dist/src/send-service.d.ts.map +1 -0
  40. package/{src/send-service.ts → dist/src/send-service.js} +60 -146
  41. package/dist/src/send-service.js.map +1 -0
  42. package/{src/tool-json-result.ts → dist/src/tool-json-result.d.ts} +14 -24
  43. package/dist/src/tool-json-result.d.ts.map +1 -0
  44. package/dist/src/tool-json-result.js +20 -0
  45. package/dist/src/tool-json-result.js.map +1 -0
  46. package/{src/types.ts → dist/src/types.d.ts} +26 -94
  47. package/dist/src/types.d.ts.map +1 -0
  48. package/dist/src/types.js +32 -0
  49. package/dist/src/types.js.map +1 -0
  50. package/package.json +7 -6
  51. package/src/recommended-system-prompt.ts +0 -3
@@ -1,204 +1,168 @@
1
- /**
2
- * XG-IM 群聊历史记录工具(供 AI 按需调用)
3
- *
4
- * 通过 OpenClaw 的 api.registerTool() 注入,让 AI 在感知到需要上下文时
5
- * 主动拉取群聊最近 N 条历史消息,而不是每次收到 @ 都强行拉取。
6
- */
7
-
8
- import axios from "axios";
9
- import { Type, type Static } from "@sinclair/typebox";
10
- import type { AnyAgentTool } from "openclaw/plugin-sdk";
11
- import { toolJsonResult } from "./tool-json-result.js";
12
- import { getToken } from "./auth.js";
13
- import type { BotIdentity, WsMessageParams, XgImConfig } from "./types.js";
14
-
15
- // ─── 工具参数 Schema ─────────────────────────────────────────────────────────
16
-
17
- const GroupHistoryParams = Type.Object({
18
- groupId: Type.String({
19
- description: "群聊 ID,即当前消息来自的群组唯一标识符",
20
- }),
21
- userId: Type.Optional(
22
- Type.String({
23
- description: "(可选)以哪个用户身份拉取历史消息的 userId,普通对话场景建议传当前发消息用户 ID;若为空则按后台默认身份查询",
24
- }),
25
- ),
26
- accountId: Type.Optional(
27
- Type.String({
28
- description:
29
- "(可选)要使用的 xg_cwork_im 账户 ID(即 accounts 的 key,例如 main/orchestrator)。",
30
- }),
31
- ),
32
- limit: Type.Optional(
33
- Type.Number({
34
- description: "需要获取的消息条数(5~30),默认 10",
35
- minimum: 1,
36
- maximum: 30,
37
- default: 10,
38
- }),
39
- ),
40
- });
41
-
42
- // ─── 内部 HTTP 工具 ──────────────────────────────────────────────────────────
43
-
44
- /** OpenClaw 配置中提取 xg_cwork_im 顶层配置(保留 accounts 以便多账户路由) */
45
- export function extractXgCworkImConfig(cfg: unknown): XgImConfig | null {
46
- const raw = (cfg as Record<string, Record<string, unknown>>)?.channels?.xg_cwork_im as XgImConfig | undefined;
47
- if (!raw?.baseUrl) return null;
48
- return raw;
49
- }
50
-
51
- /**
52
- * 根据 accountId 解析具体账号配置。
53
- *
54
- * - 若传入 accountId 且能解析为有效下标,则优先使用对应 accounts[accountId]。
55
- * - 否则:有 accounts 时默认使用 accounts[0];无 accounts 时使用顶层配置。
56
- */
57
- export function resolveAccountConfig(base: XgImConfig, accountId?: string | null): XgImConfig {
58
- const accounts = base.accounts;
59
- if (!accounts) {
60
- return base;
61
- }
62
-
63
- const map = accounts as Record<string, XgImConfig | undefined>;
64
- const defaults = map.default ? { ...map.default } : undefined;
65
-
66
- if (accountId && accountId !== "default") {
67
- const hit = map[accountId];
68
- if (hit) return { ...base, ...(defaults ?? {}), ...hit };
69
- }
70
- const firstKey = Object.keys(map).find((k) => k !== "default");
71
- const first = firstKey ? map[firstKey] : undefined;
72
- return first ? { ...base, ...(defaults ?? {}), ...first } : base;
73
- }
74
-
75
- /** 调用 IM 接口拉取群聊最近 N 条消息 */
76
- async function fetchGroupHistory(
77
- config: XgImConfig,
78
- token: string,
79
- groupId: string,
80
- limit: number,
81
- userId?: string,
82
- ): Promise<WsMessageParams[]> {
83
- const url = `${config.baseUrl}/im/message/getLatestMsgListForAI`;
84
-
85
- const params: Record<string, unknown> = {
86
- groupId,
87
- msgCount: limit,
88
- };
89
- if (userId) {
90
- params.userId = userId;
91
- }
92
-
93
- const res = await axios.get<{
94
- resultCode: number;
95
- message?: string;
96
- data?: WsMessageParams[];
97
- }>(url, {
98
- params,
99
- headers: { "access-token": token },
100
- timeout: 8_000,
101
- });
102
-
103
- const body = res.data;
104
- if ((body.resultCode !== 1 && body.resultCode !== 200) || !Array.isArray(body.data)) {
105
- return [];
106
- }
107
- return body.data;
108
- }
109
-
110
- // ─── 工具构建函数(直接传 config,而非 factory 模式)──────────────────────────
111
-
112
- /**
113
- * 构建群聊历史工具对象(使用注册时已知的 config,绕开 factory 工厂模式的命名限制)。
114
- * 由 index.ts 在 register() 里调用,并将构建好的工具对象静态地传给 api.registerTool(tool)。
115
- */
116
- export function buildGroupHistoryTool(config: XgImConfig): AnyAgentTool {
117
- return {
118
- name: "xg_cwork_im_get_group_chat_history",
119
- label: "【xg_cwork_im】获取群聊历史记录",
120
- description: [
121
- "【仅限 xg_cwork_im 通道】获取当前 IM 群聊的最近消息历史,用于理解对话上下文背景。",
122
- "",
123
- "以下情况你必须先调用此工具,不得直接向用户反问或要求澄清:",
124
- "- 用户使用了指代词却没说清楚指的是什么(如'这'、'那'、'上面说的'、'刚才提到的'、'这两家公司'等)",
125
- "- 用户的问题依赖之前的对话才能正确理解(如'对吗'、'怎么查的'、'分析一下'但没给出主语)",
126
- "- 你不确定用户问题的背景或主语时",
127
- "",
128
- "调用此工具后你会获得最近 N 条消息,用于还原上下文再给出回答。",
129
- "groupId 必须从会话元数据 group_channel 字段中解析,当且仅当其前缀为 agent:main:xg_cwork_im:group:<groupId> 时才可以调用本工具。",
130
- "",
131
- "【只有在以下情况才可以不调用】:用户的问题明确且自洽,不依赖任何历史对话。",
132
- ].join("\n"),
133
- parameters: GroupHistoryParams,
134
- async execute(_toolCallId: string, params: Static<typeof GroupHistoryParams>) {
135
- const limit = params.limit ?? 10;
136
- const { groupId, accountId, userId } = params;
137
-
138
- console.log(`[cwork_im][tool] xg_cwork_im_get_group_chat_history called: groupId=${groupId} limit=${limit}`);
139
-
140
- let identity: BotIdentity;
141
- try {
142
- const accountConfig = resolveAccountConfig(config, accountId);
143
- identity = await getToken(accountConfig);
144
- console.log(`[cwork_im][tool] token acquired for userId=${identity.userId}`);
145
- } catch (err: unknown) {
146
- return toolJsonResult({
147
- ok: false,
148
- error: `Failed to obtain access token: ${String(err)}`,
149
- messages: [],
150
- });
151
- }
152
-
153
- let messages: WsMessageParams[];
154
- try {
155
- const accountConfig = resolveAccountConfig(config, accountId);
156
- messages = await fetchGroupHistory(accountConfig, identity.token, groupId, limit, userId);
157
- console.log(
158
- `[cwork_im][tool] fetched ${messages.length} messages from group ${groupId} using accountId=${accountId ?? "0"} userId=${userId ?? "N/A"}`,
159
- );
160
- } catch (err: unknown) {
161
- return toolJsonResult({
162
- ok: false,
163
- error: `Failed to fetch group history: ${String(err)}`,
164
- messages: [],
165
- });
166
- }
167
-
168
- // 格式化成对话摘要,方便 AI 理解
169
- const formatted = messages
170
- .filter((m) => {
171
- const t = m.msgContent?.type;
172
- return t === "text" || t === "file";
173
- })
174
- .map((m) => {
175
- const senderId = m.userInfo?.id ?? "";
176
- const senderName = m.userInfo?.name || senderId || "未知用户";
177
- const isBot = senderId === identity.userId;
178
- const sender = isBot ? "[AI]" : senderName;
179
- const ts = m.timestamp ?? m.msgSendTime ?? 0;
180
- const time = new Date(ts).toLocaleTimeString("zh-CN", { hour12: false });
181
- const c = m.msgContent;
182
- const body =
183
- c?.type === "file" && c.files?.length
184
- ? [
185
- c.text?.trim(),
186
- `[附件 ${c.files.length} 个: ${c.files
187
- .map((f) => f.name?.trim() || f.fileId || "文件")
188
- .join("、")}]`,
189
- ]
190
- .filter(Boolean)
191
- .join(" ")
192
- : (c?.text ?? "");
193
- return `[${time}] ${sender}: ${body}`;
194
- });
195
-
196
- return toolJsonResult({
197
- ok: true,
198
- groupId,
199
- count: formatted.length,
200
- messages: formatted,
201
- });
202
- },
203
- };
204
- }
1
+ /**
2
+ * XG-IM 群聊历史记录工具(供 AI 按需调用)
3
+ *
4
+ * 通过 OpenClaw 的 api.registerTool() 注入,让 AI 在感知到需要上下文时
5
+ * 主动拉取群聊最近 N 条历史消息,而不是每次收到 @ 都强行拉取。
6
+ */
7
+ import axios from "axios";
8
+ import { Type } from "@sinclair/typebox";
9
+ import { toolJsonResult } from "./tool-json-result.js";
10
+ import { getToken } from "./auth.js";
11
+ // ─── 工具参数 Schema ─────────────────────────────────────────────────────────
12
+ const GroupHistoryParams = Type.Object({
13
+ groupId: Type.String({
14
+ description: "群聊 ID,即当前消息来自的群组唯一标识符",
15
+ }),
16
+ userId: Type.Optional(Type.String({
17
+ description: "(可选)以哪个用户身份拉取历史消息的 userId,普通对话场景建议传当前发消息用户 ID;若为空则按后台默认身份查询",
18
+ })),
19
+ accountId: Type.Optional(Type.String({
20
+ description: "(可选)要使用的 xg_cwork_im 账户 ID(即 accounts 的 key,例如 main/orchestrator)。",
21
+ })),
22
+ limit: Type.Optional(Type.Number({
23
+ description: "需要获取的消息条数(5~30),默认 10",
24
+ minimum: 1,
25
+ maximum: 30,
26
+ default: 10,
27
+ })),
28
+ });
29
+ // ─── 内部 HTTP 工具 ──────────────────────────────────────────────────────────
30
+ /** 从 OpenClaw 配置中提取 xg_cwork_im 顶层配置(保留 accounts 以便多账户路由) */
31
+ export function extractXgCworkImConfig(cfg) {
32
+ const raw = cfg?.channels?.xg_cwork_im;
33
+ if (!raw?.baseUrl)
34
+ return null;
35
+ return raw;
36
+ }
37
+ /**
38
+ * 根据 accountId 解析具体账号配置。
39
+ *
40
+ * - 若传入 accountId 且能解析为有效下标,则优先使用对应 accounts[accountId]。
41
+ * - 否则:有 accounts 时默认使用 accounts[0];无 accounts 时使用顶层配置。
42
+ */
43
+ export function resolveAccountConfig(base, accountId) {
44
+ const accounts = base.accounts;
45
+ if (!accounts) {
46
+ return base;
47
+ }
48
+ const map = accounts;
49
+ const defaults = map.default ? { ...map.default } : undefined;
50
+ if (accountId && accountId !== "default") {
51
+ const hit = map[accountId];
52
+ if (hit)
53
+ return { ...base, ...(defaults ?? {}), ...hit };
54
+ }
55
+ const firstKey = Object.keys(map).find((k) => k !== "default");
56
+ const first = firstKey ? map[firstKey] : undefined;
57
+ return first ? { ...base, ...(defaults ?? {}), ...first } : base;
58
+ }
59
+ /** 调用 IM 接口拉取群聊最近 N 条消息 */
60
+ async function fetchGroupHistory(config, token, groupId, limit, userId) {
61
+ const url = `${config.baseUrl}/im/message/getLatestMsgListForAI`;
62
+ const params = {
63
+ groupId,
64
+ msgCount: limit,
65
+ };
66
+ if (userId) {
67
+ params.userId = userId;
68
+ }
69
+ const res = await axios.get(url, {
70
+ params,
71
+ headers: { "access-token": token },
72
+ timeout: 8_000,
73
+ });
74
+ const body = res.data;
75
+ if ((body.resultCode !== 1 && body.resultCode !== 200) || !Array.isArray(body.data)) {
76
+ return [];
77
+ }
78
+ return body.data;
79
+ }
80
+ // ─── 工具构建函数(直接传 config,而非 factory 模式)──────────────────────────
81
+ /**
82
+ * 构建群聊历史工具对象(使用注册时已知的 config,绕开 factory 工厂模式的命名限制)。
83
+ * index.ts 在 register() 里调用,并将构建好的工具对象静态地传给 api.registerTool(tool)。
84
+ */
85
+ export function buildGroupHistoryTool(config) {
86
+ return {
87
+ name: "xg_cwork_im_get_group_chat_history",
88
+ label: "【xg_cwork_im】获取群聊历史记录",
89
+ description: [
90
+ "【仅限 xg_cwork_im 通道】获取当前 IM 群聊的最近消息历史,用于理解对话上下文背景。",
91
+ "",
92
+ "以下情况你必须先调用此工具,不得直接向用户反问或要求澄清:",
93
+ "- 用户使用了指代词却没说清楚指的是什么(如'这'、'那'、'上面说的'、'刚才提到的'、'这两家公司'等)",
94
+ "- 用户的问题依赖之前的对话才能正确理解(如'对吗'、'怎么查的'、'分析一下'但没给出主语)",
95
+ "- 你不确定用户问题的背景或主语时",
96
+ "",
97
+ "调用此工具后你会获得最近 N 条消息,用于还原上下文再给出回答。",
98
+ "groupId 必须从会话元数据 group_channel 字段中解析,当且仅当其前缀为 agent:main:xg_cwork_im:group:<groupId> 时才可以调用本工具。",
99
+ "",
100
+ "【只有在以下情况才可以不调用】:用户的问题明确且自洽,不依赖任何历史对话。",
101
+ ].join("\n"),
102
+ parameters: GroupHistoryParams,
103
+ async execute(_toolCallId, params) {
104
+ const limit = params.limit ?? 10;
105
+ const { groupId, accountId, userId } = params;
106
+ console.log(`[cwork_im][tool] xg_cwork_im_get_group_chat_history called: groupId=${groupId} limit=${limit}`);
107
+ let identity;
108
+ try {
109
+ const accountConfig = resolveAccountConfig(config, accountId);
110
+ identity = await getToken(accountConfig);
111
+ console.log(`[cwork_im][tool] token acquired for userId=${identity.userId}`);
112
+ }
113
+ catch (err) {
114
+ return toolJsonResult({
115
+ ok: false,
116
+ error: `Failed to obtain access token: ${String(err)}`,
117
+ messages: [],
118
+ });
119
+ }
120
+ let messages;
121
+ try {
122
+ const accountConfig = resolveAccountConfig(config, accountId);
123
+ messages = await fetchGroupHistory(accountConfig, identity.token, groupId, limit, userId);
124
+ console.log(`[cwork_im][tool] fetched ${messages.length} messages from group ${groupId} using accountId=${accountId ?? "0"} userId=${userId ?? "N/A"}`);
125
+ }
126
+ catch (err) {
127
+ return toolJsonResult({
128
+ ok: false,
129
+ error: `Failed to fetch group history: ${String(err)}`,
130
+ messages: [],
131
+ });
132
+ }
133
+ // 格式化成对话摘要,方便 AI 理解
134
+ const formatted = messages
135
+ .filter((m) => {
136
+ const t = m.msgContent?.type;
137
+ return t === "text" || t === "file";
138
+ })
139
+ .map((m) => {
140
+ const senderId = m.userInfo?.id ?? "";
141
+ const senderName = m.userInfo?.name || senderId || "未知用户";
142
+ const isBot = senderId === identity.userId;
143
+ const sender = isBot ? "[AI]" : senderName;
144
+ const ts = m.timestamp ?? m.msgSendTime ?? 0;
145
+ const time = new Date(ts).toLocaleTimeString("zh-CN", { hour12: false });
146
+ const c = m.msgContent;
147
+ const body = c?.type === "file" && c.files?.length
148
+ ? [
149
+ c.text?.trim(),
150
+ `[附件 ${c.files.length} 个: ${c.files
151
+ .map((f) => f.name?.trim() || f.fileId || "文件")
152
+ .join("、")}]`,
153
+ ]
154
+ .filter(Boolean)
155
+ .join(" ")
156
+ : (c?.text ?? "");
157
+ return `[${time}] ${sender}: ${body}`;
158
+ });
159
+ return toolJsonResult({
160
+ ok: true,
161
+ groupId,
162
+ count: formatted.length,
163
+ messages: formatted,
164
+ });
165
+ },
166
+ };
167
+ }
168
+ //# sourceMappingURL=group-history-tool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"group-history-tool.js","sourceRoot":"","sources":["../../src/group-history-tool.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * 入站附件:可选落盘到当前 Agent workspace 下指定子目录(相对路径)。
3
+ *
4
+ * 目录约定:{subdir}/{userId}/{YYYY-MM-DD}/{stem}_{HHmmssmmm}{ext}
5
+ * 时间取写入时的本地时区。
6
+ */
7
+ import type { OpenClawConfig } from "openclaw/plugin-sdk";
8
+ import type { Log } from "./auth.js";
9
+ import type { MsgFileVO, XgImConfig } from "./types.js";
10
+ /** 校验:非空、相对路径、不含 `..` 段 */
11
+ export declare function normalizeInboundWorkspaceSubdir(subdir: string): string | null;
12
+ export declare function resolveAgentWorkspaceDirFromRuntime(rt: unknown, cfg: OpenClawConfig): string | undefined;
13
+ export declare function ensureAgentWorkspaceFromRuntime(rt: unknown, cfg: OpenClawConfig): Promise<void>;
14
+ /** `HHmmss` + 三位毫秒,如 `120459237` */
15
+ export declare function formatInboundTimeSuffix(d: Date): string;
16
+ /**
17
+ * 将落盘绝对路径转为 OpenClaw / 沙箱可用的 workspace 相对引用(POSIX 风格,带 `./` 前缀)。
18
+ * 若文件不在 workspaceRoot 之下则返回 null(调用方应回退 file:// 或报错)。
19
+ */
20
+ export declare function absPathToWorkspaceRelativeOpenClawRef(workspaceRoot: string, absPath: string): string | null;
21
+ /**
22
+ * 沙箱内常用挂载点(如 `/workspace`)+ 相对 workspace 的路径,供 read 等工具按「绝对路径」解析。
23
+ * 若未配置 sandboxRootPrefix,则仍用 `./xg_im_inbound/...`(相对当前 cwd,部分沙箱工具会误判为不可访问)。
24
+ */
25
+ export declare function sandboxWorkspaceMediaRef(workspaceRoot: string, absPath: string, sandboxRootPrefix: string): string | null;
26
+ /** `report_120459237.pdf` */
27
+ export declare function buildInboundStoredFilename(originalFilename: string, at: Date): string;
28
+ /**
29
+ * 将入站附件下载到 workspace 下子目录;失败项保留原 URL。
30
+ */
31
+ export declare function saveInboundFilesToWorkspace(args: {
32
+ rt: unknown;
33
+ cfg: OpenClawConfig;
34
+ config: XgImConfig;
35
+ workspaceSubdir: string;
36
+ senderUserId: string | undefined;
37
+ fileItems: MsgFileVO[];
38
+ log?: Log;
39
+ }): Promise<MsgFileVO[]>;
40
+ //# sourceMappingURL=inbound-media-local.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inbound-media-local.d.ts","sourceRoot":"","sources":["../../src/inbound-media-local.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAErC,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAExD,2BAA2B;AAC3B,wBAAgB,+BAA+B,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAS7E;AAED,wBAAgB,mCAAmC,CAAC,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE,cAAc,GAAG,MAAM,GAAG,SAAS,CAWxG;AAED,wBAAsB,+BAA+B,CAAC,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CASrG;AAgBD,oCAAoC;AACpC,wBAAgB,uBAAuB,CAAC,CAAC,EAAE,IAAI,GAAG,MAAM,CAMvD;AAcD;;;GAGG;AACH,wBAAgB,qCAAqC,CAAC,aAAa,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAQ3G;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CACpC,aAAa,EAAE,MAAM,EACrB,OAAO,EAAE,MAAM,EACf,iBAAiB,EAAE,MAAM,GAC1B,MAAM,GAAG,IAAI,CAMf;AA2BD,6BAA6B;AAC7B,wBAAgB,0BAA0B,CAAC,gBAAgB,EAAE,MAAM,EAAE,EAAE,EAAE,IAAI,GAAG,MAAM,CAMrF;AAED;;GAEG;AACH,wBAAsB,2BAA2B,CAAC,IAAI,EAAE;IACpD,EAAE,EAAE,OAAO,CAAC;IACZ,GAAG,EAAE,cAAc,CAAC;IACpB,MAAM,EAAE,UAAU,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,SAAS,EAAE,SAAS,EAAE,CAAC;IACvB,GAAG,CAAC,EAAE,GAAG,CAAC;CACb,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,CAsEvB"}