@zhixuan92/multi-model-agent-mcp 0.4.0 → 1.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 (34) hide show
  1. package/README.md +18 -220
  2. package/dist/cli.d.ts +20 -22
  3. package/dist/cli.d.ts.map +1 -1
  4. package/dist/cli.js +183 -154
  5. package/dist/cli.js.map +1 -1
  6. package/dist/routing/render-provider-routing-matrix.d.ts +1 -1
  7. package/dist/routing/render-provider-routing-matrix.d.ts.map +1 -1
  8. package/dist/routing/render-provider-routing-matrix.js +38 -67
  9. package/dist/routing/render-provider-routing-matrix.js.map +1 -1
  10. package/dist/tools/audit-document.d.ts +37 -0
  11. package/dist/tools/audit-document.d.ts.map +1 -0
  12. package/dist/tools/audit-document.js +76 -0
  13. package/dist/tools/audit-document.js.map +1 -0
  14. package/dist/tools/batch-response.d.ts +21 -0
  15. package/dist/tools/batch-response.d.ts.map +1 -0
  16. package/dist/tools/batch-response.js +78 -0
  17. package/dist/tools/batch-response.js.map +1 -0
  18. package/dist/tools/debug-task.d.ts +23 -0
  19. package/dist/tools/debug-task.d.ts.map +1 -0
  20. package/dist/tools/debug-task.js +38 -0
  21. package/dist/tools/debug-task.js.map +1 -0
  22. package/dist/tools/review-code.d.ts +31 -0
  23. package/dist/tools/review-code.d.ts.map +1 -0
  24. package/dist/tools/review-code.js +65 -0
  25. package/dist/tools/review-code.js.map +1 -0
  26. package/dist/tools/shared.d.ts +31 -0
  27. package/dist/tools/shared.d.ts.map +1 -0
  28. package/dist/tools/shared.js +72 -0
  29. package/dist/tools/shared.js.map +1 -0
  30. package/dist/tools/verify-work.d.ts +22 -0
  31. package/dist/tools/verify-work.d.ts.map +1 -0
  32. package/dist/tools/verify-work.js +57 -0
  33. package/dist/tools/verify-work.js.map +1 -0
  34. package/package.json +19 -3
package/README.md CHANGED
@@ -1,238 +1,36 @@
1
1
  # @zhixuan92/multi-model-agent-mcp
2
2
 
3
- **Delegate work from your expensive parent-session model to a fleet of cheaper sub-agents, in parallel, from a single MCP tool call.**
3
+ **MCP server for multi-model-agent.** Your AI assistant gets 8 tools for delegating work to cheaper agents parallel execution, cross-agent review, 90% cost savings.
4
4
 
