mirror of
https://github.com/bytedance/deer-flow.git
synced 2026-09-20 03:26:18 +00:00
* feat(knowledge): integrate RAGFlow retrieval and management * test(knowledge): cover merged listing tool * feat(knowledge): add per-message retrieval scope * chore(docs): remove unrelated document * docs(knowledge): add interaction screenshots * feat(knowledge): simplify scope selector trigger * docs(knowledge): refresh selector screenshot * feat(knowledge): defer standalone management * docs(knowledge): show chat-only scope UI * fix(knowledge): honor scope on clarification replies * fix(knowledge): harden scoped replay validation * docs(knowledge): clarify replay scope precedence * fix(knowledge): keep provider settings on tools * fix(config): preserve tools-only knowledge settings * fix(knowledge): submit custom assistant identity * refactor(knowledge): trim PR scope changes * fix(knowledge): sanitize document scope display * feat(knowledge): enable scope selection in main chat * fix(knowledge): emphasize active scope icon without button frame * fix(knowledge): close context scrubbing and refresh e2e checks * fix(knowledge): preserve idempotent canonical retries * fix(knowledge): accept promptless conversation runs * style(knowledge): format backend regression tests * chore(knowledge): trim PR scope and fix frontend format * fix(knowledge): remove shared-scope notice * fix(knowledge): remove scope persistence notice * docs(knowledge): include main chat in catalog scope * fix(knowledge): preserve scope recovery and upgrades * fix(config): preserve LightRAG knowledge upgrades --------- Co-authored-by: foreleven <for-eleven@hotmail.com>
124 lines
5.5 KiB
Python
124 lines
5.5 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.conversation_access import conversation_references_enabled
|
|
from app.gateway.deps import get_config
|
|
from app.gateway.knowledge_scope_admission import RAGFLOW_KNOWLEDGE_SEARCH_PROVIDER
|
|
from app.gateway.run_models import MAX_CONVERSATION_REFERENCES
|
|
from deerflow.config.app_config import AppConfig
|
|
from deerflow.subagents.capacity import configured_subagent_max_running
|
|
|
|
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 SubagentBatchesFeature(BaseModel):
|
|
"""Persistence, worker, and process capacity for native-subagent batches."""
|
|
|
|
enabled: bool = Field(..., description="Compatibility alias for worker_running")
|
|
repository_available: bool = Field(..., description="Whether durable batch history APIs are available")
|
|
worker_running: bool = Field(..., description="Whether this Gateway process is executing durable batch work")
|
|
max_running: int = Field(..., description="Native subagent execution slots in this Gateway process")
|
|
|
|
|
|
class ConversationReferencesFeature(BaseModel):
|
|
"""Availability of explicit conversation references on run requests."""
|
|
|
|
enabled: bool = Field(..., description="Whether the opt-in read_conversation tool is configured, so run requests may carry conversation_references")
|
|
max_references: int = Field(..., description="Maximum conversation references accepted on one run request")
|
|
|
|
|
|
class KnowledgeBaseFeature(BaseModel):
|
|
"""Availability of RAGFlow retrieval scope selection in chat."""
|
|
|
|
scope_selection_enabled: bool = Field(
|
|
...,
|
|
description="Whether chat may select a per-message RAGFlow retrieval scope",
|
|
)
|
|
|
|
|
|
class FeaturesResponse(BaseModel):
|
|
"""Frontend-facing feature availability flags."""
|
|
|
|
agents_api: AgentsApiFeature
|
|
browser_control: BrowserControlFeature
|
|
mcp_tasks: McpTasksFeature
|
|
subagent_batches: SubagentBatchesFeature
|
|
conversation_references: ConversationReferencesFeature
|
|
knowledge_base: KnowledgeBaseFeature
|
|
|
|
|
|
@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)
|
|
subagent_batch_worker_running = bool(getattr(request.app.state, "subagent_batches_available", False))
|
|
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))),
|
|
subagent_batches=SubagentBatchesFeature(
|
|
# Keep the historical `enabled` field as a compatibility alias
|
|
# while exposing read persistence independently from execution.
|
|
# A stopped/disabled worker must not hide durable history/export.
|
|
enabled=subagent_batch_worker_running,
|
|
repository_available=getattr(request.app.state, "subagent_batch_repo", None) is not None,
|
|
worker_running=subagent_batch_worker_running,
|
|
max_running=configured_subagent_max_running(),
|
|
),
|
|
# Same predicate as run admission (``prepare_conversation_reader``), read
|
|
# through ``get_config`` so enabling the tool in config.yaml shows up
|
|
# without a restart. A UI with no entry point still needs no change here.
|
|
conversation_references=ConversationReferencesFeature(
|
|
enabled=conversation_references_enabled(config),
|
|
max_references=MAX_CONVERSATION_REFERENCES,
|
|
),
|
|
knowledge_base=KnowledgeBaseFeature(
|
|
scope_selection_enabled=_knowledge_scope_selection_enabled(config),
|
|
),
|
|
)
|
|
|
|
|
|
def _knowledge_scope_selection_enabled(config: AppConfig) -> bool:
|
|
"""Fail closed unless the effective knowledge_search entry is RAGFlow."""
|
|
settings = config.knowledge_base
|
|
if not settings.enabled or not settings.scope_selection_enabled:
|
|
return False
|
|
tool = config.get_tool_config("knowledge_search")
|
|
return tool is not None and tool.use == RAGFLOW_KNOWLEDGE_SEARCH_PROVIDER
|