jbai-cli 1.6.0 → 1.8.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.
@@ -5,159 +5,155 @@ const fs = require('fs');
5
5
  const path = require('path');
6
6
  const os = require('os');
7
7
  const config = require('../lib/config');
8
-
9
- const token = config.getToken();
10
- if (!token) {
11
- console.error('❌ No token found. Run: jbai token set');
12
- process.exit(1);
13
- }
14
-
15
- if (config.isTokenExpired(token)) {
16
- console.error('⚠️ Token expired. Run: jbai token refresh');
17
- process.exit(1);
18
- }
19
-
20
- const endpoints = config.getEndpoints();
21
- const environment = config.getEnvironment();
22
- let args = process.argv.slice(2);
23
- const handoffConfig = stripHandoffFlag(args);
24
- args = handoffConfig.args;
25
-
26
- // Check for super mode (--super, --yolo, -s)
27
- const superFlags = ['--super', '--yolo', '-s'];
28
- const superMode = args.some(a => superFlags.includes(a));
29
- args = args.filter(a => !superFlags.includes(a));
30
-
31
- // Setup OpenCode config with JetBrains provider
32
- const configDir = path.join(os.homedir(), '.config', 'opencode');
33
- const configFile = path.join(configDir, 'opencode.json');
34
-
35
- if (!fs.existsSync(configDir)) {
36
- fs.mkdirSync(configDir, { recursive: true });
37
- }
38
-
39
- // Create or update OpenCode config with JetBrains provider
40
- const providerName = environment === 'staging' ? 'jbai-staging' : 'jbai';
41
- let opencodeConfig = {};
42
-
43
- if (fs.existsSync(configFile)) {
44
- try {
45
- opencodeConfig = JSON.parse(fs.readFileSync(configFile, 'utf-8'));
46
- } catch {
47
- opencodeConfig = {};
8
+ const { ensureToken } = require('../lib/ensure-token');
9
+
10
+ (async () => {
11
+ const token = await ensureToken();
12
+ const endpoints = config.getEndpoints();
13
+ const environment = config.getEnvironment();
14
+ let args = process.argv.slice(2);
15
+ const handoffConfig = stripHandoffFlag(args);
16
+ args = handoffConfig.args;
17
+
18
+ // Check for super mode (--super, --yolo, -s)
19
+ const superFlags = ['--super', '--yolo', '-s'];
20
+ const superMode = args.some(a => superFlags.includes(a));
21
+ args = args.filter(a => !superFlags.includes(a));
22
+
23
+ // Setup OpenCode config with JetBrains provider
24
+ const configDir = path.join(os.homedir(), '.config', 'opencode');
25
+ const configFile = path.join(configDir, 'opencode.json');
26
+
27
+ if (!fs.existsSync(configDir)) {
28
+ fs.mkdirSync(configDir, { recursive: true });
48
29
  }
49
- }
50
-
51
- // Ensure provider section exists
52
- if (!opencodeConfig.provider) {
53
- opencodeConfig.provider = {};
54
- }
55
-
56
- // Environment variable name for the token
57
- const envVarName = environment === 'staging' ? 'GRAZIE_STAGING_TOKEN' : 'GRAZIE_API_TOKEN';
58
-
59
- // Provider names for OpenAI and Anthropic
60
- const anthropicProviderName = environment === 'staging' ? 'jbai-anthropic-staging' : 'jbai-anthropic';
61
-
62
- // Add/update JetBrains OpenAI provider with custom header (using env var reference)
63
- // Use OpenAI SDK to support max_completion_tokens for GPT-5.x
64
- opencodeConfig.provider[providerName] = {
65
- npm: '@ai-sdk/openai',
66
- name: `JetBrains AI OpenAI (${environment})`,
67
- options: {
68
- baseURL: endpoints.openai,
69
- apiKey: `{env:${envVarName}}`,
70
- headers: {
71
- 'Grazie-Authenticate-JWT': `{env:${envVarName}}`
30
+
31
+ // Create or update OpenCode config with JetBrains provider
32
+ const providerName = environment === 'staging' ? 'jbai-staging' : 'jbai';
33
+ let opencodeConfig = {};
34
+
35
+ if (fs.existsSync(configFile)) {
36
+ try {
37
+ opencodeConfig = JSON.parse(fs.readFileSync(configFile, 'utf-8'));
38
+ } catch {
39
+ opencodeConfig = {};
72
40
  }
73
- },
74
- models: {}
75
- };
76
-
77
- // Add OpenAI models
78
- // OpenCode requires an output limit in the config.
79
- // For O-series models we keep a larger context window but still set output.
80
- config.MODELS.openai.available.forEach(model => {
81
- const isOSeries = /^o[1-9]/.test(model);
82
- opencodeConfig.provider[providerName].models[model] = {
83
- name: model,
84
- limit: isOSeries
85
- ? { context: 200000, output: 8192 }
86
- : { context: 128000, output: 8192 }
41
+ }
42
+
43
+ // Ensure provider section exists
44
+ if (!opencodeConfig.provider) {
45
+ opencodeConfig.provider = {};
46
+ }
47
+
48
+ // Environment variable name for the token
49
+ const envVarName = environment === 'staging' ? 'GRAZIE_STAGING_TOKEN' : 'GRAZIE_API_TOKEN';
50
+
51
+ // Provider names for OpenAI and Anthropic
52
+ const anthropicProviderName = environment === 'staging' ? 'jbai-anthropic-staging' : 'jbai-anthropic';
53
+
54
+ // Add/update JetBrains OpenAI provider with custom header (using env var reference)
55
+ // Use OpenAI SDK to support max_completion_tokens for GPT-5.x
56
+ opencodeConfig.provider[providerName] = {
57
+ npm: '@ai-sdk/openai',
58
+ name: `JetBrains AI OpenAI (${environment})`,
59
+ options: {
60
+ baseURL: endpoints.openai,
61
+ apiKey: `{env:${envVarName}}`,
62
+ headers: {
63
+ 'Grazie-Authenticate-JWT': `{env:${envVarName}}`
64
+ }
65
+ },
66
+ models: {}
87
67
  };
88
- });
89
-
90
- // Add JetBrains Anthropic provider for Claude models
91
- opencodeConfig.provider[anthropicProviderName] = {
92
- npm: '@ai-sdk/anthropic',
93
- name: `JetBrains AI Anthropic (${environment})`,
94
- options: {
95
- baseURL: endpoints.anthropic,
96
- apiKey: `{env:${envVarName}}`,
97
- headers: {
98
- 'Grazie-Authenticate-JWT': `{env:${envVarName}}`
99
- }
100
- },
101
- models: {}
102
- };
103
-
104
- // Add Claude models to Anthropic provider
105
- config.MODELS.claude.available.forEach(model => {
106
- opencodeConfig.provider[anthropicProviderName].models[model] = {
107
- name: model,
108
- limit: { context: 200000, output: 8192 }
68
+
69
+ // Add OpenAI models
70
+ // OpenCode requires an output limit in the config.
71
+ // For O-series models we keep a larger context window but still set output.
72
+ config.MODELS.openai.available.forEach(model => {
73
+ const isOSeries = /^o[1-9]/.test(model);
74
+ opencodeConfig.provider[providerName].models[model] = {
75
+ name: model,
76
+ limit: isOSeries
77
+ ? { context: 200000, output: 8192 }
78
+ : { context: 128000, output: 8192 }
79
+ };
80
+ });
81
+
82
+ // Add JetBrains Anthropic provider for Claude models
83
+ opencodeConfig.provider[anthropicProviderName] = {
84
+ npm: '@ai-sdk/anthropic',
85
+ name: `JetBrains AI Anthropic (${environment})`,
86
+ options: {
87
+ baseURL: endpoints.anthropic,
88
+ apiKey: `{env:${envVarName}}`,
89
+ headers: {
90
+ 'Grazie-Authenticate-JWT': `{env:${envVarName}}`
91
+ }
92
+ },
93
+ models: {}
109
94
  };
110
- });
111
-
112
- // Write config
113
- fs.writeFileSync(configFile, JSON.stringify(opencodeConfig, null, 2));
114
-
115
- // Check if model specified
116
- const hasModel = args.includes('--model') || args.includes('-m');
117
- let finalArgs = [];
118
-
119
- if (!hasModel) {
120
- // Use provider/model format for OpenCode
121
- finalArgs.push('--model', `${providerName}/${config.MODELS.openai.default}`);
122
- }
123
-
124
- // Note: OpenCode run is already non-interactive, no super mode needed
125
- if (superMode) {
126
- console.log('ℹ️ OpenCode run is already non-interactive (no super mode flag needed)');
127
- }
128
-
129
- finalArgs.push(...args);
130
-
131
- // Set the token in environment variable for OpenCode config to reference
132
- const childEnv = {
133
- ...process.env,
134
- [envVarName]: token
135
- };
136
-
137
- const child = runWithHandoff({
138
- command: 'opencode',
139
- args: finalArgs,
140
- env: childEnv,
141
- toolName: 'jbai-opencode',
142
- handoffDefaults: {
143
- enabled: !handoffConfig.disabled,
144
- grazieToken: token,
145
- grazieEnvironment: environment === 'production' ? 'PRODUCTION' : 'STAGING',
146
- grazieModel: config.MODELS.claude.default,
147
- cwd: process.cwd(),
148
- },
149
- });
150
-
151
- if (child && typeof child.on === 'function') {
152
- child.on('error', (err) => {
153
- if (err.code === 'ENOENT') {
154
- const tool = config.TOOLS.opencode;
155
- console.error(`❌ ${tool.name} not found.\n`);
156
- console.error(`Install with: ${tool.install}`);
157
- console.error(`Or run: jbai install opencode`);
158
- } else {
159
- console.error(`Error: ${err.message}`);
160
- }
161
- process.exit(1);
95
+
96
+ // Add Claude models to Anthropic provider
97
+ config.MODELS.claude.available.forEach(model => {
98
+ opencodeConfig.provider[anthropicProviderName].models[model] = {
99
+ name: model,
100
+ limit: { context: 200000, output: 8192 }
101
+ };
162
102
  });
163
- }
103
+
104
+ // NOTE: Gemini models are NOT available via Grazie OpenAI-compatible proxy.
105
+ // The /user/v5/llm/google/v1/vertex endpoint only works with native Google API
106
+ // format (used by jbai-gemini), not OpenAI chat/completions format.
107
+ // Use `jbai gemini` instead for Gemini models.
108
+
109
+ // Enable max permissions (yolo mode) by default
110
+ opencodeConfig.yolo = true;
111
+
112
+ // Write config
113
+ fs.writeFileSync(configFile, JSON.stringify(opencodeConfig, null, 2));
114
+
115
+ // Check if model specified
116
+ const hasModel = args.includes('--model') || args.includes('-m');
117
+ let finalArgs = ['--yolo'];
118
+
119
+ if (!hasModel) {
120
+ // Use provider/model format for OpenCode
121
+ finalArgs.push('--model', `${providerName}/${config.MODELS.openai.default}`);
122
+ }
123
+
124
+ finalArgs.push(...args);
125
+
126
+ // Set the token in environment variable for OpenCode config to reference
127
+ const childEnv = {
128
+ ...process.env,
129
+ [envVarName]: token
130
+ };
131
+
132
+ const child = runWithHandoff({
133
+ command: 'opencode',
134
+ args: finalArgs,
135
+ env: childEnv,
136
+ toolName: 'jbai-opencode',
137
+ handoffDefaults: {
138
+ enabled: !handoffConfig.disabled,
139
+ grazieToken: token,
140
+ grazieEnvironment: environment === 'production' ? 'PRODUCTION' : 'STAGING',
141
+ grazieModel: config.MODELS.claude.default,
142
+ cwd: process.cwd(),
143
+ },
144
+ });
145
+
146
+ if (child && typeof child.on === 'function') {
147
+ child.on('error', (err) => {
148
+ if (err.code === 'ENOENT') {
149
+ const tool = config.TOOLS.opencode;
150
+ console.error(`❌ ${tool.name} not found.\n`);
151
+ console.error(`Install with: ${tool.install}`);
152
+ console.error(`Or run: jbai install opencode`);
153
+ } else {
154
+ console.error(`Error: ${err.message}`);
155
+ }
156
+ process.exit(1);
157
+ });
158
+ }
159
+ })();