fix issue with generating a share url and add missing url verification in settings (#3482)

This commit is contained in:
Zane
2025-07-17 15:33:34 -07:00
committed by GitHub
parent 079a64c1f7
commit 759cc6830e
3 changed files with 144 additions and 18 deletions

View File

@@ -2,7 +2,7 @@
<html>
<head>
<meta charset="UTF-8" />
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline'; img-src 'self' data: https:; connect-src 'self' http://127.0.0.1:* https://api.github.com https://github.com https://objects.githubusercontent.com; object-src 'none'; frame-src 'none'; font-src 'self' data: https:; media-src 'self' mediastream:; form-action 'none'; base-uri 'self'; manifest-src 'self'; worker-src 'self';" />
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline'; img-src 'self' data: https:; connect-src 'self' http://127.0.0.1:* https:; object-src 'none'; frame-src 'none'; font-src 'self' data: https:; media-src 'self' mediastream:; form-action 'none'; base-uri 'self'; manifest-src 'self'; worker-src 'self';" />
<title>Goose</title>
<script>
// Initialize theme before any content loads

View File

@@ -1,6 +1,6 @@
import React, { useState, useEffect } from 'react';
import { Input } from '../../ui/input';
import { Check, Lock } from 'lucide-react';
import { Check, Lock, Loader2, AlertCircle } from 'lucide-react';
import { Switch } from '../../ui/switch';
import { Button } from '../../ui/button';
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '../../ui/card';
@@ -15,6 +15,11 @@ export default function SessionSharingSection() {
baseUrl: typeof envBaseUrlShare === 'string' ? envBaseUrlShare : '',
});
const [urlError, setUrlError] = useState('');
const [testResult, setTestResult] = useState<{
status: 'success' | 'error' | 'testing' | null;
message: string;
}>({ status: null, message: '' });
// isUrlConfigured is true if the user has configured a baseUrl and it is valid.
const isUrlConfigured =
!envBaseUrlShare &&
@@ -74,6 +79,9 @@ export default function SessionSharingSection() {
baseUrl: newBaseUrl,
}));
// Clear previous test results when URL changes
setTestResult({ status: null, message: '' });
if (isValidUrl(newBaseUrl)) {
setUrlError('');
const updated = { ...sessionSharingConfig, baseUrl: newBaseUrl };
@@ -83,13 +91,72 @@ export default function SessionSharingSection() {
}
};
// Test connection to the configured URL
const testConnection = async () => {
const baseUrl = sessionSharingConfig.baseUrl;
if (!baseUrl) return;
setTestResult({ status: 'testing', message: 'Testing connection...' });
try {
// Create an AbortController for timeout
const controller = new AbortController();
const timeoutId = window.setTimeout(() => controller.abort(), 10000); // 10 second timeout
const response = await fetch(baseUrl, {
method: 'GET',
headers: {
Accept: 'application/json, text/plain, */*',
},
signal: controller.signal,
});
window.clearTimeout(timeoutId);
// Consider any response (even 404) as a successful connection
// since it means we can reach the server
if (response.status < 500) {
setTestResult({
status: 'success',
message: `Connection successful! Server responded with status ${response.status}.`,
});
} else {
setTestResult({
status: 'error',
message: `Server error: HTTP ${response.status}. The server may not be configured correctly.`,
});
}
} catch (error) {
console.error('Connection test failed:', error);
let errorMessage = 'Connection failed. ';
if (error instanceof TypeError && error.message.includes('fetch')) {
errorMessage +=
'Unable to reach the server. Please check the URL and your network connection.';
} else if (error instanceof Error) {
if (error.name === 'AbortError') {
errorMessage += 'Connection timed out. The server may be slow or unreachable.';
} else {
errorMessage += error.message;
}
} else {
errorMessage += 'Unknown error occurred.';
}
setTestResult({
status: 'error',
message: errorMessage,
});
}
};
return (
<section id="session-sharing" className="space-y-4 pr-4 mt-1">
<Card className="pb-2">
<CardHeader className="pb-0">
<CardTitle>Session Sharing</CardTitle>
<CardDescription>
{envBaseUrlShare
{(envBaseUrlShare as string)
? 'Session sharing is configured but fully opt-in — your sessions are only shared when you explicitly click the share button.'
: 'You can enable session sharing to share your sessions with others.'}
</CardDescription>
@@ -99,7 +166,7 @@ export default function SessionSharingSection() {
{/* Toggle for enabling session sharing */}
<div className="flex items-center gap-3">
<label className="text-sm cursor-pointer">
{envBaseUrlShare
{(envBaseUrlShare as string)
? 'Session sharing has already been configured'
: 'Enable session sharing'}
</label>
@@ -136,19 +203,44 @@ export default function SessionSharingSection() {
/>
</div>
{urlError && <p className="text-red-500 text-sm">{urlError}</p>}
{isUrlConfigured && (
<Button
variant="outline"
size="sm"
className="mt-2"
onClick={() => {
// Test the connection to the configured URL
console.log('Testing connection to:', sessionSharingConfig.baseUrl);
// TODO: Implement actual connection test
}}
>
Test Connection
</Button>
{(isUrlConfigured || (envBaseUrlShare as string)) && (
<div className="space-y-2">
<Button
variant="outline"
size="sm"
onClick={testConnection}
disabled={testResult.status === 'testing'}
className="flex items-center gap-2"
>
{testResult.status === 'testing' ? (
<>
<Loader2 className="w-4 h-4 animate-spin" />
Testing...
</>
) : (
'Test Connection'
)}
</Button>
{/* Test Results */}
{testResult.status && testResult.status !== 'testing' && (
<div
className={`flex items-start gap-2 p-3 rounded-md text-sm ${
testResult.status === 'success'
? 'bg-green-50 text-green-800 border border-green-200'
: 'bg-red-50 text-red-800 border border-red-200'
}`}
>
{testResult.status === 'success' ? (
<Check className="w-4 h-4 mt-0.5 flex-shrink-0" />
) : (
<AlertCircle className="w-4 h-4 mt-0.5 flex-shrink-0" />
)}
<span>{testResult.message}</span>
</div>
)}
</div>
)}
</div>
)}

View File

@@ -874,9 +874,43 @@ const openDirectoryDialog = async (
addRecentDir(dirToAdd);
const currentWindow = BrowserWindow.getFocusedWindow();
await createChat(app, undefined, dirToAdd);
if (replaceWindow && currentWindow) {
// Replace current window with new one
await createChat(app, undefined, dirToAdd);
currentWindow.close();
} else {
// Update the working directory in the current window's localStorage
if (currentWindow) {
try {
const updateConfigScript = `
try {
const currentConfig = JSON.parse(localStorage.getItem('gooseConfig') || '{}');
const updatedConfig = {
...currentConfig,
GOOSE_WORKING_DIR: '${dirToAdd.replace(/'/g, "\\'")}',
};
localStorage.setItem('gooseConfig', JSON.stringify(updatedConfig));
// Trigger a config update event so the UI can refresh
window.dispatchEvent(new CustomEvent('goose-config-updated', {
detail: { GOOSE_WORKING_DIR: '${dirToAdd.replace(/'/g, "\\'")}' }
}));
} catch (e) {
console.error('Failed to update working directory in localStorage:', e);
}
`;
await currentWindow.webContents.executeJavaScript(updateConfigScript);
console.log(`Updated working directory to: ${dirToAdd}`);
} catch (error) {
console.error('Failed to update working directory:', error);
// Fallback: create new window
await createChat(app, undefined, dirToAdd);
}
} else {
// No current window, create new one
await createChat(app, undefined, dirToAdd);
}
}
}
return result;