jbai-cli 1.3.0 → 1.4.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/README.md +2 -2
- package/bin/jbai-aider.js +33 -1
- package/bin/jbai-gemini.js +3 -3
- package/bin/jbai-opencode.js +45 -11
- package/bin/jbai.js +33 -7
- package/lib/config.js +70 -12
- package/package.json +4 -1
package/README.md
CHANGED
|
@@ -89,8 +89,8 @@ jbai-aider --super
|
|
|
89
89
|
| Claude Code | `--dangerously-skip-permissions` |
|
|
90
90
|
| Codex | `--full-auto` |
|
|
91
91
|
| Aider | `--yes` |
|
|
92
|
-
| Gemini CLI | `--
|
|
93
|
-
| OpenCode |
|
|
92
|
+
| Gemini CLI | `--yolo` |
|
|
93
|
+
| OpenCode | N/A (run mode is already non-interactive) |
|
|
94
94
|
|
|
95
95
|
⚠️ **Use with caution** - super mode allows the AI to make changes without confirmation.
|
|
96
96
|
|
package/bin/jbai-aider.js
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
const { spawn } = require('child_process');
|
|
4
|
+
const fs = require('fs');
|
|
5
|
+
const path = require('path');
|
|
6
|
+
const os = require('os');
|
|
7
|
+
const yaml = require('yaml');
|
|
4
8
|
const config = require('../lib/config');
|
|
5
9
|
|
|
6
10
|
const token = config.getToken();
|
|
@@ -15,6 +19,7 @@ if (config.isTokenExpired(token)) {
|
|
|
15
19
|
}
|
|
16
20
|
|
|
17
21
|
const endpoints = config.getEndpoints();
|
|
22
|
+
const environment = config.getEnvironment();
|
|
18
23
|
let args = process.argv.slice(2);
|
|
19
24
|
|
|
20
25
|
// Check for super mode (--super, --yolo, -s)
|
|
@@ -22,12 +27,39 @@ const superFlags = ['--super', '--yolo', '-s'];
|
|
|
22
27
|
const superMode = args.some(a => superFlags.includes(a));
|
|
23
28
|
args = args.filter(a => !superFlags.includes(a));
|
|
24
29
|
|
|
30
|
+
// Create model settings file with extra headers for JetBrains authentication
|
|
31
|
+
const configDir = path.join(os.homedir(), '.jbai');
|
|
32
|
+
const modelSettingsFile = path.join(configDir, 'aider-model-settings.yml');
|
|
33
|
+
|
|
34
|
+
// Ensure config directory exists
|
|
35
|
+
if (!fs.existsSync(configDir)) {
|
|
36
|
+
fs.mkdirSync(configDir, { recursive: true, mode: 0o700 });
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Create model settings with extra_headers for authentication
|
|
40
|
+
// Use aider/extra_params for global settings that apply to all models
|
|
41
|
+
const modelSettings = [
|
|
42
|
+
{
|
|
43
|
+
name: 'aider/extra_params',
|
|
44
|
+
extra_params: {
|
|
45
|
+
extra_headers: {
|
|
46
|
+
'Grazie-Authenticate-JWT': token
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
];
|
|
51
|
+
|
|
52
|
+
// Write model settings file
|
|
53
|
+
fs.writeFileSync(modelSettingsFile, yaml.stringify(modelSettings), { mode: 0o600 });
|
|
54
|
+
|
|
25
55
|
// Build aider arguments
|
|
56
|
+
// Note: --no-stream is required because JetBrains proxy has stream_options issues
|
|
26
57
|
const hasModel = args.includes('--model');
|
|
27
58
|
const aiderArgs = [
|
|
28
59
|
'--openai-api-base', endpoints.openai,
|
|
29
60
|
'--openai-api-key', 'placeholder',
|
|
30
|
-
'--
|
|
61
|
+
'--model-settings-file', modelSettingsFile,
|
|
62
|
+
'--no-stream'
|
|
31
63
|
];
|
|
32
64
|
|
|
33
65
|
if (!hasModel) {
|
package/bin/jbai-gemini.js
CHANGED
|
@@ -32,10 +32,10 @@ args = args.filter(a => !superFlags.includes(a));
|
|
|
32
32
|
const hasModel = args.includes('--model') || args.includes('-m');
|
|
33
33
|
let finalArgs = hasModel ? args : ['--model', config.MODELS.gemini.default, ...args];
|
|
34
34
|
|
|
35
|
-
// Add super mode flags (auto-confirm)
|
|
35
|
+
// Add super mode flags (auto-confirm) - Gemini uses --yolo
|
|
36
36
|
if (superMode) {
|
|
37
|
-
finalArgs = ['--
|
|
38
|
-
console.log('🚀 Super mode: --
|
|
37
|
+
finalArgs = ['--yolo', ...finalArgs];
|
|
38
|
+
console.log('🚀 Super mode: --yolo (auto-confirm) enabled');
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
// Set environment for Gemini CLI
|
package/bin/jbai-opencode.js
CHANGED
|
@@ -54,12 +54,14 @@ if (!opencodeConfig.provider) {
|
|
|
54
54
|
// Environment variable name for the token
|
|
55
55
|
const envVarName = environment === 'staging' ? 'GRAZIE_STAGING_TOKEN' : 'GRAZIE_API_TOKEN';
|
|
56
56
|
|
|
57
|
-
//
|
|
57
|
+
// Provider names for OpenAI and Anthropic
|
|
58
|
+
const anthropicProviderName = environment === 'staging' ? 'jbai-anthropic-staging' : 'jbai-anthropic';
|
|
59
|
+
|
|
60
|
+
// Add/update JetBrains OpenAI provider with custom header (using env var reference)
|
|
58
61
|
// Use openai-compatible SDK which properly sends custom headers
|
|
59
|
-
// Point to OpenAI endpoint for compatibility
|
|
60
62
|
opencodeConfig.provider[providerName] = {
|
|
61
63
|
npm: '@ai-sdk/openai-compatible',
|
|
62
|
-
name: `JetBrains AI (${environment})`,
|
|
64
|
+
name: `JetBrains AI OpenAI (${environment})`,
|
|
63
65
|
options: {
|
|
64
66
|
baseURL: endpoints.openai,
|
|
65
67
|
apiKey: `{env:${envVarName}}`,
|
|
@@ -70,15 +72,48 @@ opencodeConfig.provider[providerName] = {
|
|
|
70
72
|
models: {}
|
|
71
73
|
};
|
|
72
74
|
|
|
73
|
-
// Add OpenAI models
|
|
74
|
-
// Set context and output limits to avoid "max_tokens too large" errors
|
|
75
|
+
// Add OpenAI models
|
|
75
76
|
config.MODELS.openai.available.forEach(model => {
|
|
76
77
|
opencodeConfig.provider[providerName].models[model] = {
|
|
77
78
|
name: model,
|
|
78
|
-
limit: {
|
|
79
|
-
|
|
80
|
-
|
|
79
|
+
limit: { context: 128000, output: 8192 }
|
|
80
|
+
};
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
// Add other provider models (DeepSeek, Mistral, Qwen, XAI, Meta) via OpenAI endpoint
|
|
84
|
+
const otherModels = [
|
|
85
|
+
...config.MODELS.other.deepseek,
|
|
86
|
+
...config.MODELS.other.mistral,
|
|
87
|
+
...config.MODELS.other.qwen,
|
|
88
|
+
...config.MODELS.other.xai,
|
|
89
|
+
...config.MODELS.other.meta
|
|
90
|
+
];
|
|
91
|
+
otherModels.forEach(model => {
|
|
92
|
+
opencodeConfig.provider[providerName].models[model] = {
|
|
93
|
+
name: model,
|
|
94
|
+
limit: { context: 128000, output: 8192 }
|
|
95
|
+
};
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
// Add JetBrains Anthropic provider for Claude models
|
|
99
|
+
opencodeConfig.provider[anthropicProviderName] = {
|
|
100
|
+
npm: '@ai-sdk/anthropic',
|
|
101
|
+
name: `JetBrains AI Anthropic (${environment})`,
|
|
102
|
+
options: {
|
|
103
|
+
baseURL: endpoints.anthropic,
|
|
104
|
+
apiKey: `{env:${envVarName}}`,
|
|
105
|
+
headers: {
|
|
106
|
+
'Grazie-Authenticate-JWT': `{env:${envVarName}}`
|
|
81
107
|
}
|
|
108
|
+
},
|
|
109
|
+
models: {}
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
// Add Claude models to Anthropic provider
|
|
113
|
+
config.MODELS.claude.available.forEach(model => {
|
|
114
|
+
opencodeConfig.provider[anthropicProviderName].models[model] = {
|
|
115
|
+
name: model,
|
|
116
|
+
limit: { context: 200000, output: 8192 }
|
|
82
117
|
};
|
|
83
118
|
});
|
|
84
119
|
|
|
@@ -94,10 +129,9 @@ if (!hasModel) {
|
|
|
94
129
|
finalArgs.push('--model', `${providerName}/${config.MODELS.openai.default}`);
|
|
95
130
|
}
|
|
96
131
|
|
|
97
|
-
//
|
|
132
|
+
// Note: OpenCode run is already non-interactive, no super mode needed
|
|
98
133
|
if (superMode) {
|
|
99
|
-
|
|
100
|
-
console.log('🚀 Super mode: --yes (auto-confirm) enabled');
|
|
134
|
+
console.log('ℹ️ OpenCode run is already non-interactive (no super mode flag needed)');
|
|
101
135
|
}
|
|
102
136
|
|
|
103
137
|
finalArgs.push(...args);
|
package/bin/jbai.js
CHANGED
|
@@ -219,25 +219,51 @@ function httpPost(url, body, headers) {
|
|
|
219
219
|
}
|
|
220
220
|
|
|
221
221
|
function showModels() {
|
|
222
|
-
console.log('Available Models:\n');
|
|
222
|
+
console.log('Available Models via JetBrains AI Platform (Grazie):\n');
|
|
223
223
|
|
|
224
|
-
console.log('Claude (Anthropic):');
|
|
225
|
-
config.MODELS.claude.available.forEach((m
|
|
224
|
+
console.log('Claude (Anthropic) - jbai-claude:');
|
|
225
|
+
config.MODELS.claude.available.forEach((m) => {
|
|
226
226
|
const def = m === config.MODELS.claude.default ? ' (default)' : '';
|
|
227
227
|
console.log(` - ${m}${def}`);
|
|
228
228
|
});
|
|
229
229
|
|
|
230
|
-
console.log('\nGPT (OpenAI):');
|
|
231
|
-
config.MODELS.openai.available.forEach((m
|
|
230
|
+
console.log('\nGPT (OpenAI) - jbai-codex, jbai-aider:');
|
|
231
|
+
config.MODELS.openai.available.forEach((m) => {
|
|
232
232
|
const def = m === config.MODELS.openai.default ? ' (default)' : '';
|
|
233
233
|
console.log(` - ${m}${def}`);
|
|
234
234
|
});
|
|
235
235
|
|
|
236
|
-
console.log('\nGemini (Google):');
|
|
237
|
-
config.MODELS.gemini.available.forEach((m
|
|
236
|
+
console.log('\nGemini (Google) - jbai-gemini:');
|
|
237
|
+
config.MODELS.gemini.available.forEach((m) => {
|
|
238
238
|
const def = m === config.MODELS.gemini.default ? ' (default)' : '';
|
|
239
239
|
console.log(` - ${m}${def}`);
|
|
240
240
|
});
|
|
241
|
+
|
|
242
|
+
console.log('\nDeepSeek - jbai-aider, jbai-opencode:');
|
|
243
|
+
config.MODELS.other.deepseek.forEach((m) => console.log(` - ${m}`));
|
|
244
|
+
|
|
245
|
+
console.log('\nMistral - jbai-aider, jbai-opencode:');
|
|
246
|
+
config.MODELS.other.mistral.forEach((m) => console.log(` - ${m}`));
|
|
247
|
+
|
|
248
|
+
console.log('\nQwen - jbai-aider, jbai-opencode:');
|
|
249
|
+
config.MODELS.other.qwen.forEach((m) => console.log(` - ${m}`));
|
|
250
|
+
|
|
251
|
+
console.log('\nXAI (Grok) - jbai-aider, jbai-opencode:');
|
|
252
|
+
config.MODELS.other.xai.forEach((m) => console.log(` - ${m}`));
|
|
253
|
+
|
|
254
|
+
console.log('\nMeta (Llama) - jbai-aider, jbai-opencode:');
|
|
255
|
+
config.MODELS.other.meta.forEach((m) => console.log(` - ${m}`));
|
|
256
|
+
|
|
257
|
+
// Count total
|
|
258
|
+
const total = config.MODELS.claude.available.length +
|
|
259
|
+
config.MODELS.openai.available.length +
|
|
260
|
+
config.MODELS.gemini.available.length +
|
|
261
|
+
config.MODELS.other.deepseek.length +
|
|
262
|
+
config.MODELS.other.mistral.length +
|
|
263
|
+
config.MODELS.other.qwen.length +
|
|
264
|
+
config.MODELS.other.xai.length +
|
|
265
|
+
config.MODELS.other.meta.length;
|
|
266
|
+
console.log(`\nTotal: ${total} models`);
|
|
241
267
|
}
|
|
242
268
|
|
|
243
269
|
function setEnvironment(env) {
|
package/lib/config.js
CHANGED
|
@@ -12,6 +12,7 @@ const ENDPOINTS = {
|
|
|
12
12
|
openai: 'https://api.stgn.jetbrains.ai/user/v5/llm/openai/v1',
|
|
13
13
|
anthropic: 'https://api.stgn.jetbrains.ai/user/v5/llm/anthropic/v1',
|
|
14
14
|
google: 'https://api.stgn.jetbrains.ai/user/v5/llm/google/v1/vertex',
|
|
15
|
+
profiles: 'https://api.stgn.jetbrains.ai/user/v5/llm/profiles',
|
|
15
16
|
tokenUrl: 'https://platform.stgn.jetbrains.ai/'
|
|
16
17
|
},
|
|
17
18
|
production: {
|
|
@@ -19,43 +20,99 @@ const ENDPOINTS = {
|
|
|
19
20
|
openai: 'https://api.jetbrains.ai/user/v5/llm/openai/v1',
|
|
20
21
|
anthropic: 'https://api.jetbrains.ai/user/v5/llm/anthropic/v1',
|
|
21
22
|
google: 'https://api.jetbrains.ai/user/v5/llm/google/v1/vertex',
|
|
23
|
+
profiles: 'https://api.jetbrains.ai/user/v5/llm/profiles',
|
|
22
24
|
tokenUrl: 'https://platform.jetbrains.ai/'
|
|
23
25
|
}
|
|
24
26
|
};
|
|
25
27
|
|
|
28
|
+
// All models available from JetBrains AI Platform (Grazie)
|
|
29
|
+
// Model names are mapped to SDK-compatible format
|
|
26
30
|
const MODELS = {
|
|
27
31
|
claude: {
|
|
28
32
|
default: 'claude-sonnet-4-5-20250929',
|
|
29
33
|
available: [
|
|
34
|
+
// Claude 4.x series (latest)
|
|
35
|
+
'claude-opus-4-5-20250929',
|
|
30
36
|
'claude-sonnet-4-5-20250929',
|
|
37
|
+
'claude-haiku-4-5-20250929',
|
|
31
38
|
'claude-opus-4-1-20250805',
|
|
39
|
+
'claude-opus-4-20250514',
|
|
32
40
|
'claude-sonnet-4-20250514',
|
|
41
|
+
// Claude 3.x series
|
|
33
42
|
'claude-3-7-sonnet-20250219',
|
|
34
|
-
'claude-3-5-
|
|
43
|
+
'claude-3-5-sonnet-20241022',
|
|
44
|
+
'claude-3-5-haiku-20241022',
|
|
45
|
+
'claude-3-haiku-20240307'
|
|
35
46
|
]
|
|
36
47
|
},
|
|
37
48
|
openai: {
|
|
38
|
-
default: 'gpt-4o
|
|
49
|
+
default: 'gpt-4o',
|
|
39
50
|
available: [
|
|
40
|
-
|
|
41
|
-
'gpt-5
|
|
42
|
-
'gpt-5.1
|
|
43
|
-
'gpt-5
|
|
44
|
-
'
|
|
45
|
-
'
|
|
51
|
+
// GPT-5.x series (latest)
|
|
52
|
+
'gpt-5',
|
|
53
|
+
'gpt-5.1',
|
|
54
|
+
'gpt-5.2',
|
|
55
|
+
'gpt-5-mini',
|
|
56
|
+
'gpt-5-nano',
|
|
57
|
+
'gpt-5-codex',
|
|
58
|
+
'gpt-5.1-codex',
|
|
59
|
+
'gpt-5.1-codex-max',
|
|
60
|
+
'gpt-5.1-codex-mini',
|
|
61
|
+
'gpt-5.2-codex',
|
|
62
|
+
'gpt-5.2-pro',
|
|
63
|
+
// GPT-4.x series
|
|
64
|
+
'gpt-4.1',
|
|
65
|
+
'gpt-4.1-mini',
|
|
66
|
+
'gpt-4.1-nano',
|
|
67
|
+
'gpt-4o',
|
|
68
|
+
'gpt-4o-mini',
|
|
69
|
+
'gpt-4-turbo',
|
|
70
|
+
'gpt-4',
|
|
71
|
+
// O-series (reasoning)
|
|
72
|
+
'o1',
|
|
73
|
+
'o3',
|
|
74
|
+
'o3-mini',
|
|
75
|
+
'o4-mini'
|
|
46
76
|
]
|
|
47
77
|
},
|
|
48
78
|
gemini: {
|
|
49
79
|
default: 'gemini-2.5-flash',
|
|
50
80
|
available: [
|
|
51
|
-
|
|
81
|
+
// Gemini 3.x (latest)
|
|
82
|
+
'gemini-3.0-pro',
|
|
83
|
+
'gemini-3.0-flash',
|
|
84
|
+
// Gemini 2.x
|
|
52
85
|
'gemini-2.5-pro',
|
|
53
|
-
'gemini-
|
|
54
|
-
'gemini-
|
|
86
|
+
'gemini-2.5-flash',
|
|
87
|
+
'gemini-2.5-flash-lite',
|
|
88
|
+
'gemini-2.0-flash',
|
|
89
|
+
'gemini-2.0-flash-lite'
|
|
55
90
|
]
|
|
91
|
+
},
|
|
92
|
+
// Other providers available via Grazie
|
|
93
|
+
other: {
|
|
94
|
+
deepseek: ['deepseek-r1'],
|
|
95
|
+
mistral: ['mistral-large', 'mistral-small', 'mistral-codestral', 'mistral-open-7b', 'mixtral-open-8x7b', 'mixtral-open-8x22b'],
|
|
96
|
+
qwen: ['qwen-max', 'qwen-max-longcontext', 'qwen-plus', 'qwen-turbo'],
|
|
97
|
+
xai: ['xai-grok-4', 'xai-grok-4-fast', 'xai-grok-4-1-fast', 'xai-grok-code-fast-1'],
|
|
98
|
+
meta: ['grazie-chat-llama-v3-8b-instruct']
|
|
56
99
|
}
|
|
57
100
|
};
|
|
58
101
|
|
|
102
|
+
// All models for tools that support multiple providers (like Aider, OpenCode)
|
|
103
|
+
const ALL_MODELS = {
|
|
104
|
+
openai: MODELS.openai.available,
|
|
105
|
+
anthropic: MODELS.claude.available,
|
|
106
|
+
gemini: MODELS.gemini.available,
|
|
107
|
+
other: [
|
|
108
|
+
...MODELS.other.deepseek,
|
|
109
|
+
...MODELS.other.mistral,
|
|
110
|
+
...MODELS.other.qwen,
|
|
111
|
+
...MODELS.other.xai,
|
|
112
|
+
...MODELS.other.meta
|
|
113
|
+
]
|
|
114
|
+
};
|
|
115
|
+
|
|
59
116
|
function ensureConfigDir() {
|
|
60
117
|
if (!fs.existsSync(CONFIG_DIR)) {
|
|
61
118
|
fs.mkdirSync(CONFIG_DIR, { recursive: true, mode: 0o700 });
|
|
@@ -136,7 +193,7 @@ const TOOLS = {
|
|
|
136
193
|
aider: {
|
|
137
194
|
name: 'Aider',
|
|
138
195
|
command: 'aider',
|
|
139
|
-
install: '
|
|
196
|
+
install: 'brew install aider'
|
|
140
197
|
},
|
|
141
198
|
gemini: {
|
|
142
199
|
name: 'Gemini CLI',
|
|
@@ -156,6 +213,7 @@ module.exports = {
|
|
|
156
213
|
CONFIG_FILE,
|
|
157
214
|
ENDPOINTS,
|
|
158
215
|
MODELS,
|
|
216
|
+
ALL_MODELS,
|
|
159
217
|
TOOLS,
|
|
160
218
|
ensureConfigDir,
|
|
161
219
|
getToken,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jbai-cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"description": "CLI wrappers to use AI coding tools (Claude Code, Codex, Aider, Gemini CLI, OpenCode) with JetBrains AI Platform",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"jetbrains",
|
|
@@ -41,6 +41,9 @@
|
|
|
41
41
|
"engines": {
|
|
42
42
|
"node": ">=18.0.0"
|
|
43
43
|
},
|
|
44
|
+
"dependencies": {
|
|
45
|
+
"yaml": "^2.7.1"
|
|
46
|
+
},
|
|
44
47
|
"scripts": {
|
|
45
48
|
"postinstall": "node lib/postinstall.js",
|
|
46
49
|
"test": "node bin/jbai.js test"
|