opencode-studio-server 1.0.7 → 1.0.10
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 +76 -78
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -56,9 +56,34 @@ const HOME_DIR = os.homedir();
|
|
|
56
56
|
const STUDIO_CONFIG_PATH = path.join(HOME_DIR, '.config', 'opencode-studio', 'studio.json');
|
|
57
57
|
const PENDING_ACTION_PATH = path.join(HOME_DIR, '.config', 'opencode-studio', 'pending-action.json');
|
|
58
58
|
|
|
59
|
-
let pendingActionMemory = null;
|
|
60
|
-
|
|
61
|
-
function
|
|
59
|
+
let pendingActionMemory = null;
|
|
60
|
+
|
|
61
|
+
function loadStudioConfig() {
|
|
62
|
+
if (!fs.existsSync(STUDIO_CONFIG_PATH)) {
|
|
63
|
+
return {};
|
|
64
|
+
}
|
|
65
|
+
try {
|
|
66
|
+
return JSON.parse(fs.readFileSync(STUDIO_CONFIG_PATH, 'utf8'));
|
|
67
|
+
} catch {
|
|
68
|
+
return {};
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function saveStudioConfig(config) {
|
|
73
|
+
try {
|
|
74
|
+
const dir = path.dirname(STUDIO_CONFIG_PATH);
|
|
75
|
+
if (!fs.existsSync(dir)) {
|
|
76
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
77
|
+
}
|
|
78
|
+
fs.writeFileSync(STUDIO_CONFIG_PATH, JSON.stringify(config, null, 2), 'utf8');
|
|
79
|
+
return true;
|
|
80
|
+
} catch (err) {
|
|
81
|
+
console.error('Failed to save studio config:', err);
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function loadPendingAction() {
|
|
62
87
|
if (pendingActionMemory) return pendingActionMemory;
|
|
63
88
|
|
|
64
89
|
if (fs.existsSync(PENDING_ACTION_PATH)) {
|
|
@@ -94,53 +119,38 @@ const AUTH_CANDIDATE_PATHS = [
|
|
|
94
119
|
path.join(process.env.APPDATA || '', 'opencode', 'auth.json'),
|
|
95
120
|
];
|
|
96
121
|
|
|
97
|
-
const CANDIDATE_PATHS = [
|
|
98
|
-
path.join(HOME_DIR, '.config', 'opencode'),
|
|
99
|
-
path.join(HOME_DIR, '.opencode'),
|
|
100
|
-
path.join(process.env.APPDATA || '', 'opencode'),
|
|
101
|
-
path.join(process.env.LOCALAPPDATA || '', 'opencode'),
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
if (!fs.existsSync(dir)) {
|
|
130
|
-
fs.mkdirSync(dir, { recursive: true });
|
|
131
|
-
}
|
|
132
|
-
fs.writeFileSync(STUDIO_CONFIG_PATH, JSON.stringify(config, null, 2), 'utf8');
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
function getConfigDir() {
|
|
136
|
-
const studioConfig = loadStudioConfig();
|
|
137
|
-
if (studioConfig.configPath && fs.existsSync(studioConfig.configPath)) {
|
|
138
|
-
return studioConfig.configPath;
|
|
139
|
-
}
|
|
140
|
-
return detectConfigDir();
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
function getPaths() {
|
|
122
|
+
const CANDIDATE_PATHS = [
|
|
123
|
+
path.join(HOME_DIR, '.config', 'opencode'),
|
|
124
|
+
path.join(HOME_DIR, '.opencode'),
|
|
125
|
+
path.join(process.env.APPDATA || '', 'opencode'),
|
|
126
|
+
path.join(process.env.LOCALAPPDATA || '', 'opencode'),
|
|
127
|
+
];
|
|
128
|
+
|
|
129
|
+
function getConfigDir() {
|
|
130
|
+
for (const candidate of CANDIDATE_PATHS) {
|
|
131
|
+
if (fs.existsSync(candidate)) {
|
|
132
|
+
return candidate;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return null;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const PROVIDER_DISPLAY_NAMES = {
|
|
139
|
+
'github-copilot': 'GitHub Copilot',
|
|
140
|
+
'google': 'Google AI',
|
|
141
|
+
'anthropic': 'Anthropic',
|
|
142
|
+
'openai': 'OpenAI',
|
|
143
|
+
'xai': 'xAI',
|
|
144
|
+
'groq': 'Groq',
|
|
145
|
+
'together': 'Together AI',
|
|
146
|
+
'mistral': 'Mistral',
|
|
147
|
+
'deepseek': 'DeepSeek',
|
|
148
|
+
'openrouter': 'OpenRouter',
|
|
149
|
+
'amazon-bedrock': 'Amazon Bedrock',
|
|
150
|
+
'azure': 'Azure OpenAI',
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
function getPaths() {
|
|
144
154
|
const configDir = getConfigDir();
|
|
145
155
|
if (!configDir) return null;
|
|
146
156
|
return {
|
|
@@ -761,14 +771,17 @@ app.post('/api/restore', (req, res) => {
|
|
|
761
771
|
});
|
|
762
772
|
|
|
763
773
|
// Auth endpoints
|
|
764
|
-
function getAuthFile() {
|
|
765
|
-
for
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
}
|
|
774
|
+
function getAuthFile() {
|
|
775
|
+
console.log('Searching for auth file in:', AUTH_CANDIDATE_PATHS);
|
|
776
|
+
for (const candidate of AUTH_CANDIDATE_PATHS) {
|
|
777
|
+
if (fs.existsSync(candidate)) {
|
|
778
|
+
console.log('Found auth file at:', candidate);
|
|
779
|
+
return candidate;
|
|
780
|
+
}
|
|
781
|
+
}
|
|
782
|
+
console.log('No auth file found');
|
|
783
|
+
return null;
|
|
784
|
+
}
|
|
772
785
|
|
|
773
786
|
function loadAuthConfig() {
|
|
774
787
|
const authFile = getAuthFile();
|
|
@@ -793,22 +806,7 @@ function saveAuthConfig(config) {
|
|
|
793
806
|
}
|
|
794
807
|
}
|
|
795
808
|
|
|
796
|
-
|
|
797
|
-
'github-copilot': 'GitHub Copilot',
|
|
798
|
-
'google': 'Google',
|
|
799
|
-
'google-gemini-oauth': 'Google Gemini (OAuth)',
|
|
800
|
-
'anthropic': 'Anthropic',
|
|
801
|
-
'openai': 'OpenAI',
|
|
802
|
-
'zai': 'Z.AI',
|
|
803
|
-
'xai': 'xAI',
|
|
804
|
-
'groq': 'Groq',
|
|
805
|
-
'together': 'Together AI',
|
|
806
|
-
'mistral': 'Mistral',
|
|
807
|
-
'deepseek': 'DeepSeek',
|
|
808
|
-
'openrouter': 'OpenRouter',
|
|
809
|
-
'amazon-bedrock': 'Amazon Bedrock',
|
|
810
|
-
'azure': 'Azure OpenAI',
|
|
811
|
-
};
|
|
809
|
+
|
|
812
810
|
|
|
813
811
|
app.get('/api/auth', (req, res) => {
|
|
814
812
|
const authConfig = loadAuthConfig();
|
|
@@ -852,7 +850,6 @@ app.get('/api/auth', (req, res) => {
|
|
|
852
850
|
|
|
853
851
|
app.post('/api/auth/login', (req, res) => {
|
|
854
852
|
// opencode auth login is interactive and requires a terminal
|
|
855
|
-
// Open a new terminal window with the command
|
|
856
853
|
const isWindows = process.platform === 'win32';
|
|
857
854
|
const isMac = process.platform === 'darwin';
|
|
858
855
|
|
|
@@ -865,7 +862,7 @@ app.post('/api/auth/login', (req, res) => {
|
|
|
865
862
|
command = 'x-terminal-emulator -e "opencode auth login" || gnome-terminal -- opencode auth login || xterm -e "opencode auth login"';
|
|
866
863
|
}
|
|
867
864
|
|
|
868
|
-
exec(command, (err) => {
|
|
865
|
+
exec(command, { shell: true }, (err) => {
|
|
869
866
|
if (err) console.error('Failed to open terminal:', err);
|
|
870
867
|
});
|
|
871
868
|
|
|
@@ -992,6 +989,7 @@ function setActiveProfile(provider, profileName) {
|
|
|
992
989
|
saveStudioConfig(studioConfig);
|
|
993
990
|
}
|
|
994
991
|
|
|
992
|
+
function verifyActiveProfile(p, n, c) { if (!n || !c) return false; const d = loadAuthProfile(p, n); if (!d) return false; return JSON.stringify(d) === JSON.stringify(c); }
|
|
995
993
|
app.get('/api/auth/profiles', (req, res) => {
|
|
996
994
|
ensureAuthProfilesDir();
|
|
997
995
|
const activeProfiles = getActiveProfiles();
|
|
@@ -1003,7 +1001,7 @@ app.get('/api/auth/profiles', (req, res) => {
|
|
|
1003
1001
|
const providerProfiles = listAuthProfiles(provider);
|
|
1004
1002
|
profiles[provider] = {
|
|
1005
1003
|
profiles: providerProfiles,
|
|
1006
|
-
active: activeProfiles[provider]
|
|
1004
|
+
active: (activeProfiles[provider] && verifyActiveProfile(provider, activeProfiles[provider], authConfig[provider])) ? activeProfiles[provider] : null,
|
|
1007
1005
|
hasCurrentAuth: !!authConfig[provider],
|
|
1008
1006
|
};
|
|
1009
1007
|
});
|
|
@@ -1019,7 +1017,7 @@ app.get('/api/auth/profiles/:provider', (req, res) => {
|
|
|
1019
1017
|
|
|
1020
1018
|
res.json({
|
|
1021
1019
|
profiles: providerProfiles,
|
|
1022
|
-
active: activeProfiles[provider]
|
|
1020
|
+
active: (activeProfiles[provider] && verifyActiveProfile(provider, activeProfiles[provider], authConfig[provider])) ? activeProfiles[provider] : null,
|
|
1023
1021
|
hasCurrentAuth: !!authConfig[provider],
|
|
1024
1022
|
});
|
|
1025
1023
|
});
|