fix linter bug

This commit is contained in:
MuXinCG
2026-02-15 21:07:47 +08:00
parent 91e0cfb7c1
commit 9b93cea12b
26 changed files with 72 additions and 74 deletions
+1 -1
View File
@@ -24,7 +24,7 @@ from .backends import CustomSandboxBackend, MergedReadOnlyBackend
from .config import get_effective_config, apply_config_to_env
from .llm import get_chat_model
from .mcp import load_mcp_tools
from .middleware import create_memory_middleware, create_skills_middleware
from .middleware import create_memory_middleware
from .prompts import RESEARCHER_INSTRUCTIONS, get_system_prompt
from .utils import load_subagents
from .tools import tavily_search, think_tool, skill_manager, view_image
+6 -9
View File
@@ -4,10 +4,14 @@ This module provides an extensible interface for different messaging channels
(iMessage, Telegram, Discord) to communicate with the EvoScientist agent.
"""
from .base import Channel, RawIncoming, IncomingMessage, OutgoingMessage
from .base import Channel, RawIncoming, IncomingMessage, OutgoingMessage, chunk_text
from .bus import MessageBus, InboundMessage, OutboundMessage
from .capabilities import ChannelCapabilities
from .channel_manager import ChannelManager, register_channel, create_channel, available_channels
from .consumer import InboundConsumer
from .formatter import UnifiedFormatter
from .middleware import TypingManager
from .plugin import ChannelPlugin, ChannelMeta, ReloadPolicy
from .standalone import run_standalone
# Backward compat: ChannelServer is now Channel itself
@@ -27,6 +31,7 @@ __all__ = [
"run_standalone",
"register_channel",
"create_channel",
"available_channels",
# New modules
"ChannelCapabilities",
"UnifiedFormatter",
@@ -37,11 +42,3 @@ __all__ = [
"ChannelMeta",
"ReloadPolicy",
]
from .capabilities import ChannelCapabilities
from .formatter import UnifiedFormatter
from .middleware import TypingManager
from .base import chunk_text
# Plugin architecture
from .plugin import ChannelPlugin, ChannelMeta, ReloadPolicy
+1 -1
View File
@@ -7,7 +7,7 @@ streaming, threading, etc.) without per-channel branching in core logic.
from __future__ import annotations
from dataclasses import dataclass, field
from dataclasses import dataclass
from typing import Literal
FormatType = Literal["html", "markdown", "slack_mrkdwn", "discord", "plain"]
+2 -7
View File
@@ -11,7 +11,6 @@ account management (formerly ``account.py``), and pipeline assembly
from __future__ import annotations
import asyncio
import dataclasses
import importlib
import json
import logging
@@ -22,9 +21,9 @@ from datetime import datetime
from pathlib import Path
from typing import Any, Callable
from .base import Channel, RawIncoming, OutboundMessage
from .base import Channel, OutboundMessage
from .bus import MessageBus
from .bus.events import InboundMessage
from .middleware import OutboundMiddlewareBase
from .plugin import ChannelPlugin
logger = logging.getLogger(__name__)
@@ -245,10 +244,6 @@ class AccountManager:
# Inbound / outbound pipelines (formerly pipeline.py)
# ═════════════════════════════════════════════════════════════════════
from .middleware import (
OutboundMiddlewareBase,
)
class OutboundPipeline:
"""Processes outgoing messages through a middleware chain."""
+1 -1
View File
@@ -12,7 +12,7 @@ common account patterns:
from __future__ import annotations
from dataclasses import dataclass, field
from dataclasses import dataclass
from typing import Any
+1 -1
View File
@@ -12,7 +12,7 @@ from __future__ import annotations
import asyncio
import logging
import uuid
from dataclasses import dataclass, field
from dataclasses import dataclass
from typing import Any, AsyncIterator, Callable, TypeVar
from .base import Channel
@@ -4,7 +4,6 @@ import asyncio
import json
import logging
from urllib.parse import quote_plus
import time
from dataclasses import dataclass
from datetime import datetime
from pathlib import Path
@@ -212,7 +211,6 @@ class DingTalkChannel(Channel, WebSocketMixin, TokenMixin):
return
sender_id = payload.get("senderStaffId") or payload.get("senderId", "")
conv_id = payload.get("conversationId", "")
is_group = payload.get("conversationType") == "2"
# For send API (oToMessages/batchSend), userIds needs staffId, not conversationId
chat_id = sender_id
-1
View File
@@ -3,7 +3,6 @@
import asyncio
import logging
import os
import re
from dataclasses import dataclass
from datetime import datetime
+20 -7
View File
@@ -50,12 +50,24 @@ def _strip_html(text: str) -> str:
@dataclass
class EmailConfig(BaseChannelConfig):
imap_host: str = ""; imap_port: int = 993; imap_username: str = ""; imap_password: str = ""
imap_mailbox: str = "INBOX"; imap_use_ssl: bool = True
smtp_host: str = ""; smtp_port: int = 587; smtp_username: str = ""; smtp_password: str = ""
smtp_use_tls: bool = True; from_address: str = ""
poll_interval: int = 30; mark_seen: bool = True; max_body_chars: int = 12000
subject_prefix: str = "Re: "; allowed_senders: set[str] | None = None; text_chunk_limit: int = 4096
imap_host: str = ""
imap_port: int = 993
imap_username: str = ""
imap_password: str = ""
imap_mailbox: str = "INBOX"
imap_use_ssl: bool = True
smtp_host: str = ""
smtp_port: int = 587
smtp_username: str = ""
smtp_password: str = ""
smtp_use_tls: bool = True
from_address: str = ""
poll_interval: int = 30
mark_seen: bool = True
max_body_chars: int = 12000
subject_prefix: str = "Re: "
allowed_senders: set[str] | None = None
text_chunk_limit: int = 4096
class EmailChannel(Channel, PollingMixin):
@@ -352,7 +364,8 @@ class EmailChannel(Channel, PollingMixin):
await self._stop_polling()
if self._imap:
try:
self._imap.close(); self._imap.logout()
self._imap.close()
self._imap.logout()
except Exception:
pass
self._imap = None
+6 -3
View File
@@ -16,16 +16,19 @@ Send API:
- ``POST /open-apis/im/v1/messages?receive_id_type=chat_id``
"""
import asyncio
from __future__ import annotations
import json
import logging
import re
import time
from typing import Any
from typing import Any, TYPE_CHECKING
from dataclasses import dataclass
from datetime import datetime
from pathlib import Path
if TYPE_CHECKING:
from aiohttp import web
from ..base import Channel, RawIncoming, ChannelError
from ..capabilities import FEISHU as FEISHU_CAPS
from ..mixins import WebhookMixin, TokenMixin
+3 -4
View File
@@ -14,11 +14,10 @@ import asyncio
import dataclasses
import logging
import random
import re
import time
from collections import OrderedDict, defaultdict, deque
from collections import OrderedDict, deque
from collections.abc import Awaitable
from dataclasses import dataclass, field
from dataclasses import dataclass
from typing import Any, Callable
from .bus.events import InboundMessage, OutboundMessage
@@ -527,7 +526,7 @@ class RetryMiddleware:
"""
def __init__(self, channel_name: str = "unknown") -> None:
from .retry import RetryConfig, DEFAULT_RETRY, RETRY_PRESETS
from .retry import DEFAULT_RETRY, RETRY_PRESETS
self._config = RETRY_PRESETS.get(channel_name, DEFAULT_RETRY)
self._channel_name = channel_name
+1 -2
View File
@@ -16,9 +16,8 @@ import asyncio
import json
import logging
import time
from typing import Any, Callable
from typing import Any
from .base import Channel, ChannelError
logger = logging.getLogger(__name__)
-1
View File
@@ -209,7 +209,6 @@ class QQChannel(Channel):
from pathlib import Path
chat_id = self._resolve_media_chat_id(recipient, metadata)
msg_type = (metadata or {}).get("msg_type", "c2c")
msg_id = (metadata or {}).get("event_id", "")
ext = Path(file_path).suffix.lower()
file_type = self._FILE_TYPE_MAP.get(ext, 1) # default to image
+1 -2
View File
@@ -15,9 +15,8 @@ import json
import logging
import re
import subprocess
import time
from collections import deque
from dataclasses import dataclass, field
from dataclasses import dataclass
from datetime import datetime
from typing import Any
+2 -1
View File
@@ -9,7 +9,8 @@ async def validate_signal(
rpc_port: int = 7583,
) -> tuple[bool, str]:
"""Validate Signal setup by checking signal-cli availability."""
import asyncio, subprocess
import asyncio
import subprocess
if not phone_number:
return False, "phone_number is required"
-1
View File
@@ -2,7 +2,6 @@
import asyncio
import logging
import re
from dataclasses import dataclass
from datetime import datetime
+8 -4
View File
@@ -17,16 +17,20 @@ Both backends use httpx (already a core dependency) and aiohttp for
webhook server — matching the Feishu channel pattern.
"""
from __future__ import annotations
import asyncio
import hashlib
import json
import logging
import re
import time
from dataclasses import dataclass, field
from dataclasses import dataclass
from datetime import datetime
from pathlib import Path
from typing import Any
from typing import Any, TYPE_CHECKING
if TYPE_CHECKING:
from aiohttp import web
from ..mixins import WebhookMixin, TokenMixin
from ..base import Channel, RawIncoming, ChannelError
@@ -412,7 +416,7 @@ class WeChatChannel(Channel, WebhookMixin, TokenMixin):
if ann:
annotations.append(ann)
else:
annotations.append(f"[image: no download source]")
annotations.append("[image: no download source]")
elif msg_type == "voice":
recognition = xml_data.get("Recognition", "")
media_id = xml_data.get("MediaId", "")
-2
View File
@@ -13,11 +13,9 @@ References:
import base64
import hashlib
import socket
import struct
import time
import xml.etree.ElementTree as ET
from typing import Optional
# Crypto imports — all from the Python standard library + pycryptodome
# (but we'll use a pure-Python fallback if not available)
@@ -14,9 +14,15 @@ Usage:
await server.stop()
"""
from __future__ import annotations
import asyncio
import hashlib
import logging
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from aiohttp import web
logger = logging.getLogger(__name__)
@@ -89,7 +95,7 @@ class VerifyServer:
def is_verified(self) -> bool:
return self._verified.is_set()
async def _handle(self, request) -> "web.Response":
async def _handle(self, request) -> web.Response:
"""Handle GET verification request.
During onboarding we use a lenient approach:
@@ -163,7 +169,7 @@ class VerifyServer:
self._verified.set()
return web.Response(text=echostr)
async def _handle_post(self, request) -> "web.Response":
async def _handle_post(self, request) -> web.Response:
"""Handle POST — just acknowledge during verification phase."""
from aiohttp import web
return web.Response(text="success")
+1 -1
View File
@@ -162,7 +162,7 @@ async def _bus_inbound_consumer(
"""
from ..stream import events as _stream_events_mod
from ..stream.display import (
console, display_final_results, create_streaming_display,
console, create_streaming_display,
)
from ..stream.state import StreamState
from ..channels.consumer import _format_todo_list
-4
View File
@@ -483,10 +483,6 @@ def cmd_interactive(
state["agent"] = _load_agent(workspace_dir=state["workspace_dir"], checkpointer=checkpointer)
state["thread_id"] = generate_thread_id()
state["resumed"] = False
# Sync shared refs if channel is running
if _ChannelState.is_running():
_ChannelState.agent = state["agent"]
_ChannelState.thread_id = state["thread_id"]
console.print(f"[green]New session:[/green] [yellow]{state['thread_id']}[/yellow]")
if state["workspace_dir"]:
console.print(f"[dim]Workspace:[/dim] [cyan]{_shorten_path(state['workspace_dir'])}[/cyan]\n")
+2 -3
View File
@@ -2,12 +2,11 @@
import asyncio
import pytest
from EvoScientist.channels.bus.events import InboundMessage, OutboundMessage
from EvoScientist.channels.bus.events import InboundMessage
from EvoScientist.channels.bus.message_bus import MessageBus
from EvoScientist.channels.channel_manager import ChannelManager
from EvoScientist.channels.base import Channel, IncomingMessage, OutgoingMessage
from EvoScientist.channels.base import Channel, OutgoingMessage
def _run(coro):
+7 -10
View File
@@ -15,13 +15,10 @@ Test groups:
from __future__ import annotations
import asyncio
import re
import time
from collections import OrderedDict
from dataclasses import dataclass
from datetime import datetime
from typing import Any
from unittest.mock import AsyncMock, MagicMock, patch
from unittest.mock import AsyncMock, MagicMock
import pytest
@@ -38,7 +35,7 @@ from EvoScientist.channels.bus.events import (
OutboundMessage as BusOutbound,
)
from EvoScientist.channels.bus.message_bus import MessageBus
from EvoScientist.channels.channel_manager import ChannelManager, ChannelHealth
from EvoScientist.channels.channel_manager import ChannelManager
from EvoScientist.channels.consumer import InboundConsumer
from EvoScientist.channels.middleware import DedupCache
from EvoScientist.channels.retry import RetryConfig, RetryInfo, retry_async
@@ -363,7 +360,7 @@ class TestMarkdownUtils:
result = convert_markdown(
text,
code_block_formatter=lambda l, c: f"[CODE]{c}[/CODE]",
code_block_formatter=lambda lang, c: f"[CODE]{c}[/CODE]",
inline_code_formatter=lambda c: f"[IC]{c}[/IC]",
inline_rules=[],
escape_fn=bad_escape,
@@ -382,7 +379,7 @@ class TestMarkdownUtils:
text = "Normal text with \x00BLOCK0\x00 in it"
result = convert_markdown(
text,
code_block_formatter=lambda l, c: f"<pre>{c}</pre>",
code_block_formatter=lambda lang, c: f"<pre>{c}</pre>",
inline_code_formatter=lambda c: f"<code>{c}</code>",
inline_rules=[],
)
@@ -393,7 +390,7 @@ class TestMarkdownUtils:
text = "before `` after"
result = convert_markdown(
text,
code_block_formatter=lambda l, c: c,
code_block_formatter=lambda lang, c: c,
inline_code_formatter=lambda c: f"[{c}]",
inline_rules=[],
)
@@ -1213,7 +1210,7 @@ class TestInboundConsumer:
async def _test():
consumer = self._make_consumer()
# Start and immediately stop
task = asyncio.create_task(consumer.run())
asyncio.create_task(consumer.run())
await asyncio.sleep(0.1)
await consumer.stop()
await asyncio.sleep(0.1)
@@ -1232,7 +1229,7 @@ class TestInboundConsumerErrorHandling:
ch = StubChannel()
mgr.register(ch)
consumer = InboundConsumer(
_consumer = InboundConsumer(
bus=bus, manager=mgr, agent=MagicMock(),
thread_id="",
)
+1 -2
View File
@@ -5,9 +5,8 @@ import asyncio
import pytest
from EvoScientist.channels.bus.message_bus import MessageBus
from EvoScientist.channels.bus.events import InboundMessage, OutboundMessage
from EvoScientist.channels.channel_manager import ChannelManager
from EvoScientist.channels.base import Channel, InboundMessage, OutboundMessage
from EvoScientist.channels.base import Channel, OutboundMessage
def _run(coro):
-1
View File
@@ -3,7 +3,6 @@
import asyncio
from dataclasses import dataclass
import pytest
from EvoScientist.channels.base import Channel, RawIncoming
from EvoScientist.channels.capabilities import ChannelCapabilities
-1
View File
@@ -2,7 +2,6 @@
import asyncio
import pytest
from EvoScientist.channels.bus.events import InboundMessage, OutboundMessage
from EvoScientist.channels.bus.message_bus import MessageBus