mirror of
https://github.com/open-webui/open-webui.git
synced 2026-08-22 16:44:06 -05:00
refac
This commit is contained in:
@@ -27,6 +27,7 @@ from open_webui.utils.terminals import (
|
||||
terminal_context_available,
|
||||
terminal_context_config,
|
||||
terminal_context_id,
|
||||
terminal_chat_uploads,
|
||||
terminal_contexts,
|
||||
)
|
||||
from open_webui.utils.tools import bearer_auth_header, normalize_bearer_token
|
||||
@@ -87,6 +88,7 @@ async def list_terminal_servers(request: Request, user=Depends(get_verified_user
|
||||
'url': connection.get('url', ''),
|
||||
'name': connection.get('name', ''),
|
||||
'contexts': terminal_contexts(connection),
|
||||
'config': {'chat_uploads': terminal_chat_uploads(connection)},
|
||||
}
|
||||
for connection in connections
|
||||
if connection.get('enabled', True) and await has_connection_access(user, connection, user_group_ids)
|
||||
|
||||
@@ -8,6 +8,7 @@ TERMINAL_CONTEXT_HEADER = 'X-Terminal-Context-Id'
|
||||
TERMINAL_CONTEXT_DEFAULT = 'default'
|
||||
TERMINAL_CONTEXT_TYPES = {'chat', 'automation'}
|
||||
TERMINAL_CONTEXT_ID_SOURCES = {'chat': 'chat_id', 'automation': 'automation_id'}
|
||||
TERMINAL_CHAT_UPLOAD_MODES = {'default', 'filesystem'}
|
||||
|
||||
|
||||
def is_terminal_orchestrator(connection: dict) -> bool:
|
||||
@@ -104,3 +105,9 @@ def terminal_contexts(connection: dict) -> dict:
|
||||
else:
|
||||
result[context] = {}
|
||||
return result
|
||||
|
||||
|
||||
def terminal_chat_uploads(connection: dict) -> str:
|
||||
"""Return normalized main-chat upload behavior for this connection."""
|
||||
value = (connection.get('config') or {}).get('chat_uploads')
|
||||
return value if value in TERMINAL_CHAT_UPLOAD_MODES else 'default'
|
||||
|
||||
@@ -43,6 +43,10 @@ export type TerminalServer = {
|
||||
url: string;
|
||||
name: string;
|
||||
contexts?: Record<string, false | { context_id?: string }>;
|
||||
config?: {
|
||||
chat_uploads?: 'default' | 'filesystem';
|
||||
[key: string]: unknown;
|
||||
};
|
||||
};
|
||||
|
||||
export const getTerminalServers = async (token: string): Promise<TerminalServer[]> => {
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
let auth_type = 'bearer';
|
||||
let path = '/openapi.json';
|
||||
let enabled = false;
|
||||
let chatUploads: 'default' | 'filesystem' = 'default';
|
||||
let chatContextMode: 'default' | 'chat_id' | 'off' = 'default';
|
||||
let automationContextMode: 'default' | 'automation_id' | 'off' = 'default';
|
||||
let showAdvanced = false;
|
||||
@@ -80,6 +81,7 @@
|
||||
auth_type = connection?.auth_type ?? 'bearer';
|
||||
path = connection?.path ?? '/openapi.json';
|
||||
enabled = connection?.enabled ?? true;
|
||||
chatUploads = connection?.config?.chat_uploads === 'filesystem' ? 'filesystem' : 'default';
|
||||
accessGrants = connection?.config?.access_grants ?? [];
|
||||
|
||||
// Restore policy state
|
||||
@@ -125,6 +127,7 @@
|
||||
auth_type = 'bearer';
|
||||
path = '/openapi.json';
|
||||
enabled = false;
|
||||
chatUploads = 'default';
|
||||
accessGrants = [];
|
||||
chatContextMode = 'default';
|
||||
automationContextMode = 'default';
|
||||
@@ -373,6 +376,14 @@
|
||||
contexts.automation = { context_id: 'automation_id' };
|
||||
}
|
||||
const useContexts = !direct && serverType === 'orchestrator' && Object.keys(contexts).length > 0;
|
||||
const connectionConfig: Record<string, any> =
|
||||
connection?.config && typeof connection.config === 'object' ? { ...connection.config } : {};
|
||||
if (!direct) connectionConfig.access_grants = accessGrants;
|
||||
else delete connectionConfig.access_grants;
|
||||
if (useContexts) connectionConfig.contexts = contexts;
|
||||
else delete connectionConfig.contexts;
|
||||
if (chatUploads === 'filesystem') connectionConfig.chat_uploads = 'filesystem';
|
||||
else delete connectionConfig.chat_uploads;
|
||||
|
||||
const result = {
|
||||
...(!direct && id.trim() ? { id: id.trim() } : {}),
|
||||
@@ -382,10 +393,7 @@
|
||||
path,
|
||||
auth_type,
|
||||
enabled: enabled,
|
||||
config: {
|
||||
...(!direct ? { access_grants: accessGrants } : {}),
|
||||
...(useContexts ? { contexts } : {})
|
||||
},
|
||||
config: connectionConfig,
|
||||
// Policy fields
|
||||
...(serverType ? { server_type: serverType } : {}),
|
||||
...(serverType === 'orchestrator' && policyId ? { policy_id: policyId } : {})
|
||||
@@ -532,6 +540,26 @@
|
||||
</Tooltip>
|
||||
</div>
|
||||
|
||||
<div class="flex gap-2 mt-2">
|
||||
<div class="flex flex-col w-full">
|
||||
<div class="flex justify-between mb-0.5">
|
||||
<label for="terminal-chat-uploads" class={`text-xs text-gray-500`}
|
||||
>{$i18n.t('Chat Uploads')}</label
|
||||
>
|
||||
</div>
|
||||
<div class="flex flex-1 items-center">
|
||||
<select
|
||||
id="terminal-chat-uploads"
|
||||
class={`w-full text-sm ${selectClass}`}
|
||||
bind:value={chatUploads}
|
||||
>
|
||||
<option value="default">{$i18n.t('Default')}</option>
|
||||
<option value="filesystem">{$i18n.t('Filesystem')}</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Policy section (orchestrator only, admin only) -->
|
||||
{#if serverType === 'orchestrator' && !direct}
|
||||
<button
|
||||
|
||||
@@ -94,7 +94,8 @@
|
||||
url: `${WEBUI_API_BASE_URL}/terminals/${t.id}`,
|
||||
name: t.name,
|
||||
key: localStorage.token,
|
||||
contexts: t.contexts ?? {}
|
||||
contexts: t.contexts ?? {},
|
||||
config: t.config ?? {}
|
||||
}));
|
||||
terminalServers.set([...existingDirectTerminals, ...systemEntries] as any);
|
||||
}
|
||||
|
||||
@@ -56,6 +56,7 @@
|
||||
getWeekday
|
||||
} from '$lib/utils';
|
||||
import { uploadFile } from '$lib/apis/files';
|
||||
import { getCwd, uploadToTerminal } from '$lib/apis/terminal';
|
||||
import { generateAutoCompletion } from '$lib/apis';
|
||||
import { deleteFileById } from '$lib/apis/files';
|
||||
import { getChatById } from '$lib/apis/chats';
|
||||
@@ -860,19 +861,43 @@
|
||||
}
|
||||
};
|
||||
|
||||
const getFilesystemUploadTerminal = (
|
||||
selectedId = $selectedTerminalId,
|
||||
servers: any[] | null = $terminalServers,
|
||||
settingsValue: any = $settings
|
||||
) => {
|
||||
if (!selectedId) return null;
|
||||
|
||||
const systemTerminal = (servers ?? []).find(
|
||||
(t: any) => t.id && t.id === selectedId && t.config?.chat_uploads === 'filesystem'
|
||||
);
|
||||
if (systemTerminal) return systemTerminal;
|
||||
|
||||
return (
|
||||
(settingsValue?.terminalServers ?? []).find(
|
||||
(t: any) =>
|
||||
t.url === selectedId &&
|
||||
t.enabled &&
|
||||
t.config?.chat_uploads === 'filesystem'
|
||||
) ?? null
|
||||
);
|
||||
};
|
||||
|
||||
const uploadFileHandler = async (file, process = true, itemData = {}) => {
|
||||
if ($_user?.role !== 'admin' && !($_user?.permissions?.chat?.file_upload ?? true)) {
|
||||
toast.error($i18n.t('You do not have permission to upload files.'));
|
||||
return null;
|
||||
}
|
||||
|
||||
if (fileUploadCapableModels.length !== selectedModelIds.length) {
|
||||
const filesystemUploadTerminal = getFilesystemUploadTerminal();
|
||||
|
||||
if (!filesystemUploadTerminal && fileUploadCapableModels.length !== selectedModelIds.length) {
|
||||
toast.error($i18n.t('Model(s) do not support file upload'));
|
||||
return null;
|
||||
}
|
||||
|
||||
const tempItemId = uuidv4();
|
||||
const fileItem = {
|
||||
const fileItem: any = {
|
||||
type: 'file',
|
||||
file: '',
|
||||
id: null,
|
||||
@@ -896,6 +921,48 @@
|
||||
|
||||
files = [...files, fileItem];
|
||||
|
||||
if (filesystemUploadTerminal) {
|
||||
try {
|
||||
const cwd =
|
||||
(await getCwd(
|
||||
filesystemUploadTerminal.url,
|
||||
filesystemUploadTerminal.key,
|
||||
chatId || undefined
|
||||
))?.cwd || '/';
|
||||
const uploadedFile = await uploadToTerminal(
|
||||
filesystemUploadTerminal.url,
|
||||
filesystemUploadTerminal.key,
|
||||
cwd,
|
||||
file,
|
||||
chatId || undefined
|
||||
);
|
||||
|
||||
if (uploadedFile) {
|
||||
fileItem.type = 'terminal_file';
|
||||
fileItem.status = 'uploaded';
|
||||
fileItem.id = uploadedFile.path;
|
||||
fileItem.path = uploadedFile.path;
|
||||
fileItem.url = uploadedFile.path;
|
||||
fileItem.size = uploadedFile.size ?? file.size;
|
||||
fileItem.file = uploadedFile;
|
||||
files = files;
|
||||
} else {
|
||||
fileItem.status = 'error';
|
||||
fileItem.error = $i18n.t('Failed to upload file.');
|
||||
toast.error(fileItem.error);
|
||||
files = files.filter((item) => item?.itemId !== tempItemId);
|
||||
}
|
||||
} catch (e) {
|
||||
fileItem.status = 'error';
|
||||
fileItem.error = `${e}`;
|
||||
toast.error(`${e}`);
|
||||
files = files.filter((item) => item?.itemId !== tempItemId);
|
||||
} finally {
|
||||
onUpdate({ file: fileItem });
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!$temporaryChatEnabled) {
|
||||
try {
|
||||
// If the file is an audio file, provide the language for STT.
|
||||
@@ -2078,7 +2145,13 @@
|
||||
<InputMenu
|
||||
bind:files
|
||||
selectedModels={selectedModelIds}
|
||||
{fileUploadCapableModels}
|
||||
fileUploadCapableModels={getFilesystemUploadTerminal(
|
||||
$selectedTerminalId,
|
||||
$terminalServers,
|
||||
$settings
|
||||
)
|
||||
? selectedModelIds
|
||||
: fileUploadCapableModels}
|
||||
{toolApprovalMode}
|
||||
{onToolApprovalModeChange}
|
||||
{screenCaptureHandler}
|
||||
|
||||
@@ -47,7 +47,14 @@
|
||||
}))
|
||||
);
|
||||
data = data.filter((d) => d && !d.error);
|
||||
terminalServers.set([...data, ...existingSystemTerminals]);
|
||||
terminalServers.set([
|
||||
...data.map((d, i) => ({
|
||||
...d,
|
||||
key: activeTerminals[i]?.key ?? '',
|
||||
config: activeTerminals[i]?.config ?? d?.config ?? {}
|
||||
})),
|
||||
...existingSystemTerminals
|
||||
]);
|
||||
} else {
|
||||
terminalServers.set(existingSystemTerminals);
|
||||
}
|
||||
|
||||
@@ -74,7 +74,14 @@
|
||||
}))
|
||||
);
|
||||
terminalServersData = terminalServersData.filter((data: any) => data && !data.error);
|
||||
terminalServers.set([...terminalServersData, ...existingSystemTerminals] as any);
|
||||
terminalServers.set([
|
||||
...terminalServersData.map((data: any, i: number) => ({
|
||||
...data,
|
||||
key: activeTerminals[i]?.key ?? '',
|
||||
config: activeTerminals[i]?.config ?? data?.config ?? {}
|
||||
})),
|
||||
...existingSystemTerminals
|
||||
] as any);
|
||||
} else {
|
||||
terminalServers.set(existingSystemTerminals as any);
|
||||
}
|
||||
|
||||
@@ -434,6 +434,7 @@
|
||||
"Chat Permissions": "",
|
||||
"Chat Tags Auto-Generation": "",
|
||||
"Chat unshared successfully.": "",
|
||||
"Chat Uploads": "",
|
||||
"Chat Variables": "",
|
||||
"Chat Variables have conflicting model definitions": "",
|
||||
"chats": "",
|
||||
@@ -1236,6 +1237,7 @@
|
||||
"File uploaded successfully": "",
|
||||
"Filename": "",
|
||||
"Files": "",
|
||||
"Filesystem": "",
|
||||
"Fill the required fields first.": "",
|
||||
"Fill the source fields and test query first.": "",
|
||||
"Filter": "",
|
||||
|
||||
@@ -435,6 +435,7 @@
|
||||
"Chat Permissions": "",
|
||||
"Chat Tags Auto-Generation": "",
|
||||
"Chat unshared successfully.": "",
|
||||
"Chat Uploads": "",
|
||||
"Chat Variables": "",
|
||||
"Chat Variables have conflicting model definitions": "",
|
||||
"chats": "",
|
||||
@@ -1238,6 +1239,7 @@
|
||||
"File uploaded successfully": "",
|
||||
"Filename": "",
|
||||
"Files": "",
|
||||
"Filesystem": "",
|
||||
"Fill the required fields first.": "",
|
||||
"Fill the source fields and test query first.": "",
|
||||
"Filter": "",
|
||||
|
||||
@@ -161,7 +161,8 @@
|
||||
})
|
||||
.map((data, i) => ({
|
||||
...data,
|
||||
key: enabledTerminals[i]?.key ?? ''
|
||||
key: enabledTerminals[i]?.key ?? '',
|
||||
config: enabledTerminals[i]?.config ?? data?.config ?? {}
|
||||
}))
|
||||
: []),
|
||||
// Store with proxy URL and session key for FileNav file browsing
|
||||
@@ -170,7 +171,8 @@
|
||||
url: `${WEBUI_API_BASE_URL}/terminals/${t.id}`,
|
||||
name: t.name,
|
||||
key: localStorage.token,
|
||||
contexts: t.contexts ?? {}
|
||||
contexts: t.contexts ?? {},
|
||||
config: t.config ?? {}
|
||||
}))
|
||||
]);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user