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 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 | `--yes` |
93
- | OpenCode | `--yes` |
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
- '--extra-headers', JSON.stringify({ 'Grazie-Authenticate-JWT': token })
61
+ '--model-settings-file', modelSettingsFile,
62
+ '--no-stream'
31
63
  ];
32
64
 
33
65
  if (!hasModel) {
@@ -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 = ['--yes', ...finalArgs];
38
- console.log('🚀 Super mode: --yes (auto-confirm) enabled');
37
+ finalArgs = ['--yolo', ...finalArgs];
38
+ console.log('🚀 Super mode: --yolo (auto-confirm) enabled');
39
39
  }
40
40
 
41
41
  // Set environment for Gemini CLI
@@ -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
- // Add/update JetBrains provider with custom header (using env var reference)
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 (since we use openai-compatible SDK)
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
- context: 128000,
80
- output: 8192
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
- // Add super mode flags
132
+ // Note: OpenCode run is already non-interactive, no super mode needed
98
133
  if (superMode) {
99
- finalArgs.push('--yes');
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, i) => {
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, i) => {
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, i) => {
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-haiku-20241022'
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-2024-11-20',
49
+ default: 'gpt-4o',
39
50
  available: [
40
- 'gpt-4o-2024-11-20',
41
- 'gpt-5-2025-08-07',
42
- 'gpt-5.1-2025-11-13',
43
- 'gpt-5-mini-2025-08-07',
44
- 'o3-2025-04-16',
45
- 'o3-mini-2025-01-31'
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
- 'gemini-2.5-flash',
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-3-pro-preview',
54
- 'gemini-3-flash-preview'
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: 'pipx install aider-chat'
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.0",
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"