jbai-cli 1.9.1 → 1.9.6
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 +1 -1
- package/bin/jbai-claude.js +16 -9
- package/bin/jbai-codex.js +12 -39
- package/bin/jbai-continue.js +27 -43
- package/bin/jbai-council.js +665 -0
- package/bin/jbai-gemini.js +17 -6
- package/bin/jbai-goose.js +11 -39
- package/bin/jbai-opencode.js +122 -20
- package/bin/jbai-proxy.js +1129 -64
- package/bin/jbai.js +77 -41
- package/bin/test-cli-tictactoe.js +279 -0
- package/bin/test-clients.js +38 -6
- package/bin/test-model-lists.js +100 -0
- package/lib/config.js +39 -6
- package/lib/model-list.js +117 -0
- package/lib/proxy.js +46 -0
- package/package.json +3 -2
package/lib/config.js
CHANGED
|
@@ -53,7 +53,7 @@ const MODELS = {
|
|
|
53
53
|
default: 'gpt-5.2-2025-12-11',
|
|
54
54
|
available: [
|
|
55
55
|
// GPT-5.x series (latest) - require date-versioned names
|
|
56
|
-
|
|
56
|
+
'gpt-5.3-codex',
|
|
57
57
|
'gpt-5.2-2025-12-11',
|
|
58
58
|
'gpt-5.2',
|
|
59
59
|
'gpt-5.1-2025-11-13',
|
|
@@ -81,9 +81,10 @@ const MODELS = {
|
|
|
81
81
|
// Codex CLI uses OpenAI models via the "responses" API (wire_api = "responses")
|
|
82
82
|
// Includes chat-capable models PLUS codex-only models (responses API only)
|
|
83
83
|
codex: {
|
|
84
|
-
default: 'gpt-5.3-codex
|
|
84
|
+
default: 'gpt-5.3-codex',
|
|
85
85
|
available: [
|
|
86
86
|
// Codex-specific models (responses API only, NOT available via chat/completions)
|
|
87
|
+
'gpt-5.3-codex',
|
|
87
88
|
'gpt-5.3-codex-api-preview',
|
|
88
89
|
// GPT-5.x chat models (also work via responses API)
|
|
89
90
|
'gpt-5.2-2025-12-11',
|
|
@@ -115,17 +116,48 @@ const MODELS = {
|
|
|
115
116
|
'gemini-2.0-flash-001',
|
|
116
117
|
'gemini-2.0-flash-lite-001'
|
|
117
118
|
]
|
|
119
|
+
},
|
|
120
|
+
// Grazie native Chat API models — accessible via /grazie-openai/v1 translation layer.
|
|
121
|
+
// Full list is dynamic (fetched from /user/v5/llm/profiles), this is a static fallback.
|
|
122
|
+
grazie: {
|
|
123
|
+
default: 'google-gemini-3-0-flash',
|
|
124
|
+
available: [
|
|
125
|
+
// Google
|
|
126
|
+
'google-gemini-3-1-pro',
|
|
127
|
+
'google-gemini-3-0-flash',
|
|
128
|
+
'google-chat-gemini-pro-2.5',
|
|
129
|
+
'google-gemini-2.5-flash',
|
|
130
|
+
// DeepSeek
|
|
131
|
+
'deepseek-r1',
|
|
132
|
+
'deepseek-chat-v3',
|
|
133
|
+
// Mistral
|
|
134
|
+
'mistral-large',
|
|
135
|
+
'mistral-small',
|
|
136
|
+
// xAI / Grok
|
|
137
|
+
'xai-grok-4',
|
|
138
|
+
'xai-grok-4-1-fast',
|
|
139
|
+
'xai-grok-3',
|
|
140
|
+
// Qwen
|
|
141
|
+
'qwen-max',
|
|
142
|
+
'qwen-plus',
|
|
143
|
+
// Meta (via OpenRouter)
|
|
144
|
+
'openrouter-meta-llama-4-maverick',
|
|
145
|
+
'openrouter-meta-llama-4-scout',
|
|
146
|
+
]
|
|
118
147
|
}
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
// Model aliases: some CLI tools send short names that Grazie doesn't recognise yet.
|
|
151
|
+
// Map them to the Grazie-accepted equivalents so the proxy can rewrite on the fly.
|
|
152
|
+
const MODEL_ALIASES = {
|
|
122
153
|
};
|
|
123
154
|
|
|
124
155
|
// All models for tools that support multiple providers (OpenCode, Codex)
|
|
125
156
|
const ALL_MODELS = {
|
|
126
157
|
openai: MODELS.openai.available,
|
|
127
158
|
anthropic: MODELS.claude.available,
|
|
128
|
-
gemini: MODELS.gemini.available
|
|
159
|
+
gemini: MODELS.gemini.available,
|
|
160
|
+
grazie: MODELS.grazie.available
|
|
129
161
|
};
|
|
130
162
|
|
|
131
163
|
function ensureConfigDir() {
|
|
@@ -315,6 +347,7 @@ module.exports = {
|
|
|
315
347
|
CONFIG_FILE,
|
|
316
348
|
ENDPOINTS,
|
|
317
349
|
MODELS,
|
|
350
|
+
MODEL_ALIASES,
|
|
318
351
|
ALL_MODELS,
|
|
319
352
|
TOOLS,
|
|
320
353
|
ensureConfigDir,
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
const config = require('./config');
|
|
2
|
+
|
|
3
|
+
function formatModels(models, defaultModel) {
|
|
4
|
+
return models.map((m) => {
|
|
5
|
+
const def = m === defaultModel ? ' (default)' : '';
|
|
6
|
+
return ` - ${m}${def}`;
|
|
7
|
+
}).join('\n');
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
function printGroups(groups) {
|
|
11
|
+
for (const group of groups) {
|
|
12
|
+
console.log(`${group.title}:`);
|
|
13
|
+
console.log(formatModels(group.models, group.defaultModel));
|
|
14
|
+
console.log('');
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function getGroupsForTool(tool) {
|
|
19
|
+
switch (tool) {
|
|
20
|
+
case 'claude':
|
|
21
|
+
return [
|
|
22
|
+
{
|
|
23
|
+
title: 'Claude (Anthropic)',
|
|
24
|
+
models: config.MODELS.claude.available,
|
|
25
|
+
defaultModel: config.MODELS.claude.default,
|
|
26
|
+
},
|
|
27
|
+
];
|
|
28
|
+
case 'codex':
|
|
29
|
+
return [
|
|
30
|
+
{
|
|
31
|
+
title: 'Codex (OpenAI Responses)',
|
|
32
|
+
models: config.MODELS.codex.available,
|
|
33
|
+
defaultModel: config.MODELS.codex.default,
|
|
34
|
+
},
|
|
35
|
+
];
|
|
36
|
+
case 'gemini':
|
|
37
|
+
return [
|
|
38
|
+
{
|
|
39
|
+
title: 'Gemini (Google)',
|
|
40
|
+
models: config.MODELS.gemini.available,
|
|
41
|
+
defaultModel: config.MODELS.gemini.default,
|
|
42
|
+
},
|
|
43
|
+
];
|
|
44
|
+
case 'opencode':
|
|
45
|
+
case 'goose':
|
|
46
|
+
case 'continue':
|
|
47
|
+
return [
|
|
48
|
+
{
|
|
49
|
+
title: 'Claude (Anthropic)',
|
|
50
|
+
models: config.MODELS.claude.available,
|
|
51
|
+
defaultModel: config.MODELS.claude.default,
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
title: 'GPT (OpenAI Chat)',
|
|
55
|
+
models: config.MODELS.openai.available,
|
|
56
|
+
defaultModel: config.MODELS.openai.default,
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
title: 'Grazie Native Chat (Google, DeepSeek, Mistral, xAI, Qwen, etc.)',
|
|
60
|
+
models: config.MODELS.grazie.available,
|
|
61
|
+
defaultModel: config.MODELS.grazie.default,
|
|
62
|
+
},
|
|
63
|
+
];
|
|
64
|
+
case 'all':
|
|
65
|
+
default:
|
|
66
|
+
return [
|
|
67
|
+
{
|
|
68
|
+
title: 'Claude (Anthropic)',
|
|
69
|
+
models: config.MODELS.claude.available,
|
|
70
|
+
defaultModel: config.MODELS.claude.default,
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
title: 'GPT (OpenAI Chat)',
|
|
74
|
+
models: config.MODELS.openai.available,
|
|
75
|
+
defaultModel: config.MODELS.openai.default,
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
title: 'Codex (OpenAI Responses)',
|
|
79
|
+
models: config.MODELS.codex.available,
|
|
80
|
+
defaultModel: config.MODELS.codex.default,
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
title: 'Gemini (Google)',
|
|
84
|
+
models: config.MODELS.gemini.available,
|
|
85
|
+
defaultModel: config.MODELS.gemini.default,
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
title: 'Grazie Native Chat (Google, DeepSeek, Mistral, xAI, Qwen, etc.)',
|
|
89
|
+
models: config.MODELS.grazie.available,
|
|
90
|
+
defaultModel: config.MODELS.grazie.default,
|
|
91
|
+
},
|
|
92
|
+
];
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function showModelsForTool(tool, heading) {
|
|
97
|
+
const title = heading || 'Available Grazie models:';
|
|
98
|
+
console.log(`${title}\n`);
|
|
99
|
+
const groups = getGroupsForTool(tool);
|
|
100
|
+
printGroups(groups);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function isModelsCommand(args, { allowCommand = true } = {}) {
|
|
104
|
+
if (args.includes('--models') || args.includes('--list-models')) {
|
|
105
|
+
return true;
|
|
106
|
+
}
|
|
107
|
+
if (allowCommand && args[0] === 'models') {
|
|
108
|
+
return true;
|
|
109
|
+
}
|
|
110
|
+
return false;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
module.exports = {
|
|
114
|
+
getGroupsForTool,
|
|
115
|
+
isModelsCommand,
|
|
116
|
+
showModelsForTool,
|
|
117
|
+
};
|
package/lib/proxy.js
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
const http = require('http');
|
|
2
|
+
const { spawn } = require('child_process');
|
|
3
|
+
const path = require('path');
|
|
4
|
+
|
|
5
|
+
const PROXY_PORT = 18080;
|
|
6
|
+
|
|
7
|
+
function isProxyRunning(port = PROXY_PORT) {
|
|
8
|
+
return new Promise((resolve) => {
|
|
9
|
+
const req = http.get(`http://127.0.0.1:${port}/health`, { timeout: 1000 }, (res) => {
|
|
10
|
+
let body = '';
|
|
11
|
+
res.on('data', chunk => body += chunk);
|
|
12
|
+
res.on('end', () => {
|
|
13
|
+
try {
|
|
14
|
+
const info = JSON.parse(body);
|
|
15
|
+
resolve(info.status === 'ok');
|
|
16
|
+
} catch {
|
|
17
|
+
resolve(false);
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
});
|
|
21
|
+
req.on('error', () => resolve(false));
|
|
22
|
+
req.on('timeout', () => { req.destroy(); resolve(false); });
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function startProxy(port = PROXY_PORT) {
|
|
27
|
+
const proxyScript = path.join(__dirname, '..', 'bin', 'jbai-proxy.js');
|
|
28
|
+
const child = spawn(process.execPath, [proxyScript, '--port', String(port), '--_daemon'], {
|
|
29
|
+
detached: true,
|
|
30
|
+
stdio: 'ignore',
|
|
31
|
+
});
|
|
32
|
+
child.unref();
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
async function ensureProxy(port = PROXY_PORT) {
|
|
36
|
+
if (await isProxyRunning(port)) return;
|
|
37
|
+
startProxy(port);
|
|
38
|
+
// Poll until proxy is ready (up to 5 seconds)
|
|
39
|
+
for (let i = 0; i < 20; i++) {
|
|
40
|
+
await new Promise(r => setTimeout(r, 250));
|
|
41
|
+
if (await isProxyRunning(port)) return;
|
|
42
|
+
}
|
|
43
|
+
// Proxy didn't start in time — proceed anyway, wrappers will fail with clear errors
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
module.exports = { PROXY_PORT, isProxyRunning, startProxy, ensureProxy };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jbai-cli",
|
|
3
|
-
"version": "1.9.
|
|
3
|
+
"version": "1.9.6",
|
|
4
4
|
"description": "CLI wrappers to use AI coding tools (Claude Code, Codex, Gemini CLI, OpenCode, Goose, Continue) with JetBrains AI Platform",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"jetbrains",
|
|
@@ -34,7 +34,8 @@
|
|
|
34
34
|
"jbai-gemini": "bin/jbai-gemini.js",
|
|
35
35
|
"jbai-opencode": "bin/jbai-opencode.js",
|
|
36
36
|
"jbai-goose": "bin/jbai-goose.js",
|
|
37
|
-
"jbai-continue": "bin/jbai-continue.js"
|
|
37
|
+
"jbai-continue": "bin/jbai-continue.js",
|
|
38
|
+
"jbai-council": "bin/jbai-council.js"
|
|
38
39
|
},
|
|
39
40
|
"files": [
|
|
40
41
|
"bin/",
|