Skip to content

Commit 694fb37

Browse files
committed
refac
1 parent adcc50d commit 694fb37

2 files changed

Lines changed: 174 additions & 0 deletions

File tree

src/lib/utils/connections.ts

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
/**
2+
* Shared helpers for managing system-level connections.
3+
* Used by both the admin settings UI and the desktop event handler
4+
* to ensure consistent add/remove logic.
5+
*/
6+
7+
import { getOpenAIConfig, updateOpenAIConfig } from '$lib/apis/openai';
8+
import {
9+
getTerminalServerConnections,
10+
setTerminalServerConnections
11+
} from '$lib/apis/configs';
12+
13+
// ─── OpenAI Connections ─────────────────────────────────
14+
15+
/**
16+
* Add an OpenAI-compatible API connection at the system level.
17+
* Mirrors the logic in admin/Settings/Connections.svelte.
18+
*/
19+
export const addOpenAIConnection = async (
20+
token: string,
21+
connection: { url: string; key?: string; config?: object }
22+
) => {
23+
const current = await getOpenAIConfig(token);
24+
const urls = current?.OPENAI_API_BASE_URLS ?? [];
25+
const keys = current?.OPENAI_API_KEYS ?? [];
26+
const configs = current?.OPENAI_API_CONFIGS ?? {};
27+
28+
const normalizedUrl = connection.url.replace(/\/$/, '');
29+
30+
// Don't add duplicates
31+
if (urls.map((u: string) => u.replace(/\/$/, '')).includes(normalizedUrl)) {
32+
return current;
33+
}
34+
35+
urls.push(normalizedUrl);
36+
keys.push(connection.key ?? '');
37+
if (connection.config) {
38+
configs[(urls.length - 1).toString()] = connection.config;
39+
}
40+
41+
return await updateOpenAIConfig(token, {
42+
ENABLE_OPENAI_API: current?.ENABLE_OPENAI_API ?? true,
43+
OPENAI_API_BASE_URLS: urls,
44+
OPENAI_API_KEYS: keys,
45+
OPENAI_API_CONFIGS: configs
46+
});
47+
};
48+
49+
/**
50+
* Remove an OpenAI-compatible API connection by URL at the system level.
51+
* Re-indexes OPENAI_API_CONFIGS to match the admin delete pattern.
52+
*/
53+
export const removeOpenAIConnection = async (token: string, url: string) => {
54+
const current = await getOpenAIConfig(token);
55+
const urls: string[] = current?.OPENAI_API_BASE_URLS ?? [];
56+
const keys: string[] = current?.OPENAI_API_KEYS ?? [];
57+
const configs: Record<string, any> = current?.OPENAI_API_CONFIGS ?? {};
58+
59+
const normalizedUrl = url.replace(/\/$/, '');
60+
const idx = urls.findIndex((u: string) => u.replace(/\/$/, '') === normalizedUrl);
61+
if (idx === -1) return current;
62+
63+
const newUrls = urls.filter((_: string, i: number) => i !== idx);
64+
const newKeys = keys.filter((_: string, i: number) => i !== idx);
65+
66+
// Re-index configs (mirrors admin/Settings/Connections.svelte onDelete)
67+
const newConfigs: Record<string, any> = {};
68+
newUrls.forEach((_: string, newIdx: number) => {
69+
newConfigs[newIdx] = configs[newIdx < idx ? newIdx : newIdx + 1];
70+
});
71+
72+
return await updateOpenAIConfig(token, {
73+
ENABLE_OPENAI_API: current?.ENABLE_OPENAI_API ?? true,
74+
OPENAI_API_BASE_URLS: newUrls,
75+
OPENAI_API_KEYS: newKeys,
76+
OPENAI_API_CONFIGS: newConfigs
77+
});
78+
};
79+
80+
// ─── Terminal Server Connections ────────────────────────
81+
82+
/**
83+
* Add a terminal server connection at the system level.
84+
* Mirrors the logic in admin/Settings/Integrations.svelte.
85+
*/
86+
export const addTerminalConnection = async (
87+
token: string,
88+
connection: { url: string; key?: string; name?: string; auth_type?: string }
89+
) => {
90+
const current = await getTerminalServerConnections(token);
91+
const servers = current?.TERMINAL_SERVER_CONNECTIONS ?? [];
92+
93+
// Don't add duplicates
94+
if (servers.find((s: any) => s.url === connection.url)) {
95+
return current;
96+
}
97+
98+
servers.push({
99+
url: connection.url,
100+
key: connection.key ?? '',
101+
auth_type: connection.auth_type ?? 'bearer',
102+
name: connection.name ?? 'Open Terminal',
103+
enabled: true
104+
});
105+
106+
return await setTerminalServerConnections(token, {
107+
TERMINAL_SERVER_CONNECTIONS: servers
108+
});
109+
};
110+
111+
/**
112+
* Remove a terminal server connection by URL at the system level.
113+
*/
114+
export const removeTerminalConnection = async (token: string, url: string) => {
115+
const current = await getTerminalServerConnections(token);
116+
const servers = current?.TERMINAL_SERVER_CONNECTIONS ?? [];
117+
118+
const filtered = servers.filter((s: any) => s.url !== url);
119+
if (filtered.length === servers.length) return current; // nothing to remove
120+
121+
return await setTerminalServerConnections(token, {
122+
TERMINAL_SERVER_CONNECTIONS: filtered
123+
});
124+
};

