jbai-cli 1.8.2 → 1.9.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/README.md +54 -35
- package/bin/jbai-continue.js +190 -0
- package/bin/jbai-goose.js +145 -0
- package/bin/jbai-opencode.js +14 -2
- package/bin/jbai.js +14 -2
- package/lib/config.js +13 -2
- package/lib/postinstall.js +4 -2
- package/package.json +7 -3
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
**Use AI coding tools with your JetBrains AI subscription** — no separate API keys needed.
|
|
4
4
|
|
|
5
|
-
One token, all tools: Claude Code, Codex,
|
|
5
|
+
One token, all tools: Claude Code, Codex, Gemini CLI, OpenCode, Goose, Continue, **Codex Desktop, Cursor**.
|
|
6
6
|
|
|
7
7
|
## Install
|
|
8
8
|
|
|
@@ -149,17 +149,27 @@ jbai-codex
|
|
|
149
149
|
jbai-codex exec "explain this codebase"
|
|
150
150
|
```
|
|
151
151
|
|
|
152
|
-
###
|
|
152
|
+
### OpenCode
|
|
153
|
+
```bash
|
|
154
|
+
jbai-opencode
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### Goose (Block)
|
|
153
158
|
```bash
|
|
154
|
-
|
|
159
|
+
# Interactive session
|
|
160
|
+
jbai-goose
|
|
155
161
|
|
|
156
|
-
#
|
|
157
|
-
jbai-
|
|
162
|
+
# One-shot task
|
|
163
|
+
jbai-goose run -t "explain this codebase"
|
|
158
164
|
```
|
|
159
165
|
|
|
160
|
-
###
|
|
166
|
+
### Continue CLI
|
|
161
167
|
```bash
|
|
162
|
-
|
|
168
|
+
# Interactive TUI
|
|
169
|
+
jbai-continue
|
|
170
|
+
|
|
171
|
+
# One-shot (print and exit)
|
|
172
|
+
jbai-continue -p "explain this function"
|
|
163
173
|
```
|
|
164
174
|
|
|
165
175
|
### Handoff to Orca Lab (local)
|
|
@@ -179,7 +189,7 @@ jbai handoff --task "add new e2e test" \
|
|
|
179
189
|
```
|
|
180
190
|
|
|
181
191
|
### In-session handoff (interactive tools)
|
|
182
|
-
While running `jbai-codex`, `jbai-claude`, `jbai-gemini`, or `jbai-
|
|
192
|
+
While running `jbai-codex`, `jbai-claude`, `jbai-gemini`, `jbai-opencode`, `jbai-goose`, or `jbai-continue`:
|
|
183
193
|
- Press `Ctrl+]` to trigger a handoff to Orca Lab.
|
|
184
194
|
- The last prompt you typed is used as the task.
|
|
185
195
|
|
|
@@ -206,67 +216,77 @@ jbai-claude --super
|
|
|
206
216
|
# Codex - full auto mode
|
|
207
217
|
jbai-codex --super exec "refactor this code"
|
|
208
218
|
|
|
209
|
-
# Aider - auto-confirm all changes
|
|
210
|
-
jbai-aider --super
|
|
211
219
|
```
|
|
212
220
|
|
|
213
221
|
| Tool | Super Mode Flag |
|
|
214
222
|
|------|-----------------|
|
|
215
223
|
| Claude Code | `--dangerously-skip-permissions` |
|
|
216
224
|
| Codex | `--full-auto` |
|
|
217
|
-
| Aider | `--yes` |
|
|
218
225
|
| Gemini CLI | `--yolo` |
|
|
219
226
|
| OpenCode | N/A (run mode is already non-interactive) |
|
|
227
|
+
| Goose | `GOOSE_MODE=auto` |
|
|
228
|
+
| Continue CLI | `--auto` |
|
|
220
229
|
|
|
221
230
|
## Using Different Models
|
|
222
231
|
|
|
223
232
|
Each tool has a sensible default, but you can specify any available model:
|
|
224
233
|
|
|
225
234
|
```bash
|
|
226
|
-
# Claude with Opus
|
|
227
|
-
jbai-claude --model claude-opus-4-
|
|
235
|
+
# Claude with Opus 4.6
|
|
236
|
+
jbai-claude --model claude-opus-4-6
|
|
228
237
|
|
|
229
|
-
# Codex with GPT-5
|
|
230
|
-
jbai-codex --model gpt-5.
|
|
238
|
+
# Codex with GPT-5.3
|
|
239
|
+
jbai-codex --model gpt-5.3-codex-api-preview
|
|
231
240
|
|
|
232
|
-
#
|
|
233
|
-
jbai-
|
|
241
|
+
# Goose with GPT-5.2
|
|
242
|
+
jbai-goose run -t "your task" --provider openai --model gpt-5.2-2025-12-11
|
|
243
|
+
|
|
244
|
+
# Continue with Claude Opus 4.6
|
|
245
|
+
jbai-continue # select model in TUI
|
|
234
246
|
```
|
|
235
247
|
|
|
236
248
|
### Available Models
|
|
237
249
|
|
|
238
|
-
**Claude (Anthropic)**
|
|
250
|
+
**Claude (Anthropic)** - Default for Goose, Continue
|
|
239
251
|
| Model | Notes |
|
|
240
252
|
|-------|-------|
|
|
241
|
-
| `claude-sonnet-4-5-20250929` | Default
|
|
242
|
-
| `claude-opus-4-
|
|
253
|
+
| `claude-sonnet-4-5-20250929` | Default |
|
|
254
|
+
| `claude-opus-4-6` | Most capable (latest) |
|
|
255
|
+
| `claude-opus-4-5-20251101` | |
|
|
256
|
+
| `claude-opus-4-1-20250805` | |
|
|
243
257
|
| `claude-sonnet-4-20250514` | |
|
|
258
|
+
| `claude-haiku-4-5-20251001` | Fast |
|
|
244
259
|
| `claude-3-7-sonnet-20250219` | |
|
|
245
|
-
| `claude-3-5-haiku-20241022` |
|
|
260
|
+
| `claude-3-5-haiku-20241022` | Fastest |
|
|
246
261
|
|
|
247
|
-
**GPT (OpenAI)**
|
|
262
|
+
**GPT (OpenAI Chat)** - Default for OpenCode
|
|
248
263
|
| Model | Notes |
|
|
249
264
|
|-------|-------|
|
|
250
|
-
| `gpt-
|
|
251
|
-
| `gpt-5
|
|
265
|
+
| `gpt-5.2-2025-12-11` | Default, latest |
|
|
266
|
+
| `gpt-5.2` | Alias |
|
|
252
267
|
| `gpt-5.1-2025-11-13` | |
|
|
253
|
-
| `gpt-5
|
|
268
|
+
| `gpt-5-2025-08-07` | |
|
|
254
269
|
| `gpt-5-mini-2025-08-07` | Fast |
|
|
270
|
+
| `gpt-5-nano-2025-08-07` | Fastest |
|
|
271
|
+
| `gpt-4.1-2025-04-14` | |
|
|
272
|
+
| `o4-mini-2025-04-16` | Reasoning |
|
|
255
273
|
| `o3-2025-04-16` | Reasoning |
|
|
256
|
-
| `o3-mini-2025-01-31` | |
|
|
257
274
|
|
|
258
275
|
**Codex (OpenAI Responses)** - Use with Codex CLI: `jbai-codex --model <model>`
|
|
259
276
|
| Model | Notes |
|
|
260
277
|
|-------|-------|
|
|
261
|
-
| `gpt-5.
|
|
278
|
+
| `gpt-5.3-codex-api-preview` | Default, latest |
|
|
279
|
+
| `gpt-5.2-codex` | Coding-optimized |
|
|
280
|
+
| `gpt-5.2-pro-2025-12-11` | |
|
|
262
281
|
| `gpt-5.1-codex` | |
|
|
263
|
-
| `gpt-5.1-codex-
|
|
264
|
-
| `gpt-5.1-codex-
|
|
282
|
+
| `gpt-5.1-codex-max` | Most capable |
|
|
283
|
+
| `gpt-5.1-codex-mini` | Fast |
|
|
284
|
+
| `gpt-5-codex` | |
|
|
265
285
|
|
|
266
|
-
**Gemini (Google)** - Use with
|
|
286
|
+
**Gemini (Google)** - Use with Gemini CLI: `jbai-gemini`
|
|
267
287
|
| Model | Notes |
|
|
268
288
|
|-------|-------|
|
|
269
|
-
| `gemini-2.5-flash` |
|
|
289
|
+
| `gemini-2.5-flash` | Default, fast |
|
|
270
290
|
| `gemini-2.5-pro` | More capable |
|
|
271
291
|
| `gemini-3-pro-preview` | Preview |
|
|
272
292
|
| `gemini-3-flash-preview` | Preview |
|
|
@@ -301,8 +321,6 @@ jbai install
|
|
|
301
321
|
# Install specific tool
|
|
302
322
|
jbai install claude
|
|
303
323
|
jbai install codex
|
|
304
|
-
jbai install aider
|
|
305
|
-
|
|
306
324
|
# Check what's installed
|
|
307
325
|
jbai doctor
|
|
308
326
|
```
|
|
@@ -313,8 +331,9 @@ jbai doctor
|
|
|
313
331
|
|------|-----------------|
|
|
314
332
|
| Claude Code | `npm i -g @anthropic-ai/claude-code` |
|
|
315
333
|
| Codex | `npm i -g @openai/codex` |
|
|
316
|
-
|
|
|
317
|
-
|
|
|
334
|
+
| OpenCode | `npm i -g opencode-ai` |
|
|
335
|
+
| Goose | `brew install block-goose-cli` |
|
|
336
|
+
| Continue CLI | `npm i -g @continuedev/cli` |
|
|
318
337
|
|
|
319
338
|
## Token Management
|
|
320
339
|
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* jbai-continue - Continue CLI wrapper for JetBrains AI Platform
|
|
5
|
+
*
|
|
6
|
+
* Generates ~/.continue/config.yaml with Grazie models via jbai-proxy,
|
|
7
|
+
* then launches `cn` (Continue CLI).
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const { runWithHandoff, stripHandoffFlag } = require('../lib/interactive-handoff');
|
|
11
|
+
const fs = require('fs');
|
|
12
|
+
const path = require('path');
|
|
13
|
+
const os = require('os');
|
|
14
|
+
const http = require('http');
|
|
15
|
+
const config = require('../lib/config');
|
|
16
|
+
const { ensureToken } = require('../lib/ensure-token');
|
|
17
|
+
|
|
18
|
+
const PROXY_PORT = 18080;
|
|
19
|
+
|
|
20
|
+
function isProxyRunning() {
|
|
21
|
+
return new Promise((resolve) => {
|
|
22
|
+
const req = http.get(`http://127.0.0.1:${PROXY_PORT}/health`, { timeout: 1000 }, (res) => {
|
|
23
|
+
let body = '';
|
|
24
|
+
res.on('data', chunk => body += chunk);
|
|
25
|
+
res.on('end', () => {
|
|
26
|
+
try {
|
|
27
|
+
const info = JSON.parse(body);
|
|
28
|
+
resolve(info.status === 'ok');
|
|
29
|
+
} catch {
|
|
30
|
+
resolve(false);
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
req.on('error', () => resolve(false));
|
|
35
|
+
req.on('timeout', () => { req.destroy(); resolve(false); });
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function startProxy() {
|
|
40
|
+
const { spawn } = require('child_process');
|
|
41
|
+
const proxyScript = path.join(__dirname, 'jbai-proxy.js');
|
|
42
|
+
const child = spawn(process.execPath, [proxyScript, '--port', String(PROXY_PORT), '--_daemon'], {
|
|
43
|
+
detached: true,
|
|
44
|
+
stdio: 'ignore',
|
|
45
|
+
});
|
|
46
|
+
child.unref();
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function buildContinueConfig() {
|
|
50
|
+
const proxyBase = `http://127.0.0.1:${PROXY_PORT}`;
|
|
51
|
+
const models = [];
|
|
52
|
+
|
|
53
|
+
// Add Claude models first (default provider)
|
|
54
|
+
config.MODELS.claude.available.forEach(model => {
|
|
55
|
+
const isDefault = model === config.MODELS.claude.default;
|
|
56
|
+
models.push({
|
|
57
|
+
name: isDefault ? `${model} (default)` : model,
|
|
58
|
+
provider: 'anthropic',
|
|
59
|
+
model,
|
|
60
|
+
apiBase: `${proxyBase}/anthropic/v1`,
|
|
61
|
+
apiKey: 'placeholder',
|
|
62
|
+
roles: ['chat', 'edit'],
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
// Add OpenAI models via proxy
|
|
67
|
+
config.MODELS.openai.available.forEach(model => {
|
|
68
|
+
models.push({
|
|
69
|
+
name: model,
|
|
70
|
+
provider: 'openai',
|
|
71
|
+
model,
|
|
72
|
+
apiBase: `${proxyBase}/openai/v1`,
|
|
73
|
+
apiKey: 'placeholder',
|
|
74
|
+
roles: ['chat', 'edit'],
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
const defaultModel = `${config.MODELS.claude.default} (default)`;
|
|
79
|
+
|
|
80
|
+
return {
|
|
81
|
+
name: 'JetBrains AI',
|
|
82
|
+
version: '0.0.1',
|
|
83
|
+
schema: 'v1',
|
|
84
|
+
defaultModel,
|
|
85
|
+
models,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function toYaml(obj, indent = 0) {
|
|
90
|
+
const pad = ' '.repeat(indent);
|
|
91
|
+
let out = '';
|
|
92
|
+
if (Array.isArray(obj)) {
|
|
93
|
+
for (const item of obj) {
|
|
94
|
+
if (typeof item === 'object' && item !== null) {
|
|
95
|
+
out += `${pad}-\n`;
|
|
96
|
+
out += toYaml(item, indent + 2);
|
|
97
|
+
} else {
|
|
98
|
+
out += `${pad}- ${item}\n`;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
} else if (typeof obj === 'object' && obj !== null) {
|
|
102
|
+
for (const [key, val] of Object.entries(obj)) {
|
|
103
|
+
if (Array.isArray(val)) {
|
|
104
|
+
out += `${pad}${key}:\n`;
|
|
105
|
+
out += toYaml(val, indent + 2);
|
|
106
|
+
} else if (typeof val === 'object' && val !== null) {
|
|
107
|
+
out += `${pad}${key}:\n`;
|
|
108
|
+
out += toYaml(val, indent + 2);
|
|
109
|
+
} else {
|
|
110
|
+
out += `${pad}${key}: ${JSON.stringify(val)}\n`;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return out;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
(async () => {
|
|
118
|
+
const token = await ensureToken();
|
|
119
|
+
const environment = config.getEnvironment();
|
|
120
|
+
let args = process.argv.slice(2);
|
|
121
|
+
const handoffConfig = stripHandoffFlag(args);
|
|
122
|
+
args = handoffConfig.args;
|
|
123
|
+
|
|
124
|
+
// Check for super mode (--super, --yolo, -s)
|
|
125
|
+
const superFlags = ['--super', '--yolo', '-s'];
|
|
126
|
+
const superMode = args.some(a => superFlags.includes(a));
|
|
127
|
+
args = args.filter(a => !superFlags.includes(a));
|
|
128
|
+
|
|
129
|
+
// Auto-start proxy if not running
|
|
130
|
+
if (!await isProxyRunning()) {
|
|
131
|
+
startProxy();
|
|
132
|
+
await new Promise(r => setTimeout(r, 500));
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// Write Continue config
|
|
136
|
+
const configDir = path.join(os.homedir(), '.continue');
|
|
137
|
+
const configFile = path.join(configDir, 'config.yaml');
|
|
138
|
+
|
|
139
|
+
if (!fs.existsSync(configDir)) {
|
|
140
|
+
fs.mkdirSync(configDir, { recursive: true });
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
const continueConfig = buildContinueConfig();
|
|
144
|
+
const yaml = `# Auto-generated by jbai-cli — do not edit manually\n${toYaml(continueConfig)}`;
|
|
145
|
+
fs.writeFileSync(configFile, yaml);
|
|
146
|
+
|
|
147
|
+
let finalArgs = [];
|
|
148
|
+
|
|
149
|
+
// Add auto mode (allow all tools) if super
|
|
150
|
+
if (superMode) {
|
|
151
|
+
finalArgs.push('--auto');
|
|
152
|
+
console.log('🚀 Super mode: --auto (all tools allowed) enabled');
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
finalArgs.push(...args);
|
|
156
|
+
|
|
157
|
+
const childEnv = {
|
|
158
|
+
...process.env,
|
|
159
|
+
OPENAI_API_KEY: 'placeholder',
|
|
160
|
+
ANTHROPIC_API_KEY: 'placeholder',
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
const child = runWithHandoff({
|
|
164
|
+
command: 'cn',
|
|
165
|
+
args: finalArgs,
|
|
166
|
+
env: childEnv,
|
|
167
|
+
toolName: 'jbai-continue',
|
|
168
|
+
handoffDefaults: {
|
|
169
|
+
enabled: !handoffConfig.disabled,
|
|
170
|
+
grazieToken: token,
|
|
171
|
+
grazieEnvironment: environment === 'production' ? 'PRODUCTION' : 'STAGING',
|
|
172
|
+
grazieModel: config.MODELS.claude.default,
|
|
173
|
+
cwd: process.cwd(),
|
|
174
|
+
},
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
if (child && typeof child.on === 'function') {
|
|
178
|
+
child.on('error', (err) => {
|
|
179
|
+
if (err.code === 'ENOENT') {
|
|
180
|
+
const tool = config.TOOLS.continue;
|
|
181
|
+
console.error(`❌ ${tool.name} not found.\n`);
|
|
182
|
+
console.error(`Install with: ${tool.install}`);
|
|
183
|
+
console.error(`Or run: jbai install continue`);
|
|
184
|
+
} else {
|
|
185
|
+
console.error(`Error: ${err.message}`);
|
|
186
|
+
}
|
|
187
|
+
process.exit(1);
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
})();
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* jbai-goose - Goose CLI wrapper for JetBrains AI Platform
|
|
5
|
+
*
|
|
6
|
+
* Uses jbai-proxy on localhost:18080 to route requests through Grazie.
|
|
7
|
+
* Goose uses OPENAI_HOST + OPENAI_API_KEY env vars for the OpenAI provider.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const { runWithHandoff, stripHandoffFlag } = require('../lib/interactive-handoff');
|
|
11
|
+
const path = require('path');
|
|
12
|
+
const http = require('http');
|
|
13
|
+
const config = require('../lib/config');
|
|
14
|
+
const { ensureToken } = require('../lib/ensure-token');
|
|
15
|
+
|
|
16
|
+
const PROXY_PORT = 18080;
|
|
17
|
+
|
|
18
|
+
function isProxyRunning() {
|
|
19
|
+
return new Promise((resolve) => {
|
|
20
|
+
const req = http.get(`http://127.0.0.1:${PROXY_PORT}/health`, { timeout: 1000 }, (res) => {
|
|
21
|
+
let body = '';
|
|
22
|
+
res.on('data', chunk => body += chunk);
|
|
23
|
+
res.on('end', () => {
|
|
24
|
+
try {
|
|
25
|
+
const info = JSON.parse(body);
|
|
26
|
+
resolve(info.status === 'ok');
|
|
27
|
+
} catch {
|
|
28
|
+
resolve(false);
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
req.on('error', () => resolve(false));
|
|
33
|
+
req.on('timeout', () => { req.destroy(); resolve(false); });
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function startProxy() {
|
|
38
|
+
const { spawn } = require('child_process');
|
|
39
|
+
const proxyScript = path.join(__dirname, 'jbai-proxy.js');
|
|
40
|
+
const child = spawn(process.execPath, [proxyScript, '--port', String(PROXY_PORT), '--_daemon'], {
|
|
41
|
+
detached: true,
|
|
42
|
+
stdio: 'ignore',
|
|
43
|
+
});
|
|
44
|
+
child.unref();
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
(async () => {
|
|
48
|
+
const token = await ensureToken();
|
|
49
|
+
const environment = config.getEnvironment();
|
|
50
|
+
let args = process.argv.slice(2);
|
|
51
|
+
const handoffConfig = stripHandoffFlag(args);
|
|
52
|
+
args = handoffConfig.args;
|
|
53
|
+
|
|
54
|
+
// Check for super mode (--super, --yolo, -s)
|
|
55
|
+
const superFlags = ['--super', '--yolo', '-s'];
|
|
56
|
+
const superMode = args.some(a => superFlags.includes(a));
|
|
57
|
+
args = args.filter(a => !superFlags.includes(a));
|
|
58
|
+
|
|
59
|
+
// Auto-start proxy if not running
|
|
60
|
+
if (!await isProxyRunning()) {
|
|
61
|
+
startProxy();
|
|
62
|
+
await new Promise(r => setTimeout(r, 500));
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Determine if this is a "run" or "session" command
|
|
66
|
+
const isRun = args[0] === 'run';
|
|
67
|
+
const isSession = args[0] === 'session' || args.length === 0;
|
|
68
|
+
|
|
69
|
+
// Check if model specified via args or env
|
|
70
|
+
const hasModel = args.includes('--model');
|
|
71
|
+
const hasProvider = args.includes('--provider');
|
|
72
|
+
|
|
73
|
+
let finalArgs = [...args];
|
|
74
|
+
|
|
75
|
+
// Default to session if no subcommand given
|
|
76
|
+
if (args.length === 0 || (!isRun && !isSession && !['configure', 'info', 'update', 'help'].includes(args[0]))) {
|
|
77
|
+
if (args.length === 0) {
|
|
78
|
+
finalArgs = ['session'];
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Determine provider from --model flag or default to anthropic (Claude)
|
|
83
|
+
const modelIdx = args.indexOf('--model');
|
|
84
|
+
const requestedModel = modelIdx >= 0 ? args[modelIdx + 1] : null;
|
|
85
|
+
const isClaudeModel = requestedModel
|
|
86
|
+
? requestedModel.startsWith('claude')
|
|
87
|
+
: true; // default to Claude
|
|
88
|
+
|
|
89
|
+
const defaultProvider = isClaudeModel ? 'anthropic' : 'openai';
|
|
90
|
+
const defaultModel = isClaudeModel ? config.MODELS.claude.default : config.MODELS.openai.default;
|
|
91
|
+
|
|
92
|
+
// Inject provider and model if not specified
|
|
93
|
+
if (!hasProvider && (isSession || isRun || args.length === 0)) {
|
|
94
|
+
finalArgs.push('--provider', defaultProvider);
|
|
95
|
+
}
|
|
96
|
+
if (!hasModel && (isSession || isRun || args.length === 0)) {
|
|
97
|
+
finalArgs.push('--model', defaultModel);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Add super mode (auto-approve all tool calls)
|
|
101
|
+
if (superMode) {
|
|
102
|
+
console.log('🚀 Super mode: auto-approve enabled');
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const childEnv = {
|
|
106
|
+
...process.env,
|
|
107
|
+
// Configure both providers so --provider/--model can switch freely
|
|
108
|
+
OPENAI_HOST: `http://127.0.0.1:${PROXY_PORT}/openai`,
|
|
109
|
+
OPENAI_API_KEY: 'placeholder',
|
|
110
|
+
ANTHROPIC_HOST: `http://127.0.0.1:${PROXY_PORT}/anthropic`,
|
|
111
|
+
ANTHROPIC_API_KEY: 'placeholder',
|
|
112
|
+
GOOSE_PROVIDER: defaultProvider,
|
|
113
|
+
GOOSE_MODEL: defaultModel,
|
|
114
|
+
// Auto-approve mode if super
|
|
115
|
+
...(superMode ? { GOOSE_MODE: 'auto' } : {}),
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
const child = runWithHandoff({
|
|
119
|
+
command: 'goose',
|
|
120
|
+
args: finalArgs,
|
|
121
|
+
env: childEnv,
|
|
122
|
+
toolName: 'jbai-goose',
|
|
123
|
+
handoffDefaults: {
|
|
124
|
+
enabled: !handoffConfig.disabled,
|
|
125
|
+
grazieToken: token,
|
|
126
|
+
grazieEnvironment: environment === 'production' ? 'PRODUCTION' : 'STAGING',
|
|
127
|
+
grazieModel: config.MODELS.claude.default,
|
|
128
|
+
cwd: process.cwd(),
|
|
129
|
+
},
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
if (child && typeof child.on === 'function') {
|
|
133
|
+
child.on('error', (err) => {
|
|
134
|
+
if (err.code === 'ENOENT') {
|
|
135
|
+
const tool = config.TOOLS.goose;
|
|
136
|
+
console.error(`❌ ${tool.name} not found.\n`);
|
|
137
|
+
console.error(`Install with: ${tool.install}`);
|
|
138
|
+
console.error(`Or run: jbai install goose`);
|
|
139
|
+
} else {
|
|
140
|
+
console.error(`Error: ${err.message}`);
|
|
141
|
+
}
|
|
142
|
+
process.exit(1);
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
})();
|
package/bin/jbai-opencode.js
CHANGED
|
@@ -106,8 +106,20 @@ const { ensureToken } = require('../lib/ensure-token');
|
|
|
106
106
|
// format (used by jbai-gemini), not OpenAI chat/completions format.
|
|
107
107
|
// Use `jbai gemini` instead for Gemini models.
|
|
108
108
|
|
|
109
|
-
// Enable max permissions (
|
|
110
|
-
opencodeConfig.
|
|
109
|
+
// Enable max permissions for the build agent (allow all tools without asking)
|
|
110
|
+
if (!opencodeConfig.agent) {
|
|
111
|
+
opencodeConfig.agent = {};
|
|
112
|
+
}
|
|
113
|
+
if (!opencodeConfig.agent.build) {
|
|
114
|
+
opencodeConfig.agent.build = {};
|
|
115
|
+
}
|
|
116
|
+
opencodeConfig.agent.build.permission = 'allow';
|
|
117
|
+
|
|
118
|
+
// Only show JetBrains AI providers in the model picker
|
|
119
|
+
opencodeConfig.enabled_providers = [providerName, anthropicProviderName];
|
|
120
|
+
|
|
121
|
+
// Clean up legacy keys that newer OpenCode versions reject
|
|
122
|
+
delete opencodeConfig.yolo;
|
|
111
123
|
|
|
112
124
|
// Write config
|
|
113
125
|
fs.writeFileSync(configFile, JSON.stringify(opencodeConfig, null, 2));
|
package/bin/jbai.js
CHANGED
|
@@ -30,6 +30,18 @@ const TOOLS = {
|
|
|
30
30
|
command: 'opencode',
|
|
31
31
|
install: 'npm install -g opencode-ai',
|
|
32
32
|
check: 'opencode --version'
|
|
33
|
+
},
|
|
34
|
+
goose: {
|
|
35
|
+
name: 'Goose',
|
|
36
|
+
command: 'goose',
|
|
37
|
+
install: 'brew install block-goose-cli',
|
|
38
|
+
check: 'goose --version'
|
|
39
|
+
},
|
|
40
|
+
continue: {
|
|
41
|
+
name: 'Continue CLI',
|
|
42
|
+
command: 'cn',
|
|
43
|
+
install: 'npm install -g @continuedev/cli',
|
|
44
|
+
check: 'cn --version'
|
|
33
45
|
}
|
|
34
46
|
};
|
|
35
47
|
|
|
@@ -46,7 +58,7 @@ COMMANDS:
|
|
|
46
58
|
jbai handoff Continue task in Orca Lab
|
|
47
59
|
jbai env [staging|production] Switch environment
|
|
48
60
|
jbai models List available models
|
|
49
|
-
jbai install Install all AI tools (claude, codex, gemini, opencode)
|
|
61
|
+
jbai install Install all AI tools (claude, codex, gemini, opencode, goose, continue)
|
|
50
62
|
jbai install claude Install specific tool
|
|
51
63
|
jbai doctor Check which tools are installed
|
|
52
64
|
jbai help Show this help
|
|
@@ -300,7 +312,7 @@ function showModels() {
|
|
|
300
312
|
console.log(` - ${m}${def}`);
|
|
301
313
|
});
|
|
302
314
|
|
|
303
|
-
console.log('\nGPT (OpenAI Chat) - jbai-
|
|
315
|
+
console.log('\nGPT (OpenAI Chat) - jbai-opencode:');
|
|
304
316
|
config.MODELS.openai.available.forEach((m) => {
|
|
305
317
|
const def = m === config.MODELS.openai.default ? ' (default)' : '';
|
|
306
318
|
console.log(` - ${m}${def}`);
|
package/lib/config.js
CHANGED
|
@@ -48,11 +48,12 @@ const MODELS = {
|
|
|
48
48
|
]
|
|
49
49
|
},
|
|
50
50
|
openai: {
|
|
51
|
-
// Chat/Completions models (used by
|
|
51
|
+
// Chat/Completions models (used by OpenCode)
|
|
52
52
|
// Keep in sync with the OpenAI proxy's advertised list.
|
|
53
|
-
default: 'gpt-
|
|
53
|
+
default: 'gpt-5.2-2025-12-11',
|
|
54
54
|
available: [
|
|
55
55
|
// GPT-5.x series (latest) - require date-versioned names
|
|
56
|
+
// NOTE: gpt-5.3-codex-api-preview is Responses-API-only → use via jbai codex
|
|
56
57
|
'gpt-5.2-2025-12-11',
|
|
57
58
|
'gpt-5.2',
|
|
58
59
|
'gpt-5.1-2025-11-13',
|
|
@@ -295,6 +296,16 @@ const TOOLS = {
|
|
|
295
296
|
name: 'OpenCode',
|
|
296
297
|
command: 'opencode',
|
|
297
298
|
install: 'npm install -g opencode-ai'
|
|
299
|
+
},
|
|
300
|
+
goose: {
|
|
301
|
+
name: 'Goose',
|
|
302
|
+
command: 'goose',
|
|
303
|
+
install: 'brew install block-goose-cli'
|
|
304
|
+
},
|
|
305
|
+
continue: {
|
|
306
|
+
name: 'Continue CLI',
|
|
307
|
+
command: 'cn',
|
|
308
|
+
install: 'npm install -g @continuedev/cli'
|
|
298
309
|
}
|
|
299
310
|
};
|
|
300
311
|
|
package/lib/postinstall.js
CHANGED
|
@@ -41,8 +41,10 @@ Next steps:
|
|
|
41
41
|
3. Start using AI tools:
|
|
42
42
|
$ jbai-claude # Claude Code
|
|
43
43
|
$ jbai-codex # OpenAI Codex
|
|
44
|
-
$ jbai-
|
|
45
|
-
$ jbai-gemini # Gemini
|
|
44
|
+
$ jbai-opencode # OpenCode
|
|
45
|
+
$ jbai-gemini # Gemini CLI
|
|
46
|
+
$ jbai-goose # Goose (Block)
|
|
47
|
+
$ jbai-continue # Continue CLI
|
|
46
48
|
|
|
47
49
|
Run 'jbai help' for more options.
|
|
48
50
|
`);
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jbai-cli",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "CLI wrappers to use AI coding tools (Claude Code, Codex, Gemini CLI, OpenCode) with JetBrains AI Platform",
|
|
3
|
+
"version": "1.9.1",
|
|
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",
|
|
7
7
|
"ai",
|
|
@@ -9,6 +9,8 @@
|
|
|
9
9
|
"codex",
|
|
10
10
|
"gemini",
|
|
11
11
|
"opencode",
|
|
12
|
+
"goose",
|
|
13
|
+
"continue",
|
|
12
14
|
"cli",
|
|
13
15
|
"openai",
|
|
14
16
|
"anthropic",
|
|
@@ -30,7 +32,9 @@
|
|
|
30
32
|
"jbai-claude": "bin/jbai-claude.js",
|
|
31
33
|
"jbai-codex": "bin/jbai-codex.js",
|
|
32
34
|
"jbai-gemini": "bin/jbai-gemini.js",
|
|
33
|
-
"jbai-opencode": "bin/jbai-opencode.js"
|
|
35
|
+
"jbai-opencode": "bin/jbai-opencode.js",
|
|
36
|
+
"jbai-goose": "bin/jbai-goose.js",
|
|
37
|
+
"jbai-continue": "bin/jbai-continue.js"
|
|
34
38
|
},
|
|
35
39
|
"files": [
|
|
36
40
|
"bin/",
|