refactor: tech debt Wave 3+4 (tools/skills/mcp/rag/calendar/auth/cli/quality/channels/telemetry/session/bus/documents Any 治理) #11

Merged
fischer merged 2 commits from refactor/tech-debt-wave-3-4 into main 2026-07-01 08:08:36 +08:00
34 changed files with 194 additions and 222 deletions
Showing only changes of commit 57f4ee9ac0 - Show all commits

View File

@ -4,7 +4,6 @@ from __future__ import annotations
import logging import logging
from dataclasses import dataclass, field from dataclasses import dataclass, field
from typing import Any
from agentkit.core.config_driven import AgentConfig from agentkit.core.config_driven import AgentConfig
from agentkit.core.exceptions import ConfigValidationError from agentkit.core.exceptions import ConfigValidationError
@ -66,27 +65,27 @@ class SkillConfig(AgentConfig):
task_mode: str = "llm_generate", task_mode: str = "llm_generate",
supported_tasks: list[str] | None = None, supported_tasks: list[str] | None = None,
max_concurrency: int = 1, max_concurrency: int = 1,
input_schema: dict[str, Any] | None = None, input_schema: dict[str, object] | None = None,
output_schema: dict[str, Any] | None = None, output_schema: dict[str, object] | None = None,
prompt: dict[str, str] | None = None, prompt: dict[str, str] | None = None,
llm: dict[str, Any] | None = None, llm: dict[str, object] | None = None,
tools: list[str] | None = None, tools: list[str] | None = None,
memory: dict[str, Any] | None = None, memory: dict[str, object] | None = None,
custom_handler: str | None = None, custom_handler: str | None = None,
# v2 新增字段 # v2 新增字段
intent: dict[str, Any] | None = None, intent: dict[str, object] | None = None,
quality_gate: dict[str, Any] | None = None, quality_gate: dict[str, object] | None = None,
execution_mode: str = "react", execution_mode: str = "react",
max_steps: int = 5, max_steps: int = 5,
evolution: dict[str, Any] | None = None, evolution: dict[str, object] | None = None,
# v3 新增字段SKILL.md 支持 # v3 新增字段SKILL.md 支持
skill_md_path: str | None = None, skill_md_path: str | None = None,
disclosure_level: int = 1, # 默认全量加载向后兼容0=概要模式需显式指定 disclosure_level: int = 1, # 默认全量加载向后兼容0=概要模式需显式指定
# v4 新增字段:依赖声明、能力标签 # v4 新增字段:依赖声明、能力标签
dependencies: list[dict[str, Any] | DependencyDecl] | None = None, dependencies: list[dict[str, object] | DependencyDecl] | None = None,
capabilities: list[str | dict[str, Any] | CapabilityTag] | None = None, capabilities: list[str | dict[str, object] | CapabilityTag] | None = None,
# v5 新增字段:对齐守卫 # v5 新增字段:对齐守卫
alignment: dict[str, Any] | None = None, alignment: dict[str, object] | None = None,
# v6 新增字段ReWOO fallback 策略YAML 可配置) # v6 新增字段ReWOO fallback 策略YAML 可配置)
fallback_strategies: list[str] | None = None, fallback_strategies: list[str] | None = None,
# v7 新增字段:激活前置条件 + 来源标记SkillHarness preconditions / provenance # v7 新增字段:激活前置条件 + 来源标记SkillHarness preconditions / provenance
@ -163,7 +162,7 @@ class SkillConfig(AgentConfig):
@staticmethod @staticmethod
def _parse_dependencies( def _parse_dependencies(
raw: list[dict[str, Any] | DependencyDecl], raw: list[dict[str, object] | DependencyDecl],
) -> list[DependencyDecl]: ) -> list[DependencyDecl]:
"""解析依赖声明列表,支持 dict 或 DependencyDecl 实例""" """解析依赖声明列表,支持 dict 或 DependencyDecl 实例"""
result: list[DependencyDecl] = [] result: list[DependencyDecl] = []
@ -178,7 +177,7 @@ class SkillConfig(AgentConfig):
@staticmethod @staticmethod
def _parse_capabilities( def _parse_capabilities(
raw: list[str | dict[str, Any] | CapabilityTag], raw: list[str | dict[str, object] | CapabilityTag],
) -> list[CapabilityTag]: ) -> list[CapabilityTag]:
"""解析能力标签列表,支持 str / dict / CapabilityTag 实例""" """解析能力标签列表,支持 str / dict / CapabilityTag 实例"""
result: list[CapabilityTag] = [] result: list[CapabilityTag] = []
@ -194,7 +193,7 @@ class SkillConfig(AgentConfig):
return result return result
@classmethod @classmethod
def from_dict(cls, data: dict[str, Any]) -> "SkillConfig": def from_dict(cls, data: dict[str, object]) -> "SkillConfig":
"""从字典创建配置""" """从字典创建配置"""
return cls( return cls(
name=data["name"], name=data["name"],
@ -241,7 +240,7 @@ class SkillConfig(AgentConfig):
) )
return cls.from_dict(data) return cls.from_dict(data)
def to_dict(self) -> dict[str, Any]: def to_dict(self) -> dict[str, object]:
"""序列化为字典,包含 v2 字段""" """序列化为字典,包含 v2 字段"""
d = super().to_dict() d = super().to_dict()
d["intent"] = { d["intent"] = {

View File

@ -10,7 +10,6 @@ import asyncio
import logging import logging
import uuid import uuid
from dataclasses import dataclass, field from dataclasses import dataclass, field
from typing import Any
from agentkit.core.protocol import TaskMessage from agentkit.core.protocol import TaskMessage
from agentkit.core.shared_workspace import SharedWorkspace from agentkit.core.shared_workspace import SharedWorkspace
@ -42,7 +41,7 @@ class PipelineStepResult:
step_name: str step_name: str
skill: str skill: str
status: str # "success", "failed", "skipped" status: str # "success", "failed", "skipped"
output: dict[str, Any] | None = None output: dict[str, object] | None = None
error: str | None = None error: str | None = None
duration_ms: float = 0 duration_ms: float = 0
@ -54,7 +53,7 @@ class PipelineResult:
pipeline_name: str pipeline_name: str
execution_id: str execution_id: str
steps: list[PipelineStepResult] steps: list[PipelineStepResult]
final_output: dict[str, Any] | None final_output: dict[str, object] | None
success: bool success: bool
total_duration_ms: float total_duration_ms: float
@ -79,7 +78,7 @@ class GEOPipeline:
name: str, name: str,
steps: list[PipelineStep], steps: list[PipelineStep],
skill_registry: SkillRegistry | None = None, skill_registry: SkillRegistry | None = None,
agent_pool: Any = None, agent_pool: object = None,
workspace: SharedWorkspace | None = None, workspace: SharedWorkspace | None = None,
): ):
self.name = name self.name = name
@ -92,9 +91,9 @@ class GEOPipeline:
@classmethod @classmethod
def from_config( def from_config(
cls, cls,
config: dict[str, Any], config: dict[str, object],
skill_registry: SkillRegistry | None = None, skill_registry: SkillRegistry | None = None,
agent_pool: Any = None, agent_pool: object = None,
workspace: SharedWorkspace | None = None, workspace: SharedWorkspace | None = None,
) -> GEOPipeline: ) -> GEOPipeline:
"""从 YAML 配置创建 Pipeline """从 YAML 配置创建 Pipeline
@ -136,7 +135,7 @@ class GEOPipeline:
workspace=workspace, workspace=workspace,
) )
async def execute(self, input_data: dict[str, Any]) -> PipelineResult: async def execute(self, input_data: dict[str, object]) -> PipelineResult:
"""执行 Pipeline """执行 Pipeline
Args: Args:
@ -150,7 +149,7 @@ class GEOPipeline:
start_time = time.monotonic() start_time = time.monotonic()
execution_id = str(uuid.uuid4())[:8] execution_id = str(uuid.uuid4())[:8]
step_results: list[PipelineStepResult] = [] step_results: list[PipelineStepResult] = []
step_outputs: dict[str, dict[str, Any]] = {} step_outputs: dict[str, dict[str, object]] = {}
# Store initial input in workspace # Store initial input in workspace
await self._workspace.write( await self._workspace.write(
@ -227,8 +226,8 @@ class GEOPipeline:
async def _execute_step( async def _execute_step(
self, self,
step: PipelineStep, step: PipelineStep,
input_data: dict[str, Any], input_data: dict[str, object],
step_outputs: dict[str, dict[str, Any]], step_outputs: dict[str, dict[str, object]],
execution_id: str, execution_id: str,
saga: SagaOrchestrator, saga: SagaOrchestrator,
) -> PipelineStepResult: ) -> PipelineStepResult:
@ -294,8 +293,8 @@ class GEOPipeline:
) )
async def _execute_skill( async def _execute_skill(
self, skill_name: str, input_data: dict[str, Any] self, skill_name: str, input_data: dict[str, object]
) -> dict[str, Any]: ) -> dict[str, object]:
"""执行 Skill""" """执行 Skill"""
if self._agent_pool: if self._agent_pool:
agent = self._agent_pool.get_agent(skill_name) agent = self._agent_pool.get_agent(skill_name)
@ -361,9 +360,9 @@ class GEOPipeline:
def _map_input( def _map_input(
self, self,
step: PipelineStep, step: PipelineStep,
input_data: dict[str, Any], input_data: dict[str, object],
step_outputs: dict[str, dict[str, Any]], step_outputs: dict[str, dict[str, object]],
) -> dict[str, Any]: ) -> dict[str, object]:
"""根据 input_mapping 构建步骤输入 """根据 input_mapping 构建步骤输入
映射格式: {"target_key": "source_path"} 映射格式: {"target_key": "source_path"}
@ -379,7 +378,7 @@ class GEOPipeline:
merged.update(step_outputs[dep]) merged.update(step_outputs[dep])
return merged return merged
mapped: dict[str, Any] = {} mapped: dict[str, object] = {}
for target_key, source_path in step.input_mapping.items(): for target_key, source_path in step.input_mapping.items():
value = self._resolve_mapping_path(source_path, input_data, step_outputs) value = self._resolve_mapping_path(source_path, input_data, step_outputs)
if value is not None: if value is not None:
@ -390,9 +389,9 @@ class GEOPipeline:
@staticmethod @staticmethod
def _resolve_mapping_path( def _resolve_mapping_path(
path: str, path: str,
input_data: dict[str, Any], input_data: dict[str, object],
step_outputs: dict[str, dict[str, Any]], step_outputs: dict[str, dict[str, object]],
) -> Any: ) -> object:
"""解析映射路径""" """解析映射路径"""
if path.startswith("$.input."): if path.startswith("$.input."):
key = path[len("$.input."):] key = path[len("$.input."):]
@ -416,7 +415,7 @@ class GEOPipeline:
return None return None
def _evaluate_condition( def _evaluate_condition(
self, condition: str, input_data: dict[str, Any], step_outputs: dict[str, Any] self, condition: str, input_data: dict[str, object], step_outputs: dict[str, object]
) -> bool: ) -> bool:
"""评估条件表达式""" """评估条件表达式"""
import re import re
@ -435,9 +434,9 @@ class GEOPipeline:
def _build_final_output( def _build_final_output(
self, self,
step_outputs: dict[str, dict[str, Any]], step_outputs: dict[str, dict[str, object]],
input_data: dict[str, Any], input_data: dict[str, object],
) -> dict[str, Any]: ) -> dict[str, object]:
"""构建最终输出""" """构建最终输出"""
final = {"input": input_data} final = {"input": input_data}
for step_name, output in step_outputs.items(): for step_name, output in step_outputs.items():

