Files
beaver_project/app-instance/backend/beaver/tools/builtins/utility.py
steven_li 30ab74ffb2 feat(engine): 添加MCP连接管理和工具集成功能
- 集成MCP连接管理器,支持MCP服务器连接
- 添加多种内置工具:ClarifyTool、CronTool、DelegateTool、ExecuteCodeTool、
  PatchFileTool、ProcessTool、SendMessageTool、SpawnTool、TerminalTool、
  TodoTool、WebFetchTool、WebSearchTool、WriteFileTool等
- 实现工具注册和装配功能
- 添加技能选择上下文参数
- 支持思考模式控制参数thinking_enabled

feat(coordinator): 重构任务执行计划器参数命名

- 将learning_candidate_enabled重命名为allow_candidate_generation
- 更新TeamGraphScheduler中的参数传递
- 修改LocalAgentRunner中的相关参数处理
- 更新README文档中的相应描述

refactor(context): 标准化工具调用参数格式

- 添加_json导入用于参数序列化
- 实现_provider_tool_calls方法标准化OpenAI兼容的工具调用载荷
- 修复工具调用中参数非字符串类型的序列化问题

refactor(session): 优化消息历史记录过滤逻辑

- 修改get_messages_as_conversation为基于运行状态过滤消息
- 排除未完成、失败或错误结束的运行记录
- 改进对话历史的可见性控制机制

fix(store): 修复FTS索引重建逻辑

- 添加异常处理防止FTS索引创建失败
- 实现_rebuild_fts_index方法重新构建全文搜索索引
- 优化索引触发器和表的维护流程
2026-05-14 09:43:48 +08:00

138 lines
4.7 KiB
Python

"""Small local utility tools."""
from __future__ import annotations
from dataclasses import dataclass, field
import json
from typing import Any
def _json_result(success: bool, **payload: Any) -> str:
return json.dumps({"success": success, **payload}, ensure_ascii=False, indent=2)
@dataclass(slots=True)
class TodoTool:
name: str = "todo"
description: str = "Manage a lightweight task list for the current session."
toolset: str = "planning"
always_available: bool = False
parameters: dict[str, Any] = field(
default_factory=lambda: {
"type": "object",
"properties": {
"todos": {"type": "array", "items": {"type": "object"}},
"merge": {"type": "boolean", "default": False},
},
}
)
async def execute(self, *, todos: list[dict[str, Any]] | None = None, merge: bool = False, **kwargs: Any) -> str:
metadata = kwargs.get("metadata") if isinstance(kwargs.get("metadata"), dict) else {}
current = list(metadata.get("todos") or [])
if todos is None:
return _json_result(True, todos=current)
next_todos = [dict(item) for item in todos if isinstance(item, dict)]
metadata["todos"] = [*current, *next_todos] if merge else next_todos
return _json_result(True, todos=metadata["todos"])
@dataclass(slots=True)
class ClarifyTool:
name: str = "clarify"
description: str = "Ask the user for clarification by returning a structured question."
toolset: str = "planning"
always_available: bool = False
parameters: dict[str, Any] = field(
default_factory=lambda: {
"type": "object",
"properties": {
"question": {"type": "string"},
"choices": {"type": "array", "items": {"type": "string"}},
},
"required": ["question"],
}
)
async def execute(self, *, question: str, choices: list[str] | None = None, **_: Any) -> str:
return _json_result(True, question=question, choices=[str(item) for item in (choices or [])])
@dataclass(slots=True)
class SendMessageTool:
name: str = "send_message"
description: str = "Return a message payload for an external channel. Actual delivery is handled by configured services."
toolset: str = "messaging"
always_available: bool = False
parameters: dict[str, Any] = field(
default_factory=lambda: {
"type": "object",
"properties": {
"target": {"type": "string"},
"message": {"type": "string"},
},
"required": ["target", "message"],
}
)
async def execute(self, *, target: str, message: str, **_: Any) -> str:
return _json_result(True, target=target, message=message, delivered=False)
@dataclass(slots=True)
class DelegateTool:
name: str = "delegate"
description: str = "Create a structured delegation request for a sub-agent or teammate."
toolset: str = "coordination"
always_available: bool = False
parameters: dict[str, Any] = field(
default_factory=lambda: {
"type": "object",
"properties": {
"task": {"type": "string"},
"agent": {"type": "string"},
"context": {"type": "object"},
},
"required": ["task"],
}
)
async def execute(self, *, task: str, agent: str | None = None, context: dict[str, Any] | None = None, **_: Any) -> str:
return _json_result(
True,
task=task,
agent=agent or "default",
context=dict(context or {}),
queued=False,
note="Delegation request recorded; runtime execution is handled by configured agent services.",
)
@dataclass(slots=True)
class SpawnTool:
name: str = "spawn"
description: str = "Create a structured request to spawn a bounded subtask."
toolset: str = "coordination"
always_available: bool = False
parameters: dict[str, Any] = field(
default_factory=lambda: {
"type": "object",
"properties": {
"task": {"type": "string"},
"role": {"type": "string", "default": "worker"},
"write_scope": {"type": "array", "items": {"type": "string"}},
},
"required": ["task"],
}
)
async def execute(self, *, task: str, role: str = "worker", write_scope: list[str] | None = None, **_: Any) -> str:
return _json_result(
True,
task=task,
role=role,
write_scope=[str(item) for item in (write_scope or [])],
queued=False,
note="Spawn request recorded; runtime execution is handled by configured agent services.",
)