feat(settings): auto-set default provider after successful OAuth (#254)
This commit is contained in:
committed by
GitHub
Unverified
parent
19406757f1
commit
29ef9591cf
@@ -678,38 +678,38 @@ export class GatewayManager extends EventEmitter {
|
||||
|
||||
if (pids.length > 0) {
|
||||
if (!this.process || !pids.includes(String(this.process.pid))) {
|
||||
logger.info(`Found orphaned process listening on port ${port} (PIDs: ${pids.join(', ')}), attempting to kill...`);
|
||||
logger.info(`Found orphaned process listening on port ${port} (PIDs: ${pids.join(', ')}), attempting to kill...`);
|
||||
|
||||
// Unload the launchctl service first so macOS doesn't auto-
|
||||
// respawn the process we're about to kill.
|
||||
if (process.platform === 'darwin') {
|
||||
await this.unloadLaunchctlService();
|
||||
}
|
||||
// Unload the launchctl service first so macOS doesn't auto-
|
||||
// respawn the process we're about to kill.
|
||||
if (process.platform === 'darwin') {
|
||||
await this.unloadLaunchctlService();
|
||||
}
|
||||
|
||||
// Terminate orphaned processes
|
||||
for (const pid of pids) {
|
||||
try {
|
||||
if (process.platform === 'win32') {
|
||||
// On Windows, use taskkill for reliable process group termination
|
||||
import('child_process').then(cp => {
|
||||
cp.exec(`taskkill /PID ${pid} /T /F`, { timeout: 5000 }, () => {});
|
||||
}).catch(() => {});
|
||||
} else {
|
||||
// SIGTERM first so the gateway can clean up its lock file.
|
||||
process.kill(parseInt(pid), 'SIGTERM');
|
||||
}
|
||||
} catch { /* ignore */ }
|
||||
}
|
||||
await new Promise(r => setTimeout(r, process.platform === 'win32' ? 2000 : 3000));
|
||||
// Terminate orphaned processes
|
||||
for (const pid of pids) {
|
||||
try {
|
||||
if (process.platform === 'win32') {
|
||||
// On Windows, use taskkill for reliable process group termination
|
||||
import('child_process').then(cp => {
|
||||
cp.exec(`taskkill /PID ${pid} /T /F`, { timeout: 5000 }, () => { });
|
||||
}).catch(() => { });
|
||||
} else {
|
||||
// SIGTERM first so the gateway can clean up its lock file.
|
||||
process.kill(parseInt(pid), 'SIGTERM');
|
||||
}
|
||||
} catch { /* ignore */ }
|
||||
}
|
||||
await new Promise(r => setTimeout(r, process.platform === 'win32' ? 2000 : 3000));
|
||||
|
||||
// SIGKILL any survivors (Unix only — Windows taskkill /F is already forceful)
|
||||
if (process.platform !== 'win32') {
|
||||
for (const pid of pids) {
|
||||
try { process.kill(parseInt(pid), 0); process.kill(parseInt(pid), 'SIGKILL'); } catch { /* already exited */ }
|
||||
}
|
||||
await new Promise(r => setTimeout(r, 1000));
|
||||
}
|
||||
return null;
|
||||
// SIGKILL any survivors (Unix only — Windows taskkill /F is already forceful)
|
||||
if (process.platform !== 'win32') {
|
||||
for (const pid of pids) {
|
||||
try { process.kill(parseInt(pid), 0); process.kill(parseInt(pid), 'SIGKILL'); } catch { /* already exited */ }
|
||||
}
|
||||
await new Promise(r => setTimeout(r, 1000));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -785,7 +785,7 @@ export class GatewayManager extends EventEmitter {
|
||||
spawnEnv['OPENCLAW_NO_RESPAWN'] = '1';
|
||||
const existingNodeOpts = spawnEnv['NODE_OPTIONS'] ?? '';
|
||||
if (!existingNodeOpts.includes('--disable-warning=ExperimentalWarning') &&
|
||||
!existingNodeOpts.includes('--no-warnings')) {
|
||||
!existingNodeOpts.includes('--no-warnings')) {
|
||||
spawnEnv['NODE_OPTIONS'] = `${existingNodeOpts} --disable-warning=ExperimentalWarning`.trim();
|
||||
}
|
||||
}
|
||||
@@ -1014,7 +1014,7 @@ export class GatewayManager extends EventEmitter {
|
||||
// Pre-set the NODE_OPTIONS that entry.ts would have added via respawn
|
||||
const existingNodeOpts = spawnEnv['NODE_OPTIONS'] ?? '';
|
||||
if (!existingNodeOpts.includes('--disable-warning=ExperimentalWarning') &&
|
||||
!existingNodeOpts.includes('--no-warnings')) {
|
||||
!existingNodeOpts.includes('--no-warnings')) {
|
||||
spawnEnv['NODE_OPTIONS'] = `${existingNodeOpts} --disable-warning=ExperimentalWarning`.trim();
|
||||
}
|
||||
}
|
||||
@@ -1347,6 +1347,8 @@ export class GatewayManager extends EventEmitter {
|
||||
const reasonStr = reason?.toString() || 'unknown';
|
||||
logger.warn(`Gateway WebSocket closed (code=${code}, reason=${reasonStr}, handshake=${handshakeComplete ? 'ok' : 'pending'})`);
|
||||
if (!handshakeComplete) {
|
||||
// If the socket closes before the handshake completes, it usually means the server is still starting or restarting.
|
||||
// Rejecting this promise will cause the caller (startProcess/reconnect logic) to retry cleanly.
|
||||
rejectOnce(new Error(`WebSocket closed before handshake: ${reasonStr}`));
|
||||
return;
|
||||
}
|
||||
@@ -1358,7 +1360,12 @@ export class GatewayManager extends EventEmitter {
|
||||
});
|
||||
|
||||
this.ws.on('error', (error) => {
|
||||
logger.error('Gateway WebSocket error:', error);
|
||||
// Suppress noisy ECONNREFUSED/WebSocket handshake errors that happen during expected Gateway restarts.
|
||||
if (error.message?.includes('closed before handshake') || (error as NodeJS.ErrnoException).code === 'ECONNREFUSED') {
|
||||
logger.debug(`Gateway WebSocket connection error (transient): ${error.message}`);
|
||||
} else {
|
||||
logger.error('Gateway WebSocket error:', error);
|
||||
}
|
||||
if (!handshakeComplete) {
|
||||
rejectOnce(error);
|
||||
}
|
||||
|
||||
@@ -516,7 +516,14 @@ function AddProviderDialog({ existingTypes, onClose, onAdd, onValidateKey }: Add
|
||||
// If we call add() here with undefined baseUrl, it will overwrite and erase it!
|
||||
// So we just fetch the latest list from the backend to update the UI.
|
||||
try {
|
||||
await useProviderStore.getState().fetchProviders();
|
||||
const store = useProviderStore.getState();
|
||||
await store.fetchProviders();
|
||||
|
||||
// Auto-set as default if no default is currently configured
|
||||
if (!store.defaultProviderId && latestRef.current.selectedType) {
|
||||
// Provider type is expected to match provider ID for built-in OAuth providers
|
||||
await store.setDefaultProvider(latestRef.current.selectedType);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Failed to refresh providers after OAuth:', err);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user