5
- This is the MCP stdio server for [`multi-model-agent`](https://github.com/zhixuan312/multi-model-agent). Your MCP client (Claude Code, Claude Desktop, Codex CLI, Cursor, …) spawns it on demand and gets six tools: `delegate_tasks`, `register_context_block`, `retry_tasks`, `get_task_output`, `get_task_detail`, and `get_batch_telemetry`. Each `delegate_tasks` call runs the supplied tasks in parallel across the providers you configured, auto-routing each to the cheapest one that has the required capabilities and quality tier — or pinning to a specific provider when you want control. Every response envelope carries a pre-computed `headline` field so the calling agent can narrate the ROI story in one line without any arithmetic.
5
+ Works with Claude Code, Codex CLI, Cursor, Gemini CLI, and Claude Desktop.
6
6
 
7
- ## Why use it
8
-
9
- - **Cut cost and context.** Mechanical work (file edits, search, doc lookups) runs on cheap providers in a clean worker context. Your parent session's window stays lean and its judgment unblocked.
10
- - **Run tasks in parallel.** Independent tasks in one call execute concurrently; wall-clock time drops with task count.
11
- - **Mix providers in one config.** Claude, Codex, and any OpenAI-compatible endpoint (MiniMax, DeepSeek, Groq, local vLLM, …) live side-by-side.
12
- - **Auto-route and escalate.** Capability filter → tier filter → cheapest qualifying provider; on failure the chain is walked automatically, stopping at the first success.
13
- - **No bare failures.** Every termination path (incomplete, max_turns, timeout, error) populates `output` from the runner's scratchpad.
14
- - **Sandboxed by default.** `cwd-only` file tool confinement and shell-disabled by default. Opt out per-task only when needed.
15
- - **Pre-computed ROI headline**: every `delegate_tasks` response carries a `headline` field — a one-line summary of tasks, success rate, wall-clock, serial savings, cost, and ROI. Quote it verbatim; no arithmetic required.
16
- - **Visible ROI.** Every response surfaces `aggregateCost`, `timings`, and per-task `savedCostUSD` for delegation savings.
17
-
18
- ## How it works
19
-
20
- You don't run this server yourself. Your MCP client spawns it over stdio whenever a session starts, using the config snippets below. No install step, no long-running process to manage — `npx` fetches the latest version on demand each time.
21
-
22
- Requires Node `>= 22`.
23
-
24
- ## Configure
25
-
26
- Create `~/.multi-model/config.json`:
27
-
28
- ```json
29
- {
30
- "providers": {
31
- "claude": {
32
- "type": "claude",
33
- "model": "claude-sonnet-4-6",
34
- "costTier": "medium"
35
- },
36
- "codex": {
37
- "type": "codex",
38
- "model": "gpt-5-codex",
39
- "costTier": "medium"
40
- },
41
- "minimax": {
42
- "type": "openai-compatible",
43
- "model": "MiniMax-M2",
44
- "baseUrl": "https://api.minimax.io/v1",
45
- "apiKeyEnv": "MINIMAX_API_KEY",
46
- "costTier": "free",
47
- "hostedTools": ["web_search"]
48
- }
49
- },
50
- "defaults": {
51
- "maxTurns": 200,
52
- "timeoutMs": 600000,
53
- "tools": "full"
54
- }
55
- }
56
- ```
57
-
58
- Config lookup order: `--config <path>` → `MULTI_MODEL_CONFIG` env var → `~/.multi-model/config.json`.
59
-
60
- Provider auth:
61
-
62
- - **`codex`** uses `codex login` if available, otherwise `OPENAI_API_KEY`
63
- - **`claude`** uses `ANTHROPIC_API_KEY` if set, otherwise the local Claude auth flow
64
- - **`openai-compatible`** uses `apiKeyEnv` (preferred) or inline `apiKey`
65
-
66
- ## Setup
67
-
68
- ### Claude Code
69
-
70
- One command — the client will spawn the server on demand. Use `-s user` so the server is available in **every** project on your machine, not just the directory where you ran the command:
71
-
72
- ```bash
73
- claude mcp add multi-model-agent -s user -- npx -y @zhixuan92/multi-model-agent-mcp serve
74
- ```
75
-
76
- If your providers need environment variables:
7
+ ## Install
77
8
 
78
9
  ```bash
79
10
  claude mcp add multi-model-agent -s user \
80
- -e OPENAI_API_KEY=sk-... \
81
- -e ANTHROPIC_API_KEY=sk-ant-... \
82
- -e MINIMAX_API_KEY=... \
83
11
  -- npx -y @zhixuan92/multi-model-agent-mcp serve
84
12
  ```
85
13
 
86
- Without `-s user`, `claude mcp add` defaults to local scope and only registers the server in the current project.
87
-
88
- ### Codex CLI
89
-
90
- Codex CLI reads MCP servers from `~/.codex/config.toml`. Add this block:
91
-
92
- ```toml
93
- [mcp_servers.multi-model-agent]
94
- command = "npx"
95
- args = ["-y", "@zhixuan92/multi-model-agent-mcp", "serve"]
96
-
97
- [mcp_servers.multi-model-agent.env]
98
- OPENAI_API_KEY = "sk-..."
99
- ANTHROPIC_API_KEY = "sk-ant-..."
100
- MINIMAX_API_KEY = "..."
101
- ```
102
-
103
- Only set the env keys for the providers you actually configured. If you use `codex login`, the `codex` provider inside `multi-model-agent` reuses that auth automatically — but Claude, MiniMax, and other API-key providers still need to be passed through `[mcp_servers.multi-model-agent.env]` because the spawned MCP process does not inherit your shell environment. Restart `codex` after editing the file.
104
-
105
- ### Claude Desktop
106
-
107
- Add to `claude_desktop_config.json`:
108
-
109
- ```json
110
- {
111
- "mcpServers": {
112
- "multi-model-agent": {
113
- "command": "npx",
114
- "args": ["-y", "@zhixuan92/multi-model-agent-mcp", "serve"],
115
- "env": {
116
- "OPENAI_API_KEY": "sk-...",
117
- "ANTHROPIC_API_KEY": "sk-ant-...",
118
- "MINIMAX_API_KEY": "..."
119
- }
120
- }
121
- }
122
- }
123
- ```
124
-
125
- Restart your MCP client after changing config.
126
-
127
- ## Updating
128
-
129
- `npx -y @zhixuan92/multi-model-agent-mcp serve` **always fetches the latest published version** on each spawn — you never need to run `npm update` or re-register the server to pick up a release.
130
-
131
- To apply an update: **fully quit** your MCP client (⌘Q on macOS — just closing the window is not enough for Claude Code / Codex CLI because the MCP process lives with the session), then reopen. The next `delegate_tasks` call will spawn a fresh server from the latest npm version.
132
-
133
- **Pinning a version** — if you need reproducibility (CI, shared team config, debugging a regression), add an explicit version tag to the spawn command:
134
-
135
- ```bash
136
- claude mcp add multi-model-agent -s user -- npx -y @zhixuan92/multi-model-agent-mcp@0.3.0 serve
137
- ```
138
-
139
- or in `config.toml` / `claude_desktop_config.json`:
140
-
141
- ```toml
142
- args = ["-y", "@zhixuan92/multi-model-agent-mcp@0.3.0", "serve"]
143
- ```
144
-
145
- **Breaking changes** — this project is on 0.x semver. MINOR bumps (`0.2.x → 0.3.0`) may change the config schema or the `delegate_tasks` tool input. PATCH bumps (`0.3.0 → 0.3.1`) are strictly backwards-compatible bug fixes. Skim the [CHANGELOG](https://github.com/zhixuan312/multi-model-agent/blob/HEAD/CHANGELOG.md) before adopting a new MINOR version and update `~/.multi-model/config.json` (and any stored `delegate_tasks` call shapes in your rules/prompts) if the changelog calls out a schema change. Provider auth, the config file path, and the MCP tool names themselves are stable across all 0.x releases.
146
-
147
- ## Recommended: delegation rule for Claude Code
148
-
149
- Claude Code's native `Task` / `Agent` subagents inherit your parent session's expensive model and eat its context window. We ship a drop-in rule file that teaches Claude Code **when** to delegate work through `delegate_tasks` instead — mechanical edits go to free providers, reasoning-tier work escalates only when needed, and independent tasks run in parallel.
150
-
151
- Install globally:
152
-
153
- ```bash
154
- mkdir -p ~/.claude/rules
155
- curl -o ~/.claude/rules/multi-model-delegation.md \
156
- https://raw.githubusercontent.com/zhixuan312/multi-model-agent/HEAD/docs/claude-code-delegation-rule.md
157
- ```
158
-
159
- Restart Claude Code after installing. The full rule — judgment-vs-labor principle, decision procedure, provider routing table, dispatch shape, verification, escalation ladder — lives at [`docs/claude-code-delegation-rule.md`](https://github.com/zhixuan312/multi-model-agent/blob/HEAD/docs/claude-code-delegation-rule.md). Read that file before adapting it to your own provider names.
160
-
161
- ## The `delegate_tasks` tool
162
-
163
- Accepts an array of tasks and runs them concurrently. Auto-routes each task by capability filter → quality tier filter → cheapest remaining provider, or pin a task to a specific provider.
164
-
165
- ```json
166
- {
167
- "tasks": [
168
- {
169
- "prompt": "Refactor auth.ts to use JWT.",
170
- "provider": "claude",
171
- "tier": "reasoning",
172
- "requiredCapabilities": ["file_read", "file_write"],
173
- "tools": "full",
174
- "cwd": "/path/to/project",
175
- "parentModel": "claude-sonnet-4-5",
176
- "includeProgressTrace": true
177
- },
178
- {
179
- "prompt": "Write tests for the auth module.",
180
- "tier": "standard",
181
- "requiredCapabilities": ["file_read", "file_write", "grep"],
182
- "tools": "full",
183
- "cwd": "/path/to/project",
184
- "expectedCoverage": {
185
- "minSections": 3,
186
- "sectionPattern": "^Test \\d+:",
187
- "requiredMarkers": ["happy path", "edge case"]
188
- }
189
- }
190
- ]
191
- }
192
- ```
193
-
194
- Per-task fields: `prompt`, `tier`, `requiredCapabilities`, `provider?`, `tools?`, `maxTurns?`, `timeoutMs?`, `cwd?`, `effort?`, `sandboxPolicy?`, `contextBlockIds?`, `expectedCoverage?`, `includeProgressTrace?`, `parentModel?`, `skipCompletionHeuristic?`.
195
-
196
- `expectedCoverage` supports `minSections?`, `sectionPattern?`, and `requiredMarkers?`. `includeProgressTrace` opts a task into returning its bounded post-hoc progress trace. `parentModel` lets the server estimate `savedCostUSD` relative to the calling model. `skipCompletionHeuristic: true` disables the short-output completion heuristic in the runner's supervision layer — use for tight-format outputs (single-line verdicts, CSV rows, opaque identifiers) that don't follow prose conventions. The `empty` and `thinking_only` degeneracy checks still fire independently. If you also set `expectedCoverage`, the coverage contract is authoritative and the short-output heuristic is automatically skipped on coverage pass — you don't need both.
197
-
198
- Capabilities: `file_read`, `file_write`, `grep`, `glob`, `shell`, `web_search`, `web_fetch`.
199
-
200
- ### ROI headline
201
-
202
- Every `delegate_tasks` response envelope — both `full` mode and `summary` mode — carries a pre-computed `headline` field: a one-line summary of tasks / success rate / wall-clock / serial-savings / actual cost / saved cost / ROI multiplier (when a single baseline is declared). The calling agent is expected to quote it verbatim to the user after every dispatch, with no arithmetic. Example:
203
-
204
- > *"11 tasks, 5/11 ok (45.5%), wall 5m 54s, saved ~18m 30s vs serial, $1.37 actual / $8.91 saved vs claude-opus-4-6 (7.5x ROI)"*
205
-
206
- When a batch declares mixed parent models across its tasks, the ROI multiplier is suppressed (because a single ratio across different baselines is not coherent) and the cost clause reads `$X actual / $Y saved vs multiple baselines`. When no `parentModel` is declared, the cost clause collapses to `$X actual`.
207
-
208
- If the primary response came back via summary mode or a client-side limit obscured the envelope, call `get_batch_telemetry(batchId)` — it returns the same `headline` plus the envelope with a ~600-byte header and ~200 bytes per task in `results[]`. A typical 10–30-task batch comes back at 2–7 KB, well under the client's tool-result size limit; very large batches (100+ tasks) scale linearly and may approach the limit.
209
-
210
- ## Security
211
-
212
- ### Sandbox enforcement
213
-
214
- The default `sandboxPolicy: "cwd-only"` confines delegated sub-agents to the task's working directory. The check runs inside every file-tool call in the core `assertWithinCwd` helper — violations are surfaced to the model as normal tool errors, so the model can retry with a valid path rather than silently failing.
215
-
216
- 1. **File reads** are allowed only inside `cwd` and its descendants. Path traversal (`../`, absolute paths outside `cwd`) is rejected.
217
- 2. **File writes** are subject to the same restriction.
218
- 3. **Symlink resolution uses `fs.realpath`.** A symlink inside `cwd` that points outside `cwd` is treated as outside and rejected — the check runs on the resolved real path, not the literal path.
219
- 4. **Nonexistent target paths** resolve by walking back to the nearest existing ancestor and re-applying the check, so symlinks in ancestor directories are still caught.
220
- 5. **`runShell` is hard-disabled** under `cwd-only`. The tool returns an error telling the model to use `readFile` / `writeFile` / `grep` / `glob` / `listFiles` instead. Set `sandboxPolicy: "none"` per-provider or per-task to opt in to shell.
221
- 6. **The check is per-call**, not per-session. Every tool invocation revalidates.
222
- 7. **Errors are surfaced to the model**, not silently swallowed, so the model can observe the rejection and adjust.
14
+ No install step, no long-running process. Your MCP client spawns it on demand via `npx`. Requires Node >= 22.
223
15
 
224
- ### Other hardening
16
+ ## What you get
225
17
 
226
- - `readFile` rejects targets larger than 50 MiB; `writeFile` rejects content larger than 100 MiB.
227
- - The server warns at config-load time if it sees an inline `apiKey` instead of `apiKeyEnv`.
228
- - The server warns once if `~/.codex/auth.json` is group- or world-readable.
229
- - `CODEX_DEBUG=1` enables raw request/response logging to stderr (do not enable in environments that ship logs anywhere).
18
+ | Tool | What it does |
19
+ |---|---|
20
+ | `delegate_tasks` | Dispatch tasks in parallel with full execution control |
21
+ | `audit_document` | Audit docs/files for issues parallel per file |
22
+ | `review_code` | Code review with spec + quality pipeline — parallel per file |
23
+ | `verify_work` | Verify work against a checklist — parallel per file |
24
+ | `debug_task` | Hypothesis-driven debugging with file context |
25
+ | `register_context_block` | Store reusable context for later tasks |
26
+ | `retry_tasks` | Re-run specific tasks from a previous batch |
27
+ | `get_batch_slice` | Fetch output or telemetry from a previous batch |
230
28
 
231
- ## Documentation
29
+ ## Setup & Configuration
232
30
 
233
- Full docs, capability matrix, configuration reference, troubleshooting, and contributor guide:
31
+ See the full setup guide with config examples, client-specific instructions, and auth details:
234
32
 
235
- **<https://github.com/zhixuan312/multi-model-agent#readme>**
33
+ **[github.com/zhixuan312/multi-model-agent](https://github.com/zhixuan312/multi-model-agent#quick-start)**
236
34
 
237
35
  ## License
238
36
 
package/dist/cli.d.ts CHANGED
@@ -2,34 +2,19 @@
2
2
  import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
3
3
  import { z } from 'zod';
4
4
  import { runTasks } from '@zhixuan92/multi-model-agent-core/run-tasks';
5
- import type { MultiModelConfig, RunResult, BatchTimings, BatchProgress, BatchAggregateCost } from '@zhixuan92/multi-model-agent-core';
5
+ import type { MultiModelConfig } from '@zhixuan92/multi-model-agent-core';
6
+ export { computeTimings, computeBatchProgress, computeAggregateCost } from './tools/batch-response.js';
6
7
  export declare const SERVER_NAME = "multi-model-agent";
7
- export declare function computeTimings(wallClockMs: number, results: RunResult[]): BatchTimings;
8
- export declare function computeBatchProgress(results: RunResult[]): BatchProgress;
9
- export declare function computeAggregateCost(results: RunResult[]): BatchAggregateCost;
10
8
  export declare const SERVER_VERSION: string;
11
- export declare function buildTaskSchema(availableProviders: [string, ...string[]]): z.ZodObject<{
9
+ export declare function buildTaskSchema(availableAgents: [string, ...string[]]): z.ZodObject<{
12
10
  prompt: z.ZodString;
13
- provider: z.ZodOptional<z.ZodEnum<{
11
+ agentType: z.ZodOptional<z.ZodEnum<{
14
12
  [x: string]: string;
15
13
  }>>;
16
- tier: z.ZodEnum<{
17
- reasoning: "reasoning";
18
- standard: "standard";
19
- trivial: "trivial";
20
- }>;
21
- requiredCapabilities: z.ZodArray<z.ZodEnum<{
22
- file_read: "file_read";
23
- file_write: "file_write";
24
- grep: "grep";
25
- glob: "glob";
26
- shell: "shell";
27
- web_search: "web_search";
28
- web_fetch: "web_fetch";
29
- }>>;
30
14
  tools: z.ZodOptional<z.ZodEnum<{
31
- full: "full";
15
+ readonly: "readonly";
32
16
  none: "none";
17
+ full: "full";
33
18
  }>>;
34
19
  maxTurns: z.ZodOptional<z.ZodNumber>;
35
20
  timeoutMs: z.ZodOptional<z.ZodNumber>;
@@ -44,6 +29,7 @@ export declare function buildTaskSchema(availableProviders: [string, ...string[]
44
29
  none: "none";
45
30
  "cwd-only": "cwd-only";
46
31
  }>>;
32
+ requiredCapabilities: z.ZodOptional<z.ZodArray<z.ZodString>>;
47
33
  contextBlockIds: z.ZodOptional<z.ZodArray<z.ZodString>>;
48
34
  expectedCoverage: z.ZodOptional<z.ZodObject<{
49
35
  minSections: z.ZodOptional<z.ZodNumber>;
@@ -51,8 +37,20 @@ export declare function buildTaskSchema(availableProviders: [string, ...string[]
51
37
  requiredMarkers: z.ZodOptional<z.ZodArray<z.ZodString>>;
52
38
  }, z.core.$strip>>;
53
39
  skipCompletionHeuristic: z.ZodOptional<z.ZodBoolean>;
54
- includeProgressTrace: z.ZodOptional<z.ZodBoolean>;
55
40
  parentModel: z.ZodOptional<z.ZodString>;
41
+ maxCostUSD: z.ZodOptional<z.ZodNumber>;
42
+ reviewPolicy: z.ZodOptional<z.ZodEnum<{
43
+ full: "full";
44
+ off: "off";
45
+ spec_only: "spec_only";
46
+ }>>;
47
+ maxReviewRounds: z.ZodOptional<z.ZodNumber>;
48
+ briefQualityPolicy: z.ZodOptional<z.ZodEnum<{
49
+ normalize: "normalize";
50
+ strict: "strict";
51
+ warn: "warn";
52
+ off: "off";
53
+ }>>;
56
54
  }, z.core.$strip>;
57
55
  export declare function buildMcpServer(config: Parameters<typeof runTasks>[1], options?: {
58
56
  /** Character threshold that triggers auto-switch from 'full' to
package/dist/cli.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAQA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,EAAE,QAAQ,EAAE,MAAM,6CAA6C,CAAC;AAEvE,OAAO,KAAK,EACV,gBAAgB,EAGhB,SAAS,EACT,YAAY,EACZ,aAAa,EACb,kBAAkB,EACnB,MAAM,mCAAmC,CAAC;AAI3C,eAAO,MAAM,WAAW,sBAAsB,CAAC;AAc/C,wBAAgB,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,GAAG,YAAY,CAItF;AAED,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,SAAS,EAAE,GAAG,aAAa,CAgBxE;AAED,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,SAAS,EAAE,GAAG,kBAAkB,CAyB7E;AAgGD,eAAO,MAAM,cAAc,QAAc,CAAC;AAE1C,wBAAgB,eAAe,CAAC,kBAAkB,EAAE,CAAC,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBA6CxE;AAkCD,wBAAgB,cAAc,CAC5B,MAAM,EAAE,UAAU,CAAC,OAAO,QAAQ,CAAC,CAAC,CAAC,CAAC,EACtC,OAAO,CAAC,EAAE;IACR;;;;;wEAKoE;IACpE,2BAA2B,CAAC,EAAE,MAAM,CAAC;IACrC,+EAA+E;IAC/E,qBAAqB,CAAC,EAAE,OAAO,QAAQ,CAAC;CACzC,aAqeF;AAED;;;;;GAKG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,gBAAgB,CAAC,CAuBhE"}
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAQA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,EAAE,QAAQ,EAAE,MAAM,6CAA6C,CAAC;AAEvE,OAAO,KAAK,EACV,gBAAgB,EAQjB,MAAM,mCAAmC,CAAC;AAa3C,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAEvG,eAAO,MAAM,WAAW,sBAAsB,CAAC;AAwH/C,eAAO,MAAM,cAAc,QAAc,CAAC;AAE1C,wBAAgB,eAAe,CAAC,eAAe,EAAE,CAAC,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBA4HrE;AAkCD,wBAAgB,cAAc,CAC5B,MAAM,EAAE,UAAU,CAAC,OAAO,QAAQ,CAAC,CAAC,CAAC,CAAC,EACtC,OAAO,CAAC,EAAE;IACR;;;;;wEAKoE;IACpE,2BAA2B,CAAC,EAAE,MAAM,CAAC;IACrC,+EAA+E;IAC/E,qBAAqB,CAAC,EAAE,OAAO,QAAQ,CAAC;CACzC,aAgdF;AAED;;;;;GAKG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,gBAAgB,CAAC,CA4BhE"}