ai-cli-mcp 2.5.0 → 2.7.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/CHANGELOG.md +14 -0
- package/CONTRIBUTING.md +10 -0
- package/README.ja.md +5 -7
- package/README.md +5 -145
- package/dist/__tests__/cli-builder.test.js +278 -0
- package/dist/__tests__/server.test.js +1 -1
- package/dist/cli-builder.js +145 -0
- package/dist/cli-parse.js +85 -0
- package/dist/cli.js +111 -0
- package/dist/server.js +27 -143
- package/docs/development.md +156 -0
- package/package.json +4 -2
- package/src/__tests__/cli-builder.test.ts +345 -0
- package/src/__tests__/server.test.ts +1 -1
- package/src/cli-builder.ts +190 -0
- package/src/cli-parse.ts +96 -0
- package/src/cli.ts +121 -0
- package/src/server.ts +27 -190
- package/AGENT.md +0 -57
- package/RELEASE.md +0 -74
- package/print-eslint-config.js +0 -3
- package/start.bat +0 -9
- package/start.sh +0 -21
- package/test-standalone.js +0 -5877
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
# [2.7.0](https://github.com/mkXultra/claude-code-mcp/compare/v2.6.0...v2.7.0) (2026-03-01)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Features
|
|
5
|
+
|
|
6
|
+
* CLIラッパーとパーサーの追加(cli.run, cli.run.parse) ([330eacf](https://github.com/mkXultra/claude-code-mcp/commit/330eacf26e03484b389438522886448882f58289))
|
|
7
|
+
|
|
8
|
+
# [2.6.0](https://github.com/mkXultra/claude-code-mcp/compare/v2.5.0...v2.6.0) (2026-02-09)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Features
|
|
12
|
+
|
|
13
|
+
* update model support (gpt-5.3-codex, sonnet[1m], opusplan) and refactor README ([eb6574d](https://github.com/mkXultra/claude-code-mcp/commit/eb6574d3760269d4be96cd934bc03d94ccb3801f))
|
|
14
|
+
|
|
1
15
|
# [2.5.0](https://github.com/mkXultra/claude-code-mcp/compare/v2.4.0...v2.5.0) (2026-01-24)
|
|
2
16
|
|
|
3
17
|
|
package/CONTRIBUTING.md
CHANGED
|
@@ -38,6 +38,16 @@ npm run build
|
|
|
38
38
|
npx @modelcontextprotocol/inspector node dist/server.js
|
|
39
39
|
```
|
|
40
40
|
|
|
41
|
+
## CLI Direct Execution
|
|
42
|
+
|
|
43
|
+
Run AI CLI tools directly from the terminal (foreground, no MCP server):
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
npm run -s cli.run -- --model sonnet --workFolder /tmp --prompt "hello"
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
See [docs/development.md](docs/development.md#cli-direct-execution-clirun) for full options.
|
|
50
|
+
|
|
41
51
|
## Local Development with npm link
|
|
42
52
|
|
|
43
53
|
```bash
|
package/README.ja.md
CHANGED
|
@@ -9,8 +9,6 @@ AI CLIツール(Claude, Codex, Gemini)をバックグラウンドプロセ
|
|
|
9
9
|
|
|
10
10
|
Cursorなどのエディタが、複雑な手順を伴う編集や操作に苦戦していることに気づいたことはありませんか?このサーバーは、強力な統合 `run` ツールを提供し、複数のAIエージェントを活用してコーディングタスクをより効果的に処理できるようにします。
|
|
11
11
|
|
|
12
|
-
<img src="assets/screenshot.png" width="300" alt="Screenshot">
|
|
13
|
-
|
|
14
12
|
## 概要
|
|
15
13
|
|
|
16
14
|
このMCPサーバーは、LLMがAI CLIツールと対話するためのツールを提供します。MCPクライアントと統合することで、LLMは以下のことが可能になります:
|
|
@@ -19,8 +17,8 @@ Cursorなどのエディタが、複雑な手順を伴う編集や操作に苦
|
|
|
19
17
|
- 自動承認モードでCodex CLIを実行(`--full-auto` を使用)
|
|
20
18
|
- 自動承認モードでGemini CLIを実行(`-y` を使用)
|
|
21
19
|
- 複数のAIモデルのサポート:
|
|
22
|
-
- Claude (sonnet, opus, haiku)
|
|
23
|
-
- Codex (gpt-5.2-codex, gpt-5.1-codex-mini, gpt-5.1-codex-max, など)
|
|
20
|
+
- Claude (sonnet, sonnet[1m], opus, opusplan, haiku)
|
|
21
|
+
- Codex (gpt-5.3-codex, gpt-5.2-codex, gpt-5.1-codex-mini, gpt-5.1-codex-max, など)
|
|
24
22
|
- Gemini (gemini-2.5-pro, gemini-2.5-flash, gemini-3-pro-preview, gemini-3-flash-preview)
|
|
25
23
|
- PID追跡によるバックグラウンドプロセスの管理
|
|
26
24
|
- ツールからの構造化された出力の解析と返却
|
|
@@ -134,10 +132,10 @@ Claude CLI、Codex CLI、またはGemini CLIを使用してプロンプトを実
|
|
|
134
132
|
- `workFolder` (string, 必須): CLIを実行する作業ディレクトリ。絶対パスである必要があります。
|
|
135
133
|
- **モデル (Models):**
|
|
136
134
|
- **Ultra エイリアス:** `claude-ultra`, `codex-ultra` (自動的に high-reasoning に設定), `gemini-ultra`
|
|
137
|
-
- Claude: `sonnet`, `opus`, `haiku`
|
|
138
|
-
- Codex: `gpt-5.2-codex`, `gpt-5.1-codex-mini`, `gpt-5.1-codex-max`, `gpt-5.2`, `gpt-5.1`, `gpt-5`
|
|
135
|
+
- Claude: `sonnet`, `sonnet[1m]`, `opus`, `opusplan`, `haiku`
|
|
136
|
+
- Codex: `gpt-5.3-codex`, `gpt-5.2-codex`, `gpt-5.1-codex-mini`, `gpt-5.1-codex-max`, `gpt-5.2`, `gpt-5.1`, `gpt-5`
|
|
139
137
|
- Gemini: `gemini-2.5-pro`, `gemini-2.5-flash`, `gemini-3-pro-preview`, `gemini-3-flash-preview`
|
|
140
|
-
- `reasoning_effort` (string, 任意): Codex専用。`model_reasoning_effort` を設定します(許容値: "low", "medium", "high")。
|
|
138
|
+
- `reasoning_effort` (string, 任意): Codex専用。`model_reasoning_effort` を設定します(許容値: "low", "medium", "high", "xhigh")。
|
|
141
139
|
- `session_id` (string, 任意): 以前のセッションを再開するためのセッションID。対応モデル: haiku, sonnet, opus, gemini-2.5-pro, gemini-2.5-flash, gemini-3-pro-preview, gemini-3-flash-preview。
|
|
142
140
|
|
|
143
141
|
### `wait`
|
package/README.md
CHANGED
|
@@ -11,8 +11,6 @@ An MCP (Model Context Protocol) server that allows running AI CLI tools (Claude,
|
|
|
11
11
|
|
|
12
12
|
Did you notice that Cursor sometimes struggles with complex, multi-step edits or operations? This server, with its powerful unified `run` tool, enables multiple AI agents to handle your coding tasks more effectively.
|
|
13
13
|
|
|
14
|
-
<img src="assets/screenshot.png" width="300" alt="Screenshot">
|
|
15
|
-
|
|
16
14
|
## Overview
|
|
17
15
|
|
|
18
16
|
This MCP server provides tools that can be used by LLMs to interact with AI CLI tools. When integrated with MCP clients, it allows LLMs to:
|
|
@@ -20,7 +18,7 @@ This MCP server provides tools that can be used by LLMs to interact with AI CLI
|
|
|
20
18
|
- Run Claude CLI with all permissions bypassed (using `--dangerously-skip-permissions`)
|
|
21
19
|
- Execute Codex CLI with automatic approval mode (using `--full-auto`)
|
|
22
20
|
- Execute Gemini CLI with automatic approval mode (using `-y`)
|
|
23
|
-
- Support multiple AI models: Claude (sonnet, opus, haiku), Codex (gpt-5.2-codex, gpt-5.1-codex-mini, gpt-5.1-codex-max, gpt-5.2, gpt-5.1, gpt-5.1-codex, gpt-5-codex, gpt-5-codex-mini, gpt-5), and Gemini (gemini-2.5-pro, gemini-2.5-flash, gemini-3-pro-preview, gemini-3-flash-preview)
|
|
21
|
+
- Support multiple AI models: Claude (sonnet, sonnet[1m], opus, opusplan, haiku), Codex (gpt-5.3-codex, gpt-5.2-codex, gpt-5.1-codex-mini, gpt-5.1-codex-max, gpt-5.2, gpt-5.1, gpt-5.1-codex, gpt-5-codex, gpt-5-codex-mini, gpt-5), and Gemini (gemini-2.5-pro, gemini-2.5-flash, gemini-3-pro-preview, gemini-3-flash-preview)
|
|
24
22
|
- Manage background processes with PID tracking
|
|
25
23
|
- Parse and return structured outputs from both tools
|
|
26
24
|
|
|
@@ -133,10 +131,10 @@ Executes a prompt using Claude CLI, Codex CLI, or Gemini CLI. The appropriate CL
|
|
|
133
131
|
- `workFolder` (string, required): The working directory for the CLI execution. Must be an absolute path.
|
|
134
132
|
**Models:**
|
|
135
133
|
- **Ultra Aliases:** `claude-ultra`, `codex-ultra` (defaults to high-reasoning), `gemini-ultra`
|
|
136
|
-
- Claude: `sonnet`, `opus`, `haiku`
|
|
137
|
-
- Codex: `gpt-5.2-codex`, `gpt-5.1-codex-mini`, `gpt-5.1-codex-max`, `gpt-5.2`, `gpt-5.1`, `gpt-5`
|
|
134
|
+
- Claude: `sonnet`, `sonnet[1m]`, `opus`, `opusplan`, `haiku`
|
|
135
|
+
- Codex: `gpt-5.3-codex`, `gpt-5.2-codex`, `gpt-5.1-codex-mini`, `gpt-5.1-codex-max`, `gpt-5.2`, `gpt-5.1`, `gpt-5`
|
|
138
136
|
- Gemini: `gemini-2.5-pro`, `gemini-2.5-flash`, `gemini-3-pro-preview`, `gemini-3-flash-preview`
|
|
139
|
-
- `reasoning_effort` (string, optional): Codex only. Sets `model_reasoning_effort` (allowed: "low", "medium", "high").
|
|
137
|
+
- `reasoning_effort` (string, optional): Codex only. Sets `model_reasoning_effort` (allowed: "low", "medium", "high", "xhigh").
|
|
140
138
|
- `session_id` (string, optional): Optional session ID to resume a previous session. Supported for: haiku, sonnet, opus, gemini-2.5-pro, gemini-2.5-flash, gemini-3-pro-preview, gemini-3-flash-preview.
|
|
141
139
|
|
|
142
140
|
### `wait`
|
|
@@ -165,77 +163,6 @@ Terminates a running AI agent process by PID.
|
|
|
165
163
|
**Arguments:**
|
|
166
164
|
- `pid` (number, required): The process ID to terminate.
|
|
167
165
|
|
|
168
|
-
### Examples
|
|
169
|
-
|
|
170
|
-
Here are some visual examples of the server in action:
|
|
171
|
-
|
|
172
|
-
<img src="assets/claude_tool_git_example.png" alt="Claude Tool Git Example" width="50%">
|
|
173
|
-
|
|
174
|
-
<img src="assets/additional_claude_screenshot.png" alt="Additional Claude Screenshot" width="50%">
|
|
175
|
-
|
|
176
|
-
<img src="assets/cursor-screenshot.png" alt="Cursor Screenshot" width="50%">
|
|
177
|
-
|
|
178
|
-
### Fixing ESLint Setup
|
|
179
|
-
|
|
180
|
-
Here's an example of using the Claude Code MCP tool to interactively fix an ESLint setup by deleting old configuration files and creating a new one:
|
|
181
|
-
|
|
182
|
-
<img src="assets/eslint_example.png" alt="ESLint file operations example" width="50%">
|
|
183
|
-
|
|
184
|
-
### Listing Files Example
|
|
185
|
-
|
|
186
|
-
Here's an example of the Claude Code tool listing files in a directory:
|
|
187
|
-
|
|
188
|
-
<img src="assets/file_list_example.png" alt="File listing example" width="50%">
|
|
189
|
-
|
|
190
|
-
## Key Use Cases
|
|
191
|
-
|
|
192
|
-
This server, through its unified `run` tool, unlocks a wide range of powerful capabilities by giving your AI direct access to both Claude and Codex CLI tools. Here are some examples of what you can achieve:
|
|
193
|
-
|
|
194
|
-
1. **Code Generation, Analysis & Refactoring:**
|
|
195
|
-
- `"Generate a Python script to parse CSV data and output JSON."`
|
|
196
|
-
- `"Analyze my_script.py for potential bugs and suggest improvements."`
|
|
197
|
-
|
|
198
|
-
2. **File System Operations (Create, Read, Edit, Manage):**
|
|
199
|
-
- **Creating Files:** `"Your work folder is /Users/steipete/my_project\n\nCreate a new file named 'config.yml' in the 'app/settings' directory with the following content:\nport: 8080\ndatabase: main_db"`
|
|
200
|
-
- **Editing Files:** `"Your work folder is /Users/steipete/my_project\n\nEdit file 'public/css/style.css': Add a new CSS rule at the end to make all 'h2' elements have a 'color: navy'."`
|
|
201
|
-
- **Moving/Copying/Deleting:** `"Your work folder is /Users/steipete/my_project\n\nMove the file 'report.docx' from the 'drafts' folder to the 'final_reports' folder and rename it to 'Q1_Report_Final.docx'."`
|
|
202
|
-
|
|
203
|
-
3. **Version Control (Git):**
|
|
204
|
-
- `"Your work folder is /Users/steipete/my_project\n\n1. Stage the file 'src/main.java'.\n2. Commit the changes with the message 'feat: Implement user authentication'.\n3. Push the commit to the 'develop' branch on origin."`
|
|
205
|
-
|
|
206
|
-
4. **Running Terminal Commands:**
|
|
207
|
-
- `"Your work folder is /Users/steipete/my_project/frontend\n\nRun the command 'npm run build'."`
|
|
208
|
-
- `"Open the URL https://developer.mozilla.org in my default web browser."`
|
|
209
|
-
|
|
210
|
-
5. **Web Search & Summarization:**
|
|
211
|
-
- `"Search the web for 'benefits of server-side rendering' and provide a concise summary."`
|
|
212
|
-
|
|
213
|
-
6. **Complex Multi-Step Workflows:**
|
|
214
|
-
- Automate version bumps, update changelogs, and tag releases: `"Your work folder is /Users/steipete/my_project\n\nFollow these steps: 1. Update the version in package.json to 2.5.0. 2. Add a new section to CHANGELOG.md for version 2.5.0 with the heading '### Added' and list 'New feature X'. 3. Stage package.json and CHANGELOG.md. 4. Commit with message 'release: version 2.5.0'. 5. Push the commit. 6. Create and push a git tag v2.5.0."`
|
|
215
|
-
|
|
216
|
-
<img src="assets/multistep_example.png" alt="Complex multi-step operation example" width="50%">
|
|
217
|
-
|
|
218
|
-
7. **Repairing Files with Syntax Errors:**
|
|
219
|
-
- `"Your work folder is /path/to/project\n\nThe file 'src/utils/parser.js' has syntax errors after a recent complex edit that broke its structure. Please analyze it, identify the syntax errors, and correct the file to make it valid JavaScript again, ensuring the original logic is preserved as much as possible."`
|
|
220
|
-
|
|
221
|
-
8. **Interacting with GitHub (e.g., Creating a Pull Request):**
|
|
222
|
-
- `"Your work folder is /Users/steipete/my_project\n\nCreate a GitHub Pull Request in the repository 'owner/repo' from the 'feature-branch' to the 'main' branch. Title: 'feat: Implement new login flow'. Body: 'This PR adds a new and improved login experience for users.'"`
|
|
223
|
-
|
|
224
|
-
9. **Interacting with GitHub (e.g., Checking PR CI Status):**
|
|
225
|
-
- `"Your work folder is /Users/steipete/my_project\n\nCheck the status of CI checks for Pull Request #42 in the GitHub repository 'owner/repo'. Report if they have passed, failed, or are still running."`
|
|
226
|
-
|
|
227
|
-
### Correcting GitHub Actions Workflow
|
|
228
|
-
|
|
229
|
-
<img src="assets/github_actions_fix_example.png" alt="GitHub Actions workflow fix example" width="50%">
|
|
230
|
-
|
|
231
|
-
### Complex Multi-Step Operations
|
|
232
|
-
|
|
233
|
-
This example illustrates the AI agent handling a more complex, multi-step task, such as preparing a release by creating a branch, updating multiple files (`package.json`, `CHANGELOG.md`), committing changes, and initiating a pull request, all within a single, coherent operation.
|
|
234
|
-
|
|
235
|
-
<img src="assets/claude_code_multistep_example.png" alt="AI agent multi-step example" width="50%">
|
|
236
|
-
|
|
237
|
-
**CRITICAL: Remember to provide Current Working Directory (CWD) context in your prompts for file system or git operations (e.g., `"Your work folder is /path/to/project\n\n...your command..."`).**
|
|
238
|
-
|
|
239
166
|
## Troubleshooting
|
|
240
167
|
|
|
241
168
|
- **"Command not found" (claude-code-mcp):** If installed globally, ensure the npm global bin directory is in your system's PATH. If using `npx`, ensure `npx` itself is working.
|
|
@@ -244,76 +171,9 @@ This example illustrates the AI agent handling a more complex, multi-step task,
|
|
|
244
171
|
- **JSON Errors from Server:** If `MCP_CLAUDE_DEBUG` is `true`, error messages or logs might interfere with MCP's JSON parsing. Set to `false` for normal operation.
|
|
245
172
|
- **ESM/Import Errors:** Ensure you are using Node.js v20 or later.
|
|
246
173
|
|
|
247
|
-
**For Developers: Local Setup & Contribution**
|
|
248
|
-
|
|
249
|
-
If you want to develop or contribute to this server, or run it from a cloned repository for testing, please see our [Local Installation & Development Setup Guide](./docs/local_install.md).
|
|
250
|
-
|
|
251
|
-
## Testing
|
|
252
|
-
|
|
253
|
-
The project includes comprehensive test suites:
|
|
254
|
-
|
|
255
|
-
```bash
|
|
256
|
-
# Run all tests
|
|
257
|
-
npm test
|
|
258
|
-
|
|
259
|
-
# Run unit tests only
|
|
260
|
-
npm run test:unit
|
|
261
|
-
|
|
262
|
-
# Run e2e tests (with mocks)
|
|
263
|
-
npm run test:e2e
|
|
264
|
-
|
|
265
|
-
# Run e2e tests locally (requires Claude CLI)
|
|
266
|
-
npm run test:e2e:local
|
|
267
|
-
|
|
268
|
-
# Watch mode for development
|
|
269
|
-
npm run test:watch
|
|
270
|
-
|
|
271
|
-
# Coverage report
|
|
272
|
-
npm run test:coverage
|
|
273
|
-
```
|
|
274
|
-
|
|
275
|
-
For detailed testing documentation, see our [E2E Testing Guide](./docs/e2e-testing.md).
|
|
276
|
-
|
|
277
|
-
## Manual Testing with MCP Inspector
|
|
278
|
-
|
|
279
|
-
You can manually test the MCP server using the Model Context Protocol Inspector:
|
|
280
|
-
|
|
281
|
-
```bash
|
|
282
|
-
# Build the project first
|
|
283
|
-
npm run build
|
|
284
|
-
|
|
285
|
-
# Start the MCP Inspector with the server
|
|
286
|
-
npx @modelcontextprotocol/inspector node dist/server.js
|
|
287
|
-
```
|
|
288
|
-
|
|
289
|
-
This will open a web interface where you can:
|
|
290
|
-
1. View all available tools (`run`, `list_processes`, `get_result`, `kill_process`)
|
|
291
|
-
2. Test each tool with different parameters
|
|
292
|
-
3. Test different AI models including:
|
|
293
|
-
- Claude models: `sonnet`, `opus`, `haiku`
|
|
294
|
-
- Codex models: `gpt-5.2-codex`, `gpt-5.1-codex-mini`, `gpt-5.1-codex-max`, `gpt-5.2`, `gpt-5.1`, `gpt-5.1-codex`, `gpt-5-codex`, `gpt-5-codex-mini`, `gpt-5`
|
|
295
|
-
- Gemini models: `gemini-2.5-pro`, `gemini-2.5-flash`, `gemini-3-pro-preview`, `gemini-3-flash-preview`
|
|
296
|
-
|
|
297
|
-
Example test: Select the `run` tool and provide:
|
|
298
|
-
- `prompt`: "What is 2+2?"
|
|
299
|
-
- `workFolder`: "/tmp"
|
|
300
|
-
- `model`: "gemini-2.5-flash"
|
|
301
|
-
|
|
302
|
-
## Configuration via Environment Variables
|
|
303
|
-
|
|
304
|
-
The server's behavior can be customized using these environment variables:
|
|
305
|
-
|
|
306
|
-
- `CLAUDE_CLI_PATH`: Absolute path to the Claude CLI executable.
|
|
307
|
-
- Default: Checks `~/.claude/local/claude`, then falls back to `claude` (expecting it in PATH).
|
|
308
|
-
- `MCP_CLAUDE_DEBUG`: Set to `true` for verbose debug logging from this MCP server. Default: `false`.
|
|
309
|
-
|
|
310
|
-
These can be set in your shell environment or within the `env` block of your `mcp.json` server configuration (though the `env` block in `mcp.json` examples was removed for simplicity, it's still a valid way to set them for the server process if needed).
|
|
311
|
-
|
|
312
174
|
## Contributing
|
|
313
175
|
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
Submit issues and pull requests to the [GitHub repository](https://github.com/mkXultra/claude-code-mcp).
|
|
176
|
+
For development setup, testing, and contribution guidelines, see the [Development Guide](./docs/development.md).
|
|
317
177
|
|
|
318
178
|
## Advanced Configuration (Optional)
|
|
319
179
|
|
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
2
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
3
|
+
// Mock dependencies
|
|
4
|
+
vi.mock('node:fs');
|
|
5
|
+
vi.mock('node:path', () => ({
|
|
6
|
+
resolve: vi.fn((...args) => args[args.length - 1]),
|
|
7
|
+
isAbsolute: vi.fn((p) => p.startsWith('/')),
|
|
8
|
+
}));
|
|
9
|
+
const mockExistsSync = vi.mocked(existsSync);
|
|
10
|
+
const mockReadFileSync = vi.mocked(readFileSync);
|
|
11
|
+
// Import after mocks
|
|
12
|
+
import { buildCliCommand, resolveModelAlias, getReasoningEffort, } from '../cli-builder.js';
|
|
13
|
+
const DEFAULT_CLI_PATHS = {
|
|
14
|
+
claude: '/usr/bin/claude',
|
|
15
|
+
codex: '/usr/bin/codex',
|
|
16
|
+
gemini: '/usr/bin/gemini',
|
|
17
|
+
};
|
|
18
|
+
describe('cli-builder', () => {
|
|
19
|
+
beforeEach(() => {
|
|
20
|
+
vi.clearAllMocks();
|
|
21
|
+
// By default, workFolder exists
|
|
22
|
+
mockExistsSync.mockReturnValue(true);
|
|
23
|
+
});
|
|
24
|
+
describe('resolveModelAlias', () => {
|
|
25
|
+
it('should resolve claude-ultra to opus', () => {
|
|
26
|
+
expect(resolveModelAlias('claude-ultra')).toBe('opus');
|
|
27
|
+
});
|
|
28
|
+
it('should resolve codex-ultra to gpt-5.3-codex', () => {
|
|
29
|
+
expect(resolveModelAlias('codex-ultra')).toBe('gpt-5.3-codex');
|
|
30
|
+
});
|
|
31
|
+
it('should resolve gemini-ultra to gemini-3-pro-preview', () => {
|
|
32
|
+
expect(resolveModelAlias('gemini-ultra')).toBe('gemini-3-pro-preview');
|
|
33
|
+
});
|
|
34
|
+
it('should pass through non-alias model names', () => {
|
|
35
|
+
expect(resolveModelAlias('sonnet')).toBe('sonnet');
|
|
36
|
+
expect(resolveModelAlias('gpt-5.2-codex')).toBe('gpt-5.2-codex');
|
|
37
|
+
});
|
|
38
|
+
it('should pass through empty string', () => {
|
|
39
|
+
expect(resolveModelAlias('')).toBe('');
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
describe('getReasoningEffort', () => {
|
|
43
|
+
it('should return empty string for non-string input', () => {
|
|
44
|
+
expect(getReasoningEffort('gpt-5.2', undefined)).toBe('');
|
|
45
|
+
expect(getReasoningEffort('gpt-5.2', null)).toBe('');
|
|
46
|
+
expect(getReasoningEffort('gpt-5.2', 123)).toBe('');
|
|
47
|
+
});
|
|
48
|
+
it('should return empty string for empty/whitespace input', () => {
|
|
49
|
+
expect(getReasoningEffort('gpt-5.2', '')).toBe('');
|
|
50
|
+
expect(getReasoningEffort('gpt-5.2', ' ')).toBe('');
|
|
51
|
+
});
|
|
52
|
+
it('should normalize to lowercase', () => {
|
|
53
|
+
expect(getReasoningEffort('gpt-5.2', 'HIGH')).toBe('high');
|
|
54
|
+
expect(getReasoningEffort('gpt-5.2', 'Low')).toBe('low');
|
|
55
|
+
});
|
|
56
|
+
it('should accept valid values', () => {
|
|
57
|
+
expect(getReasoningEffort('gpt-5.2', 'low')).toBe('low');
|
|
58
|
+
expect(getReasoningEffort('gpt-5.2', 'medium')).toBe('medium');
|
|
59
|
+
expect(getReasoningEffort('gpt-5.2', 'high')).toBe('high');
|
|
60
|
+
expect(getReasoningEffort('gpt-5.2', 'xhigh')).toBe('xhigh');
|
|
61
|
+
});
|
|
62
|
+
it('should throw for invalid reasoning effort value', () => {
|
|
63
|
+
expect(() => getReasoningEffort('gpt-5.2', 'ultra')).toThrow('Invalid reasoning_effort: ultra. Allowed values: low, medium, high, xhigh.');
|
|
64
|
+
});
|
|
65
|
+
it('should throw for non-codex models', () => {
|
|
66
|
+
expect(() => getReasoningEffort('sonnet', 'high')).toThrow('reasoning_effort is only supported for Codex models (gpt-*).');
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
describe('buildCliCommand', () => {
|
|
70
|
+
describe('validation', () => {
|
|
71
|
+
it('should throw when workFolder is missing', () => {
|
|
72
|
+
expect(() => buildCliCommand({
|
|
73
|
+
prompt: 'hello',
|
|
74
|
+
workFolder: '',
|
|
75
|
+
cliPaths: DEFAULT_CLI_PATHS,
|
|
76
|
+
})).toThrow('Missing or invalid required parameter: workFolder');
|
|
77
|
+
});
|
|
78
|
+
it('should throw when neither prompt nor prompt_file is provided', () => {
|
|
79
|
+
expect(() => buildCliCommand({
|
|
80
|
+
workFolder: '/tmp',
|
|
81
|
+
cliPaths: DEFAULT_CLI_PATHS,
|
|
82
|
+
})).toThrow('Either prompt or prompt_file must be provided');
|
|
83
|
+
});
|
|
84
|
+
it('should throw when both prompt and prompt_file are provided', () => {
|
|
85
|
+
expect(() => buildCliCommand({
|
|
86
|
+
prompt: 'hello',
|
|
87
|
+
prompt_file: '/tmp/prompt.txt',
|
|
88
|
+
workFolder: '/tmp',
|
|
89
|
+
cliPaths: DEFAULT_CLI_PATHS,
|
|
90
|
+
})).toThrow('Cannot specify both prompt and prompt_file');
|
|
91
|
+
});
|
|
92
|
+
it('should throw when prompt_file does not exist', () => {
|
|
93
|
+
mockExistsSync.mockImplementation((p) => {
|
|
94
|
+
if (p === '/tmp/nonexistent.txt')
|
|
95
|
+
return false;
|
|
96
|
+
return true; // workFolder exists
|
|
97
|
+
});
|
|
98
|
+
expect(() => buildCliCommand({
|
|
99
|
+
prompt_file: '/tmp/nonexistent.txt',
|
|
100
|
+
workFolder: '/tmp',
|
|
101
|
+
cliPaths: DEFAULT_CLI_PATHS,
|
|
102
|
+
})).toThrow('Prompt file does not exist');
|
|
103
|
+
});
|
|
104
|
+
it('should throw when workFolder does not exist', () => {
|
|
105
|
+
mockExistsSync.mockReturnValue(false);
|
|
106
|
+
expect(() => buildCliCommand({
|
|
107
|
+
prompt: 'hello',
|
|
108
|
+
workFolder: '/nonexistent',
|
|
109
|
+
cliPaths: DEFAULT_CLI_PATHS,
|
|
110
|
+
})).toThrow('Working folder does not exist');
|
|
111
|
+
});
|
|
112
|
+
it('should read prompt from file', () => {
|
|
113
|
+
mockExistsSync.mockReturnValue(true);
|
|
114
|
+
mockReadFileSync.mockReturnValue('prompt from file');
|
|
115
|
+
const cmd = buildCliCommand({
|
|
116
|
+
prompt_file: '/tmp/prompt.txt',
|
|
117
|
+
workFolder: '/tmp',
|
|
118
|
+
cliPaths: DEFAULT_CLI_PATHS,
|
|
119
|
+
});
|
|
120
|
+
expect(cmd.prompt).toBe('prompt from file');
|
|
121
|
+
});
|
|
122
|
+
});
|
|
123
|
+
describe('claude agent', () => {
|
|
124
|
+
it('should build claude command with default model', () => {
|
|
125
|
+
const cmd = buildCliCommand({
|
|
126
|
+
prompt: 'hello world',
|
|
127
|
+
workFolder: '/tmp',
|
|
128
|
+
cliPaths: DEFAULT_CLI_PATHS,
|
|
129
|
+
});
|
|
130
|
+
expect(cmd.agent).toBe('claude');
|
|
131
|
+
expect(cmd.cliPath).toBe('/usr/bin/claude');
|
|
132
|
+
expect(cmd.args).toEqual([
|
|
133
|
+
'--dangerously-skip-permissions',
|
|
134
|
+
'--output-format',
|
|
135
|
+
'stream-json',
|
|
136
|
+
'--verbose',
|
|
137
|
+
'-p',
|
|
138
|
+
'hello world',
|
|
139
|
+
]);
|
|
140
|
+
expect(cmd.resolvedModel).toBe('');
|
|
141
|
+
});
|
|
142
|
+
it('should build claude command with model', () => {
|
|
143
|
+
const cmd = buildCliCommand({
|
|
144
|
+
prompt: 'test',
|
|
145
|
+
workFolder: '/tmp',
|
|
146
|
+
model: 'sonnet',
|
|
147
|
+
cliPaths: DEFAULT_CLI_PATHS,
|
|
148
|
+
});
|
|
149
|
+
expect(cmd.agent).toBe('claude');
|
|
150
|
+
expect(cmd.args).toContain('--model');
|
|
151
|
+
expect(cmd.args).toContain('sonnet');
|
|
152
|
+
expect(cmd.resolvedModel).toBe('sonnet');
|
|
153
|
+
});
|
|
154
|
+
it('should build claude command with session_id', () => {
|
|
155
|
+
const cmd = buildCliCommand({
|
|
156
|
+
prompt: 'test',
|
|
157
|
+
workFolder: '/tmp',
|
|
158
|
+
session_id: 'ses-123',
|
|
159
|
+
cliPaths: DEFAULT_CLI_PATHS,
|
|
160
|
+
});
|
|
161
|
+
expect(cmd.args).toContain('-r');
|
|
162
|
+
expect(cmd.args).toContain('ses-123');
|
|
163
|
+
});
|
|
164
|
+
it('should resolve claude-ultra alias to opus', () => {
|
|
165
|
+
const cmd = buildCliCommand({
|
|
166
|
+
prompt: 'test',
|
|
167
|
+
workFolder: '/tmp',
|
|
168
|
+
model: 'claude-ultra',
|
|
169
|
+
cliPaths: DEFAULT_CLI_PATHS,
|
|
170
|
+
});
|
|
171
|
+
expect(cmd.agent).toBe('claude');
|
|
172
|
+
expect(cmd.resolvedModel).toBe('opus');
|
|
173
|
+
expect(cmd.args).toContain('opus');
|
|
174
|
+
});
|
|
175
|
+
});
|
|
176
|
+
describe('codex agent', () => {
|
|
177
|
+
it('should build codex command', () => {
|
|
178
|
+
const cmd = buildCliCommand({
|
|
179
|
+
prompt: 'test',
|
|
180
|
+
workFolder: '/tmp',
|
|
181
|
+
model: 'gpt-5.2-codex',
|
|
182
|
+
cliPaths: DEFAULT_CLI_PATHS,
|
|
183
|
+
});
|
|
184
|
+
expect(cmd.agent).toBe('codex');
|
|
185
|
+
expect(cmd.cliPath).toBe('/usr/bin/codex');
|
|
186
|
+
expect(cmd.args).toContain('exec');
|
|
187
|
+
expect(cmd.args).toContain('--full-auto');
|
|
188
|
+
expect(cmd.args).toContain('--json');
|
|
189
|
+
expect(cmd.args).toContain('--model');
|
|
190
|
+
expect(cmd.args).toContain('gpt-5.2-codex');
|
|
191
|
+
});
|
|
192
|
+
it('should build codex command with session_id using exec resume', () => {
|
|
193
|
+
const cmd = buildCliCommand({
|
|
194
|
+
prompt: 'test',
|
|
195
|
+
workFolder: '/tmp',
|
|
196
|
+
model: 'gpt-5.2',
|
|
197
|
+
session_id: 'codex-ses-456',
|
|
198
|
+
cliPaths: DEFAULT_CLI_PATHS,
|
|
199
|
+
});
|
|
200
|
+
expect(cmd.args[0]).toBe('exec');
|
|
201
|
+
expect(cmd.args[1]).toBe('resume');
|
|
202
|
+
expect(cmd.args[2]).toBe('codex-ses-456');
|
|
203
|
+
});
|
|
204
|
+
it('should build codex command with reasoning_effort', () => {
|
|
205
|
+
const cmd = buildCliCommand({
|
|
206
|
+
prompt: 'test',
|
|
207
|
+
workFolder: '/tmp',
|
|
208
|
+
model: 'gpt-5.2-codex',
|
|
209
|
+
reasoning_effort: 'high',
|
|
210
|
+
cliPaths: DEFAULT_CLI_PATHS,
|
|
211
|
+
});
|
|
212
|
+
expect(cmd.args).toContain('-c');
|
|
213
|
+
expect(cmd.args).toContain('model_reasoning_effort=high');
|
|
214
|
+
});
|
|
215
|
+
it('should resolve codex-ultra and default to xhigh reasoning', () => {
|
|
216
|
+
const cmd = buildCliCommand({
|
|
217
|
+
prompt: 'test',
|
|
218
|
+
workFolder: '/tmp',
|
|
219
|
+
model: 'codex-ultra',
|
|
220
|
+
cliPaths: DEFAULT_CLI_PATHS,
|
|
221
|
+
});
|
|
222
|
+
expect(cmd.agent).toBe('codex');
|
|
223
|
+
expect(cmd.resolvedModel).toBe('gpt-5.3-codex');
|
|
224
|
+
expect(cmd.args).toContain('-c');
|
|
225
|
+
expect(cmd.args).toContain('model_reasoning_effort=xhigh');
|
|
226
|
+
});
|
|
227
|
+
it('should allow overriding reasoning_effort for codex-ultra', () => {
|
|
228
|
+
const cmd = buildCliCommand({
|
|
229
|
+
prompt: 'test',
|
|
230
|
+
workFolder: '/tmp',
|
|
231
|
+
model: 'codex-ultra',
|
|
232
|
+
reasoning_effort: 'low',
|
|
233
|
+
cliPaths: DEFAULT_CLI_PATHS,
|
|
234
|
+
});
|
|
235
|
+
expect(cmd.args).toContain('model_reasoning_effort=low');
|
|
236
|
+
expect(cmd.args).not.toContain('model_reasoning_effort=xhigh');
|
|
237
|
+
});
|
|
238
|
+
});
|
|
239
|
+
describe('gemini agent', () => {
|
|
240
|
+
it('should build gemini command', () => {
|
|
241
|
+
const cmd = buildCliCommand({
|
|
242
|
+
prompt: 'test',
|
|
243
|
+
workFolder: '/tmp',
|
|
244
|
+
model: 'gemini-2.5-pro',
|
|
245
|
+
cliPaths: DEFAULT_CLI_PATHS,
|
|
246
|
+
});
|
|
247
|
+
expect(cmd.agent).toBe('gemini');
|
|
248
|
+
expect(cmd.cliPath).toBe('/usr/bin/gemini');
|
|
249
|
+
expect(cmd.args).toContain('-y');
|
|
250
|
+
expect(cmd.args).toContain('--output-format');
|
|
251
|
+
expect(cmd.args).toContain('json');
|
|
252
|
+
expect(cmd.args).toContain('--model');
|
|
253
|
+
expect(cmd.args).toContain('gemini-2.5-pro');
|
|
254
|
+
});
|
|
255
|
+
it('should build gemini command with session_id', () => {
|
|
256
|
+
const cmd = buildCliCommand({
|
|
257
|
+
prompt: 'test',
|
|
258
|
+
workFolder: '/tmp',
|
|
259
|
+
model: 'gemini-2.5-pro',
|
|
260
|
+
session_id: 'gem-789',
|
|
261
|
+
cliPaths: DEFAULT_CLI_PATHS,
|
|
262
|
+
});
|
|
263
|
+
expect(cmd.args).toContain('-r');
|
|
264
|
+
expect(cmd.args).toContain('gem-789');
|
|
265
|
+
});
|
|
266
|
+
it('should resolve gemini-ultra alias', () => {
|
|
267
|
+
const cmd = buildCliCommand({
|
|
268
|
+
prompt: 'test',
|
|
269
|
+
workFolder: '/tmp',
|
|
270
|
+
model: 'gemini-ultra',
|
|
271
|
+
cliPaths: DEFAULT_CLI_PATHS,
|
|
272
|
+
});
|
|
273
|
+
expect(cmd.agent).toBe('gemini');
|
|
274
|
+
expect(cmd.resolvedModel).toBe('gemini-3-pro-preview');
|
|
275
|
+
});
|
|
276
|
+
});
|
|
277
|
+
});
|
|
278
|
+
});
|
|
@@ -652,7 +652,7 @@ describe('ClaudeCodeServer Unit Tests', () => {
|
|
|
652
652
|
}
|
|
653
653
|
});
|
|
654
654
|
// Verify spawn was called with resolved model name
|
|
655
|
-
expect(mockSpawn).toHaveBeenCalledWith(expect.any(String), expect.arrayContaining(['--model', '
|
|
655
|
+
expect(mockSpawn).toHaveBeenCalledWith(expect.any(String), expect.arrayContaining(['--model', 'haiku']), expect.any(Object));
|
|
656
656
|
// Verify PID is returned
|
|
657
657
|
expect(result.content[0].text).toContain('"pid": 12345');
|
|
658
658
|
});
|