Aari 5ffc2d3e27
feat(mcp): complete durable task notifications and chat UI (#4833)
* feat(mcp): add reliable task notifications and cancellation

* feat(mcp): add background task chat UI

* fix(mcp): hide and sanitize task notification prompts

* fix(mcp): sanitize projected task names

* fix(mcp): harden task notifications and details

* fix(mcp): harden task lifecycle recovery

* fix(mcp): gate task UI and isolate cancellations

* test: scope plain-text response locator

* fix(mcp): align task notification boundaries

* fix(mcp): bound task delivery retries

* fix background task notification races
2026-08-22 16:53:32 +08:00

63 lines
2.3 KiB
Python

"""Read-only feature-flag endpoint for the frontend bootstrap.
Reports which optional features are exposed over HTTP so the frontend can gate
UI and avoid firing requests that the backend would reject. Config-only flags
read through ``get_config`` so edits to ``config.yaml`` take effect on the next
request, while startup-scoped capabilities report the runtime that actually
started.
"""
from fastapi import APIRouter, Depends, Request
from pydantic import BaseModel, Field
from app.gateway.browser_capability import browser_capability
from app.gateway.deps import get_config
from deerflow.config.app_config import AppConfig
router = APIRouter(prefix="/api", tags=["features"])
class AgentsApiFeature(BaseModel):
"""Availability of the custom-agent management API."""
enabled: bool = Field(..., description="Whether the agents_api routes are exposed over HTTP")
class BrowserControlFeature(BaseModel):
"""Availability of live agentic browser control."""
enabled: bool = Field(..., description="Whether the live browser routes and UI are available")
class McpTasksFeature(BaseModel):
"""Availability of the durable MCP task runtime."""
enabled: bool = Field(..., description="Whether durable MCP task APIs and UI are available")
class FeaturesResponse(BaseModel):
"""Frontend-facing feature availability flags."""
agents_api: AgentsApiFeature
browser_control: BrowserControlFeature
mcp_tasks: McpTasksFeature
@router.get(
"/features",
response_model=FeaturesResponse,
summary="List Feature Flags",
description="Report which optional features are available, so the frontend can gate UI before issuing requests.",
)
async def list_features(request: Request, config: AppConfig = Depends(get_config)) -> FeaturesResponse:
"""Return availability of optional frontend features."""
browser = browser_capability(config)
return FeaturesResponse(
agents_api=AgentsApiFeature(enabled=config.agents_api.enabled),
browser_control=BrowserControlFeature(enabled=browser.available),
# MCP task bindings and the submitter are startup-scoped. Report the
# capability that actually started rather than a hot-reloaded config
# value that would require a Gateway restart to take effect.
mcp_tasks=McpTasksFeature(enabled=bool(getattr(request.app.state, "mcp_tasks_available", False))),
)