@aigne/afs-wecom 1.11.0-beta.12

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/dist/index.cjs ADDED
@@ -0,0 +1,286 @@
1
+ const require_client = require('./client.cjs');
2
+ const require_decorate = require('./_virtual/_@oxc-project_runtime@0.108.0/helpers/decorate.cjs');
3
+ let _aigne_afs_provider = require("@aigne/afs/provider");
4
+ let _aigne_afs_messaging = require("@aigne/afs-messaging");
5
+
6
+ //#region src/index.ts
7
+ var AFSWeCom = class extends _aigne_afs_messaging.BaseMessageProvider {
8
+ static manifest() {
9
+ return {
10
+ name: "wecom",
11
+ description: "WeChat Work (企业微信) messaging — webhook or bot API with auto token refresh.\n- Webhook mode for simple group notifications\n- Bot mode with corp credentials for bidirectional messaging\n- Path: /:bot/conversations/:convId/messages/:msgId",
12
+ uriTemplate: "wecom://{corpId}",
13
+ category: "messaging",
14
+ schema: {
15
+ type: "object",
16
+ properties: {
17
+ corpId: {
18
+ type: "string",
19
+ description: "WeChat Work Corp ID"
20
+ },
21
+ corpSecret: {
22
+ type: "string",
23
+ description: "WeChat Work Corp Secret",
24
+ sensitive: true
25
+ },
26
+ agentId: {
27
+ type: "string",
28
+ description: "Agent ID for bot mode"
29
+ },
30
+ webhook: {
31
+ type: "string",
32
+ description: "Webhook key for outbound-only mode",
33
+ sensitive: true
34
+ }
35
+ }
36
+ },
37
+ tags: [
38
+ "wecom",
39
+ "wechat-work",
40
+ "messaging",
41
+ "chat",
42
+ "enterprise"
43
+ ],
44
+ capabilityTags: [
45
+ "read-write",
46
+ "crud",
47
+ "search",
48
+ "auth:token",
49
+ "remote",
50
+ "http",
51
+ "real-time",
52
+ "rate-limited"
53
+ ],
54
+ security: {
55
+ riskLevel: "external",
56
+ resourceAccess: ["internet"],
57
+ notes: ["Connects to WeChat Work API — requires corp credentials or webhook key"]
58
+ },
59
+ capabilities: { network: {
60
+ egress: true,
61
+ allowedDomains: ["qyapi.weixin.qq.com"]
62
+ } }
63
+ };
64
+ }
65
+ static treeSchema() {
66
+ return {
67
+ operations: [
68
+ "list",
69
+ "read",
70
+ "exec",
71
+ "stat",
72
+ "explain"
73
+ ],
74
+ tree: {
75
+ "/": {
76
+ kind: "messaging:root",
77
+ operations: ["list", "exec"],
78
+ actions: [
79
+ "add-bot",
80
+ "remove-bot",
81
+ "process-event"
82
+ ]
83
+ },
84
+ "/{bot}": {
85
+ kind: "messaging:bot",
86
+ operations: ["list", "read"]
87
+ },
88
+ "/{bot}/ctl": {
89
+ kind: "messaging:status",
90
+ operations: ["read"]
91
+ },
92
+ "/{bot}/conversations": {
93
+ kind: "messaging:conversations",
94
+ operations: ["list"]
95
+ },
96
+ "/{bot}/conversations/{convId}": {
97
+ kind: "messaging:conversation",
98
+ operations: ["list"]
99
+ },
100
+ "/{bot}/conversations/{convId}/messages": {
101
+ kind: "messaging:messages",
102
+ operations: ["list", "exec"],
103
+ actions: ["send"]
104
+ },
105
+ "/{bot}/conversations/{convId}/messages/{msgId}": {
106
+ kind: "messaging:message",
107
+ operations: ["read"]
108
+ }
109
+ },
110
+ auth: {
111
+ type: "custom",
112
+ env: ["WECOM_CORP_ID", "WECOM_CORP_SECRET"]
113
+ },
114
+ bestFor: [
115
+ "enterprise messaging",
116
+ "workflow alerts",
117
+ "team notifications"
118
+ ],
119
+ notFor: ["file storage", "database queries"]
120
+ };
121
+ }
122
+ providerName = "wecom";
123
+ eventPrefix = "wecom";
124
+ constructor(options) {
125
+ let bots;
126
+ if (options.bots) bots = options.bots;
127
+ else {
128
+ if (!options.webhook && !options.corpId) throw new Error("AFSWeCom requires either webhook or corpId");
129
+ bots = [{
130
+ name: "default",
131
+ webhook: options.webhook,
132
+ corpId: options.corpId,
133
+ corpSecret: options.corpSecret,
134
+ agentId: options.agentId,
135
+ conversations: options.conversations ?? [],
136
+ apiBase: options.apiBase
137
+ }];
138
+ }
139
+ super({
140
+ bots,
141
+ bufferSize: options.bufferSize
142
+ });
143
+ }
144
+ getMessageCapabilities() {
145
+ return {
146
+ formats: {
147
+ send: ["text"],
148
+ receive: ["text"]
149
+ },
150
+ maxMessageLength: 2048,
151
+ features: {
152
+ edit: false,
153
+ delete: false,
154
+ reply: false,
155
+ thread: false,
156
+ reaction: false,
157
+ inlineKeyboard: false
158
+ },
159
+ limits: { messagesPerSecond: 5 }
160
+ };
161
+ }
162
+ createBotClient(config) {
163
+ const webhook = config.webhook;
164
+ const corpId = config.corpId;
165
+ const corpSecret = config.corpSecret;
166
+ const agentId = config.agentId;
167
+ const apiBase = config.apiBase;
168
+ if (corpId && corpSecret && agentId) return require_client.WeComClient.bot({
169
+ corpId,
170
+ corpSecret,
171
+ agentId,
172
+ apiBase
173
+ });
174
+ if (webhook) return require_client.WeComClient.webhook(webhook, { apiBase });
175
+ throw new Error(`WeCom bot "${config.name}" requires webhook or corpId+corpSecret+agentId`);
176
+ }
177
+ async sendMessage(client, convId, text, _opts) {
178
+ const wc = client;
179
+ if (wc.mode === "bot") return { messageId: (await wc.sendMessage(convId, text)).msgId };
180
+ await wc.sendWebhook(text);
181
+ return { messageId: String(Date.now()) };
182
+ }
183
+ async sendTypingIndicator(_client, _convId) {}
184
+ normalizeMessage(raw) {
185
+ const msg = raw;
186
+ return {
187
+ id: String(msg.MsgId ?? msg.msgId ?? "0"),
188
+ text: String(msg.Content ?? msg.content ?? ""),
189
+ from: this.normalizeSender({ id: msg.FromUserName ?? msg.fromUser }),
190
+ timestamp: Number(msg.CreateTime ?? msg.createTime ?? Math.floor(Date.now() / 1e3)),
191
+ conversationId: String(msg.conversationId ?? ""),
192
+ platform: { agentId: msg.AgentID ?? msg.agentId }
193
+ };
194
+ }
195
+ normalizeSender(raw) {
196
+ return {
197
+ id: String(raw.id ?? "0"),
198
+ name: String(raw.name ?? raw.id ?? ""),
199
+ isBot: raw.isBot
200
+ };
201
+ }
202
+ async listRootActions(_ctx) {
203
+ return { data: [
204
+ this.buildEntry("/.actions/add-bot", { meta: { description: "Add a bot instance at runtime" } }),
205
+ this.buildEntry("/.actions/remove-bot", { meta: { description: "Remove a bot instance" } }),
206
+ this.buildEntry("/.actions/process-event", { meta: { description: "Process an incoming WeCom callback event" } })
207
+ ] };
208
+ }
209
+ async execProcessEvent(_ctx, args) {
210
+ this._processEvent(args);
211
+ return {
212
+ success: true,
213
+ data: { ok: true }
214
+ };
215
+ }
216
+ /** Process a WeCom callback event — delegates to emitMessageReceived(). */
217
+ _processEvent(payload) {
218
+ const parsed = require_client.WeComClient.parseEvent(payload);
219
+ if (!parsed) return;
220
+ const { text, msgId, fromUser, createTime } = parsed;
221
+ const botName = payload.botName ?? this._botOrder[0] ?? "default";
222
+ this.emitMessageReceived(botName, {
223
+ id: msgId,
224
+ text,
225
+ from: {
226
+ id: fromUser,
227
+ name: fromUser
228
+ },
229
+ timestamp: createTime,
230
+ conversationId: String(payload.conversationId ?? payload.ChatId ?? payload.chatId ?? ""),
231
+ platform: { agentId: payload.AgentID ?? payload.agentId }
232
+ });
233
+ }
234
+ /** Add a conversation to a bot. Defaults to first bot. */
235
+ addConversation(convId, botName) {
236
+ const name = botName ?? this._botOrder[0];
237
+ if (!name) return;
238
+ const convs = this._botConversations.get(name);
239
+ if (!convs || convs.has(convId)) return;
240
+ convs.add(convId);
241
+ const buffers = this._botBuffers.get(name);
242
+ if (buffers && !buffers.has(convId)) buffers.set(convId, []);
243
+ }
244
+ /** Remove a conversation from a bot. */
245
+ removeConversation(convId, botName) {
246
+ const name = botName ?? this._botOrder[0];
247
+ if (!name) return;
248
+ const convs = this._botConversations.get(name);
249
+ if (convs) convs.delete(convId);
250
+ const buffers = this._botBuffers.get(name);
251
+ if (buffers) buffers.delete(convId);
252
+ }
253
+ /** Add a message to the ring buffer directly. Public for testing/conformance. */
254
+ _addToBuffer(convId, msg) {
255
+ const botName = this._botOrder[0] ?? "default";
256
+ const convs = this._botConversations.get(botName);
257
+ if (convs && !convs.has(convId)) convs.add(convId);
258
+ let botBuffers = this._botBuffers.get(botName);
259
+ if (!botBuffers) {
260
+ botBuffers = /* @__PURE__ */ new Map();
261
+ this._botBuffers.set(botName, botBuffers);
262
+ }
263
+ let buffer = botBuffers.get(convId);
264
+ if (!buffer) {
265
+ buffer = [];
266
+ botBuffers.set(convId, buffer);
267
+ }
268
+ buffer.push({
269
+ id: msg.msgId,
270
+ text: msg.content,
271
+ from: {
272
+ id: msg.fromUser,
273
+ name: msg.fromUser
274
+ },
275
+ timestamp: msg.createTime ?? Math.floor(Date.now() / 1e3),
276
+ conversationId: convId,
277
+ platform: {}
278
+ });
279
+ while (buffer.length > this._bufferSize) buffer.shift();
280
+ }
281
+ };
282
+ require_decorate.__decorate([(0, _aigne_afs_provider.Actions)("/")], AFSWeCom.prototype, "listRootActions", null);
283
+ require_decorate.__decorate([_aigne_afs_provider.Actions.Exec("/", "process-event")], AFSWeCom.prototype, "execProcessEvent", null);
284
+
285
+ //#endregion
286
+ exports.AFSWeCom = AFSWeCom;
@@ -0,0 +1,104 @@
1
+ import { WeComClient, WeComEvent, WeComParsedEvent } from "./client.cjs";
2
+ import { AFSExecResult, AFSListResult, ProviderTreeSchema } from "@aigne/afs";
3
+ import { RouteContext } from "@aigne/afs/provider";
4
+ import { BaseMessageProvider, BotConfig, BufferedMessage, MessageCapabilities, MessageSender, SendOptions } from "@aigne/afs-messaging";
5
+
6
+ //#region src/index.d.ts
7
+ interface AFSWeComOptions {
8
+ /** Multi-bot config */
9
+ bots?: Array<{
10
+ name: string; /** Webhook key (outbound only) */
11
+ webhook?: string; /** Corp ID for bot mode */
12
+ corpId?: string; /** Corp secret for bot mode */
13
+ corpSecret?: string; /** Agent ID for bot mode */
14
+ agentId?: number;
15
+ conversations?: string[];
16
+ apiBase?: string;
17
+ }>;
18
+ /** Single-bot shorthand: webhook key (outbound only) */
19
+ webhook?: string;
20
+ /** Single-bot shorthand: corp ID */
21
+ corpId?: string;
22
+ /** Single-bot shorthand: corp secret */
23
+ corpSecret?: string;
24
+ /** Single-bot shorthand: agent ID */
25
+ agentId?: number;
26
+ /** Single-bot shorthand: conversation IDs to monitor */
27
+ conversations?: string[];
28
+ apiBase?: string;
29
+ bufferSize?: number;
30
+ }
31
+ declare class AFSWeCom extends BaseMessageProvider {
32
+ static manifest(): {
33
+ name: string;
34
+ description: string;
35
+ uriTemplate: string;
36
+ category: string;
37
+ schema: {
38
+ type: string;
39
+ properties: {
40
+ corpId: {
41
+ type: string;
42
+ description: string;
43
+ };
44
+ corpSecret: {
45
+ type: string;
46
+ description: string;
47
+ sensitive: boolean;
48
+ };
49
+ agentId: {
50
+ type: string;
51
+ description: string;
52
+ };
53
+ webhook: {
54
+ type: string;
55
+ description: string;
56
+ sensitive: boolean;
57
+ };
58
+ };
59
+ };
60
+ tags: string[];
61
+ capabilityTags: string[];
62
+ security: {
63
+ riskLevel: string;
64
+ resourceAccess: string[];
65
+ notes: string[];
66
+ };
67
+ capabilities: {
68
+ network: {
69
+ egress: boolean;
70
+ allowedDomains: string[];
71
+ };
72
+ };
73
+ };
74
+ static treeSchema(): ProviderTreeSchema;
75
+ readonly providerName = "wecom";
76
+ readonly eventPrefix = "wecom";
77
+ constructor(options: AFSWeComOptions);
78
+ getMessageCapabilities(): MessageCapabilities;
79
+ createBotClient(config: BotConfig): WeComClient;
80
+ sendMessage(client: unknown, convId: string, text: string, _opts?: SendOptions): Promise<{
81
+ messageId: string;
82
+ }>;
83
+ sendTypingIndicator(_client: unknown, _convId: string): Promise<void>;
84
+ normalizeMessage(raw: Record<string, unknown>): BufferedMessage;
85
+ normalizeSender(raw: Record<string, unknown>): MessageSender;
86
+ listRootActions(_ctx: RouteContext): Promise<AFSListResult>;
87
+ execProcessEvent(_ctx: RouteContext, args: Record<string, unknown>): Promise<AFSExecResult>;
88
+ /** Process a WeCom callback event — delegates to emitMessageReceived(). */
89
+ _processEvent(payload: any): void;
90
+ /** Add a conversation to a bot. Defaults to first bot. */
91
+ addConversation(convId: string, botName?: string): void;
92
+ /** Remove a conversation from a bot. */
93
+ removeConversation(convId: string, botName?: string): void;
94
+ /** Add a message to the ring buffer directly. Public for testing/conformance. */
95
+ _addToBuffer(convId: string, msg: {
96
+ msgId: string;
97
+ content: string;
98
+ fromUser: string;
99
+ createTime?: number;
100
+ }): void;
101
+ }
102
+ //#endregion
103
+ export { AFSWeCom, AFSWeComOptions, type WeComClient, type WeComEvent, type WeComParsedEvent };
104
+ //# sourceMappingURL=index.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.cts","names":[],"sources":["../src/index.ts"],"mappings":";;;;;;UAoCiB,eAAA;EA6BJ;EA3BX,IAAA,GAAO,KAAA;IACL,IAAA,UAqEmB;IAnEnB,OAAA,WA6HwB;IA3HxB,MAAA,WAgJkC;IA9IlC,UAAA,WAmKC;IAjKD,OAAA;IACA,aAAA;IACA,OAAA;EAAA;EA6L6C;EA1L/C,OAAA;EAqMmD;EAnMnD,MAAA;EAqNQ;EAnNR,UAAA;EAqNW;EAnNX,OAAA;EAO4B;EAL5B,aAAA;EACA,OAAA;EACA,UAAA;AAAA;AAAA,cAGW,QAAA,SAAiB,mBAAA;EAAA,OACrB,QAAA,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;SA0CA,UAAA,CAAA,GAAc,kBAAA;EAAA,SA6BZ,YAAA;EAAA,SACA,WAAA;cAEG,OAAA,EAAS,eAAA;EA0BrB,sBAAA,CAAA,GAA0B,mBAAA;EAqB1B,eAAA,CAAgB,MAAA,EAAQ,SAAA,GAAY,WAAA;EAgB9B,WAAA,CACJ,MAAA,WACA,MAAA,UACA,IAAA,UACA,KAAA,GAAQ,WAAA,GACP,OAAA;IAAU,SAAA;EAAA;EAaP,mBAAA,CAAoB,OAAA,WAAkB,OAAA,WAAkB,OAAA;EAE9D,gBAAA,CAAiB,GAAA,EAAK,MAAA,oBAA0B,eAAA;EAehD,eAAA,CAAgB,GAAA,EAAK,MAAA,oBAA0B,aAAA;EAWzC,eAAA,CAAgB,IAAA,EAAM,YAAA,GAAe,OAAA,CAAQ,aAAA;EAiB7C,gBAAA,CACJ,IAAA,EAAM,YAAA,EACN,IAAA,EAAM,MAAA,oBACL,OAAA,CAAQ,aAAA;EA9CW;EAsDtB,aAAA,CAAc,OAAA;EAtDkC;EA0EhD,eAAA,CAAgB,MAAA,UAAgB,OAAA;EA3DX;EAwErB,kBAAA,CAAmB,MAAA,UAAgB,OAAA;EAxEY;EAkF/C,YAAA,CACE,MAAA,UACA,GAAA;IACE,KAAA;IACA,OAAA;IACA,QAAA;IACA,UAAA;EAAA;AAAA"}
@@ -0,0 +1,104 @@
1
+ import { WeComClient, WeComEvent, WeComParsedEvent } from "./client.mjs";
2
+ import { RouteContext } from "@aigne/afs/provider";
3
+ import { BaseMessageProvider, BotConfig, BufferedMessage, MessageCapabilities, MessageSender, SendOptions } from "@aigne/afs-messaging";
4
+ import { AFSExecResult, AFSListResult, ProviderTreeSchema } from "@aigne/afs";
5
+
6
+ //#region src/index.d.ts
7
+ interface AFSWeComOptions {
8
+ /** Multi-bot config */
9
+ bots?: Array<{
10
+ name: string; /** Webhook key (outbound only) */
11
+ webhook?: string; /** Corp ID for bot mode */
12
+ corpId?: string; /** Corp secret for bot mode */
13
+ corpSecret?: string; /** Agent ID for bot mode */
14
+ agentId?: number;
15
+ conversations?: string[];
16
+ apiBase?: string;
17
+ }>;
18
+ /** Single-bot shorthand: webhook key (outbound only) */
19
+ webhook?: string;
20
+ /** Single-bot shorthand: corp ID */
21
+ corpId?: string;
22
+ /** Single-bot shorthand: corp secret */
23
+ corpSecret?: string;
24
+ /** Single-bot shorthand: agent ID */
25
+ agentId?: number;
26
+ /** Single-bot shorthand: conversation IDs to monitor */
27
+ conversations?: string[];
28
+ apiBase?: string;
29
+ bufferSize?: number;
30
+ }
31
+ declare class AFSWeCom extends BaseMessageProvider {
32
+ static manifest(): {
33
+ name: string;
34
+ description: string;
35
+ uriTemplate: string;
36
+ category: string;
37
+ schema: {
38
+ type: string;
39
+ properties: {
40
+ corpId: {
41
+ type: string;
42
+ description: string;
43
+ };
44
+ corpSecret: {
45
+ type: string;
46
+ description: string;
47
+ sensitive: boolean;
48
+ };
49
+ agentId: {
50
+ type: string;
51
+ description: string;
52
+ };
53
+ webhook: {
54
+ type: string;
55
+ description: string;
56
+ sensitive: boolean;
57
+ };
58
+ };
59
+ };
60
+ tags: string[];
61
+ capabilityTags: string[];
62
+ security: {
63
+ riskLevel: string;
64
+ resourceAccess: string[];
65
+ notes: string[];
66
+ };
67
+ capabilities: {
68
+ network: {
69
+ egress: boolean;
70
+ allowedDomains: string[];
71
+ };
72
+ };
73
+ };
74
+ static treeSchema(): ProviderTreeSchema;
75
+ readonly providerName = "wecom";
76
+ readonly eventPrefix = "wecom";
77
+ constructor(options: AFSWeComOptions);
78
+ getMessageCapabilities(): MessageCapabilities;
79
+ createBotClient(config: BotConfig): WeComClient;
80
+ sendMessage(client: unknown, convId: string, text: string, _opts?: SendOptions): Promise<{
81
+ messageId: string;
82
+ }>;
83
+ sendTypingIndicator(_client: unknown, _convId: string): Promise<void>;
84
+ normalizeMessage(raw: Record<string, unknown>): BufferedMessage;
85
+ normalizeSender(raw: Record<string, unknown>): MessageSender;
86
+ listRootActions(_ctx: RouteContext): Promise<AFSListResult>;
87
+ execProcessEvent(_ctx: RouteContext, args: Record<string, unknown>): Promise<AFSExecResult>;
88
+ /** Process a WeCom callback event — delegates to emitMessageReceived(). */
89
+ _processEvent(payload: any): void;
90
+ /** Add a conversation to a bot. Defaults to first bot. */
91
+ addConversation(convId: string, botName?: string): void;
92
+ /** Remove a conversation from a bot. */
93
+ removeConversation(convId: string, botName?: string): void;
94
+ /** Add a message to the ring buffer directly. Public for testing/conformance. */
95
+ _addToBuffer(convId: string, msg: {
96
+ msgId: string;
97
+ content: string;
98
+ fromUser: string;
99
+ createTime?: number;
100
+ }): void;
101
+ }
102
+ //#endregion
103
+ export { AFSWeCom, AFSWeComOptions, type WeComClient, type WeComEvent, type WeComParsedEvent };
104
+ //# sourceMappingURL=index.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/index.ts"],"mappings":";;;;;;UAoCiB,eAAA;EA6BJ;EA3BX,IAAA,GAAO,KAAA;IACL,IAAA,UAqEmB;IAnEnB,OAAA,WA6HwB;IA3HxB,MAAA,WAgJkC;IA9IlC,UAAA,WAmKC;IAjKD,OAAA;IACA,aAAA;IACA,OAAA;EAAA;EA6L6C;EA1L/C,OAAA;EAqMmD;EAnMnD,MAAA;EAqNQ;EAnNR,UAAA;EAqNW;EAnNX,OAAA;EAO4B;EAL5B,aAAA;EACA,OAAA;EACA,UAAA;AAAA;AAAA,cAGW,QAAA,SAAiB,mBAAA;EAAA,OACrB,QAAA,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;SA0CA,UAAA,CAAA,GAAc,kBAAA;EAAA,SA6BZ,YAAA;EAAA,SACA,WAAA;cAEG,OAAA,EAAS,eAAA;EA0BrB,sBAAA,CAAA,GAA0B,mBAAA;EAqB1B,eAAA,CAAgB,MAAA,EAAQ,SAAA,GAAY,WAAA;EAgB9B,WAAA,CACJ,MAAA,WACA,MAAA,UACA,IAAA,UACA,KAAA,GAAQ,WAAA,GACP,OAAA;IAAU,SAAA;EAAA;EAaP,mBAAA,CAAoB,OAAA,WAAkB,OAAA,WAAkB,OAAA;EAE9D,gBAAA,CAAiB,GAAA,EAAK,MAAA,oBAA0B,eAAA;EAehD,eAAA,CAAgB,GAAA,EAAK,MAAA,oBAA0B,aAAA;EAWzC,eAAA,CAAgB,IAAA,EAAM,YAAA,GAAe,OAAA,CAAQ,aAAA;EAiB7C,gBAAA,CACJ,IAAA,EAAM,YAAA,EACN,IAAA,EAAM,MAAA,oBACL,OAAA,CAAQ,aAAA;EA9CW;EAsDtB,aAAA,CAAc,OAAA;EAtDkC;EA0EhD,eAAA,CAAgB,MAAA,UAAgB,OAAA;EA3DX;EAwErB,kBAAA,CAAmB,MAAA,UAAgB,OAAA;EAxEY;EAkF/C,YAAA,CACE,MAAA,UACA,GAAA;IACE,KAAA;IACA,OAAA;IACA,QAAA;IACA,UAAA;EAAA;AAAA"}