diff --git a/packages/dbgpt-serve/src/dbgpt_serve/connector/api/endpoints.py b/packages/dbgpt-serve/src/dbgpt_serve/connector/api/endpoints.py index e7f888736..e46d72bd6 100644 --- a/packages/dbgpt-serve/src/dbgpt_serve/connector/api/endpoints.py +++ b/packages/dbgpt-serve/src/dbgpt_serve/connector/api/endpoints.py @@ -132,6 +132,42 @@ async def list_connectors( return Result.failed(msg=str(e)) +class ConfirmRequest(BaseModel): + confirm_id: str + approved: bool + + +# IMPORTANT: keep these fixed-path routes BEFORE any "/{connector_id}" routes, +# otherwise FastAPI matches /{connector_id} first and treats "pending-confirms" / +# "confirm" as a connector_id value. +@router.get("/pending-confirms") +async def list_pending_confirms() -> List[dict]: + from dbgpt.agent.resource.connector.confirmation import _PENDING_CONFIRMATIONS + + return list(_PENDING_CONFIRMATIONS.values()) + + +@router.post("/confirm") +async def confirm_action(request: ConfirmRequest) -> Dict[str, str]: + from dbgpt.agent.resource.connector.manager import ConnectorManager as _CM + + if global_system_app is None: + raise HTTPException(status_code=503, detail="SystemApp not initialised") + cm = global_system_app.get_component( + "connector_manager", _CM, default_component=None + ) + if cm is None: + raise HTTPException(status_code=503, detail="ConnectorManager not available") + registry = cm.get_confirmation_registry() + resolved = registry.resolve(request.confirm_id, request.approved) + if not resolved: + raise HTTPException(status_code=404, detail="confirm_id not found or expired") + from dbgpt.agent.resource.connector.confirmation import _PENDING_CONFIRMATIONS + + _PENDING_CONFIRMATIONS.pop(request.confirm_id, None) + return {"status": "ok"} + + @router.get("/{connector_id}", response_model=Result[ConnectorResponse]) async def get_connector( connector_id: str, @@ -195,39 +231,6 @@ def init_endpoints(system_app: SystemApp, config: ServeConfig) -> None: global_system_app = system_app -class ConfirmRequest(BaseModel): - confirm_id: str - approved: bool - - -@router.get("/pending-confirms") -async def list_pending_confirms() -> List[dict]: - from dbgpt.agent.resource.connector.confirmation import _PENDING_CONFIRMATIONS - - return list(_PENDING_CONFIRMATIONS.values()) - - -@router.post("/confirm") -async def confirm_action(request: ConfirmRequest) -> Dict[str, str]: - from dbgpt.agent.resource.connector.manager import ConnectorManager as _CM - - if global_system_app is None: - raise HTTPException(status_code=503, detail="SystemApp not initialised") - cm = global_system_app.get_component( - "connector_manager", _CM, default_component=None - ) - if cm is None: - raise HTTPException(status_code=503, detail="ConnectorManager not available") - registry = cm.get_confirmation_registry() - resolved = registry.resolve(request.confirm_id, request.approved) - if not resolved: - raise HTTPException(status_code=404, detail="confirm_id not found or expired") - from dbgpt.agent.resource.connector.confirmation import _PENDING_CONFIRMATIONS - - _PENDING_CONFIRMATIONS.pop(request.confirm_id, None) - return {"status": "ok"} - - def _get_task_service(): from ..service.scheduled_task_service import ScheduledTaskService diff --git a/web/hooks/use-connector-api.ts b/web/hooks/use-connector-api.ts index 95bd8e704..1ec7fb1b4 100644 --- a/web/hooks/use-connector-api.ts +++ b/web/hooks/use-connector-api.ts @@ -3,6 +3,9 @@ import { ConnectorCatalogEntry, ConnectorInstance, CreateConnectorRequest } from import { useCallback, useEffect, useState } from 'react'; const API_BASE = '/api/v2/serve/connectors'; +// FastAPI registers GET / and POST / under api_prefix, so list/create require +// a trailing slash. Single-resource routes (`/{id}`, `/{id}/test`, etc.) do not. +const API_BASE_LIST = `${API_BASE}/`; // Backend ConnectorResponse uses `connector_id`; frontend code uses `id`. // Normalize at the boundary so the rest of the app can stay on `id`. @@ -43,7 +46,7 @@ export function useConnectors() { useEffect(() => { setLoading(true); axios - .get(API_BASE) + .get(API_BASE_LIST) .then(res => { const raw = unwrap(res) ?? []; setConnectors(raw.map(normalizeConnector)); @@ -65,7 +68,7 @@ export function useCreateConnector() { const create = useCallback(async (data: CreateConnectorRequest): Promise => { setLoading(true); try { - const res = await axios.post(API_BASE, data); + const res = await axios.post(API_BASE_LIST, data); return normalizeConnector(unwrap(res)); } catch (err) { console.error('Failed to create connector:', err);