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.
- package/index.js +85 -83
- 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
|
-
|
|
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
|
|