opencode-studio-server 1.2.0 → 1.2.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.
Files changed (2) hide show
  1. package/index.js +67 -6
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -129,6 +129,34 @@ function loadStudioConfig() {
129
129
  "name": "2.5 Flash Lite",
130
130
  "reasoning": false
131
131
  },
132
+ "google/gemini-3-flash": {
133
+ "id": "google/gemini-3-flash",
134
+ "name": "3 Flash (Google)",
135
+ "reasoning": true,
136
+ "limit": { "context": 1048576, "output": 65536 },
137
+ "cost": { "input": 0.5, "output": 3, "cache_read": 0.05 },
138
+ "modalities": {
139
+ "input": ["text", "image", "video", "audio", "pdf"],
140
+ "output": ["text"]
141
+ },
142
+ "variants": {
143
+ "minimal": { "options": { "thinkingConfig": { "thinkingLevel": "minimal", "includeThoughts": true } } },
144
+ "low": { "options": { "thinkingConfig": { "thinkingLevel": "low", "includeThoughts": true } } },
145
+ "medium": { "options": { "thinkingConfig": { "thinkingLevel": "medium", "includeThoughts": true } } },
146
+ "high": { "options": { "thinkingConfig": { "thinkingLevel": "high", "includeThoughts": true } } }
147
+ }
148
+ },
149
+ "opencode/glm-4.7-free": {
150
+ "id": "opencode/glm-4.7-free",
151
+ "name": "GLM 4.7 Free",
152
+ "reasoning": false,
153
+ "limit": { "context": 128000, "output": 4096 },
154
+ "cost": { "input": 0, "output": 0 },
155
+ "modalities": {
156
+ "input": ["text"],
157
+ "output": ["text"]
158
+ }
159
+ },
132
160
  "gemini-claude-sonnet-4-5-thinking": {
133
161
  "id": "gemini-claude-sonnet-4-5-thinking",
134
162
  "name": "Sonnet 4.5",
@@ -223,7 +251,12 @@ const loadConfig = () => {
223
251
  const configPath = getConfigPath();
224
252
  if (!configPath || !fs.existsSync(configPath)) return null;
225
253
  try {
226
- return JSON.parse(fs.readFileSync(configPath, 'utf8'));
254
+ const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
255
+ const studioConfig = loadStudioConfig();
256
+ if (studioConfig.activeGooglePlugin === 'antigravity' && !config.small_model) {
257
+ config.small_model = "google/gemini-3-flash";
258
+ }
259
+ return config;
227
260
  } catch {
228
261
  return null;
229
262
  }
@@ -487,7 +520,11 @@ app.get('/api/auth', (req, res) => {
487
520
 
488
521
  providers.forEach(p => {
489
522
  const saved = listAuthProfiles(p.id, activePlugin);
490
- const curr = !!authCfg[p.id];
523
+ let curr = !!authCfg[p.id];
524
+ if (p.id === 'google') {
525
+ const key = activePlugin === 'antigravity' ? 'google.antigravity' : 'google.gemini';
526
+ curr = !!authCfg[key] || !!authCfg.google;
527
+ }
491
528
  credentials.push({ ...p, active: ac[p.id] || (curr ? 'current' : null), profiles: saved, hasCurrentAuth: curr });
492
529
  });
493
530
  res.json({
@@ -508,7 +545,13 @@ app.get('/api/auth/profiles', (req, res) => {
508
545
 
509
546
  providers.forEach(p => {
510
547
  const saved = listAuthProfiles(p, activePlugin);
511
- const curr = authCfg[p];
548
+ // Correct current auth check: handle google vs google.gemini/antigravity
549
+ let curr = !!authCfg[p];
550
+ if (p === 'google') {
551
+ const key = activePlugin === 'antigravity' ? 'google.antigravity' : 'google.gemini';
552
+ curr = !!authCfg[key] || !!authCfg.google;
553
+ }
554
+
512
555
  if (saved.length > 0 || curr) {
513
556
  profiles[p] = { active: ac[p], profiles: saved, hasCurrentAuth: !!curr };
514
557
  }
@@ -587,6 +630,14 @@ app.put('/api/auth/profiles/:provider/:name', (req, res) => {
587
630
  const oldPath = path.join(AUTH_PROFILES_DIR, namespace, `${name}.json`);
588
631
  const newPath = path.join(AUTH_PROFILES_DIR, namespace, `${newName}.json`);
589
632
  if (fs.existsSync(oldPath)) fs.renameSync(oldPath, newPath);
633
+
634
+ // Update active profile name if it was the one renamed
635
+ const studio = loadStudioConfig();
636
+ if (studio.activeProfiles && studio.activeProfiles[provider] === name) {
637
+ studio.activeProfiles[provider] = newName;
638
+ saveStudioConfig(studio);
639
+ }
640
+
590
641
  res.json({ success: true, name: newName });
591
642
  });
592
643
 
@@ -715,12 +766,22 @@ app.get('/api/usage', async (req, res) => {
715
766
 
716
767
  const mid = msg.modelID || (msg.model && (msg.model.modelID || msg.model.id)) || 'unknown';
717
768
  stats.totalCost += c; stats.totalTokens += t;
718
- [stats.byModel, stats.byTime, stats.byProject].forEach((obj, i) => {
719
- const key = i === 0 ? mid : (i === 1 ? tk : pid);
769
+ [stats.byModel, stats.byProject].forEach((obj, i) => {
770
+ const key = i === 0 ? mid : pid;
720
771
  if (!obj[key]) obj[key] = { name: key, id: key, cost: 0, tokens: 0, inputTokens: 0, outputTokens: 0 };
721
- if (i === 2) obj[key].name = pmap.get(s)?.name || 'Unassigned';
772
+ if (i === 1) obj[key].name = pmap.get(s)?.name || 'Unassigned';
722
773
  obj[key].cost += c; obj[key].tokens += t; obj[key].inputTokens += it; obj[key].outputTokens += ot;
723
774
  });
775
+
776
+ if (!stats.byTime[tk]) stats.byTime[tk] = { date: tk, name: tk, id: tk, cost: 0, tokens: 0, inputTokens: 0, outputTokens: 0 };
777
+ const te = stats.byTime[tk];
778
+ te.cost += c; te.tokens += t; te.inputTokens += it; te.outputTokens += ot;
779
+ if (!te[mid]) te[mid] = 0;
780
+ te[mid] += c;
781
+
782
+ const kIn = `${mid}_input`, kOut = `${mid}_output`;
783
+ te[kIn] = (te[kIn] || 0) + it;
784
+ te[kOut] = (te[kOut] || 0) + ot;
724
785
  }
725
786
  } catch {}
726
787
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-studio-server",
3
- "version": "1.2.0",
3
+ "version": "1.2.1",
4
4
  "description": "Backend server for OpenCode Studio - manages opencode configurations",
5
5
  "main": "index.js",
6
6
  "bin": {