From 8069a16227af7686e40e2e68f15f73858793ee3e Mon Sep 17 00:00:00 2001 From: Xin Wang Date: Sun, 8 Feb 2026 21:59:56 +0800 Subject: [PATCH] Patch both api and web sides --- api/app/routers/knowledge.py | 17 ++++++++++++++++- api/app/routers/workflows.py | 9 ++++++--- web/README.md | 2 +- web/services/apiClient.ts | 2 +- web/services/backendApi.ts | 18 ++++++++++-------- 5 files changed, 34 insertions(+), 14 deletions(-) diff --git a/api/app/routers/knowledge.py b/api/app/routers/knowledge.py index df22b8f..e4fae3e 100644 --- a/api/app/routers/knowledge.py +++ b/api/app/routers/knowledge.py @@ -146,12 +146,27 @@ def delete_knowledge_base(kb_id: str, db: Session = Depends(get_db)): @router.post("/bases/{kb_id}/documents") def upload_document( kb_id: str, - data: KnowledgeDocumentCreate, + data: Optional[KnowledgeDocumentCreate] = None, + name: Optional[str] = Query(default=None), + size: Optional[str] = Query(default=None), + file_type: Optional[str] = Query(default=None), + storage_url: Optional[str] = Query(default=None), db: Session = Depends(get_db) ): kb = db.query(KnowledgeBase).filter(KnowledgeBase.id == kb_id).first() if not kb: raise HTTPException(status_code=404, detail="Knowledge base not found") + + if data is None: + if not name or not size: + raise HTTPException(status_code=422, detail="name and size are required") + data = KnowledgeDocumentCreate( + name=name, + size=size, + fileType=file_type or "txt", + storageUrl=storage_url, + ) + doc = KnowledgeDocument( id=str(uuid.uuid4())[:8], kb_id=kb_id, diff --git a/api/app/routers/workflows.py b/api/app/routers/workflows.py index bdbc034..c6f9c9f 100644 --- a/api/app/routers/workflows.py +++ b/api/app/routers/workflows.py @@ -1,6 +1,5 @@ from fastapi import APIRouter, Depends, HTTPException from sqlalchemy.orm import Session -from typing import List import uuid from datetime import datetime @@ -11,7 +10,7 @@ from ..schemas import WorkflowCreate, WorkflowUpdate, WorkflowOut router = APIRouter(prefix="/workflows", tags=["Workflows"]) -@router.get("", response_model=List[WorkflowOut]) +@router.get("") def list_workflows( page: int = 1, limit: int = 50, @@ -62,8 +61,12 @@ def update_workflow(id: str, data: WorkflowUpdate, db: Session = Depends(get_db) raise HTTPException(status_code=404, detail="Workflow not found") update_data = data.model_dump(exclude_unset=True) + field_map = { + "nodeCount": "node_count", + "globalPrompt": "global_prompt", + } for field, value in update_data.items(): - setattr(workflow, field, value) + setattr(workflow, field_map.get(field, field), value) workflow.updated_at = datetime.utcnow().isoformat() db.commit() diff --git a/web/README.md b/web/README.md index e900716..30b2f88 100644 --- a/web/README.md +++ b/web/README.md @@ -16,6 +16,6 @@ View your app in AI Studio: https://ai.studio/apps/drive/1Cg9WH_2bOQEHVVj-lSN5l2 1. Install dependencies: `npm install` 2. Set the `GEMINI_API_KEY` in [.env.local](.env.local) to your Gemini API key -3. Optional: set `VITE_API_BASE_URL` (for backend API, default `http://localhost:8000/api`) +3. Optional: set `VITE_API_BASE_URL` (for backend API, default `http://127.0.0.1:8100/api`) 4. Run the app: `npm run dev` diff --git a/web/services/apiClient.ts b/web/services/apiClient.ts index 3008828..d8c5232 100644 --- a/web/services/apiClient.ts +++ b/web/services/apiClient.ts @@ -1,4 +1,4 @@ -const DEFAULT_API_BASE_URL = 'http://localhost:8000/api'; +const DEFAULT_API_BASE_URL = 'http://127.0.0.1:8100/api'; const trimTrailingSlash = (value: string): string => value.replace(/\/+$/, ''); diff --git a/web/services/backendApi.ts b/web/services/backendApi.ts index 86f9e8d..6faf468 100644 --- a/web/services/backendApi.ts +++ b/web/services/backendApi.ts @@ -173,13 +173,15 @@ export const deleteAssistant = async (id: string): Promise => { }; export const fetchVoices = async (): Promise => { - const response = await apiRequest('/voices'); - return response.map((item) => mapVoice(item)); + const response = await apiRequest<{ list?: AnyRecord[] } | AnyRecord[]>('/voices'); + const list = Array.isArray(response) ? response : (response.list || []); + return list.map((item) => mapVoice(item)); }; export const fetchWorkflows = async (): Promise => { - const response = await apiRequest('/workflows'); - return response.map((item) => mapWorkflow(item)); + const response = await apiRequest<{ list?: AnyRecord[] } | AnyRecord[]>('/workflows'); + const list = Array.isArray(response) ? response : (response.list || []); + return list.map((item) => mapWorkflow(item)); }; export const fetchWorkflowById = async (id: string): Promise => { @@ -238,12 +240,12 @@ export const deleteKnowledgeBase = async (kbId: string): Promise => { }; export const uploadKnowledgeDocument = async (kbId: string, file: File): Promise => { - const params = new URLSearchParams({ + const payload = { name: file.name, size: `${(file.size / 1024).toFixed(1)} KB`, - file_type: file.type || 'txt', - }); - await apiRequest(`/knowledge/bases/${kbId}/documents?${params.toString()}`, { method: 'POST' }); + fileType: file.type || 'txt', + }; + await apiRequest(`/knowledge/bases/${kbId}/documents`, { method: 'POST', body: payload }); }; export const deleteKnowledgeDocument = async (kbId: string, docId: string): Promise => {