opencode-studio-server 1.12.13 → 1.12.14

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 +85 -83
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -1406,22 +1406,6 @@ app.get('/api/auth/providers', (req, res) => {
1406
1406
  });
1407
1407
 
1408
1408
  app.get('/api/auth', (req, res) => {
1409
- importCurrentGoogleAuthToPool();
1410
- syncAntigravityPool();
1411
- const authCfg = loadAuthConfig() || {};
1412
- const studio = loadStudioConfig();
1413
- const ac = studio.activeProfiles || {};
1414
- const credentials = [];
1415
- const activePlugin = studio.activeGooglePlugin;
1416
-
1417
- // DEBUG LOGGING
1418
- console.log('--- Auth Debug ---');
1419
- console.log('Active Google Plugin:', activePlugin);
1420
- console.log('Found keys in authCfg:', Object.keys(authCfg));
1421
- if (authCfg.google) console.log('Google Auth found!');
1422
- if (authCfg['google.antigravity']) console.log('google.antigravity found!');
1423
- if (authCfg['google.gemini']) console.log('google.gemini found!');
1424
-
1425
1409
  const providers = [
1426
1410
  { id: 'google', name: 'Google', type: 'oauth' },
1427
1411
  { id: 'anthropic', name: 'Anthropic', type: 'api' },
@@ -1436,6 +1420,15 @@ app.get('/api/auth', (req, res) => {
1436
1420
  { id: 'azure', name: 'Azure OpenAI', type: 'api' }
1437
1421
  ];
1438
1422
 
1423
+ providers.forEach(p => importCurrentAuthToPool(p.id));
1424
+ syncAntigravityPool();
1425
+
1426
+ const authCfg = loadAuthConfig() || {};
1427
+ const studio = loadStudioConfig();
1428
+ const ac = studio.activeProfiles || {};
1429
+ const credentials = [];
1430
+ const activePlugin = studio.activeGooglePlugin;
1431
+
1439
1432
  const opencodeCfg = loadConfig();
1440
1433
  const currentPlugins = opencodeCfg?.plugin || [];
1441
1434
 
@@ -1483,13 +1476,15 @@ app.get('/api/auth', (req, res) => {
1483
1476
  });
1484
1477
 
1485
1478
  app.get('/api/auth/profiles', (req, res) => {
1479
+ const providers = ['google', 'anthropic', 'openai', 'xai', 'openrouter', 'together', 'mistral', 'deepseek', 'amazon-bedrock', 'azure', 'github-copilot'];
1480
+ providers.forEach(p => importCurrentAuthToPool(p));
1486
1481
  syncAntigravityPool();
1482
+
1487
1483
  const authCfg = loadAuthConfig() || {};
1488
1484
  const studio = loadStudioConfig();
1489
1485
  const ac = studio.activeProfiles || {};
1490
1486
  const activePlugin = studio.activeGooglePlugin;
1491
1487
  const profiles = {};
1492
- const providers = ['google', 'anthropic', 'openai', 'xai', 'openrouter', 'together', 'mistral', 'deepseek', 'amazon-bedrock', 'azure', 'github-copilot'];
1493
1488
 
1494
1489
  providers.forEach(p => {
1495
1490
  const saved = listAuthProfiles(p, activePlugin);
@@ -1882,6 +1877,78 @@ function listAntigravityAccounts() {
1882
1877
  }));
1883
1878
  }
1884
1879
 
1880
+ function decodeJWT(token) {
1881
+ try {
1882
+ const parts = token.split('.');
1883
+ if (parts.length !== 3) return null;
1884
+ const payload = Buffer.from(parts[1], 'base64').toString('utf8');
1885
+ return JSON.parse(payload);
1886
+ } catch {
1887
+ return null;
1888
+ }
1889
+ }
1890
+
1891
+ function importCurrentAuthToPool(provider) {
1892
+ if (provider === 'google') {
1893
+ return importCurrentGoogleAuthToPool();
1894
+ }
1895
+
1896
+ const authCfg = loadAuthConfig();
1897
+ if (!authCfg || !authCfg[provider]) return;
1898
+
1899
+ const creds = authCfg[provider];
1900
+ let email = creds.email;
1901
+
1902
+ if (!email && provider === 'openai' && creds.access) {
1903
+ const decoded = decodeJWT(creds.access);
1904
+ if (decoded && decoded['https://api.openai.com/profile']?.email) {
1905
+ email = decoded['https://api.openai.com/profile'].email;
1906
+ }
1907
+ }
1908
+
1909
+ const name = email || creds.accountId || creds.id || `profile-${Date.now()}`;
1910
+ const profileDir = path.join(AUTH_PROFILES_DIR, provider);
1911
+ if (!fs.existsSync(profileDir)) fs.mkdirSync(profileDir, { recursive: true });
1912
+
1913
+ const profilePath = path.join(profileDir, `${name}.json`);
1914
+
1915
+ let shouldSync = true;
1916
+ if (fs.existsSync(profilePath)) {
1917
+ try {
1918
+ const current = JSON.parse(fs.readFileSync(profilePath, 'utf8'));
1919
+ if (JSON.stringify(current) === JSON.stringify(creds)) {
1920
+ shouldSync = false;
1921
+ }
1922
+ } catch {
1923
+ }
1924
+ }
1925
+
1926
+ if (shouldSync) {
1927
+ console.log(`[Auth] Syncing ${provider} login for ${name} to pool.`);
1928
+ atomicWriteFileSync(profilePath, JSON.stringify(creds, null, 2));
1929
+
1930
+ const metadata = loadPoolMetadata();
1931
+ if (!metadata[provider]) metadata[provider] = {};
1932
+
1933
+ metadata[provider][name] = {
1934
+ ...(metadata[provider][name] || {}),
1935
+ email: email || null,
1936
+ createdAt: metadata[provider][name]?.createdAt || Date.now(),
1937
+ lastUsed: Date.now(),
1938
+ usageCount: metadata[provider][name]?.usageCount || 0,
1939
+ imported: true
1940
+ };
1941
+ savePoolMetadata(metadata);
1942
+
1943
+ const studio = loadStudioConfig();
1944
+ if (!studio.activeProfiles) studio.activeProfiles = {};
1945
+ if (studio.activeProfiles[provider] !== name) {
1946
+ studio.activeProfiles[provider] = name;
1947
+ saveStudioConfig(studio);
1948
+ }
1949
+ }
1950
+ }
1951
+
1885
1952
  function importCurrentGoogleAuthToPool() {
1886
1953
  const studio = loadStudioConfig();
1887
1954
  // Only applies if Antigravity is active
@@ -1982,70 +2049,6 @@ function syncAntigravityPool() {
1982
2049
  savePoolMetadata(metadata);
1983
2050
  }
1984
2051
 
1985
- function importExistingAuth() {
1986
- const authCfg = loadAuthConfig();
1987
- if (!authCfg) return;
1988
-
1989
- const studio = loadStudioConfig();
1990
- const activeProfiles = studio.activeProfiles || {};
1991
- let changed = false;
1992
-
1993
- // Standard providers to check
1994
- const providers = ['google', 'openai', 'anthropic', 'xai', 'openrouter', 'github-copilot', 'mistral', 'deepseek', 'amazon-bedrock', 'azure'];
1995
-
1996
- providers.forEach(provider => {
1997
- if (!authCfg[provider]) return; // No creds for this provider
1998
-
1999
- // Determine namespace
2000
- // For auto-import, we target the standard 'google' namespace unless antigravity plugin is active?
2001
- // Actually, auth.json 'google' key usually means Gemini/Vertex standard auth.
2002
- const namespace = provider === 'google' && studio.activeGooglePlugin === 'antigravity'
2003
- ? 'google.antigravity'
2004
- : (provider === 'google' ? 'google.gemini' : provider);
2005
-
2006
- const profileDir = path.join(AUTH_PROFILES_DIR, namespace);
2007
-
2008
- // If we already have an active profile for this provider, skip import
2009
- if (activeProfiles[provider]) return;
2010
-
2011
- // If directory exists and has files, check if empty
2012
- if (fs.existsSync(profileDir) && fs.readdirSync(profileDir).filter(f => f.endsWith('.json')).length > 0) {
2013
- return;
2014
- }
2015
-
2016
- // Import!
2017
- if (!fs.existsSync(profileDir)) fs.mkdirSync(profileDir, { recursive: true });
2018
-
2019
- const email = authCfg[provider].email || null;
2020
- const name = email || `imported-${Date.now()}`;
2021
- const profilePath = path.join(profileDir, `${name}.json`);
2022
-
2023
- console.log(`[AutoImport] Importing existing ${provider} credentials as ${name}`);
2024
- atomicWriteFileSync(profilePath, JSON.stringify(authCfg[provider], null, 2));
2025
-
2026
- // Set as active
2027
- if (!studio.activeProfiles) studio.activeProfiles = {};
2028
- studio.activeProfiles[provider] = name;
2029
- changed = true;
2030
-
2031
- // Update metadata
2032
- const metadata = loadPoolMetadata();
2033
- if (!metadata[namespace]) metadata[namespace] = {};
2034
- metadata[namespace][name] = {
2035
- email: email,
2036
- createdAt: Date.now(),
2037
- lastUsed: Date.now(),
2038
- usageCount: 0,
2039
- imported: true
2040
- };
2041
- savePoolMetadata(metadata);
2042
- });
2043
-
2044
- if (changed) {
2045
- saveStudioConfig(studio);
2046
- }
2047
- }
2048
-
2049
2052
  function getAccountStatus(meta, now) {
2050
2053
  if (!meta) return 'ready';
2051
2054
  if (meta.cooldownUntil && meta.cooldownUntil > now) return 'cooldown';
@@ -3035,8 +3038,7 @@ app.post('/api/presets/:id/apply', (req, res) => {
3035
3038
 
3036
3039
  // Start watcher on server start
3037
3040
  function startServer() {
3038
- // setupLogWatcher(); // Disabled as per user request (manual switching only)
3039
- importExistingAuth();
3041
+ ['google', 'anthropic', 'openai', 'xai', 'openrouter', 'together', 'mistral', 'deepseek', 'amazon-bedrock', 'azure', 'github-copilot'].forEach(p => importCurrentAuthToPool(p));
3040
3042
  app.listen(PORT, () => console.log(`Server running at http://localhost:${PORT}`));
3041
3043
  }
3042
3044
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-studio-server",
3
- "version": "1.12.13",
3
+ "version": "1.12.14",
4
4
  "description": "Backend server for OpenCode Studio - manages opencode configurations",
5
5
  "main": "index.js",
6
6
  "bin": {