jbai-cli 1.9.2 → 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 CHANGED
@@ -236,7 +236,7 @@ Each tool has a sensible default, but you can specify any available model:
236
236
  jbai-claude --model claude-opus-4-6
237
237
 
238
238
  # Codex with GPT-5.3
239
- jbai-codex --model gpt-5.3-codex
239
+ jbai-codex --model gpt-5.3-codex-api-preview
240
240
 
241
241
  # Goose with GPT-5.2
242
242
  jbai-goose run -t "your task" --provider openai --model gpt-5.2-2025-12-11
@@ -275,8 +275,7 @@ jbai-continue # select model in TUI
275
275
  **Codex (OpenAI Responses)** - Use with Codex CLI: `jbai-codex --model <model>`
276
276
  | Model | Notes |
277
277
  |-------|-------|
278
- | `gpt-5.3-codex` | Default, latest |
279
- | `gpt-5.3-codex-api-preview` | Alias |
278
+ | `gpt-5.3-codex-api-preview` | Default, latest |
280
279
  | `gpt-5.2-codex` | Coding-optimized |
281
280
  | `gpt-5.2-pro-2025-12-11` | |
282
281
  | `gpt-5.1-codex` | |
@@ -300,7 +299,7 @@ jbai-continue # select model in TUI
300
299
  | `jbai token` | Show token status |
301
300
  | `jbai token set` | Set/update token |
302
301
  | `jbai test` | Test API connections |
303
- | `jbai models` | List all models |
302
+ | `jbai models [tool]` | List Grazie models |
304
303
  | `jbai proxy setup` | Setup proxy + configure Codex Desktop |
305
304
  | `jbai proxy status` | Check proxy status |
306
305
  | `jbai proxy stop` | Stop proxy |
@@ -2,15 +2,22 @@
2
2
 
3
3
  const { runWithHandoff, stripHandoffFlag } = require('../lib/interactive-handoff');
4
4
  const config = require('../lib/config');
5
+ const { isModelsCommand, showModelsForTool } = require('../lib/model-list');
5
6
  const { ensureToken } = require('../lib/ensure-token');
7
+ const { PROXY_PORT, ensureProxy } = require('../lib/proxy');
6
8
 
