fix issue with generating a share url and add missing url verification in settings (#3482)
This commit is contained in:
@@ -2,7 +2,7 @@
|
|||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<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>
|
<title>Goose</title>
|
||||||
<script>
|
<script>
|
||||||
// Initialize theme before any content loads
|
// Initialize theme before any content loads
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
import { Input } from '../../ui/input';
|
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 { Switch } from '../../ui/switch';
|
||||||
import { Button } from '../../ui/button';
|
import { Button } from '../../ui/button';
|
||||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '../../ui/card';
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '../../ui/card';
|
||||||
@@ -15,6 +15,11 @@ export default function SessionSharingSection() {
|
|||||||
baseUrl: typeof envBaseUrlShare === 'string' ? envBaseUrlShare : '',
|
baseUrl: typeof envBaseUrlShare === 'string' ? envBaseUrlShare : '',
|
||||||
});
|
});
|
||||||
const [urlError, setUrlError] = useState('');
|
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.
|
// isUrlConfigured is true if the user has configured a baseUrl and it is valid.
|
||||||
const isUrlConfigured =
|
const isUrlConfigured =
|
||||||
!envBaseUrlShare &&
|
!envBaseUrlShare &&
|
||||||
@@ -74,6 +79,9 @@ export default function SessionSharingSection() {
|
|||||||
baseUrl: newBaseUrl,
|
baseUrl: newBaseUrl,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
// Clear previous test results when URL changes
|
||||||
|
setTestResult({ status: null, message: '' });
|
||||||
|
|
||||||
if (isValidUrl(newBaseUrl)) {
|
if (isValidUrl(newBaseUrl)) {
|
||||||
setUrlError('');
|
setUrlError('');
|
||||||
const updated = { ...sessionSharingConfig, baseUrl: newBaseUrl };
|
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 (
|
return (
|
||||||
<section id="session-sharing" className="space-y-4 pr-4 mt-1">
|
<section id="session-sharing" className="space-y-4 pr-4 mt-1">
|
||||||
<Card className="pb-2">
|
<Card className="pb-2">
|
||||||
<CardHeader className="pb-0">
|
<CardHeader className="pb-0">
|
||||||
<CardTitle>Session Sharing</CardTitle>
|
<CardTitle>Session Sharing</CardTitle>
|
||||||
<CardDescription>
|
<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.'
|
? '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.'}
|
: 'You can enable session sharing to share your sessions with others.'}
|
||||||
</CardDescription>
|
</CardDescription>
|
||||||
@@ -99,7 +166,7 @@ export default function SessionSharingSection() {
|
|||||||
{/* Toggle for enabling session sharing */}
|
{/* Toggle for enabling session sharing */}
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
<label className="text-sm cursor-pointer">
|
<label className="text-sm cursor-pointer">
|
||||||
{envBaseUrlShare
|
{(envBaseUrlShare as string)
|
||||||
? 'Session sharing has already been configured'
|
? 'Session sharing has already been configured'
|
||||||
: 'Enable session sharing'}
|
: 'Enable session sharing'}
|
||||||
</label>
|
</label>
|
||||||
@@ -136,19 +203,44 @@ export default function SessionSharingSection() {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{urlError && <p className="text-red-500 text-sm">{urlError}</p>}
|
{urlError && <p className="text-red-500 text-sm">{urlError}</p>}
|
||||||
{isUrlConfigured && (
|
|
||||||
<Button
|
{(isUrlConfigured || (envBaseUrlShare as string)) && (
|
||||||
variant="outline"
|
<div className="space-y-2">
|
||||||
size="sm"
|
<Button
|
||||||
className="mt-2"
|
variant="outline"
|
||||||
onClick={() => {
|
size="sm"
|
||||||
// Test the connection to the configured URL
|
onClick={testConnection}
|
||||||
console.log('Testing connection to:', sessionSharingConfig.baseUrl);
|
disabled={testResult.status === 'testing'}
|
||||||
// TODO: Implement actual connection test
|
className="flex items-center gap-2"
|
||||||
}}
|
>
|
||||||
>
|
{testResult.status === 'testing' ? (
|
||||||
Test Connection
|
<>
|
||||||
</Button>
|
<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>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
+35
-1
@@ -874,9 +874,43 @@ const openDirectoryDialog = async (
|
|||||||
|
|
||||||
addRecentDir(dirToAdd);
|
addRecentDir(dirToAdd);
|
||||||
const currentWindow = BrowserWindow.getFocusedWindow();
|
const currentWindow = BrowserWindow.getFocusedWindow();
|
||||||
await createChat(app, undefined, dirToAdd);
|
|
||||||
if (replaceWindow && currentWindow) {
|
if (replaceWindow && currentWindow) {
|
||||||
|
// Replace current window with new one
|
||||||
|
await createChat(app, undefined, dirToAdd);
|
||||||
currentWindow.close();
|
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;
|
return result;
|
||||||
|
|||||||
Reference in New Issue
Block a user