@chinchillaenterprises/mcp-slack 3.1.1 → 4.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.
package/README.md CHANGED
@@ -1,74 +1,91 @@
1
1
  # MCP Slack Server
2
2
 
3
- A powerful multi-account Model Context Protocol (MCP) server for Slack that enables seamless workspace switching and persistent credential storage.
3
+ A Model Context Protocol (MCP) server for Slack. **v4.0.0** loads a single account from environment variables — no encrypted credential store, no keychain, no runtime account switching. To use a second workspace, add a second MCP server entry with its own token (see below).
4
4
 
5
5
  ## Features
6
6
 
7
- - 🔄 **Multi-Account Support**: Switch between multiple Slack workspaces at runtime
8
- - 🔐 **Secure Credential Storage**: Uses native OS keychains with encrypted file-based fallback
9
- - ⚡ **Fast Performance**: <200ms startup time for 10+ workspaces
10
- - 🛡️ **Dual Storage System**: Automatic fallback to encrypted file storage if keychain unavailable
7
+ - 🔑 **Env-first auth**: One Slack account per server, loaded from `SLACK_BOT_TOKEN` at startup — no on-disk credentials
8
+ - 🧩 **Multi-workspace via config**: Run one server entry per workspace (e.g. `slack`, `slack-work`)
11
9
  - 🔍 **Comprehensive Slack Tools**: 40+ tools for messages, channels, users, files, and more
12
10
  - 📸 **File Upload & Diagrams**: Upload files and render HTML/Mermaid diagrams as images directly to Slack
13
- - 📁 **Reliable Persistence**: Accounts persist across Claude sessions
11
+ - 🤝 **Legate coordination**: `slack_poll` / `slack_claim_lane` / `slack_checkin` for multi-session agents
14
12
  - ✨ **Automatic Markdown Conversion**: Converts common markdown formatting to Slack's mrkdwn format
15
13
 
16
- ## Installation
17
-
18
- ### Using Claude Desktop
19
-
20
- ```bash
21
- claude mcp add slack -- npx @chinchillaenterprises/mcp-slack
22
- ```
23
-
24
- ### Using Claude Code (Recommended)
25
-
26
- ```bash
27
- # Install with user scope for persistence across sessions
28
- claude mcp add slack -s user -- npx @chinchillaenterprises/mcp-slack
29
-
30
- # Or with environment variables for default workspace
31
- claude mcp add slack -s user -e DEFAULT_BOT_TOKEN=xoxb-YOUR-BOT-TOKEN -e DEFAULT_TEAM_ID=YOUR-TEAM-ID -- npx @chinchillaenterprises/mcp-slack
14
+ ## Installation & Configuration
15
+
16
+ The server reads its token from the `env` block of its MCP server entry. Add an entry to your Claude config (`~/.claude.json` or a project-local `.mcp.json`):
17
+
18
+ ```jsonc
19
+ {
20
+ "mcpServers": {
21
+ "slack": {
22
+ "command": "npx",
23
+ "args": ["-y", "@chinchillaenterprises/mcp-slack"],
24
+ "env": {
25
+ "SLACK_BOT_TOKEN": "xoxb-YOUR-BOT-TOKEN",
26
+ "SLACK_USER_TOKEN": "xoxp-YOUR-USER-TOKEN" // optional
27
+ }
28
+ }
29
+ }
30
+ }
32
31
  ```
33
32
 
34
- ### Manual Installation
35
-
36
- ```bash
37
- npm install -g @chinchillaenterprises/mcp-slack
33
+ ### Multiple workspaces = multiple server entries
34
+
35
+ There is no in-app account switching. To talk to a second workspace, add a second server entry with its own token. Tools are namespaced by entry, so they stay separate:
36
+
37
+ ```jsonc
38
+ {
39
+ "mcpServers": {
40
+ "slack": {
41
+ "command": "npx",
42
+ "args": ["-y", "@chinchillaenterprises/mcp-slack"],
43
+ "env": { "SLACK_BOT_TOKEN": "xoxb-PERSONAL-WORKSPACE-TOKEN" }
44
+ },
45
+ "slack-work": {
46
+ "command": "npx",
47
+ "args": ["-y", "@chinchillaenterprises/mcp-slack"],
48
+ "env": { "SLACK_BOT_TOKEN": "xoxb-WORK-WORKSPACE-TOKEN" }
49
+ }
50
+ }
51
+ }
38
52
  ```
39
53
 
40
- ## Configuration
41
-
42
54
  ### Environment Variables
