diff --git a/.understand-anything/knowledge-graph.json b/.understand-anything/knowledge-graph.json index 564cd74..b06890d 100644 --- a/.understand-anything/knowledge-graph.json +++ b/.understand-anything/knowledge-graph.json @@ -13,7 +13,7 @@ "Redis" ], "description": "AI驱动的Agent框架,支持ReAct引擎、多LLM网关、Pipeline编排、自适应反思和消息总线", - "analyzedAt": "2026-06-14T08:41:38.874016+00:00", + "analyzedAt": "2026-06-15T06:01:34.043135+00:00", "gitCommitHash": "d9d1b16e5911ad958cd8ae38958058bea13f3fcc" }, "nodes": [ @@ -181,18 +181,6 @@ ], "complexity": "moderate" }, - { - "id": "file:src/agentkit/chat/skill_routing.py", - "type": "file", - "name": "skill_routing.py", - "filePath": "src/agentkit/chat/skill_routing.py", - "layer": "unknown", - "summary": "Shared skill routing logic for GUI and CLI chat.", - "tags": [ - "chat" - ], - "complexity": "moderate" - }, { "id": "file:src/agentkit/cli/__init__.py", "type": "file", @@ -397,18 +385,6 @@ ], "complexity": "moderate" }, - { - "id": "file:src/agentkit/core/goal_planner.py", - "type": "file", - "name": "goal_planner.py", - "filePath": "src/agentkit/core/goal_planner.py", - "layer": "service", - "summary": "GoalPlanner — 目标分析与计划生成", - "tags": [ - "core" - ], - "complexity": "moderate" - }, { "id": "file:src/agentkit/core/headroom_compressor.py", "type": "file", @@ -457,18 +433,6 @@ ], "complexity": "moderate" }, - { - "id": "file:src/agentkit/core/plan_exec_engine.py", - "type": "file", - "name": "plan_exec_engine.py", - "filePath": "src/agentkit/core/plan_exec_engine.py", - "layer": "service", - "summary": "Plan-and-Execute 执行引擎适配器", - "tags": [ - "core" - ], - "complexity": "moderate" - }, { "id": "file:src/agentkit/core/plan_executor.py", "type": "file", @@ -1719,18 +1683,6 @@ ], "complexity": "simple" }, - { - "id": "file:src/agentkit/server/app.py", - "type": "file", - "name": "app.py", - "filePath": "src/agentkit/server/app.py", - "layer": "api", - "summary": "FastAPI Application Factory", - "tags": [ - "server" - ], - "complexity": "moderate" - }, { "id": "file:src/agentkit/server/client.py", "type": "file", @@ -1755,30 +1707,6 @@ ], "complexity": "moderate" }, - { - "id": "file:src/agentkit/server/config.py", - "type": "file", - "name": "config.py", - "filePath": "src/agentkit/server/config.py", - "layer": "api", - "summary": "Server configuration loader - loads agentkit.yaml and .env", - "tags": [ - "server" - ], - "complexity": "moderate" - }, - { - "id": "file:src/agentkit/server/middleware.py", - "type": "file", - "name": "middleware.py", - "filePath": "src/agentkit/server/middleware.py", - "layer": "api", - "summary": "Server middleware - Authentication and Rate Limiting", - "tags": [ - "server" - ], - "complexity": "moderate" - }, { "id": "file:src/agentkit/server/routes/__init__.py", "type": "file", @@ -1805,19 +1733,6 @@ ], "complexity": "moderate" }, - { - "id": "file:src/agentkit/server/routes/chat.py", - "type": "file", - "name": "chat.py", - "filePath": "src/agentkit/server/routes/chat.py", - "layer": "api", - "summary": "Chat API routes — multi-turn conversation with Agent via REST and WebSocket.", - "tags": [ - "server", - "routes" - ], - "complexity": "moderate" - }, { "id": "file:src/agentkit/server/routes/evolution.py", "type": "file", @@ -3274,145 +3189,6 @@ ], "complexity": "simple" }, - { - "id": "class:ExecutionMode", - "type": "class", - "name": "ExecutionMode", - "filePath": "src/agentkit/chat/skill_routing.py", - "layer": "unknown", - "summary": "How the downstream should execute this routing result.", - "tags": [ - "ExecutionMode" - ], - "complexity": "simple" - }, - { - "id": "class:SkillRoutingResult", - "type": "class", - "name": "SkillRoutingResult", - "filePath": "src/agentkit/chat/skill_routing.py", - "layer": "unknown", - "summary": "Result of skill routing for a user message.", - "tags": [ - "SkillRoutingResult" - ], - "complexity": "simple" - }, - { - "id": "class:HeuristicClassifier", - "type": "class", - "name": "HeuristicClassifier", - "filePath": "src/agentkit/chat/skill_routing.py", - "layer": "unknown", - "summary": "零成本本地启发式分类器,替代 LLM quick_classify。", - "tags": [ - "HeuristicClassifier" - ], - "complexity": "simple" - }, - { - "id": "func:HeuristicClassifier.classify", - "type": "function", - "name": "classify", - "filePath": "src/agentkit/chat/skill_routing.py", - "layer": "unknown", - "summary": "HeuristicClassifier.classify(content) 方法", - "tags": [ - "HeuristicClassifier", - "classify" - ], - "complexity": "simple" - }, - { - "id": "class:CostAwareRouter", - "type": "class", - "name": "CostAwareRouter", - "filePath": "src/agentkit/chat/skill_routing.py", - "layer": "unknown", - "summary": "三层成本感知路由器。", - "tags": [ - "CostAwareRouter" - ], - "complexity": "moderate" - }, - { - "id": "func:CostAwareRouter.__init__", - "type": "function", - "name": "__init__", - "filePath": "src/agentkit/chat/skill_routing.py", - "layer": "unknown", - "summary": "CostAwareRouter.__init__(llm_gateway, model, org_context, auction_enabled, classifier, merged_llm_classify, semantic_router) 方法", - "tags": [ - "CostAwareRouter", - "__init__" - ], - "complexity": "simple" - }, - { - "id": "func:CostAwareRouter._match_layer0", - "type": "function", - "name": "_match_layer0", - "filePath": "src/agentkit/chat/skill_routing.py", - "layer": "unknown", - "summary": "CostAwareRouter._match_layer0(content) 方法", - "tags": [ - "CostAwareRouter", - "_match_layer0" - ], - "complexity": "simple" - }, - { - "id": "func:CostAwareRouter.quick_classify", - "type": "function", - "name": "quick_classify", - "filePath": "src/agentkit/chat/skill_routing.py", - "layer": "unknown", - "summary": "CostAwareRouter.quick_classify(content) 异步方法", - "tags": [ - "CostAwareRouter", - "quick_classify" - ], - "complexity": "simple" - }, - { - "id": "func:CostAwareRouter._classify_merged", - "type": "function", - "name": "_classify_merged", - "filePath": "src/agentkit/chat/skill_routing.py", - "layer": "unknown", - "summary": "CostAwareRouter._classify_merged(content, skill_registry, intent_router, default_tools, default_system_prompt, default_model, default_agent_name, agent_tool_registry, session_id, complexity) 异步方法", - "tags": [ - "CostAwareRouter", - "_classify_merged" - ], - "complexity": "simple" - }, - { - "id": "func:CostAwareRouter._route_layer2", - "type": "function", - "name": "_route_layer2", - "filePath": "src/agentkit/chat/skill_routing.py", - "layer": "unknown", - "summary": "CostAwareRouter._route_layer2(content, skill_registry, intent_router, default_tools, default_system_prompt, default_model, default_agent_name, agent_tool_registry, session_id, complexity, trace) 异步方法", - "tags": [ - "CostAwareRouter", - "_route_layer2" - ], - "complexity": "simple" - }, - { - "id": "func:CostAwareRouter.route", - "type": "function", - "name": "route", - "filePath": "src/agentkit/chat/skill_routing.py", - "layer": "unknown", - "summary": "CostAwareRouter.route(content, skill_registry, intent_router, default_tools, default_system_prompt, default_model, default_agent_name, agent_tool_registry, session_id, transparency) 异步方法", - "tags": [ - "CostAwareRouter", - "route" - ], - "complexity": "simple" - }, { "id": "class:AgentPool", "type": "class", @@ -5322,213 +5098,6 @@ ], "complexity": "simple" }, - { - "id": "class:GoalPlanner", - "type": "class", - "name": "GoalPlanner", - "filePath": "src/agentkit/core/goal_planner.py", - "layer": "service", - "summary": "目标分析与计划生成器", - "tags": [ - "GoalPlanner" - ], - "complexity": "complex" - }, - { - "id": "func:GoalPlanner.__init__", - "type": "function", - "name": "__init__", - "filePath": "src/agentkit/core/goal_planner.py", - "layer": "service", - "summary": "GoalPlanner.__init__(llm_gateway, max_parallel) 方法", - "tags": [ - "GoalPlanner", - "__init__" - ], - "complexity": "simple" - }, - { - "id": "func:GoalPlanner.generate_plan", - "type": "function", - "name": "generate_plan", - "filePath": "src/agentkit/core/goal_planner.py", - "layer": "service", - "summary": "GoalPlanner.generate_plan(goal, context, available_skills) 异步方法", - "tags": [ - "GoalPlanner", - "generate_plan" - ], - "complexity": "simple" - }, - { - "id": "func:GoalPlanner._rule_based_decompose", - "type": "function", - "name": "_rule_based_decompose", - "filePath": "src/agentkit/core/goal_planner.py", - "layer": "service", - "summary": "GoalPlanner._rule_based_decompose(goal, context, available_skills) 方法", - "tags": [ - "GoalPlanner", - "_rule_based_decompose" - ], - "complexity": "simple" - }, - { - "id": "func:GoalPlanner._extract_parallel_items", - "type": "function", - "name": "_extract_parallel_items", - "filePath": "src/agentkit/core/goal_planner.py", - "layer": "service", - "summary": "GoalPlanner._extract_parallel_items(goal) 方法", - "tags": [ - "GoalPlanner", - "_extract_parallel_items" - ], - "complexity": "simple" - }, - { - "id": "func:GoalPlanner._extract_sequential_parts", - "type": "function", - "name": "_extract_sequential_parts", - "filePath": "src/agentkit/core/goal_planner.py", - "layer": "service", - "summary": "GoalPlanner._extract_sequential_parts(goal) 方法", - "tags": [ - "GoalPlanner", - "_extract_sequential_parts" - ], - "complexity": "simple" - }, - { - "id": "func:GoalPlanner._decompose_parallel_goal", - "type": "function", - "name": "_decompose_parallel_goal", - "filePath": "src/agentkit/core/goal_planner.py", - "layer": "service", - "summary": "GoalPlanner._decompose_parallel_goal(goal, parallel_items, available_skills) 方法", - "tags": [ - "GoalPlanner", - "_decompose_parallel_goal" - ], - "complexity": "simple" - }, - { - "id": "func:GoalPlanner._decompose_sequential_goal", - "type": "function", - "name": "_decompose_sequential_goal", - "filePath": "src/agentkit/core/goal_planner.py", - "layer": "service", - "summary": "GoalPlanner._decompose_sequential_goal(goal, sequential_parts, available_skills) 方法", - "tags": [ - "GoalPlanner", - "_decompose_sequential_goal" - ], - "complexity": "simple" - }, - { - "id": "func:GoalPlanner._decompose_simple_goal", - "type": "function", - "name": "_decompose_simple_goal", - "filePath": "src/agentkit/core/goal_planner.py", - "layer": "service", - "summary": "GoalPlanner._decompose_simple_goal(goal, available_skills) 方法", - "tags": [ - "GoalPlanner", - "_decompose_simple_goal" - ], - "complexity": "simple" - }, - { - "id": "func:GoalPlanner._infer_required_skills", - "type": "function", - "name": "_infer_required_skills", - "filePath": "src/agentkit/core/goal_planner.py", - "layer": "service", - "summary": "GoalPlanner._infer_required_skills(text, available_skills) 方法", - "tags": [ - "GoalPlanner", - "_infer_required_skills" - ], - "complexity": "simple" - }, - { - "id": "func:GoalPlanner._identify_skill_gaps", - "type": "function", - "name": "_identify_skill_gaps", - "filePath": "src/agentkit/core/goal_planner.py", - "layer": "service", - "summary": "GoalPlanner._identify_skill_gaps(plan, available_skills) 方法", - "tags": [ - "GoalPlanner", - "_identify_skill_gaps" - ], - "complexity": "simple" - }, - { - "id": "func:GoalPlanner._should_refine_with_llm", - "type": "function", - "name": "_should_refine_with_llm", - "filePath": "src/agentkit/core/goal_planner.py", - "layer": "service", - "summary": "GoalPlanner._should_refine_with_llm(plan) 方法", - "tags": [ - "GoalPlanner", - "_should_refine_with_llm" - ], - "complexity": "simple" - }, - { - "id": "func:GoalPlanner._llm_refine_plan", - "type": "function", - "name": "_llm_refine_plan", - "filePath": "src/agentkit/core/goal_planner.py", - "layer": "service", - "summary": "GoalPlanner._llm_refine_plan(goal, initial_plan, context, available_skills) 异步方法", - "tags": [ - "GoalPlanner", - "_llm_refine_plan" - ], - "complexity": "simple" - }, - { - "id": "func:GoalPlanner._build_parallel_groups", - "type": "function", - "name": "_build_parallel_groups", - "filePath": "src/agentkit/core/goal_planner.py", - "layer": "service", - "summary": "GoalPlanner._build_parallel_groups(steps) 方法", - "tags": [ - "GoalPlanner", - "_build_parallel_groups" - ], - "complexity": "simple" - }, - { - "id": "func:GoalPlanner.update_plan_from_feedback", - "type": "function", - "name": "update_plan_from_feedback", - "filePath": "src/agentkit/core/goal_planner.py", - "layer": "service", - "summary": "GoalPlanner.update_plan_from_feedback(plan, modifications) 方法", - "tags": [ - "GoalPlanner", - "update_plan_from_feedback" - ], - "complexity": "simple" - }, - { - "id": "func:GoalPlanner.validate_plan", - "type": "function", - "name": "validate_plan", - "filePath": "src/agentkit/core/goal_planner.py", - "layer": "service", - "summary": "GoalPlanner.validate_plan(plan) 方法", - "tags": [ - "GoalPlanner", - "validate_plan" - ], - "complexity": "simple" - }, { "id": "class:HeadroomCompressor", "type": "class", @@ -6307,301 +5876,6 @@ ], "complexity": "simple" }, - { - "id": "class:_StreamState", - "type": "class", - "name": "_StreamState", - "filePath": "src/agentkit/core/plan_exec_engine.py", - "layer": "service", - "summary": "流式执行内部状态,用于在 execute_stream 中跨 yield 传递", - "tags": [ - "_StreamState" - ], - "complexity": "simple" - }, - { - "id": "class:PlanExecEngine", - "type": "class", - "name": "PlanExecEngine", - "filePath": "src/agentkit/core/plan_exec_engine.py", - "layer": "service", - "summary": "Plan-and-Execute 执行引擎适配器", - "tags": [ - "PlanExecEngine" - ], - "complexity": "complex" - }, - { - "id": "func:PlanExecEngine.__init__", - "type": "function", - "name": "__init__", - "filePath": "src/agentkit/core/plan_exec_engine.py", - "layer": "service", - "summary": "PlanExecEngine.__init__(llm_gateway, max_replans, default_timeout) 方法", - "tags": [ - "PlanExecEngine", - "__init__" - ], - "complexity": "simple" - }, - { - "id": "func:PlanExecEngine.execute", - "type": "function", - "name": "execute", - "filePath": "src/agentkit/core/plan_exec_engine.py", - "layer": "service", - "summary": "PlanExecEngine.execute(messages, tools, model, agent_name, task_type, system_prompt, trace_recorder, memory_retriever, task_id, compressor, retrieval_config, cancellation_token, timeout_seconds) 异步方法", - "tags": [ - "PlanExecEngine", - "execute" - ], - "complexity": "simple" - }, - { - "id": "func:PlanExecEngine.execute_stream", - "type": "function", - "name": "execute_stream", - "filePath": "src/agentkit/core/plan_exec_engine.py", - "layer": "service", - "summary": "PlanExecEngine.execute_stream(messages, tools, model, agent_name, task_type, system_prompt, trace_recorder, memory_retriever, task_id, compressor, retrieval_config, cancellation_token, timeout_seconds) 异步方法", - "tags": [ - "PlanExecEngine", - "execute_stream" - ], - "complexity": "simple" - }, - { - "id": "func:PlanExecEngine._execute_loop", - "type": "function", - "name": "_execute_loop", - "filePath": "src/agentkit/core/plan_exec_engine.py", - "layer": "service", - "summary": "PlanExecEngine._execute_loop(messages, tools, model, agent_name, task_type, system_prompt, trace_recorder, memory_retriever, task_id, compressor, retrieval_config, cancellation_token) 异步方法", - "tags": [ - "PlanExecEngine", - "_execute_loop" - ], - "complexity": "simple" - }, - { - "id": "func:PlanExecEngine._execute_with_replanning", - "type": "function", - "name": "_execute_with_replanning", - "filePath": "src/agentkit/core/plan_exec_engine.py", - "layer": "service", - "summary": "PlanExecEngine._execute_with_replanning(plan, messages, tools, model, agent_name, task_type, system_prompt, trace_recorder, task_id, cancellation_token, trajectory, total_tokens) 异步方法", - "tags": [ - "PlanExecEngine", - "_execute_with_replanning" - ], - "complexity": "simple" - }, - { - "id": "func:PlanExecEngine._extract_goal", - "type": "function", - "name": "_extract_goal", - "filePath": "src/agentkit/core/plan_exec_engine.py", - "layer": "service", - "summary": "PlanExecEngine._extract_goal(messages) 方法", - "tags": [ - "PlanExecEngine", - "_extract_goal" - ], - "complexity": "simple" - }, - { - "id": "func:PlanExecEngine._extract_skill_names", - "type": "function", - "name": "_extract_skill_names", - "filePath": "src/agentkit/core/plan_exec_engine.py", - "layer": "service", - "summary": "PlanExecEngine._extract_skill_names(tools) 方法", - "tags": [ - "PlanExecEngine", - "_extract_skill_names" - ], - "complexity": "simple" - }, - { - "id": "func:PlanExecEngine._build_task_message", - "type": "function", - "name": "_build_task_message", - "filePath": "src/agentkit/core/plan_exec_engine.py", - "layer": "service", - "summary": "PlanExecEngine._build_task_message(messages, agent_name, task_type, task_id) 方法", - "tags": [ - "PlanExecEngine", - "_build_task_message" - ], - "complexity": "simple" - }, - { - "id": "func:PlanExecEngine._create_executor", - "type": "function", - "name": "_create_executor", - "filePath": "src/agentkit/core/plan_exec_engine.py", - "layer": "service", - "summary": "PlanExecEngine._create_executor(messages, model, system_prompt, tools) 方法", - "tags": [ - "PlanExecEngine", - "_create_executor" - ], - "complexity": "simple" - }, - { - "id": "func:PlanExecEngine._plan_to_pipeline", - "type": "function", - "name": "_plan_to_pipeline", - "filePath": "src/agentkit/core/plan_exec_engine.py", - "layer": "service", - "summary": "PlanExecEngine._plan_to_pipeline(plan, agent_name) 方法", - "tags": [ - "PlanExecEngine", - "_plan_to_pipeline" - ], - "complexity": "simple" - }, - { - "id": "func:PlanExecEngine._plan_result_to_pipeline_result", - "type": "function", - "name": "_plan_result_to_pipeline_result", - "filePath": "src/agentkit/core/plan_exec_engine.py", - "layer": "service", - "summary": "PlanExecEngine._plan_result_to_pipeline_result(plan, plan_result) 方法", - "tags": [ - "PlanExecEngine", - "_plan_result_to_pipeline_result" - ], - "complexity": "simple" - }, - { - "id": "func:PlanExecEngine._pipeline_to_plan", - "type": "function", - "name": "_pipeline_to_plan", - "filePath": "src/agentkit/core/plan_exec_engine.py", - "layer": "service", - "summary": "PlanExecEngine._pipeline_to_plan(pipeline, goal) 方法", - "tags": [ - "PlanExecEngine", - "_pipeline_to_plan" - ], - "complexity": "simple" - }, - { - "id": "func:PlanExecEngine._merge_completed_results", - "type": "function", - "name": "_merge_completed_results", - "filePath": "src/agentkit/core/plan_exec_engine.py", - "layer": "service", - "summary": "PlanExecEngine._merge_completed_results(plan, plan_result) 方法", - "tags": [ - "PlanExecEngine", - "_merge_completed_results" - ], - "complexity": "simple" - }, - { - "id": "func:PlanExecEngine._aggregate_output", - "type": "function", - "name": "_aggregate_output", - "filePath": "src/agentkit/core/plan_exec_engine.py", - "layer": "service", - "summary": "PlanExecEngine._aggregate_output(plan, plan_result) 方法", - "tags": [ - "PlanExecEngine", - "_aggregate_output" - ], - "complexity": "simple" - }, - { - "id": "class:_LLMStepExecutor", - "type": "class", - "name": "_LLMStepExecutor", - "filePath": "src/agentkit/core/plan_exec_engine.py", - "layer": "service", - "summary": "LLM 直接调用步骤执行器", - "tags": [ - "_LLMStepExecutor" - ], - "complexity": "simple" - }, - { - "id": "func:_LLMStepExecutor.__init__", - "type": "function", - "name": "__init__", - "filePath": "src/agentkit/core/plan_exec_engine.py", - "layer": "service", - "summary": "_LLMStepExecutor.__init__(llm_gateway, messages, model, system_prompt, tools) 方法", - "tags": [ - "_LLMStepExecutor", - "__init__" - ], - "complexity": "simple" - }, - { - "id": "func:_LLMStepExecutor.create_agent_from_skill", - "type": "function", - "name": "create_agent_from_skill", - "filePath": "src/agentkit/core/plan_exec_engine.py", - "layer": "service", - "summary": "_LLMStepExecutor.create_agent_from_skill(skill_name) 异步方法", - "tags": [ - "_LLMStepExecutor", - "create_agent_from_skill" - ], - "complexity": "simple" - }, - { - "id": "func:_LLMStepExecutor.get_agent", - "type": "function", - "name": "get_agent", - "filePath": "src/agentkit/core/plan_exec_engine.py", - "layer": "service", - "summary": "_LLMStepExecutor.get_agent(key) 方法", - "tags": [ - "_LLMStepExecutor", - "get_agent" - ], - "complexity": "simple" - }, - { - "id": "class:_LLMStepAgent", - "type": "class", - "name": "_LLMStepAgent", - "filePath": "src/agentkit/core/plan_exec_engine.py", - "layer": "service", - "summary": "LLM 直接调用步骤 Agent", - "tags": [ - "_LLMStepAgent" - ], - "complexity": "simple" - }, - { - "id": "func:_LLMStepAgent.__init__", - "type": "function", - "name": "__init__", - "filePath": "src/agentkit/core/plan_exec_engine.py", - "layer": "service", - "summary": "_LLMStepAgent.__init__(name, llm_gateway, messages, model, system_prompt, tools) 方法", - "tags": [ - "_LLMStepAgent", - "__init__" - ], - "complexity": "simple" - }, - { - "id": "func:_LLMStepAgent.execute", - "type": "function", - "name": "execute", - "filePath": "src/agentkit/core/plan_exec_engine.py", - "layer": "service", - "summary": "_LLMStepAgent.execute(task_msg) 异步方法", - "tags": [ - "_LLMStepAgent", - "execute" - ], - "complexity": "simple" - }, { "id": "class:FailureAction", "type": "class", @@ -20775,352 +20049,6 @@ ], "complexity": "simple" }, - { - "id": "class:MCPServerConfig", - "type": "class", - "name": "MCPServerConfig", - "filePath": "src/agentkit/server/config.py", - "layer": "api", - "summary": "Configuration for a single MCP Server connection", - "tags": [ - "MCPServerConfig" - ], - "complexity": "simple" - }, - { - "id": "func:MCPServerConfig.validate", - "type": "function", - "name": "validate", - "filePath": "src/agentkit/server/config.py", - "layer": "api", - "summary": "MCPServerConfig.validate() 方法", - "tags": [ - "MCPServerConfig", - "validate" - ], - "complexity": "simple" - }, - { - "id": "func:MCPServerConfig.from_dict", - "type": "function", - "name": "from_dict", - "filePath": "src/agentkit/server/config.py", - "layer": "api", - "summary": "MCPServerConfig.from_dict(cls, data) 方法", - "tags": [ - "MCPServerConfig", - "from_dict" - ], - "complexity": "simple" - }, - { - "id": "class:ServerConfig", - "type": "class", - "name": "ServerConfig", - "filePath": "src/agentkit/server/config.py", - "layer": "api", - "summary": "Server configuration loaded from agentkit.yaml", - "tags": [ - "ServerConfig" - ], - "complexity": "complex" - }, - { - "id": "func:ServerConfig.__init__", - "type": "function", - "name": "__init__", - "filePath": "src/agentkit/server/config.py", - "layer": "api", - "summary": "ServerConfig.__init__(host, port, workers, api_key, rate_limit, llm_config, skill_paths, auto_discover_skills, log_level, log_format, task_store, cors_origins, memory, mcp_servers, telemetry, compression, session, bus, marketplace, alignment, router, usage_store, cascade_store, evolution, on_change) 方法", - "tags": [ - "ServerConfig", - "__init__" - ], - "complexity": "simple" - }, - { - "id": "func:ServerConfig.has_llm_provider", - "type": "function", - "name": "has_llm_provider", - "filePath": "src/agentkit/server/config.py", - "layer": "api", - "summary": "ServerConfig.has_llm_provider() 方法", - "tags": [ - "ServerConfig", - "has_llm_provider" - ], - "complexity": "simple" - }, - { - "id": "func:ServerConfig.from_yaml", - "type": "function", - "name": "from_yaml", - "filePath": "src/agentkit/server/config.py", - "layer": "api", - "summary": "ServerConfig.from_yaml(cls, path) 方法", - "tags": [ - "ServerConfig", - "from_yaml" - ], - "complexity": "simple" - }, - { - "id": "func:ServerConfig.from_dict", - "type": "function", - "name": "from_dict", - "filePath": "src/agentkit/server/config.py", - "layer": "api", - "summary": "ServerConfig.from_dict(cls, data) 方法", - "tags": [ - "ServerConfig", - "from_dict" - ], - "complexity": "simple" - }, - { - "id": "func:ServerConfig._build_llm_config", - "type": "function", - "name": "_build_llm_config", - "filePath": "src/agentkit/server/config.py", - "layer": "api", - "summary": "ServerConfig._build_llm_config(data) 方法", - "tags": [ - "ServerConfig", - "_build_llm_config" - ], - "complexity": "simple" - }, - { - "id": "func:ServerConfig._build_mcp_configs", - "type": "function", - "name": "_build_mcp_configs", - "filePath": "src/agentkit/server/config.py", - "layer": "api", - "summary": "ServerConfig._build_mcp_configs(data) 方法", - "tags": [ - "ServerConfig", - "_build_mcp_configs" - ], - "complexity": "simple" - }, - { - "id": "func:ServerConfig.load_skill_configs", - "type": "function", - "name": "load_skill_configs", - "filePath": "src/agentkit/server/config.py", - "layer": "api", - "summary": "ServerConfig.load_skill_configs() 方法", - "tags": [ - "ServerConfig", - "load_skill_configs" - ], - "complexity": "simple" - }, - { - "id": "func:ServerConfig.load_dotenv", - "type": "function", - "name": "load_dotenv", - "filePath": "src/agentkit/server/config.py", - "layer": "api", - "summary": "ServerConfig.load_dotenv(dotenv_path) 方法", - "tags": [ - "ServerConfig", - "load_dotenv" - ], - "complexity": "simple" - }, - { - "id": "func:ServerConfig.watch_config", - "type": "function", - "name": "watch_config", - "filePath": "src/agentkit/server/config.py", - "layer": "api", - "summary": "ServerConfig.watch_config(config_path) 方法", - "tags": [ - "ServerConfig", - "watch_config" - ], - "complexity": "simple" - }, - { - "id": "func:ServerConfig.stop_watching", - "type": "function", - "name": "stop_watching", - "filePath": "src/agentkit/server/config.py", - "layer": "api", - "summary": "ServerConfig.stop_watching() 方法", - "tags": [ - "ServerConfig", - "stop_watching" - ], - "complexity": "simple" - }, - { - "id": "func:ServerConfig._watch_with_watchfiles", - "type": "function", - "name": "_watch_with_watchfiles", - "filePath": "src/agentkit/server/config.py", - "layer": "api", - "summary": "ServerConfig._watch_with_watchfiles(path) 异步方法", - "tags": [ - "ServerConfig", - "_watch_with_watchfiles" - ], - "complexity": "simple" - }, - { - "id": "func:ServerConfig._poll_config_loop", - "type": "function", - "name": "_poll_config_loop", - "filePath": "src/agentkit/server/config.py", - "layer": "api", - "summary": "ServerConfig._poll_config_loop(path) 异步方法", - "tags": [ - "ServerConfig", - "_poll_config_loop" - ], - "complexity": "simple" - }, - { - "id": "func:ServerConfig._try_reload_config", - "type": "function", - "name": "_try_reload_config", - "filePath": "src/agentkit/server/config.py", - "layer": "api", - "summary": "ServerConfig._try_reload_config(path) 方法", - "tags": [ - "ServerConfig", - "_try_reload_config" - ], - "complexity": "simple" - }, - { - "id": "class:APIKeyAuthMiddleware", - "type": "class", - "name": "APIKeyAuthMiddleware", - "filePath": "src/agentkit/server/middleware.py", - "layer": "api", - "summary": "API Key authentication middleware.", - "tags": [ - "APIKeyAuthMiddleware" - ], - "complexity": "simple" - }, - { - "id": "func:APIKeyAuthMiddleware.__init__", - "type": "function", - "name": "__init__", - "filePath": "src/agentkit/server/middleware.py", - "layer": "api", - "summary": "APIKeyAuthMiddleware.__init__(app, api_key) 方法", - "tags": [ - "APIKeyAuthMiddleware", - "__init__" - ], - "complexity": "simple" - }, - { - "id": "func:APIKeyAuthMiddleware.dispatch", - "type": "function", - "name": "dispatch", - "filePath": "src/agentkit/server/middleware.py", - "layer": "api", - "summary": "APIKeyAuthMiddleware.dispatch(request, call_next) 异步方法", - "tags": [ - "APIKeyAuthMiddleware", - "dispatch" - ], - "complexity": "simple" - }, - { - "id": "class:RateLimiter", - "type": "class", - "name": "RateLimiter", - "filePath": "src/agentkit/server/middleware.py", - "layer": "api", - "summary": "Fixed-window rate limiter.", - "tags": [ - "RateLimiter" - ], - "complexity": "simple" - }, - { - "id": "func:RateLimiter.__init__", - "type": "function", - "name": "__init__", - "filePath": "src/agentkit/server/middleware.py", - "layer": "api", - "summary": "RateLimiter.__init__(max_requests, window_seconds) 方法", - "tags": [ - "RateLimiter", - "__init__" - ], - "complexity": "simple" - }, - { - "id": "func:RateLimiter.is_allowed", - "type": "function", - "name": "is_allowed", - "filePath": "src/agentkit/server/middleware.py", - "layer": "api", - "summary": "RateLimiter.is_allowed(key) 方法", - "tags": [ - "RateLimiter", - "is_allowed" - ], - "complexity": "simple" - }, - { - "id": "func:RateLimiter.max_requests", - "type": "function", - "name": "max_requests", - "filePath": "src/agentkit/server/middleware.py", - "layer": "api", - "summary": "RateLimiter.max_requests() 方法", - "tags": [ - "RateLimiter", - "max_requests" - ], - "complexity": "simple" - }, - { - "id": "class:RateLimitMiddleware", - "type": "class", - "name": "RateLimitMiddleware", - "filePath": "src/agentkit/server/middleware.py", - "layer": "api", - "summary": "Rate limiting middleware.", - "tags": [ - "RateLimitMiddleware" - ], - "complexity": "simple" - }, - { - "id": "func:RateLimitMiddleware.__init__", - "type": "function", - "name": "__init__", - "filePath": "src/agentkit/server/middleware.py", - "layer": "api", - "summary": "RateLimitMiddleware.__init__(app, max_requests, window_seconds) 方法", - "tags": [ - "RateLimitMiddleware", - "__init__" - ], - "complexity": "simple" - }, - { - "id": "func:RateLimitMiddleware.dispatch", - "type": "function", - "name": "dispatch", - "filePath": "src/agentkit/server/middleware.py", - "layer": "api", - "summary": "RateLimitMiddleware.dispatch(request, call_next) 异步方法", - "tags": [ - "RateLimitMiddleware", - "dispatch" - ], - "complexity": "simple" - }, { "id": "class:CreateAgentRequest", "type": "class", @@ -21133,131 +20061,6 @@ ], "complexity": "simple" }, - { - "id": "class:CreateSessionRequest", - "type": "class", - "name": "CreateSessionRequest", - "filePath": "src/agentkit/server/routes/chat.py", - "layer": "api", - "summary": "CreateSessionRequest类,继承自BaseModel", - "tags": [ - "CreateSessionRequest" - ], - "complexity": "simple" - }, - { - "id": "class:SendMessageRequest", - "type": "class", - "name": "SendMessageRequest", - "filePath": "src/agentkit/server/routes/chat.py", - "layer": "api", - "summary": "SendMessageRequest类,继承自BaseModel", - "tags": [ - "SendMessageRequest" - ], - "complexity": "simple" - }, - { - "id": "class:SessionResponse", - "type": "class", - "name": "SessionResponse", - "filePath": "src/agentkit/server/routes/chat.py", - "layer": "api", - "summary": "SessionResponse类,继承自BaseModel", - "tags": [ - "SessionResponse" - ], - "complexity": "simple" - }, - { - "id": "class:MessageResponse", - "type": "class", - "name": "MessageResponse", - "filePath": "src/agentkit/server/routes/chat.py", - "layer": "api", - "summary": "MessageResponse类,继承自BaseModel", - "tags": [ - "MessageResponse" - ], - "complexity": "simple" - }, - { - "id": "class:ChatConnectionManager", - "type": "class", - "name": "ChatConnectionManager", - "filePath": "src/agentkit/server/routes/chat.py", - "layer": "api", - "summary": "Track active WebSocket connections per session_id.", - "tags": [ - "ChatConnectionManager" - ], - "complexity": "moderate" - }, - { - "id": "func:ChatConnectionManager.__init__", - "type": "function", - "name": "__init__", - "filePath": "src/agentkit/server/routes/chat.py", - "layer": "api", - "summary": "ChatConnectionManager.__init__() 方法", - "tags": [ - "ChatConnectionManager", - "__init__" - ], - "complexity": "simple" - }, - { - "id": "func:ChatConnectionManager.add", - "type": "function", - "name": "add", - "filePath": "src/agentkit/server/routes/chat.py", - "layer": "api", - "summary": "ChatConnectionManager.add(session_id, ws, pending) 方法", - "tags": [ - "ChatConnectionManager", - "add" - ], - "complexity": "simple" - }, - { - "id": "func:ChatConnectionManager.remove", - "type": "function", - "name": "remove", - "filePath": "src/agentkit/server/routes/chat.py", - "layer": "api", - "summary": "ChatConnectionManager.remove(session_id, ws) 方法", - "tags": [ - "ChatConnectionManager", - "remove" - ], - "complexity": "simple" - }, - { - "id": "func:ChatConnectionManager.get_connections", - "type": "function", - "name": "get_connections", - "filePath": "src/agentkit/server/routes/chat.py", - "layer": "api", - "summary": "ChatConnectionManager.get_connections(session_id) 方法", - "tags": [ - "ChatConnectionManager", - "get_connections" - ], - "complexity": "simple" - }, - { - "id": "func:ChatConnectionManager.send_json", - "type": "function", - "name": "send_json", - "filePath": "src/agentkit/server/routes/chat.py", - "layer": "api", - "summary": "ChatConnectionManager.send_json(session_id, message) 异步方法", - "tags": [ - "ChatConnectionManager", - "send_json" - ], - "complexity": "simple" - }, { "id": "class:TriggerEvolutionRequest", "type": "class", @@ -28649,78 +27452,6 @@ ], "complexity": "simple" }, - { - "id": "func:validate_skill_name", - "type": "function", - "name": "validate_skill_name", - "filePath": "src/agentkit/chat/skill_routing.py", - "layer": "unknown", - "summary": "validate_skill_name(name) 函数 → str", - "tags": [ - "validate_skill_name" - ], - "complexity": "simple" - }, - { - "id": "func:parse_skill_prefix", - "type": "function", - "name": "parse_skill_prefix", - "filePath": "src/agentkit/chat/skill_routing.py", - "layer": "unknown", - "summary": "parse_skill_prefix(content) 函数 → Subscript(value=Name(id='tuple', ctx=Load()), slice=Tuple(elts=[BinOp(left=Name(id='str', ctx=Load()), op=BitOr(), right=Constant(value=None)), Name(id='str', ctx=Load())], ctx=Load()), ctx=Load())", - "tags": [ - "parse_skill_prefix" - ], - "complexity": "simple" - }, - { - "id": "func:build_skill_system_prompt", - "type": "function", - "name": "build_skill_system_prompt", - "filePath": "src/agentkit/chat/skill_routing.py", - "layer": "unknown", - "summary": "build_skill_system_prompt(skill_config) 函数 → BinOp(left=Name(id='str', ctx=Load()), op=BitOr(), right=Constant(value=None))", - "tags": [ - "build_skill_system_prompt" - ], - "complexity": "moderate" - }, - { - "id": "func:resolve_skill_routing", - "type": "function", - "name": "resolve_skill_routing", - "filePath": "src/agentkit/chat/skill_routing.py", - "layer": "unknown", - "summary": "resolve_skill_routing(content, skill_registry, intent_router, default_tools, default_system_prompt, default_model, default_agent_name, agent_tool_registry, session_id, force_skill) 异步函数 → SkillRoutingResult", - "tags": [ - "resolve_skill_routing" - ], - "complexity": "complex" - }, - { - "id": "func:_build_tools_description", - "type": "function", - "name": "_build_tools_description", - "filePath": "src/agentkit/chat/skill_routing.py", - "layer": "unknown", - "summary": "_build_tools_description(tools) 函数 → str", - "tags": [ - "_build_tools_description" - ], - "complexity": "moderate" - }, - { - "id": "func:_tokenize_content", - "type": "function", - "name": "_tokenize_content", - "filePath": "src/agentkit/chat/skill_routing.py", - "layer": "unknown", - "summary": "_tokenize_content(content) 函数 → Subscript(value=Name(id='list', ctx=Load()), slice=Name(id='str', ctx=Load()), ctx=Load())", - "tags": [ - "_tokenize_content" - ], - "complexity": "moderate" - }, { "id": "func:chat", "type": "function", @@ -29549,114 +28280,6 @@ ], "complexity": "simple" }, - { - "id": "func:_build_llm_gateway", - "type": "function", - "name": "_build_llm_gateway", - "filePath": "src/agentkit/server/app.py", - "layer": "api", - "summary": "_build_llm_gateway(config) 函数 → LLMGateway", - "tags": [ - "_build_llm_gateway" - ], - "complexity": "complex" - }, - { - "id": "func:_build_skill_registry", - "type": "function", - "name": "_build_skill_registry", - "filePath": "src/agentkit/server/app.py", - "layer": "api", - "summary": "_build_skill_registry(config) 函数 → SkillRegistry", - "tags": [ - "_build_skill_registry" - ], - "complexity": "simple" - }, - { - "id": "func:lifespan", - "type": "function", - "name": "lifespan", - "filePath": "src/agentkit/server/app.py", - "layer": "api", - "summary": "lifespan(app) 异步函数", - "tags": [ - "lifespan" - ], - "complexity": "complex" - }, - { - "id": "func:_on_config_change", - "type": "function", - "name": "_on_config_change", - "filePath": "src/agentkit/server/app.py", - "layer": "api", - "summary": "_on_config_change(app, config) 函数 → None", - "tags": [ - "_on_config_change" - ], - "complexity": "complex" - }, - { - "id": "func:create_app", - "type": "function", - "name": "create_app", - "filePath": "src/agentkit/server/app.py", - "layer": "api", - "summary": "create_app(llm_gateway, skill_registry, tool_registry, api_key, rate_limit, server_config) 函数 → FastAPI", - "tags": [ - "create_app" - ], - "complexity": "complex" - }, - { - "id": "func:_resolve_env_vars", - "type": "function", - "name": "_resolve_env_vars", - "filePath": "src/agentkit/server/config.py", - "layer": "api", - "summary": "_resolve_env_vars(value) 函数 → Any", - "tags": [ - "_resolve_env_vars" - ], - "complexity": "simple" - }, - { - "id": "func:_deep_resolve", - "type": "function", - "name": "_deep_resolve", - "filePath": "src/agentkit/server/config.py", - "layer": "api", - "summary": "_deep_resolve(data) 函数 → Any", - "tags": [ - "_deep_resolve" - ], - "complexity": "moderate" - }, - { - "id": "func:find_config_path", - "type": "function", - "name": "find_config_path", - "filePath": "src/agentkit/server/config.py", - "layer": "api", - "summary": "find_config_path(config_arg) 函数 → BinOp(left=Name(id='str', ctx=Load()), op=BitOr(), right=Constant(value=None))", - "tags": [ - "find_config_path" - ], - "complexity": "moderate" - }, - { - "id": "func:_load_client_keys", - "type": "function", - "name": "_load_client_keys", - "filePath": "src/agentkit/server/middleware.py", - "layer": "api", - "summary": "_load_client_keys(config_dir) 函数 → Subscript(value=Name(id='dict', ctx=Load()), slice=Tuple(elts=[Name(id='str', ctx=Load()), Name(id='str', ctx=Load())], ctx=Load()), ctx=Load())", - "tags": [ - "_load_client_keys" - ], - "complexity": "moderate" - }, { "id": "func:_get_pool", "type": "function", @@ -29729,138 +28352,6 @@ ], "complexity": "simple" }, - { - "id": "func:_get_session_manager", - "type": "function", - "name": "_get_session_manager", - "filePath": "src/agentkit/server/routes/chat.py", - "layer": "api", - "summary": "_get_session_manager(request) 函数 → SessionManager", - "tags": [ - "_get_session_manager" - ], - "complexity": "simple" - }, - { - "id": "func:_session_to_response", - "type": "function", - "name": "_session_to_response", - "filePath": "src/agentkit/server/routes/chat.py", - "layer": "api", - "summary": "_session_to_response(session) 函数 → SessionResponse", - "tags": [ - "_session_to_response" - ], - "complexity": "simple" - }, - { - "id": "func:_message_to_response", - "type": "function", - "name": "_message_to_response", - "filePath": "src/agentkit/server/routes/chat.py", - "layer": "api", - "summary": "_message_to_response(msg) 函数 → MessageResponse", - "tags": [ - "_message_to_response" - ], - "complexity": "simple" - }, - { - "id": "func:list_sessions", - "type": "function", - "name": "list_sessions", - "filePath": "src/agentkit/server/routes/chat.py", - "layer": "api", - "summary": "list_sessions(req) 异步函数", - "tags": [ - "list_sessions" - ], - "complexity": "simple" - }, - { - "id": "func:create_session", - "type": "function", - "name": "create_session", - "filePath": "src/agentkit/server/routes/chat.py", - "layer": "api", - "summary": "create_session(request, req) 异步函数", - "tags": [ - "create_session" - ], - "complexity": "simple" - }, - { - "id": "func:get_session", - "type": "function", - "name": "get_session", - "filePath": "src/agentkit/server/routes/chat.py", - "layer": "api", - "summary": "get_session(session_id, req) 异步函数", - "tags": [ - "get_session" - ], - "complexity": "simple" - }, - { - "id": "func:get_messages", - "type": "function", - "name": "get_messages", - "filePath": "src/agentkit/server/routes/chat.py", - "layer": "api", - "summary": "get_messages(session_id, req, limit, offset) 异步函数", - "tags": [ - "get_messages" - ], - "complexity": "simple" - }, - { - "id": "func:send_message", - "type": "function", - "name": "send_message", - "filePath": "src/agentkit/server/routes/chat.py", - "layer": "api", - "summary": "send_message(session_id, request, req) 异步函数", - "tags": [ - "send_message" - ], - "complexity": "moderate" - }, - { - "id": "func:close_session", - "type": "function", - "name": "close_session", - "filePath": "src/agentkit/server/routes/chat.py", - "layer": "api", - "summary": "close_session(session_id, req) 异步函数", - "tags": [ - "close_session" - ], - "complexity": "simple" - }, - { - "id": "func:chat_websocket", - "type": "function", - "name": "chat_websocket", - "filePath": "src/agentkit/server/routes/chat.py", - "layer": "api", - "summary": "chat_websocket(websocket, session_id) 异步函数 → None", - "tags": [ - "chat_websocket" - ], - "complexity": "complex" - }, - { - "id": "func:_handle_chat_message", - "type": "function", - "name": "_handle_chat_message", - "filePath": "src/agentkit/server/routes/chat.py", - "layer": "api", - "summary": "_handle_chat_message(websocket, session_id, content, sm, cancellation_token, pending_replies, pending_confirmations) 异步函数 → None", - "tags": [ - "_handle_chat_message" - ], - "complexity": "complex" - }, { "id": "func:_get_evolution_store", "type": "function", @@ -31576,6 +30067,479 @@ "compute_cosine_similarity" ], "complexity": "moderate" + }, + { + "id": "file:src/agentkit/core/plan_exec_engine.py", + "type": "file", + "name": "plan_exec_engine.py", + "summary": "Plan-and-Execute 执行引擎适配器,组合 GoalPlanner + PlanExecutor + PipelineReplanner,兼容 ReActEngine 接口,支持三阶段流程(规划→执行→重规划)", + "tags": [ + "core", + "engine", + "plan-exec", + "autonomous" + ], + "filePath": "src/agentkit/core/plan_exec_engine.py" + }, + { + "id": "class:src/agentkit/core/plan_exec_engine.py:PlanExecEngine", + "type": "class", + "name": "PlanExecEngine", + "summary": "Plan-and-Execute 执行引擎主类,支持 SharedWorkspace 状态传递和 step_event_callback 进度推送", + "tags": [ + "core", + "engine", + "plan-exec" + ], + "filePath": "src/agentkit/core/plan_exec_engine.py" + }, + { + "id": "class:src/agentkit/core/plan_exec_engine.py:ReActStepExecutor", + "type": "class", + "name": "ReActStepExecutor", + "summary": "ReAct 循环步骤执行器,使用 ReActEngine 执行每个 PlanStep,支持工具调用和 confirmation_handler", + "tags": [ + "core", + "executor", + "react" + ], + "filePath": "src/agentkit/core/plan_exec_engine.py" + }, + { + "id": "class:src/agentkit/core/plan_exec_engine.py:_ReActStepAgent", + "type": "class", + "name": "_ReActStepAgent", + "summary": "ReAct 循环步骤 Agent,将 PlanStep 描述交给 ReActEngine 执行", + "tags": [ + "core", + "agent", + "react" + ], + "filePath": "src/agentkit/core/plan_exec_engine.py" + }, + { + "id": "file:src/agentkit/core/goal_planner.py", + "type": "file", + "name": "goal_planner.py", + "summary": "目标分析与计划生成器,将自然语言目标分解为结构化 ExecutionPlan,支持规则分解、动词模式匹配、LLM 细化和能力缺口识别", + "tags": [ + "core", + "planner", + "decomposition" + ], + "filePath": "src/agentkit/core/goal_planner.py" + }, + { + "id": "class:src/agentkit/core/goal_planner.py:GoalPlanner", + "type": "class", + "name": "GoalPlanner", + "summary": "目标分析与计划生成器主类,支持规则分解(并列/顺序/动词模式)、LLM 细化、能力缺口识别", + "tags": [ + "core", + "planner" + ], + "filePath": "src/agentkit/core/goal_planner.py" + }, + { + "id": "file:src/agentkit/experts/orchestrator.py", + "type": "file", + "name": "orchestrator.py", + "summary": "专家团队协作计划执行引擎,支持串行/子任务并行/竞争并行、LLM 合并策略(BEST/VOTE/FUSION)、里程碑检查、重试+重规划+回退", + "tags": [ + "experts", + "orchestrator", + "team" + ], + "filePath": "src/agentkit/experts/orchestrator.py" + }, + { + "id": "class:src/agentkit/experts/orchestrator.py:TeamOrchestrator", + "type": "class", + "name": "TeamOrchestrator", + "summary": "团队编排引擎,执行 CollaborationPlan,支持串行/并行/竞争阶段、LLM 合并策略、重试→重规划→回退", + "tags": [ + "experts", + "orchestrator" + ], + "filePath": "src/agentkit/experts/orchestrator.py" + }, + { + "id": "file:src/agentkit/experts/team.py", + "type": "file", + "name": "team.py", + "summary": "专家团队容器,管理 Expert 生命周期、共享上下文、协作计划和团队状态,暴露 workspace/handoff_transport/get_expert/set_status 公共 API", + "tags": [ + "experts", + "team", + "container" + ], + "filePath": "src/agentkit/experts/team.py" + }, + { + "id": "class:src/agentkit/experts/team.py:ExpertTeam", + "type": "class", + "name": "ExpertTeam", + "summary": "专家团队容器主类,暴露 workspace/handoff_transport/team_channel/get_expert/set_status 公共 API", + "tags": [ + "experts", + "team" + ], + "filePath": "src/agentkit/experts/team.py" + }, + { + "id": "class:src/agentkit/experts/team.py:TeamStatus", + "type": "class", + "name": "TeamStatus", + "summary": "专家团队生命周期状态枚举:FORMING→PLANNING→EXECUTING→SYNTHESIZING→COMPLETED→DISSOLVED", + "tags": [ + "experts", + "enum" + ], + "filePath": "src/agentkit/experts/team.py" + }, + { + "id": "file:src/agentkit/experts/router.py", + "type": "file", + "name": "router.py", + "summary": "专家团队路由器,解析 @team 前缀和复杂度阈值,将用户输入路由到 ExpertTeam 模式", + "tags": [ + "experts", + "router" + ], + "filePath": "src/agentkit/experts/router.py" + }, + { + "id": "class:src/agentkit/experts/router.py:ExpertTeamRouter", + "type": "class", + "name": "ExpertTeamRouter", + "summary": "专家团队路由器,支持 @team 前缀触发、指定成员、高复杂度自动建议团队模式", + "tags": [ + "experts", + "router" + ], + "filePath": "src/agentkit/experts/router.py" + }, + { + "id": "file:src/agentkit/experts/config.py", + "type": "file", + "name": "config.py", + "summary": "Expert 配置与模板定义,ExpertConfig 扩展 AgentConfig 新增 persona/thinking_style/bound_skills 等角色属性", + "tags": [ + "experts", + "config" + ], + "filePath": "src/agentkit/experts/config.py" + }, + { + "id": "class:src/agentkit/experts/config.py:ExpertConfig", + "type": "class", + "name": "ExpertConfig", + "summary": "专家配置类,扩展 AgentConfig 新增 persona/thinking_style/collaboration_strategy/bound_skills/avatar/color/is_lead", + "tags": [ + "experts", + "config" + ], + "filePath": "src/agentkit/experts/config.py" + }, + { + "id": "class:src/agentkit/experts/config.py:ExpertTemplate", + "type": "class", + "name": "ExpertTemplate", + "summary": "专家模板,可复用的 Expert 配置模板", + "tags": [ + "experts", + "template" + ], + "filePath": "src/agentkit/experts/config.py" + }, + { + "id": "file:src/agentkit/experts/expert.py", + "type": "file", + "name": "expert.py", + "summary": "专家运行时包装器,持有 ExpertConfig 和 ConfigDrivenAgent,添加团队感知行为", + "tags": [ + "experts", + "expert", + "runtime" + ], + "filePath": "src/agentkit/experts/expert.py" + }, + { + "id": "class:src/agentkit/experts/expert.py:Expert", + "type": "class", + "name": "Expert", + "summary": "专家运行时包装器,支持团队频道消息广播、跨 Expert 协助请求、计划修改提案", + "tags": [ + "experts", + "expert" + ], + "filePath": "src/agentkit/experts/expert.py" + }, + { + "id": "file:src/agentkit/experts/plan.py", + "type": "file", + "name": "plan.py", + "summary": "协作计划数据模型,定义 Expert Team 的结构化协作蓝图,包括阶段、角色分配、依赖关系、并行类型、合并策略和里程碑", + "tags": [ + "experts", + "plan", + "model" + ], + "filePath": "src/agentkit/experts/plan.py" + }, + { + "id": "class:src/agentkit/experts/plan.py:CollaborationPlan", + "type": "class", + "name": "CollaborationPlan", + "summary": "协作计划主类,包含有序阶段列表、共享变量、状态管理、依赖关系验证(DFS循环检测)", + "tags": [ + "experts", + "plan" + ], + "filePath": "src/agentkit/experts/plan.py" + }, + { + "id": "class:src/agentkit/experts/plan.py:PlanPhase", + "type": "class", + "name": "PlanPhase", + "summary": "协作计划阶段,包含 assigned_expert/task_description/depends_on/parallel_type/merge_strategy/milestone", + "tags": [ + "experts", + "plan", + "phase" + ], + "filePath": "src/agentkit/experts/plan.py" + }, + { + "id": "class:src/agentkit/experts/plan.py:MergeStrategy", + "type": "class", + "name": "MergeStrategy", + "summary": "合并策略枚举:BEST/VOTE/FUSION", + "tags": [ + "experts", + "enum", + "merge" + ], + "filePath": "src/agentkit/experts/plan.py" + }, + { + "id": "class:src/agentkit/experts/plan.py:ParallelType", + "type": "class", + "name": "ParallelType", + "summary": "并行执行类型枚举:SERIAL/SUBTASK_PARALLEL/COMPETITIVE_PARALLEL", + "tags": [ + "experts", + "enum" + ], + "filePath": "src/agentkit/experts/plan.py" + }, + { + "id": "file:src/agentkit/experts/registry.py", + "type": "file", + "name": "registry.py", + "summary": "专家模板注册中心,管理 ExpertTemplate 的注册、发现、搜索和批量加载", + "tags": [ + "experts", + "registry" + ], + "filePath": "src/agentkit/experts/registry.py" + }, + { + "id": "class:src/agentkit/experts/registry.py:ExpertTemplateRegistry", + "type": "class", + "name": "ExpertTemplateRegistry", + "summary": "专家模板注册中心,支持注册/获取/搜索模板", + "tags": [ + "experts", + "registry" + ], + "filePath": "src/agentkit/experts/registry.py" + }, + { + "id": "file:src/agentkit/chat/skill_routing.py", + "type": "file", + "name": "skill_routing.py", + "summary": "共享技能路由逻辑,包含三层成本感知路由器 CostAwareRouter、启发式分类器 HeuristicClassifier", + "tags": [ + "chat", + "routing", + "skill" + ], + "filePath": "src/agentkit/chat/skill_routing.py" + }, + { + "id": "class:src/agentkit/chat/skill_routing.py:CostAwareRouter", + "type": "class", + "name": "CostAwareRouter", + "summary": "三层成本感知路由器:Layer0 规则匹配→Layer1 复杂度分类→Layer2 能力匹配/团队升级", + "tags": [ + "chat", + "router", + "cost-aware" + ], + "filePath": "src/agentkit/chat/skill_routing.py" + }, + { + "id": "file:src/agentkit/server/routes/chat.py", + "type": "file", + "name": "chat.py", + "summary": "Chat API 路由,提供 REST 和 WebSocket 端点,支持专家团队事件推送", + "tags": [ + "server", + "route", + "chat", + "websocket" + ], + "filePath": "src/agentkit/server/routes/chat.py" + }, + { + "id": "file:src/agentkit/server/app.py", + "type": "file", + "name": "app.py", + "summary": "FastAPI 应用工厂,初始化全部组件", + "tags": [ + "server", + "app", + "factory" + ], + "filePath": "src/agentkit/server/app.py" + }, + { + "id": "file:src/agentkit/server/config.py", + "type": "file", + "name": "config.py", + "summary": "服务器配置加载器,从 agentkit.yaml 加载配置", + "tags": [ + "server", + "config" + ], + "filePath": "src/agentkit/server/config.py" + }, + { + "id": "class:src/agentkit/server/config.py:ServerConfig", + "type": "class", + "name": "ServerConfig", + "summary": "服务器配置主类", + "tags": [ + "server", + "config" + ], + "filePath": "src/agentkit/server/config.py" + }, + { + "id": "file:src/agentkit/server/middleware.py", + "type": "file", + "name": "middleware.py", + "summary": "服务器中间件,包含 API Key 认证和速率限制", + "tags": [ + "server", + "middleware", + "auth" + ], + "filePath": "src/agentkit/server/middleware.py" + }, + { + "id": "file:src/agentkit/server/frontend/src/stores/chat.ts", + "type": "file", + "name": "chat.ts", + "summary": "Pinia 聊天状态管理,管理对话列表、WebSocket 连接、专家团队事件", + "tags": [ + "frontend", + "store", + "chat", + "pinia" + ], + "filePath": "src/agentkit/server/frontend/src/stores/chat.ts" + }, + { + "id": "file:src/agentkit/server/frontend/src/stores/team.ts", + "type": "file", + "name": "team.ts", + "summary": "Pinia 专家团队状态管理", + "tags": [ + "frontend", + "store", + "team", + "pinia" + ], + "filePath": "src/agentkit/server/frontend/src/stores/team.ts" + }, + { + "id": "file:src/agentkit/server/frontend/src/components/chat/ExpertTeamView.vue", + "type": "file", + "name": "ExpertTeamView.vue", + "summary": "专家团队视图组件,展示活跃专家列表、阶段完成进度条", + "tags": [ + "frontend", + "component", + "team", + "vue" + ], + "filePath": "src/agentkit/server/frontend/src/components/chat/ExpertTeamView.vue" + }, + { + "id": "file:src/agentkit/server/frontend/src/components/chat/PlanVisualization.vue", + "type": "file", + "name": "PlanVisualization.vue", + "summary": "协作计划时间线可视化组件", + "tags": [ + "frontend", + "component", + "plan", + "visualization", + "vue" + ], + "filePath": "src/agentkit/server/frontend/src/components/chat/PlanVisualization.vue" + }, + { + "id": "file:src/agentkit/server/frontend/src/views/ChatView.vue", + "type": "file", + "name": "ChatView.vue", + "summary": "聊天主视图", + "tags": [ + "frontend", + "view", + "chat", + "vue" + ], + "filePath": "src/agentkit/server/frontend/src/views/ChatView.vue" + }, + { + "id": "file:tests/unit/experts/test_team_orchestrator.py", + "type": "file", + "name": "test_team_orchestrator.py", + "summary": "TeamOrchestrator 单元测试,覆盖串行/并行/竞争/合并策略/里程碑/重试/重规划/回退", + "tags": [ + "test", + "unit", + "orchestrator" + ], + "filePath": "tests/unit/experts/test_team_orchestrator.py" + }, + { + "id": "file:tests/unit/core/test_autonomous_research_task.py", + "type": "file", + "name": "test_autonomous_research_task.py", + "summary": "多步研究任务端到端验证", + "tags": [ + "test", + "unit", + "plan-exec", + "e2e" + ], + "filePath": "tests/unit/core/test_autonomous_research_task.py" + }, + { + "id": "file:tests/unit/experts/test_team.py", + "type": "file", + "name": "test_team.py", + "summary": "ExpertTeam 容器单元测试", + "tags": [ + "test", + "unit", + "team" + ], + "filePath": "tests/unit/experts/test_team.py" } ], "edges": [ @@ -31978,83 +30942,6 @@ "type": "contains", "label": "方法 route" }, - { - "id": "edge:ba88bd96", - "source": "file:src/agentkit/chat/skill_routing.py", - "target": "class:ExecutionMode", - "type": "contains", - "label": "定义类 ExecutionMode" - }, - { - "id": "edge:c087f43d", - "source": "file:src/agentkit/chat/skill_routing.py", - "target": "class:SkillRoutingResult", - "type": "contains", - "label": "定义类 SkillRoutingResult" - }, - { - "id": "edge:d1538ba5", - "source": "file:src/agentkit/chat/skill_routing.py", - "target": "class:HeuristicClassifier", - "type": "contains", - "label": "定义类 HeuristicClassifier" - }, - { - "id": "edge:97ef5b0e", - "source": "class:HeuristicClassifier", - "target": "func:HeuristicClassifier.classify", - "type": "contains", - "label": "方法 classify" - }, - { - "id": "edge:5a56c960", - "source": "file:src/agentkit/chat/skill_routing.py", - "target": "class:CostAwareRouter", - "type": "contains", - "label": "定义类 CostAwareRouter" - }, - { - "id": "edge:4990de00", - "source": "class:CostAwareRouter", - "target": "func:CostAwareRouter.__init__", - "type": "contains", - "label": "方法 __init__" - }, - { - "id": "edge:ab1f09de", - "source": "class:CostAwareRouter", - "target": "func:CostAwareRouter._match_layer0", - "type": "contains", - "label": "方法 _match_layer0" - }, - { - "id": "edge:545f5197", - "source": "class:CostAwareRouter", - "target": "func:CostAwareRouter.quick_classify", - "type": "contains", - "label": "方法 quick_classify" - }, - { - "id": "edge:173bc9da", - "source": "class:CostAwareRouter", - "target": "func:CostAwareRouter._classify_merged", - "type": "contains", - "label": "方法 _classify_merged" - }, - { - "id": "edge:8cbeb570", - "source": "class:CostAwareRouter", - "target": "func:CostAwareRouter._route_layer2", - "type": "contains", - "label": "方法 _route_layer2" - }, - { - "id": "edge:d7482799", - "source": "class:CostAwareRouter", - "target": "func:CostAwareRouter.route", - "type": "contains", - "label": "方法 route" - }, { "id": "edge:e9a687a2", "source": "file:src/agentkit/core/agent_pool.py", @@ -33245,118 +32132,6 @@ "type": "contains", "label": "方法 __init__" }, - { - "id": "edge:c5c23e75", - "source": "file:src/agentkit/core/goal_planner.py", - "target": "class:GoalPlanner", - "type": "contains", - "label": "定义类 GoalPlanner" - }, - { - "id": "edge:e25dc94f", - "source": "class:GoalPlanner", - "target": "func:GoalPlanner.__init__", - "type": "contains", - "label": "方法 __init__" - }, - { - "id": "edge:2ce5d553", - "source": "class:GoalPlanner", - "target": "func:GoalPlanner.generate_plan", - "type": "contains", - "label": "方法 generate_plan" - }, - { - "id": "edge:d92a975c", - "source": "class:GoalPlanner", - "target": "func:GoalPlanner._rule_based_decompose", - "type": "contains", - "label": "方法 _rule_based_decompose" - }, - { - "id": "edge:38b1b00b", - "source": "class:GoalPlanner", - "target": "func:GoalPlanner._extract_parallel_items", - "type": "contains", - "label": "方法 _extract_parallel_items" - }, - { - "id": "edge:f28df35f", - "source": "class:GoalPlanner", - "target": "func:GoalPlanner._extract_sequential_parts", - "type": "contains", - "label": "方法 _extract_sequential_parts" - }, - { - "id": "edge:edc125d1", - "source": "class:GoalPlanner", - "target": "func:GoalPlanner._decompose_parallel_goal", - "type": "contains", - "label": "方法 _decompose_parallel_goal" - }, - { - "id": "edge:ccbed0d7", - "source": "class:GoalPlanner", - "target": "func:GoalPlanner._decompose_sequential_goal", - "type": "contains", - "label": "方法 _decompose_sequential_goal" - }, - { - "id": "edge:1ddac9ce", - "source": "class:GoalPlanner", - "target": "func:GoalPlanner._decompose_simple_goal", - "type": "contains", - "label": "方法 _decompose_simple_goal" - }, - { - "id": "edge:3597abfa", - "source": "class:GoalPlanner", - "target": "func:GoalPlanner._infer_required_skills", - "type": "contains", - "label": "方法 _infer_required_skills" - }, - { - "id": "edge:361f48b1", - "source": "class:GoalPlanner", - "target": "func:GoalPlanner._identify_skill_gaps", - "type": "contains", - "label": "方法 _identify_skill_gaps" - }, - { - "id": "edge:82f70cd2", - "source": "class:GoalPlanner", - "target": "func:GoalPlanner._should_refine_with_llm", - "type": "contains", - "label": "方法 _should_refine_with_llm" - }, - { - "id": "edge:b0eae8b1", - "source": "class:GoalPlanner", - "target": "func:GoalPlanner._llm_refine_plan", - "type": "contains", - "label": "方法 _llm_refine_plan" - }, - { - "id": "edge:269080d0", - "source": "class:GoalPlanner", - "target": "func:GoalPlanner._build_parallel_groups", - "type": "contains", - "label": "方法 _build_parallel_groups" - }, - { - "id": "edge:ff7681fe", - "source": "class:GoalPlanner", - "target": "func:GoalPlanner.update_plan_from_feedback", - "type": "contains", - "label": "方法 update_plan_from_feedback" - }, - { - "id": "edge:9036d4de", - "source": "class:GoalPlanner", - "target": "func:GoalPlanner.validate_plan", - "type": "contains", - "label": "方法 validate_plan" - }, { "id": "edge:c9672dd2", "source": "file:src/agentkit/core/headroom_compressor.py", @@ -33784,167 +32559,6 @@ "type": "contains", "label": "方法 reset" }, - { - "id": "edge:02944f73", - "source": "file:src/agentkit/core/plan_exec_engine.py", - "target": "class:_StreamState", - "type": "contains", - "label": "定义类 _StreamState" - }, - { - "id": "edge:db08af08", - "source": "file:src/agentkit/core/plan_exec_engine.py", - "target": "class:PlanExecEngine", - "type": "contains", - "label": "定义类 PlanExecEngine" - }, - { - "id": "edge:2334426a", - "source": "class:PlanExecEngine", - "target": "func:PlanExecEngine.__init__", - "type": "contains", - "label": "方法 __init__" - }, - { - "id": "edge:994e4460", - "source": "class:PlanExecEngine", - "target": "func:PlanExecEngine.execute", - "type": "contains", - "label": "方法 execute" - }, - { - "id": "edge:ace71045", - "source": "class:PlanExecEngine", - "target": "func:PlanExecEngine.execute_stream", - "type": "contains", - "label": "方法 execute_stream" - }, - { - "id": "edge:1425fbd0", - "source": "class:PlanExecEngine", - "target": "func:PlanExecEngine._execute_loop", - "type": "contains", - "label": "方法 _execute_loop" - }, - { - "id": "edge:faea6c24", - "source": "class:PlanExecEngine", - "target": "func:PlanExecEngine._execute_with_replanning", - "type": "contains", - "label": "方法 _execute_with_replanning" - }, - { - "id": "edge:e15e6a32", - "source": "class:PlanExecEngine", - "target": "func:PlanExecEngine._extract_goal", - "type": "contains", - "label": "方法 _extract_goal" - }, - { - "id": "edge:34670599", - "source": "class:PlanExecEngine", - "target": "func:PlanExecEngine._extract_skill_names", - "type": "contains", - "label": "方法 _extract_skill_names" - }, - { - "id": "edge:867ffaa9", - "source": "class:PlanExecEngine", - "target": "func:PlanExecEngine._build_task_message", - "type": "contains", - "label": "方法 _build_task_message" - }, - { - "id": "edge:0c0ba843", - "source": "class:PlanExecEngine", - "target": "func:PlanExecEngine._create_executor", - "type": "contains", - "label": "方法 _create_executor" - }, - { - "id": "edge:986c5d73", - "source": "class:PlanExecEngine", - "target": "func:PlanExecEngine._plan_to_pipeline", - "type": "contains", - "label": "方法 _plan_to_pipeline" - }, - { - "id": "edge:3ecbe8f8", - "source": "class:PlanExecEngine", - "target": "func:PlanExecEngine._plan_result_to_pipeline_result", - "type": "contains", - "label": "方法 _plan_result_to_pipeline_result" - }, - { - "id": "edge:5c55280d", - "source": "class:PlanExecEngine", - "target": "func:PlanExecEngine._pipeline_to_plan", - "type": "contains", - "label": "方法 _pipeline_to_plan" - }, - { - "id": "edge:096286ac", - "source": "class:PlanExecEngine", - "target": "func:PlanExecEngine._merge_completed_results", - "type": "contains", - "label": "方法 _merge_completed_results" - }, - { - "id": "edge:7ba109a2", - "source": "class:PlanExecEngine", - "target": "func:PlanExecEngine._aggregate_output", - "type": "contains", - "label": "方法 _aggregate_output" - }, - { - "id": "edge:7833b477", - "source": "file:src/agentkit/core/plan_exec_engine.py", - "target": "class:_LLMStepExecutor", - "type": "contains", - "label": "定义类 _LLMStepExecutor" - }, - { - "id": "edge:7971eb03", - "source": "class:_LLMStepExecutor", - "target": "func:_LLMStepExecutor.__init__", - "type": "contains", - "label": "方法 __init__" - }, - { - "id": "edge:a31aea14", - "source": "class:_LLMStepExecutor", - "target": "func:_LLMStepExecutor.create_agent_from_skill", - "type": "contains", - "label": "方法 create_agent_from_skill" - }, - { - "id": "edge:2cac3a56", - "source": "class:_LLMStepExecutor", - "target": "func:_LLMStepExecutor.get_agent", - "type": "contains", - "label": "方法 get_agent" - }, - { - "id": "edge:208995f1", - "source": "file:src/agentkit/core/plan_exec_engine.py", - "target": "class:_LLMStepAgent", - "type": "contains", - "label": "定义类 _LLMStepAgent" - }, - { - "id": "edge:66ae46d8", - "source": "class:_LLMStepAgent", - "target": "func:_LLMStepAgent.__init__", - "type": "contains", - "label": "方法 __init__" - }, - { - "id": "edge:f1a81248", - "source": "class:_LLMStepAgent", - "target": "func:_LLMStepAgent.execute", - "type": "contains", - "label": "方法 execute" - }, { "id": "edge:2cc61531", "source": "file:src/agentkit/core/plan_executor.py", @@ -41876,195 +40490,6 @@ "type": "contains", "label": "方法 validate_api_key" }, - { - "id": "edge:9a2959e6", - "source": "file:src/agentkit/server/config.py", - "target": "class:MCPServerConfig", - "type": "contains", - "label": "定义类 MCPServerConfig" - }, - { - "id": "edge:507a0fe3", - "source": "class:MCPServerConfig", - "target": "func:MCPServerConfig.validate", - "type": "contains", - "label": "方法 validate" - }, - { - "id": "edge:8176c1e2", - "source": "class:MCPServerConfig", - "target": "func:MCPServerConfig.from_dict", - "type": "contains", - "label": "方法 from_dict" - }, - { - "id": "edge:81257924", - "source": "file:src/agentkit/server/config.py", - "target": "class:ServerConfig", - "type": "contains", - "label": "定义类 ServerConfig" - }, - { - "id": "edge:9162001f", - "source": "class:ServerConfig", - "target": "func:ServerConfig.__init__", - "type": "contains", - "label": "方法 __init__" - }, - { - "id": "edge:24c22e30", - "source": "class:ServerConfig", - "target": "func:ServerConfig.has_llm_provider", - "type": "contains", - "label": "方法 has_llm_provider" - }, - { - "id": "edge:f0269c63", - "source": "class:ServerConfig", - "target": "func:ServerConfig.from_yaml", - "type": "contains", - "label": "方法 from_yaml" - }, - { - "id": "edge:05cf258f", - "source": "class:ServerConfig", - "target": "func:ServerConfig.from_dict", - "type": "contains", - "label": "方法 from_dict" - }, - { - "id": "edge:153af43f", - "source": "class:ServerConfig", - "target": "func:ServerConfig._build_llm_config", - "type": "contains", - "label": "方法 _build_llm_config" - }, - { - "id": "edge:549e6c90", - "source": "class:ServerConfig", - "target": "func:ServerConfig._build_mcp_configs", - "type": "contains", - "label": "方法 _build_mcp_configs" - }, - { - "id": "edge:be90b3ca", - "source": "class:ServerConfig", - "target": "func:ServerConfig.load_skill_configs", - "type": "contains", - "label": "方法 load_skill_configs" - }, - { - "id": "edge:dd92403a", - "source": "class:ServerConfig", - "target": "func:ServerConfig.load_dotenv", - "type": "contains", - "label": "方法 load_dotenv" - }, - { - "id": "edge:a77873d5", - "source": "class:ServerConfig", - "target": "func:ServerConfig.watch_config", - "type": "contains", - "label": "方法 watch_config" - }, - { - "id": "edge:db2ba37b", - "source": "class:ServerConfig", - "target": "func:ServerConfig.stop_watching", - "type": "contains", - "label": "方法 stop_watching" - }, - { - "id": "edge:eac44a78", - "source": "class:ServerConfig", - "target": "func:ServerConfig._watch_with_watchfiles", - "type": "contains", - "label": "方法 _watch_with_watchfiles" - }, - { - "id": "edge:62491759", - "source": "class:ServerConfig", - "target": "func:ServerConfig._poll_config_loop", - "type": "contains", - "label": "方法 _poll_config_loop" - }, - { - "id": "edge:35baaed9", - "source": "class:ServerConfig", - "target": "func:ServerConfig._try_reload_config", - "type": "contains", - "label": "方法 _try_reload_config" - }, - { - "id": "edge:2bff015d", - "source": "file:src/agentkit/server/middleware.py", - "target": "class:APIKeyAuthMiddleware", - "type": "contains", - "label": "定义类 APIKeyAuthMiddleware" - }, - { - "id": "edge:65ff9263", - "source": "class:APIKeyAuthMiddleware", - "target": "func:APIKeyAuthMiddleware.__init__", - "type": "contains", - "label": "方法 __init__" - }, - { - "id": "edge:9a0de58c", - "source": "class:APIKeyAuthMiddleware", - "target": "func:APIKeyAuthMiddleware.dispatch", - "type": "contains", - "label": "方法 dispatch" - }, - { - "id": "edge:49edecfe", - "source": "file:src/agentkit/server/middleware.py", - "target": "class:RateLimiter", - "type": "contains", - "label": "定义类 RateLimiter" - }, - { - "id": "edge:0802a848", - "source": "class:RateLimiter", - "target": "func:RateLimiter.__init__", - "type": "contains", - "label": "方法 __init__" - }, - { - "id": "edge:cbdf2fae", - "source": "class:RateLimiter", - "target": "func:RateLimiter.is_allowed", - "type": "contains", - "label": "方法 is_allowed" - }, - { - "id": "edge:10a15d1f", - "source": "class:RateLimiter", - "target": "func:RateLimiter.max_requests", - "type": "contains", - "label": "方法 max_requests" - }, - { - "id": "edge:82d28f3c", - "source": "file:src/agentkit/server/middleware.py", - "target": "class:RateLimitMiddleware", - "type": "contains", - "label": "定义类 RateLimitMiddleware" - }, - { - "id": "edge:7d6554a5", - "source": "class:RateLimitMiddleware", - "target": "func:RateLimitMiddleware.__init__", - "type": "contains", - "label": "方法 __init__" - }, - { - "id": "edge:58608c40", - "source": "class:RateLimitMiddleware", - "target": "func:RateLimitMiddleware.dispatch", - "type": "contains", - "label": "方法 dispatch" - }, { "id": "edge:d5ef810d", "source": "file:src/agentkit/server/routes/agents.py", @@ -42072,76 +40497,6 @@ "type": "contains", "label": "定义类 CreateAgentRequest" }, - { - "id": "edge:f125fe73", - "source": "file:src/agentkit/server/routes/chat.py", - "target": "class:CreateSessionRequest", - "type": "contains", - "label": "定义类 CreateSessionRequest" - }, - { - "id": "edge:e9535fd6", - "source": "file:src/agentkit/server/routes/chat.py", - "target": "class:SendMessageRequest", - "type": "contains", - "label": "定义类 SendMessageRequest" - }, - { - "id": "edge:55c4e7a4", - "source": "file:src/agentkit/server/routes/chat.py", - "target": "class:SessionResponse", - "type": "contains", - "label": "定义类 SessionResponse" - }, - { - "id": "edge:8299a103", - "source": "file:src/agentkit/server/routes/chat.py", - "target": "class:MessageResponse", - "type": "contains", - "label": "定义类 MessageResponse" - }, - { - "id": "edge:4bf8e255", - "source": "file:src/agentkit/server/routes/chat.py", - "target": "class:ChatConnectionManager", - "type": "contains", - "label": "定义类 ChatConnectionManager" - }, - { - "id": "edge:348d5875", - "source": "class:ChatConnectionManager", - "target": "func:ChatConnectionManager.__init__", - "type": "contains", - "label": "方法 __init__" - }, - { - "id": "edge:25c49351", - "source": "class:ChatConnectionManager", - "target": "func:ChatConnectionManager.add", - "type": "contains", - "label": "方法 add" - }, - { - "id": "edge:dd20d530", - "source": "class:ChatConnectionManager", - "target": "func:ChatConnectionManager.remove", - "type": "contains", - "label": "方法 remove" - }, - { - "id": "edge:b80f88f7", - "source": "class:ChatConnectionManager", - "target": "func:ChatConnectionManager.get_connections", - "type": "contains", - "label": "方法 get_connections" - }, - { - "id": "edge:c764983e", - "source": "class:ChatConnectionManager", - "target": "func:ChatConnectionManager.send_json", - "type": "contains", - "label": "方法 send_json" - }, { "id": "edge:188a8a9b", "source": "file:src/agentkit/server/routes/evolution.py", @@ -46328,48 +44683,6 @@ "type": "contains", "label": "定义函数 create_message_bus" }, - { - "id": "edge:52a16449", - "source": "file:src/agentkit/chat/skill_routing.py", - "target": "func:validate_skill_name", - "type": "contains", - "label": "定义函数 validate_skill_name" - }, - { - "id": "edge:e6ef0239", - "source": "file:src/agentkit/chat/skill_routing.py", - "target": "func:parse_skill_prefix", - "type": "contains", - "label": "定义函数 parse_skill_prefix" - }, - { - "id": "edge:613db7e4", - "source": "file:src/agentkit/chat/skill_routing.py", - "target": "func:build_skill_system_prompt", - "type": "contains", - "label": "定义函数 build_skill_system_prompt" - }, - { - "id": "edge:501ec945", - "source": "file:src/agentkit/chat/skill_routing.py", - "target": "func:resolve_skill_routing", - "type": "contains", - "label": "定义函数 resolve_skill_routing" - }, - { - "id": "edge:7559d5b0", - "source": "file:src/agentkit/chat/skill_routing.py", - "target": "func:_build_tools_description", - "type": "contains", - "label": "定义函数 _build_tools_description" - }, - { - "id": "edge:af6b95c3", - "source": "file:src/agentkit/chat/skill_routing.py", - "target": "func:_tokenize_content", - "type": "contains", - "label": "定义函数 _tokenize_content" - }, { "id": "edge:cf3ce3f3", "source": "file:src/agentkit/cli/chat.py", @@ -46853,69 +45166,6 @@ "type": "contains", "label": "定义函数 create_cascade_state_store" }, - { - "id": "edge:221ecd78", - "source": "file:src/agentkit/server/app.py", - "target": "func:_build_llm_gateway", - "type": "contains", - "label": "定义函数 _build_llm_gateway" - }, - { - "id": "edge:19063754", - "source": "file:src/agentkit/server/app.py", - "target": "func:_build_skill_registry", - "type": "contains", - "label": "定义函数 _build_skill_registry" - }, - { - "id": "edge:dcc93a12", - "source": "file:src/agentkit/server/app.py", - "target": "func:lifespan", - "type": "contains", - "label": "定义函数 lifespan" - }, - { - "id": "edge:7e3a30bc", - "source": "file:src/agentkit/server/app.py", - "target": "func:_on_config_change", - "type": "contains", - "label": "定义函数 _on_config_change" - }, - { - "id": "edge:7a1d96af", - "source": "file:src/agentkit/server/app.py", - "target": "func:create_app", - "type": "contains", - "label": "定义函数 create_app" - }, - { - "id": "edge:0b4e48c3", - "source": "file:src/agentkit/server/config.py", - "target": "func:_resolve_env_vars", - "type": "contains", - "label": "定义函数 _resolve_env_vars" - }, - { - "id": "edge:2e3b09df", - "source": "file:src/agentkit/server/config.py", - "target": "func:_deep_resolve", - "type": "contains", - "label": "定义函数 _deep_resolve" - }, - { - "id": "edge:fa64dcbe", - "source": "file:src/agentkit/server/config.py", - "target": "func:find_config_path", - "type": "contains", - "label": "定义函数 find_config_path" - }, - { - "id": "edge:75112588", - "source": "file:src/agentkit/server/middleware.py", - "target": "func:_load_client_keys", - "type": "contains", - "label": "定义函数 _load_client_keys" - }, { "id": "edge:db535d7d", "source": "file:src/agentkit/server/routes/agents.py", @@ -46958,83 +45208,6 @@ "type": "contains", "label": "定义函数 delete_agent" }, - { - "id": "edge:ef808d20", - "source": "file:src/agentkit/server/routes/chat.py", - "target": "func:_get_session_manager", - "type": "contains", - "label": "定义函数 _get_session_manager" - }, - { - "id": "edge:503fce57", - "source": "file:src/agentkit/server/routes/chat.py", - "target": "func:_session_to_response", - "type": "contains", - "label": "定义函数 _session_to_response" - }, - { - "id": "edge:9852a7ea", - "source": "file:src/agentkit/server/routes/chat.py", - "target": "func:_message_to_response", - "type": "contains", - "label": "定义函数 _message_to_response" - }, - { - "id": "edge:09821956", - "source": "file:src/agentkit/server/routes/chat.py", - "target": "func:list_sessions", - "type": "contains", - "label": "定义函数 list_sessions" - }, - { - "id": "edge:5f27cef6", - "source": "file:src/agentkit/server/routes/chat.py", - "target": "func:create_session", - "type": "contains", - "label": "定义函数 create_session" - }, - { - "id": "edge:48e60255", - "source": "file:src/agentkit/server/routes/chat.py", - "target": "func:get_session", - "type": "contains", - "label": "定义函数 get_session" - }, - { - "id": "edge:6050e885", - "source": "file:src/agentkit/server/routes/chat.py", - "target": "func:get_messages", - "type": "contains", - "label": "定义函数 get_messages" - }, - { - "id": "edge:62f6b597", - "source": "file:src/agentkit/server/routes/chat.py", - "target": "func:send_message", - "type": "contains", - "label": "定义函数 send_message" - }, - { - "id": "edge:b659ab9d", - "source": "file:src/agentkit/server/routes/chat.py", - "target": "func:close_session", - "type": "contains", - "label": "定义函数 close_session" - }, - { - "id": "edge:13c4be75", - "source": "file:src/agentkit/server/routes/chat.py", - "target": "func:chat_websocket", - "type": "contains", - "label": "定义函数 chat_websocket" - }, - { - "id": "edge:d5cf8477", - "source": "file:src/agentkit/server/routes/chat.py", - "target": "func:_handle_chat_message", - "type": "contains", - "label": "定义函数 _handle_chat_message" - }, { "id": "edge:0902a064", "source": "file:src/agentkit/server/routes/evolution.py", @@ -47665,13 +45838,6 @@ "type": "contains", "label": "定义函数 execute_command" }, - { - "id": "edge:a49e88cb", - "source": "file:src/agentkit/server/routes/terminal.py", - "target": "func:list_sessions", - "type": "contains", - "label": "定义函数 list_sessions" - }, { "id": "edge:13706074", "source": "file:src/agentkit/server/routes/terminal.py", @@ -47679,13 +45845,6 @@ "type": "contains", "label": "定义函数 get_session_history" }, - { - "id": "edge:23300d24", - "source": "file:src/agentkit/server/routes/terminal.py", - "target": "func:close_session", - "type": "contains", - "label": "定义函数 close_session" - }, { "id": "edge:8a826a0c", "source": "file:src/agentkit/server/routes/terminal.py", @@ -48092,13 +46251,6 @@ "type": "imports", "label": "导入 IntentRouter" }, - { - "id": "edge:6170007c", - "source": "file:configs/geo_server.py", - "target": "file:src/agentkit/server/app.py", - "type": "imports", - "label": "导入 create_app" - }, { "id": "edge:6612091d", "source": "file:configs/geo_server.py", @@ -48470,27 +46622,6 @@ "type": "imports", "label": "导入 compute_cosine_similarity" }, - { - "id": "edge:1e9da62e", - "source": "file:src/agentkit/chat/skill_routing.py", - "target": "file:src/agentkit/marketplace/auction.py", - "type": "imports", - "label": "导入 AuctionHouse" - }, - { - "id": "edge:b7ee0a30", - "source": "file:src/agentkit/chat/skill_routing.py", - "target": "file:src/agentkit/marketplace/auction.py", - "type": "imports", - "label": "导入 Bid" - }, - { - "id": "edge:674e9689", - "source": "file:src/agentkit/chat/skill_routing.py", - "target": "file:src/agentkit/telemetry/tracer.py", - "type": "imports", - "label": "导入 get_tracer" - }, { "id": "edge:641190fa", "source": "file:src/agentkit/cli/chat.py", @@ -48498,20 +46629,6 @@ "type": "imports", "label": "导入 run_onboarding" }, - { - "id": "edge:5237be67", - "source": "file:src/agentkit/cli/chat.py", - "target": "file:src/agentkit/server/config.py", - "type": "imports", - "label": "导入 ServerConfig" - }, - { - "id": "edge:2c0adc8d", - "source": "file:src/agentkit/cli/chat.py", - "target": "file:src/agentkit/server/config.py", - "type": "imports", - "label": "导入 find_config_path" - }, { "id": "edge:ab63631a", "source": "file:src/agentkit/cli/chat.py", @@ -48638,13 +46755,6 @@ "type": "imports", "label": "导入 OpenAICompatibleProvider" }, - { - "id": "edge:14e8e59b", - "source": "file:src/agentkit/cli/chat.py", - "target": "file:src/agentkit/chat/skill_routing.py", - "type": "imports", - "label": "导入 resolve_skill_routing" - }, { "id": "edge:624b806a", "source": "file:src/agentkit/cli/init.py", @@ -48715,20 +46825,6 @@ "type": "imports", "label": "导入 chat" }, - { - "id": "edge:a81d6e60", - "source": "file:src/agentkit/cli/main.py", - "target": "file:src/agentkit/server/config.py", - "type": "imports", - "label": "导入 ServerConfig" - }, - { - "id": "edge:5b582bc5", - "source": "file:src/agentkit/cli/main.py", - "target": "file:src/agentkit/server/config.py", - "type": "imports", - "label": "导入 find_config_path" - }, { "id": "edge:39136050", "source": "file:src/agentkit/cli/main.py", @@ -48736,27 +46832,6 @@ "type": "imports", "label": "导入 run_onboarding" }, - { - "id": "edge:1f3e1227", - "source": "file:src/agentkit/cli/main.py", - "target": "file:src/agentkit/server/app.py", - "type": "imports", - "label": "导入 create_app" - }, - { - "id": "edge:f27d1398", - "source": "file:src/agentkit/cli/main.py", - "target": "file:src/agentkit/server/config.py", - "type": "imports", - "label": "导入 ServerConfig" - }, - { - "id": "edge:b9437edb", - "source": "file:src/agentkit/cli/main.py", - "target": "file:src/agentkit/server/config.py", - "type": "imports", - "label": "导入 find_config_path" - }, { "id": "edge:29d713bb", "source": "file:src/agentkit/cli/main.py", @@ -48771,13 +46846,6 @@ "type": "imports", "label": "导入 run_onboarding" }, - { - "id": "edge:6296b7b7", - "source": "file:src/agentkit/cli/onboarding.py", - "target": "file:src/agentkit/server/config.py", - "type": "imports", - "label": "导入 find_config_path" - }, { "id": "edge:c97f258e", "source": "file:src/agentkit/cli/onboarding.py", @@ -48841,27 +46909,6 @@ "type": "imports", "label": "导入 AgentKitClient" }, - { - "id": "edge:855c6668", - "source": "file:src/agentkit/cli/task.py", - "target": "file:src/agentkit/server/config.py", - "type": "imports", - "label": "导入 ServerConfig" - }, - { - "id": "edge:d8988844", - "source": "file:src/agentkit/cli/task.py", - "target": "file:src/agentkit/server/config.py", - "type": "imports", - "label": "导入 find_config_path" - }, - { - "id": "edge:f3076b0e", - "source": "file:src/agentkit/cli/task.py", - "target": "file:src/agentkit/server/app.py", - "type": "imports", - "label": "导入 create_app" - }, { "id": "edge:7e9d17a6", "source": "file:src/agentkit/cli/task.py", @@ -49464,13 +47511,6 @@ "type": "imports", "label": "导入 ReWOOEngine" }, - { - "id": "edge:31b29e42", - "source": "file:src/agentkit/core/config_driven.py", - "target": "file:src/agentkit/core/plan_exec_engine.py", - "type": "imports", - "label": "导入 PlanExecEngine" - }, { "id": "edge:a0c0e638", "source": "file:src/agentkit/core/config_driven.py", @@ -49653,41 +47693,6 @@ "type": "imports", "label": "导入 TaskStatus" }, - { - "id": "edge:02032768", - "source": "file:src/agentkit/core/goal_planner.py", - "target": "file:src/agentkit/core/plan_schema.py", - "type": "imports", - "label": "导入 ExecutionPlan" - }, - { - "id": "edge:07adecaf", - "source": "file:src/agentkit/core/goal_planner.py", - "target": "file:src/agentkit/core/plan_schema.py", - "type": "imports", - "label": "导入 PlanStep" - }, - { - "id": "edge:38e9241e", - "source": "file:src/agentkit/core/goal_planner.py", - "target": "file:src/agentkit/core/plan_schema.py", - "type": "imports", - "label": "导入 PlanStepStatus" - }, - { - "id": "edge:4809031d", - "source": "file:src/agentkit/core/goal_planner.py", - "target": "file:src/agentkit/core/plan_schema.py", - "type": "imports", - "label": "导入 SkillGap" - }, - { - "id": "edge:cb2d7d96", - "source": "file:src/agentkit/core/goal_planner.py", - "target": "file:src/agentkit/core/plan_schema.py", - "type": "imports", - "label": "导入 SkillGapLevel" - }, { "id": "edge:45fb819d", "source": "file:src/agentkit/core/headroom_compressor.py", @@ -49723,13 +47728,6 @@ "type": "imports", "label": "导入 SharedWorkspace" }, - { - "id": "edge:e9cf7f5d", - "source": "file:src/agentkit/core/orchestrator.py", - "target": "file:src/agentkit/core/goal_planner.py", - "type": "imports", - "label": "导入 GoalPlanner" - }, { "id": "edge:b31dd748", "source": "file:src/agentkit/core/orchestrator.py", @@ -49814,216 +47812,6 @@ "type": "imports", "label": "导入 TaskExperience" }, - { - "id": "edge:f6cf456a", - "source": "file:src/agentkit/core/plan_exec_engine.py", - "target": "file:src/agentkit/core/exceptions.py", - "type": "imports", - "label": "导入 TaskCancelledError" - }, - { - "id": "edge:0e234b06", - "source": "file:src/agentkit/core/plan_exec_engine.py", - "target": "file:src/agentkit/core/exceptions.py", - "type": "imports", - "label": "导入 TaskTimeoutError" - }, - { - "id": "edge:d5ae51fe", - "source": "file:src/agentkit/core/plan_exec_engine.py", - "target": "file:src/agentkit/core/goal_planner.py", - "type": "imports", - "label": "导入 GoalPlanner" - }, - { - "id": "edge:7e86945e", - "source": "file:src/agentkit/core/plan_exec_engine.py", - "target": "file:src/agentkit/core/plan_executor.py", - "type": "imports", - "label": "导入 PlanExecutor" - }, - { - "id": "edge:60efa7a2", - "source": "file:src/agentkit/core/plan_exec_engine.py", - "target": "file:src/agentkit/core/plan_executor.py", - "type": "imports", - "label": "导入 PlanExecutionResult" - }, - { - "id": "edge:a7a9217c", - "source": "file:src/agentkit/core/plan_exec_engine.py", - "target": "file:src/agentkit/core/plan_executor.py", - "type": "imports", - "label": "导入 StepExecutionResult" - }, - { - "id": "edge:087158af", - "source": "file:src/agentkit/core/plan_exec_engine.py", - "target": "file:src/agentkit/core/plan_schema.py", - "type": "imports", - "label": "导入 ExecutionPlan" - }, - { - "id": "edge:2e534e8f", - "source": "file:src/agentkit/core/plan_exec_engine.py", - "target": "file:src/agentkit/core/plan_schema.py", - "type": "imports", - "label": "导入 PlanStep" - }, - { - "id": "edge:f1821d93", - "source": "file:src/agentkit/core/plan_exec_engine.py", - "target": "file:src/agentkit/core/plan_schema.py", - "type": "imports", - "label": "导入 PlanStepStatus" - }, - { - "id": "edge:3204a7ff", - "source": "file:src/agentkit/core/plan_exec_engine.py", - "target": "file:src/agentkit/core/protocol.py", - "type": "imports", - "label": "导入 CancellationToken" - }, - { - "id": "edge:ec00f7a4", - "source": "file:src/agentkit/core/plan_exec_engine.py", - "target": "file:src/agentkit/core/protocol.py", - "type": "imports", - "label": "导入 TaskMessage" - }, - { - "id": "edge:d212c09e", - "source": "file:src/agentkit/core/plan_exec_engine.py", - "target": "file:src/agentkit/core/protocol.py", - "type": "imports", - "label": "导入 TaskResult" - }, - { - "id": "edge:9e41e8ef", - "source": "file:src/agentkit/core/plan_exec_engine.py", - "target": "file:src/agentkit/core/protocol.py", - "type": "imports", - "label": "导入 TaskStatus" - }, - { - "id": "edge:8dc5823d", - "source": "file:src/agentkit/core/plan_exec_engine.py", - "target": "file:src/agentkit/core/react.py", - "type": "imports", - "label": "导入 ReActEvent" - }, - { - "id": "edge:b2b399dc", - "source": "file:src/agentkit/core/plan_exec_engine.py", - "target": "file:src/agentkit/core/react.py", - "type": "imports", - "label": "导入 ReActResult" - }, - { - "id": "edge:d38deeaf", - "source": "file:src/agentkit/core/plan_exec_engine.py", - "target": "file:src/agentkit/core/react.py", - "type": "imports", - "label": "导入 ReActStep" - }, - { - "id": "edge:a739ae19", - "source": "file:src/agentkit/core/plan_exec_engine.py", - "target": "file:src/agentkit/orchestrator/reflection.py", - "type": "imports", - "label": "导入 PipelineReflector" - }, - { - "id": "edge:03bc334f", - "source": "file:src/agentkit/core/plan_exec_engine.py", - "target": "file:src/agentkit/orchestrator/reflection.py", - "type": "imports", - "label": "导入 PipelineReplanner" - }, - { - "id": "edge:aa16b7e2", - "source": "file:src/agentkit/core/plan_exec_engine.py", - "target": "file:src/agentkit/orchestrator/pipeline_schema.py", - "type": "imports", - "label": "导入 Pipeline" - }, - { - "id": "edge:8704674e", - "source": "file:src/agentkit/core/plan_exec_engine.py", - "target": "file:src/agentkit/orchestrator/pipeline_schema.py", - "type": "imports", - "label": "导入 PipelineResult" - }, - { - "id": "edge:c1fadfc8", - "source": "file:src/agentkit/core/plan_exec_engine.py", - "target": "file:src/agentkit/orchestrator/pipeline_schema.py", - "type": "imports", - "label": "导入 ReflectionReport" - }, - { - "id": "edge:02fa829c", - "source": "file:src/agentkit/core/plan_exec_engine.py", - "target": "file:src/agentkit/orchestrator/pipeline_schema.py", - "type": "imports", - "label": "导入 StageResult" - }, - { - "id": "edge:92f430ee", - "source": "file:src/agentkit/core/plan_exec_engine.py", - "target": "file:src/agentkit/orchestrator/pipeline_schema.py", - "type": "imports", - "label": "导入 StageStatus" - }, - { - "id": "edge:3d3840cc", - "source": "file:src/agentkit/core/plan_exec_engine.py", - "target": "file:src/agentkit/core/compressor.py", - "type": "imports", - "label": "导入 CompressionStrategy" - }, - { - "id": "edge:fce19bd6", - "source": "file:src/agentkit/core/plan_exec_engine.py", - "target": "file:src/agentkit/core/compressor.py", - "type": "imports", - "label": "导入 ContextCompressor" - }, - { - "id": "edge:67f9a6dd", - "source": "file:src/agentkit/core/plan_exec_engine.py", - "target": "file:src/agentkit/core/trace.py", - "type": "imports", - "label": "导入 TraceRecorder" - }, - { - "id": "edge:36ef38e1", - "source": "file:src/agentkit/core/plan_exec_engine.py", - "target": "file:src/agentkit/memory/retriever.py", - "type": "imports", - "label": "导入 MemoryRetriever" - }, - { - "id": "edge:5f854a05", - "source": "file:src/agentkit/core/plan_exec_engine.py", - "target": "file:src/agentkit/llm/gateway.py", - "type": "imports", - "label": "导入 LLMGateway" - }, - { - "id": "edge:664dfe15", - "source": "file:src/agentkit/core/plan_exec_engine.py", - "target": "file:src/agentkit/tools/base.py", - "type": "imports", - "label": "导入 Tool" - }, - { - "id": "edge:dc44ee12", - "source": "file:src/agentkit/core/plan_exec_engine.py", - "target": "file:src/agentkit/orchestrator/pipeline_schema.py", - "type": "imports", - "label": "导入 PipelineStage" - }, { "id": "edge:e1fd14ac", "source": "file:src/agentkit/core/plan_executor.py", @@ -51767,13 +49555,6 @@ "type": "imports", "label": "导入 ToolRegistry" }, - { - "id": "edge:6e703e96", - "source": "file:src/agentkit/mcp/manager.py", - "target": "file:src/agentkit/server/config.py", - "type": "imports", - "label": "导入 MCPServerConfig" - }, { "id": "edge:760974ec", "source": "file:src/agentkit/memory/__init__.py", @@ -52950,538 +50731,6 @@ "type": "imports", "label": "导入 Skill" }, - { - "id": "edge:86d67e4d", - "source": "file:src/agentkit/server/__init__.py", - "target": "file:src/agentkit/server/app.py", - "type": "imports", - "label": "导入 create_app" - }, - { - "id": "edge:584b4959", - "source": "file:src/agentkit/server/app.py", - "target": "file:src/agentkit/core/agent_pool.py", - "type": "imports", - "label": "导入 AgentPool" - }, - { - "id": "edge:635eb8c7", - "source": "file:src/agentkit/server/app.py", - "target": "file:src/agentkit/llm/gateway.py", - "type": "imports", - "label": "导入 LLMGateway" - }, - { - "id": "edge:9bc113ae", - "source": "file:src/agentkit/server/app.py", - "target": "file:src/agentkit/llm/providers/anthropic.py", - "type": "imports", - "label": "导入 AnthropicProvider" - }, - { - "id": "edge:b729ef1d", - "source": "file:src/agentkit/server/app.py", - "target": "file:src/agentkit/llm/providers/gemini.py", - "type": "imports", - "label": "导入 GeminiProvider" - }, - { - "id": "edge:37a49a5a", - "source": "file:src/agentkit/server/app.py", - "target": "file:src/agentkit/llm/providers/openai.py", - "type": "imports", - "label": "导入 OpenAICompatibleProvider" - }, - { - "id": "edge:96fe08e0", - "source": "file:src/agentkit/server/app.py", - "target": "file:src/agentkit/mcp/manager.py", - "type": "imports", - "label": "导入 MCPManager" - }, - { - "id": "edge:4474e6c3", - "source": "file:src/agentkit/server/app.py", - "target": "file:src/agentkit/quality/gate.py", - "type": "imports", - "label": "导入 QualityGate" - }, - { - "id": "edge:a85c3c17", - "source": "file:src/agentkit/server/app.py", - "target": "file:src/agentkit/quality/output.py", - "type": "imports", - "label": "导入 OutputStandardizer" - }, - { - "id": "edge:272b3062", - "source": "file:src/agentkit/server/app.py", - "target": "file:src/agentkit/router/intent.py", - "type": "imports", - "label": "导入 IntentRouter" - }, - { - "id": "edge:b832d1dd", - "source": "file:src/agentkit/server/app.py", - "target": "file:src/agentkit/skills/base.py", - "type": "imports", - "label": "导入 Skill" - }, - { - "id": "edge:4a36fa29", - "source": "file:src/agentkit/server/app.py", - "target": "file:src/agentkit/skills/base.py", - "type": "imports", - "label": "导入 SkillConfig" - }, - { - "id": "edge:52cfa2dd", - "source": "file:src/agentkit/server/app.py", - "target": "file:src/agentkit/skills/registry.py", - "type": "imports", - "label": "导入 SkillRegistry" - }, - { - "id": "edge:4625c408", - "source": "file:src/agentkit/server/app.py", - "target": "file:src/agentkit/tools/registry.py", - "type": "imports", - "label": "导入 ToolRegistry" - }, - { - "id": "edge:0e6a0499", - "source": "file:src/agentkit/server/app.py", - "target": "file:src/agentkit/tools/skill_install.py", - "type": "imports", - "label": "导入 SkillInstallTool" - }, - { - "id": "edge:d9ee5826", - "source": "file:src/agentkit/server/app.py", - "target": "file:src/agentkit/server/config.py", - "type": "imports", - "label": "导入 ServerConfig" - }, - { - "id": "edge:2b91343f", - "source": "file:src/agentkit/server/app.py", - "target": "file:src/agentkit/server/routes/__init__.py", - "type": "imports", - "label": "导入 agents" - }, - { - "id": "edge:3b50e476", - "source": "file:src/agentkit/server/app.py", - "target": "file:src/agentkit/server/routes/__init__.py", - "type": "imports", - "label": "导入 tasks" - }, - { - "id": "edge:a462c191", - "source": "file:src/agentkit/server/app.py", - "target": "file:src/agentkit/server/routes/__init__.py", - "type": "imports", - "label": "导入 skills" - }, - { - "id": "edge:0f0f25c3", - "source": "file:src/agentkit/server/app.py", - "target": "file:src/agentkit/server/routes/__init__.py", - "type": "imports", - "label": "导入 llm" - }, - { - "id": "edge:20af6a89", - "source": "file:src/agentkit/server/app.py", - "target": "file:src/agentkit/server/routes/__init__.py", - "type": "imports", - "label": "导入 health" - }, - { - "id": "edge:3daefd28", - "source": "file:src/agentkit/server/app.py", - "target": "file:src/agentkit/server/routes/__init__.py", - "type": "imports", - "label": "导入 metrics" - }, - { - "id": "edge:46a4f7d6", - "source": "file:src/agentkit/server/app.py", - "target": "file:src/agentkit/server/routes/__init__.py", - "type": "imports", - "label": "导入 ws" - }, - { - "id": "edge:f605be2a", - "source": "file:src/agentkit/server/app.py", - "target": "file:src/agentkit/server/routes/__init__.py", - "type": "imports", - "label": "导入 evolution" - }, - { - "id": "edge:2a55c107", - "source": "file:src/agentkit/server/app.py", - "target": "file:src/agentkit/server/routes/__init__.py", - "type": "imports", - "label": "导入 memory" - }, - { - "id": "edge:71ee87c6", - "source": "file:src/agentkit/server/app.py", - "target": "file:src/agentkit/server/routes/__init__.py", - "type": "imports", - "label": "导入 portal" - }, - { - "id": "edge:3cf8be0e", - "source": "file:src/agentkit/server/app.py", - "target": "file:src/agentkit/server/routes/__init__.py", - "type": "imports", - "label": "导入 evolution_dashboard" - }, - { - "id": "edge:1470f871", - "source": "file:src/agentkit/server/app.py", - "target": "file:src/agentkit/server/routes/__init__.py", - "type": "imports", - "label": "导入 kb_management" - }, - { - "id": "edge:888c3575", - "source": "file:src/agentkit/server/app.py", - "target": "file:src/agentkit/server/routes/__init__.py", - "type": "imports", - "label": "导入 skill_management" - }, - { - "id": "edge:b8780854", - "source": "file:src/agentkit/server/app.py", - "target": "file:src/agentkit/server/routes/__init__.py", - "type": "imports", - "label": "导入 workflows" - }, - { - "id": "edge:de4a2388", - "source": "file:src/agentkit/server/app.py", - "target": "file:src/agentkit/server/routes/__init__.py", - "type": "imports", - "label": "导入 chat" - }, - { - "id": "edge:ce4c282e", - "source": "file:src/agentkit/server/app.py", - "target": "file:src/agentkit/server/routes/__init__.py", - "type": "imports", - "label": "导入 terminal" - }, - { - "id": "edge:4dd885c9", - "source": "file:src/agentkit/server/app.py", - "target": "file:src/agentkit/server/routes/__init__.py", - "type": "imports", - "label": "导入 settings" - }, - { - "id": "edge:3b409b80", - "source": "file:src/agentkit/server/app.py", - "target": "file:src/agentkit/server/middleware.py", - "type": "imports", - "label": "导入 APIKeyAuthMiddleware" - }, - { - "id": "edge:fcf5a9aa", - "source": "file:src/agentkit/server/app.py", - "target": "file:src/agentkit/server/middleware.py", - "type": "imports", - "label": "导入 RateLimitMiddleware" - }, - { - "id": "edge:2f73c726", - "source": "file:src/agentkit/server/app.py", - "target": "file:src/agentkit/server/task_store.py", - "type": "imports", - "label": "导入 create_task_store" - }, - { - "id": "edge:1e55490b", - "source": "file:src/agentkit/server/app.py", - "target": "file:src/agentkit/server/runner.py", - "type": "imports", - "label": "导入 BackgroundRunner" - }, - { - "id": "edge:02707eb0", - "source": "file:src/agentkit/server/app.py", - "target": "file:src/agentkit/core/logging.py", - "type": "imports", - "label": "导入 setup_structured_logging" - }, - { - "id": "edge:aeaf0409", - "source": "file:src/agentkit/server/app.py", - "target": "file:src/agentkit/telemetry/setup.py", - "type": "imports", - "label": "导入 setup_telemetry" - }, - { - "id": "edge:0f16e81e", - "source": "file:src/agentkit/server/app.py", - "target": "file:src/agentkit/core/compressor.py", - "type": "imports", - "label": "导入 create_compressor" - }, - { - "id": "edge:e8ba6d01", - "source": "file:src/agentkit/server/app.py", - "target": "file:src/agentkit/bus/redis_bus.py", - "type": "imports", - "label": "导入 create_message_bus" - }, - { - "id": "edge:e6162d7e", - "source": "file:src/agentkit/server/app.py", - "target": "file:src/agentkit/org/context.py", - "type": "imports", - "label": "导入 OrganizationContext" - }, - { - "id": "edge:35a7f353", - "source": "file:src/agentkit/server/app.py", - "target": "file:src/agentkit/quality/alignment.py", - "type": "imports", - "label": "导入 AlignmentGuard" - }, - { - "id": "edge:0e639f42", - "source": "file:src/agentkit/server/app.py", - "target": "file:src/agentkit/quality/alignment.py", - "type": "imports", - "label": "导入 AlignmentConfig" - }, - { - "id": "edge:355f915a", - "source": "file:src/agentkit/server/app.py", - "target": "file:src/agentkit/chat/skill_routing.py", - "type": "imports", - "label": "导入 CostAwareRouter" - }, - { - "id": "edge:696ba787", - "source": "file:src/agentkit/server/app.py", - "target": "file:src/agentkit/session/manager.py", - "type": "imports", - "label": "导入 SessionManager" - }, - { - "id": "edge:fc7d1a2a", - "source": "file:src/agentkit/server/app.py", - "target": "file:src/agentkit/session/store.py", - "type": "imports", - "label": "导入 create_session_store" - }, - { - "id": "edge:d7970f24", - "source": "file:src/agentkit/server/app.py", - "target": "file:src/agentkit/core/config_driven.py", - "type": "imports", - "label": "导入 AgentConfig" - }, - { - "id": "edge:5b1f3143", - "source": "file:src/agentkit/server/app.py", - "target": "file:src/agentkit/memory/profile.py", - "type": "imports", - "label": "导入 MemoryStore" - }, - { - "id": "edge:0d6c3510", - "source": "file:src/agentkit/server/app.py", - "target": "file:src/agentkit/tools/memory_tool.py", - "type": "imports", - "label": "导入 MemoryTool" - }, - { - "id": "edge:e206f97b", - "source": "file:src/agentkit/server/app.py", - "target": "file:src/agentkit/tools/shell.py", - "type": "imports", - "label": "导入 ShellTool" - }, - { - "id": "edge:33f76b63", - "source": "file:src/agentkit/server/app.py", - "target": "file:src/agentkit/tools/web_search.py", - "type": "imports", - "label": "导入 WebSearchTool" - }, - { - "id": "edge:5191fb7f", - "source": "file:src/agentkit/server/app.py", - "target": "file:src/agentkit/tools/web_crawl.py", - "type": "imports", - "label": "导入 WebCrawlTool" - }, - { - "id": "edge:b2729f09", - "source": "file:src/agentkit/server/app.py", - "target": "file:src/agentkit/tools/baidu_search.py", - "type": "imports", - "label": "导入 BaiduSearchTool" - }, - { - "id": "edge:2d7f5ad1", - "source": "file:src/agentkit/server/app.py", - "target": "file:src/agentkit/llm/providers/usage_store.py", - "type": "imports", - "label": "导入 create_usage_store" - }, - { - "id": "edge:d79e762a", - "source": "file:src/agentkit/server/app.py", - "target": "file:src/agentkit/skills/loader.py", - "type": "imports", - "label": "导入 SkillLoader" - }, - { - "id": "edge:09b4d41b", - "source": "file:src/agentkit/server/app.py", - "target": "file:src/agentkit/core/headroom_compressor.py", - "type": "imports", - "label": "导入 HeadroomCompressor" - }, - { - "id": "edge:50130d5e", - "source": "file:src/agentkit/server/app.py", - "target": "file:src/agentkit/chat/semantic_router.py", - "type": "imports", - "label": "导入 SemanticRouter" - }, - { - "id": "edge:2b8c9689", - "source": "file:src/agentkit/server/app.py", - "target": "file:src/agentkit/evolution/evolution_store.py", - "type": "imports", - "label": "导入 create_evolution_store" - }, - { - "id": "edge:5aaf0234", - "source": "file:src/agentkit/server/app.py", - "target": "file:src/agentkit/quality/cascade_state_store.py", - "type": "imports", - "label": "导入 create_cascade_state_store" - }, - { - "id": "edge:6e426a18", - "source": "file:src/agentkit/server/app.py", - "target": "file:src/agentkit/memory/retriever.py", - "type": "imports", - "label": "导入 MemoryRetriever" - }, - { - "id": "edge:0b7e38da", - "source": "file:src/agentkit/server/app.py", - "target": "file:src/agentkit/memory/working.py", - "type": "imports", - "label": "导入 WorkingMemory" - }, - { - "id": "edge:61c10022", - "source": "file:src/agentkit/server/app.py", - "target": "file:src/agentkit/memory/semantic.py", - "type": "imports", - "label": "导入 SemanticMemory" - }, - { - "id": "edge:dc00427a", - "source": "file:src/agentkit/server/app.py", - "target": "file:src/agentkit/memory/http_rag.py", - "type": "imports", - "label": "导入 HttpRAGService" - }, - { - "id": "edge:19fac287", - "source": "file:src/agentkit/server/app.py", - "target": "file:src/agentkit/memory/profile.py", - "type": "imports", - "label": "导入 MemoryStore" - }, - { - "id": "edge:91523015", - "source": "file:src/agentkit/server/app.py", - "target": "file:src/agentkit/tools/headroom_retrieve.py", - "type": "imports", - "label": "导入 HeadroomRetrieveTool" - }, - { - "id": "edge:69fde1c5", - "source": "file:src/agentkit/server/app.py", - "target": "file:src/agentkit/memory/episodic.py", - "type": "imports", - "label": "导入 EpisodicMemory" - }, - { - "id": "edge:cff4ce5d", - "source": "file:src/agentkit/server/app.py", - "target": "file:src/agentkit/memory/embedder.py", - "type": "imports", - "label": "导入 OpenAIEmbedder" - }, - { - "id": "edge:e5caa12d", - "source": "file:src/agentkit/server/app.py", - "target": "file:src/agentkit/memory/embedder.py", - "type": "imports", - "label": "导入 EmbeddingCache" - }, - { - "id": "edge:15076481", - "source": "file:src/agentkit/server/app.py", - "target": "file:src/agentkit/memory/models.py", - "type": "imports", - "label": "导入 EpisodeModel" - }, - { - "id": "edge:30fb9dcd", - "source": "file:src/agentkit/server/app.py", - "target": "file:src/agentkit/memory/models.py", - "type": "imports", - "label": "导入 create_episodic_session_factory" - }, - { - "id": "edge:aa9f8979", - "source": "file:src/agentkit/server/app.py", - "target": "file:src/agentkit/skills/loader.py", - "type": "imports", - "label": "导入 SkillLoader" - }, - { - "id": "edge:30f837f3", - "source": "file:src/agentkit/server/config.py", - "target": "file:src/agentkit/llm/config.py", - "type": "imports", - "label": "导入 LLMConfig" - }, - { - "id": "edge:acd5627b", - "source": "file:src/agentkit/server/config.py", - "target": "file:src/agentkit/llm/config.py", - "type": "imports", - "label": "导入 ProviderConfig" - }, - { - "id": "edge:46ee0dd3", - "source": "file:src/agentkit/server/config.py", - "target": "file:src/agentkit/skills/base.py", - "type": "imports", - "label": "导入 SkillConfig" - }, - { - "id": "edge:8b328dee", - "source": "file:src/agentkit/server/config.py", - "target": "file:src/agentkit/llm/config.py", - "type": "imports", - "label": "导入 CacheConfig" - }, { "id": "edge:c9d5beab", "source": "file:src/agentkit/server/routes/__init__.py", @@ -53601,48 +50850,6 @@ "type": "imports", "label": "导入 SkillConfig" }, - { - "id": "edge:23f3e739", - "source": "file:src/agentkit/server/routes/chat.py", - "target": "file:src/agentkit/core/protocol.py", - "type": "imports", - "label": "导入 CancellationToken" - }, - { - "id": "edge:a6ee5a6e", - "source": "file:src/agentkit/server/routes/chat.py", - "target": "file:src/agentkit/core/react.py", - "type": "imports", - "label": "导入 ReActEngine" - }, - { - "id": "edge:1e26333b", - "source": "file:src/agentkit/server/routes/chat.py", - "target": "file:src/agentkit/session/manager.py", - "type": "imports", - "label": "导入 SessionManager" - }, - { - "id": "edge:df686b6c", - "source": "file:src/agentkit/server/routes/chat.py", - "target": "file:src/agentkit/session/models.py", - "type": "imports", - "label": "导入 MessageRole" - }, - { - "id": "edge:9adb5477", - "source": "file:src/agentkit/server/routes/chat.py", - "target": "file:src/agentkit/session/models.py", - "type": "imports", - "label": "导入 SessionStatus" - }, - { - "id": "edge:76254760", - "source": "file:src/agentkit/server/routes/chat.py", - "target": "file:src/agentkit/chat/skill_routing.py", - "type": "imports", - "label": "导入 resolve_skill_routing" - }, { "id": "edge:62fbad94", "source": "file:src/agentkit/server/routes/evolution.py", @@ -53678,13 +50885,6 @@ "type": "imports", "label": "导入 ReActEngine" }, - { - "id": "edge:6931899e", - "source": "file:src/agentkit/server/routes/portal.py", - "target": "file:src/agentkit/chat/skill_routing.py", - "type": "imports", - "label": "导入 ExecutionMode" - }, { "id": "edge:8c887346", "source": "file:src/agentkit/server/routes/portal.py", @@ -54874,6 +52074,300 @@ "target": "file:src/agentkit/tools/base.py", "type": "imports", "label": "导入 Tool" + }, + { + "source": "class:src/agentkit/core/plan_exec_engine.py:PlanExecEngine", + "target": "class:src/agentkit/core/goal_planner.py:GoalPlanner", + "type": "depends_on", + "weight": 0.8 + }, + { + "source": "class:src/agentkit/core/plan_exec_engine.py:PlanExecEngine", + "target": "class:src/agentkit/core/plan_exec_engine.py:ReActStepExecutor", + "type": "creates", + "weight": 0.7 + }, + { + "source": "class:src/agentkit/core/plan_exec_engine.py:ReActStepExecutor", + "target": "class:src/agentkit/core/plan_exec_engine.py:_ReActStepAgent", + "type": "creates", + "weight": 0.7 + }, + { + "source": "class:src/agentkit/core/plan_exec_engine.py:_ReActStepAgent", + "target": "file:src/agentkit/core/react.py", + "type": "imports", + "weight": 0.7 + }, + { + "source": "class:src/agentkit/core/plan_exec_engine.py:PlanExecEngine", + "target": "file:src/agentkit/core/shared_workspace.py", + "type": "imports", + "weight": 0.7 + }, + { + "source": "class:src/agentkit/experts/orchestrator.py:TeamOrchestrator", + "target": "class:src/agentkit/experts/team.py:ExpertTeam", + "type": "depends_on", + "weight": 0.8 + }, + { + "source": "class:src/agentkit/experts/orchestrator.py:TeamOrchestrator", + "target": "class:src/agentkit/experts/plan.py:CollaborationPlan", + "type": "depends_on", + "weight": 0.8 + }, + { + "source": "class:src/agentkit/experts/orchestrator.py:TeamOrchestrator", + "target": "class:src/agentkit/experts/expert.py:Expert", + "type": "calls", + "weight": 0.8 + }, + { + "source": "class:src/agentkit/experts/orchestrator.py:TeamOrchestrator", + "target": "file:src/agentkit/core/shared_workspace.py", + "type": "imports", + "weight": 0.7 + }, + { + "source": "class:src/agentkit/experts/orchestrator.py:TeamOrchestrator", + "target": "class:src/agentkit/experts/plan.py:MergeStrategy", + "type": "uses", + "weight": 0.6 + }, + { + "source": "class:src/agentkit/experts/orchestrator.py:TeamOrchestrator", + "target": "class:src/agentkit/experts/plan.py:ParallelType", + "type": "uses", + "weight": 0.6 + }, + { + "source": "class:src/agentkit/experts/team.py:ExpertTeam", + "target": "class:src/agentkit/experts/expert.py:Expert", + "type": "contains", + "weight": 1.0 + }, + { + "source": "class:src/agentkit/experts/team.py:ExpertTeam", + "target": "class:src/agentkit/experts/config.py:ExpertConfig", + "type": "uses", + "weight": 0.6 + }, + { + "source": "class:src/agentkit/experts/team.py:ExpertTeam", + "target": "class:src/agentkit/experts/plan.py:CollaborationPlan", + "type": "uses", + "weight": 0.6 + }, + { + "source": "class:src/agentkit/experts/team.py:ExpertTeam", + "target": "file:src/agentkit/core/shared_workspace.py", + "type": "imports", + "weight": 0.7 + }, + { + "source": "class:src/agentkit/experts/expert.py:Expert", + "target": "class:src/agentkit/experts/config.py:ExpertConfig", + "type": "contains", + "weight": 1.0 + }, + { + "source": "class:src/agentkit/experts/expert.py:Expert", + "target": "file:src/agentkit/core/config_driven.py", + "type": "imports", + "weight": 0.7 + }, + { + "source": "class:src/agentkit/experts/router.py:ExpertTeamRouter", + "target": "class:src/agentkit/experts/registry.py:ExpertTemplateRegistry", + "type": "uses", + "weight": 0.6 + }, + { + "source": "class:src/agentkit/chat/skill_routing.py:CostAwareRouter", + "target": "class:src/agentkit/experts/router.py:ExpertTeamRouter", + "type": "depends_on", + "weight": 0.8 + }, + { + "source": "file:src/agentkit/server/routes/chat.py", + "target": "file:src/agentkit/chat/skill_routing.py", + "type": "imports", + "weight": 0.7 + }, + { + "source": "file:src/agentkit/server/routes/chat.py", + "target": "file:src/agentkit/core/react.py", + "type": "imports", + "weight": 0.7 + }, + { + "source": "file:src/agentkit/server/app.py", + "target": "file:src/agentkit/server/config.py", + "type": "imports", + "weight": 0.7 + }, + { + "source": "file:src/agentkit/server/app.py", + "target": "file:src/agentkit/server/middleware.py", + "type": "imports", + "weight": 0.7 + }, + { + "source": "file:src/agentkit/server/frontend/src/stores/chat.ts", + "target": "file:src/agentkit/server/frontend/src/stores/team.ts", + "type": "imports", + "weight": 0.7 + }, + { + "source": "file:src/agentkit/server/frontend/src/components/chat/ExpertTeamView.vue", + "target": "file:src/agentkit/server/frontend/src/stores/team.ts", + "type": "imports", + "weight": 0.7 + }, + { + "source": "file:src/agentkit/server/frontend/src/components/chat/PlanVisualization.vue", + "target": "file:src/agentkit/server/frontend/src/stores/team.ts", + "type": "imports", + "weight": 0.7 + }, + { + "source": "file:src/agentkit/server/frontend/src/views/ChatView.vue", + "target": "file:src/agentkit/server/frontend/src/stores/chat.ts", + "type": "imports", + "weight": 0.7 + }, + { + "source": "file:src/agentkit/server/frontend/src/views/ChatView.vue", + "target": "file:src/agentkit/server/frontend/src/components/chat/ExpertTeamView.vue", + "type": "imports", + "weight": 0.7 + }, + { + "source": "file:tests/unit/experts/test_team_orchestrator.py", + "target": "class:src/agentkit/experts/orchestrator.py:TeamOrchestrator", + "type": "tested_by", + "weight": 0.5 + }, + { + "source": "file:tests/unit/core/test_autonomous_research_task.py", + "target": "class:src/agentkit/core/plan_exec_engine.py:PlanExecEngine", + "type": "tested_by", + "weight": 0.5 + }, + { + "source": "file:tests/unit/experts/test_team.py", + "target": "class:src/agentkit/experts/team.py:ExpertTeam", + "type": "tested_by", + "weight": 0.5 + }, + { + "source": "file:src/agentkit/core/plan_exec_engine.py", + "target": "class:src/agentkit/core/plan_exec_engine.py:PlanExecEngine", + "type": "contains", + "weight": 1.0 + }, + { + "source": "file:src/agentkit/core/plan_exec_engine.py", + "target": "class:src/agentkit/core/plan_exec_engine.py:ReActStepExecutor", + "type": "contains", + "weight": 1.0 + }, + { + "source": "file:src/agentkit/core/plan_exec_engine.py", + "target": "class:src/agentkit/core/plan_exec_engine.py:_ReActStepAgent", + "type": "contains", + "weight": 1.0 + }, + { + "source": "file:src/agentkit/core/goal_planner.py", + "target": "class:src/agentkit/core/goal_planner.py:GoalPlanner", + "type": "contains", + "weight": 1.0 + }, + { + "source": "file:src/agentkit/experts/orchestrator.py", + "target": "class:src/agentkit/experts/orchestrator.py:TeamOrchestrator", + "type": "contains", + "weight": 1.0 + }, + { + "source": "file:src/agentkit/experts/team.py", + "target": "class:src/agentkit/experts/team.py:ExpertTeam", + "type": "contains", + "weight": 1.0 + }, + { + "source": "file:src/agentkit/experts/team.py", + "target": "class:src/agentkit/experts/team.py:TeamStatus", + "type": "contains", + "weight": 1.0 + }, + { + "source": "file:src/agentkit/experts/router.py", + "target": "class:src/agentkit/experts/router.py:ExpertTeamRouter", + "type": "contains", + "weight": 1.0 + }, + { + "source": "file:src/agentkit/experts/config.py", + "target": "class:src/agentkit/experts/config.py:ExpertConfig", + "type": "contains", + "weight": 1.0 + }, + { + "source": "file:src/agentkit/experts/config.py", + "target": "class:src/agentkit/experts/config.py:ExpertTemplate", + "type": "contains", + "weight": 1.0 + }, + { + "source": "file:src/agentkit/experts/expert.py", + "target": "class:src/agentkit/experts/expert.py:Expert", + "type": "contains", + "weight": 1.0 + }, + { + "source": "file:src/agentkit/experts/plan.py", + "target": "class:src/agentkit/experts/plan.py:CollaborationPlan", + "type": "contains", + "weight": 1.0 + }, + { + "source": "file:src/agentkit/experts/plan.py", + "target": "class:src/agentkit/experts/plan.py:PlanPhase", + "type": "contains", + "weight": 1.0 + }, + { + "source": "file:src/agentkit/experts/plan.py", + "target": "class:src/agentkit/experts/plan.py:MergeStrategy", + "type": "contains", + "weight": 1.0 + }, + { + "source": "file:src/agentkit/experts/plan.py", + "target": "class:src/agentkit/experts/plan.py:ParallelType", + "type": "contains", + "weight": 1.0 + }, + { + "source": "file:src/agentkit/experts/registry.py", + "target": "class:src/agentkit/experts/registry.py:ExpertTemplateRegistry", + "type": "contains", + "weight": 1.0 + }, + { + "source": "file:src/agentkit/chat/skill_routing.py", + "target": "class:src/agentkit/chat/skill_routing.py:CostAwareRouter", + "type": "contains", + "weight": 1.0 + }, + { + "source": "file:src/agentkit/server/config.py", + "target": "class:src/agentkit/server/config.py:ServerConfig", + "type": "contains", + "weight": 1.0 } ], "tours": [ diff --git a/.understand-anything/meta.json b/.understand-anything/meta.json index 7353a48..50e97f2 100644 --- a/.understand-anything/meta.json +++ b/.understand-anything/meta.json @@ -1,6 +1,6 @@ { - "lastAnalyzedAt": "2026-06-14T10:00:00.000000+00:00", - "gitCommitHash": "d9d1b16e5911ad958cd8ae38958058bea13f3fcc", + "lastAnalyzedAt": "2026-06-15T06:01:34.200955+00:00", + "gitCommitHash": "64d62a2b60c57fbb1844c1f46c541234c8f9d871", "version": "1.0.0", - "analyzedFiles": 208 -} + "analyzedFiles": 2416 +} \ No newline at end of file diff --git a/agentkit.yaml b/agentkit.yaml index 5211ad8..4d77882 100644 --- a/agentkit.yaml +++ b/agentkit.yaml @@ -5,12 +5,22 @@ server: rate_limit: 60 llm: providers: - test: + bailian-coding: type: openai - base_url: '' - max_tokens: 4096 - timeout: 120.0 - api_key: '' + base_url: https://coding.dashscope.aliyuncs.com/v1 + api_key: "${DASHSCOPE_API_KEY}" + models: + qwen3.7-plus: {alias: default} + qwen3-coder-plus: {alias: coding} + qwen3-max-2026-01-23: {alias: powerful} + qwen-turbo: {alias: fast} + deepseek: + type: openai + base_url: https://api.deepseek.com/v1 + api_key: "${DEEPSEEK_API_KEY}" + models: + deepseek-chat: {alias: chat} + deepseek-reasoner: {alias: reasoning} model_aliases: default: bailian-coding/qwen3.7-plus fast: bailian-coding/qwen-turbo @@ -18,23 +28,9 @@ llm: coding: bailian-coding/qwen3-coder-plus chat: deepseek/deepseek-chat reasoning: deepseek/deepseek-reasoner -session: - backend: memory -bus: - backend: memory -task_store: - backend: memory -skills: - auto_discover: true - paths: - - ./configs/skills -logging: - level: INFO - format: text -router: - classifier: heuristic - auction_enabled: false - semantic: - enabled: true - similarity_high: 0.85 - similarity_low: 0.4 +session: {backend: memory} +bus: {backend: memory} +task_store: {backend: memory} +skills: {auto_discover: true, paths: ["./configs/skills"]} +logging: {level: INFO, format: text} +router: {classifier: heuristic, auction_enabled: false} diff --git a/configs/geo_server.py b/configs/geo_server.py index 65a89fb..9f25f34 100644 --- a/configs/geo_server.py +++ b/configs/geo_server.py @@ -15,7 +15,7 @@ import os from fastapi import FastAPI from agentkit.server.app import _build_llm_gateway, create_app -from agentkit.server.config import ServerConfig +from agentkit.server.config import ServerConfig, find_config_path, load_config_with_dotenv from agentkit.skills.loader import SkillLoader from agentkit.skills.registry import SkillRegistry from agentkit.tools.registry import ToolRegistry @@ -27,16 +27,13 @@ logger = logging.getLogger(__name__) CONFIGS_DIR = os.path.dirname(os.path.abspath(__file__)) SKILLS_DIR = os.path.join(CONFIGS_DIR, "skills") -# 查找 agentkit.yaml:项目根目录 > configs 目录 -_PROJECT_ROOT = os.path.dirname(CONFIGS_DIR) -_AGENTKIT_YAML = os.path.join(_PROJECT_ROOT, "agentkit.yaml") - def _load_server_config() -> ServerConfig: - """Load ServerConfig from agentkit.yaml with env var resolution.""" - if os.path.isfile(_AGENTKIT_YAML): - return ServerConfig.from_yaml(_AGENTKIT_YAML) - raise FileNotFoundError(f"agentkit.yaml not found at {_AGENTKIT_YAML}") + """Load ServerConfig from agentkit.yaml with .env resolution.""" + config_path = find_config_path() + if config_path: + return load_config_with_dotenv(config_path) + raise FileNotFoundError("agentkit.yaml not found (searched CWD and ~/.agentkit/)") def _init_tool_registry() -> ToolRegistry: diff --git a/src/agentkit/cli/chat.py b/src/agentkit/cli/chat.py index 8bdbdcd..40b316b 100644 --- a/src/agentkit/cli/chat.py +++ b/src/agentkit/cli/chat.py @@ -46,7 +46,7 @@ async def _chat_async( ) -> None: """Async implementation of the chat command.""" from agentkit.cli.onboarding import run_onboarding - from agentkit.server.config import ServerConfig, find_config_path + from agentkit.server.config import find_config_path # ── Onboarding check ────────────────────────────────────────── config_path = find_config_path(config_arg) @@ -59,14 +59,9 @@ async def _chat_async( # ── Load config ─────────────────────────────────────────────── rprint(f"[dim]Loading config from {config_path}[/dim]") - # Load .env - from pathlib import Path + from agentkit.server.config import load_config_with_dotenv - dotenv = Path(config_path).parent / ".env" - if dotenv.exists(): - _load_dotenv(str(dotenv)) - - server_config = ServerConfig.from_yaml(config_path) + server_config = load_config_with_dotenv(config_path) # ── Build in-process components ─────────────────────────────── from agentkit.session.manager import SessionManager @@ -380,27 +375,6 @@ def _resolve_default_model(server_config: "ServerConfig") -> str: return "default" -def _load_dotenv(dotenv_path: str) -> None: - """Load .env file into environment.""" - from pathlib import Path - - path = Path(dotenv_path) - if not path.exists(): - return - with open(path, encoding="utf-8") as f: - for line in f: - line = line.strip() - if not line or line.startswith("#"): - continue - if "=" not in line: - continue - key, _, value = line.partition("=") - key = key.strip() - value = value.strip().strip("\"'") - if key and key not in os.environ: - os.environ[key] = value - - def _print_help() -> None: """Print chat command help.""" rprint( diff --git a/src/agentkit/cli/main.py b/src/agentkit/cli/main.py index b1e8050..483e6a9 100644 --- a/src/agentkit/cli/main.py +++ b/src/agentkit/cli/main.py @@ -12,21 +12,27 @@ app = typer.Typer( ) from agentkit.cli.task import task_app # noqa: E402 + app.add_typer(task_app, name="task") from agentkit.cli.skill import skill_app # noqa: E402 + app.add_typer(skill_app, name="skill") from agentkit.cli.init import init # noqa: E402 + app.command(name="init")(init) from agentkit.cli.usage import usage # noqa: E402 + app.command(name="usage")(usage) from agentkit.cli.pair import pair # noqa: E402 + app.command(name="pair")(pair) from agentkit.cli.chat import chat # noqa: E402 + app.command(name="chat")(chat) @@ -39,11 +45,10 @@ def gui( ): """Start AgentKit with a web UI for chatting with your Agent""" import os - import sys import webbrowser import uvicorn - from agentkit.server.config import ServerConfig, find_config_path + from agentkit.server.config import find_config_path, load_config_with_dotenv from agentkit.cli.onboarding import run_onboarding # When port=0, default to localhost for security (desktop client mode) @@ -56,6 +61,7 @@ def gui( if config_path is None: rprint("[yellow]No agentkit.yaml found.[/yellow]") from rich.prompt import Confirm + if Confirm.ask("Would you like to run the setup wizard?", default=True): config_path = run_onboarding(config_arg=config) if config_path is None: @@ -66,12 +72,7 @@ def gui( server_config = None if config_path: rprint(f"[green]Loading config from {config_path}[/green]") - server_config = ServerConfig.from_yaml(config_path) - - from pathlib import Path - dotenv = Path(config_path).parent / ".env" - server_config.load_dotenv(str(dotenv)) - server_config = ServerConfig.from_yaml(config_path) + server_config = load_config_with_dotenv(config_path) os.environ["AGENTKIT_CONFIG_PATH"] = config_path @@ -79,14 +80,15 @@ def gui( if not server_config.has_llm_provider(): rprint("[yellow]No LLM API key configured.[/yellow]") from rich.prompt import Confirm + if Confirm.ask("Would you like to run the setup wizard?", default=True): config_path = run_onboarding(config_arg=config) if config_path is None: - rprint("[red]Setup cancelled. GUI may not function correctly without API key.[/red]") + rprint( + "[red]Setup cancelled. GUI may not function correctly without API key.[/red]" + ) else: - server_config = ServerConfig.from_yaml(config_path) - server_config.load_dotenv(str(dotenv)) - server_config = ServerConfig.from_yaml(config_path) + server_config = load_config_with_dotenv(config_path) os.environ["AGENTKIT_CONFIG_PATH"] = config_path else: rprint("[dim]Continuing without LLM provider — chat will not work.[/dim]") @@ -101,15 +103,19 @@ def gui( if not no_open and browser_url: import threading + def _open_browser(): import time + time.sleep(2.0) webbrowser.open(browser_url) + threading.Thread(target=_open_browser, daemon=True).start() # Create app directly (not factory mode) so server_config with resolved API keys # is passed through without relying on env var inheritance in multiprocessing. from agentkit.server.app import create_app + app = create_app(server_config=server_config) if port == 0: @@ -152,14 +158,20 @@ def serve( workers: int = typer.Option(1, "--workers", help="Number of workers"), reload: bool = typer.Option(False, "--reload", help="Enable auto-reload"), config: Optional[str] = typer.Option(None, "--config", help="Path to agentkit.yaml"), - task_store_backend: Optional[str] = typer.Option(None, "--task-store-backend", help="Task store backend: memory or redis"), - task_store_redis_url: Optional[str] = typer.Option(None, "--task-store-redis-url", help="Redis URL for task store (only used when backend=redis)"), + task_store_backend: Optional[str] = typer.Option( + None, "--task-store-backend", help="Task store backend: memory or redis" + ), + task_store_redis_url: Optional[str] = typer.Option( + None, + "--task-store-redis-url", + help="Redis URL for task store (only used when backend=redis)", + ), ): """Start the AgentKit server""" import uvicorn - from agentkit.server.config import ServerConfig, find_config_path - from agentkit.cli.onboarding import needs_onboarding, run_onboarding + from agentkit.server.config import find_config_path, load_config_with_dotenv + from agentkit.cli.onboarding import run_onboarding # Load .env file if present config_path = find_config_path(config) @@ -168,6 +180,7 @@ def serve( if config_path is None: rprint("[yellow]No agentkit.yaml found.[/yellow]") from rich.prompt import Confirm + if Confirm.ask("Would you like to run the setup wizard?", default=True): config_path = run_onboarding(config_arg=config) if config_path is None: @@ -177,28 +190,21 @@ def serve( if config_path: rprint(f"[green]Loading config from {config_path}[/green]") - server_config = ServerConfig.from_yaml(config_path) - - # Load .env file for env var resolution - from pathlib import Path - dotenv = Path(config_path).parent / ".env" - server_config.load_dotenv(str(dotenv)) - - # Re-load config after .env is loaded (env vars now available) - server_config = ServerConfig.from_yaml(config_path) + server_config = load_config_with_dotenv(config_path) # Check if LLM API key is configured if not server_config.has_llm_provider(): rprint("[yellow]No LLM API key configured.[/yellow]") from rich.prompt import Confirm + if Confirm.ask("Would you like to run the setup wizard?", default=True): config_path = run_onboarding(config_arg=config) if config_path is None: - rprint("[red]Setup cancelled. Server may not function correctly without API key.[/red]") + rprint( + "[red]Setup cancelled. Server may not function correctly without API key.[/red]" + ) else: - server_config = ServerConfig.from_yaml(config_path) - server_config.load_dotenv(str(dotenv)) - server_config = ServerConfig.from_yaml(config_path) + server_config = load_config_with_dotenv(config_path) else: rprint("[dim]Continuing without LLM provider — API calls will fail.[/dim]") @@ -216,6 +222,7 @@ def serve( # Store config for app factory import os import json as _json + os.environ["AGENTKIT_CONFIG_PATH"] = config_path # Pass task_store overrides via env var so create_app can read them if server_config.task_store: @@ -233,6 +240,7 @@ def serve( # Apply CLI task_store overrides even without config file import os import json as _json + ts_override: dict = {} if task_store_backend is not None: ts_override["backend"] = task_store_backend @@ -258,6 +266,7 @@ def version(): """Show AgentKit version""" try: from importlib.metadata import version as get_version + v = get_version("fischer-agentkit") except Exception: v = "0.1.0 (dev)" diff --git a/src/agentkit/cli/onboarding.py b/src/agentkit/cli/onboarding.py index ea02197..f40c329 100644 --- a/src/agentkit/cli/onboarding.py +++ b/src/agentkit/cli/onboarding.py @@ -109,8 +109,18 @@ PROVIDER_PRESETS: dict[str, dict[str, Any]] = { def needs_onboarding(config_arg: str | None = None) -> bool: - """Check if onboarding is needed (no config file found).""" - return find_config_path(config_arg) is None + """Check if onboarding is needed (no config file found or no valid LLM provider).""" + config_path = find_config_path(config_arg) + if config_path is None: + return True + # Config exists but has no valid LLM provider — needs onboarding to add one + from agentkit.server.config import load_config_with_dotenv + + try: + config = load_config_with_dotenv(config_path) + return not config.has_llm_provider() + except Exception: + return True def run_onboarding( @@ -119,20 +129,48 @@ def run_onboarding( ) -> str | None: """Run the interactive onboarding wizard. - Returns: - Path to the generated config file, or None if cancelled. - """ - rprint(Panel( - "[bold]Welcome to AgentKit![/bold]\n\n" - "No configuration file found. Let's set up your first Agent.\n" - "This will create [cyan]agentkit.yaml[/cyan] and [cyan].env[/cyan] for you.", - title="AgentKit Setup", - border_style="bright_blue", - )) + If agentkit.yaml already exists, only the LLM section is updated + (preserving all other settings). If it doesn't exist, a full config + is generated. - output_path = Path(output_dir).resolve() + Returns: + Path to the generated/updated config file, or None if cancelled. + """ + # Determine output directory from config_arg if provided + if config_arg: + output_path = Path(config_arg).resolve().parent + else: + output_path = Path(output_dir).resolve() output_path.mkdir(parents=True, exist_ok=True) + existing_config_path = find_config_path(config_arg) + existing_config: dict[str, Any] | None = None + if existing_config_path: + with open(existing_config_path, encoding="utf-8") as f: + existing_config = yaml.safe_load(f) or {} + + if existing_config: + rprint( + Panel( + "[bold]AgentKit Configuration Update[/bold]\n\n" + "An [cyan]agentkit.yaml[/cyan] already exists but has no valid LLM provider.\n" + "This wizard will [green]update[/green] the LLM section while preserving\n" + "your existing settings.", + title="AgentKit Setup", + border_style="bright_blue", + ) + ) + else: + rprint( + Panel( + "[bold]Welcome to AgentKit![/bold]\n\n" + "No configuration file found. Let's set up your first Agent.\n" + "This will create [cyan]agentkit.yaml[/cyan] and [cyan].env[/cyan] for you.", + title="AgentKit Setup", + border_style="bright_blue", + ) + ) + # ── Step 1: Choose LLM provider ────────────────────────────── rprint("\n[bold]Step 1: Choose your LLM provider[/bold]") provider_keys = list(PROVIDER_PRESETS.keys()) @@ -169,12 +207,16 @@ def run_onboarding( for i, model in enumerate(available_models, 1): alias = preset["models"][model].get("alias", "") alias_str = f" [dim]({alias})[/dim]" if alias else "" - recommended = " [green]← recommended[/green]" if model == preset.get("default_model") else "" + recommended = ( + " [green]← recommended[/green]" if model == preset.get("default_model") else "" + ) rprint(f" [cyan]{i}[/cyan]. {model}{alias_str}{recommended}") model_choice = Prompt.ask( "Select default model", choices=[str(i) for i in range(1, len(available_models) + 1)], - default=str(available_models.index(preset.get("default_model", available_models[0])) + 1), + default=str( + available_models.index(preset.get("default_model", available_models[0])) + 1 + ), ) selected_model = available_models[int(model_choice) - 1] # Rebuild models dict: selected model gets "default" alias @@ -184,7 +226,9 @@ def run_onboarding( updated_models[model] = {**conf, "alias": "default"} else: # Remove "default" alias from other models - updated_models[model] = {k: v for k, v in conf.items() if k != "alias" or v != "default"} + updated_models[model] = { + k: v for k, v in conf.items() if k != "alias" or v != "default" + } preset = {**preset, "models": updated_models} rprint(f"[green]Selected: {selected_model}[/green]") else: @@ -200,7 +244,11 @@ def run_onboarding( "models": preset["models"], } } - model_aliases: dict[str, str] = {alias: f"{selected_key}/{model}" for model, conf in preset["models"].items() if (alias := conf.get("alias"))} + model_aliases: dict[str, str] = { + alias: f"{selected_key}/{model}" + for model, conf in preset["models"].items() + if (alias := conf.get("alias")) + } if Confirm.ask("\nWould you like to add a second LLM provider (for fallback)?", default=False): remaining = [k for k in provider_keys if k != selected_key] @@ -228,38 +276,47 @@ def run_onboarding( if alias and alias not in model_aliases: model_aliases[alias] = f"{key2}/{model}" - # ── Step 4: Generate config files ───────────────────────────── + # ── Step 4: Generate/update config files ───────────────────────── rprint("\n[bold]Step 3: Generating configuration...[/bold]") - config = { - "server": { - "host": "0.0.0.0", - "port": 8001, - "workers": 1, - "rate_limit": 60, - }, - "llm": { - "providers": providers_config, - "model_aliases": model_aliases, - }, - "session": { - "backend": "memory", - }, - "bus": { - "backend": "memory", - }, - "task_store": { - "backend": "memory", - }, - "skills": { - "auto_discover": True, - "paths": ["./skills"], - }, - "logging": { - "level": "INFO", - "format": "text", - }, - } + if existing_config: + # Merge: only update LLM section, preserve everything else + if "llm" not in existing_config: + existing_config["llm"] = {} + existing_config["llm"]["providers"] = providers_config + existing_config["llm"]["model_aliases"] = model_aliases + config = existing_config + else: + # New config — generate full template + config = { + "server": { + "host": "0.0.0.0", + "port": 8001, + "workers": 1, + "rate_limit": 60, + }, + "llm": { + "providers": providers_config, + "model_aliases": model_aliases, + }, + "session": { + "backend": "memory", + }, + "bus": { + "backend": "memory", + }, + "task_store": { + "backend": "memory", + }, + "skills": { + "auto_discover": True, + "paths": ["./configs/skills"], + }, + "logging": { + "level": "INFO", + "format": "text", + }, + } # Write agentkit.yaml config_path = output_path / "agentkit.yaml" @@ -267,14 +324,28 @@ def run_onboarding( yaml.dump(config, f, default_flow_style=False, allow_unicode=True, sort_keys=False) rprint(f" [green]Created:[/green] {config_path}") - # Write .env + # Write .env (merge with existing) env_path = output_path / ".env" - env_lines = [f"{k}={v}" for k, v in env_vars.items()] + existing_env: dict[str, str] = {} + existing_env_lines: list[str] = [] + if env_path.exists(): + with open(env_path, encoding="utf-8") as f: + existing_env_lines = f.readlines() + for line in existing_env_lines: + stripped = line.strip() + if stripped and not stripped.startswith("#") and "=" in stripped: + k, _, v = stripped.partition("=") + existing_env[k.strip()] = v.strip().strip("\"'") + + # Merge new env vars (new values take precedence) + existing_env.update(env_vars) + with open(env_path, "w", encoding="utf-8") as f: f.write("# AgentKit Environment Variables\n") f.write("# Generated by onboarding wizard\n\n") - f.write("\n".join(env_lines) + "\n") - rprint(f" [green]Created:[/green] {env_path}") + for k, v in existing_env.items(): + f.write(f"{k}={v}\n") + rprint(f" [green]Updated:[/green] {env_path}") # ── Step 4: Agent personality (optional) ────────────────────── rprint("\n[bold]Step 4: Customize your Agent (optional)[/bold]") @@ -286,6 +357,7 @@ def run_onboarding( # Create SOUL.md from agentkit.memory.profile import MemoryStore + memory_store = MemoryStore(base_dir=Path.home() / ".agentkit") soul_content = f"""## 身份 我是{agent_name},一个专业的 AI 助手。 @@ -304,12 +376,14 @@ def run_onboarding( memory_store.get_file("soul").write(soul_content.strip()) rprint(" [green]Created:[/green] ~/.agentkit/SOUL.md") - rprint(Panel( - "[bold green]Setup complete![/bold green]\n\n" - "You can now run:\n" - " [cyan]agentkit chat[/cyan] — Start chatting with your Agent\n" - " [cyan]agentkit serve[/cyan] — Start the API server", - border_style="green", - )) + rprint( + Panel( + "[bold green]Setup complete![/bold green]\n\n" + "You can now run:\n" + " [cyan]agentkit chat[/cyan] — Start chatting with your Agent\n" + " [cyan]agentkit serve[/cyan] — Start the API server", + border_style="green", + ) + ) return str(config_path) diff --git a/src/agentkit/cli/task.py b/src/agentkit/cli/task.py index 6b22ad0..1453298 100644 --- a/src/agentkit/cli/task.py +++ b/src/agentkit/cli/task.py @@ -14,12 +14,16 @@ task_app = typer.Typer(name="task", help="Task management commands", no_args_is_ @task_app.command("submit") def submit( input: Optional[str] = typer.Option(None, "--input", "-i", help="Input data as JSON string"), - input_file: Optional[str] = typer.Option(None, "--input-file", "-f", help="Input data from JSON file"), + input_file: Optional[str] = typer.Option( + None, "--input-file", "-f", help="Input data from JSON file" + ), skill: Optional[str] = typer.Option(None, "--skill", "-s", help="Skill name"), agent: Optional[str] = typer.Option(None, "--agent", "-a", help="Agent name"), mode: str = typer.Option("sync", "--mode", "-m", help="Execution mode: sync or async"), server_url: Optional[str] = typer.Option(None, "--server-url", help="AgentKit server URL"), - config: Optional[str] = typer.Option(None, "--config", help="Path to agentkit.yaml (local mode)"), + config: Optional[str] = typer.Option( + None, "--config", help="Path to agentkit.yaml (local mode)" + ), ): """Submit a task for execution""" # Parse input data @@ -43,23 +47,28 @@ def submit( def _submit_remote(input_data, skill, agent, mode, server_url): """Submit task to a remote AgentKit server.""" from agentkit.server.client import AgentKitClient + client = AgentKitClient(base_url=server_url) if mode == "async": - result = asyncio.run(client.submit_task_async( - input_data=input_data, - skill_name=skill, - agent_name=agent, - )) + result = asyncio.run( + client.submit_task_async( + input_data=input_data, + skill_name=skill, + agent_name=agent, + ) + ) rprint("[green]Task submitted (async)[/green]") rprint(f" Task ID: {result.get('task_id', 'N/A')}") rprint(f" Status: {result.get('status', 'N/A')}") else: - result = asyncio.run(client.submit_task( - input_data=input_data, - skill_name=skill, - agent_name=agent, - )) + result = asyncio.run( + client.submit_task( + input_data=input_data, + skill_name=skill, + agent_name=agent, + ) + ) rprint("[green]Task completed[/green]") if "output_data" in result: rprint(json.dumps(result["output_data"], indent=2, ensure_ascii=False)) @@ -67,19 +76,18 @@ def _submit_remote(input_data, skill, agent, mode, server_url): def _submit_local(input_data, skill, agent, mode, config_path): """Submit task locally without a running server.""" - from agentkit.server.config import ServerConfig, find_config_path + from agentkit.server.config import find_config_path, load_config_with_dotenv # Load config resolved_path = find_config_path(config_path) if resolved_path: - server_config = ServerConfig.from_yaml(resolved_path) - server_config.load_dotenv() - server_config = ServerConfig.from_yaml(resolved_path) + server_config = load_config_with_dotenv(resolved_path) else: server_config = None # Build app components from agentkit.server.app import create_app + app = create_app(server_config=server_config) # Execute task through the app's agent pool @@ -90,7 +98,9 @@ def _submit_local(input_data, skill, agent, mode, config_path): # Determine which skill/agent to use if skill: if not skill_registry.has_skill(skill): - rprint(f"[red]Skill '{skill}' not found. Available: {[s.name for s in skill_registry.list_skills()]}[/red]") + rprint( + f"[red]Skill '{skill}' not found. Available: {[s.name for s in skill_registry.list_skills()]}[/red]" + ) raise typer.Exit(code=1) skill_obj = skill_registry.get(skill) agent_name = skill_obj.name @@ -102,9 +112,10 @@ def _submit_local(input_data, skill, agent, mode, config_path): # Create agent and execute agent_instance = agent_pool.get_or_create(agent_name) - from agentkit.core.protocol import TaskMessage, TaskStatus + from agentkit.core.protocol import TaskMessage from datetime import datetime, timezone import uuid + task = TaskMessage( task_id=str(uuid.uuid4()), agent_name=agent_name, @@ -134,6 +145,7 @@ def status( raise typer.Exit(code=1) from agentkit.server.client import AgentKitClient + client = AgentKitClient(base_url=server_url) result = asyncio.run(client.get_task_status(task_id)) @@ -157,6 +169,7 @@ def list_tasks( raise typer.Exit(code=1) from agentkit.server.client import AgentKitClient + client = AgentKitClient(base_url=server_url) tasks = asyncio.run(client.list_tasks(status=status_filter, limit=limit)) @@ -190,6 +203,7 @@ def cancel( raise typer.Exit(code=1) from agentkit.server.client import AgentKitClient + client = AgentKitClient(base_url=server_url) result = asyncio.run(client.cancel_task(task_id)) rprint(f"[green]Task cancelled[/green]: {result}") diff --git a/src/agentkit/cli/templates.py b/src/agentkit/cli/templates.py index aade2e2..333d8c7 100644 --- a/src/agentkit/cli/templates.py +++ b/src/agentkit/cli/templates.py @@ -13,18 +13,24 @@ server: llm: providers: - dashscope: + bailian-coding: type: openai api_key: "${DASHSCOPE_API_KEY}" base_url: "https://coding.dashscope.aliyuncs.com/v1" models: + qwen3.7-plus: + alias: default qwen3-coder-plus: - max_tokens: 64000 - qwen3-max: - max_tokens: 128000 + alias: coding + qwen3-max-2026-01-23: + alias: powerful + qwen-turbo: + alias: fast model_aliases: - default: dashscope/qwen3-coder-plus - powerful: dashscope/qwen3-max + default: bailian-coding/qwen3.7-plus + coding: bailian-coding/qwen3-coder-plus + powerful: bailian-coding/qwen3-max-2026-01-23 + fast: bailian-coding/qwen-turbo session: backend: memory @@ -32,6 +38,9 @@ session: bus: backend: memory +task_store: + backend: memory + skills: auto_discover: true paths: @@ -40,6 +49,10 @@ skills: logging: level: "INFO" format: "text" # "text" or "json" + +router: + classifier: heuristic + auction_enabled: false """ ENV_EXAMPLE = """\ @@ -49,8 +62,13 @@ ENV_EXAMPLE = """\ # LLM API Keys (at least one required) DASHSCOPE_API_KEY=sk-your-dashscope-key +# Optional: additional providers +# DEEPSEEK_API_KEY=sk-your-deepseek-key +# OPENAI_API_KEY=sk-your-openai-key +# ANTHROPIC_API_KEY=sk-your-anthropic-key + # Server (optional) -AGENTKIT_API_KEY= # Set to enable API key authentication +# AGENTKIT_API_KEY= # Set to enable API key authentication """ DOCKER_COMPOSE = """\ @@ -66,6 +84,8 @@ services: depends_on: redis: condition: service_healthy + postgres: + condition: service_healthy healthcheck: test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:8001/api/v1/health')"] interval: 30s @@ -82,6 +102,22 @@ services: timeout: 5s retries: 5 + postgres: + image: pgvector/pgvector:pg16 + ports: + - "5432:5432" + environment: + POSTGRES_DB: agentkit + POSTGRES_USER: agentkit + POSTGRES_PASSWORD: agentkit + volumes: + - pgdata:/var/lib/postgresql/data + healthcheck: + test: ["CMD-SHELL", "pg_isready -U agentkit"] + interval: 10s + timeout: 5s + retries: 5 + volumes: pgdata: """ diff --git a/src/agentkit/server/app.py b/src/agentkit/server/app.py index 9b73922..709a834 100644 --- a/src/agentkit/server/app.py +++ b/src/agentkit/server/app.py @@ -21,7 +21,7 @@ from agentkit.skills.base import Skill from agentkit.skills.registry import SkillRegistry from agentkit.tools.registry import ToolRegistry from agentkit.tools.skill_install import SkillInstallTool -from agentkit.server.config import ServerConfig +from agentkit.server.config import ServerConfig, load_dotenv from agentkit.server.routes import ( agents, tasks, @@ -49,18 +49,6 @@ from agentkit.telemetry.setup import setup_telemetry logger = logging.getLogger(__name__) -_ALLOWED_ENV_PREFIXES = ( - "AGENTKIT_", - "DASHSCOPE_", - "OPENAI_", - "ANTHROPIC_", - "GEMINI_", - "TAVILY_", - "SERPER_", - "DEEPSEEK_", -) -_ALLOWED_ENV_EXACT = {"DATABASE_URL", "REDIS_URL"} - def _build_llm_gateway(config: ServerConfig) -> LLMGateway: """Build LLMGateway from ServerConfig, registering all providers.""" @@ -487,27 +475,10 @@ def create_app( if config_path and os.path.exists(config_path): # Load .env before parsing config (so ${ENV_VAR} substitutions work) + from pathlib import Path as _P + _dotenv = _P(config_path).parent / ".env" - if _dotenv.exists(): - with open(_dotenv, encoding="utf-8") as _f: - for _line in _f: - _line = _line.strip() - if not _line or _line.startswith("#") or "=" not in _line: - continue - _key, _, _val = _line.partition("=") - _key = _key.strip() - _val = _val.strip().strip("\"'") - if _key and _key not in os.environ: - allowed = ( - any(_key.startswith(p) for p in _ALLOWED_ENV_PREFIXES) - or _key in _ALLOWED_ENV_EXACT - ) - if not allowed: - logger.warning( - f"Skipping .env variable '{_key}' (not in allowed prefixes)" - ) - continue - os.environ[_key] = _val + load_dotenv(_dotenv) server_config = ServerConfig.from_yaml(config_path) app = FastAPI(title="AgentKit Server", version="2.0.0", lifespan=lifespan) diff --git a/src/agentkit/server/client_config.py b/src/agentkit/server/client_config.py index 1b23607..05c4ba5 100644 --- a/src/agentkit/server/client_config.py +++ b/src/agentkit/server/client_config.py @@ -23,7 +23,10 @@ class ClientConfig: clients_path = os.path.join(self.config_dir, "clients.yaml") if os.path.exists(clients_path): with open(clients_path, encoding="utf-8") as f: - return yaml.safe_load(f) or {} + data = yaml.safe_load(f) or {} + from agentkit.server.config import _deep_resolve + + return _deep_resolve(data) return {} def reload(self): @@ -49,13 +52,20 @@ class ClientConfig: return client_info["skills_dir"] # Fall back to default from agentkit.yaml default_config = self._load_default_config() - return default_config.get("skills", {}).get("paths", ["./skills"])[0] if default_config else None + return ( + default_config.get("skills", {}).get("paths", ["./skills"])[0] + if default_config + else None + ) def _load_default_config(self) -> dict: config_path = os.path.join(self.config_dir, "agentkit.yaml") if os.path.exists(config_path): + from agentkit.server.config import _deep_resolve + with open(config_path, encoding="utf-8") as f: - return yaml.safe_load(f) or {} + data = yaml.safe_load(f) or {} + return _deep_resolve(data) return {} def validate_api_key(self, api_key: str) -> bool: diff --git a/src/agentkit/server/config.py b/src/agentkit/server/config.py index c2d4e5b..ebcbb03 100644 --- a/src/agentkit/server/config.py +++ b/src/agentkit/server/config.py @@ -4,7 +4,7 @@ import asyncio import logging import os import re -from dataclasses import dataclass, field +from dataclasses import dataclass from pathlib import Path from typing import Any, Callable @@ -148,9 +148,9 @@ class ServerConfig: self._last_mtime: float = 0.0 def has_llm_provider(self) -> bool: - """检查是否配置了有效的 LLM Provider(API Key 非空)""" + """检查是否配置了有效的 LLM Provider(API Key 已解析且非空)""" for name, provider in self.llm_config.providers.items(): - if provider.api_key: + if provider.api_key and not provider.api_key.startswith("${"): return True return False @@ -333,25 +333,6 @@ class ServerConfig: logger.warning(f"Failed to load skill config from {yaml_file}: {e}") return configs - def load_dotenv(self, dotenv_path: str = ".env") -> None: - """Load environment variables from a .env file (simple key=value format).""" - path = Path(dotenv_path) - if not path.exists(): - return - - with open(path, encoding="utf-8") as f: - for line in f: - line = line.strip() - if not line or line.startswith("#"): - continue - if "=" not in line: - continue - key, _, value = line.partition("=") - key = key.strip() - value = value.strip().strip("\"'") - if key and key not in os.environ: - os.environ[key] = value - def watch_config(self, config_path: str | None = None) -> None: """Start watching the config file for changes and hot-reload. @@ -376,6 +357,7 @@ class ServerConfig: try: import watchfiles # noqa: F401 + self._watcher_task = asyncio.ensure_future(self._watch_with_watchfiles(path)) logger.info(f"Config watcher started (watchfiles) for {path}") except ImportError: @@ -393,6 +375,7 @@ class ServerConfig: """Watch config file using watchfiles library.""" try: from watchfiles import awatch + async for changes in awatch(path): for change_type, changed_path in changes: logger.info(f"Config file change detected: {change_type} on {changed_path}") @@ -428,7 +411,7 @@ class ServerConfig: return # Validate basic structure: must have at least a server or llm section - if not hasattr(new_config, 'host') or not hasattr(new_config, 'llm_config'): + if not hasattr(new_config, "host") or not hasattr(new_config, "llm_config"): logger.error(f"Invalid config structure in {path}. Keeping current config.") return @@ -464,6 +447,84 @@ class ServerConfig: logger.error(f"Config on_change callback error: {e}") +# ── .env loading ─────────────────────────────────────────────────────── + +_ALLOWED_ENV_PREFIXES = ( + "AGENTKIT_", + "DASHSCOPE_", + "OPENAI_", + "ANTHROPIC_", + "GEMINI_", + "TAVILY_", + "SERPER_", + "DEEPSEEK_", + "DOUBAO_", +) +_ALLOWED_ENV_EXACT = {"DATABASE_URL", "REDIS_URL"} + + +def load_dotenv( + dotenv_path: str | Path, + *, + allowed_prefixes: tuple[str, ...] | None = None, + allowed_exact: set[str] | None = None, +) -> None: + """Load environment variables from a .env file. + + Only variables matching allowed prefixes or exact names are loaded. + Existing environment variables are never overwritten. + + Args: + dotenv_path: Path to the .env file. + allowed_prefixes: Env var prefixes to allow. None = allow all. + allowed_exact: Exact env var names to allow. None = allow all. + """ + path = Path(dotenv_path) + if not path.exists(): + return + + prefixes = allowed_prefixes + exact = allowed_exact + + with open(path, encoding="utf-8") as f: + for line in f: + line = line.strip() + if not line or line.startswith("#"): + continue + if "=" not in line: + continue + key, _, value = line.partition("=") + key = key.strip() + value = value.strip().strip("\"'") + if not key or key in os.environ: + continue + # Apply allowlist if provided + if prefixes is not None or exact is not None: + allowed = False + if prefixes and any(key.startswith(p) for p in prefixes): + allowed = True + if exact and key in exact: + allowed = True + if not allowed: + logger.warning(f"Skipping .env variable '{key}' (not in allowed list)") + continue + os.environ[key] = value + + +def load_config_with_dotenv(config_path: str | Path) -> ServerConfig: + """Load ServerConfig with .env resolution (production-standard loading). + + 1. Load .env from config file's parent directory + 2. Parse agentkit.yaml with env vars resolved + + This is the canonical way to load config in all CLI commands and app factory. + """ + config_path = str(config_path) + dotenv = Path(config_path).parent / ".env" + load_dotenv(dotenv) + return ServerConfig.from_yaml(config_path) + + def find_config_path(config_arg: str | None = None) -> str | None: """Find the agentkit.yaml config file. diff --git a/src/agentkit/server/routes/settings.py b/src/agentkit/server/routes/settings.py index b68b734..78ef6a4 100644 --- a/src/agentkit/server/routes/settings.py +++ b/src/agentkit/server/routes/settings.py @@ -1,6 +1,8 @@ """Settings API routes with config hot-reload support.""" import logging +import os +import re from typing import Any import yaml @@ -16,6 +18,7 @@ router = APIRouter(tags=["settings"]) # Helper: mask API keys (show only last 4 chars) # --------------------------------------------------------------------------- + def _mask_api_key(key: str | None) -> str: """Mask an API key, showing only the last 4 characters.""" if not key: @@ -29,6 +32,7 @@ def _mask_api_key(key: str | None) -> str: # Pydantic models for request/response # --------------------------------------------------------------------------- + class LlmProviderResponse(BaseModel): name: str type: str @@ -103,16 +107,88 @@ class GeneralConfigUpdate(BaseModel): # Helper: read/write config file # --------------------------------------------------------------------------- + def _read_yaml_config(config_path: str) -> dict: """Read the YAML config file and return the parsed dict.""" with open(config_path, encoding="utf-8") as f: return yaml.safe_load(f) or {} +def _reverse_resolve_env(data: Any, original: Any) -> Any: + """Reverse-resolve env var references: if original had ${VAR} and current + value matches os.environ[VAR], keep the ${VAR} reference instead of + writing the plaintext value back to YAML.""" + if isinstance(original, str) and isinstance(data, str): + # Check if original was an env var reference like ${VAR} or ${VAR:-default} + env_refs = re.findall(r"\$\{([^}]+)\}", original) + for expr in env_refs: + var_name = expr.split(":-")[0] if ":-" in expr else expr + env_val = os.environ.get(var_name) + if env_val is not None and data == env_val: + return original # Keep the ${VAR} reference + # If original was a ${VAR} reference but value doesn't match env, still keep ref + if re.match(r"^\$\{[^}]+\}$", original): + return original + if isinstance(data, dict) and isinstance(original, dict): + result = {} + for k in data: + result[k] = _reverse_resolve_env(data[k], original.get(k)) + return result + if isinstance(data, list) and isinstance(original, list): + # For lists: reverse-resolve matching items, keep new items as-is + result = [] + for i, item in enumerate(data): + if i < len(original): + result.append(_reverse_resolve_env(item, original[i])) + else: + result.append(item) + return result + # For lists that changed length or type mismatches, return data as-is + return data + + def _write_yaml_config(config_path: str, data: dict) -> None: - """Write the full config dict back to the YAML file.""" - with open(config_path, "w", encoding="utf-8") as f: - yaml.dump(data, f, default_flow_style=False, allow_unicode=True, sort_keys=False) + """Write the full config dict back to the YAML file. + + Preserves ${VAR} env var references: if the original YAML had ${VAR} + and the resolved value matches os.environ[VAR], the reference is kept + instead of writing the plaintext value. + + Uses ruamel.yaml when available to preserve comments and formatting. + Falls back to PyYAML otherwise. + """ + original = _read_yaml_config(config_path) + preserved = _reverse_resolve_env(data, original) + try: + from ruamel.yaml import YAML + + yaml_writer = YAML() + yaml_writer.default_flow_style = False + yaml_writer.allow_unicode = True + # Re-read with ruamel to get the commented structure + with open(config_path, encoding="utf-8") as f: + original_data = yaml_writer.load(f) + # Apply preserved values onto the ruamel-parsed structure + _deep_update_ruamel(original_data, preserved) + with open(config_path, "w", encoding="utf-8") as f: + yaml_writer.dump(original_data, f) + except ImportError: + with open(config_path, "w", encoding="utf-8") as f: + yaml.dump(preserved, f, default_flow_style=False, allow_unicode=True, sort_keys=False) + + +def _deep_update_ruamel(target: Any, source: Any) -> None: + """Deep-update a ruamel.yaml CommentedMap with values from source dict. + + Preserves comments and formatting in target while updating values. + """ + if not isinstance(source, dict) or not hasattr(target, "__setitem__"): + return + for key, value in source.items(): + if key in target and isinstance(value, dict) and hasattr(target[key], "__setitem__"): + _deep_update_ruamel(target[key], value) + else: + target[key] = value def _get_config_path(request: Request) -> str: @@ -123,10 +199,45 @@ def _get_config_path(request: Request) -> str: return server_config._config_path +def _write_env_var(config_path: str, key: str, value: str) -> None: + """Write or update an environment variable in the .env file next to config. + + If the key already exists in .env, its value is updated in place. + If not, it's appended. Comments and formatting are preserved. + """ + from pathlib import Path + + env_path = Path(config_path).parent / ".env" + lines: list[str] = [] + found = False + + if env_path.exists(): + with open(env_path, encoding="utf-8") as f: + lines = f.readlines() + for i, line in enumerate(lines): + stripped = line.strip() + if stripped.startswith(f"{key}="): + lines[i] = f"{key}={value}\n" + found = True + break + else: + lines = ["# AgentKit Environment Variables\n", "\n"] + + if not found: + lines.append(f"{key}={value}\n") + + with open(env_path, "w", encoding="utf-8") as f: + f.writelines(lines) + + # Also set in current process so the next from_yaml resolves correctly + os.environ[key] = value + + # --------------------------------------------------------------------------- # LLM Settings # --------------------------------------------------------------------------- + @router.get("/settings/llm", response_model=LlmConfigResponse) async def get_llm_settings(request: Request): """Return LLM config with masked API keys.""" @@ -137,15 +248,17 @@ async def get_llm_settings(request: Request): llm_config = config.llm_config providers = [] for name, pconf in llm_config.providers.items(): - providers.append(LlmProviderResponse( - name=name, - type=pconf.type, - api_key=_mask_api_key(pconf.api_key), - base_url=pconf.base_url or "", - models=pconf.models, - max_tokens=pconf.max_tokens, - timeout=pconf.timeout, - )) + providers.append( + LlmProviderResponse( + name=name, + type=pconf.type, + api_key=_mask_api_key(pconf.api_key), + base_url=pconf.base_url or "", + models=pconf.models, + max_tokens=pconf.max_tokens, + timeout=pconf.timeout, + ) + ) return LlmConfigResponse( providers=providers, @@ -156,7 +269,11 @@ async def get_llm_settings(request: Request): @router.put("/settings/llm", response_model=LlmConfigResponse) async def update_llm_settings(request: Request, update: LlmConfigUpdate): - """Update LLM config and trigger hot reload via config file write.""" + """Update LLM config and trigger hot reload via config file write. + + When a new plaintext API key is provided, it is stored in .env (not + agentkit.yaml) and the yaml reference is set to ${ENV_KEY}. + """ config_path = _get_config_path(request) data = _read_yaml_config(config_path) @@ -174,13 +291,22 @@ async def update_llm_settings(request: Request, update: LlmConfigUpdate): "timeout": p.timeout, } if p.api_key is not None: - # If the user sends a masked key (****xxxx), don't overwrite if p.api_key.startswith("****"): - # Keep existing key + # Masked key — keep existing yaml value (preserves ${VAR} refs) existing = data.get("llm", {}).get("providers", {}).get(p.name, {}) p_dict["api_key"] = existing.get("api_key", "") else: - p_dict["api_key"] = p.api_key + # New plaintext key — write to .env, keep ${VAR} ref in yaml + # Extract env_key from existing ${VAR} reference if present + existing = data.get("llm", {}).get("providers", {}).get(p.name, {}) + existing_key = existing.get("api_key", "") + env_match = re.match(r"^\$\{([^}]+)\}$", str(existing_key)) + if env_match: + env_key = env_match.group(1).split(":-")[0] + else: + env_key = f"{p.name.upper().replace('-', '_')}_API_KEY" + _write_env_var(config_path, env_key, p.api_key) + p_dict["api_key"] = f"${{{env_key}}}" else: # Keep existing key if not provided existing = data.get("llm", {}).get("providers", {}).get(p.name, {}) @@ -205,15 +331,17 @@ async def update_llm_settings(request: Request, update: LlmConfigUpdate): llm_config = config.llm_config providers = [] for name, pconf in llm_config.providers.items(): - providers.append(LlmProviderResponse( - name=name, - type=pconf.type, - api_key=_mask_api_key(pconf.api_key), - base_url=pconf.base_url or "", - models=pconf.models, - max_tokens=pconf.max_tokens, - timeout=pconf.timeout, - )) + providers.append( + LlmProviderResponse( + name=name, + type=pconf.type, + api_key=_mask_api_key(pconf.api_key), + base_url=pconf.base_url or "", + models=pconf.models, + max_tokens=pconf.max_tokens, + timeout=pconf.timeout, + ) + ) return LlmConfigResponse( providers=providers, @@ -226,6 +354,7 @@ async def update_llm_settings(request: Request, update: LlmConfigUpdate): # Skills Settings # --------------------------------------------------------------------------- + @router.get("/settings/skills", response_model=SkillsConfigResponse) async def get_skills_settings(request: Request): """Return skill paths config.""" @@ -266,6 +395,7 @@ async def update_skills_settings(request: Request, update: SkillsConfigUpdate): # Knowledge Base Settings # --------------------------------------------------------------------------- + @router.get("/settings/kb", response_model=KbConfigResponse) async def get_kb_settings(request: Request): """Return knowledge base connection config.""" @@ -294,6 +424,7 @@ async def update_kb_settings(request: Request, update: KbConfigUpdate): # General Settings # --------------------------------------------------------------------------- + @router.get("/settings/general", response_model=GeneralConfigResponse) async def get_general_settings(request: Request): """Return general settings (log level, server port, etc.).""" diff --git a/tests/unit/server/test_settings_routes.py b/tests/unit/server/test_settings_routes.py index 8755312..5936b26 100644 --- a/tests/unit/server/test_settings_routes.py +++ b/tests/unit/server/test_settings_routes.py @@ -2,6 +2,9 @@ from __future__ import annotations +import os +import unittest.mock + import pytest import yaml from fastapi.testclient import TestClient @@ -355,7 +358,11 @@ class TestNoConfigPath: """When server_config has no _config_path, PUT should return 400.""" from agentkit.llm.gateway import LLMGateway - app = create_app(llm_gateway=LLMGateway()) + # Mock os.environ to prevent auto-discovery of agentkit.yaml in CWD + with unittest.mock.patch.dict(os.environ, {}, clear=True): + # Also ensure no agentkit.yaml is found in CWD + with unittest.mock.patch("pathlib.Path.exists", return_value=False): + app = create_app(llm_gateway=LLMGateway()) # server_config is None in this case client = TestClient(app) diff --git a/tests/unit/test_cli.py b/tests/unit/test_cli.py index 3523b6b..9f1fee0 100644 --- a/tests/unit/test_cli.py +++ b/tests/unit/test_cli.py @@ -66,7 +66,9 @@ class TestServeCommand: def test_serve_starts_uvicorn(self): """agentkit serve calls uvicorn.run with correct params""" from agentkit.cli.main import app - with patch("uvicorn.run") as mock_run: + with patch("uvicorn.run") as mock_run, \ + patch("agentkit.server.config.find_config_path", return_value=None), \ + patch("rich.prompt.Confirm.ask", return_value=False): result = runner.invoke(app, ["serve", "--host", "0.0.0.0", "--port", "8001"]) mock_run.assert_called_once() call_kwargs = mock_run.call_args