View File

@ -8,9 +8,8 @@
import logging import logging
import re import re
from typing import Any, Callable, Coroutine from typing import Callable, Coroutine
from agentkit.skills.base import Skill, SkillConfig
from agentkit.skills.registry import SkillRegistry from agentkit.skills.registry import SkillRegistry
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -28,7 +27,7 @@ class SkillPipeline:
def __init__( def __init__(
self, self,
name: str, name: str,
steps: list[dict[str, Any]], steps: list[dict[str, object]],
skill_registry: SkillRegistry | None = None, skill_registry: SkillRegistry | None = None,
): ):
""" """
@ -43,9 +42,9 @@ class SkillPipeline:
async def execute( async def execute(
self, self,
input_data: dict[str, Any], input_data: dict[str, object],
agent_factory: Callable[..., Coroutine] | None = None, agent_factory: Callable[..., Coroutine] | None = None,
) -> dict[str, Any]: ) -> dict[str, object]:
"""顺序执行 Pipeline 中所有步骤 """顺序执行 Pipeline 中所有步骤
Args: Args:
@ -57,8 +56,8 @@ class SkillPipeline:
包含 pipeline 名称各步骤结果和最终输出的字典 包含 pipeline 名称各步骤结果和最终输出的字典
""" """
success = True success = True
current_input: dict[str, Any] = input_data current_input: dict[str, object] = input_data
results: list[dict[str, Any]] = [] results: list[dict[str, object]] = []
for i, step_def in enumerate(self._steps): for i, step_def in enumerate(self._steps):
skill_name = step_def["skill_name"] skill_name = step_def["skill_name"]
@ -112,9 +111,9 @@ class SkillPipeline:
async def _execute_skill( async def _execute_skill(
self, self,
skill_name: str, skill_name: str,
input_data: dict[str, Any], input_data: dict[str, object],
agent_factory: Callable[..., Coroutine] | None = None, agent_factory: Callable[..., Coroutine] | None = None,
) -> dict[str, Any]: ) -> dict[str, object]:
"""执行单个 Skill """执行单个 Skill
优先使用 agent_factory其次通过 SkillRegistry 查找 Skill 并创建 Agent 执行 优先使用 agent_factory其次通过 SkillRegistry 查找 Skill 并创建 Agent 执行
@ -152,8 +151,8 @@ class SkillPipeline:
def _evaluate_condition( def _evaluate_condition(
self, self,
condition: str, condition: str,
current_input: dict[str, Any], current_input: dict[str, object],
results: list[dict[str, Any]], results: list[dict[str, object]],
) -> bool: ) -> bool:
"""评估简单条件表达式 """评估简单条件表达式
@ -180,10 +179,10 @@ class SkillPipeline:
return False return False
@staticmethod @staticmethod
def _resolve_path(path: str, data: dict[str, Any]) -> Any: def _resolve_path(path: str, data: dict[str, object]) -> object:
"""解析点号路径,如 'output.score'""" """解析点号路径,如 'output.score'"""
parts = path.split(".") parts = path.split(".")
obj: Any = data obj: object = data
for part in parts: for part in parts:
if isinstance(obj, dict): if isinstance(obj, dict):
obj = obj.get(part) obj = obj.get(part)
@ -193,15 +192,15 @@ class SkillPipeline:
def _map_input( def _map_input(
self, self,
current_input: dict[str, Any], current_input: dict[str, object],
mapping: dict[str, str], mapping: dict[str, str],
results: list[dict[str, Any]], results: list[dict[str, object]],
) -> dict[str, Any]: ) -> dict[str, object]:
"""根据映射规则将上一步输出映射到当前步骤输入 """根据映射规则将上一步输出映射到当前步骤输入
mapping 格式: {"target_key": "source.path"} mapping 格式: {"target_key": "source.path"}
""" """
mapped: dict[str, Any] = {} mapped: dict[str, object] = {}
for target_key, source_path in mapping.items(): for target_key, source_path in mapping.items():
value = self._resolve_path(source_path, current_input) value = self._resolve_path(source_path, current_input)
if value is not None: if value is not None:

View File

@ -7,7 +7,7 @@ from typing import TYPE_CHECKING
from agentkit.core.exceptions import SkillNotFoundError from agentkit.core.exceptions import SkillNotFoundError
from agentkit.skills.base import Skill, SkillConfig from agentkit.skills.base import Skill, SkillConfig
from agentkit.skills.schema import DependencyDecl, HealthCheckResult from agentkit.skills.schema import HealthCheckResult
if TYPE_CHECKING: if TYPE_CHECKING:
from agentkit.skills.pipeline import SkillPipeline from agentkit.skills.pipeline import SkillPipeline

View File