43
55
 
44
- For the default workspace:
45
- - `DEFAULT_BOT_TOKEN`: Slack bot token (xoxb-...)
46
- - `DEFAULT_USER_TOKEN`: Slack user token (xoxp-...)
47
- - `DEFAULT_TEAM_ID`: Slack team/workspace ID
48
- - `DEFAULT_ACCOUNT_NAME`: Display name for the workspace
56
+ | Variable | Required | Description |
57
+ |----------|----------|-------------|
58
+ | `SLACK_BOT_TOKEN` | **yes** | Slack bot token (`xoxb-…`). Falls back to `DEFAULT_BOT_TOKEN` for back-compat. |
59
+ | `SLACK_USER_TOKEN` | no | Slack user token (`xoxp-…`) for user-scoped operations. Falls back to `DEFAULT_USER_TOKEN`. |
60
+ | `SLACK_TEAM_ID` | no | Team/workspace ID. Auto-discovered via `auth.test` on first use if omitted. Falls back to `DEFAULT_TEAM_ID`. |
61
+ | `SLACK_WORKSPACE` | no | Display name for the workspace. Falls back to `DEFAULT_ACCOUNT_NAME`. |
49
62
 
50
- ## Usage
63
+ If `SLACK_BOT_TOKEN` (or `DEFAULT_BOT_TOKEN`) is absent, the server still boots — but every tool call returns a clear error telling you to set `SLACK_BOT_TOKEN`.
51
64
 
52
- ### Account Management
65
+ ## Usage
53
66
 
54
- The V3 architecture introduces powerful account management capabilities:
67
+ ### Account Tools (read-only)
55
68
 
56
- - **list_accounts**: View all configured workspaces
57
- - **switch_account**: Change active workspace at runtime
58
- - **add_account**: Add new workspace credentials
59
- - **remove_account**: Remove workspace from configuration
60
- - **update_account**: Update existing workspace credentials
69
+ - **get_active_account**: Show which workspace this server is wired to (name, team ID — no secrets)
70
+ - **list_accounts**: List the single active account (kept for back-compat)
61
71
 
62
72
  ### Core Slack Tools
63
73
 
64
74
  #### Messaging
65
75
  - `slack_send_message`: Send messages to channels (with automatic markdown → Slack formatting)
66
76
  - `slack_send_formatted_message`: Send rich Block Kit messages
77
+ - `slack_send_card`: Post a polished Block Kit card (header, section blocks with two-column fields, context footer, optional color bar)
78
+ - `slack_send_table`: Post a column-aligned ASCII table inside a code block (lightweight text alternative to `slack_send_diagram`)
67
79
  - `slack_edit_message`: Edit existing messages
68
80
  - `slack_delete_message`: Delete messages
69
81
  - `slack_schedule_message`: Schedule messages for later
70
82
  - `slack_forward_message`: Forward messages between channels
71
83
 
84
+ #### Task Lifecycle (threaded, single-thread progress)
85
+ - `slack_start_task`: Post a parent `⏳ <title>` card (adds a ⏳ status reaction); returns `{ task_ts, channel }`
86
+ - `slack_update_task`: Post a threaded progress reply; with `step`/`total_steps` updates the parent's progress bar (no @-mentions)
87
+ - `slack_complete_task`: Final threaded reply + edits the parent into a ✅/❌ summary card, swaps the ⏳ reaction; the only task tool that may `@`-mention (`notify_user`)
88
+
72
89
  #### Channels & History
73
90
  - `slack_list_channels`: List accessible channels
74
91
  - `slack_get_channel_history`: Get recent messages
@@ -114,66 +131,80 @@ The `slack_send_message` tool now automatically converts common markdown formatt
114
131
 
115
132
  This means Claude can use standard markdown formatting and it will appear correctly in Slack without manual conversion.
116
133
 
117
- ## Advanced Features
134
+ ## Session UX
135
+
136
+ These features keep agent-driven Slack usage cheap (in context tokens) and tidy.
137
+
138
+ ### Lean tool outputs (`verbose` flag)
139
+
140
+ The chatty read tools — `slack_get_channel_history`, `slack_list_users`, `slack_list_channels`, `slack_search_messages`, `slack_search_by_user`, `slack_search_by_date_range`, and `slack_get_workspace_stats` — return **lean output by default**. Lean output:
141
+
142
+ - Drops pretty-print whitespace and metadata exhaust (profile image URLs, team/bot IDs, edited markers, reaction blobs, full Block Kit JSON).
143
+ - **Preserves message body text verbatim** — content is never clipped or summarized.
144
+ - Caps how many *items* are returned and appends a footer like `(showing 25 of 340 — pass verbose:true or a higher limit/cursor for the rest)` so nothing is silently dropped.
145
+
146
+ Pass `verbose: true` on any of these tools to get the **full raw API payload** — the firehose is always one call away. Lean results are the main lever against the largest single source of session token cost (verbose results lingering in the context window).
147
+
148
+ ### ASCII tables vs. PNG tables
118
149
 
