ai-cli-mcp 2.19.0 → 2.20.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +26 -0
- package/README.ja.md +34 -8
- package/README.md +41 -8
- package/dist/app/cli.js +1 -0
- package/dist/app/mcp.js +64 -12
- package/dist/cli-builder.js +13 -6
- package/dist/cli-process-service.js +76 -91
- package/dist/cli-utils.js +6 -0
- package/dist/cli.js +1 -1
- package/dist/model-catalog.js +3 -2
- package/dist/parsers.js +8 -2
- package/package.json +27 -3
- package/server.json +3 -3
- package/.gemini/settings.json +0 -11
- package/.github/dependabot.yml +0 -28
- package/.github/pull_request_template.md +0 -28
- package/.github/workflows/ci.yml +0 -34
- package/.github/workflows/dependency-review.yml +0 -22
- package/.github/workflows/publish.yml +0 -89
- package/.github/workflows/test.yml +0 -20
- package/.github/workflows/watch-session-prs.yml +0 -276
- package/.husky/pre-commit +0 -1
- package/.mcp.json +0 -11
- package/.releaserc.json +0 -18
- package/.vscode/settings.json +0 -3
- package/CONTRIBUTING.md +0 -81
- package/dist/__tests__/app-cli.test.js +0 -392
- package/dist/__tests__/cli-bin-smoke.test.js +0 -101
- package/dist/__tests__/cli-builder.test.js +0 -442
- package/dist/__tests__/cli-process-service.test.js +0 -655
- package/dist/__tests__/cli-utils.test.js +0 -171
- package/dist/__tests__/e2e.test.js +0 -256
- package/dist/__tests__/edge-cases.test.js +0 -130
- package/dist/__tests__/error-cases.test.js +0 -292
- package/dist/__tests__/mcp-contract.test.js +0 -636
- package/dist/__tests__/mocks.js +0 -32
- package/dist/__tests__/model-alias.test.js +0 -36
- package/dist/__tests__/parsers.test.js +0 -646
- package/dist/__tests__/peek.test.js +0 -36
- package/dist/__tests__/process-management.test.js +0 -949
- package/dist/__tests__/server.test.js +0 -809
- package/dist/__tests__/setup.js +0 -11
- package/dist/__tests__/utils/claude-mock.js +0 -80
- package/dist/__tests__/utils/mcp-client.js +0 -121
- package/dist/__tests__/utils/opencode-mock.js +0 -91
- package/dist/__tests__/utils/persistent-mock.js +0 -28
- package/dist/__tests__/utils/test-helpers.js +0 -11
- package/dist/__tests__/validation.test.js +0 -308
- package/dist/__tests__/version-print.test.js +0 -65
- package/dist/__tests__/wait.test.js +0 -260
- package/docs/RELEASE_CHECKLIST.md +0 -65
- package/docs/cli-architecture.md +0 -275
- package/docs/concept.md +0 -154
- package/docs/development.md +0 -156
- package/docs/e2e-testing.md +0 -148
- package/docs/prd.md +0 -146
- package/docs/session-stacking.md +0 -67
- package/src/__tests__/app-cli.test.ts +0 -495
- package/src/__tests__/cli-bin-smoke.test.ts +0 -136
- package/src/__tests__/cli-builder.test.ts +0 -549
- package/src/__tests__/cli-process-service.test.ts +0 -759
- package/src/__tests__/cli-utils.test.ts +0 -200
- package/src/__tests__/e2e.test.ts +0 -311
- package/src/__tests__/edge-cases.test.ts +0 -176
- package/src/__tests__/error-cases.test.ts +0 -370
- package/src/__tests__/mcp-contract.test.ts +0 -755
- package/src/__tests__/mocks.ts +0 -35
- package/src/__tests__/model-alias.test.ts +0 -44
- package/src/__tests__/parsers.test.ts +0 -730
- package/src/__tests__/peek.test.ts +0 -44
- package/src/__tests__/process-management.test.ts +0 -1129
- package/src/__tests__/server.test.ts +0 -1020
- package/src/__tests__/setup.ts +0 -13
- package/src/__tests__/utils/claude-mock.ts +0 -87
- package/src/__tests__/utils/mcp-client.ts +0 -159
- package/src/__tests__/utils/opencode-mock.ts +0 -108
- package/src/__tests__/utils/persistent-mock.ts +0 -33
- package/src/__tests__/utils/test-helpers.ts +0 -13
- package/src/__tests__/validation.test.ts +0 -369
- package/src/__tests__/version-print.test.ts +0 -81
- package/src/__tests__/wait.test.ts +0 -302
- package/src/app/cli.ts +0 -424
- package/src/app/mcp.ts +0 -466
- package/src/bin/ai-cli-mcp.ts +0 -7
- package/src/bin/ai-cli.ts +0 -11
- package/src/cli-builder.ts +0 -274
- package/src/cli-parse.ts +0 -105
- package/src/cli-process-service.ts +0 -709
- package/src/cli-utils.ts +0 -258
- package/src/cli.ts +0 -124
- package/src/model-catalog.ts +0 -87
- package/src/parsers.ts +0 -965
- package/src/peek.ts +0 -95
- package/src/process-result.ts +0 -88
- package/src/process-service.ts +0 -368
- package/src/server.ts +0 -10
- package/tsconfig.json +0 -16
- package/vitest.config.e2e.ts +0 -27
- package/vitest.config.ts +0 -22
- package/vitest.config.unit.ts +0 -28
package/src/cli-utils.ts
DELETED
|
@@ -1,258 +0,0 @@
|
|
|
1
|
-
import { accessSync, constants } from 'node:fs';
|
|
2
|
-
import { homedir } from 'node:os';
|
|
3
|
-
import { join } from 'node:path';
|
|
4
|
-
import * as path from 'path';
|
|
5
|
-
|
|
6
|
-
const debugMode = process.env.MCP_CLAUDE_DEBUG === 'true';
|
|
7
|
-
|
|
8
|
-
export function debugLog(message?: any, ...optionalParams: any[]): void {
|
|
9
|
-
if (debugMode) {
|
|
10
|
-
console.error(message, ...optionalParams);
|
|
11
|
-
}
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export interface CliBinaryStatus {
|
|
15
|
-
configuredCommand: string;
|
|
16
|
-
resolvedPath: string | null;
|
|
17
|
-
available: boolean;
|
|
18
|
-
lookup: 'env' | 'local' | 'path';
|
|
19
|
-
error?: string;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export type CliBinaryName = 'claude' | 'codex' | 'gemini' | 'forge' | 'opencode';
|
|
23
|
-
|
|
24
|
-
export interface CliPaths {
|
|
25
|
-
claude: string;
|
|
26
|
-
codex: string;
|
|
27
|
-
gemini: string;
|
|
28
|
-
forge: string;
|
|
29
|
-
opencode: string;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export interface CliDoctorStatus {
|
|
33
|
-
claude: CliBinaryStatus;
|
|
34
|
-
codex: CliBinaryStatus;
|
|
35
|
-
gemini: CliBinaryStatus;
|
|
36
|
-
forge: CliBinaryStatus;
|
|
37
|
-
opencode: CliBinaryStatus;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
function getPathDelimiter(): string {
|
|
41
|
-
return process.platform === 'win32' ? ';' : ':';
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
function getPathExtensions(): string[] {
|
|
45
|
-
if (process.platform !== 'win32') {
|
|
46
|
-
return [''];
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
const rawPathext = process.env.PATHEXT || '.EXE;.CMD;.BAT;.COM';
|
|
50
|
-
return ['', ...rawPathext.split(';').filter(Boolean)];
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
function findExecutableOnPath(commandName: string): string | null {
|
|
54
|
-
const rawPath = process.env.PATH || '';
|
|
55
|
-
if (!rawPath) {
|
|
56
|
-
return null;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
const pathEntries = rawPath.split(getPathDelimiter()).filter(Boolean);
|
|
60
|
-
const extensions = getPathExtensions();
|
|
61
|
-
|
|
62
|
-
for (const entry of pathEntries) {
|
|
63
|
-
for (const extension of extensions) {
|
|
64
|
-
const candidate = join(entry, `${commandName}${extension}`);
|
|
65
|
-
if (isExecutableFile(candidate)) {
|
|
66
|
-
return candidate;
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
return null;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
function validateCustomCliName(envVarName: string, customCliName: string): string | null {
|
|
75
|
-
if (path.isAbsolute(customCliName)) {
|
|
76
|
-
return null;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
if (
|
|
80
|
-
customCliName.startsWith('./') ||
|
|
81
|
-
customCliName.startsWith('../') ||
|
|
82
|
-
customCliName.includes('/')
|
|
83
|
-
) {
|
|
84
|
-
return `Invalid ${envVarName}: Relative paths are not allowed. Use either a simple name (e.g., '${customCliName.split('/').pop() || 'cli'}') or an absolute path (e.g., '/tmp/${customCliName.split('/').pop() || 'cli'}-test')`;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
return null;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
function inspectCliBinary(options: {
|
|
91
|
-
envVarName: string;
|
|
92
|
-
customCliName: string | undefined;
|
|
93
|
-
defaultCliName: string;
|
|
94
|
-
localInstallPath?: string;
|
|
95
|
-
}): CliBinaryStatus {
|
|
96
|
-
const configuredCommand = options.customCliName || options.defaultCliName;
|
|
97
|
-
|
|
98
|
-
if (options.customCliName) {
|
|
99
|
-
const validationError = validateCustomCliName(options.envVarName, options.customCliName);
|
|
100
|
-
if (validationError) {
|
|
101
|
-
return {
|
|
102
|
-
configuredCommand,
|
|
103
|
-
resolvedPath: null,
|
|
104
|
-
available: false,
|
|
105
|
-
lookup: 'env',
|
|
106
|
-
error: validationError,
|
|
107
|
-
};
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
if (path.isAbsolute(options.customCliName)) {
|
|
111
|
-
return {
|
|
112
|
-
configuredCommand,
|
|
113
|
-
resolvedPath: options.customCliName,
|
|
114
|
-
available: isExecutableFile(options.customCliName),
|
|
115
|
-
lookup: 'env',
|
|
116
|
-
};
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
const resolvedPath = findExecutableOnPath(configuredCommand);
|
|
120
|
-
return {
|
|
121
|
-
configuredCommand,
|
|
122
|
-
resolvedPath,
|
|
123
|
-
available: resolvedPath !== null,
|
|
124
|
-
lookup: 'env',
|
|
125
|
-
};
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
if (options.localInstallPath && isExecutableFile(options.localInstallPath)) {
|
|
129
|
-
return {
|
|
130
|
-
configuredCommand,
|
|
131
|
-
resolvedPath: options.localInstallPath,
|
|
132
|
-
available: true,
|
|
133
|
-
lookup: 'local',
|
|
134
|
-
};
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
const resolvedPath = findExecutableOnPath(configuredCommand);
|
|
138
|
-
return {
|
|
139
|
-
configuredCommand,
|
|
140
|
-
resolvedPath,
|
|
141
|
-
available: resolvedPath !== null,
|
|
142
|
-
lookup: 'path',
|
|
143
|
-
};
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
function getCliCommandOrThrow(status: CliBinaryStatus): string {
|
|
147
|
-
if (status.error) {
|
|
148
|
-
throw new Error(status.error);
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
if (status.lookup === 'env' && !path.isAbsolute(status.configuredCommand)) {
|
|
152
|
-
return status.configuredCommand;
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
return status.resolvedPath || status.configuredCommand;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
function isExecutableFile(filePath: string): boolean {
|
|
159
|
-
try {
|
|
160
|
-
accessSync(filePath, constants.X_OK);
|
|
161
|
-
return true;
|
|
162
|
-
} catch {
|
|
163
|
-
return false;
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
function getCliBinaryConfig(name: CliBinaryName): {
|
|
168
|
-
envVarName: string;
|
|
169
|
-
customCliName: string | undefined;
|
|
170
|
-
defaultCliName: string;
|
|
171
|
-
localInstallPath?: string;
|
|
172
|
-
} {
|
|
173
|
-
if (name === 'claude') {
|
|
174
|
-
return {
|
|
175
|
-
envVarName: 'CLAUDE_CLI_NAME',
|
|
176
|
-
customCliName: process.env.CLAUDE_CLI_NAME,
|
|
177
|
-
defaultCliName: 'claude',
|
|
178
|
-
localInstallPath: join(homedir(), '.claude', 'local', 'claude'),
|
|
179
|
-
};
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
if (name === 'codex') {
|
|
183
|
-
return {
|
|
184
|
-
envVarName: 'CODEX_CLI_NAME',
|
|
185
|
-
customCliName: process.env.CODEX_CLI_NAME,
|
|
186
|
-
defaultCliName: 'codex',
|
|
187
|
-
localInstallPath: join(homedir(), '.codex', 'local', 'codex'),
|
|
188
|
-
};
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
if (name === 'forge') {
|
|
192
|
-
return {
|
|
193
|
-
envVarName: 'FORGE_CLI_NAME',
|
|
194
|
-
customCliName: process.env.FORGE_CLI_NAME,
|
|
195
|
-
defaultCliName: 'forge',
|
|
196
|
-
localInstallPath: join(homedir(), '.forge', 'local', 'forge'),
|
|
197
|
-
};
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
if (name === 'opencode') {
|
|
201
|
-
return {
|
|
202
|
-
envVarName: 'OPENCODE_CLI_NAME',
|
|
203
|
-
customCliName: process.env.OPENCODE_CLI_NAME,
|
|
204
|
-
defaultCliName: 'opencode',
|
|
205
|
-
};
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
return {
|
|
209
|
-
envVarName: 'GEMINI_CLI_NAME',
|
|
210
|
-
customCliName: process.env.GEMINI_CLI_NAME,
|
|
211
|
-
defaultCliName: 'gemini',
|
|
212
|
-
localInstallPath: join(homedir(), '.gemini', 'local', 'gemini'),
|
|
213
|
-
};
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
function getCliBinaryStatus(name: CliBinaryName): CliBinaryStatus {
|
|
217
|
-
return inspectCliBinary(getCliBinaryConfig(name));
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
export function getCliDoctorStatus(): CliDoctorStatus {
|
|
221
|
-
return {
|
|
222
|
-
claude: getCliBinaryStatus('claude'),
|
|
223
|
-
codex: getCliBinaryStatus('codex'),
|
|
224
|
-
gemini: getCliBinaryStatus('gemini'),
|
|
225
|
-
forge: getCliBinaryStatus('forge'),
|
|
226
|
-
opencode: getCliBinaryStatus('opencode'),
|
|
227
|
-
};
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
export function findGeminiCli(): string {
|
|
231
|
-
debugLog('[Debug] Attempting to find Gemini CLI...');
|
|
232
|
-
const status = getCliBinaryStatus('gemini');
|
|
233
|
-
return getCliCommandOrThrow(status);
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
export function findCodexCli(): string {
|
|
237
|
-
debugLog('[Debug] Attempting to find Codex CLI...');
|
|
238
|
-
const status = getCliBinaryStatus('codex');
|
|
239
|
-
return getCliCommandOrThrow(status);
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
export function findForgeCli(): string {
|
|
243
|
-
debugLog('[Debug] Attempting to find Forge CLI...');
|
|
244
|
-
const status = getCliBinaryStatus('forge');
|
|
245
|
-
return getCliCommandOrThrow(status);
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
export function findOpencodeCli(): string {
|
|
249
|
-
debugLog('[Debug] Attempting to find OpenCode CLI...');
|
|
250
|
-
const status = getCliBinaryStatus('opencode');
|
|
251
|
-
return getCliCommandOrThrow(status);
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
export function findClaudeCli(): string {
|
|
255
|
-
debugLog('[Debug] Attempting to find Claude CLI...');
|
|
256
|
-
const status = getCliBinaryStatus('claude');
|
|
257
|
-
return getCliCommandOrThrow(status);
|
|
258
|
-
}
|
package/src/cli.ts
DELETED
|
@@ -1,124 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import { spawn } from 'node:child_process';
|
|
3
|
-
import { buildCliCommand } from './cli-builder.js';
|
|
4
|
-
import { findClaudeCli, findCodexCli, findForgeCli, findGeminiCli, findOpencodeCli } from './cli-utils.js';
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Minimal argv parser. No external dependencies.
|
|
8
|
-
* Supports: --key value, --key=value
|
|
9
|
-
*/
|
|
10
|
-
function parseArgs(argv: string[]): Record<string, string> {
|
|
11
|
-
const result: Record<string, string> = {};
|
|
12
|
-
for (let i = 0; i < argv.length; i++) {
|
|
13
|
-
const arg = argv[i];
|
|
14
|
-
if (!arg.startsWith('--')) continue;
|
|
15
|
-
|
|
16
|
-
const eqIdx = arg.indexOf('=');
|
|
17
|
-
if (eqIdx !== -1) {
|
|
18
|
-
// --key=value
|
|
19
|
-
result[arg.slice(2, eqIdx)] = arg.slice(eqIdx + 1);
|
|
20
|
-
} else {
|
|
21
|
-
// --key value
|
|
22
|
-
const key = arg.slice(2);
|
|
23
|
-
const next = argv[i + 1];
|
|
24
|
-
if (next !== undefined && !next.startsWith('--')) {
|
|
25
|
-
result[key] = next;
|
|
26
|
-
i++;
|
|
27
|
-
} else {
|
|
28
|
-
result[key] = '';
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
return result;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
const USAGE = `Usage: npm run -s cli.run -- --model <model> --workFolder <path> --prompt "..." [options]
|
|
36
|
-
|
|
37
|
-
Options:
|
|
38
|
-
--model Model name or alias (e.g. sonnet, opus, gpt-5.2-codex, gemini-2.5-pro, forge, opencode, oc-openai/gpt-5.4)
|
|
39
|
-
--workFolder Working directory (absolute path)
|
|
40
|
-
--prompt Prompt string (mutually exclusive with --prompt_file)
|
|
41
|
-
--prompt_file Path to a file containing the prompt
|
|
42
|
-
--session_id Session ID to resume, including OpenCode in-place resumes
|
|
43
|
-
--reasoning_effort Claude/Codex only: Claude=low|medium|high, Codex=low|medium|high|xhigh; unsupported for Gemini, Forge, and OpenCode
|
|
44
|
-
--help Show this help message
|
|
45
|
-
|
|
46
|
-
Raw CLI output goes to stdout. Use cli.run.parse to parse the output:
|
|
47
|
-
npm run -s cli.run -- ... > raw.txt
|
|
48
|
-
npm run -s cli.run.parse -- --agent claude < raw.txt
|
|
49
|
-
npm run -s cli.run.parse -- --agent opencode < raw.txt
|
|
50
|
-
`;
|
|
51
|
-
|
|
52
|
-
async function main(): Promise<void> {
|
|
53
|
-
const args = parseArgs(process.argv.slice(2));
|
|
54
|
-
|
|
55
|
-
if ('help' in args) {
|
|
56
|
-
process.stdout.write(USAGE);
|
|
57
|
-
process.exit(0);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
if (!args.workFolder) {
|
|
61
|
-
process.stderr.write('Error: --workFolder is required\n\n');
|
|
62
|
-
process.stderr.write(USAGE);
|
|
63
|
-
process.exit(1);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
if (!args.prompt && !args.prompt_file) {
|
|
67
|
-
process.stderr.write('Error: --prompt or --prompt_file is required\n\n');
|
|
68
|
-
process.stderr.write(USAGE);
|
|
69
|
-
process.exit(1);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
// Resolve CLI paths
|
|
73
|
-
const cliPaths = {
|
|
74
|
-
claude: findClaudeCli(),
|
|
75
|
-
codex: findCodexCli(),
|
|
76
|
-
gemini: findGeminiCli(),
|
|
77
|
-
forge: findForgeCli(),
|
|
78
|
-
opencode: findOpencodeCli(),
|
|
79
|
-
};
|
|
80
|
-
|
|
81
|
-
// Build command
|
|
82
|
-
let cmd;
|
|
83
|
-
try {
|
|
84
|
-
cmd = buildCliCommand({
|
|
85
|
-
prompt: args.prompt || undefined,
|
|
86
|
-
prompt_file: args.prompt_file || undefined,
|
|
87
|
-
workFolder: args.workFolder,
|
|
88
|
-
model: args.model || undefined,
|
|
89
|
-
session_id: args.session_id || undefined,
|
|
90
|
-
reasoning_effort: args.reasoning_effort || undefined,
|
|
91
|
-
cliPaths,
|
|
92
|
-
});
|
|
93
|
-
} catch (error: any) {
|
|
94
|
-
process.stderr.write(`Error: ${error.message}\n`);
|
|
95
|
-
process.exit(1);
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
// Log agent info to stderr (does not pollute stdout)
|
|
99
|
-
process.stderr.write(`[cli.run] agent=${cmd.agent} model=${cmd.resolvedModel || '(default)'}\n`);
|
|
100
|
-
|
|
101
|
-
// Spawn foreground process — raw output passthrough
|
|
102
|
-
const child = spawn(cmd.cliPath, cmd.args, {
|
|
103
|
-
cwd: cmd.cwd,
|
|
104
|
-
stdio: 'inherit',
|
|
105
|
-
detached: false,
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
const exitCode = await new Promise<number>((resolve) => {
|
|
109
|
-
child.on('close', (code) => {
|
|
110
|
-
resolve(code ?? 1);
|
|
111
|
-
});
|
|
112
|
-
child.on('error', (err) => {
|
|
113
|
-
process.stderr.write(`Process error: ${err.message}\n`);
|
|
114
|
-
resolve(1);
|
|
115
|
-
});
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
process.exit(exitCode);
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
main().catch((err) => {
|
|
122
|
-
process.stderr.write(`Fatal error: ${err.message}\n`);
|
|
123
|
-
process.exit(1);
|
|
124
|
-
});
|
package/src/model-catalog.ts
DELETED
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
export const CLAUDE_MODELS = ['sonnet', 'sonnet[1m]', 'opus', 'opusplan', 'haiku'] as const;
|
|
2
|
-
export const CODEX_MODELS = [
|
|
3
|
-
'gpt-5.4',
|
|
4
|
-
'gpt-5.3-codex',
|
|
5
|
-
'gpt-5.2-codex',
|
|
6
|
-
'gpt-5.1-codex-mini',
|
|
7
|
-
'gpt-5.1-codex-max',
|
|
8
|
-
'gpt-5.2',
|
|
9
|
-
'gpt-5.1',
|
|
10
|
-
'gpt-5.1-codex',
|
|
11
|
-
'gpt-5-codex',
|
|
12
|
-
'gpt-5-codex-mini',
|
|
13
|
-
'gpt-5',
|
|
14
|
-
] as const;
|
|
15
|
-
export const GEMINI_MODELS = [
|
|
16
|
-
'gemini-2.5-pro',
|
|
17
|
-
'gemini-2.5-flash',
|
|
18
|
-
'gemini-3.1-pro-preview',
|
|
19
|
-
'gemini-3-pro-preview',
|
|
20
|
-
'gemini-3-flash-preview',
|
|
21
|
-
] as const;
|
|
22
|
-
export const FORGE_MODELS = ['forge'] as const;
|
|
23
|
-
export const OPENCODE_MODELS = ['opencode'] as const;
|
|
24
|
-
|
|
25
|
-
export const MODEL_ALIASES: Record<string, string> = {
|
|
26
|
-
'claude-ultra': 'opus',
|
|
27
|
-
'codex-ultra': 'gpt-5.4',
|
|
28
|
-
'gemini-ultra': 'gemini-3.1-pro-preview',
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
export const MODEL_ALIAS_DETAILS = [
|
|
32
|
-
{ name: 'claude-ultra', resolvesTo: 'opus', agent: 'claude', defaultReasoningEffort: 'high' },
|
|
33
|
-
{ name: 'codex-ultra', resolvesTo: 'gpt-5.4', agent: 'codex', defaultReasoningEffort: 'xhigh' },
|
|
34
|
-
{ name: 'gemini-ultra', resolvesTo: 'gemini-3.1-pro-preview', agent: 'gemini' },
|
|
35
|
-
] as const;
|
|
36
|
-
|
|
37
|
-
export interface DynamicModelBackendDescription {
|
|
38
|
-
explicitPrefix: string;
|
|
39
|
-
explicitPattern: string;
|
|
40
|
-
discoveryCommand: string;
|
|
41
|
-
modelsAreDynamic: boolean;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
export function getSupportedModelsDescription(): string {
|
|
45
|
-
return [
|
|
46
|
-
'"claude-ultra", "codex-ultra", "gemini-ultra"',
|
|
47
|
-
...CLAUDE_MODELS.map((model) => `"${model}"`),
|
|
48
|
-
...CODEX_MODELS.map((model) => `"${model}"`),
|
|
49
|
-
...GEMINI_MODELS.map((model) => `"${model}"`),
|
|
50
|
-
...FORGE_MODELS.map((model) => `"${model}"`),
|
|
51
|
-
...OPENCODE_MODELS.map((model) => `"${model}"`),
|
|
52
|
-
'"oc-<provider/model>"',
|
|
53
|
-
].join(', ');
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
export function getModelParameterDescription(): string {
|
|
57
|
-
return `The model to use. Aliases: "claude-ultra" (auto high effort), "codex-ultra" (auto xhigh reasoning), "gemini-ultra". Standard: ${[...CLAUDE_MODELS, ...CODEX_MODELS, ...GEMINI_MODELS, ...FORGE_MODELS, ...OPENCODE_MODELS].map((model) => `"${model}"`).join(', ')}. OpenCode also accepts explicit dynamic models using "oc-<provider/model>". "forge" is a provider key, not a Forge model family selector.`;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
export function getModelsPayload(): {
|
|
61
|
-
aliases: ReadonlyArray<(typeof MODEL_ALIAS_DETAILS)[number]>;
|
|
62
|
-
claude: ReadonlyArray<string>;
|
|
63
|
-
codex: ReadonlyArray<string>;
|
|
64
|
-
gemini: ReadonlyArray<string>;
|
|
65
|
-
forge: ReadonlyArray<string>;
|
|
66
|
-
opencode: ReadonlyArray<string>;
|
|
67
|
-
dynamicModelBackends: {
|
|
68
|
-
opencode: DynamicModelBackendDescription;
|
|
69
|
-
};
|
|
70
|
-
} {
|
|
71
|
-
return {
|
|
72
|
-
aliases: MODEL_ALIAS_DETAILS,
|
|
73
|
-
claude: CLAUDE_MODELS,
|
|
74
|
-
codex: CODEX_MODELS,
|
|
75
|
-
gemini: GEMINI_MODELS,
|
|
76
|
-
forge: FORGE_MODELS,
|
|
77
|
-
opencode: OPENCODE_MODELS,
|
|
78
|
-
dynamicModelBackends: {
|
|
79
|
-
opencode: {
|
|
80
|
-
explicitPrefix: 'oc-',
|
|
81
|
-
explicitPattern: 'oc-<provider/model>',
|
|
82
|
-
discoveryCommand: 'opencode models',
|
|
83
|
-
modelsAreDynamic: true,
|
|
84
|
-
},
|
|
85
|
-
},
|
|
86
|
-
};
|
|
87
|
-
}
|