@ -8,7 +8,6 @@ from __future__ import annotations
import logging import logging
from dataclasses import dataclass, field from dataclasses import dataclass, field
from typing import Any
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -67,13 +66,13 @@ class SkillSpec:
description: str = "" description: str = ""
capabilities: list[CapabilityTag] = field(default_factory=list) capabilities: list[CapabilityTag] = field(default_factory=list)
dependencies: list[DependencyDecl] = field(default_factory=list) dependencies: list[DependencyDecl] = field(default_factory=list)
input_schema: dict[str, Any] | None = None input_schema: dict[str, object] | None = None
output_schema: dict[str, Any] | None = None output_schema: dict[str, object] | None = None
quality_gate: dict[str, Any] | None = None quality_gate: dict[str, object] | None = None
metadata: dict[str, Any] = field(default_factory=dict) metadata: dict[str, object] = field(default_factory=dict)
@classmethod @classmethod
def from_dict(cls, data: dict[str, Any]) -> SkillSpec: def from_dict(cls, data: dict[str, object]) -> SkillSpec:
"""从字典创建 SkillSpec""" """从字典创建 SkillSpec"""
capabilities = [ capabilities = [
CapabilityTag(**cap) if isinstance(cap, dict) else cap CapabilityTag(**cap) if isinstance(cap, dict) else cap
@ -95,9 +94,9 @@ class SkillSpec:
metadata=data.get("metadata", {}), metadata=data.get("metadata", {}),
) )
def to_dict(self) -> dict[str, Any]: def to_dict(self) -> dict[str, object]:
"""序列化为字典""" """序列化为字典"""
d: dict[str, Any] = { d: dict[str, object] = {
"name": self.name, "name": self.name,
"version": self.version, "version": self.version,
"description": self.description, "description": self.description,
@ -165,7 +164,7 @@ class HealthCheckResult:
version_mismatches: list[str] = field(default_factory=list) version_mismatches: list[str] = field(default_factory=list)
warnings: list[str] = field(default_factory=list) warnings: list[str] = field(default_factory=list)
def to_dict(self) -> dict[str, Any]: def to_dict(self) -> dict[str, object]:
return { return {
"skill_name": self.skill_name, "skill_name": self.skill_name,
"skill_version": self.skill_version, "skill_version": self.skill_version,

View File

@ -12,7 +12,6 @@ constraints/output_format从本地 SkillRegistry 检索。
from __future__ import annotations from __future__ import annotations
import logging import logging
from typing import Any
from agentkit.chat.skill_routing import collect_prompt_parts, format_preconditions_block from agentkit.chat.skill_routing import collect_prompt_parts, format_preconditions_block
from agentkit.core.exceptions import SkillNotFoundError from agentkit.core.exceptions import SkillNotFoundError
@ -36,7 +35,7 @@ class SkillDetailTool(Tool):
def __init__( def __init__(
self, self,
skill_registry: Any, skill_registry: object,
name: str = "skill_detail", name: str = "skill_detail",
description: str = ( description: str = (
"Load full instructions for a registered skill by name or keyword. " "Load full instructions for a registered skill by name or keyword. "
@ -44,8 +43,8 @@ class SkillDetailTool(Tool):
"and you need the complete instructions to execute the skill. " "and you need the complete instructions to execute the skill. "
"Returns the skill's identity, context, instructions, constraints, and output format." "Returns the skill's identity, context, instructions, constraints, and output format."
), ),
input_schema: dict[str, Any] | None = None, input_schema: dict[str, object] | None = None,
output_schema: dict[str, Any] | None = None, output_schema: dict[str, object] | None = None,
version: str = "1.0.0", version: str = "1.0.0",
tags: list[str] | None = None, tags: list[str] | None = None,
): ):
@ -97,7 +96,7 @@ class SkillDetailTool(Tool):
pass # 非精确匹配,降级到关键词搜索 pass # 非精确匹配,降级到关键词搜索
# 关键词搜索:匹配 skill 名称和描述 # 关键词搜索:匹配 skill 名称和描述
matches: list[Any] = [] matches: list[object] = []
query_lower = query.lower() query_lower = query.lower()
for skill in self._registry.list_skills(): for skill in self._registry.list_skills():
name = skill.name.lower() name = skill.name.lower()
@ -117,7 +116,7 @@ class SkillDetailTool(Tool):
return self._format_skill_full(matches[0]) return self._format_skill_full(matches[0])
@staticmethod @staticmethod
def _format_skill_full(skill: Any) -> dict[str, Any]: def _format_skill_full(skill: object) -> dict[str, object]:
"""格式化 skill 的完整 instructions 供 LLM 使用。""" """格式化 skill 的完整 instructions 供 LLM 使用。"""
config = skill.config config = skill.config
prompt_parts = collect_prompt_parts(config, with_headers=True) prompt_parts = collect_prompt_parts(config, with_headers=True)

View File

@ -8,7 +8,6 @@
import logging import logging
import re import re
from typing import Any
import yaml import yaml
@ -27,7 +26,7 @@ class SkillMdParser:
""" """
@staticmethod @staticmethod
def parse(file_path: str) -> tuple[dict[str, Any], dict[str, str], str]: def parse(file_path: str) -> tuple[dict[str, object], dict[str, str], str]:
"""解析 SKILL.md 文件 """解析 SKILL.md 文件
Note: Only H1 headings (# ) are treated as section delimiters. Note: Only H1 headings (# ) are treated as section delimiters.
@ -48,7 +47,7 @@ class SkillMdParser:
content = f.read() content = f.read()
# 提取 YAML frontmatter--- 标记之间) # 提取 YAML frontmatter--- 标记之间)
frontmatter: dict[str, Any] = {} frontmatter: dict[str, object] = {}
body = content body = content
if content.startswith("---"): if content.startswith("---"):
parts = content.split("---", 2) parts = content.split("---", 2)
@ -81,7 +80,7 @@ class SkillMdParser:
@staticmethod @staticmethod
def to_skill_config( def to_skill_config(
frontmatter: dict[str, Any], frontmatter: dict[str, object],
sections: dict[str, str], sections: dict[str, str],
file_path: str, file_path: str,
disclosure_level: int = 1, disclosure_level: int = 1,
@ -99,7 +98,7 @@ class SkillMdParser:
""" """
# 构建 IntentConfig # 构建 IntentConfig
intent_data = frontmatter.get("intent") or {} intent_data = frontmatter.get("intent") or {}
intent_config_data: dict[str, Any] = { intent_config_data: dict[str, object] = {
"keywords": intent_data.get("keywords", []), "keywords": intent_data.get("keywords", []),
"description": intent_data.get("description", ""), "description": intent_data.get("description", ""),
"examples": intent_data.get("examples", []), "examples": intent_data.get("examples", []),
@ -107,7 +106,7 @@ class SkillMdParser:
# 构建 QualityGateConfig # 构建 QualityGateConfig
qg_data = frontmatter.get("quality_gate") or {} qg_data = frontmatter.get("quality_gate") or {}
quality_gate_config_data: dict[str, Any] = { quality_gate_config_data: dict[str, object] = {
"required_fields": qg_data.get("required_fields", []), "required_fields": qg_data.get("required_fields", []),
"min_word_count": qg_data.get("min_word_count", 0), "min_word_count": qg_data.get("min_word_count", 0),
"max_retries": qg_data.get("max_retries", 0), "max_retries": qg_data.get("max_retries", 0),

View File

@ -7,7 +7,7 @@ The LLM calls this tool to signal "I'm done planning, move to building".
from __future__ import annotations from __future__ import annotations
import logging import logging
from typing import TYPE_CHECKING, Any from typing import TYPE_CHECKING
from agentkit.tools.base import Tool from agentkit.tools.base import Tool
@ -55,7 +55,7 @@ class AdvancePhaseTool(Tool):
) )
self._engine = engine self._engine = engine
async def execute(self, **kwargs) -> dict[str, Any]: async def execute(self, **kwargs) -> dict[str, object]:
# Capture previous phase before transition (engine is single-threaded per request). # Capture previous phase before transition (engine is single-threaded per request).
previous = self._engine.current_phase previous = self._engine.current_phase
new_phase = self._engine.advance_phase() new_phase = self._engine.advance_phase()

View File

@ -1,7 +1,5 @@
"""AgentTool - 将 Agent 包装为 Tool""" """AgentTool - 将 Agent 包装为 Tool"""
from typing import Any
from agentkit.tools.base import Tool from agentkit.tools.base import Tool
@ -36,7 +34,7 @@ class AgentTool(Tool):
self.timeout_seconds = timeout_seconds self.timeout_seconds = timeout_seconds
self._dispatcher = None self._dispatcher = None
def set_dispatcher(self, dispatcher: Any) -> "AgentTool": def set_dispatcher(self, dispatcher: object) -> "AgentTool":
"""注入 Dispatcher""" """注入 Dispatcher"""
self._dispatcher = dispatcher self._dispatcher = dispatcher
return self return self

View File

@ -10,7 +10,6 @@ from __future__ import annotations
import asyncio import asyncio
import logging import logging
import uuid import uuid
from typing import Any
from agentkit.tools.base import Tool from agentkit.tools.base import Tool
@ -42,12 +41,12 @@ class AskHumanTool(Tool):
# request_id -> asyncio.Future # request_id -> asyncio.Future
self._pending_replies: dict[str, asyncio.Future] | None = None self._pending_replies: dict[str, asyncio.Future] | None = None
# Callback to push question to client # Callback to push question to client
self._ask_callback: Any = None self._ask_callback: object = None
def configure( def configure(
self, self,
pending_replies: dict[str, asyncio.Future] | None = None, pending_replies: dict[str, asyncio.Future] | None = None,
ask_callback: Any = None, ask_callback: object = None,
) -> None: ) -> None:
"""Configure the tool with WebSocket communication channels. """Configure the tool with WebSocket communication channels.
@ -61,7 +60,7 @@ class AskHumanTool(Tool):
self._ask_callback = ask_callback self._ask_callback = ask_callback
@property @property
def parameters(self) -> dict[str, Any]: def parameters(self) -> dict[str, object]:
return { return {
"type": "object", "type": "object",
"properties": { "properties": {
@ -78,7 +77,7 @@ class AskHumanTool(Tool):
"required": ["question"], "required": ["question"],
} }
async def execute(self, **kwargs: Any) -> dict: async def execute(self, **kwargs: object) -> dict:
"""Ask the user a question and wait for their reply. """Ask the user a question and wait for their reply.
Args: Args:

View File

@ -7,7 +7,6 @@
import json import json
import logging import logging
import urllib.parse import urllib.parse
from typing import Any
import httpx import httpx
@ -30,8 +29,8 @@ class BaiduSearchTool(Tool):
self, self,
name: str = "baidu_search", name: str = "baidu_search",
description: str = "执行百度搜索,返回搜索结果列表", description: str = "执行百度搜索,返回搜索结果列表",
input_schema: dict[str, Any] | None = None, input_schema: dict[str, object] | None = None,
output_schema: dict[str, Any] | None = None, output_schema: dict[str, object] | None = None,
version: str = "1.0.0", version: str = "1.0.0",
tags: list[str] | None = None, tags: list[str] | None = None,
api_key: str | None = None, api_key: str | None = None,
@ -49,7 +48,7 @@ class BaiduSearchTool(Tool):
self._api_url = api_url self._api_url = api_url
@staticmethod @staticmethod
def _default_input_schema() -> dict[str, Any]: def _default_input_schema() -> dict[str, object]:
return { return {
"type": "object", "type": "object",
"properties": { "properties": {
@ -67,7 +66,7 @@ class BaiduSearchTool(Tool):
} }
@staticmethod @staticmethod
def _default_output_schema() -> dict[str, Any]: def _default_output_schema() -> dict[str, object]:
return { return {
"type": "object", "type": "object",
"properties": { "properties": {

View File

@ -2,7 +2,6 @@
import time import time
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from typing import Any
import jsonschema import jsonschema
@ -23,7 +22,7 @@ class ToolValidationError(Exception):
message: str, message: str,
*, *,
error_code: str = "schema_mismatch", error_code: str = "schema_mismatch",
details: dict[str, Any] | None = None, details: dict[str, object] | None = None,
) -> None: ) -> None:
super().__init__(message) super().__init__(message)
self.error_code = error_code self.error_code = error_code
@ -40,8 +39,8 @@ class Tool(ABC):
self, self,
name: str, name: str,
description: str, description: str,
input_schema: dict[str, Any] | None = None, input_schema: dict[str, object] | None = None,
output_schema: dict[str, Any] | None = None, output_schema: dict[str, object] | None = None,
version: str = "1.0.0", version: str = "1.0.0",
tags: list[str] | None = None, tags: list[str] | None = None,
): ):
@ -99,7 +98,7 @@ class Tool(ABC):
finally: finally:
_span_cm.__exit__(None, None, None) _span_cm.__exit__(None, None, None)
def _validate_input(self, kwargs: dict[str, Any]) -> None: def _validate_input(self, kwargs: dict[str, object]) -> None:
"""校验 kwargs 是否符合 self.input_schema。 """校验 kwargs 是否符合 self.input_schema。
- input_schema=None 跳过(向后兼容,旧工具无 schema) - input_schema=None 跳过(向后兼容,旧工具无 schema)

View File

@ -16,7 +16,6 @@ from __future__ import annotations
import asyncio import asyncio
import logging import logging
from typing import Any
import httpx import httpx
@ -140,7 +139,7 @@ class BitableTool(Tool):
if self._client is not None and not self._client.is_closed: if self._client is not None and not self._client.is_closed:
await self._client.aclose() await self._client.aclose()
async def execute(self, **kwargs) -> dict[str, Any]: async def execute(self, **kwargs) -> dict[str, object]:
action = kwargs.get("action") action = kwargs.get("action")
handlers = { handlers = {
"create_table": self._create_table, "create_table": self._create_table,
@ -169,7 +168,7 @@ class BitableTool(Tool):
# create_table # create_table
# ------------------------------------------------------------------ # ------------------------------------------------------------------
async def _create_table(self, **kwargs) -> dict[str, Any]: async def _create_table(self, **kwargs) -> dict[str, object]:
table_name = kwargs.get("table_name") table_name = kwargs.get("table_name")
if not table_name: if not table_name:
return {"success": False, "error": "Missing required field: table_name"} return {"success": False, "error": "Missing required field: table_name"}
@ -186,7 +185,7 @@ class BitableTool(Tool):
# import_excel # import_excel
# ------------------------------------------------------------------ # ------------------------------------------------------------------
async def _import_excel(self, **kwargs) -> dict[str, Any]: async def _import_excel(self, **kwargs) -> dict[str, object]:
file_path = kwargs.get("file_path") file_path = kwargs.get("file_path")
file_url = kwargs.get("file_url") file_url = kwargs.get("file_url")
if not file_path and not file_url: if not file_path and not file_url:
@ -201,13 +200,13 @@ class BitableTool(Tool):
if not sheets: if not sheets:
return {"success": False, "error": "Excel file has no sheets with data"} return {"success": False, "error": "Excel file has no sheets with data"}
results: list[dict[str, Any]] = [] results: list[dict[str, object]] = []
for sheet in sheets: for sheet in sheets:
result = await self._import_sheet(sheet) result = await self._import_sheet(sheet)
results.append(result) results.append(result)
return {"success": True, "sheets": results} return {"success": True, "sheets": results}
async def _import_sheet(self, sheet: ParsedSheet) -> dict[str, Any]: async def _import_sheet(self, sheet: ParsedSheet) -> dict[str, object]:
"""Create a bitable table from a parsed sheet and upsert all rows.""" """Create a bitable table from a parsed sheet and upsert all rows."""
client = await self._get_client() client = await self._get_client()
@ -253,13 +252,13 @@ class BitableTool(Tool):
} }
async def _batch_create_records( async def _batch_create_records(
self, table_id: str, records: list[dict[str, Any]] self, table_id: str, records: list[dict[str, object]]
) -> dict[str, Any]: ) -> dict[str, object]:
"""Create records in batches via POST /tables/{id}/records.""" """Create records in batches via POST /tables/{id}/records."""
client = await self._get_client() client = await self._get_client()
total = len(records) total = len(records)
successful = 0 successful = 0
errors: list[dict[str, Any]] = [] errors: list[dict[str, object]] = []
for start in range(0, total, BATCH_SIZE): for start in range(0, total, BATCH_SIZE):
batch = records[start : start + BATCH_SIZE] batch = records[start : start + BATCH_SIZE]
@ -292,7 +291,7 @@ class BitableTool(Tool):
# import_database # import_database
# ------------------------------------------------------------------ # ------------------------------------------------------------------
async def _import_database(self, **kwargs) -> dict[str, Any]: async def _import_database(self, **kwargs) -> dict[str, object]:
conn_str = kwargs.get("connection_string") conn_str = kwargs.get("connection_string")
table_names = kwargs.get("table_names") table_names = kwargs.get("table_names")
if not conn_str: if not conn_str:
@ -300,7 +299,7 @@ class BitableTool(Tool):
if not table_names: if not table_names:
return {"success": False, "error": "Missing required field: table_names"} return {"success": False, "error": "Missing required field: table_names"}
results: list[dict[str, Any]] = [] results: list[dict[str, object]] = []
for src_table in table_names: for src_table in table_names:
try: try:
# Offload sync DB reflection to thread pool (P2 #21-23). # Offload sync DB reflection to thread pool (P2 #21-23).
@ -313,7 +312,7 @@ class BitableTool(Tool):
results.append({"table_name": src_table, "success": False, "error": str(e)}) results.append({"table_name": src_table, "success": False, "error": str(e)})
return {"success": True, "tables": results} return {"success": True, "tables": results}
async def _import_reflected_table(self, reflected: dict[str, Any]) -> dict[str, Any]: async def _import_reflected_table(self, reflected: dict[str, object]) -> dict[str, object]:
"""Create a bitable table from reflected DB data and upsert rows.""" """Create a bitable table from reflected DB data and upsert rows."""
client = await self._get_client() client = await self._get_client()
table_name = reflected["table_name"] table_name = reflected["table_name"]
@ -376,7 +375,7 @@ class BitableTool(Tool):
# collect_api # collect_api
# ------------------------------------------------------------------ # ------------------------------------------------------------------
async def _collect_api(self, **kwargs) -> dict[str, Any]: async def _collect_api(self, **kwargs) -> dict[str, object]:
table_id = kwargs.get("table_id") table_id = kwargs.get("table_id")
records = kwargs.get("records") records = kwargs.get("records")
field_mapping = kwargs.get("field_mapping") field_mapping = kwargs.get("field_mapping")
@ -403,7 +402,7 @@ class BitableTool(Tool):
# upsert_records # upsert_records
# ------------------------------------------------------------------ # ------------------------------------------------------------------
async def _upsert_records(self, **kwargs) -> dict[str, Any]: async def _upsert_records(self, **kwargs) -> dict[str, object]:
table_id = kwargs.get("table_id") table_id = kwargs.get("table_id")
records = kwargs.get("records") records = kwargs.get("records")
pk_field_id = kwargs.get("primary_key_field_id") pk_field_id = kwargs.get("primary_key_field_id")
@ -421,13 +420,13 @@ class BitableTool(Tool):
return {"success": True, **result} return {"success": True, **result}
async def _batch_upsert( async def _batch_upsert(
self, table_id: str, records: list[dict[str, Any]], pk_field_id: str self, table_id: str, records: list[dict[str, object]], pk_field_id: str
) -> dict[str, Any]: ) -> dict[str, object]:
"""Upsert records in batches of BATCH_SIZE via POST /tables/{id}/upsert.""" """Upsert records in batches of BATCH_SIZE via POST /tables/{id}/upsert."""
client = await self._get_client() client = await self._get_client()
total = len(records) total = len(records)
successful = 0 successful = 0
errors: list[dict[str, Any]] = [] errors: list[dict[str, object]] = []
for start in range(0, total, BATCH_SIZE): for start in range(0, total, BATCH_SIZE):
batch = records[start : start + BATCH_SIZE] batch = records[start : start + BATCH_SIZE]
@ -464,13 +463,13 @@ class BitableTool(Tool):
# query_records # query_records
# ------------------------------------------------------------------ # ------------------------------------------------------------------
async def _query_records(self, **kwargs) -> dict[str, Any]: async def _query_records(self, **kwargs) -> dict[str, object]:
table_id = kwargs.get("table_id") table_id = kwargs.get("table_id")
if not table_id: if not table_id:
return {"success": False, "error": "Missing required field: table_id"} return {"success": False, "error": "Missing required field: table_id"}
client = await self._get_client() client = await self._get_client()
params: dict[str, Any] = {} params: dict[str, object] = {}
if kwargs.get("cursor"): if kwargs.get("cursor"):
params["cursor"] = kwargs["cursor"] params["cursor"] = kwargs["cursor"]
if kwargs.get("limit"): if kwargs.get("limit"):

View File

@ -3,7 +3,7 @@
from __future__ import annotations from __future__ import annotations
import logging import logging
from typing import TYPE_CHECKING, Any from typing import TYPE_CHECKING
from agentkit.tools.base import Tool from agentkit.tools.base import Tool
@ -24,8 +24,8 @@ class RunTestsTool(Tool):
self, self,
name: str = "run_tests", name: str = "run_tests",
description: str = "Run project tests to verify code changes. Executes pytest and linting commands.", description: str = "Run project tests to verify code changes. Executes pytest and linting commands.",
input_schema: dict[str, Any] | None = None, input_schema: dict[str, object] | None = None,
output_schema: dict[str, Any] | None = None, output_schema: dict[str, object] | None = None,
version: str = "1.0.0", version: str = "1.0.0",
tags: list[str] | None = None, tags: list[str] | None = None,
working_dir: str | None = None, working_dir: str | None = None,
@ -45,7 +45,7 @@ class RunTestsTool(Tool):
self._max_retries = max_retries self._max_retries = max_retries
@staticmethod @staticmethod
def _default_input_schema() -> dict[str, Any]: def _default_input_schema() -> dict[str, object]:
return { return {
"type": "object", "type": "object",
"properties": { "properties": {
@ -112,8 +112,8 @@ class ToolSearchTool(Tool):
"Returns full descriptions (name, description, parameters) of matching tools. " "Returns full descriptions (name, description, parameters) of matching tools. "
"Use this when you need details about a tool that was only listed by name." "Use this when you need details about a tool that was only listed by name."
), ),
input_schema: dict[str, Any] | None = None, input_schema: dict[str, object] | None = None,
output_schema: dict[str, Any] | None = None, output_schema: dict[str, object] | None = None,
version: str = "1.0.0", version: str = "1.0.0",
tags: list[str] | None = None, tags: list[str] | None = None,
top_k: int = 5, top_k: int = 5,
@ -176,7 +176,7 @@ class ToolSearchTool(Tool):
} }
@staticmethod @staticmethod
def _format_tool_full(tool: Tool) -> dict[str, Any]: def _format_tool_full(tool: Tool) -> dict[str, object]:
"""Format a tool's full description for the LLM.""" """Format a tool's full description for the LLM."""
return { return {
"name": tool.name, "name": tool.name,

View File

@ -13,7 +13,6 @@ from __future__ import annotations
import re import re
from datetime import datetime, timedelta from datetime import datetime, timedelta
from typing import Any
from agentkit.calendar.models import ReminderRule from agentkit.calendar.models import ReminderRule
from agentkit.calendar.service import CalendarService from agentkit.calendar.service import CalendarService
@ -321,14 +320,14 @@ class CalendarTool(Tool):
""" """
self._default_user_id = user_id self._default_user_id = user_id
def _resolve_user_id(self, kwargs: dict[str, Any]) -> str | None: def _resolve_user_id(self, kwargs: dict[str, object]) -> str | None:
"""Resolve user_id: prefer caller-provided, fall back to default.""" """Resolve user_id: prefer caller-provided, fall back to default."""
provided = kwargs.get("user_id") provided = kwargs.get("user_id")
if provided and isinstance(provided, str) and provided.strip(): if provided and isinstance(provided, str) and provided.strip():
return provided return provided
return self._default_user_id return self._default_user_id
async def execute(self, **kwargs) -> dict[str, Any]: async def execute(self, **kwargs) -> dict[str, object]:
action = kwargs.get("action") action = kwargs.get("action")
if action == "create_event": if action == "create_event":
@ -345,7 +344,7 @@ class CalendarTool(Tool):
# create_event # create_event
# ------------------------------------------------------------------ # ------------------------------------------------------------------
async def _create_event(self, **kwargs) -> dict[str, Any]: async def _create_event(self, **kwargs) -> dict[str, object]:
user_id = self._resolve_user_id(kwargs) user_id = self._resolve_user_id(kwargs)
title = kwargs.get("title") title = kwargs.get("title")
start_time = kwargs.get("start_time") start_time = kwargs.get("start_time")
@ -494,7 +493,7 @@ class CalendarTool(Tool):
# query_events # query_events
# ------------------------------------------------------------------ # ------------------------------------------------------------------
async def _query_events(self, **kwargs) -> dict[str, Any]: async def _query_events(self, **kwargs) -> dict[str, object]:
user_id = self._resolve_user_id(kwargs) user_id = self._resolve_user_id(kwargs)
if not user_id: if not user_id:
return {"success": False, "error": "Missing required field: user_id"} return {"success": False, "error": "Missing required field: user_id"}
@ -519,7 +518,7 @@ class CalendarTool(Tool):
# update_event # update_event
# ------------------------------------------------------------------ # ------------------------------------------------------------------
async def _update_event(self, **kwargs) -> dict[str, Any]: async def _update_event(self, **kwargs) -> dict[str, object]:
event_id = kwargs.get("event_id") event_id = kwargs.get("event_id")
user_id = self._resolve_user_id(kwargs) user_id = self._resolve_user_id(kwargs)
if not event_id: if not event_id:
@ -536,7 +535,7 @@ class CalendarTool(Tool):
# Build fields dict from updatable params (only those explicitly provided) # Build fields dict from updatable params (only those explicitly provided)
updatable = ["title", "description", "location", "is_all_day"] updatable = ["title", "description", "location", "is_all_day"]
fields: dict[str, Any] = {} fields: dict[str, object] = {}
for key in updatable: for key in updatable:
if key in kwargs and kwargs[key] is not None: if key in kwargs and kwargs[key] is not None:
fields[key] = kwargs[key] fields[key] = kwargs[key]
@ -565,7 +564,7 @@ class CalendarTool(Tool):
# delete_event # delete_event
# ------------------------------------------------------------------ # ------------------------------------------------------------------
async def _delete_event(self, **kwargs) -> dict[str, Any]: async def _delete_event(self, **kwargs) -> dict[str, object]:
event_id = kwargs.get("event_id") event_id = kwargs.get("event_id")
user_id = self._resolve_user_id(kwargs) user_id = self._resolve_user_id(kwargs)
if not event_id: if not event_id:

View File

@ -9,7 +9,6 @@
import asyncio import asyncio
import json import json
import logging import logging
from typing import Any
from agentkit.tools.base import Tool from agentkit.tools.base import Tool
@ -137,7 +136,7 @@ class DynamicSelector(Tool):
description: str, description: str,
tools: list[Tool], tools: list[Tool],
mode: str = "keyword", mode: str = "keyword",
llm_client: Any = None, llm_client: object = None,
version: str = "1.0.0", version: str = "1.0.0",
tags: list[str] | None = None, tags: list[str] | None = None,
): ):

View File

@ -10,7 +10,7 @@ from __future__ import annotations
import asyncio import asyncio
import base64 import base64
import logging import logging
from typing import Any, Callable, Awaitable from typing import Callable, Awaitable
import httpx import httpx
@ -62,8 +62,8 @@ class ComputerUseTool(Tool):
self, self,
name: str = "computer_use", name: str = "computer_use",
description: str = "Anthropic Computer Use API 集成,支持截屏识别和 UI 操作", description: str = "Anthropic Computer Use API 集成,支持截屏识别和 UI 操作",
input_schema: dict[str, Any] | None = None, input_schema: dict[str, object] | None = None,
output_schema: dict[str, Any] | None = None, output_schema: dict[str, object] | None = None,
version: str = "1.0.0", version: str = "1.0.0",
tags: list[str] | None = None, tags: list[str] | None = None,
api_key: str | None = None, api_key: str | None = None,
@ -71,7 +71,7 @@ class ComputerUseTool(Tool):
api_base_url: str = _ANTHROPIC_COMPUTER_USE_URL, api_base_url: str = _ANTHROPIC_COMPUTER_USE_URL,
session_factory: type[ComputerUseSession] | None = None, session_factory: type[ComputerUseSession] | None = None,
recorder: ComputerUseRecorder | None = None, recorder: ComputerUseRecorder | None = None,
fallback_callback: Callable[[str, dict[str, Any]], Awaitable[dict[str, Any]]] | None = None, fallback_callback: Callable[[str, dict[str, object]], Awaitable[dict[str, object]]] | None = None,
max_retries: int = 1, max_retries: int = 1,
request_timeout: float = 30.0, request_timeout: float = 30.0,
): ):
@ -112,7 +112,7 @@ class ComputerUseTool(Tool):
await self._http_client.aclose() await self._http_client.aclose()
@staticmethod @staticmethod
def _default_input_schema() -> dict[str, Any]: def _default_input_schema() -> dict[str, object]:
return { return {
"type": "object", "type": "object",
"properties": { "properties": {
@ -177,7 +177,7 @@ class ComputerUseTool(Tool):
} }
@staticmethod @staticmethod
def _default_output_schema() -> dict[str, Any]: def _default_output_schema() -> dict[str, object]:
return { return {
"type": "object", "type": "object",
"properties": { "properties": {
@ -254,7 +254,7 @@ class ComputerUseTool(Tool):
self, self,
session: ComputerUseSession, session: ComputerUseSession,
action: str, action: str,
params: dict[str, Any], params: dict[str, object],
) -> ActionResult: ) -> ActionResult:
"""带降级链的操作执行 """带降级链的操作执行
@ -318,14 +318,14 @@ class ComputerUseTool(Tool):
self, self,
session: ComputerUseSession, session: ComputerUseSession,
action: str, action: str,
params: dict[str, Any], params: dict[str, object],
) -> ActionResult: ) -> ActionResult:
"""调用 Anthropic Computer Use API """调用 Anthropic Computer Use API
通过 Anthropic Messages API 发送 computer_use_tool 请求 通过 Anthropic Messages API 发送 computer_use_tool 请求
""" """
# 构造 computer_use 工具调用参数 # 构造 computer_use 工具调用参数
tool_input: dict[str, Any] = {"action": action} tool_input: dict[str, object] = {"action": action}
if action == "click": if action == "click":
tool_input["coordinate"] = [params.get("x", 0), params.get("y", 0)] tool_input["coordinate"] = [params.get("x", 0), params.get("y", 0)]
elif action == "type": elif action == "type":
@ -354,7 +354,7 @@ class ComputerUseTool(Tool):
screenshot_b64 = screenshot_result.screenshot_base64 screenshot_b64 = screenshot_result.screenshot_base64
# 构造 API 请求 # 构造 API 请求
content_blocks: list[dict[str, Any]] = [] content_blocks: list[dict[str, object]] = []
if screenshot_b64: if screenshot_b64:
content_blocks.append({ content_blocks.append({
"type": "image", "type": "image",
@ -437,7 +437,7 @@ class ComputerUseTool(Tool):
metadata={"api_response": data}, metadata={"api_response": data},
) )
def _validate_params(self, action: str, kwargs: dict[str, Any]) -> str | None: def _validate_params(self, action: str, kwargs: dict[str, object]) -> str | None:
"""验证操作参数 """验证操作参数
Returns: Returns:
@ -459,9 +459,9 @@ class ComputerUseTool(Tool):
return f"drag 操作需要 {', '.join(missing)} 参数" return f"drag 操作需要 {', '.join(missing)} 参数"
return None return None
def _format_result(self, result: ActionResult, session_id: str) -> dict[str, Any]: def _format_result(self, result: ActionResult, session_id: str) -> dict[str, object]:
"""格式化操作结果""" """格式化操作结果"""
formatted: dict[str, Any] = { formatted: dict[str, object] = {
"success": result.success, "success": result.success,
"action": result.action, "action": result.action,
"output": result.output, "output": result.output,
@ -482,9 +482,9 @@ class ComputerUseTool(Tool):
action: str, action: str,
error: str, error: str,
fallback: str = "", fallback: str = "",
) -> dict[str, Any]: ) -> dict[str, object]:
"""构造错误结果""" """构造错误结果"""
result: dict[str, Any] = { result: dict[str, object] = {
"success": False, "success": False,
"action": action, "action": action,
"error": error, "error": error,

View File

@ -11,7 +11,6 @@ import logging
import time import time
from dataclasses import asdict, dataclass, field from dataclasses import asdict, dataclass, field
from pathlib import Path from pathlib import Path
from typing import Any
from agentkit.tools.computer_use_session import ComputerUseSession, ActionResult from agentkit.tools.computer_use_session import ComputerUseSession, ActionResult
@ -27,17 +26,17 @@ class ActionRecord:
timestamp: float timestamp: float
action: str action: str
params: dict[str, Any] = field(default_factory=dict) params: dict[str, object] = field(default_factory=dict)
success: bool = False success: bool = False
output: str = "" output: str = ""
error: str = "" error: str = ""
screenshot_path: str = "" screenshot_path: str = ""
def to_dict(self) -> dict[str, Any]: def to_dict(self) -> dict[str, object]:
return asdict(self) return asdict(self)
@classmethod @classmethod
def from_dict(cls, data: dict[str, Any]) -> ActionRecord: def from_dict(cls, data: dict[str, object]) -> ActionRecord:
return cls(**data) return cls(**data)
@ -69,7 +68,7 @@ class ComputerUseRecorder:
def record( def record(
self, self,
action: str, action: str,
params: dict[str, Any], params: dict[str, object],
result: ActionResult, result: ActionResult,
screenshot_path: str = "", screenshot_path: str = "",
) -> ActionRecord: ) -> ActionRecord:
@ -220,7 +219,7 @@ class ComputerUseRecorder:
"""失败操作数""" """失败操作数"""
return sum(1 for r in self._records if not r.success) return sum(1 for r in self._records if not r.success)
def summary(self) -> dict[str, Any]: def summary(self) -> dict[str, object]:
"""生成录制摘要""" """生成录制摘要"""
return { return {
"total_actions": self.total_actions, "total_actions": self.total_actions,

View File

@ -7,7 +7,6 @@ handle documents via function calling. U6 implements "create"; U9 adds "read".
from __future__ import annotations from __future__ import annotations
from pathlib import Path from pathlib import Path
from typing import Any
from agentkit.documents.service import DocumentService from agentkit.documents.service import DocumentService
from agentkit.memory.document_loader import DocumentLoader from agentkit.memory.document_loader import DocumentLoader
@ -81,7 +80,7 @@ class DocumentTool(Tool):
self._service = service self._service = service
self._loader = loader or DocumentLoader() self._loader = loader or DocumentLoader()
async def execute(self, **kwargs) -> dict[str, Any]: async def execute(self, **kwargs) -> dict[str, object]:
action = kwargs.get("action", "create") action = kwargs.get("action", "create")
if action == "read": if action == "read":
@ -90,7 +89,7 @@ class DocumentTool(Tool):
return await self._execute_create(**kwargs) return await self._execute_create(**kwargs)
return {"success": False, "error": f"Unknown action: {action!r} (use 'create' or 'read')"} return {"success": False, "error": f"Unknown action: {action!r} (use 'create' or 'read')"}
async def _execute_create(self, **kwargs) -> dict[str, Any]: async def _execute_create(self, **kwargs) -> dict[str, object]:
format_key = kwargs.get("format", "") format_key = kwargs.get("format", "")
content = kwargs.get("content", "") content = kwargs.get("content", "")
conversation_id = kwargs.get("conversation_id", "") conversation_id = kwargs.get("conversation_id", "")
@ -129,7 +128,7 @@ class DocumentTool(Tool):
except Exception as e: except Exception as e:
return {"success": False, "error": f"Document creation failed: {e}"} return {"success": False, "error": f"Document creation failed: {e}"}
async def _execute_read(self, **kwargs) -> dict[str, Any]: async def _execute_read(self, **kwargs) -> dict[str, object]:
file_path = kwargs.get("filename") or kwargs.get("content") file_path = kwargs.get("filename") or kwargs.get("content")
if not file_path: if not file_path:
return {"success": False, "error": "filename (file path) is required for read"} return {"success": False, "error": "filename (file path) is required for read"}

View File

@ -12,7 +12,6 @@ from __future__ import annotations
import logging import logging
from pathlib import Path from pathlib import Path
from typing import Any
from agentkit.tools.base import Tool from agentkit.tools.base import Tool
from agentkit.tools.symbol_extractor import ( from agentkit.tools.symbol_extractor import (
@ -40,8 +39,8 @@ class ReadFileTool(Tool):
self, self,
name: str = "read_file", name: str = "read_file",
description: str | None = None, description: str | None = None,
input_schema: dict[str, Any] | None = None, input_schema: dict[str, object] | None = None,
output_schema: dict[str, Any] | None = None, output_schema: dict[str, object] | None = None,
version: str = "1.0.0", version: str = "1.0.0",
tags: list[str] | None = None, tags: list[str] | None = None,
): ):
@ -63,7 +62,7 @@ class ReadFileTool(Tool):
) )
@staticmethod @staticmethod
def _default_input_schema() -> dict[str, Any]: def _default_input_schema() -> dict[str, object]:
return { return {
"type": "object", "type": "object",
"properties": { "properties": {
@ -95,7 +94,7 @@ class ReadFileTool(Tool):
} }
@staticmethod @staticmethod
def _default_output_schema() -> dict[str, Any]: def _default_output_schema() -> dict[str, object]:
return { return {
"type": "object", "type": "object",
"properties": { "properties": {
@ -115,7 +114,7 @@ class ReadFileTool(Tool):
}, },
} }
async def execute(self, **kwargs) -> dict[str, Any]: async def execute(self, **kwargs) -> dict[str, object]:
raw_path = kwargs.get("path") raw_path = kwargs.get("path")
if not raw_path: if not raw_path:
return self._error("`path` is required") return self._error("`path` is required")
@ -235,8 +234,8 @@ class ReadFileTool(Tool):
@staticmethod @staticmethod
def _error( def _error(
message: str, *, path: str | None = None, detail: str | None = None message: str, *, path: str | None = None, detail: str | None = None
) -> dict[str, Any]: ) -> dict[str, object]:
result: dict[str, Any] = { result: dict[str, object] = {
"content": "", "content": "",
"is_error": True, "is_error": True,
"error": message, "error": message,

View File

@ -1,7 +1,7 @@
"""FunctionTool - 将普通 Python 函数包装为 Tool""" """FunctionTool - 将普通 Python 函数包装为 Tool"""
import inspect import inspect
from typing import Any, Callable, Awaitable from typing import Callable, Awaitable
from agentkit.tools.base import Tool from agentkit.tools.base import Tool
@ -17,8 +17,8 @@ class FunctionTool(Tool):
name: str, name: str,
description: str, description: str,
func: Callable[..., Awaitable[dict]] | Callable[..., dict], func: Callable[..., Awaitable[dict]] | Callable[..., dict],
input_schema: dict[str, Any] | None = None, input_schema: dict[str, object] | None = None,
output_schema: dict[str, Any] | None = None, output_schema: dict[str, object] | None = None,
version: str = "1.0.0", version: str = "1.0.0",
tags: list[str] | None = None, tags: list[str] | None = None,
): ):

View File

@ -6,7 +6,6 @@
""" """
import logging import logging
from typing import Any
from agentkit.tools.base import Tool from agentkit.tools.base import Tool
@ -20,7 +19,7 @@ class HeadroomRetrieveTool(Tool):
压缩内容中包含 <!-- CCR:hash=xxx --> 标记LLM 可使用该哈希值检索 压缩内容中包含 <!-- CCR:hash=xxx --> 标记LLM 可使用该哈希值检索
""" """
def __init__(self, compressor: Any): def __init__(self, compressor: object):
super().__init__( super().__init__(
name="headroom_retrieve", name="headroom_retrieve",
description=( description=(

View File

@ -2,7 +2,6 @@
import json import json
import logging import logging
from typing import Any
from agentkit.tools.base import Tool from agentkit.tools.base import Tool
@ -20,9 +19,9 @@ class MCPTool(Tool):
self, self,
name: str, name: str,
description: str, description: str,
client: Any, client: object,
input_schema: dict[str, Any] | None = None, input_schema: dict[str, object] | None = None,
output_schema: dict[str, Any] | None = None, output_schema: dict[str, object] | None = None,
version: str = "1.0.0", version: str = "1.0.0",
tags: list[str] | None = None, tags: list[str] | None = None,
): ):

View File

@ -14,7 +14,6 @@ from __future__ import annotations
import re import re
from datetime import datetime, timezone from datetime import datetime, timezone
from typing import Any
from agentkit.memory.profile import MemoryFile, MemoryStore from agentkit.memory.profile import MemoryFile, MemoryStore
from agentkit.tools.base import Tool from agentkit.tools.base import Tool
@ -75,7 +74,7 @@ class MemoryTool(Tool):
) )
self._store = memory_store self._store = memory_store
async def execute(self, **kwargs) -> dict[str, Any]: async def execute(self, **kwargs) -> dict[str, object]:
action = kwargs.get("action", "") action = kwargs.get("action", "")
file_key = kwargs.get("file", "") file_key = kwargs.get("file", "")
@ -150,7 +149,7 @@ class MemoryTool(Tool):
async def _update_soul( async def _update_soul(
self, mf: MemoryFile, section: str, content: str, reason: str self, mf: MemoryFile, section: str, content: str, reason: str
) -> dict[str, Any]: ) -> dict[str, object]:
"""执行 SOUL 动态更新,带版本追踪和更新历史. """执行 SOUL 动态更新,带版本追踪和更新历史.
采用原子写入策略先在内存中构建完整内容再一次性写入文件 采用原子写入策略先在内存中构建完整内容再一次性写入文件

View File

@ -8,7 +8,6 @@ from __future__ import annotations
import re import re
from dataclasses import dataclass, field from dataclasses import dataclass, field
from enum import Enum from enum import Enum
from typing import Any
class ErrorType(Enum): class ErrorType(Enum):
@ -49,7 +48,7 @@ class ParsedOutput:
raw_output: str = "" raw_output: str = ""
suggestions: list[str] = field(default_factory=list) suggestions: list[str] = field(default_factory=list)
def to_dict(self) -> dict[str, Any]: def to_dict(self) -> dict[str, object]:
return { return {
"exit_code": self.exit_code, "exit_code": self.exit_code,
"is_error": self.is_error, "is_error": self.is_error,

View File

@ -1,7 +1,6 @@
"""ToolRegistry - 工具注册中心""" """ToolRegistry - 工具注册中心"""
import logging import logging
from typing import Any
from agentkit.core.exceptions import ToolNotFoundError from agentkit.core.exceptions import ToolNotFoundError
from agentkit.tools.base import Tool from agentkit.tools.base import Tool

View File

@ -6,7 +6,6 @@ SchemaGenerateTool: 生成 Schema.org JSON-LD 标记
import json import json
import logging import logging
from typing import Any
import httpx import httpx
@ -47,8 +46,8 @@ class SchemaExtractTool(Tool):
self, self,
name: str = "schema_extract", name: str = "schema_extract",
description: str = "从网页 HTML 中提取结构化数据JSON-LD、Microdata、RDFa 等)", description: str = "从网页 HTML 中提取结构化数据JSON-LD、Microdata、RDFa 等)",
input_schema: dict[str, Any] | None = None, input_schema: dict[str, object] | None = None,
output_schema: dict[str, Any] | None = None, output_schema: dict[str, object] | None = None,
version: str = "1.0.0", version: str = "1.0.0",
tags: list[str] | None = None, tags: list[str] | None = None,
): ):
@ -62,7 +61,7 @@ class SchemaExtractTool(Tool):
) )
@staticmethod @staticmethod
def _default_input_schema() -> dict[str, Any]: def _default_input_schema() -> dict[str, object]:
return { return {
"type": "object", "type": "object",
"properties": { "properties": {
@ -81,7 +80,7 @@ class SchemaExtractTool(Tool):
} }
@staticmethod @staticmethod
def _default_output_schema() -> dict[str, Any]: def _default_output_schema() -> dict[str, object]:
return { return {
"type": "object", "type": "object",
"properties": { "properties": {
@ -164,7 +163,7 @@ class SchemaExtractTool(Tool):
) )
# 整理结果 # 整理结果
schemas: list[dict[str, Any]] = [] schemas: list[dict[str, object]] = []
for fmt in formats: for fmt in formats:
items = data.get(fmt, []) items = data.get(fmt, [])
if items: if items:
@ -206,8 +205,8 @@ class SchemaGenerateTool(Tool):
self, self,
name: str = "schema_generate", name: str = "schema_generate",
description: str = "生成 Schema.org JSON-LD 结构化数据标记", description: str = "生成 Schema.org JSON-LD 结构化数据标记",
input_schema: dict[str, Any] | None = None, input_schema: dict[str, object] | None = None,
output_schema: dict[str, Any] | None = None, output_schema: dict[str, object] | None = None,
version: str = "1.0.0", version: str = "1.0.0",
tags: list[str] | None = None, tags: list[str] | None = None,
): ):
@ -221,7 +220,7 @@ class SchemaGenerateTool(Tool):
) )
@staticmethod @staticmethod
def _default_input_schema() -> dict[str, Any]: def _default_input_schema() -> dict[str, object]:
return { return {
"type": "object", "type": "object",
"properties": { "properties": {
@ -238,7 +237,7 @@ class SchemaGenerateTool(Tool):
} }
@staticmethod @staticmethod
def _default_output_schema() -> dict[str, Any]: def _default_output_schema() -> dict[str, object]:
return { return {
"type": "object", "type": "object",
"properties": { "properties": {
@ -249,16 +248,16 @@ class SchemaGenerateTool(Tool):
}, },
} }
def _generate_manual(self, schema_type: str, properties: dict[str, Any]) -> str: def _generate_manual(self, schema_type: str, properties: dict[str, object]) -> str:
"""手动构建 JSON-LD无需外部依赖""" """手动构建 JSON-LD无需外部依赖"""
jsonld_obj: dict[str, Any] = { jsonld_obj: dict[str, object] = {
"@context": "https://schema.org", "@context": "https://schema.org",
"@type": schema_type, "@type": schema_type,
} }
jsonld_obj.update(properties) jsonld_obj.update(properties)
return json.dumps(jsonld_obj, ensure_ascii=False, indent=2) return json.dumps(jsonld_obj, ensure_ascii=False, indent=2)
def _generate_with_schemaorg(self, schema_type: str, properties: dict[str, Any]) -> str | None: def _generate_with_schemaorg(self, schema_type: str, properties: dict[str, object]) -> str | None:
"""使用 pydantic-schemaorg 生成 JSON-LD带验证""" """使用 pydantic-schemaorg 生成 JSON-LD带验证"""
if not _PYDANTIC_SCHEMAORG_AVAILABLE: if not _PYDANTIC_SCHEMAORG_AVAILABLE:
return None return None
@ -278,7 +277,7 @@ class SchemaGenerateTool(Tool):
else: else:
return None return None
jsonld_obj: dict[str, Any] = { jsonld_obj: dict[str, object] = {
"@context": "https://schema.org", "@context": "https://schema.org",
"@type": schema_type, "@type": schema_type,
} }

View File

@ -12,7 +12,6 @@ from __future__ import annotations
import math import math
import re import re
from collections import Counter from collections import Counter
from typing import Any
from agentkit.tools.base import Tool from agentkit.tools.base import Tool
@ -92,7 +91,7 @@ class ToolSearchIndex:
"""Convert a tool's searchable metadata into a single text document.""" """Convert a tool's searchable metadata into a single text document."""
parts: list[str] = [str(tool.name), str(tool.description)] parts: list[str] = [str(tool.name), str(tool.description)]
schema: dict[str, Any] | None = tool.input_schema schema: dict[str, object] | None = tool.input_schema
if schema: if schema:
props = schema.get("properties", {}) props = schema.get("properties", {})
for pname, pinfo in props.items(): for pname, pinfo in props.items():

View File

@ -14,7 +14,7 @@ import shlex
import time import time
import uuid import uuid
from collections import deque from collections import deque
from typing import Any, Callable, Awaitable from typing import Callable, Awaitable
from agentkit.tools.base import Tool from agentkit.tools.base import Tool
from agentkit.tools.output_parser import OutputParser, ParsedOutput from agentkit.tools.output_parser import OutputParser, ParsedOutput
@ -232,8 +232,8 @@ class ShellTool(Tool):
self, self,
name: str = "shell", name: str = "shell",
description: str = "执行 Shell 命令,支持会话模式保持跨命令状态", description: str = "执行 Shell 命令,支持会话模式保持跨命令状态",
input_schema: dict[str, Any] | None = None, input_schema: dict[str, object] | None = None,
output_schema: dict[str, Any] | None = None, output_schema: dict[str, object] | None = None,
version: str = "1.0.0", version: str = "1.0.0",
tags: list[str] | None = None, tags: list[str] | None = None,
confirm_callback: Callable[[str], Awaitable[bool]] | None = None, confirm_callback: Callable[[str], Awaitable[bool]] | None = None,
@ -253,10 +253,10 @@ class ShellTool(Tool):
self._confirm_callback = confirm_callback self._confirm_callback = confirm_callback
self._default_timeout = default_timeout self._default_timeout = default_timeout
self._max_output_length = max_output_length self._max_output_length = max_output_length
self._audit_log: deque[dict[str, Any]] = deque(maxlen=10000) self._audit_log: deque[dict[str, object]] = deque(maxlen=10000)
@staticmethod @staticmethod
def _default_input_schema() -> dict[str, Any]: def _default_input_schema() -> dict[str, object]:
return { return {
"type": "object", "type": "object",
"properties": { "properties": {
@ -287,7 +287,7 @@ class ShellTool(Tool):
} }
@staticmethod @staticmethod
def _default_output_schema() -> dict[str, Any]: def _default_output_schema() -> dict[str, object]:
return { return {
"type": "object", "type": "object",
"properties": { "properties": {
@ -613,6 +613,6 @@ class ShellTool(Tool):
return self._session_manager return self._session_manager
@property @property
def audit_log(self) -> list[dict[str, Any]]: def audit_log(self) -> list[dict[str, object]]:
"""获取审计日志(副本)""" """获取审计日志(副本)"""
return list(self._audit_log) return list(self._audit_log)

View File

@ -4,7 +4,7 @@ import asyncio
import logging import logging
import os import os
import re import re
from typing import Any, Callable, Awaitable from typing import Callable, Awaitable
from agentkit.tools.base import Tool from agentkit.tools.base import Tool
@ -34,8 +34,8 @@ class SkillInstallTool(Tool):
"重要:安装前应先用 skill_search 工具搜索确认技能名称和来源(source)。" "重要:安装前应先用 skill_search 工具搜索确认技能名称和来源(source)。"
"如果用户只提供了模糊名称,先用 skill_search 搜索,再根据搜索结果安装。" "如果用户只提供了模糊名称,先用 skill_search 搜索,再根据搜索结果安装。"
), ),
input_schema: dict[str, Any] | None = None, input_schema: dict[str, object] | None = None,
output_schema: dict[str, Any] | None = None, output_schema: dict[str, object] | None = None,
version: str = "1.0.0", version: str = "1.0.0",
tags: list[str] | None = None, tags: list[str] | None = None,
confirm_callback: Callable[[str], Awaitable[bool]] | None = None, confirm_callback: Callable[[str], Awaitable[bool]] | None = None,

View File

@ -2,7 +2,6 @@
import asyncio import asyncio
import logging import logging
from typing import Any
from agentkit.tools.base import Tool from agentkit.tools.base import Tool
@ -27,8 +26,8 @@ class SkillSearchTool(Tool):
"搜索可用的 Agent 技能包。在安装技能之前,应先使用此工具搜索确认技能名称和来源。" "搜索可用的 Agent 技能包。在安装技能之前,应先使用此工具搜索确认技能名称和来源。"
"返回匹配的技能列表,包含名称、描述和安装来源。" "返回匹配的技能列表,包含名称、描述和安装来源。"
), ),
input_schema: dict[str, Any] | None = None, input_schema: dict[str, object] | None = None,
output_schema: dict[str, Any] | None = None, output_schema: dict[str, object] | None = None,
version: str = "1.0.0", version: str = "1.0.0",
tags: list[str] | None = None, tags: list[str] | None = None,
): ):

View File

@ -14,7 +14,6 @@ import shlex
import time import time
from collections import deque from collections import deque
from dataclasses import dataclass, field from dataclasses import dataclass, field
from typing import Any
from agentkit.tools.output_parser import OutputParser, ParsedOutput from agentkit.tools.output_parser import OutputParser, ParsedOutput

View File

@ -1,7 +1,6 @@
"""WebCrawlTool - 基于 Crawl4AI 的网页抓取工具,支持优雅降级""" """WebCrawlTool - 基于 Crawl4AI 的网页抓取工具,支持优雅降级"""
import logging import logging
from typing import Any
from agentkit.tools.base import Tool from agentkit.tools.base import Tool
@ -31,8 +30,8 @@ class WebCrawlTool(Tool):
self, self,
name: str = "web_crawl", name: str = "web_crawl",
description: str = "抓取网页内容,支持 Markdown/HTML 输出和 CSS 选择器提取", description: str = "抓取网页内容,支持 Markdown/HTML 输出和 CSS 选择器提取",
input_schema: dict[str, Any] | None = None, input_schema: dict[str, object] | None = None,
output_schema: dict[str, Any] | None = None, output_schema: dict[str, object] | None = None,
version: str = "1.0.0", version: str = "1.0.0",
tags: list[str] | None = None, tags: list[str] | None = None,
): ):
@ -46,7 +45,7 @@ class WebCrawlTool(Tool):
) )
@staticmethod @staticmethod
def _default_input_schema() -> dict[str, Any]: def _default_input_schema() -> dict[str, object]:
return { return {
"type": "object", "type": "object",
"properties": { "properties": {
@ -74,7 +73,7 @@ class WebCrawlTool(Tool):
} }
@staticmethod @staticmethod
def _default_output_schema() -> dict[str, Any]: def _default_output_schema() -> dict[str, object]:
return { return {
"type": "object", "type": "object",
"properties": { "properties": {
@ -142,7 +141,7 @@ class WebCrawlTool(Tool):
status_code = result.status_code if hasattr(result, "status_code") else 200 status_code = result.status_code if hasattr(result, "status_code") else 200
response: dict[str, Any] = { response: dict[str, object] = {
"content": content, "content": content,
"status_code": status_code, "status_code": status_code,
"links": links, "links": links,

View File

@ -10,7 +10,6 @@ import json
import logging import logging
import re import re
import urllib.parse import urllib.parse
from typing import Any
import httpx import httpx
@ -32,8 +31,8 @@ class WebSearchTool(Tool):
self, self,
name: str = "web_search", name: str = "web_search",
description: str = "搜索互联网信息。返回搜索结果列表,包含标题、链接和摘要。", description: str = "搜索互联网信息。返回搜索结果列表,包含标题、链接和摘要。",
input_schema: dict[str, Any] | None = None, input_schema: dict[str, object] | None = None,
output_schema: dict[str, Any] | None = None, output_schema: dict[str, object] | None = None,
version: str = "1.0.0", version: str = "1.0.0",
tags: list[str] | None = None, tags: list[str] | None = None,
tavily_api_key: str | None = None, tavily_api_key: str | None = None,
@ -53,7 +52,7 @@ class WebSearchTool(Tool):
self._default_max_results = default_max_results self._default_max_results = default_max_results
@staticmethod @staticmethod
def _default_input_schema() -> dict[str, Any]: def _default_input_schema() -> dict[str, object]:
return { return {
"type": "object", "type": "object",
"properties": { "properties": {
@ -71,7 +70,7 @@ class WebSearchTool(Tool):
} }
@staticmethod @staticmethod
def _default_output_schema() -> dict[str, Any]: def _default_output_schema() -> dict[str, object]:
return { return {
"type": "object", "type": "object",
"properties": { "properties": {