119
- ### Persistent Storage
150
+ - `slack_send_table` renders a column-aligned monospace table inside a code block. Cheap (it's text), good for status grids and comparison matrices. Accepts an array of objects, a 2D array (first row = header), or a markdown pipe-table string.
151
+ - `slack_send_diagram` renders an HTML `<table>` as a PNG image — use it when you want a polished, presentation-grade table.
120
152
 
121
- The server uses a dual-storage system for maximum reliability:
153
+ ### Threaded task lifecycle
122
154
 
123
- 1. **Primary Storage**: Native OS keychain
124
- - **macOS**: Keychain Access
125
- - **Windows**: Credential Manager
126
- - **Linux**: Secret Service API
155
+ Use `slack_start_task` → `slack_update_task` → `slack_complete_task` to run a long task in **one thread** instead of spamming a channel. The parent card shows a live progress bar and a ⏳ → ✅/❌ status reaction. Only `slack_complete_task` may `@`-mention the user (via `notify_user`); routine updates stay quiet.
156
+
157
+ ### Session identity (`chat:write.customize`)
158
+
159
+ The message-posting tools (`slack_send_message`, `slack_send_formatted_message`, `slack_send_card`, and the task tools) accept optional `username`, `icon_emoji`, and `icon_url` params so a session can post under a consistent identity like `Claude · ChillMCP`. Defaults can be set once via environment variables:
160
+
161
+ - `SLACK_SESSION_USERNAME`: default display name for posted messages
162
+ - `SLACK_SESSION_ICON`: default icon — either a `:emoji:` name or an image URL
163
+
164
+ > **Scope required:** username/icon overrides require the **`chat:write.customize`** bot scope. If the scope is missing, Slack ignores the override and the message still posts under the app's default identity (degrades gracefully).
165
+
166
+ ## Advanced Features
127
167
 
128
- 2. **Fallback Storage**: Encrypted file storage
129
- - Location: `~/.mcp-slack/accounts.json`
130
- - Credentials encrypted using AES-256-CBC
131
- - Automatic failover if keychain unavailable
132
- - Permissions restricted to user only (0600)
168
+ ### Credentials (env-only)
133
169
 
134
- ### Data Security
170
+ There is **no on-disk credential store** — no keychain, no `accounts.json`, no encryption keys. The bot/user tokens live only in the `env` block of the MCP server entry and in process memory for the lifetime of the server. Rotating a token is just editing the config and restarting the server.
135
171
 
136
- - Bot tokens and user tokens are encrypted at rest
137
- - Encryption key stored separately with restricted permissions
138
- - No plaintext credentials on disk
139
- - Automatic cleanup of stale sessions
172
+ The only file the server writes is **Legate poll state** (`~/.mcp-slack/legate-state/<call_sign>.json`) poll cursors and check-in status for the multi-session coordination tools. That is not credentials.
140
173
 
141
174
  ### Performance Optimizations
142
175
 
143
- - Lazy loading of workspace configurations
144
- - Efficient caching of API responses
176
+ - Efficient 120s TTL caching of `users.list` / `conversations.list`
177
+ - Lazy workspace-info hydration (`auth.test` on first use)
145
178
  - Minimal startup overhead
146
179
 
147
180
  ## Architecture
148
181
 
149
- MCP Slack Server implements the Account Manager Tools Pattern with dual storage:
182
+ Single account, loaded from env. Multi-workspace is achieved by running multiple server entries:
150
183
 
151
184
  ```
152
- ┌─────────────┐ ┌──────────────┐ ┌─────────────┐
153
- │ Claude │────▶│ MCP Server │────▶│ Slack
154
- Desktop │ │ │ Workspaces │
155
- └─────────────┘ └──────────────┘ └─────────────┘
156
-
157
- ┌───────┴───────┐
158
- ▼ ▼
159
- ┌──────────────┐ ┌──────────────┐
160
- │ OS Keychain │ │ Encrypted │
161
- │ Storage │ │ File Storage │
162
- └──────────────┘ └──────────────┘
163
- Primary Fallback
185
+ ┌─────────────┐ ┌──────────────────┐ ┌─────────────┐
186
+ │ Claude │────▶│ slack (server) │────▶│ Workspace A
187
+ │ │ SLACK_BOT_TOKEN └─────────────┘
188
+ │ │ └──────────────────┘
189
+ │ ┌──────────────────┐ ┌─────────────┐
190
+ │ │────▶│ slack-work │────▶│ Workspace B │
191
+ │ │ │ SLACK_BOT_TOKEN │ └─────────────┘
192
+ └─────────────┘ └──────────────────┘
164
193
  ```
165
194
 
166
195
  ## Troubleshooting
167
196
 
168
- ### "Secure storage unavailable"
169
- This warning appears when keychain access is denied or unavailable. The server will continue working with temporary storage.
197
+ ### "No Slack bot token. Set SLACK_BOT_TOKEN…"
198
+ The server booted without a token. Add `SLACK_BOT_TOKEN` to the `env` block of this server's entry in `~/.claude.json` (or `.mcp.json`) and restart.
170
199
 
171
200
  ### Missing channels or users
172
201
  Ensure your bot token has the necessary OAuth scopes:
173
202
  - `channels:read`
174
203
  - `chat:write`
204
+ - `chat:write.customize` (only needed for the `username` / `icon_emoji` / `icon_url` session-identity overrides)
175
205
  - `users:read`
176
206
  - `files:read`
207
+ - `reactions:write` (for the task-lifecycle status reactions)
177
208
 
178
209
  ### Performance issues
179
210
  - Check network connectivity to Slack
@@ -217,7 +248,7 @@ npm install playwright
217
248
  The existing `slack_send_formatted_message` tool should be enhanced to support Block Kit layouts for richer Slack messages (headers, sections, dividers, context blocks).
218
249
 
219
250
  ### Why These Matter
220
- The ForgeClaw project (Chinchilla AI's agent platform) uses AI agent teams that dynamically restructure per project phase. Before each phase, the team posts their formation diagram to Slack. Currently limited to ASCII art in code blocks. These tools enable posting actual rendered diagrams as images — much more professional and readable.
251
+ The Echelon project (Chinchilla AI's agent platform) uses AI agent teams that dynamically restructure per project phase. Before each phase, the team posts their formation diagram to Slack. Currently limited to ASCII art in code blocks. These tools enable posting actual rendered diagrams as images — much more professional and readable.
221
252
 
222
253
  ## License
223
254
 
package/dist/index.d.ts CHANGED
@@ -1,3 +1,157 @@
1
1
  #!/usr/bin/env node
2
+ /**
3
+ * Compact result formatter. Default (lean) form is single-line / minimal — NO
4
+ * pretty-print — so it doesn't bloat the context window. Pass { verbose: true } for
5
+ * the fuller, indented form when a human actually needs to read every field.
6
+ *
7
+ * Accepts an already-prepared `data` value. Callers are expected to have already
8
+ * trimmed to the fields that matter for the lean case (see the READ tools), but this
9
+ * function is also safe to hand a full object for the verbose path.
10
+ */
11
+ export declare function leanResult(data: unknown, opts?: {
12
+ verbose?: boolean;
13
+ }): string;
14
+ export declare function isFlatObject(v: unknown): v is Record<string, unknown>;
15
+ interface RenderTableColumn {
16
+ key: string;
17
+ label?: string;
18
+ align?: "left" | "right";
19
+ maxWidth?: number;
20
+ }
21
+ /**
22
+ * Render tabular data as a clean, column-aligned monospace ASCII table using
23
+ * box-drawing characters. The output is meant to be dropped inside a Slack code
24
+ * block (```) so it renders with a fixed-width font and column alignment survives.
25
+ *
26
+ * Accepts any of:
27
+ * - array of flat objects → columns inferred from keys (or pass `columns`)
28
+ * - 2D array (string[][]) → first row treated as header
29
+ * - a markdown table string (| a | b |\n|---|---|\n| 1 | 2 |)
30
+ *
31
+ * Long cells are truncated with an ellipsis past a per-column max width (default 40).
32
+ * Numeric-looking columns are right-aligned automatically unless overridden.
33
+ */
34
+ export declare function renderTable(rows: Record<string, unknown>[] | unknown[][] | string, columns?: RenderTableColumn[]): string;
35
+ export declare function cellToString(v: unknown): string;
36
+ export declare function parseMarkdownTable(md: string): {
37
+ headers: string[];
38
+ body: string[][];
39
+ };
40
+ /**
41
+ * Render a unicode progress bar, e.g. renderProgressBar(40) => "▰▰▰▰▱▱▱▱▱▱ 40%".
42
+ */
43
+ export declare function renderProgressBar(pct: number, width?: number): string;
44
+ interface CardSection {
45
+ text?: string;
46
+ fields?: {
47
+ label?: string;
48
+ value: string;
49
+ }[];
50
+ }
51
+ interface BuildCardOpts {
52
+ header: string;
53
+ sections?: CardSection[];
54
+ context?: string;
55
+ color?: string;
56
+ }
57
+ /**
58
+ * Build a Slack Block Kit blocks[] array: a header block, section blocks (each with
59
+ * optional two-column fields), dividers between sections, and an optional context
60
+ * footer. Used by slack_send_card and the task-lifecycle summary cards.
61
+ *
62
+ * Returns { blocks } always, plus { attachments } when a color bar is requested
63
+ * (Slack only supports the colored left-bar via the legacy attachments wrapper).
64
+ */
65
+ export declare function buildCard(opts: BuildCardOpts): {
66
+ blocks: any[];
67
+ attachments?: any[];
68
+ };
69
+ export declare function truncatePlain(s: string, max: number): string;
70
+ export declare class SlackerV3Server {
71
+ private server;
72
+ private accountState;
73
+ private readonly CACHE_TTL_MS;
74
+ private usersCache;
75
+ private channelsCache;
76
+ private taskRegistry;
77
+ private browser;
78
+ private browserIdleTimer;
79
+ private readonly BROWSER_IDLE_MS;
80
+ private static readonly NO_TOKEN_MESSAGE;
81
+ constructor();
82
+ private loadAccountFromEnv;
83
+ private getActiveClient;
84
+ private getActiveUserClient;
85
+ private ensureWorkspaceInfo;
86
+ private currentAccountKey;
87
+ private getAllUsersCached;
88
+ private getAllChannelsCached;
89
+ private describeActiveAccount;
90
+ private getActiveAccount;
91
+ private listAccounts;
92
+ private slackListChannels;
93
+ private convertMarkdownToSlackMrkdwn;
94
+ private processExplicitMentions;
95
+ private resolveRecipient;
96
+ private slackSendMessage;
97
+ private slackSendTable;
98
+ private taskKey;
99
+ private identityOverrides;
100
+ private swapReaction;
101
+ private slackSendCard;
102
+ private slackStartTask;
103
+ private slackUpdateTask;
104
+ private slackCompleteTask;
105
+ private static readonly NATO_CALL_SIGNS;
106
+ private legateStateDir;
107
+ private sanitizeCallSign;
108
+ private loadLegateState;
109
+ private saveLegateState;
110
+ private tsGreater;
111
+ private mentionsToken;
112
+ private classifyAddressing;
113
+ private looksSelfAuthored;
114
+ private slackPoll;
115
+ private laneKey;
116
+ private parseLaneClaim;
117
+ private slackClaimLane;
118
+ private slackCheckin;
119
+ private slackGetChannelHistory;
120
+ private moreFooter;
121
+ private slackAddReaction;
122
+ private slackListUsers;
123
+ private slackGetUserByName;
124
+ private slackGetUserInfo;
125
+ private slackSearchFiles;
126
+ private slackSearchMessages;
127
+ private searchFooter;
128
+ private slackSearchByUser;
129
+ private slackSearchByDateRange;
130
+ private slackPinMessage;
131
+ private slackUnpinMessage;
132
+ private slackDeleteMessage;
133
+ private slackEditMessage;
134
+ private slackScheduleMessage;
135
+ private slackGetUserStatus;
136
+ private slackGetUserProfile;
137
+ private slackCreateReminder;
138
+ private slackListReminders;
139
+ private slackGetCustomEmoji;
140
+ private slackSendFormattedMessage;
141
+ private slackAuditUserActivity;
142
+ private slackBulkReactMessages;
143
+ private slackForwardMessage;
144
+ private slackBulkForwardMessages;
145
+ private slackGetThreadReplies;
146
+ private slackGetWorkspaceStats;
147
+ private slackUploadFile;
148
+ private slackSendDiagram;
149
+ private getBrowser;
150
+ private scheduleBrowserIdleClose;
151
+ private closeBrowser;
152
+ private renderHtmlToPng;
153
+ private setupHandlers;
154
+ run(): Promise<void>;
155
+ }
2
156
  export {};
3
157
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAoCA;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,GAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAO,GAAG,MAAM,CAWlF;AAGD,wBAAgB,YAAY,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAKrE;AAED,UAAU,iBAAiB;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,WAAW,CACzB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,OAAO,EAAE,EAAE,GAAG,MAAM,EACtD,OAAO,CAAC,EAAE,iBAAiB,EAAE,GAC5B,MAAM,CA6ER;AAED,wBAAgB,YAAY,CAAC,CAAC,EAAE,OAAO,GAAG,MAAM,CAI/C;AAGD,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,MAAM,GAAG;IAAE,OAAO,EAAE,MAAM,EAAE,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,EAAE,CAAA;CAAE,CAmBtF;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,SAAK,GAAG,MAAM,CAKjE;AAED,UAAU,WAAW;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAC9C;AAED,UAAU,aAAa;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,WAAW,EAAE,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;GAOG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,aAAa,GAAG;IAAE,MAAM,EAAE,GAAG,EAAE,CAAC;IAAC,WAAW,CAAC,EAAE,GAAG,EAAE,CAAA;CAAE,CAqCrF;AAED,wBAAgB,aAAa,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAE5D;AAmTD,qBAAa,eAAe;IAC1B,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,YAAY,CAAe;IAGnC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAW;IACxC,OAAO,CAAC,UAAU,CAA6C;IAC/D,OAAO,CAAC,aAAa,CAA6C;IAKlE,OAAO,CAAC,YAAY,CAKL;IAGf,OAAO,CAAC,OAAO,CAAa;IAC5B,OAAO,CAAC,gBAAgB,CAA+B;IACvD,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAiB;IAGjD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,gBAAgB,CAES;;IAoCjD,OAAO,CAAC,kBAAkB;YA8BZ,eAAe;YAOf,mBAAmB;YAUnB,mBAAmB;IAmBjC,OAAO,CAAC,iBAAiB;YAKX,iBAAiB;YAqBjB,oBAAoB;YA6BpB,qBAAqB;YAerB,gBAAgB;YAkBhB,YAAY;YAiBZ,iBAAiB;IAgF/B,OAAO,CAAC,4BAA4B;YAsBtB,uBAAuB;YAiCvB,gBAAgB;YAwEhB,gBAAgB;YAmChB,cAAc;IAgC5B,OAAO,CAAC,OAAO;IAQf,OAAO,CAAC,iBAAiB;YAqBX,YAAY;YAWZ,aAAa;YA2Bb,cAAc;YA2Cd,eAAe;YA4Cf,iBAAiB;IA0E/B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,eAAe,CAKrC;IAEF,OAAO,CAAC,cAAc;IAKtB,OAAO,CAAC,gBAAgB;YAOV,eAAe;YAcf,eAAe;IAU7B,OAAO,CAAC,SAAS;IAMjB,OAAO,CAAC,aAAa;IAQrB,OAAO,CAAC,kBAAkB;IAuC1B,OAAO,CAAC,iBAAiB;YAcX,SAAS;IAmFvB,OAAO,CAAC,OAAO;IASf,OAAO,CAAC,cAAc;YAMR,cAAc;YA6Ed,YAAY;YAgCZ,sBAAsB;IA0CpC,OAAO,CAAC,UAAU;YAOJ,gBAAgB;YAoBhB,cAAc;YA4Cd,kBAAkB;YAmElB,gBAAgB;YAqChB,gBAAgB;YAqChB,mBAAmB;IAwCjC,OAAO,CAAC,YAAY;YAON,iBAAiB;YAwCjB,sBAAsB;YA0CtB,eAAe;YAmBf,iBAAiB;YAmBjB,kBAAkB;YAmBlB,gBAAgB;YAoBhB,oBAAoB;YAoBpB,kBAAkB;YA2BlB,mBAAmB;YAkBnB,mBAAmB;YAwBnB,kBAAkB;YAuBlB,mBAAmB;YAenB,yBAAyB;YAqBzB,sBAAsB;YAiCtB,sBAAsB;YAkCtB,mBAAmB;YAkDnB,wBAAwB;YA8ExB,qBAAqB;YAqCrB,sBAAsB;YA2CtB,eAAe;YAqDf,gBAAgB;YAgEhB,UAAU;IAkBxB,OAAO,CAAC,wBAAwB;YASlB,YAAY;YAgBZ,eAAe;IA2G7B,OAAO,CAAC,aAAa;IAu6Bf,GAAG;CAcV"}