This commit is contained in:
tcmofashi
2026-04-03 23:18:30 +08:00
parent 185361f2c3
commit 7b9e1cf925
40 changed files with 52 additions and 86 deletions

View File

@@ -6,7 +6,7 @@ without the overhead of an Agent.
import asyncio
from agentlite import LLMClient, llm_complete, llm_stream
from agentlite import LLMClient
from agentlite.config import AgentConfig, ProviderConfig, ModelConfig
@@ -55,7 +55,7 @@ async def main():
)
# Create client
client = LLMClient(config)
LLMClient(config)
# Make a call
# response = await client.complete(
@@ -91,7 +91,7 @@ async def main():
temperature=0.8,
)
client = LLMClient(provider=provider)
LLMClient(provider=provider)
# response = await client.complete(
# user_prompt="What are the benefits of type hints?",

View File

@@ -6,8 +6,7 @@ This example shows how to use skills with an Agent.
import asyncio
from pathlib import Path
from agentlite import Agent, OpenAIProvider
from agentlite.skills import discover_skills, index_skills_by_name, SkillTool
from agentlite.skills import discover_skills, index_skills_by_name
async def main():

View File

@@ -7,7 +7,6 @@ and delegate tasks to them using the Task tool.
import asyncio
from agentlite import Agent, OpenAIProvider
from agentlite.labor_market import LaborMarket
from agentlite.tools.multiagent.task import Task
@@ -61,8 +60,8 @@ async def main():
parent.tools.add(Task(labor_market=parent.labor_market))
print("Created parent agent with subagents:")
print(f" - coder: Writes code")
print(f" - reviewer: Reviews code")
print(" - coder: Writes code")
print(" - reviewer: Reviews code")
# Example 2: Using subagents
print("\n=== Example 2: Delegating Tasks ===")

View File

