@rithamnatani/agentmux 1.5.39
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 +440 -0
- package/dist/clientFilter.d.ts +5 -0
- package/dist/clientFilter.d.ts.map +1 -0
- package/dist/clientFilter.js +31 -0
- package/dist/clientFilter.js.map +1 -0
- package/dist/config.d.ts +28 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +112 -0
- package/dist/config.js.map +1 -0
- package/dist/constants.d.ts +115 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +118 -0
- package/dist/constants.js.map +1 -0
- package/dist/execution.d.ts +23 -0
- package/dist/execution.d.ts.map +1 -0
- package/dist/execution.js +2 -0
- package/dist/execution.js.map +1 -0
- package/dist/httpServer.d.ts +12 -0
- package/dist/httpServer.d.ts.map +1 -0
- package/dist/httpServer.js +323 -0
- package/dist/httpServer.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +98 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts +19 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +172 -0
- package/dist/logger.js.map +1 -0
- package/dist/modelCatalog.d.ts +15 -0
- package/dist/modelCatalog.d.ts.map +1 -0
- package/dist/modelCatalog.generated.json +80 -0
- package/dist/modelCatalog.js +81 -0
- package/dist/modelCatalog.js.map +1 -0
- package/dist/router/config.d.ts +13 -0
- package/dist/router/config.d.ts.map +1 -0
- package/dist/router/config.js +198 -0
- package/dist/router/config.js.map +1 -0
- package/dist/router/defaultConfig.d.ts +13 -0
- package/dist/router/defaultConfig.d.ts.map +1 -0
- package/dist/router/defaultConfig.js +82 -0
- package/dist/router/defaultConfig.js.map +1 -0
- package/dist/router/executor.d.ts +35 -0
- package/dist/router/executor.d.ts.map +1 -0
- package/dist/router/executor.js +189 -0
- package/dist/router/executor.js.map +1 -0
- package/dist/router/modelMetadata.d.ts +5 -0
- package/dist/router/modelMetadata.d.ts.map +1 -0
- package/dist/router/modelMetadata.js +81 -0
- package/dist/router/modelMetadata.js.map +1 -0
- package/dist/router/quota.d.ts +4 -0
- package/dist/router/quota.d.ts.map +1 -0
- package/dist/router/quota.js +5 -0
- package/dist/router/quota.js.map +1 -0
- package/dist/router/router.d.ts +3 -0
- package/dist/router/router.d.ts.map +1 -0
- package/dist/router/router.js +141 -0
- package/dist/router/router.js.map +1 -0
- package/dist/router/types.d.ts +86 -0
- package/dist/router/types.d.ts.map +1 -0
- package/dist/router/types.js +2 -0
- package/dist/router/types.js.map +1 -0
- package/dist/routerConfig.d.ts +14 -0
- package/dist/routerConfig.d.ts.map +1 -0
- package/dist/routerConfig.js +194 -0
- package/dist/routerConfig.js.map +1 -0
- package/dist/serverApp.d.ts +43 -0
- package/dist/serverApp.d.ts.map +1 -0
- package/dist/serverApp.js +618 -0
- package/dist/serverApp.js.map +1 -0
- package/dist/service/bootstrap.d.ts +3 -0
- package/dist/service/bootstrap.d.ts.map +1 -0
- package/dist/service/bootstrap.js +32 -0
- package/dist/service/bootstrap.js.map +1 -0
- package/dist/service/manager.d.ts +6 -0
- package/dist/service/manager.d.ts.map +1 -0
- package/dist/service/manager.js +318 -0
- package/dist/service/manager.js.map +1 -0
- package/dist/service/paths.d.ts +10 -0
- package/dist/service/paths.d.ts.map +1 -0
- package/dist/service/paths.js +57 -0
- package/dist/service/paths.js.map +1 -0
- package/dist/service/renderers.d.ts +7 -0
- package/dist/service/renderers.d.ts.map +1 -0
- package/dist/service/renderers.js +110 -0
- package/dist/service/renderers.js.map +1 -0
- package/dist/service/runtime.d.ts +14 -0
- package/dist/service/runtime.d.ts.map +1 -0
- package/dist/service/runtime.js +129 -0
- package/dist/service/runtime.js.map +1 -0
- package/dist/service/types.d.ts +33 -0
- package/dist/service/types.d.ts.map +1 -0
- package/dist/service/types.js +2 -0
- package/dist/service/types.js.map +1 -0
- package/dist/taskClientPolicy.d.ts +16 -0
- package/dist/taskClientPolicy.d.ts.map +1 -0
- package/dist/taskClientPolicy.js +44 -0
- package/dist/taskClientPolicy.js.map +1 -0
- package/dist/taskStore.d.ts +12 -0
- package/dist/taskStore.d.ts.map +1 -0
- package/dist/taskStore.js +30 -0
- package/dist/taskStore.js.map +1 -0
- package/dist/tierConfig.d.ts +16 -0
- package/dist/tierConfig.d.ts.map +1 -0
- package/dist/tierConfig.js +70 -0
- package/dist/tierConfig.js.map +1 -0
- package/dist/tools/ask-claude.tool.d.ts +3 -0
- package/dist/tools/ask-claude.tool.d.ts.map +1 -0
- package/dist/tools/ask-claude.tool.js +30 -0
- package/dist/tools/ask-claude.tool.js.map +1 -0
- package/dist/tools/ask-codex.tool.d.ts +3 -0
- package/dist/tools/ask-codex.tool.d.ts.map +1 -0
- package/dist/tools/ask-codex.tool.js +29 -0
- package/dist/tools/ask-codex.tool.js.map +1 -0
- package/dist/tools/ask-cursor.tool.d.ts +3 -0
- package/dist/tools/ask-cursor.tool.d.ts.map +1 -0
- package/dist/tools/ask-cursor.tool.js +30 -0
- package/dist/tools/ask-cursor.tool.js.map +1 -0
- package/dist/tools/ask-gemini.tool.d.ts +3 -0
- package/dist/tools/ask-gemini.tool.d.ts.map +1 -0
- package/dist/tools/ask-gemini.tool.js +40 -0
- package/dist/tools/ask-gemini.tool.js.map +1 -0
- package/dist/tools/ask-opencode.tool.d.ts +3 -0
- package/dist/tools/ask-opencode.tool.d.ts.map +1 -0
- package/dist/tools/ask-opencode.tool.js +29 -0
- package/dist/tools/ask-opencode.tool.js.map +1 -0
- package/dist/tools/ask-router.tool.d.ts +20 -0
- package/dist/tools/ask-router.tool.d.ts.map +1 -0
- package/dist/tools/ask-router.tool.js +550 -0
- package/dist/tools/ask-router.tool.js.map +1 -0
- package/dist/tools/fetch-chunk.tool.d.ts +3 -0
- package/dist/tools/fetch-chunk.tool.d.ts.map +1 -0
- package/dist/tools/fetch-chunk.tool.js +58 -0
- package/dist/tools/fetch-chunk.tool.js.map +1 -0
- package/dist/tools/get-run.tool.d.ts +3 -0
- package/dist/tools/get-run.tool.d.ts.map +1 -0
- package/dist/tools/get-run.tool.js +53 -0
- package/dist/tools/get-run.tool.js.map +1 -0
- package/dist/tools/important-read-now.tool.d.ts +3 -0
- package/dist/tools/important-read-now.tool.d.ts.map +1 -0
- package/dist/tools/important-read-now.tool.js +31 -0
- package/dist/tools/important-read-now.tool.js.map +1 -0
- package/dist/tools/index.d.ts +12 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +59 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/opencode-copilot-usage.tool.d.ts +3 -0
- package/dist/tools/opencode-copilot-usage.tool.d.ts.map +1 -0
- package/dist/tools/opencode-copilot-usage.tool.js +85 -0
- package/dist/tools/opencode-copilot-usage.tool.js.map +1 -0
- package/dist/tools/recommend-route.tool.d.ts +3 -0
- package/dist/tools/recommend-route.tool.d.ts.map +1 -0
- package/dist/tools/recommend-route.tool.js +88 -0
- package/dist/tools/recommend-route.tool.js.map +1 -0
- package/dist/tools/registry.d.ts +31 -0
- package/dist/tools/registry.d.ts.map +1 -0
- package/dist/tools/registry.js +105 -0
- package/dist/tools/registry.js.map +1 -0
- package/dist/tools/simple-tools.d.ts +12 -0
- package/dist/tools/simple-tools.d.ts.map +1 -0
- package/dist/tools/simple-tools.js +121 -0
- package/dist/tools/simple-tools.js.map +1 -0
- package/dist/tools/test-tool.example.d.ts +13 -0
- package/dist/tools/test-tool.example.d.ts.map +1 -0
- package/dist/tools/test-tool.example.js +32 -0
- package/dist/tools/test-tool.example.js.map +1 -0
- package/dist/tools/tiered-request.tool.d.ts +3 -0
- package/dist/tools/tiered-request.tool.d.ts.map +1 -0
- package/dist/tools/tiered-request.tool.js +147 -0
- package/dist/tools/tiered-request.tool.js.map +1 -0
- package/dist/utils/changeModeChunker.d.ts +11 -0
- package/dist/utils/changeModeChunker.d.ts.map +1 -0
- package/dist/utils/changeModeChunker.js +89 -0
- package/dist/utils/changeModeChunker.js.map +1 -0
- package/dist/utils/changeModeParser.d.ts +15 -0
- package/dist/utils/changeModeParser.d.ts.map +1 -0
- package/dist/utils/changeModeParser.js +67 -0
- package/dist/utils/changeModeParser.js.map +1 -0
- package/dist/utils/changeModeTranslator.d.ts +8 -0
- package/dist/utils/changeModeTranslator.d.ts.map +1 -0
- package/dist/utils/changeModeTranslator.js +70 -0
- package/dist/utils/changeModeTranslator.js.map +1 -0
- package/dist/utils/chunkCache.d.ts +22 -0
- package/dist/utils/chunkCache.d.ts.map +1 -0
- package/dist/utils/chunkCache.js +147 -0
- package/dist/utils/chunkCache.js.map +1 -0
- package/dist/utils/claudeExecutor.d.ts +3 -0
- package/dist/utils/claudeExecutor.d.ts.map +1 -0
- package/dist/utils/claudeExecutor.js +21 -0
- package/dist/utils/claudeExecutor.js.map +1 -0
- package/dist/utils/cliDetector.d.ts +20 -0
- package/dist/utils/cliDetector.d.ts.map +1 -0
- package/dist/utils/cliDetector.js +95 -0
- package/dist/utils/cliDetector.js.map +1 -0
- package/dist/utils/codexExecutor.d.ts +3 -0
- package/dist/utils/codexExecutor.d.ts.map +1 -0
- package/dist/utils/codexExecutor.js +19 -0
- package/dist/utils/codexExecutor.js.map +1 -0
- package/dist/utils/commandExecutor.d.ts +29 -0
- package/dist/utils/commandExecutor.d.ts.map +1 -0
- package/dist/utils/commandExecutor.js +487 -0
- package/dist/utils/commandExecutor.js.map +1 -0
- package/dist/utils/cursorCli.d.ts +3 -0
- package/dist/utils/cursorCli.d.ts.map +1 -0
- package/dist/utils/cursorCli.js +20 -0
- package/dist/utils/cursorCli.js.map +1 -0
- package/dist/utils/cursorExecutor.d.ts +3 -0
- package/dist/utils/cursorExecutor.d.ts.map +1 -0
- package/dist/utils/cursorExecutor.js +22 -0
- package/dist/utils/cursorExecutor.js.map +1 -0
- package/dist/utils/geminiExecutor.d.ts +4 -0
- package/dist/utils/geminiExecutor.d.ts.map +1 -0
- package/dist/utils/geminiExecutor.js +131 -0
- package/dist/utils/geminiExecutor.js.map +1 -0
- package/dist/utils/githubCli.d.ts +22 -0
- package/dist/utils/githubCli.d.ts.map +1 -0
- package/dist/utils/githubCli.js +131 -0
- package/dist/utils/githubCli.js.map +1 -0
- package/dist/utils/opencodeCatalog.d.ts +33 -0
- package/dist/utils/opencodeCatalog.d.ts.map +1 -0
- package/dist/utils/opencodeCatalog.js +171 -0
- package/dist/utils/opencodeCatalog.js.map +1 -0
- package/dist/utils/opencodeExecutor.d.ts +3 -0
- package/dist/utils/opencodeExecutor.d.ts.map +1 -0
- package/dist/utils/opencodeExecutor.js +16 -0
- package/dist/utils/opencodeExecutor.js.map +1 -0
- package/dist/utils/timeoutManager.d.ts +2 -0
- package/dist/utils/timeoutManager.d.ts.map +1 -0
- package/dist/utils/timeoutManager.js +2 -0
- package/dist/utils/timeoutManager.js.map +1 -0
- package/dist/utils/worktrunkIsolation.d.ts +26 -0
- package/dist/utils/worktrunkIsolation.d.ts.map +1 -0
- package/dist/utils/worktrunkIsolation.js +80 -0
- package/dist/utils/worktrunkIsolation.js.map +1 -0
- package/package.json +72 -0
package/README.md
ADDED
|
@@ -0,0 +1,440 @@
|
|
|
1
|
+
# AgentMux MCP
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@rithamnatani/agentmux)
|
|
4
|
+
[](https://github.com/rithamnatani/agentmux/actions/workflows/tests.yml)
|
|
5
|
+
[](https://github.com/rithamnatani/agentmux/actions/workflows/scan.yml)
|
|
6
|
+
[](https://github.com/rithamnatani/agentmux/releases/latest)
|
|
7
|
+
[](https://www.npmjs.com/package/@rithamnatani/agentmux)
|
|
8
|
+
[](https://www.typescriptlang.org/)
|
|
9
|
+
|
|
10
|
+
**An MCP server that lets Claude, Gemini, Codex, and OpenCode call each other as tools.**
|
|
11
|
+
|
|
12
|
+
```
|
|
13
|
+
Claude: "Hey Gemini, what do you think about this code?"
|
|
14
|
+
Gemini: "It's mass. Let me ask Codex for a second opinion."
|
|
15
|
+
Codex: "You're both wrong. Here's the fix."
|
|
16
|
+
OpenCode: "I checked with three providers. They all agree with Codex."
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## One-Line Install (macOS / Linux)
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
curl -fsSL https://raw.githubusercontent.com/rithamnatani/agentmux/main/install.sh | bash
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Detects which AI CLIs you have installed and configures AgentMux for them automatically.
|
|
28
|
+
|
|
29
|
+
- Claude Code is configured to use a per-user local HTTP service on `127.0.0.1`
|
|
30
|
+
- Gemini CLI, Codex CLI, and OpenCode keep using stdio/local config by default
|
|
31
|
+
- The installer may update client config files on your behalf
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## What It Does
|
|
36
|
+
|
|
37
|
+
AgentMux sits between your AI clients and bridges them via the [Model Context Protocol](https://modelcontextprotocol.io/). Install it once, and whichever AI you're talking to gains the ability to call the others.
|
|
38
|
+
|
|
39
|
+
- **Claude** can ask Gemini, Codex, OpenCode, or Cursor Agent for help
|
|
40
|
+
- **Gemini** can delegate to Claude, Codex, OpenCode, or Cursor Agent
|
|
41
|
+
- **Codex** can consult Claude, Gemini, OpenCode, or Cursor Agent
|
|
42
|
+
- **OpenCode** can call Claude, Gemini, Codex, or Cursor Agent (across 75+ providers)
|
|
43
|
+
- **Cursor** (via MCP) can call the other CLIs; Ask-Cursor is hidden there so the router never delegates back into the same host
|
|
44
|
+
- Each client's own tools are hidden (no talking to yourself, that's weird)
|
|
45
|
+
- Auto-detects which CLIs you have installed — only shows what's available
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## Why AgentMux Exists
|
|
50
|
+
|
|
51
|
+
AgentMux is a hard fork focused on using the AI subscriptions you already pay for as one coordinated coding system.
|
|
52
|
+
|
|
53
|
+
Many developers have access to several capable CLIs at once: ChatGPT/Codex, Gemini, Claude, OpenCode provider accounts, Cursor, Copilot, or student plans. Switching between them by hand is slow and lossy. AgentMux lets one host act as the orchestrator while the other CLIs become callable subagents with isolated worktrees, recoverable run records, and tiered routing.
|
|
54
|
+
|
|
55
|
+
The stdio install paths use `@latest`, so those clients pick up new releases automatically. Claude Code's managed HTTP service intentionally runs from a stable installed runtime instead of a transient `npx` cache; rerun the installer or `agentmux service refresh --configure-claude` after upgrading.
|
|
56
|
+
|
|
57
|
+
The default tiers are intentionally only a starting point. Real setups differ by subscription, quota, client support, local credentials, and model availability, so the router can be overridden with a local JSON config.
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## Prerequisites
|
|
62
|
+
|
|
63
|
+
You need **Node.js >= 20** and at least **one** of these CLIs installed:
|
|
64
|
+
|
|
65
|
+
| CLI | Install |
|
|
66
|
+
|-----|---------|
|
|
67
|
+
| [Claude Code](https://docs.anthropic.com/en/docs/claude-code/overview) | `npm install -g @anthropic-ai/claude-code` |
|
|
68
|
+
| [Gemini CLI](https://github.com/google-gemini/gemini-cli) | `npm install -g @google/gemini-cli` |
|
|
69
|
+
| [Codex CLI](https://github.com/openai/codex) | `npm install -g @openai/codex` |
|
|
70
|
+
| [OpenCode](https://opencode.ai) | `curl -fsSL https://opencode.ai/install | bash` |
|
|
71
|
+
|
|
72
|
+
> AgentMux is most useful with two or more CLIs installed. With only one, the install still works, but there may be nothing to bridge yet.
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## Manual Installation
|
|
77
|
+
|
|
78
|
+
Prefer to install per-client yourself? Each command is one line.
|
|
79
|
+
|
|
80
|
+
### Claude Code
|
|
81
|
+
|
|
82
|
+
Recommended for Claude Code stability:
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
npm install -g @rithamnatani/agentmux
|
|
86
|
+
agentmux service install --configure-claude
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
This installs a per-user background service that listens only on `127.0.0.1`, configures Claude Code to use AgentMux over HTTP, and keeps the underlying server alive even if Claude drops a stdio subprocess.
|
|
90
|
+
|
|
91
|
+
The managed service installs as a per-user login/background service:
|
|
92
|
+
|
|
93
|
+
- macOS: `launchd` LaunchAgent
|
|
94
|
+
- Ubuntu/Debian: `systemd --user`
|
|
95
|
+
- Windows: Scheduled Task at user logon
|
|
96
|
+
|
|
97
|
+
Security model:
|
|
98
|
+
|
|
99
|
+
- Listens only on `127.0.0.1`
|
|
100
|
+
- Uses `Authorization: Bearer <token>` for every HTTP MCP request
|
|
101
|
+
- Stores generated service artifacts in a user-owned service directory
|
|
102
|
+
|
|
103
|
+
Operational notes:
|
|
104
|
+
|
|
105
|
+
- `agentmux service install` refuses transient `npx` runtimes; use a global install or a stable local checkout
|
|
106
|
+
- Generated service state includes an env file you can edit if your local AI CLIs require additional credentials or PATH entries
|
|
107
|
+
- On Linux, the default `systemd --user` service follows your login session; enable `linger` yourself only if you intentionally want it to stay up after logout
|
|
108
|
+
|
|
109
|
+
Legacy stdio installation is still available:
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
claude mcp add --scope user AgentMux -- npx -y @rithamnatani/agentmux@latest
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
<details>
|
|
116
|
+
<summary>Claude Desktop (JSON config)</summary>
|
|
117
|
+
|
|
118
|
+
Add to `~/Library/Application Support/Claude/claude_desktop_config.json` on macOS:
|
|
119
|
+
|
|
120
|
+
```json
|
|
121
|
+
{
|
|
122
|
+
"mcpServers": {
|
|
123
|
+
"AgentMux": {
|
|
124
|
+
"command": "npx",
|
|
125
|
+
"args": ["-y", "@rithamnatani/agentmux@latest"]
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Restart Claude Desktop completely after saving.
|
|
132
|
+
</details>
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
### Gemini CLI
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
gemini mcp add --scope user AgentMux npx -y @rithamnatani/agentmux@latest
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
<details>
|
|
143
|
+
<summary>Manual config (~/.gemini/settings.json)</summary>
|
|
144
|
+
|
|
145
|
+
```json
|
|
146
|
+
{
|
|
147
|
+
"mcpServers": {
|
|
148
|
+
"AgentMux": {
|
|
149
|
+
"command": "npx",
|
|
150
|
+
"args": ["-y", "@rithamnatani/agentmux@latest"]
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
```
|
|
155
|
+
</details>
|
|
156
|
+
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
### Codex CLI
|
|
160
|
+
|
|
161
|
+
```bash
|
|
162
|
+
codex mcp add AgentMux -- npx -y @rithamnatani/agentmux@latest
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
<details>
|
|
166
|
+
<summary>Manual config (~/.codex/config.toml) or pass --mcp-config</summary>
|
|
167
|
+
|
|
168
|
+
```bash
|
|
169
|
+
codex --mcp-config mcp.json
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
Where `mcp.json` contains:
|
|
173
|
+
|
|
174
|
+
```json
|
|
175
|
+
{
|
|
176
|
+
"mcpServers": {
|
|
177
|
+
"AgentMux": {
|
|
178
|
+
"command": "npx",
|
|
179
|
+
"args": ["-y", "@rithamnatani/agentmux@latest"]
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
```
|
|
184
|
+
</details>
|
|
185
|
+
|
|
186
|
+
---
|
|
187
|
+
|
|
188
|
+
### Cursor
|
|
189
|
+
|
|
190
|
+
Use [Cursor MCP](https://cursor.com/docs/mcp) with a stdio server entry in **`~/.cursor/mcp.json`** (Linux/WSL global), **`%USERPROFILE%\.cursor\mcp.json`** (Windows global), or **`.cursor/mcp.json`** (project).
|
|
191
|
+
|
|
192
|
+
**Local checkout** (this repo only; runs the code you just built—`${workspaceFolder}` is the opened project root):
|
|
193
|
+
|
|
194
|
+
```json
|
|
195
|
+
{
|
|
196
|
+
"mcpServers": {
|
|
197
|
+
"AgentMux": {
|
|
198
|
+
"type": "stdio",
|
|
199
|
+
"command": "node",
|
|
200
|
+
"args": ["${workspaceFolder}/dist/index.js"]
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
Run `npm run build` whenever you change TypeScript so `dist/index.js` stays in sync. This repo’s [`.cursor/mcp.json`](.cursor/mcp.json) points at a **local** `dist` build.
|
|
207
|
+
|
|
208
|
+
**Windows Cursor (desktop app) + repo only in WSL:** you do **not** need to copy the tree onto NTFS for MCP to work. Put this in **`%USERPROFILE%\.cursor\mcp.json`** (for example `C:\Users\Admin\.cursor\mcp.json`) so the server starts inside WSL against your Linux checkout:
|
|
209
|
+
|
|
210
|
+
```json
|
|
211
|
+
{
|
|
212
|
+
"mcpServers": {
|
|
213
|
+
"AgentMux": {
|
|
214
|
+
"type": "stdio",
|
|
215
|
+
"command": "wsl.exe",
|
|
216
|
+
"args": ["-e", "node", "/home/rthm/dev/agentmux/dist/index.js"]
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
Default WSL distro must have Node 20+, your CLIs, and a built `dist/` at that path (`wsl -e` runs non-interactively in the default distro).
|
|
223
|
+
|
|
224
|
+
**Your own npm package (optional):** yes, the normal toolchain is `npm login`, change `"name"` in `package.json` to a scope you own (e.g. `@yourname/agentmux`), then `npm publish` from a clean `npm run build`. Cursor can then use `"command": "npx", "args": ["-y", "@yourname/agentmux@latest"]` on any machine without a git checkout. Publishing requires npm credentials; nothing here can log in for you.
|
|
225
|
+
|
|
226
|
+
Node.js 20+ must be on your `PATH`. Install at least one other CLI (Gemini, Codex, OpenCode, Claude, …) so AgentMux registers bridge tools. When the MCP session is hosted by Cursor, **Ask-Cursor** is omitted from the tool list and the smart router skips Cursor-backed candidates so the agent does not spawn a nested Cursor run against itself.
|
|
227
|
+
|
|
228
|
+
**Long-running tools (Ask-*, smart router tiers):** Cursor often enforces a short wait on plain `tools/call`. For the Cursor MCP client, AgentMux **automatically uses MCP task execution** (same as an explicit task request) so work continues in the background and the UI polls for completion instead of hitting that wall. Other hosts are unchanged unless you set `AGENTMUX_AUTO_TASK_CLIENTS` to a comma-separated list of `clientInfo.name` values (use `all` to opt every client in).
|
|
229
|
+
|
|
230
|
+
**WSL vs Windows:** If the Cursor app runs on Windows but your CLIs live in WSL, the MCP subprocess must still reach `node`/`npx` and those binaries—point `command`/`args` at WSL (for example `wsl.exe` plus your Linux command) or open the folder as a [WSL remote workspace](https://cursor.com/docs) so stdio runs in Linux.
|
|
231
|
+
|
|
232
|
+
**Router tiers:** AgentMux ships with default `Ask-Trivial`, `Ask-Low`, `Ask-Medium`, `Ask-High`, `Ask-Crucial`, and huge-context tiers, but those defaults are not meant to be universal. Set `AGENTMUX_ROUTER_CONFIG` to a JSON file to override any tier with the models and CLIs available in your own subscriptions.
|
|
233
|
+
|
|
234
|
+
```json
|
|
235
|
+
{
|
|
236
|
+
"medium": [
|
|
237
|
+
{
|
|
238
|
+
"label": "My OpenCode medium model",
|
|
239
|
+
"toolName": "Ask-OpenCode",
|
|
240
|
+
"backend": "opencode",
|
|
241
|
+
"model": "provider/model-name",
|
|
242
|
+
"extraArgs": { "variant": "xhigh" }
|
|
243
|
+
},
|
|
244
|
+
{
|
|
245
|
+
"label": "Gemini fallback",
|
|
246
|
+
"toolName": "Ask-Gemini",
|
|
247
|
+
"backend": "gemini",
|
|
248
|
+
"model": "gemini-3.1-pro-preview"
|
|
249
|
+
}
|
|
250
|
+
]
|
|
251
|
+
}
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
---
|
|
255
|
+
|
|
256
|
+
### OpenCode
|
|
257
|
+
|
|
258
|
+
OpenCode's `mcp add` command is interactive, so add AgentMux to `~/.config/opencode/opencode.json` directly:
|
|
259
|
+
|
|
260
|
+
```json
|
|
261
|
+
{
|
|
262
|
+
"mcp": {
|
|
263
|
+
"AgentMux": {
|
|
264
|
+
"type": "local",
|
|
265
|
+
"command": ["npx", "-y", "@rithamnatani/agentmux@latest"]
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
If the file already exists, merge the `"AgentMux"` entry into the existing `"mcp"` object.
|
|
272
|
+
|
|
273
|
+
---
|
|
274
|
+
|
|
275
|
+
### Any Other MCP Client
|
|
276
|
+
|
|
277
|
+
AgentMux supports both stdio and Streamable HTTP.
|
|
278
|
+
|
|
279
|
+
For stdio-capable clients, point them at:
|
|
280
|
+
|
|
281
|
+
```
|
|
282
|
+
npx -y @rithamnatani/agentmux@latest
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
For a managed local HTTP service, install AgentMux globally and run:
|
|
286
|
+
|
|
287
|
+
```bash
|
|
288
|
+
agentmux service install
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
The service listens on `127.0.0.1` only and exposes `/mcp` plus `/health`.
|
|
292
|
+
|
|
293
|
+
---
|
|
294
|
+
|
|
295
|
+
## Available Tools
|
|
296
|
+
|
|
297
|
+
Once connected, your AI client gains access to tools for the *other* CLIs (never its own):
|
|
298
|
+
|
|
299
|
+
| Tool | Description |
|
|
300
|
+
|------|-------------|
|
|
301
|
+
| `List-Gemini-Models` | List available Gemini models and their strengths |
|
|
302
|
+
| `Ask-Gemini` | Ask-Gemini a question or give it a task |
|
|
303
|
+
| `Fetch-Chunk` | Retrieve chunked responses from Gemini |
|
|
304
|
+
| `Gemini-Help` | Get Gemini CLI help info |
|
|
305
|
+
| `List-Codex-Models` | List available Codex models |
|
|
306
|
+
| `Ask-Codex` | Ask-Codex a question or give it a task |
|
|
307
|
+
| `Codex-Help` | Get Codex CLI help info |
|
|
308
|
+
| `List-Claude-Models` | List available Claude models |
|
|
309
|
+
| `Ask-Claude` | Ask-Claude a question or give it a task |
|
|
310
|
+
| `Claude-Help` | Get Claude Code CLI help info |
|
|
311
|
+
| `List-OpenCode-Models` | List available OpenCode models from all configured providers |
|
|
312
|
+
| `Ask-OpenCode` | Ask-OpenCode a question or give it a task |
|
|
313
|
+
| `OpenCode-Help` | Get OpenCode CLI help info |
|
|
314
|
+
|
|
315
|
+
---
|
|
316
|
+
|
|
317
|
+
## Task-Capable Ask Tools
|
|
318
|
+
|
|
319
|
+
The `Ask-*` tools still work as normal synchronous MCP tools, but they now also advertise optional task-based execution for MCP clients that support tasks.
|
|
320
|
+
|
|
321
|
+
- Task-capable clients can run long `Ask-*` calls using MCP tasks to avoid long blocking tool requests
|
|
322
|
+
- Older clients keep using the same `Ask-*` tools synchronously with no config changes
|
|
323
|
+
- `List-*`, `*-Help`, and `Fetch-Chunk` remain normal synchronous tools
|
|
324
|
+
|
|
325
|
+
---
|
|
326
|
+
|
|
327
|
+
## Usage Examples
|
|
328
|
+
|
|
329
|
+
Once installed, just talk naturally to your AI:
|
|
330
|
+
|
|
331
|
+
```
|
|
332
|
+
"Ask-Gemini what it thinks about this architecture"
|
|
333
|
+
"Have Codex review this function for performance issues"
|
|
334
|
+
"Get Claude's opinion on this error message"
|
|
335
|
+
"Use OpenCode to get a second opinion from Llama"
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
Or get a second opinion on anything:
|
|
339
|
+
|
|
340
|
+
```
|
|
341
|
+
"I want three perspectives on how to refactor this module —
|
|
342
|
+
ask Gemini and Codex what they'd do differently"
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
---
|
|
346
|
+
|
|
347
|
+
## How It Works
|
|
348
|
+
|
|
349
|
+
```
|
|
350
|
+
┌─────────────┐ MCP (stdio) ┌──────────────┐ CLI calls ┌─────────────┐
|
|
351
|
+
│ Your AI │ ◄──────────────────► │ AgentMux │ ───────────────► │ Other AIs │
|
|
352
|
+
│ Client │ │ server │ │ (CLI tools) │
|
|
353
|
+
└─────────────┘ └──────────────┘ └─────────────┘
|
|
354
|
+
|
|
355
|
+
1. Your AI client connects to AgentMux via MCP
|
|
356
|
+
2. AgentMux detects which CLIs are installed on your system
|
|
357
|
+
3. It registers tools for the OTHER clients (hides tools for the calling client)
|
|
358
|
+
4. When a tool is called, AgentMux executes the corresponding CLI command
|
|
359
|
+
5. Results flow back through MCP to your AI client
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
For Claude Code, AgentMux can also run as a local background HTTP service:
|
|
363
|
+
|
|
364
|
+
```
|
|
365
|
+
┌─────────────┐ MCP (HTTP) ┌──────────────┐ CLI calls ┌─────────────┐
|
|
366
|
+
│ Claude Code │ ◄──────────────────► │ AgentMux │ ───────────────► │ Other AIs │
|
|
367
|
+
│ Client │ 127.0.0.1 only │ service │ │ (CLI tools) │
|
|
368
|
+
└─────────────┘ └──────────────┘ └─────────────┘
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
---
|
|
372
|
+
|
|
373
|
+
## Troubleshooting
|
|
374
|
+
|
|
375
|
+
**"No usable AI CLIs detected"**
|
|
376
|
+
Make sure at least one other CLI is installed and on your PATH:
|
|
377
|
+
```bash
|
|
378
|
+
which gemini && which codex && which claude && which opencode
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
**No tools showing up?**
|
|
382
|
+
If only your own CLI is installed, AgentMux hides it (no self-calls). Install a *different* CLI to enable cross-model collaboration.
|
|
383
|
+
|
|
384
|
+
**MCP server not responding?**
|
|
385
|
+
1. Check that Node.js >= 20 is installed
|
|
386
|
+
2. Run `npx -y @rithamnatani/agentmux@latest` directly to see if the stdio server starts
|
|
387
|
+
3. Restart your AI client completely
|
|
388
|
+
|
|
389
|
+
**Claude Code disconnecting after successful calls?**
|
|
390
|
+
Use the managed background service instead of the legacy stdio integration:
|
|
391
|
+
|
|
392
|
+
```bash
|
|
393
|
+
npm install -g @rithamnatani/agentmux
|
|
394
|
+
agentmux service install --configure-claude
|
|
395
|
+
agentmux service doctor
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
Helpful service commands:
|
|
399
|
+
|
|
400
|
+
- `agentmux service status`
|
|
401
|
+
- `agentmux service doctor`
|
|
402
|
+
- `agentmux service logs`
|
|
403
|
+
- `agentmux service refresh`
|
|
404
|
+
- `agentmux service uninstall`
|
|
405
|
+
|
|
406
|
+
**Need to tune timeouts or cleanup behavior?**
|
|
407
|
+
AgentMux supports these optional environment variables:
|
|
408
|
+
|
|
409
|
+
- `AGENTMUX_TRANSPORT` (`stdio` or `http`)
|
|
410
|
+
- `AGENTMUX_ASK_TIMEOUT_MS`
|
|
411
|
+
- `AGENTMUX_HELP_TIMEOUT_MS`
|
|
412
|
+
- `AGENTMUX_CLI_DETECT_TIMEOUT_MS`
|
|
413
|
+
- `AGENTMUX_KILL_GRACE_MS`
|
|
414
|
+
- `AGENTMUX_HTTP_HOST` (defaults to `127.0.0.1`)
|
|
415
|
+
- `AGENTMUX_HTTP_PORT` (defaults to `37420`)
|
|
416
|
+
- `AGENTMUX_HTTP_PATH` (defaults to `/mcp`)
|
|
417
|
+
- `AGENTMUX_HTTP_AUTH_TOKEN` (required for direct HTTP mode)
|
|
418
|
+
- `AGENTMUX_HTTP_SESSION_IDLE_MS`
|
|
419
|
+
- `AGENTMUX_LOG_PATH` (defaults to `~/.agentmux/logs/agentmux.log`)
|
|
420
|
+
- `AGENTMUX_LOG_LEVEL` (`error`, `info`, or `debug`; defaults to `debug` for the file log)
|
|
421
|
+
- `AGENTMUX_STDERR_LOG_LEVEL` (`silent`, `error`, `info`, or `debug`; defaults to `error`)
|
|
422
|
+
- `AGENTMUX_SERVICE_ROOT_DIR`
|
|
423
|
+
- `AGENTMUX_SERVICE_LOG_PATH`
|
|
424
|
+
- `AGENTMUX_SERVICE_ENV_PATH`
|
|
425
|
+
- `AGENTMUX_SERVICE_MANIFEST_PATH`
|
|
426
|
+
- `AGENTMUX_ROUTER_CONFIG` (JSON file overriding router tier candidates)
|
|
427
|
+
|
|
428
|
+
The server writes structured JSON-line logs to a single file destination, rotates them automatically for long-running service mode, and includes full prompt bodies for `Ask-*` requests so disconnects and crashes can be reconstructed after the fact.
|
|
429
|
+
|
|
430
|
+
---
|
|
431
|
+
|
|
432
|
+
## Development
|
|
433
|
+
|
|
434
|
+
```bash
|
|
435
|
+
git clone https://github.com/rithamnatani/agentmux.git
|
|
436
|
+
cd agentmux
|
|
437
|
+
npm install
|
|
438
|
+
npm run build
|
|
439
|
+
npm run dev
|
|
440
|
+
```
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { UnifiedTool } from './tools/registry.js';
|
|
2
|
+
export declare function getExcludedCategory(clientName: string | undefined): UnifiedTool['category'] | undefined;
|
|
3
|
+
export declare function filterToolsForClient(tools: UnifiedTool[], clientName: string | undefined): UnifiedTool[];
|
|
4
|
+
export declare function isToolBlockedForClient(tool: UnifiedTool | undefined, clientName: string | undefined): boolean;
|
|
5
|
+
//# sourceMappingURL=clientFilter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clientFilter.d.ts","sourceRoot":"","sources":["../src/clientFilter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAiBlD,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,GAAG,WAAW,CAAC,UAAU,CAAC,GAAG,SAAS,CAGvG;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,WAAW,EAAE,EAAE,UAAU,EAAE,MAAM,GAAG,SAAS,GAAG,WAAW,EAAE,CAKxG;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,WAAW,GAAG,SAAS,EAAE,UAAU,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAI7G"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Client-based tool filtering: hide a client's own tools
|
|
3
|
+
* (no point asking yourself for a second opinion).
|
|
4
|
+
*/
|
|
5
|
+
const CLIENT_EXCLUSIONS = {
|
|
6
|
+
'claude-code': 'claude',
|
|
7
|
+
'codex-mcp-client': 'codex',
|
|
8
|
+
'gemini-cli-mcp-client': 'gemini',
|
|
9
|
+
'opencode': 'opencode',
|
|
10
|
+
/** Cursor Agent MCP (`clientInfo.name` from initialize). */
|
|
11
|
+
'Cursor': 'cursor',
|
|
12
|
+
'cursor': 'cursor',
|
|
13
|
+
};
|
|
14
|
+
export function getExcludedCategory(clientName) {
|
|
15
|
+
if (!clientName)
|
|
16
|
+
return undefined;
|
|
17
|
+
return CLIENT_EXCLUSIONS[clientName] ?? CLIENT_EXCLUSIONS[clientName.toLowerCase()];
|
|
18
|
+
}
|
|
19
|
+
export function filterToolsForClient(tools, clientName) {
|
|
20
|
+
const excluded = getExcludedCategory(clientName);
|
|
21
|
+
if (!excluded)
|
|
22
|
+
return tools;
|
|
23
|
+
return tools.filter(t => t.category !== excluded);
|
|
24
|
+
}
|
|
25
|
+
export function isToolBlockedForClient(tool, clientName) {
|
|
26
|
+
if (!tool)
|
|
27
|
+
return false;
|
|
28
|
+
const excluded = getExcludedCategory(clientName);
|
|
29
|
+
return excluded !== undefined && tool.category === excluded;
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=clientFilter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clientFilter.js","sourceRoot":"","sources":["../src/clientFilter.ts"],"names":[],"mappings":"AAEA;;;GAGG;AAEH,MAAM,iBAAiB,GAA4C;IACjE,aAAa,EAAa,QAAQ;IAClC,kBAAkB,EAAQ,OAAO;IACjC,uBAAuB,EAAG,QAAQ;IAClC,UAAU,EAAgB,UAAU;IACpC,4DAA4D;IAC5D,QAAQ,EAAkB,QAAQ;IAClC,QAAQ,EAAkB,QAAQ;CACnC,CAAC;AAEF,MAAM,UAAU,mBAAmB,CAAC,UAA8B;IAChE,IAAI,CAAC,UAAU;QAAE,OAAO,SAAS,CAAC;IAClC,OAAO,iBAAiB,CAAC,UAAU,CAAC,IAAI,iBAAiB,CAAC,UAAU,CAAC,WAAW,EAAE,CAAC,CAAC;AACtF,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,KAAoB,EAAE,UAA8B;IACvF,MAAM,QAAQ,GAAG,mBAAmB,CAAC,UAAU,CAAC,CAAC;IACjD,IAAI,CAAC,QAAQ;QAAE,OAAO,KAAK,CAAC;IAE5B,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC;AACpD,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,IAA6B,EAAE,UAA8B;IAClG,IAAI,CAAC,IAAI;QAAE,OAAO,KAAK,CAAC;IACxB,MAAM,QAAQ,GAAG,mBAAmB,CAAC,UAAU,CAAC,CAAC;IACjD,OAAO,QAAQ,KAAK,SAAS,IAAI,IAAI,CAAC,QAAQ,KAAK,QAAQ,CAAC;AAC9D,CAAC"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export type MultiCliLogLevel = 'error' | 'info' | 'debug';
|
|
2
|
+
export type MultiCliStderrLogLevel = MultiCliLogLevel | 'silent';
|
|
3
|
+
export type MultiCliTransport = 'stdio' | 'http';
|
|
4
|
+
export interface MultiCliConfig {
|
|
5
|
+
transport: MultiCliTransport;
|
|
6
|
+
askTimeoutMs: number;
|
|
7
|
+
helpTimeoutMs: number;
|
|
8
|
+
cliDetectTimeoutMs: number;
|
|
9
|
+
killGraceMs: number;
|
|
10
|
+
taskTtlMs: number;
|
|
11
|
+
taskPollIntervalMs: number;
|
|
12
|
+
progressIdleHeartbeatMs: number;
|
|
13
|
+
progressThrottleMs: number;
|
|
14
|
+
httpHost: string;
|
|
15
|
+
httpPort: number;
|
|
16
|
+
httpPath: string;
|
|
17
|
+
httpAuthToken?: string;
|
|
18
|
+
httpSessionIdleMs: number;
|
|
19
|
+
logPath: string;
|
|
20
|
+
logLevel: MultiCliLogLevel;
|
|
21
|
+
stderrLogLevel: MultiCliStderrLogLevel;
|
|
22
|
+
serviceRootDir: string;
|
|
23
|
+
serviceLogPath: string;
|
|
24
|
+
serviceEnvPath: string;
|
|
25
|
+
serviceManifestPath: string;
|
|
26
|
+
}
|
|
27
|
+
export declare function loadConfig(env?: NodeJS.ProcessEnv): MultiCliConfig;
|
|
28
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,gBAAgB,GAAG,OAAO,GAAG,MAAM,GAAG,OAAO,CAAC;AAC1D,MAAM,MAAM,sBAAsB,GAAG,gBAAgB,GAAG,QAAQ,CAAC;AACjE,MAAM,MAAM,iBAAiB,GAAG,OAAO,GAAG,MAAM,CAAC;AAsBjD,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,iBAAiB,CAAC;IAC7B,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,uBAAuB,EAAE,MAAM,CAAC;IAChC,kBAAkB,EAAE,MAAM,CAAC;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,cAAc,EAAE,sBAAsB,CAAC;IACvC,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,mBAAmB,EAAE,MAAM,CAAC;CAC7B;AAmGD,wBAAgB,UAAU,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,cAAc,CAkD/E"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import os from 'node:os';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
function getDefaultServiceRootDir(platform = process.platform, env = process.env) {
|
|
4
|
+
switch (platform) {
|
|
5
|
+
case 'darwin':
|
|
6
|
+
return path.join(os.homedir(), 'Library', 'Application Support', 'AgentMux');
|
|
7
|
+
case 'win32':
|
|
8
|
+
return path.join(env.LOCALAPPDATA ?? path.join(os.homedir(), 'AppData', 'Local'), 'AgentMux');
|
|
9
|
+
default:
|
|
10
|
+
return path.join(env.XDG_CONFIG_HOME ?? path.join(os.homedir(), '.config'), 'agentmux');
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
const DEFAULTS = {
|
|
14
|
+
transport: 'stdio',
|
|
15
|
+
askTimeoutMs: 15 * 60 * 1000,
|
|
16
|
+
helpTimeoutMs: 30 * 1000,
|
|
17
|
+
cliDetectTimeoutMs: 5 * 1000,
|
|
18
|
+
killGraceMs: 5 * 1000,
|
|
19
|
+
taskTtlMs: 60 * 60 * 1000,
|
|
20
|
+
taskPollIntervalMs: 1000,
|
|
21
|
+
progressIdleHeartbeatMs: 10 * 1000,
|
|
22
|
+
progressThrottleMs: 1000,
|
|
23
|
+
httpHost: '127.0.0.1',
|
|
24
|
+
httpPort: 37420,
|
|
25
|
+
httpPath: '/mcp',
|
|
26
|
+
httpAuthToken: undefined,
|
|
27
|
+
httpSessionIdleMs: 30 * 60 * 1000,
|
|
28
|
+
logPath: path.join(os.homedir(), '.agentmux', 'logs', 'agentmux.log'),
|
|
29
|
+
logLevel: 'debug',
|
|
30
|
+
stderrLogLevel: 'error',
|
|
31
|
+
serviceRootDir: getDefaultServiceRootDir(),
|
|
32
|
+
serviceLogPath: path.join(getDefaultServiceRootDir(), 'logs', 'service.log'),
|
|
33
|
+
serviceEnvPath: path.join(getDefaultServiceRootDir(), 'env'),
|
|
34
|
+
serviceManifestPath: path.join(getDefaultServiceRootDir(), 'manifest.json'),
|
|
35
|
+
};
|
|
36
|
+
function parsePositiveInt(value, fallback) {
|
|
37
|
+
if (!value)
|
|
38
|
+
return fallback;
|
|
39
|
+
const parsed = Number.parseInt(value, 10);
|
|
40
|
+
if (!Number.isFinite(parsed) || parsed <= 0) {
|
|
41
|
+
return fallback;
|
|
42
|
+
}
|
|
43
|
+
return parsed;
|
|
44
|
+
}
|
|
45
|
+
function parseLogLevel(value, fallback) {
|
|
46
|
+
switch (value) {
|
|
47
|
+
case 'error':
|
|
48
|
+
case 'info':
|
|
49
|
+
case 'debug':
|
|
50
|
+
return value;
|
|
51
|
+
default:
|
|
52
|
+
return fallback;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
function parseTransport(value, fallback) {
|
|
56
|
+
switch (value) {
|
|
57
|
+
case 'stdio':
|
|
58
|
+
case 'http':
|
|
59
|
+
return value;
|
|
60
|
+
default:
|
|
61
|
+
return fallback;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
function parseStderrLogLevel(value, fallback) {
|
|
65
|
+
switch (value) {
|
|
66
|
+
case 'error':
|
|
67
|
+
case 'info':
|
|
68
|
+
case 'debug':
|
|
69
|
+
case 'silent':
|
|
70
|
+
return value;
|
|
71
|
+
default:
|
|
72
|
+
return fallback;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
function parseString(value, fallback) {
|
|
76
|
+
if (!value) {
|
|
77
|
+
return fallback;
|
|
78
|
+
}
|
|
79
|
+
const trimmed = value.trim();
|
|
80
|
+
return trimmed || fallback;
|
|
81
|
+
}
|
|
82
|
+
function normalizeHttpPath(value, fallback) {
|
|
83
|
+
const parsed = parseString(value, fallback);
|
|
84
|
+
return parsed.startsWith('/') ? parsed : `/${parsed}`;
|
|
85
|
+
}
|
|
86
|
+
export function loadConfig(env = process.env) {
|
|
87
|
+
const serviceRootDir = parseString(env.AGENTMUX_SERVICE_ROOT_DIR, DEFAULTS.serviceRootDir);
|
|
88
|
+
return {
|
|
89
|
+
transport: parseTransport(env.AGENTMUX_TRANSPORT, DEFAULTS.transport),
|
|
90
|
+
askTimeoutMs: parsePositiveInt(env.AGENTMUX_ASK_TIMEOUT_MS, DEFAULTS.askTimeoutMs),
|
|
91
|
+
helpTimeoutMs: parsePositiveInt(env.AGENTMUX_HELP_TIMEOUT_MS, DEFAULTS.helpTimeoutMs),
|
|
92
|
+
cliDetectTimeoutMs: parsePositiveInt(env.AGENTMUX_CLI_DETECT_TIMEOUT_MS, DEFAULTS.cliDetectTimeoutMs),
|
|
93
|
+
killGraceMs: parsePositiveInt(env.AGENTMUX_KILL_GRACE_MS, DEFAULTS.killGraceMs),
|
|
94
|
+
taskTtlMs: parsePositiveInt(env.AGENTMUX_TASK_TTL_MS, DEFAULTS.taskTtlMs),
|
|
95
|
+
taskPollIntervalMs: parsePositiveInt(env.AGENTMUX_TASK_POLL_INTERVAL_MS, DEFAULTS.taskPollIntervalMs),
|
|
96
|
+
progressIdleHeartbeatMs: parsePositiveInt(env.AGENTMUX_PROGRESS_IDLE_HEARTBEAT_MS, DEFAULTS.progressIdleHeartbeatMs),
|
|
97
|
+
progressThrottleMs: parsePositiveInt(env.AGENTMUX_PROGRESS_THROTTLE_MS, DEFAULTS.progressThrottleMs),
|
|
98
|
+
httpHost: parseString(env.AGENTMUX_HTTP_HOST, DEFAULTS.httpHost),
|
|
99
|
+
httpPort: parsePositiveInt(env.AGENTMUX_HTTP_PORT, DEFAULTS.httpPort),
|
|
100
|
+
httpPath: normalizeHttpPath(env.AGENTMUX_HTTP_PATH, DEFAULTS.httpPath),
|
|
101
|
+
httpAuthToken: env.AGENTMUX_HTTP_AUTH_TOKEN?.trim() || DEFAULTS.httpAuthToken,
|
|
102
|
+
httpSessionIdleMs: parsePositiveInt(env.AGENTMUX_HTTP_SESSION_IDLE_MS, DEFAULTS.httpSessionIdleMs),
|
|
103
|
+
logPath: parseString(env.AGENTMUX_LOG_PATH, DEFAULTS.logPath),
|
|
104
|
+
logLevel: parseLogLevel(env.AGENTMUX_LOG_LEVEL, DEFAULTS.logLevel),
|
|
105
|
+
stderrLogLevel: parseStderrLogLevel(env.AGENTMUX_STDERR_LOG_LEVEL, DEFAULTS.stderrLogLevel),
|
|
106
|
+
serviceRootDir,
|
|
107
|
+
serviceLogPath: parseString(env.AGENTMUX_SERVICE_LOG_PATH, path.join(serviceRootDir, 'logs', 'service.log')),
|
|
108
|
+
serviceEnvPath: parseString(env.AGENTMUX_SERVICE_ENV_PATH, path.join(serviceRootDir, 'env')),
|
|
109
|
+
serviceManifestPath: parseString(env.AGENTMUX_SERVICE_MANIFEST_PATH ?? env.AGENTMUX_SERVICE_RUNTIME_PATH, path.join(serviceRootDir, 'manifest.json')),
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|