diff --git a/backend/open_webui/apps/webui/main.py b/backend/open_webui/apps/webui/main.py index e58f83654..1210ac7c3 100644 --- a/backend/open_webui/apps/webui/main.py +++ b/backend/open_webui/apps/webui/main.py @@ -10,11 +10,11 @@ from open_webui.apps.webui.routers import ( auths, chats, configs, - projects, files, functions, memories, models, + knowledge, prompts, tools, users, @@ -111,15 +111,15 @@ app.include_router(auths.router, prefix="/auths", tags=["auths"]) app.include_router(users.router, prefix="/users", tags=["users"]) app.include_router(chats.router, prefix="/chats", tags=["chats"]) -app.include_router(projects.router, prefix="/projects", tags=["projects"]) app.include_router(models.router, prefix="/models", tags=["models"]) +app.include_router(knowledge.router, prefix="/knowledge", tags=["knowledge"]) app.include_router(prompts.router, prefix="/prompts", tags=["prompts"]) -app.include_router(memories.router, prefix="/memories", tags=["memories"]) app.include_router(files.router, prefix="/files", tags=["files"]) app.include_router(tools.router, prefix="/tools", tags=["tools"]) app.include_router(functions.router, prefix="/functions", tags=["functions"]) +app.include_router(memories.router, prefix="/memories", tags=["memories"]) app.include_router(utils.router, prefix="/utils", tags=["utils"]) diff --git a/backend/open_webui/apps/webui/models/projects.py b/backend/open_webui/apps/webui/models/knowledge.py similarity index 65% rename from backend/open_webui/apps/webui/models/projects.py rename to backend/open_webui/apps/webui/models/knowledge.py index 07535c958..d5d329f00 100644 --- a/backend/open_webui/apps/webui/models/projects.py +++ b/backend/open_webui/apps/webui/models/knowledge.py @@ -14,12 +14,12 @@ log = logging.getLogger(__name__) log.setLevel(SRC_LOG_LEVELS["MODELS"]) #################### -# Projects DB Schema +# Knowledge DB Schema #################### -class Project(Base): - __tablename__ = "project" +class Knowledge(Base): + __tablename__ = "knowledge" id = Column(Text, unique=True, primary_key=True) user_id = Column(Text) @@ -34,7 +34,7 @@ class Project(Base): updated_at = Column(BigInteger) -class ProjectModel(BaseModel): +class KnowledgeModel(BaseModel): model_config = ConfigDict(from_attributes=True) id: str @@ -55,7 +55,7 @@ class ProjectModel(BaseModel): #################### -class ProjectResponse(BaseModel): +class KnowledgeResponse(BaseModel): id: str name: str description: str @@ -65,18 +65,18 @@ class ProjectResponse(BaseModel): updated_at: int # timestamp in epoch -class ProjectForm(BaseModel): +class KnowledgeForm(BaseModel): name: str description: str data: Optional[dict] = None -class ProjectTable: - def insert_new_project( - self, user_id: str, form_data: ProjectForm - ) -> Optional[ProjectModel]: +class KnowledgeTable: + def insert_new_knowledge( + self, user_id: str, form_data: KnowledgeForm + ) -> Optional[KnowledgeModel]: with get_db() as db: - project = ProjectModel( + knowledge = KnowledgeModel( **{ **form_data.model_dump(), "id": str(uuid.uuid4()), @@ -87,59 +87,59 @@ class ProjectTable: ) try: - result = Project(**project.model_dump()) + result = Knowledge(**knowledge.model_dump()) db.add(result) db.commit() db.refresh(result) if result: - return ProjectModel.model_validate(result) + return KnowledgeModel.model_validate(result) else: return None except Exception: return None - def get_projects(self) -> list[ProjectModel]: + def get_knowledge_items(self) -> list[KnowledgeModel]: with get_db() as db: return [ - ProjectModel.model_validate(project) - for project in db.query(Project) - .order_by(Project.updated_at.desc()) + KnowledgeModel.model_validate(knowledge) + for knowledge in db.query(Knowledge) + .order_by(Knowledge.updated_at.desc()) .all() ] - def get_project_by_id(self, id: str) -> Optional[ProjectModel]: + def get_knowledge_by_id(self, id: str) -> Optional[KnowledgeModel]: try: with get_db() as db: - project = db.query(Project).filter_by(id=id).first() - return ProjectModel.model_validate(project) if project else None + knowledge = db.query(Knowledge).filter_by(id=id).first() + return KnowledgeModel.model_validate(knowledge) if knowledge else None except Exception: return None - def update_project_by_id( - self, id: str, form_data: ProjectForm - ) -> Optional[ProjectModel]: + def update_knowledge_by_id( + self, id: str, form_data: KnowledgeForm + ) -> Optional[KnowledgeModel]: try: with get_db() as db: - db.query(Project).filter_by(id=id).update( + db.query(Knowledge).filter_by(id=id).update( { "name": form_data.name, "updated_id": int(time.time()), } ) db.commit() - return self.get_project_by_id(id=form_data.id) + return self.get_knowledge_by_id(id=form_data.id) except Exception as e: log.exception(e) return None - def delete_project_by_id(self, id: str) -> bool: + def delete_knowledge_by_id(self, id: str) -> bool: try: with get_db() as db: - db.query(Project).filter_by(id=id).delete() + db.query(Knowledge).filter_by(id=id).delete() db.commit() return True except Exception: return False -Projects = ProjectTable() +Knowledges = KnowledgeTable() diff --git a/backend/open_webui/apps/webui/routers/knowledge.py b/backend/open_webui/apps/webui/routers/knowledge.py new file mode 100644 index 000000000..0f97fb18c --- /dev/null +++ b/backend/open_webui/apps/webui/routers/knowledge.py @@ -0,0 +1,112 @@ +import json +from typing import Optional, Union +from pydantic import BaseModel +from fastapi import APIRouter, Depends, HTTPException, status + + +from open_webui.apps.webui.models.knowledge import ( + Knowledges, + KnowledgeModel, + KnowledgeForm, + KnowledgeResponse, +) +from open_webui.constants import ERROR_MESSAGES +from open_webui.utils.utils import get_admin_user, get_verified_user + +router = APIRouter() + +############################ +# GetKnowledgeItems +############################ + + +@router.get( + "/", response_model=Optional[Union[list[KnowledgeResponse], KnowledgeResponse]] +) +async def get_knowledge_items( + id: Optional[str] = None, user=Depends(get_verified_user) +): + if id: + knowledge = Knowledges.get_knowledge_by_id(id=id) + + if knowledge: + return knowledge + else: + raise HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, + detail=ERROR_MESSAGES.NOT_FOUND, + ) + else: + return [ + KnowledgeResponse(**knowledge.model_dump()) + for knowledge in Knowledges.get_knowledge_items() + ] + + +############################ +# CreateNewKnowledge +############################ + + +@router.post("/create", response_model=Optional[KnowledgeResponse]) +async def create_new_knowledge(form_data: KnowledgeForm, user=Depends(get_admin_user)): + knowledge = Knowledges.insert_new_knowledge(user.id, form_data) + + if knowledge: + return knowledge + else: + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail=ERROR_MESSAGES.FILE_EXISTS, + ) + + +############################ +# GetKnowledgeById +############################ + + +@router.get("/{id}", response_model=Optional[KnowledgeResponse]) +async def get_knowledge_by_id(id: str, user=Depends(get_verified_user)): + knowledge = Knowledges.get_knowledge_by_id(id=id) + + if knowledge: + return knowledge + else: + raise HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, + detail=ERROR_MESSAGES.NOT_FOUND, + ) + + +############################ +# UpdateKnowledgeById +############################ + + +@router.post("/{id}/update", response_model=Optional[KnowledgeResponse]) +async def update_knowledge_by_id( + id: str, + form_data: KnowledgeForm, + user=Depends(get_admin_user), +): + knowledge = Knowledges.update_knowledge_by_id(id=id, form_data=form_data) + + if knowledge: + return knowledge + else: + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail=ERROR_MESSAGES.ID_TAKEN, + ) + + +############################ +# DeleteKnowledgeById +############################ + + +@router.delete("/{id}/delete", response_model=bool) +async def delete_knowledge_by_id(id: str, user=Depends(get_admin_user)): + result = Knowledges.delete_knowledge_by_id(id=id) + return result diff --git a/backend/open_webui/apps/webui/routers/projects.py b/backend/open_webui/apps/webui/routers/projects.py deleted file mode 100644 index 493bde99e..000000000 --- a/backend/open_webui/apps/webui/routers/projects.py +++ /dev/null @@ -1,107 +0,0 @@ -import json -from typing import Optional, Union -from pydantic import BaseModel -from fastapi import APIRouter, Depends, HTTPException, status - - -from open_webui.apps.webui.models.projects import ( - Projects, - ProjectModel, - ProjectForm, - ProjectResponse, -) -from open_webui.constants import ERROR_MESSAGES -from open_webui.utils.utils import get_admin_user, get_verified_user - -router = APIRouter() - -############################ -# GetProjects -############################ - - -@router.get("/", response_model=Optional[Union[list[ProjectResponse], ProjectResponse]]) -async def get_projects(id: Optional[str] = None, user=Depends(get_verified_user)): - if id: - project = Projects.get_project_by_id(id=id) - - if project: - return project - else: - raise HTTPException( - status_code=status.HTTP_401_UNAUTHORIZED, - detail=ERROR_MESSAGES.NOT_FOUND, - ) - else: - return [ - ProjectResponse(**project.model_dump()) - for project in Projects.get_projects() - ] - - -############################ -# CreateNewProject -############################ - - -@router.post("/create", response_model=Optional[ProjectResponse]) -async def create_new_project(form_data: ProjectForm, user=Depends(get_admin_user)): - project = Projects.insert_new_project(user.id, form_data) - - if project: - return project - else: - raise HTTPException( - status_code=status.HTTP_400_BAD_REQUEST, - detail=ERROR_MESSAGES.FILE_EXISTS, - ) - - -############################ -# GetProjectById -############################ - - -@router.get("/{id}", response_model=Optional[ProjectResponse]) -async def get_projects(id: str, user=Depends(get_verified_user)): - project = Projects.get_project_by_id(id=id) - - if project: - return project - else: - raise HTTPException( - status_code=status.HTTP_401_UNAUTHORIZED, - detail=ERROR_MESSAGES.NOT_FOUND, - ) - - -############################ -# UpdateProjectById -############################ - - -@router.post("/{id}/update", response_model=Optional[ProjectResponse]) -async def update_project_by_id( - id: str, - form_data: ProjectForm, - user=Depends(get_admin_user), -): - project = Projects.update_project_by_id(form_data) - if project: - return project - else: - raise HTTPException( - status_code=status.HTTP_400_BAD_REQUEST, - detail=ERROR_MESSAGES.ID_TAKEN, - ) - - -############################ -# DeleteProjectById -############################ - - -@router.delete("/{id}/delete", response_model=bool) -async def delete_project_by_id(id: str, user=Depends(get_admin_user)): - result = Projects.delete_project_by_id(id=id) - return result diff --git a/backend/open_webui/migrations/versions/6a39f3d8e55c_add_project_table.py b/backend/open_webui/migrations/versions/6a39f3d8e55c_add_knowledge_table.py similarity index 85% rename from backend/open_webui/migrations/versions/6a39f3d8e55c_add_project_table.py rename to backend/open_webui/migrations/versions/6a39f3d8e55c_add_knowledge_table.py index e61c49437..5521babd9 100644 --- a/backend/open_webui/migrations/versions/6a39f3d8e55c_add_project_table.py +++ b/backend/open_webui/migrations/versions/6a39f3d8e55c_add_knowledge_table.py @@ -1,4 +1,4 @@ -"""Add project table +"""Add knowledge table Revision ID: 6a39f3d8e55c Revises: c0fbf31ca0db @@ -19,10 +19,10 @@ depends_on = None def upgrade(): - # Creating the 'project' table - print("Creating project table") - project_table = op.create_table( - "project", + # Creating the 'knowledge' table + print("Creating knowledge table") + knowledge_table = op.create_table( + "knowledge", sa.Column("id", sa.Text(), primary_key=True), sa.Column("user_id", sa.Text(), nullable=False), sa.Column("name", sa.Text(), nullable=False), @@ -33,7 +33,7 @@ def upgrade(): sa.Column("updated_at", sa.BigInteger(), nullable=True), ) - print("Migrating data from document table to project table") + print("Migrating data from document table to knowledge table") # Representation of the existing 'document' table document_table = table( "document", @@ -57,10 +57,10 @@ def upgrade(): ) ) - # Insert data into project table from document table + # Insert data into knowledge table from document table for doc in documents: op.get_bind().execute( - project_table.insert().values( + knowledge_table.insert().values( id=doc.collection_name, user_id=doc.user_id, description=doc.name, @@ -76,4 +76,4 @@ def upgrade(): def downgrade(): - op.drop_table("project") + op.drop_table("knowledge") diff --git a/src/lib/apis/projects/index.ts b/src/lib/apis/knowledge/index.ts similarity index 72% rename from src/lib/apis/projects/index.ts rename to src/lib/apis/knowledge/index.ts index af448d1bb..600c3bbac 100644 --- a/src/lib/apis/projects/index.ts +++ b/src/lib/apis/knowledge/index.ts @@ -1,9 +1,9 @@ import { WEBUI_API_BASE_URL } from '$lib/constants'; -export const createNewProject = async (token: string, name: string, description: string) => { +export const createNewKnowledge = async (token: string, name: string, description: string) => { let error = null; - const res = await fetch(`${WEBUI_API_BASE_URL}/projects/create`, { + const res = await fetch(`${WEBUI_API_BASE_URL}/knowledge/create`, { method: 'POST', headers: { Accept: 'application/json', @@ -32,10 +32,10 @@ export const createNewProject = async (token: string, name: string, description: return res; }; -export const getProjects = async (token: string = '') => { +export const getKnowledgeItems = async (token: string = '') => { let error = null; - const res = await fetch(`${WEBUI_API_BASE_URL}/projects/`, { + const res = await fetch(`${WEBUI_API_BASE_URL}/knowledge/`, { method: 'GET', headers: { Accept: 'application/json', @@ -63,10 +63,10 @@ export const getProjects = async (token: string = '') => { return res; }; -export const getProjectById = async (token: string, id: string) => { +export const getKnowledgeById = async (token: string, id: string) => { let error = null; - const res = await fetch(`${WEBUI_API_BASE_URL}/projects/${id}`, { + const res = await fetch(`${WEBUI_API_BASE_URL}/knowledge/${id}`, { method: 'GET', headers: { Accept: 'application/json', @@ -95,14 +95,16 @@ export const getProjectById = async (token: string, id: string) => { return res; }; -type ProjectForm = { +type KnowledgeForm = { name: string; + description: string; + data: object; }; -export const updateProjectById = async (token: string, id: string, form: ProjectForm) => { +export const updateKnowledgeById = async (token: string, id: string, form: KnowledgeForm) => { let error = null; - const res = await fetch(`${WEBUI_API_BASE_URL}/projects/${id}/update`, { + const res = await fetch(`${WEBUI_API_BASE_URL}/knowledge/${id}/update`, { method: 'POST', headers: { Accept: 'application/json', @@ -110,7 +112,9 @@ export const updateProjectById = async (token: string, id: string, form: Project authorization: `Bearer ${token}` }, body: JSON.stringify({ - name: form.name + name: form.name, + description: form.description, + data: form.data }) }) .then(async (res) => { @@ -134,10 +138,10 @@ export const updateProjectById = async (token: string, id: string, form: Project return res; }; -export const deleteProjectById = async (token: string, id: string) => { +export const deleteKnowledgeById = async (token: string, id: string) => { let error = null; - const res = await fetch(`${WEBUI_API_BASE_URL}/projects/${id}/delete`, { + const res = await fetch(`${WEBUI_API_BASE_URL}/knowledge/${id}/delete`, { method: 'DELETE', headers: { Accept: 'application/json', diff --git a/src/lib/components/admin/Settings/Documents.svelte b/src/lib/components/admin/Settings/Documents.svelte index dfdc97511..d4ff6bd66 100644 --- a/src/lib/components/admin/Settings/Documents.svelte +++ b/src/lib/components/admin/Settings/Documents.svelte @@ -19,8 +19,8 @@ updateRAGConfig } from '$lib/apis/retrieval'; - import { projects, models } from '$lib/stores'; - import { getProjects } from '$lib/apis/projects'; + import { knowledge, models } from '$lib/stores'; + import { getKnowledgeItems } from '$lib/apis/knowledge'; import { deleteAllFiles, deleteFileById } from '$lib/apis/files'; import ResetUploadDirConfirmDialog from '$lib/components/common/ConfirmDialog.svelte'; @@ -69,7 +69,7 @@ scanDirLoading = false; if (res) { - await projects.set(await getProjects(localStorage.token)); + await knowledge.set(await getKnowledgeItems(localStorage.token)); toast.success($i18n.t('Scan complete!')); } }; diff --git a/src/lib/components/chat/MessageInput/Commands.svelte b/src/lib/components/chat/MessageInput/Commands.svelte index de92c00f5..d23c4c8d8 100644 --- a/src/lib/components/chat/MessageInput/Commands.svelte +++ b/src/lib/components/chat/MessageInput/Commands.svelte @@ -5,7 +5,7 @@ const dispatch = createEventDispatcher(); import Prompts from './Commands/Prompts.svelte'; - import Projects from './Commands/Projects.svelte'; + import Knowledge from './Commands/Knowledge.svelte'; import Models from './Commands/Models.svelte'; import { removeLastWordFromString } from '$lib/utils'; @@ -97,7 +97,7 @@ {#if command?.charAt(0) === '/'} {:else if command?.charAt(0) === '#'} - { return e.item; }) - : $projects; + : $knowledge; } $: if (command) { @@ -34,7 +34,7 @@ }; export const selectDown = () => { - selectedIdx = Math.min(selectedIdx + 1, filteredProjects.length - 1); + selectedIdx = Math.min(selectedIdx + 1, filteredItems.length - 1); }; const confirmSelect = async (item) => { @@ -71,13 +71,13 @@ }; onMount(() => { - fuse = new Fuse($projects, { + fuse = new Fuse($knowledge, { keys: ['name', 'description'] }); }); -{#if filteredProjects.length > 0 || prompt.split(' ')?.at(0)?.substring(1).startsWith('http')} +{#if filteredItems.length > 0 || prompt.split(' ')?.at(0)?.substring(1).startsWith('http')}
- {#each filteredProjects as project, idx} + {#each filteredItems as item, idx} {/each} diff --git a/src/lib/components/workspace/Projects.svelte b/src/lib/components/workspace/Knowledge.svelte similarity index 70% rename from src/lib/components/workspace/Projects.svelte rename to src/lib/components/workspace/Knowledge.svelte index 437b3590b..77d1124f8 100644 --- a/src/lib/components/workspace/Projects.svelte +++ b/src/lib/components/workspace/Knowledge.svelte @@ -7,9 +7,9 @@ import { onMount, getContext } from 'svelte'; const i18n = getContext('i18n'); - import { WEBUI_NAME, projects } from '$lib/stores'; + import { WEBUI_NAME, knowledge } from '$lib/stores'; - import { getProjects, deleteProjectById } from '$lib/apis/projects'; + import { getKnowledgeItems, deleteKnowledgeById } from '$lib/apis/knowledge'; import { blobToFile, transformFileName } from '$lib/utils'; @@ -18,50 +18,50 @@ import GarbageBin from '../icons/GarbageBin.svelte'; import Pencil from '../icons/Pencil.svelte'; import DeleteConfirmDialog from '../common/ConfirmDialog.svelte'; - import ProjectMenu from './Projects/ProjectMenu.svelte'; + import ItemMenu from './Knowledge/ItemMenu.svelte'; let query = ''; - let selectedProject = null; + let selectedItem = null; let showDeleteConfirm = false; - let filteredProjects; - $: filteredProjects = $projects.filter((project) => query === '' || project.name.includes(query)); + let filteredItems; + $: filteredItems = $knowledge.filter((item) => query === '' || item.name.includes(query)); - const deleteHandler = async (project) => { - const res = await deleteProjectById(localStorage.token, project.id).catch((e) => { + const deleteHandler = async (item) => { + const res = await deleteKnowledgeById(localStorage.token, item.id).catch((e) => { toast.error(e); }); if (res) { - projects.set(await getProjects(localStorage.token)); - toast.success($i18n.t('Project deleted successfully.')); + knowledge.set(await getKnowledgeItems(localStorage.token)); + toast.success($i18n.t('Knowledge deleted successfully.')); } }; onMount(async () => { - projects.set(await getProjects(localStorage.token)); + knowledge.set(await getKnowledgeItems(localStorage.token)); }); - {$i18n.t('Projects')} | {$WEBUI_NAME} + {$i18n.t('Knowledge')} | {$WEBUI_NAME} { - deleteHandler(selectedProject); + deleteHandler(selectedItem); }} />
- {$i18n.t('Projects')} + {$i18n.t('Knowledge')}
- {$projects.length} + {$knowledge.length}
@@ -85,16 +85,16 @@
+ +
+ {#if id && knowledge} +
+
+
+ {knowledge.name} +
+
+ {knowledge.description} +
+
+
+ {:else} + + {/if} +
+
diff --git a/src/lib/components/workspace/Projects/ProjectMenu.svelte b/src/lib/components/workspace/Knowledge/ItemMenu.svelte similarity index 100% rename from src/lib/components/workspace/Projects/ProjectMenu.svelte rename to src/lib/components/workspace/Knowledge/ItemMenu.svelte diff --git a/src/lib/components/workspace/Models/Knowledge/Selector.svelte b/src/lib/components/workspace/Models/Knowledge/Selector.svelte index 5dfd43ef9..0f04723b8 100644 --- a/src/lib/components/workspace/Models/Knowledge/Selector.svelte +++ b/src/lib/components/workspace/Models/Knowledge/Selector.svelte @@ -3,33 +3,33 @@ import { onMount, getContext } from 'svelte'; import { flyAndScale } from '$lib/utils/transitions'; - import { projects } from '$lib/stores'; + import { knowledge } from '$lib/stores'; import Dropdown from '$lib/components/common/Dropdown.svelte'; const i18n = getContext('i18n'); export let onClose: Function = () => {}; - export let knowledge = []; + export let _knowledge = []; let items = []; onMount(() => { let collections = [ - ...$projects + ...$knowledge .reduce((a, e, i, arr) => { return [...new Set([...a, ...(e?.content?.tags ?? []).map((tag) => tag.name)])]; }, []) .map((tag) => ({ name: tag, type: 'collection', - collection_names: $projects + collection_names: $knowledge .filter((doc) => (doc?.content?.tags ?? []).map((tag) => tag.name).includes(tag)) .map((doc) => doc.collection_name) })) ]; - items = [...collections, ...$projects]; + items = [...collections, ...$knowledge]; }); @@ -60,9 +60,9 @@ { - if (!knowledge.find((k) => k.name === item.name)) { - knowledge = [ - ...knowledge, + if (!_knowledge.find((k) => k.name === item.name)) { + _knowledge = [ + ..._knowledge, { ...item, type: item?.type ?? 'doc' diff --git a/src/lib/components/workspace/Projects/Project.svelte b/src/lib/components/workspace/Projects/Project.svelte deleted file mode 100644 index e69de29bb..000000000 diff --git a/src/lib/stores/index.ts b/src/lib/stores/index.ts index 844eea514..7dadb9454 100644 --- a/src/lib/stores/index.ts +++ b/src/lib/stores/index.ts @@ -29,7 +29,7 @@ export const tags = writable([]); export const models: Writable = writable([]); export const prompts: Writable = writable([]); -export const projects: Writable = writable([]); +export const knowledge: Writable = writable([]); export const tools = writable([]); export const functions = writable([]); diff --git a/src/routes/(app)/+layout.svelte b/src/routes/(app)/+layout.svelte index 0556a87a1..0f005d3b7 100644 --- a/src/routes/(app)/+layout.svelte +++ b/src/routes/(app)/+layout.svelte @@ -10,7 +10,7 @@ import { page } from '$app/stores'; import { fade } from 'svelte/transition'; - import { getProjects } from '$lib/apis/projects'; + import { getKnowledgeItems } from '$lib/apis/knowledge'; import { getFunctions } from '$lib/apis/functions'; import { getModels as _getModels, getVersionUpdates } from '$lib/apis'; import { getAllChatTags } from '$lib/apis/chats'; @@ -28,7 +28,7 @@ settings, models, prompts, - projects, + knowledge, tools, functions, tags, @@ -105,7 +105,7 @@ prompts.set(await getPrompts(localStorage.token)); })(), (async () => { - projects.set(await getProjects(localStorage.token)); + knowledge.set(await getKnowledgeItems(localStorage.token)); })(), (async () => { tools.set(await getTools(localStorage.token)); diff --git a/src/routes/(app)/workspace/+layout.svelte b/src/routes/(app)/workspace/+layout.svelte index a3a91133e..65cd300a9 100644 --- a/src/routes/(app)/workspace/+layout.svelte +++ b/src/routes/(app)/workspace/+layout.svelte @@ -61,6 +61,17 @@ href="/workspace/models">{$i18n.t('Models')} + + {$i18n.t('Knowledge')} + + {$i18n.t('Prompts')} - - {$i18n.t('Projects')} - -