7
9
  (async () => {
8
- const token = await ensureToken();
9
- const endpoints = config.getEndpoints();
10
10
  let args = process.argv.slice(2);
11
11
  const handoffConfig = stripHandoffFlag(args);
12
12
  args = handoffConfig.args;
13
13
 
14
+ if (isModelsCommand(args)) {
15
+ showModelsForTool('claude', 'Available Grazie models for jbai-claude:');
16
+ return;
17
+ }
18
+
19
+ const token = await ensureToken();
20
+
14
21
  // Check for super mode (--super, --yolo, -s)
15
22
  const superFlags = ['--super', '--yolo', '-s'];
16
23
  const superMode = args.some(a => superFlags.includes(a));
@@ -26,19 +33,19 @@ const { ensureToken } = require('../lib/ensure-token');
26
33
  console.log('🚀 Super mode: --dangerously-skip-permissions enabled');
27
34
  }
28
35
 
29
- // Set environment for Claude Code
30
- // Use ANTHROPIC_CUSTOM_HEADERS for the Grazie auth header
31
- // Remove /v1 from endpoint - Claude Code adds it automatically
32
- const baseUrl = endpoints.anthropic.replace(/\/v1$/, '');
36
+ // Auto-start proxy if not running (serves /anthropic/v1/models with only Grazie Claude models)
37
+ await ensureProxy();
38
+
39
+ // Route through proxy — it handles JWT injection and serves provider-filtered model list
33
40
  const env = {
34
41
  ...process.env,
35
- ANTHROPIC_BASE_URL: baseUrl,
42
+ ANTHROPIC_BASE_URL: `http://127.0.0.1:${PROXY_PORT}/anthropic`,
36
43
  ANTHROPIC_API_KEY: 'placeholder',
37
- ANTHROPIC_CUSTOM_HEADERS: `Grazie-Authenticate-JWT: ${token}`
38
44
  };
39
45
 
40
- // Remove any existing auth token that might conflict
46
+ // Remove any existing auth token/headers that might conflict
41
47
  delete env.ANTHROPIC_AUTH_TOKEN;
48
+ delete env.ANTHROPIC_CUSTOM_HEADERS;
42
49
 
43
50
  const child = runWithHandoff({
44
51
  command: 'claude',
package/bin/jbai-codex.js CHANGED
@@ -4,46 +4,14 @@ const { runWithHandoff, stripHandoffFlag } = require('../lib/interactive-handoff
4
4
  const fs = require('fs');
5
5
  const path = require('path');
6
6
  const os = require('os');
7
- const http = require('http');
8
7
  const config = require('../lib/config');
8
+ const { isModelsCommand, showModelsForTool } = require('../lib/model-list');
9
9
  const { ensureToken } = require('../lib/ensure-token');
10
+ const { PROXY_PORT, ensureProxy } = require('../lib/proxy');
10
11
 
11
- const PROXY_PORT = 18080;
12
12
  const PROXY_PROVIDER = 'jbai-proxy';
13
13
 
14
- function isProxyRunning() {
15
- return new Promise((resolve) => {
16
- const req = http.get(`http://127.0.0.1:${PROXY_PORT}/health`, { timeout: 1000 }, (res) => {
17
- let body = '';
18
- res.on('data', chunk => body += chunk);
19
- res.on('end', () => {
20
- try {
21
- const info = JSON.parse(body);
22
- resolve(info.status === 'ok');
23
- } catch {
24
- resolve(false);
25
- }
26
- });
27
- });
28
- req.on('error', () => resolve(false));
29
- req.on('timeout', () => { req.destroy(); resolve(false); });
30
- });
31
- }
32
-
33
- function startProxy() {
34
- const { spawn } = require('child_process');
35
- const proxyScript = path.join(__dirname, 'jbai-proxy.js');
36
- const child = spawn(process.execPath, [proxyScript, '--port', String(PROXY_PORT), '--_daemon'], {
37
- detached: true,
38
- stdio: 'ignore',
39
- });
40
- child.unref();
41
- }
42
-
43
14
  (async () => {
44
- const token = await ensureToken();
45
- const environment = config.getEnvironment();
46
- const envVarName = environment === 'staging' ? 'GRAZIE_STAGING_TOKEN' : 'GRAZIE_API_TOKEN';
47
15
  let args = process.argv.slice(2);
48
16
  const handoffConfig = stripHandoffFlag(args);
49
17
  args = handoffConfig.args;
@@ -53,13 +21,18 @@ function startProxy() {
53
21
  const superMode = args.some(a => superFlags.includes(a));
54
22
  args = args.filter(a => !superFlags.includes(a));
55
23
 
56
- // Auto-start proxy if not running (serves /v1/models with our model list)
57
- if (!await isProxyRunning()) {
58
- startProxy();
59
- // Wait briefly for proxy to start
60
- await new Promise(r => setTimeout(r, 500));
24
+ if (isModelsCommand(args)) {
25
+ showModelsForTool('codex', 'Available Grazie models for jbai-codex:');
26
+ return;
61
27
  }
62
28
 
29
+ const token = await ensureToken();
30
+ const environment = config.getEnvironment();
31
+ const envVarName = environment === 'staging' ? 'GRAZIE_STAGING_TOKEN' : 'GRAZIE_API_TOKEN';
32
+
33
+ // Auto-start proxy if not running (serves /v1/models with our model list)
34
+ await ensureProxy();
35
+
63
36
  // Ensure Codex config exists
64
37
  const codexDir = path.join(os.homedir(), '.codex');
65
38
  const codexConfig = path.join(codexDir, 'config.toml');
@@ -11,48 +11,19 @@ const { runWithHandoff, stripHandoffFlag } = require('../lib/interactive-handoff
11
11
  const fs = require('fs');
12
12
  const path = require('path');
13
13
  const os = require('os');
14
- const http = require('http');
15
14
  const config = require('../lib/config');
15
+ const { isModelsCommand, showModelsForTool } = require('../lib/model-list');
16
16
  const { ensureToken } = require('../lib/ensure-token');
17
+ const { PROXY_PORT, ensureProxy } = require('../lib/proxy');
17
18
 
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() {
19
+ function buildContinueConfig(requestedModel) {
50
20
  const proxyBase = `http://127.0.0.1:${PROXY_PORT}`;
51
21
  const models = [];
22
+ const targetModel = requestedModel || config.MODELS.claude.default;
52
23
 
53
24
  // Add Claude models first (default provider)
54
25
  config.MODELS.claude.available.forEach(model => {
55
- const isDefault = model === config.MODELS.claude.default;
26
+ const isDefault = model === targetModel;
56
27
  models.push({
57
28
  name: isDefault ? `${model} (default)` : model,
58
29
  provider: 'anthropic',
@@ -65,8 +36,9 @@ function buildContinueConfig() {
65
36
 
66
37
  // Add OpenAI models via proxy
67
38
  config.MODELS.openai.available.forEach(model => {
39
+ const isDefault = model === targetModel;
68
40
  models.push({
69
- name: model,
41
+ name: isDefault ? `${model} (default)` : model,
70
42
  provider: 'openai',
71
43
  model,
72
44
  apiBase: `${proxyBase}/openai/v1`,
@@ -75,7 +47,8 @@ function buildContinueConfig() {
75
47
  });
76
48
  });
77
49
 
78
- const defaultModel = `${config.MODELS.claude.default} (default)`;
50
+ const defaultEntry = models.find(m => m.model === targetModel);
51
+ const defaultModel = defaultEntry ? defaultEntry.name : `${config.MODELS.claude.default} (default)`;
79
52
 
80
53
  return {
81
54
  name: 'JetBrains AI',
@@ -115,8 +88,6 @@ function toYaml(obj, indent = 0) {
115
88
  }
116
89
 
117
90
  (async () => {
118
- const token = await ensureToken();
119
- const environment = config.getEnvironment();
120
91
  let args = process.argv.slice(2);
121
92
  const handoffConfig = stripHandoffFlag(args);
122
93
  args = handoffConfig.args;
@@ -126,12 +97,25 @@ function toYaml(obj, indent = 0) {
126
97
  const superMode = args.some(a => superFlags.includes(a));
127
98
  args = args.filter(a => !superFlags.includes(a));
128
99
 
129
- // Auto-start proxy if not running
130
- if (!await isProxyRunning()) {
131
- startProxy();
132
- await new Promise(r => setTimeout(r, 500));
100
+ if (isModelsCommand(args)) {
101
+ showModelsForTool('continue', 'Available Grazie models for jbai-continue:');
102
+ return;
133
103
  }
134
104
 
105
+ // Extract --model/-m from args (Continue CLI uses a different --model semantics)
106
+ let requestedModel = null;
107
+ const modelFlagIdx = args.findIndex(a => a === '--model' || a === '-m');
108
+ if (modelFlagIdx >= 0) {
109
+ requestedModel = args[modelFlagIdx + 1] || null;
110
+ args.splice(modelFlagIdx, 2);
111
+ }
112
+
113
+ const token = await ensureToken();
114
+ const environment = config.getEnvironment();
115
+
116
+ // Auto-start proxy if not running
117
+ await ensureProxy();
118
+
135
119
  // Write Continue config
136
120
  const configDir = path.join(os.homedir(), '.continue');
137
121
  const configFile = path.join(configDir, 'config.yaml');
@@ -140,7 +124,7 @@ function toYaml(obj, indent = 0) {
140
124
  fs.mkdirSync(configDir, { recursive: true });
141
125
  }
142
126
 
143
- const continueConfig = buildContinueConfig();
127
+ const continueConfig = buildContinueConfig(requestedModel);
144
128
  const yaml = `# Auto-generated by jbai-cli — do not edit manually\n${toYaml(continueConfig)}`;
145
129
  fs.writeFileSync(configFile, yaml);
146
130