jbai-cli 1.8.0 → 1.8.2

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/bin/jbai-codex.js CHANGED
@@ -4,14 +4,45 @@ 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');
7
8
  const config = require('../lib/config');
8
9
  const { ensureToken } = require('../lib/ensure-token');
9
10
 
11
+ const PROXY_PORT = 18080;
12
+ const PROXY_PROVIDER = 'jbai-proxy';
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
+
10
43
  (async () => {
11
44
  const token = await ensureToken();
12
- const endpoints = config.getEndpoints();
13
45
  const environment = config.getEnvironment();
14
- const providerName = environment === 'staging' ? 'jbai-staging' : 'jbai';
15
46
  const envVarName = environment === 'staging' ? 'GRAZIE_STAGING_TOKEN' : 'GRAZIE_API_TOKEN';
16
47
  let args = process.argv.slice(2);
17
48
  const handoffConfig = stripHandoffFlag(args);
@@ -22,6 +53,13 @@ const { ensureToken } = require('../lib/ensure-token');
22
53
  const superMode = args.some(a => superFlags.includes(a));
23
54
  args = args.filter(a => !superFlags.includes(a));
24
55
 
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));
61
+ }
62
+
25
63
  // Ensure Codex config exists
26
64
  const codexDir = path.join(os.homedir(), '.codex');
27
65
  const codexConfig = path.join(codexDir, 'config.toml');
@@ -30,40 +68,28 @@ const { ensureToken } = require('../lib/ensure-token');
30
68
  fs.mkdirSync(codexDir, { recursive: true });
31
69
  }
32
70
 
33
- // Check if our provider is configured
71
+ // Check if our proxy provider is configured
34
72
  let configContent = '';
35
73
  if (fs.existsSync(codexConfig)) {
36
74
  configContent = fs.readFileSync(codexConfig, 'utf-8');
37
75
  }
38
76
 
39
- if (!configContent.includes(`[model_providers.${providerName}]`)) {
77
+ if (!configContent.includes(`[model_providers.${PROXY_PROVIDER}]`)) {
40
78
  const providerConfig = `
41
- # JetBrains AI (${environment})
42
- [model_providers.${providerName}]
43
- name = "JetBrains AI (${environment})"
44
- base_url = "${endpoints.openai}"
45
- env_http_headers = { "Grazie-Authenticate-JWT" = "${envVarName}" }
79
+ # JetBrains AI via local proxy (serves model list + auto-injects auth)
80
+ [model_providers.${PROXY_PROVIDER}]
81
+ name = "JetBrains AI (Proxy)"
82
+ base_url = "http://localhost:${PROXY_PORT}/openai/v1"
83
+ env_key = "JBAI_PROXY_KEY"
46
84
  wire_api = "responses"
47
85
  `;
48
86
  fs.appendFileSync(codexConfig, providerConfig);
49
- console.log(`✅ Added ${providerName} provider to Codex config`);
50
- }
51
-
52
- // Point Codex model picker to our proxy (serves our model list instead of chatgpt.com)
53
- const proxyModelUrl = 'http://localhost:18080/';
54
- if (!configContent.includes('chatgpt_base_url')) {
55
- fs.appendFileSync(codexConfig, `\nchatgpt_base_url = "${proxyModelUrl}"\n`);
56
- console.log('✅ Set chatgpt_base_url to jbai-proxy for model picker');
57
- } else if (!configContent.includes(proxyModelUrl)) {
58
- // Update existing chatgpt_base_url
59
- configContent = fs.readFileSync(codexConfig, 'utf-8');
60
- const updated = configContent.replace(/^chatgpt_base_url\s*=\s*"[^"]*"/m, `chatgpt_base_url = "${proxyModelUrl}"`);
61
- fs.writeFileSync(codexConfig, updated);
62
- console.log('✅ Updated chatgpt_base_url to jbai-proxy');
87
+ console.log(`✅ Added ${PROXY_PROVIDER} provider to Codex config`);
63
88
  }
64
89
 
65
90
  const hasModel = args.includes('--model');
66
- const finalArgs = ['-c', `model_provider=${providerName}`];
91
+ // Use proxy provider so Codex fetches /v1/models from our proxy (shows all Grazie models)
92
+ const finalArgs = ['-c', `model_provider=${PROXY_PROVIDER}`];
67
93
 
68
94
  if (!hasModel) {
69
95
  finalArgs.push('--model', config.MODELS.codex?.default || config.MODELS.openai.default);
@@ -79,7 +105,8 @@ wire_api = "responses"
79
105
 
80
106
  const childEnv = {
81
107
  ...process.env,
82
- [envVarName]: token
108
+ [envVarName]: token,
109
+ JBAI_PROXY_KEY: 'placeholder', // Proxy handles auth via Grazie JWT
83
110
  };
84
111
 
85
112
  const child = runWithHandoff({
@@ -114,7 +114,7 @@ const { ensureToken } = require('../lib/ensure-token');
114
114
 
115
115
  // Check if model specified
116
116
  const hasModel = args.includes('--model') || args.includes('-m');
117
- let finalArgs = ['--yolo'];
117
+ let finalArgs = [];
118
118
 
119
119
  if (!hasModel) {
120
120
  // Use provider/model format for OpenCode
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jbai-cli",
3
- "version": "1.8.0",
3
+ "version": "1.8.2",
4
4
  "description": "CLI wrappers to use AI coding tools (Claude Code, Codex, Gemini CLI, OpenCode) with JetBrains AI Platform",
5
5
  "keywords": [
6
6
  "jetbrains",