Compare commits

..

1 Commits

Author SHA1 Message Date
hetao 1c9fdfef6b fix: fix the bug introduced by coordinator messages update 2025-07-18 21:36:07 +08:00
7 changed files with 393 additions and 28465 deletions
-6
View File
@@ -12,12 +12,6 @@ AGENT_RECURSION_LIMIT=30
# Example: ALLOWED_ORIGINS=http://localhost:3000,http://example.com
ALLOWED_ORIGINS=http://localhost:3000
# Enable or disable MCP server configuration, the default is false.
# Please enable this feature before securing your front-end and back-end in a managed environment.
# Otherwise, you system could be compromised.
ENABLE_MCP_SERVER_CONFIGURATION=false
# Search Engine, Supported values: tavily (recommended), duckduckgo, brave_search, arxiv
SEARCH_API=tavily
TAVILY_API_KEY=tvly-xxx
+1 -10
View File
@@ -1,13 +1,4 @@
# MCP IntegrationsBeta
Now This feature is diabled by default. You can enable it by setting the environment ENABLE_MCP_SERVER_CONFIGURATION to be true
> [!WARNING]
> Please enable this feature before securing your frond-end and back-end in a managed environment.
> Otherwise, you system could be compromised.
This feature is diabled by default. You can enable it by setting the environment ENABLE_MCP_SERVER_CONFIGURATION
Please enable this feature before securing your frond-end and back-end in an internal environment.q
# MCP Integrations
## Example of MCP Server Configuration
+3 -4
View File
@@ -307,7 +307,6 @@ async def _execute_agent_step(
) -> Command[Literal["research_team"]]:
"""Helper function to execute a step using the specified agent."""
current_plan = state.get("current_plan")
plan_title = current_plan.title
observations = state.get("observations", [])
# Find the first unexecuted step
@@ -329,16 +328,16 @@ async def _execute_agent_step(
# Format completed steps information
completed_steps_info = ""
if completed_steps:
completed_steps_info = "# Completed Research Steps\n\n"
completed_steps_info = "# Existing Research Findings\n\n"
for i, step in enumerate(completed_steps):
completed_steps_info += f"## Completed Step {i + 1}: {step.title}\n\n"
completed_steps_info += f"## Existing Finding {i + 1}: {step.title}\n\n"
completed_steps_info += f"<finding>\n{step.execution_res}\n</finding>\n\n"
# Prepare the input for the agent with completed steps info
agent_input = {
"messages": [
HumanMessage(
content=f"# Research Topic\n\n{plan_title}\n\n{completed_steps_info}# Current Step\n\n## Title\n\n{current_step.title}\n\n## Description\n\n{current_step.description}\n\n## Locale\n\n{state.get('locale', 'en-US')}"
content=f"{completed_steps_info}# Current Task\n\n## Title\n\n{current_step.title}\n\n## Description\n\n{current_step.description}\n\n## Locale\n\n{state.get('locale', 'en-US')}"
)
]
}
+3 -30
View File
@@ -58,14 +58,12 @@ app = FastAPI(
allowed_origins_str = os.getenv("ALLOWED_ORIGINS", "http://localhost:3000")
allowed_origins = [origin.strip() for origin in allowed_origins_str.split(",")]
logger.info(f"Allowed origins: {allowed_origins}")
app.add_middleware(
CORSMiddleware,
allow_origins=allowed_origins, # Restrict to specific origins
allow_credentials=True,
allow_methods=["GET", "POST", "OPTIONS"], # Use the configured list of methods
allow_headers=["*"], # Now allow all headers, but can be restricted further
allow_methods=["GET", "POST"], # Be specific about allowed methods
allow_headers=["Content-Type", "Authorization", "X-Requested-With"], # Be specific
)
graph = build_graph_with_memory()
@@ -73,20 +71,6 @@ graph = build_graph_with_memory()
@app.post("/api/chat/stream")
async def chat_stream(request: ChatRequest):
# Check if MCP server configuration is enabled
mcp_enabled = os.getenv("ENABLE_MCP_SERVER_CONFIGURATION", "false").lower() in [
"true",
"1",
"yes",
]
# Validate MCP settings if provided
if request.mcp_settings and not mcp_enabled:
raise HTTPException(
status_code=403,
detail="MCP server configuration is disabled. Set ENABLE_MCP_SERVER_CONFIGURATION=true to enable MCP features.",
)
thread_id = request.thread_id
if thread_id == "__default__":
thread_id = str(uuid4())
@@ -100,7 +84,7 @@ async def chat_stream(request: ChatRequest):
request.max_search_results,
request.auto_accepted_plan,
request.interrupt_feedback,
request.mcp_settings if mcp_enabled else {},
request.mcp_settings,
request.enable_background_investigation,
request.report_style,
request.enable_deep_thinking,
@@ -379,17 +363,6 @@ async def enhance_prompt(request: EnhancePromptRequest):
@app.post("/api/mcp/server/metadata", response_model=MCPServerMetadataResponse)
async def mcp_server_metadata(request: MCPServerMetadataRequest):
"""Get information about an MCP server."""
# Check if MCP server configuration is enabled
if os.getenv("ENABLE_MCP_SERVER_CONFIGURATION", "false").lower() not in [
"true",
"1",
"yes",
]:
raise HTTPException(
status_code=403,
detail="MCP server configuration is disabled. Set ENABLE_MCP_SERVER_CONFIGURATION=true to enable MCP features.",
)
try:
# Set default timeout with a longer value for this endpoint
timeout = 300 # Default to 300 seconds for this endpoint
-119
View File
@@ -260,10 +260,6 @@ class TestEnhancePromptEndpoint:
class TestMCPEndpoint:
@patch("src.server.app.load_mcp_tools")
@patch.dict(
os.environ,
{"ENABLE_MCP_SERVER_CONFIGURATION": "true"},
)
def test_mcp_server_metadata_success(self, mock_load_tools, client):
mock_load_tools.return_value = [
{"name": "test_tool", "description": "Test tool"}
@@ -285,10 +281,6 @@ class TestMCPEndpoint:
assert len(response_data["tools"]) == 1
@patch("src.server.app.load_mcp_tools")
@patch.dict(
os.environ,
{"ENABLE_MCP_SERVER_CONFIGURATION": "true"},
)
def test_mcp_server_metadata_with_custom_timeout(self, mock_load_tools, client):
mock_load_tools.return_value = []
@@ -304,10 +296,6 @@ class TestMCPEndpoint:
mock_load_tools.assert_called_once()
@patch("src.server.app.load_mcp_tools")
@patch.dict(
os.environ,
{"ENABLE_MCP_SERVER_CONFIGURATION": "true"},
)
def test_mcp_server_metadata_with_exception(self, mock_load_tools, client):
mock_load_tools.side_effect = HTTPException(
status_code=400, detail="MCP Server Error"
@@ -325,30 +313,6 @@ class TestMCPEndpoint:
assert response.status_code == 500
assert response.json()["detail"] == "Internal Server Error"
@patch("src.server.app.load_mcp_tools")
@patch.dict(
os.environ,
{"ENABLE_MCP_SERVER_CONFIGURATION": ""},
)
def test_mcp_server_metadata_without_enable_configuration(
self, mock_load_tools, client
):
request_data = {
"transport": "stdio",
"command": "test_command",
"args": ["arg1", "arg2"],
"env": {"ENV_VAR": "value"},
}
response = client.post("/api/mcp/server/metadata", json=request_data)
assert response.status_code == 403
assert (
response.json()["detail"]
== "MCP server configuration is disabled. Set ENABLE_MCP_SERVER_CONFIGURATION=true to enable MCP features."
)
class TestRAGEndpoints:
@patch("src.server.app.SELECTED_RAG_PROVIDER", "test_provider")
@@ -413,89 +377,6 @@ class TestChatStreamEndpoint:
assert response.status_code == 200
assert response.headers["content-type"] == "text/event-stream; charset=utf-8"
@patch("src.server.app.graph")
def test_chat_stream_with_mcp_settings(self, mock_graph, client):
# Mock the async stream
async def mock_astream(*args, **kwargs):
yield ("agent1", "step1", {"test": "data"})
mock_graph.astream = mock_astream
request_data = {
"thread_id": "__default__",
"messages": [{"role": "user", "content": "Hello"}],
"resources": [],
"max_plan_iterations": 3,
"max_step_num": 10,
"max_search_results": 5,
"auto_accepted_plan": True,
"interrupt_feedback": "",
"mcp_settings": {
"servers": {
"mcp-github-trending": {
"transport": "stdio",
"command": "uvx",
"args": ["mcp-github-trending"],
"env": {"MCP_SERVER_ID": "mcp-github-trending"},
"enabled_tools": ["get_github_trending_repositories"],
"add_to_agents": ["researcher"],
}
}
},
"enable_background_investigation": False,
"report_style": "academic",
}
response = client.post("/api/chat/stream", json=request_data)
assert response.status_code == 403
assert (
response.json()["detail"]
== "MCP server configuration is disabled. Set ENABLE_MCP_SERVER_CONFIGURATION=true to enable MCP features."
)
@patch("src.server.app.graph")
@patch.dict(
os.environ,
{"ENABLE_MCP_SERVER_CONFIGURATION": "true"},
)
def test_chat_stream_with_mcp_settings_enabled(self, mock_graph, client):
# Mock the async stream
async def mock_astream(*args, **kwargs):
yield ("agent1", "step1", {"test": "data"})
mock_graph.astream = mock_astream
request_data = {
"thread_id": "__default__",
"messages": [{"role": "user", "content": "Hello"}],
"resources": [],
"max_plan_iterations": 3,
"max_step_num": 10,
"max_search_results": 5,
"auto_accepted_plan": True,
"interrupt_feedback": "",
"mcp_settings": {
"servers": {
"mcp-github-trending": {
"transport": "stdio",
"command": "uvx",
"args": ["mcp-github-trending"],
"env": {"MCP_SERVER_ID": "mcp-github-trending"},
"enabled_tools": ["get_github_trending_repositories"],
"add_to_agents": ["researcher"],
}
}
},
"enable_background_investigation": False,
"report_style": "academic",
}
response = client.post("/api/chat/stream", json=request_data)
assert response.status_code == 200
assert response.headers["content-type"] == "text/event-stream; charset=utf-8"
class TestAstreamWorkflowGenerator:
@pytest.mark.asyncio
File diff suppressed because one or more lines are too long
+1 -2
View File
@@ -1,6 +1,5 @@
import { useMemo } from "react";
import { useStore, useToolCalls } from "~/core/store";
import { parseJSON } from "~/core/utils/json";
import { Tooltip } from "./tooltip";
import { WarningFilled } from "@ant-design/icons";
import { useTranslations } from "next-intl";
@@ -24,7 +23,7 @@ export const Link = ({
(toolCalls || []).forEach((call) => {
if (call && call.name === "web_search" && call.result) {
try {
const result = parseJSON(call.result, []) as Array<{ url: string }>;
const result = JSON.parse(call.result) as Array<{ url: string }>;
if (Array.isArray(result)) {
result.forEach((r) => {
if (r && typeof r.url === 'string') {