@zhixuan92/multi-model-agent 3.0.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.
- package/LICENSE +21 -0
- package/README.md +217 -0
- package/dist/cli/index.d.ts +61 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +252 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/install-skill.d.ts +158 -0
- package/dist/cli/install-skill.d.ts.map +1 -0
- package/dist/cli/install-skill.js +425 -0
- package/dist/cli/install-skill.js.map +1 -0
- package/dist/cli/print-token.d.ts +18 -0
- package/dist/cli/print-token.d.ts.map +1 -0
- package/dist/cli/print-token.js +60 -0
- package/dist/cli/print-token.js.map +1 -0
- package/dist/cli/serve.d.ts +44 -0
- package/dist/cli/serve.d.ts.map +1 -0
- package/dist/cli/serve.js +61 -0
- package/dist/cli/serve.js.map +1 -0
- package/dist/cli/status.d.ts +49 -0
- package/dist/cli/status.d.ts.map +1 -0
- package/dist/cli/status.js +155 -0
- package/dist/cli/status.js.map +1 -0
- package/dist/http/async-dispatch.d.ts +32 -0
- package/dist/http/async-dispatch.d.ts.map +1 -0
- package/dist/http/async-dispatch.js +53 -0
- package/dist/http/async-dispatch.js.map +1 -0
- package/dist/http/auth.d.ts +26 -0
- package/dist/http/auth.d.ts.map +1 -0
- package/dist/http/auth.js +64 -0
- package/dist/http/auth.js.map +1 -0
- package/dist/http/cwd-validator.d.ts +11 -0
- package/dist/http/cwd-validator.d.ts.map +1 -0
- package/dist/http/cwd-validator.js +115 -0
- package/dist/http/cwd-validator.js.map +1 -0
- package/dist/http/errors.d.ts +4 -0
- package/dist/http/errors.d.ts.map +1 -0
- package/dist/http/errors.js +9 -0
- package/dist/http/errors.js.map +1 -0
- package/dist/http/execution-context.d.ts +15 -0
- package/dist/http/execution-context.d.ts.map +1 -0
- package/dist/http/execution-context.js +35 -0
- package/dist/http/execution-context.js.map +1 -0
- package/dist/http/handler-deps.d.ts +16 -0
- package/dist/http/handler-deps.d.ts.map +1 -0
- package/dist/http/handler-deps.js +2 -0
- package/dist/http/handler-deps.js.map +1 -0
- package/dist/http/handlers/control/batch.d.ts +24 -0
- package/dist/http/handlers/control/batch.d.ts.map +1 -0
- package/dist/http/handlers/control/batch.js +81 -0
- package/dist/http/handlers/control/batch.js.map +1 -0
- package/dist/http/handlers/control/clarifications.d.ts +19 -0
- package/dist/http/handlers/control/clarifications.d.ts.map +1 -0
- package/dist/http/handlers/control/clarifications.js +58 -0
- package/dist/http/handlers/control/clarifications.js.map +1 -0
- package/dist/http/handlers/control/context-blocks.d.ts +22 -0
- package/dist/http/handlers/control/context-blocks.d.ts.map +1 -0
- package/dist/http/handlers/control/context-blocks.js +88 -0
- package/dist/http/handlers/control/context-blocks.js.map +1 -0
- package/dist/http/handlers/introspection/health.d.ts +13 -0
- package/dist/http/handlers/introspection/health.d.ts.map +1 -0
- package/dist/http/handlers/introspection/health.js +17 -0
- package/dist/http/handlers/introspection/health.js.map +1 -0
- package/dist/http/handlers/introspection/status.d.ts +26 -0
- package/dist/http/handlers/introspection/status.d.ts.map +1 -0
- package/dist/http/handlers/introspection/status.js +136 -0
- package/dist/http/handlers/introspection/status.js.map +1 -0
- package/dist/http/handlers/introspection/tools-list.d.ts +9 -0
- package/dist/http/handlers/introspection/tools-list.d.ts.map +1 -0
- package/dist/http/handlers/introspection/tools-list.js +28 -0
- package/dist/http/handlers/introspection/tools-list.js.map +1 -0
- package/dist/http/handlers/tools/audit.d.ts +4 -0
- package/dist/http/handlers/tools/audit.d.ts.map +1 -0
- package/dist/http/handlers/tools/audit.js +39 -0
- package/dist/http/handlers/tools/audit.js.map +1 -0
- package/dist/http/handlers/tools/debug.d.ts +4 -0
- package/dist/http/handlers/tools/debug.d.ts.map +1 -0
- package/dist/http/handlers/tools/debug.js +39 -0
- package/dist/http/handlers/tools/debug.js.map +1 -0
- package/dist/http/handlers/tools/delegate.d.ts +4 -0
- package/dist/http/handlers/tools/delegate.d.ts.map +1 -0
- package/dist/http/handlers/tools/delegate.js +57 -0
- package/dist/http/handlers/tools/delegate.js.map +1 -0
- package/dist/http/handlers/tools/execute-plan.d.ts +4 -0
- package/dist/http/handlers/tools/execute-plan.d.ts.map +1 -0
- package/dist/http/handlers/tools/execute-plan.js +39 -0
- package/dist/http/handlers/tools/execute-plan.js.map +1 -0
- package/dist/http/handlers/tools/retry.d.ts +4 -0
- package/dist/http/handlers/tools/retry.d.ts.map +1 -0
- package/dist/http/handlers/tools/retry.js +52 -0
- package/dist/http/handlers/tools/retry.js.map +1 -0
- package/dist/http/handlers/tools/review.d.ts +4 -0
- package/dist/http/handlers/tools/review.d.ts.map +1 -0
- package/dist/http/handlers/tools/review.js +39 -0
- package/dist/http/handlers/tools/review.js.map +1 -0
- package/dist/http/handlers/tools/verify.d.ts +4 -0
- package/dist/http/handlers/tools/verify.d.ts.map +1 -0
- package/dist/http/handlers/tools/verify.js +39 -0
- package/dist/http/handlers/tools/verify.js.map +1 -0
- package/dist/http/loopback.d.ts +17 -0
- package/dist/http/loopback.d.ts.map +1 -0
- package/dist/http/loopback.js +43 -0
- package/dist/http/loopback.js.map +1 -0
- package/dist/http/middleware/body-reader.d.ts +16 -0
- package/dist/http/middleware/body-reader.d.ts.map +1 -0
- package/dist/http/middleware/body-reader.js +44 -0
- package/dist/http/middleware/body-reader.js.map +1 -0
- package/dist/http/project-registry.d.ts +54 -0
- package/dist/http/project-registry.d.ts.map +1 -0
- package/dist/http/project-registry.js +132 -0
- package/dist/http/project-registry.js.map +1 -0
- package/dist/http/router.d.ts +14 -0
- package/dist/http/router.d.ts.map +1 -0
- package/dist/http/router.js +41 -0
- package/dist/http/router.js.map +1 -0
- package/dist/http/server.d.ts +16 -0
- package/dist/http/server.d.ts.map +1 -0
- package/dist/http/server.js +235 -0
- package/dist/http/server.js.map +1 -0
- package/dist/http/types.d.ts +9 -0
- package/dist/http/types.d.ts.map +1 -0
- package/dist/http/types.js +2 -0
- package/dist/http/types.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/install/claude-code.d.ts +43 -0
- package/dist/install/claude-code.d.ts.map +1 -0
- package/dist/install/claude-code.js +65 -0
- package/dist/install/claude-code.js.map +1 -0
- package/dist/install/codex-cli.d.ts +39 -0
- package/dist/install/codex-cli.d.ts.map +1 -0
- package/dist/install/codex-cli.js +318 -0
- package/dist/install/codex-cli.js.map +1 -0
- package/dist/install/cursor.d.ts +72 -0
- package/dist/install/cursor.d.ts.map +1 -0
- package/dist/install/cursor.js +81 -0
- package/dist/install/cursor.js.map +1 -0
- package/dist/install/gemini-cli.d.ts +66 -0
- package/dist/install/gemini-cli.d.ts.map +1 -0
- package/dist/install/gemini-cli.js +111 -0
- package/dist/install/gemini-cli.js.map +1 -0
- package/dist/install/include-utils.d.ts +27 -0
- package/dist/install/include-utils.d.ts.map +1 -0
- package/dist/install/include-utils.js +90 -0
- package/dist/install/include-utils.js.map +1 -0
- package/dist/install/manifest.d.ts +90 -0
- package/dist/install/manifest.d.ts.map +1 -0
- package/dist/install/manifest.js +200 -0
- package/dist/install/manifest.js.map +1 -0
- package/dist/openapi.d.ts +15 -0
- package/dist/openapi.d.ts.map +1 -0
- package/dist/openapi.js +314 -0
- package/dist/openapi.js.map +1 -0
- package/dist/skills/_shared/auth.md +32 -0
- package/dist/skills/_shared/error-handling.md +31 -0
- package/dist/skills/_shared/polling.md +40 -0
- package/dist/skills/_shared/response-shape.md +46 -0
- package/dist/skills/mma-audit/SKILL.md +55 -0
- package/dist/skills/mma-clarifications/SKILL.md +68 -0
- package/dist/skills/mma-context-blocks/SKILL.md +69 -0
- package/dist/skills/mma-debug/SKILL.md +59 -0
- package/dist/skills/mma-delegate/SKILL.md +63 -0
- package/dist/skills/mma-execute-plan/SKILL.md +63 -0
- package/dist/skills/mma-retry/SKILL.md +54 -0
- package/dist/skills/mma-review/SKILL.md +55 -0
- package/dist/skills/mma-verify/SKILL.md +57 -0
- package/dist/skills/multi-model-agent/SKILL.md +55 -0
- package/package.json +60 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Zhang Zhixuan
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
# @zhixuan92/multi-model-agent-mcp
|
|
2
|
+
|
|
3
|
+
**MCP server for multi-model-agent.** Your AI assistant gets 10 tools for delegating work to cheaper agents — parallel execution, cross-agent review, 90% cost savings.
|
|
4
|
+
|
|
5
|
+
Works with Claude Code, Codex CLI, Cursor, Gemini CLI, and Claude Desktop.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
Requires Node >= 22 and a config file at `~/.multi-model/config.json`.
|
|
10
|
+
|
|
11
|
+
**1. Create config** — define your two agent slots. Three agent types are supported:
|
|
12
|
+
|
|
13
|
+
| Type | Auth | API key needed? |
|
|
14
|
+
|---|---|---|
|
|
15
|
+
| `claude` | Your existing Claude Code / Claude subscription | No — uses local OAuth |
|
|
16
|
+
| `codex` | Your existing Codex subscription (`codex login`) | No — reads `~/.codex/auth.json` |
|
|
17
|
+
| `openai-compatible` | Any OpenAI-compatible API (GPT, MiniMax, DeepSeek, Groq, local vLLM) | Yes — `apiKeyEnv` or `apiKey` |
|
|
18
|
+
|
|
19
|
+
**Example — Claude + Codex (no API keys):**
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
mkdir -p ~/.multi-model && cat > ~/.multi-model/config.json << 'EOF'
|
|
23
|
+
{
|
|
24
|
+
"agents": {
|
|
25
|
+
"standard": { "type": "codex", "model": "codex-mini-latest" },
|
|
26
|
+
"complex": { "type": "claude", "model": "claude-sonnet-4-20250514" }
|
|
27
|
+
},
|
|
28
|
+
"defaults": { "timeoutMs": 1800000, "maxCostUSD": 10, "tools": "full" }
|
|
29
|
+
}
|
|
30
|
+
EOF
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
**Example — OpenAI-compatible endpoints (API keys required):**
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
mkdir -p ~/.multi-model && cat > ~/.multi-model/config.json << 'EOF'
|
|
37
|
+
{
|
|
38
|
+
"agents": {
|
|
39
|
+
"standard": {
|
|
40
|
+
"type": "openai-compatible",
|
|
41
|
+
"model": "MiniMax-M2",
|
|
42
|
+
"baseUrl": "https://api.minimax.io/v1",
|
|
43
|
+
"apiKeyEnv": "MINIMAX_API_KEY"
|
|
44
|
+
},
|
|
45
|
+
"complex": {
|
|
46
|
+
"type": "openai-compatible",
|
|
47
|
+
"model": "gpt-5",
|
|
48
|
+
"baseUrl": "https://api.openai.com/v1",
|
|
49
|
+
"apiKeyEnv": "OPENAI_API_KEY"
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
"defaults": { "timeoutMs": 1800000, "maxCostUSD": 10, "tools": "full", "parentModel": "claude-opus-4-6" }
|
|
53
|
+
}
|
|
54
|
+
EOF
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
> **`parentModel`** (optional): When set, headlines show `$Y saved vs model (Zx ROI)`. When omitted, headlines show `$X actual`.
|
|
58
|
+
|
|
59
|
+
Mix and match freely — e.g., `claude` for complex + `openai-compatible` for standard.
|
|
60
|
+
|
|
61
|
+
**2. Register the MCP server:**
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
# Claude/Codex agents (no env vars needed):
|
|
65
|
+
claude mcp add multi-model-agent -s user \
|
|
66
|
+
-- npx -y @zhixuan92/multi-model-agent-mcp serve
|
|
67
|
+
|
|
68
|
+
# OpenAI-compatible agents (pass API keys):
|
|
69
|
+
claude mcp add multi-model-agent -s user \
|
|
70
|
+
-e MINIMAX_API_KEY=... -e OPENAI_API_KEY=... \
|
|
71
|
+
-- npx -y @zhixuan92/multi-model-agent-mcp serve
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
No install step, no long-running process. Your MCP client spawns it on demand via `npx`.
|
|
75
|
+
|
|
76
|
+
For Codex CLI, Claude Desktop, and Cursor setup, see the [full guide](https://github.com/zhixuan312/multi-model-agent#quick-start).
|
|
77
|
+
|
|
78
|
+
## What you get
|
|
79
|
+
|
|
80
|
+
| Tool | What it does |
|
|
81
|
+
|---|---|
|
|
82
|
+
| `delegate_tasks` | Dispatch tasks in parallel with minimal input: `prompt` plus optional `agentType`, `filePaths`, `done`, and `contextBlockIds`. The MCP interprets your request and infers missing details — if confused, it returns a proposed interpretation for confirmation. |
|
|
83
|
+
| `audit_document` | Audit docs/files for issues — parallel per file. Accepts `contextBlockIds` for delta audits (round 2+). |
|
|
84
|
+
| `review_code` | Code review with spec + quality pipeline — parallel per file. Accepts `contextBlockIds` for diff-scoped/delta reviews. |
|
|
85
|
+
| `verify_work` | Verify work against a checklist — parallel per file. Accepts `contextBlockIds` for shared context. |
|
|
86
|
+
| `debug_task` | Hypothesis-driven debugging with file context. Accepts `contextBlockIds` for shared context. |
|
|
87
|
+
| `execute_plan` | Execute tasks from a plan document — worker reads plan files, finds matching task by descriptor, implements it. Multiple tasks run in parallel. |
|
|
88
|
+
| `register_context_block` | Store reusable context for later tasks |
|
|
89
|
+
| `retry_tasks` | Re-run specific tasks from a previous batch |
|
|
90
|
+
| `get_batch_slice` | Fetch output or telemetry from a previous batch |
|
|
91
|
+
| `confirm_clarifications` | Resume a clarification set by confirming or editing proposed interpretations |
|
|
92
|
+
|
|
93
|
+
## Diagnostic logging
|
|
94
|
+
|
|
95
|
+
Diagnostic logging is OFF by default.
|
|
96
|
+
|
|
97
|
+
It stays disabled when the `diagnostics` block is absent or when `diagnostics.log` is `false` in `~/.multi-model/config.json`.
|
|
98
|
+
|
|
99
|
+
To capture a crash/disconnect log to send us, add a `diagnostics` block to your config.
|
|
100
|
+
|
|
101
|
+
Minimal example:
|
|
102
|
+
|
|
103
|
+
```json
|
|
104
|
+
{
|
|
105
|
+
"diagnostics": { "log": true }
|
|
106
|
+
}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Full config shape example:
|
|
110
|
+
|
|
111
|
+
```json
|
|
112
|
+
{
|
|
113
|
+
"agents": {
|
|
114
|
+
"standard": { "type": "codex", "model": "codex-mini-latest" },
|
|
115
|
+
"complex": { "type": "claude", "model": "claude-sonnet-4-20250514" }
|
|
116
|
+
},
|
|
117
|
+
"defaults": {
|
|
118
|
+
"timeoutMs": 1800000,
|
|
119
|
+
"maxCostUSD": 10,
|
|
120
|
+
"tools": "full"
|
|
121
|
+
},
|
|
122
|
+
"diagnostics": {
|
|
123
|
+
"log": true,
|
|
124
|
+
"logDir": "/some/path"
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
`diagnostics.logDir` is optional; when omitted, logs default to `~/.multi-model/logs/`.
|
|
130
|
+
|
|
131
|
+
When enabled, the server appends JSONL records to `mcp-YYYY-MM-DD.jsonl` in append mode.
|
|
132
|
+
|
|
133
|
+
Only crash/disconnect diagnostic events are logged: `startup`, `request_start`, `request_complete`, `shutdown`, and `error`. This is a crash-diagnosis log, not a progress feed.
|
|
134
|
+
|
|
135
|
+
## Setup & Configuration
|
|
136
|
+
|
|
137
|
+
See the full setup guide with config examples, client-specific instructions, and auth details:
|
|
138
|
+
|
|
139
|
+
→ **[github.com/zhixuan312/multi-model-agent](https://github.com/zhixuan312/multi-model-agent#quick-start)**
|
|
140
|
+
|
|
141
|
+
## Running as an HTTP daemon
|
|
142
|
+
|
|
143
|
+
The default transport is stdio — Claude Code spawns one `mmagent` process per session. When the Claude Code session ends (compaction, `/clear`, exit), the process dies; the next tool call has to start a fresh one.
|
|
144
|
+
|
|
145
|
+
To survive Claude Code lifecycle events, run `mmagent` as a long-running HTTP daemon. Multiple Claude Code sessions can connect to the same daemon (each pointing at its own project directory), and a client reconnect reuses the project's in-memory stores.
|
|
146
|
+
|
|
147
|
+
### Start the daemon
|
|
148
|
+
|
|
149
|
+
Foreground (quickest way to try):
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
mmagent serve --http
|
|
153
|
+
# → http://127.0.0.1:7312
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Background (macOS launchd / Linux systemd): see `scripts/README.md`.
|
|
157
|
+
|
|
158
|
+
### Point Claude Code at the daemon
|
|
159
|
+
|
|
160
|
+
In each project's `.mcp.json`:
|
|
161
|
+
|
|
162
|
+
```jsonc
|
|
163
|
+
{
|
|
164
|
+
"mcpServers": {
|
|
165
|
+
"multi-model-agent": {
|
|
166
|
+
"url": "http://127.0.0.1:7312/?cwd=/absolute/path/to/project"
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
Two projects = two `.mcp.json` files, each with a different `?cwd=`.
|
|
173
|
+
|
|
174
|
+
### Auth (optional)
|
|
175
|
+
|
|
176
|
+
For shared development machines:
|
|
177
|
+
|
|
178
|
+
```jsonc
|
|
179
|
+
// ~/.multi-model/config.json
|
|
180
|
+
{
|
|
181
|
+
"transport": {
|
|
182
|
+
"mode": "http",
|
|
183
|
+
"http": { "auth": { "enabled": true } }
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
On startup, `mmagent` generates a random token at `~/.multi-model/runtime/token` (mode 600). Paste it into `.mcp.json`:
|
|
189
|
+
|
|
190
|
+
```jsonc
|
|
191
|
+
{
|
|
192
|
+
"url": "http://127.0.0.1:7312/?cwd=...",
|
|
193
|
+
"headers": { "Authorization": "Bearer <token-from-that-file>" }
|
|
194
|
+
}
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
### Check daemon status
|
|
198
|
+
|
|
199
|
+
```bash
|
|
200
|
+
mmagent status
|
|
201
|
+
# mmagent 2.8.0 · pid 6821 · uptime 3h 24m · http://127.0.0.1:7312
|
|
202
|
+
# Projects (2):
|
|
203
|
+
# /Users/me/project-X 1 sess 7 batches last seen 8s ago
|
|
204
|
+
# /Users/me/project-Y 1 sess 2 batches last seen 4m ago
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### Upgrades
|
|
208
|
+
|
|
209
|
+
`npm i -g @zhixuan92/multi-model-agent-mcp@latest` writes the new binary but does not restart the running daemon. Restart manually:
|
|
210
|
+
|
|
211
|
+
- **launchd**: `launchctl kickstart -k gui/$(id -u)/com.zhixuan92.mmagent`
|
|
212
|
+
- **systemd**: `systemctl --user restart mmagent`
|
|
213
|
+
- **foreground**: `Ctrl-C` and run `mmagent serve --http` again.
|
|
214
|
+
|
|
215
|
+
## License
|
|
216
|
+
|
|
217
|
+
[MIT](./LICENSE) — Copyright (c) 2026 Zhang Zhixuan
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { type ParsedArgs } from 'minimist';
|
|
2
|
+
import { type MultiModelConfig } from '@zhixuan92/multi-model-agent-core';
|
|
3
|
+
/**
|
|
4
|
+
* Minimal I/O dependencies — allows tests to intercept stdout/stderr and
|
|
5
|
+
* override process.argv / process.exit.
|
|
6
|
+
*/
|
|
7
|
+
export interface CliDeps {
|
|
8
|
+
/**
|
|
9
|
+
* argv[0..] (not including node path or script path) passed to minimist.
|
|
10
|
+
* Defaults to process.argv.slice(2).
|
|
11
|
+
*/
|
|
12
|
+
argv?: () => string[];
|
|
13
|
+
/**
|
|
14
|
+
* Current working directory. Defaults to process.cwd().
|
|
15
|
+
* Used only for resolving the CWD/.multi-model-agent.json discovery path.
|
|
16
|
+
*/
|
|
17
|
+
cwd?: () => string;
|
|
18
|
+
/**
|
|
19
|
+
* Home directory. Defaults to os.homedir().
|
|
20
|
+
* Used only for resolving the ~/.multi-model/config.json discovery path.
|
|
21
|
+
*/
|
|
22
|
+
homeDir?: () => string;
|
|
23
|
+
/**
|
|
24
|
+
* Environment variable accessor. Defaults to process.env.
|
|
25
|
+
*/
|
|
26
|
+
env?: () => Record<string, string | undefined>;
|
|
27
|
+
/** Write to stdout. Defaults to process.stdout.write.bind(process.stdout). */
|
|
28
|
+
stdout?: (s: string) => boolean;
|
|
29
|
+
/** Write to stderr. Defaults to process.stderr.write.bind(process.stderr). */
|
|
30
|
+
stderr?: (s: string) => boolean;
|
|
31
|
+
/** Exit the process. Defaults to process.exit. */
|
|
32
|
+
exit?: (code: number) => never;
|
|
33
|
+
}
|
|
34
|
+
/** Parse minimist args from an argv array. */
|
|
35
|
+
export declare function parseArgs(argv: string[]): ParsedArgs;
|
|
36
|
+
/**
|
|
37
|
+
* Resolve the config file path using the discovery order:
|
|
38
|
+
* 1. --config <path> (explicit flag)
|
|
39
|
+
* 2. $MMAGENT_CONFIG (env var)
|
|
40
|
+
* 3. CWD/.multi-model-agent.json
|
|
41
|
+
* 4. ~/.multi-model/config.json
|
|
42
|
+
*
|
|
43
|
+
* Returns the first path that exists, or undefined if none exist.
|
|
44
|
+
* Does NOT validate or parse the file — caller uses loadConfigFromFile().
|
|
45
|
+
*/
|
|
46
|
+
export declare function resolveConfigPath(explicit: string | undefined, env: Record<string, string | undefined>, cwd: string, home: string): string | undefined;
|
|
47
|
+
/**
|
|
48
|
+
* Load config using the discovery order.
|
|
49
|
+
* Tries each candidate in priority order and returns the first successfully
|
|
50
|
+
* loaded config. Returns an error listing all attempted paths if none are found
|
|
51
|
+
* or every found file is unreadable/invalid.
|
|
52
|
+
*/
|
|
53
|
+
export declare function loadConfig(explicitPath: string | undefined, deps: Pick<CliDeps, 'cwd' | 'homeDir' | 'env'>): Promise<MultiModelConfig>;
|
|
54
|
+
/**
|
|
55
|
+
* Main entry point — exported so it can be unit-tested without subprocess spawning.
|
|
56
|
+
*
|
|
57
|
+
* @param deps I/O dependencies (defaults to real process globals).
|
|
58
|
+
*/
|
|
59
|
+
export declare function main(deps?: CliDeps): Promise<void>;
|
|
60
|
+
export type { MultiModelConfig };
|
|
61
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AAyBA,OAAiB,EAAE,KAAK,UAAU,EAAE,MAAM,UAAU,CAAC;AACrD,OAAO,EAEL,KAAK,gBAAgB,EACtB,MAAM,mCAAmC,CAAC;AAM3C;;;GAGG;AACH,MAAM,WAAW,OAAO;IACtB;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,MAAM,EAAE,CAAC;IACtB;;;OAGG;IACH,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,MAAM,CAAC;IACvB;;OAEG;IACH,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;IAC/C,8EAA8E;IAC9E,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC;IAChC,8EAA8E;IAC9E,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC;IAChC,kDAAkD;IAClD,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,KAAK,CAAC;CAChC;AAED,8CAA8C;AAC9C,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,UAAU,CASpD;AA4BD;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,MAAM,GAAG,SAAS,EAC5B,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,EACvC,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,GACX,MAAM,GAAG,SAAS,CAKpB;AAED;;;;;GAKG;AACH,wBAAsB,UAAU,CAC9B,YAAY,EAAE,MAAM,GAAG,SAAS,EAChC,IAAI,EAAE,IAAI,CAAC,OAAO,EAAE,KAAK,GAAG,SAAS,GAAG,KAAK,CAAC,GAC7C,OAAO,CAAC,gBAAgB,CAAC,CA0B3B;AAkCD;;;;GAIG;AACH,wBAAsB,IAAI,CAAC,IAAI,GAAE,OAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAsF5D;AA8BD,YAAY,EAAE,gBAAgB,EAAE,CAAC"}
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI entry point for `mmagent` / `multi-model-agent`.
|
|
3
|
+
*
|
|
4
|
+
* Usage:
|
|
5
|
+
* mmagent serve [--config <path>]
|
|
6
|
+
* mmagent --help
|
|
7
|
+
* mmagent --version
|
|
8
|
+
*
|
|
9
|
+
* Config discovery order (highest priority → lowest):
|
|
10
|
+
* 1. --config <path> (explicit flag)
|
|
11
|
+
* 2. $MMAGENT_CONFIG env var
|
|
12
|
+
* 3. CWD/.multi-model-agent.json
|
|
13
|
+
* 4. ~/.multi-model/config.json
|
|
14
|
+
*
|
|
15
|
+
* All side effects (process.exit, stdout/stderr writes) are contained in the
|
|
16
|
+
* bootstrap at the bottom of this file. The internal `main()` function is
|
|
17
|
+
* exported so it can be unit-tested without spawning subprocesses.
|
|
18
|
+
*
|
|
19
|
+
* Signal lifecycle is owned by `serve.ts` — this module delegates to
|
|
20
|
+
* `startServe()` which registers SIGTERM/SIGINT handlers and manages process.exit.
|
|
21
|
+
*/
|
|
22
|
+
import * as path from 'node:path';
|
|
23
|
+
import * as fs from 'node:fs';
|
|
24
|
+
import * as os from 'node:os';
|
|
25
|
+
import { fileURLToPath } from 'node:url';
|
|
26
|
+
import minimist from 'minimist';
|
|
27
|
+
import { loadConfigFromFile, } from '@zhixuan92/multi-model-agent-core';
|
|
28
|
+
import { startServe } from './serve.js';
|
|
29
|
+
import { printToken } from './print-token.js';
|
|
30
|
+
import { runStatus, buildServerUrl } from './status.js';
|
|
31
|
+
import { main as installSkillMain } from './install-skill.js';
|
|
32
|
+
/** Parse minimist args from an argv array. */
|
|
33
|
+
export function parseArgs(argv) {
|
|
34
|
+
return minimist(argv, {
|
|
35
|
+
string: ['config'],
|
|
36
|
+
boolean: ['help', 'version', 'json'],
|
|
37
|
+
alias: { config: 'c', help: 'h', version: 'v', json: 'j' },
|
|
38
|
+
// Note: stopEarly is NOT set. With stopEarly:true, options after the first
|
|
39
|
+
// positional argument (the subcommand) would be silently dropped. E.g.
|
|
40
|
+
// `mmagent serve --config ./config.json` would lose --config.
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Build the ordered list of config-file candidates from discovery sources.
|
|
45
|
+
* Returns an array of resolved paths; callers filter for existence and
|
|
46
|
+
* iterate in priority order. This single builder ensures that
|
|
47
|
+
* resolveConfigPath() and loadConfig() cannot drift apart.
|
|
48
|
+
*/
|
|
49
|
+
function buildCandidatePaths(explicit, env, cwd, home) {
|
|
50
|
+
const paths = [];
|
|
51
|
+
if (explicit)
|
|
52
|
+
paths.push(explicit);
|
|
53
|
+
const envVal = (env['MMAGENT_CONFIG'] ?? '').trim();
|
|
54
|
+
if (envVal)
|
|
55
|
+
paths.push(envVal);
|
|
56
|
+
paths.push(path.join(cwd, '.multi-model-agent.json'));
|
|
57
|
+
paths.push(path.join(home, '.multi-model', 'config.json'));
|
|
58
|
+
return paths;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Resolve the config file path using the discovery order:
|
|
62
|
+
* 1. --config <path> (explicit flag)
|
|
63
|
+
* 2. $MMAGENT_CONFIG (env var)
|
|
64
|
+
* 3. CWD/.multi-model-agent.json
|
|
65
|
+
* 4. ~/.multi-model/config.json
|
|
66
|
+
*
|
|
67
|
+
* Returns the first path that exists, or undefined if none exist.
|
|
68
|
+
* Does NOT validate or parse the file — caller uses loadConfigFromFile().
|
|
69
|
+
*/
|
|
70
|
+
export function resolveConfigPath(explicit, env, cwd, home) {
|
|
71
|
+
for (const p of buildCandidatePaths(explicit, env, cwd, home)) {
|
|
72
|
+
if (p && fs.existsSync(p))
|
|
73
|
+
return p;
|
|
74
|
+
}
|
|
75
|
+
return undefined;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Load config using the discovery order.
|
|
79
|
+
* Tries each candidate in priority order and returns the first successfully
|
|
80
|
+
* loaded config. Returns an error listing all attempted paths if none are found
|
|
81
|
+
* or every found file is unreadable/invalid.
|
|
82
|
+
*/
|
|
83
|
+
export async function loadConfig(explicitPath, deps) {
|
|
84
|
+
const cwd = deps.cwd?.() ?? process.cwd();
|
|
85
|
+
const home = deps.homeDir?.() ?? os.homedir();
|
|
86
|
+
const env = deps.env?.() ?? process.env;
|
|
87
|
+
const attempted = [];
|
|
88
|
+
for (const p of buildCandidatePaths(explicitPath, env, cwd, home)) {
|
|
89
|
+
if (!p) {
|
|
90
|
+
attempted.push('<source: not set>');
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
attempted.push(p);
|
|
94
|
+
if (!fs.existsSync(p))
|
|
95
|
+
continue;
|
|
96
|
+
try {
|
|
97
|
+
return await loadConfigFromFile(p);
|
|
98
|
+
}
|
|
99
|
+
catch (err) {
|
|
100
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
101
|
+
throw new Error(`Config error (${p}): ${msg}`);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
throw new Error(`No config file found. Tried:\n${attempted.join('\n')}\n` +
|
|
105
|
+
`Set one via --config, $MMAGENT_CONFIG, or place it at a default location above.`);
|
|
106
|
+
}
|
|
107
|
+
const HELP_TEXT = `\
|
|
108
|
+
mmagent — multi-model-agent HTTP server
|
|
109
|
+
|
|
110
|
+
Usage:
|
|
111
|
+
mmagent [command] [options]
|
|
112
|
+
|
|
113
|
+
Commands:
|
|
114
|
+
serve Start the HTTP server (default)
|
|
115
|
+
print-token Print the bearer auth token to stdout
|
|
116
|
+
status Show server status (requires a running server)
|
|
117
|
+
install-skill Install or uninstall a skill for an AI client
|
|
118
|
+
|
|
119
|
+
Global options:
|
|
120
|
+
--config, -c <path> Path to config file
|
|
121
|
+
--help, -h Show this help
|
|
122
|
+
--version, -v Show version
|
|
123
|
+
`;
|
|
124
|
+
/**
|
|
125
|
+
* Read the server package version from package.json, walking up from this file.
|
|
126
|
+
*/
|
|
127
|
+
function readServerVersion() {
|
|
128
|
+
try {
|
|
129
|
+
const thisDir = path.dirname(fileURLToPath(import.meta.url));
|
|
130
|
+
const pkgPath = path.join(thisDir, '..', '..', 'package.json');
|
|
131
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
|
|
132
|
+
return pkg.version ?? '0.0.0';
|
|
133
|
+
}
|
|
134
|
+
catch {
|
|
135
|
+
return '0.0.0';
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Main entry point — exported so it can be unit-tested without subprocess spawning.
|
|
140
|
+
*
|
|
141
|
+
* @param deps I/O dependencies (defaults to real process globals).
|
|
142
|
+
*/
|
|
143
|
+
export async function main(deps = {}) {
|
|
144
|
+
const argv = deps.argv?.() ?? process.argv.slice(2);
|
|
145
|
+
const stdout = deps.stdout ?? process.stdout.write.bind(process.stdout);
|
|
146
|
+
const stderr = deps.stderr ?? process.stderr.write.bind(process.stderr);
|
|
147
|
+
const exit = deps.exit ?? process.exit.bind(process);
|
|
148
|
+
const opts = parseArgs(argv);
|
|
149
|
+
const positional = opts._;
|
|
150
|
+
const subcommand = positional[0] ?? 'serve';
|
|
151
|
+
const configArg = typeof opts['config'] === 'string' ? opts['config'] : undefined;
|
|
152
|
+
if (opts['help']) {
|
|
153
|
+
stdout(HELP_TEXT);
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
if (opts['version']) {
|
|
157
|
+
stdout(readServerVersion() + '\n');
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
switch (subcommand) {
|
|
161
|
+
case 'serve': {
|
|
162
|
+
const config = await loadConfig(configArg, deps);
|
|
163
|
+
// startServe() blocks until a signal arrives and exits the process.
|
|
164
|
+
await startServe(config, exit);
|
|
165
|
+
break;
|
|
166
|
+
}
|
|
167
|
+
case 'print-token': {
|
|
168
|
+
const config = await loadConfig(configArg, deps).catch(() => null);
|
|
169
|
+
const tokenFile = config
|
|
170
|
+
? config.server.auth.tokenFile
|
|
171
|
+
: path.join(deps.homeDir?.() ?? os.homedir(), '.multi-model', 'auth-token');
|
|
172
|
+
const code = printToken({
|
|
173
|
+
homeDir: deps.homeDir?.() ?? os.homedir(),
|
|
174
|
+
tokenFile,
|
|
175
|
+
env: deps.env?.() ?? process.env,
|
|
176
|
+
stdout: deps.stdout,
|
|
177
|
+
stderr: deps.stderr,
|
|
178
|
+
});
|
|
179
|
+
exit(code);
|
|
180
|
+
break;
|
|
181
|
+
}
|
|
182
|
+
case 'status': {
|
|
183
|
+
const jsonFlag = opts['json'] === true;
|
|
184
|
+
const config = await loadConfig(configArg, deps).catch(() => null);
|
|
185
|
+
const home = deps.homeDir?.() ?? os.homedir();
|
|
186
|
+
const tokenFile = config
|
|
187
|
+
? config.server.auth.tokenFile
|
|
188
|
+
: path.join(home, '.multi-model', 'auth-token');
|
|
189
|
+
const serverUrl = config
|
|
190
|
+
? buildServerUrl(config.server.bind, config.server.port)
|
|
191
|
+
: buildServerUrl('127.0.0.1', 7337);
|
|
192
|
+
const code = await runStatus({
|
|
193
|
+
serverUrl,
|
|
194
|
+
tokenFile,
|
|
195
|
+
json: jsonFlag,
|
|
196
|
+
env: deps.env?.() ?? process.env,
|
|
197
|
+
homeDir: home,
|
|
198
|
+
stdout: deps.stdout,
|
|
199
|
+
stderr: deps.stderr,
|
|
200
|
+
});
|
|
201
|
+
exit(code);
|
|
202
|
+
break;
|
|
203
|
+
}
|
|
204
|
+
case 'install-skill': {
|
|
205
|
+
// Forward all argv tokens that come after the subcommand name.
|
|
206
|
+
// minimist with stopEarly:true would have captured them in opts._, but
|
|
207
|
+
// since we don't use stopEarly we need to find the subcommand boundary
|
|
208
|
+
// in the raw argv array and pass everything after it.
|
|
209
|
+
const subCmdIdx = argv.indexOf('install-skill');
|
|
210
|
+
const subArgv = subCmdIdx >= 0 ? argv.slice(subCmdIdx + 1) : positional.slice(1);
|
|
211
|
+
const code = await installSkillMain({
|
|
212
|
+
argv: subArgv,
|
|
213
|
+
homeDir: deps.homeDir?.() ?? os.homedir(),
|
|
214
|
+
stdout: deps.stdout,
|
|
215
|
+
stderr: deps.stderr,
|
|
216
|
+
});
|
|
217
|
+
exit(code);
|
|
218
|
+
break;
|
|
219
|
+
}
|
|
220
|
+
default: {
|
|
221
|
+
stderr(`Unknown command: ${subcommand}\nRun 'mmagent --help' for usage.\n`);
|
|
222
|
+
exit(1);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
// ── Bootstrap ──────────────────────────────────────────────────────────────
|
|
227
|
+
// Only run main() when this module is executed as the CLI entry point.
|
|
228
|
+
// Tests import main() directly and pass CliDeps.
|
|
229
|
+
function isMain() {
|
|
230
|
+
try {
|
|
231
|
+
const argv1 = process.argv[1];
|
|
232
|
+
if (!argv1)
|
|
233
|
+
return false;
|
|
234
|
+
// Resolve to absolute path to handle relative argv[1], symlinks, and
|
|
235
|
+
// platform-specific path normalization consistently.
|
|
236
|
+
const entryPath = import.meta.url.startsWith('file://')
|
|
237
|
+
? fileURLToPath(import.meta.url)
|
|
238
|
+
: path.resolve(argv1);
|
|
239
|
+
return path.resolve(argv1) === entryPath;
|
|
240
|
+
}
|
|
241
|
+
catch {
|
|
242
|
+
return false;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
if (isMain()) {
|
|
246
|
+
void main().catch((err) => {
|
|
247
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
248
|
+
process.stderr.write(`mmagent: ${msg}\n`);
|
|
249
|
+
process.exit(1);
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
|