@@ -7,7 +7,6 @@ to enable/disable specific tools.
import asyncio
from pathlib import Path
from agentlite import Agent, OpenAIProvider
from agentlite.tools import (
ConfigurableToolset,
ToolSuiteConfig,
@@ -57,7 +56,7 @@ async def main():
)
)
toolset = ConfigurableToolset(config)
print(f"File tool settings:")
print("File tool settings:")
print(f" Max lines: {config.file_tools.max_lines}")
print(f" Max bytes: {config.file_tools.max_bytes}")
print(f" Allow outside work dir: {config.file_tools.allow_write_outside_work_dir}")
@@ -66,7 +65,7 @@ async def main():
print("\n=== Example 5: Using with Agent ===")
# Create a safe configuration (no shell, no write outside work dir)
safe_config = ToolSuiteConfig(
ToolSuiteConfig(
file_tools=FileToolsConfig(
allow_write_outside_work_dir=False,
),

View File

@@ -8,7 +8,7 @@ from __future__ import annotations
import asyncio
from collections.abc import AsyncIterator, Sequence
from typing import TYPE_CHECKING, Any, Optional
from typing import TYPE_CHECKING
from agentlite.message import (
ContentPart,
@@ -17,8 +17,8 @@ from agentlite.message import (
ToolCall,
ToolCallPart,
)
from agentlite.provider import ChatProvider, StreamedMessage, TokenUsage
from agentlite.tool import SimpleToolset, Tool, ToolResult, ToolType
from agentlite.provider import ChatProvider
from agentlite.tool import SimpleToolset, ToolResult, ToolType
from agentlite.labor_market import LaborMarket
if TYPE_CHECKING:
@@ -311,7 +311,7 @@ class Agent:
# Execute all tool calls concurrently
futures = [self.tools.handle(tc) for tc in tool_calls]
for tc, future in zip(tool_calls, futures):
for tc, future in zip(tool_calls, futures, strict=False):
try:
if asyncio.isfuture(future):
result = await future

View File

@@ -6,7 +6,7 @@ models, and agent settings.
from __future__ import annotations
from typing import Any, Literal, Optional, Union
from typing import Literal, Optional
from pydantic import BaseModel, Field, SecretStr, model_validator

View File

@@ -32,11 +32,10 @@ from __future__ import annotations
from collections.abc import AsyncIterator
from typing import Optional
from agentlite.config import AgentConfig, ModelConfig, ProviderConfig
from agentlite.config import AgentConfig
from agentlite.message import Message, TextPart
from agentlite.provider import ChatProvider, TokenUsage
from agentlite.providers.openai import OpenAIProvider
from agentlite.tool import Tool
class LLMResponse:
@@ -174,7 +173,7 @@ class LLMClient:
try:
if usage is None and hasattr(stream, "usage") and stream.usage:
usage = stream.usage
except:
except Exception:
pass
content = "".join(content_parts)

View File

@@ -6,10 +6,8 @@ tools from external MCP-compatible servers.
from __future__ import annotations
import asyncio
from typing import TYPE_CHECKING, Any
from agentlite.message import TextPart
from agentlite.tool import CallableTool, ToolOk, ToolResult, ToolError
if TYPE_CHECKING:

View File

@@ -7,7 +7,7 @@ and provides the base types for streaming responses.
from __future__ import annotations
from collections.abc import AsyncIterator, Sequence
from typing import Protocol, runtime_checkable
from typing import Protocol, Union, runtime_checkable
from pydantic import BaseModel
@@ -44,8 +44,6 @@ class TokenUsage(BaseModel):
return self.input_tokens + self.output_tokens
from typing import Union
StreamedPart = Union[ContentPart, ToolCall, ToolCallPart]

View File

@@ -13,7 +13,6 @@ from typing import TYPE_CHECKING, Any
import httpx
from openai import AsyncOpenAI, OpenAIError
from openai.types.chat import (
ChatCompletion,
ChatCompletionChunk,
ChatCompletionMessageParam,
ChatCompletionToolParam,
@@ -27,7 +26,6 @@ from agentlite.message import (
)
from agentlite.provider import (
APIConnectionError,
APIEmptyResponseError,
APIStatusError,
APITimeoutError,
ChatProviderError,

View File

@@ -195,7 +195,6 @@ def discover_skills(skills_dir: Path) -> list["Skill"]:
>>> for skill in skills:
... print(f"{skill.name}: {skill.description}")
"""
from agentlite.skills.models import Skill
if not skills_dir.is_dir():
return []

View File

@@ -16,7 +16,7 @@ Example:
from __future__ import annotations
from collections.abc import Iterable, Iterator
from collections.abc import Iterable
from pathlib import Path
from typing import Literal, Optional

View File

@@ -7,7 +7,7 @@ in a hierarchical agent architecture.
from __future__ import annotations
from pathlib import Path
from typing import Any, Optional
from typing import Optional
from pydantic import BaseModel, Field, model_validator

View File

@@ -19,7 +19,6 @@ from typing import (
Protocol,
TypeVar,
Union,
cast,
Generic,
get_type_hints,
)
@@ -298,10 +297,6 @@ class CallableTool2(ABC, Generic[Params]):
return ToolError(message=f"Tool execution failed: {e}")
# Import Generic here to avoid issues with type checking
from typing import Generic
class Toolset(Protocol):
"""Protocol for tool collections.

View File

@@ -8,9 +8,9 @@ for enabling/disabling individual tools.
from __future__ import annotations
from pathlib import Path
from typing import Any, Optional
from typing import Optional
from agentlite.tool import CallableTool2, ToolOk, ToolError, ToolResult, SimpleToolset
from agentlite.tool import SimpleToolset
from agentlite.tools.config import (
ToolSuiteConfig,
FileToolsConfig,

View File

@@ -6,7 +6,6 @@ allowing users to enable/disable specific tools.
from __future__ import annotations
from typing import Any
from pydantic import BaseModel, Field

View File

@@ -165,7 +165,6 @@ class ReadFile(CallableTool2[Params]):
for i, line in enumerate(selected_lines):
line_num = start_idx + i + 1
original_line = line
# Truncate if needed
if len(line) > self._max_line_length:

View File

@@ -3,7 +3,4 @@
This module provides tools for creating and managing subagents.
"""
from agentlite.tools.multiagent.task import Task
from agentlite.tools.multiagent.create import CreateSubagent
__all__ = []

View File

@@ -8,8 +8,6 @@ from typing import Optional
import asyncio
import platform
import shlex
from pathlib import Path
from pydantic import BaseModel, Field
@@ -152,7 +150,7 @@ class Shell(CallableTool2[Params]):
if process.returncode == 0:
return ToolOk(
output=output,
message=f"Command executed successfully (exit code 0).",
message="Command executed successfully (exit code 0).",
)
else:
return ToolError(

View File

@@ -7,7 +7,6 @@ from __future__ import annotations
import urllib.request
import urllib.error
from pathlib import Path
from pydantic import BaseModel, Field

View File

@@ -19,12 +19,10 @@ from agentlite import (
Message,
TextPart,
ToolCall,
ToolOk,
ToolError,
tool,
)
from agentlite.provider import ChatProvider, StreamedMessage, TokenUsage
from agentlite.tool import Tool, ToolResult
from agentlite.provider import StreamedMessage, TokenUsage
from agentlite.tool import Tool
# =============================================================================

View File

@@ -8,7 +8,7 @@ from __future__ import annotations
import pytest
from agentlite import Agent, TextPart
from agentlite import Agent
@pytest.mark.integration

View File

@@ -17,7 +17,7 @@ import pytest
# Add src to path
sys.path.insert(0, str(Path(__file__).parent.parent.parent / "src"))
from agentlite import Agent, OpenAIProvider, LLMClient, llm_complete
from agentlite import Agent, OpenAIProvider, LLMClient
from agentlite.skills import discover_skills, SkillTool, index_skills_by_name
from agentlite.tools import ConfigurableToolset
@@ -74,7 +74,7 @@ async def test_agent_with_tools():
print("=" * 60)
try:
from agentlite.tools import ToolSuiteConfig, ReadFile, Glob
from agentlite.tools import ToolSuiteConfig
provider = get_provider()
@@ -173,7 +173,6 @@ async def test_subagents():
print("=" * 60)
try:
from agentlite.labor_market import LaborMarket
from agentlite.tools.multiagent.task import Task
provider = get_provider()
@@ -246,7 +245,7 @@ async def test_skills():
skill_tool = SkillTool(skill_index, parent_agent=agent)
agent.tools.add(skill_tool)
print(f"✅ Added SkillTool to agent")
print("✅ Added SkillTool to agent")
print("✅ Skills test PASSED")
return True

View File

@@ -5,7 +5,6 @@ from __future__ import annotations
import os
import sys
import asyncio
import signal
sys.path.insert(0, "/home/tcmofashi/proj/l2d_backend/agentlite/src")

View File

@@ -56,7 +56,7 @@ async def main():
start_time = time.time()
message = "Run 'echo test' and tell me the result."
logger.info(f"\n=== Starting Agent Run ===")
logger.info("\n=== Starting Agent Run ===")
logger.info(f"Message: {message}")
logger.info(f"Max iterations: {agent.max_iterations}")
logger.info(f"Tools: {[t.name for t in agent.tools.tools]}")
@@ -178,7 +178,7 @@ async def main():
output_preview = output[:100] if output else "None"
logger.info(f" Output preview: {output_preview}...")
except asyncio.TimeoutError:
logger.error(f" !!! Tool execution TIMEOUT")
logger.error(" !!! Tool execution TIMEOUT")
output = "Tool execution timed out"
is_error = True
except Exception as e:
@@ -209,7 +209,7 @@ async def main():
final_response = f"Max iterations ({agent.max_iterations}) reached"
logger.info(f"\n{'=' * 60}")
logger.info(f"FINAL RESULT:")
logger.info("FINAL RESULT:")
logger.info(f"{'=' * 60}")
logger.info(f"{final_response}")
logger.info(f"Total iterations: {iterations}")

View File

@@ -22,11 +22,6 @@ from agentlite import Agent, OpenAIProvider
from agentlite.tools import (
ConfigurableToolset,
ToolSuiteConfig,
Shell,
ReadFile,
WriteFile,
Glob,
Grep,
)
# =============================================================================

View File

@@ -17,7 +17,7 @@ from pathlib import Path
import pytest
from agentlite import Agent, TextPart, tool
from agentlite import Agent, tool
# =============================================================================

View File

@@ -16,7 +16,7 @@ from typing import Any
import pytest
import yaml
from agentlite import Agent, Message, TextPart, tool
from agentlite import Agent, tool
def tool_output(result: Any) -> Any:

View File

@@ -6,7 +6,6 @@ and all exception types.
from __future__ import annotations
import pytest
from agentlite.provider import (
TokenUsage,
@@ -106,7 +105,6 @@ class TestChatProviderProtocol:
def test_protocol_is_runtime_checkable(self):
"""Test that ChatProvider is runtime checkable."""
# ChatProvider should have @runtime_checkable
from typing import runtime_checkable
assert hasattr(ChatProvider, "__protocol_attrs__")

View File

@@ -195,7 +195,6 @@ class TestToolDecoratorMemorixBug:
This is an integration-style test to ensure the decorated tool
has all required attributes for Agent usage.
"""
from agentlite import Agent, OpenAIProvider
@tool()
async def add_memory(content: str, importance: float = 0.5) -> dict:

View File

@@ -15,7 +15,7 @@ ROOT_PATH = Path(__file__).resolve().parent.parent
if str(ROOT_PATH) not in sys_path:
sys_path.insert(0, str(ROOT_PATH))
from src.common.database.database_model import Expression, Jargon, ModifiedBy
from src.common.database.database_model import Expression, Jargon, ModifiedBy # noqa: E402
def build_argument_parser() -> ArgumentParser:

View File

@@ -239,8 +239,7 @@ def load_utils_via_file(monkeypatch):
@pytest.mark.asyncio
async def test_message_utils(monkeypatch):
load_message_via_file(monkeypatch)
utils_module = load_utils_via_file(monkeypatch)
MessageUtils = utils_module.MessageUtils
load_utils_via_file(monkeypatch)
@pytest.mark.asyncio

View File

@@ -22,9 +22,9 @@ if str(_root) not in sys.path:
if str(_maisaka_path) not in sys.path:
sys.path.insert(0, str(_maisaka_path))
from src.prompt.prompt_manager import prompt_manager
from src.maisaka.cli import BufferCLI
from src.maisaka.config import console
from src.prompt.prompt_manager import prompt_manager # noqa: E402
from src.maisaka.cli import BufferCLI # noqa: E402
from src.maisaka.config import console # noqa: E402
def main():

View File

@@ -36,8 +36,8 @@ def get_chat_name(chat_id: str) -> str:
elif chat_stream.user_nickname:
return f"{chat_stream.user_nickname}的私聊"
if get_chat_manager:
chat_manager = get_chat_manager()
if _script_chat_manager:
chat_manager = _script_chat_manager
stream_name = chat_manager.get_stream_name(chat_id)
if stream_name:
return stream_name

View File

@@ -5,6 +5,7 @@ import sys
import time
import json
import importlib
from dataclasses import dataclass
from typing import Optional, Dict, Any
from datetime import datetime
@@ -23,7 +24,17 @@ sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
from src.common.logger import initialize_logging, get_logger
from src.common.database.database import db
from src.common.database.database_model import LLMUsage
from maim_message import UserInfo, GroupInfo
from src.common.data_models.mai_message_data_model import UserInfo, GroupInfo
try:
from maim_message import ChatStream, UserInfo, GroupInfo
except Exception:
@dataclass
class ChatStream:
stream_id: str
platform: str
user_info: UserInfo
group_info: GroupInfo
logger = get_logger("test_memory_retrieval")

View File

@@ -205,7 +205,7 @@ class HeartFChatting:
# TODO: Planner逻辑
# TODO: 动作执行逻辑
cycle_detail = self._end_cycle(current_cycle_detail)
self._end_cycle(current_cycle_detail)
await asyncio.sleep(0.1) # 最小等待时间,避免过快循环
return True

View File

@@ -12,7 +12,6 @@ from src.chat.heart_flow.heartflow_message_processor import HeartFCMessageReceiv
from src.common.logger import get_logger
from src.common.utils.utils_message import MessageUtils
from src.common.utils.utils_session import SessionUtils
from src.config.config import global_config
from src.platform_io.route_key_factory import RouteKeyFactory
from src.core.announcement_manager import global_announcement_manager
from src.plugin_runtime.component_query import component_query_service

View File

@@ -1135,9 +1135,6 @@ class DefaultReplyer:
return content, reasoning_content, model_name, tool_calls
async def get_prompt_info(self, message: str, sender: str, target: str):
del message
del sender
del target
return ""
related_info = ""
start_time = time.time()

View File

@@ -1058,12 +1058,9 @@ class StatisticOutputTask(AsyncTask):
from src.chat.message_receive.chat_manager import chat_manager as _stat_chat_manager
if chat_id in _stat_chat_manager.sessions:
session = _stat_chat_manager.sessions[chat_id]
name = _stat_chat_manager.get_session_name(chat_id)
if name and name.strip():
return name.strip()
if user_name and user_name.strip():
return user_name.strip()
# 如果从chat_stream获取失败尝试解析chat_id格式
if chat_id.startswith("g"):

View File

@@ -92,7 +92,6 @@ class UniversalMessageSender:
"""
# TODO: 重构至新的发送模型
message_preview = (message.processed_plain_text or "")[:200]
platform = message.platform
try:
# 尝试通过主 API 发送