feat: add Open WebUI AI chat integration and widget
Adds a new "openWebUi" integration kind (under a new "ai" category) and an AI Chat widget for chatting with models served by Open WebUI. - Integration: Bearer API key auth, model list, native chat history CRUD, and token-by-token streaming chat completions (SSE). - Widget: in-input model picker, streaming responses, and an in-widget history panel. Reconstructs conversations from Open WebUI's message tree with a flat fallback. - Streaming is delivered over the WebSocket subscription link. - Adds integration and widget documentation.
This commit is contained in:
1 parent
f3608b26a0
commit
005c2e4cd1
25 files changed
+1290
No files matched your search
@@ -195,6 +195,7 @@ export type HomarrDocumentationPath =
|
||||
| "/docs/integrations/ntfy"
|
||||
| "/docs/integrations/nzbget"
|
||||
| "/docs/integrations/open-media-vault"
|
||||
| "/docs/integrations/open-webui"
|
||||
| "/docs/integrations/opnsense"
|
||||
| "/docs/integrations/overseerr"
|
||||
| "/docs/integrations/paperless-ngx"
|
||||
|
||||
@@ -59,5 +59,6 @@ export const integrationDocSlugs: Record<IntegrationKind, string | null> = {
|
||||
peaNut: "peanut",
|
||||
beszel: "beszel",
|
||||
archiveTeamWarrior: null,
|
||||
openWebUi: "open-webui",
|
||||
mock: null,
|
||||
};
|
||||
@@ -51,4 +51,5 @@ export const widgetDocSlugs: Record<WidgetKind, string | null> = {
|
||||
beszelAlerts: "beszel-alerts",
|
||||
beszelSystemStats: "beszel-system-stats",
|
||||
customApi: "custom-api",
|
||||
openWebUi: "open-webui",
|
||||
};
|
||||
@@ -504,6 +504,15 @@ export const integrationDefs = {
|
||||
defaultUrl: "http://localhost:8001",
|
||||
documentationUrl: null,
|
||||
},
|
||||
openWebUi: {
|
||||
name: "Open WebUI",
|
||||
secretKinds: [["apiKey"]],
|
||||
iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons@master/svg/open-webui.svg",
|
||||
category: ["ai"],
|
||||
documentationUrl: createDocumentationLink("/docs/integrations/open-webui"),
|
||||
defaultPort: 8080,
|
||||
apiKeySettingsPath: "/?settings=open#account",
|
||||
},
|
||||
// This integration only returns mock data, it is used during development (but can also be used in production by directly going to the create page)
|
||||
mock: {
|
||||
name: "Mock",
|
||||
@@ -617,6 +626,7 @@ export const integrationCategories = [
|
||||
"documents",
|
||||
"mediaLibrary",
|
||||
"uptimeMonitoring",
|
||||
"ai",
|
||||
] as const;
|
||||
|
||||
export type IntegrationCategory = (typeof integrationCategories)[number];
|
||||
@@ -40,6 +40,7 @@ export const widgetIntegrationSupport: Partial<Record<WidgetKind, readonly Integ
|
||||
audioStats: ["navidrome", "audiobookshelf"],
|
||||
vpn: getIntegrationKindsByCategory("vpn"),
|
||||
anchorNote: ["anchor"],
|
||||
openWebUi: ["openWebUi"],
|
||||
};
|
||||
|
||||
export const getWidgetKindsForIntegration = (integrationKind: IntegrationKind): WidgetKind[] => {
|
||||
|
||||
@@ -49,6 +49,7 @@ export const widgetKinds = [
|
||||
"beszelAlerts",
|
||||
"beszelSystemStats",
|
||||
"customApi",
|
||||
"openWebUi",
|
||||
] as const;
|
||||
export type WidgetKind = (typeof widgetKinds)[number];
|
||||
|
||||
|
||||
Reference in new issue
Block a user