src/routes/+layout.svelte

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,12 @@
5353
import { getSessionUser, userSignOut } from '$lib/apis/auths';
5454
import { getAllTags, getChatList } from '$lib/apis/chats';
5555
import { chatCompletion } from '$lib/apis/openai';
56+
import {
57+
addOpenAIConnection,
58+
removeOpenAIConnection,
59+
addTerminalConnection,
60+
removeTerminalConnection
61+
} from '$lib/utils/connections';
5662
5763
import { WEBUI_API_BASE_URL, WEBUI_BASE_URL, WEBUI_HOSTNAME } from '$lib/constants';
5864
import { bestMatchingLanguage, displayFileHandler } from '$lib/utils';
@@ -692,6 +698,45 @@
692698
}
693699
};
694700
701+
const desktopEventHandler = async (event) => {
702+
// Events that don't require auth
703+
if (event.type === 'page:reload') {
704+
location.reload();
705+
return;
706+
}
707+
708+
const token = localStorage.token;
709+
if (!token) return;
710+
711+
// Only admins can modify system-level connections
712+
if ($user?.role !== 'admin') return;
713+
714+
try {
715+
if (event.type === 'connections:terminal') {
716+
if (event.data.action === 'add') {
717+
await addTerminalConnection(token, {
718+
url: event.data.url,
719+
key: event.data.key,
720+
name: 'Local Open Terminal'
721+
});
722+
} else if (event.data.action === 'remove') {
723+
await removeTerminalConnection(token, event.data.url);
724+
}
725+
} else if (event.type === 'connections:openai') {
726+
if (event.data.action === 'add') {
727+
await addOpenAIConnection(token, {
728+
url: event.data.url,
729+
key: event.data.key
730+
});
731+
} else if (event.data.action === 'remove') {
732+
await removeOpenAIConnection(token, event.data.url);
733+
}
734+
}
735+
} catch (e) {
736+
console.error('Desktop connection update failed:', e);
737+
}
738+
};
739+
695740
const windowMessageEventHandler = async (event) => {
696741
if (
697742
!['https://openwebui.com', 'https://www.openwebui.com', 'http://localhost:9999'].includes(
@@ -767,6 +812,11 @@
767812
appData.set(data);
768813
}
769814
}
815+
816+
// Listen for desktop service lifecycle events (scalable protocol)
817+
if (window.electronAPI.onEvent) {
818+
window.electronAPI.onEvent(desktopEventHandler);
819+
}
770820
}
771821
772822
// Listen for messages on the BroadcastChannel

0 commit comments

Comments
 (0)