refactor: tech debt Wave 3+4 (tools/skills/mcp/rag/calendar/auth/cli/quality/channels/telemetry/session/bus/documents Any 治理) #11
|
|
@ -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"] = {
|
||||||
|
|
|
||||||
|
|
@ -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():
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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),
|
||||||
|
|
|
||||||
|
|
@ -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()
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -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": {
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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"):
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
):
|
):
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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"}
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
):
|
):
|
||||||
|
|
|
||||||
|
|
@ -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=(
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
):
|
):
|
||||||
|
|
|
||||||
|
|
@ -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 动态更新,带版本追踪和更新历史.
|
||||||
|
|
||||||
采用原子写入策略:先在内存中构建完整内容,再一次性写入文件,
|
采用原子写入策略:先在内存中构建完整内容,再一次性写入文件,
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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():
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
):
|
):
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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": {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue