refactor(all): drop name-restating docstrings; loop LINE text overrides

This commit is contained in:
Teknium
2026-09-02 23:13:37 -07:00
parent 8a71c19439
commit f2d9c79617
3 changed files with 7 additions and 25 deletions
+7 -9
View File
@@ -262,7 +262,6 @@ class _LineClient:
logger.debug("LINE loading indicator failed: %s", exc)
async def fetch_content(self, message_id: str) -> bytes:
"""Download an inbound media message's binary content."""
async with self._session(30.0) as session:
url = LINE_CONTENT_URL_FMT.format(message_id=message_id)
async with session.get(url, headers={"Authorization": f"Bearer {self._token}"}) as resp:
@@ -380,10 +379,13 @@ class LineAdapter(BasePlatformAdapter):
# Slow-LLM postback button threshold + user-overridable copy
threshold = env_or("LINE_SLOW_RESPONSE_THRESHOLD", "slow_response_threshold", DEFAULT_SLOW_RESPONSE_THRESHOLD)
self.slow_response_threshold = _coerce(float, threshold, DEFAULT_SLOW_RESPONSE_THRESHOLD)
self.pending_text = env_or("LINE_PENDING_TEXT", "pending_text", DEFAULT_PENDING_REPLY_TEXT)
self.button_label = env_or("LINE_BUTTON_LABEL", "button_label", DEFAULT_BUTTON_LABEL)
self.delivered_text = env_or("LINE_DELIVERED_TEXT", "delivered_text", DEFAULT_DELIVERED_TEXT)
self.interrupted_text = env_or("LINE_INTERRUPTED_TEXT", "interrupted_text", DEFAULT_INTERRUPTED_TEXT)
for attr, env, default in (
("pending_text", "LINE_PENDING_TEXT", DEFAULT_PENDING_REPLY_TEXT),
("button_label", "LINE_BUTTON_LABEL", DEFAULT_BUTTON_LABEL),
("delivered_text", "LINE_DELIVERED_TEXT", DEFAULT_DELIVERED_TEXT),
("interrupted_text", "LINE_INTERRUPTED_TEXT", DEFAULT_INTERRUPTED_TEXT),
):
setattr(self, attr, env_or(env, attr, default))
# Runtime state
self._client: Optional[_LineClient] = None
self._app = self._runner = self._site = None # aiohttp web.Application / AppRunner / TCPSite
@@ -398,7 +400,6 @@ class LineAdapter(BasePlatformAdapter):
self._pending_buttons: Dict[str, str] = {} # one outstanding button per chat: chat_id → request_id
def _fail(self, code: str, detail: str, *, retryable: bool = False) -> bool:
"""Record a fatal connect error and return False."""
self._set_fatal_error(code, detail, retryable=retryable)
return False
@@ -713,7 +714,6 @@ class LineAdapter(BasePlatformAdapter):
return token
def _media_url(self, token: str, filename: str) -> str:
"""Build the public HTTPS URL for a media token."""
if self.public_base_url:
base = self.public_base_url
else:
@@ -724,7 +724,6 @@ class LineAdapter(BasePlatformAdapter):
return f"{base}{DEFAULT_MEDIA_PATH_PREFIX}/{token}/{_urlquote(filename, safe='')}"
def _serve_file(self, path: Path) -> str:
"""Register ``path`` for serving and return its public URL."""
return self._media_url(self._register_media(str(path.resolve())), path.name)
def _missing_public_url(self) -> bool:
@@ -949,7 +948,6 @@ def interactive_setup() -> None:
def register(ctx) -> None:
"""Plugin entry point — called by the Hermes plugin system at startup."""
ctx.register_platform(
name="line", label="LINE", adapter_factory=lambda cfg: LineAdapter(cfg), check_fn=check_requirements,
validate_config=validate_config, is_connected=is_connected,
-9
View File
@@ -43,12 +43,10 @@ _MEDIA_KIND_PRECEDENCE = (("audio/", MessageType.VOICE), ("image/", MessageType.
def _parse_comma_list(value: str) -> List[str]:
"""Split a comma-separated string into a stripped list."""
return [v.strip() for v in value.split(",") if v.strip()]
def _redact_id(contact_id: str) -> str:
"""Redact a contact/group ID for logging."""
if not contact_id:
return "<none>"
s = str(contact_id)
@@ -129,7 +127,6 @@ class SimplexAdapter(BasePlatformAdapter):
self.ws_url, self.auto_accept, "enabled" if self.group_allow_from else "disabled")
async def connect(self, *, is_reconnect: bool = False) -> bool:
"""Connect to the simplex-chat daemon and start the WebSocket listener."""
try:
import websockets as _wsclient
except ImportError:
@@ -154,7 +151,6 @@ class SimplexAdapter(BasePlatformAdapter):
return True
async def disconnect(self) -> None:
"""Stop WebSocket listener and clean up."""
self._running = False
await _cancel_task(self._ws_task)
await _cancel_task(self._health_task)
@@ -175,7 +171,6 @@ class SimplexAdapter(BasePlatformAdapter):
logger.info("SimpleX: disconnected")
async def _ws_listener(self) -> None:
"""Maintain a persistent WebSocket connection to the daemon."""
import websockets as _wsclient
from websockets.exceptions import ConnectionClosed
backoff = WS_RETRY_DELAY_INITIAL
@@ -223,7 +218,6 @@ class SimplexAdapter(BasePlatformAdapter):
logger.debug("SimpleX: WS application-idle for %.0fs", elapsed)
async def _handle_event(self, event: dict) -> None:
"""Dispatch a daemon event to the appropriate handler."""
# Usually {"corrId": ..., "resp": {"type": ...}}, but some daemons put the
# response fields at top level — normalize both.
resp = event.get("resp") if isinstance(event.get("resp"), dict) else event
@@ -296,7 +290,6 @@ class SimplexAdapter(BasePlatformAdapter):
logger.exception(err_msg)
async def _handle_chat_item(self, chat_item: dict) -> None:
"""Process a single chat item from a newChatItems event."""
chat_info = chat_item.get("chatInfo", {}) or {}
chat_item_data = chat_item.get("chatItem", {}) or {}
chat_type = chat_info.get("type", "")
@@ -421,7 +414,6 @@ class SimplexAdapter(BasePlatformAdapter):
logger.warning("SimpleX: WS send error: %s", e)
async def _send_command(self, command: str, timeout: float = 30.0) -> Optional[dict]:
"""Send a command and await the correlated response."""
ws = self._ws
if not ws:
logger.warning("SimpleX: command sent but WebSocket not connected")
@@ -694,7 +686,6 @@ def interactive_setup() -> None:
def register(ctx) -> None:
"""Plugin entry point — called by the Hermes plugin system at startup."""
ctx.register_platform(
name="simplex", label="SimpleX Chat", adapter_factory=lambda cfg: SimplexAdapter(cfg),
check_fn=check_requirements, validate_config=validate_config, is_connected=is_connected,
-7
View File
@@ -150,12 +150,10 @@ def _credentials(config) -> tuple[str, str, str]:
def validate_config(config) -> bool:
"""True when the config has the minimum required credentials."""
return bool(all(_credentials(config)))
def is_connected(config) -> bool:
"""Check whether Teams is configured (env or config.yaml)."""
return validate_config(config)
@@ -451,7 +449,6 @@ class TeamsAdapter(BasePlatformAdapter):
return await _read_httpx_body_with_limit(response, media_type="attachment")
async def _on_message(self, ctx: ActivityContext[MessageActivity]) -> None:
"""Process an incoming Teams message and dispatch to the gateway."""
activity = ctx.activity
bot_id = self._app.id if self._app else None
if bot_id and getattr(activity.from_, "id", None) == bot_id:
@@ -570,7 +567,6 @@ class TeamsAdapter(BasePlatformAdapter):
async def _on_card_action(
self, ctx: "ActivityContext[AdaptiveCardInvokeActivity]"
) -> "InvokeResponse[AdaptiveCardActionMessageResponse]":
"""Handle an Adaptive Card Action.Execute button click."""
from tools.approval import resolve_gateway_approval, has_blocking_approval
data = ctx.activity.value.action.data or {}
@@ -615,7 +611,6 @@ class TeamsAdapter(BasePlatformAdapter):
self, chat_id: str, command: str, session_key: str, description: str = "dangerous command",
metadata: Optional[Dict[str, Any]] = None, allow_permanent: bool = True, allow_session: bool = True,
smart_denied: bool = False) -> SendResult:
"""Send an Adaptive Card approval prompt with Allow/Deny buttons."""
if not self._app:
return SendResult(success=False, error="Teams app not initialized")
# Button data carries a truncated cmd — just enough to reconstruct the card body.
@@ -739,7 +734,6 @@ _SETUP_INTRO = ( # "" → blank line
def interactive_setup() -> None:
"""Guide the user through Teams setup using the Teams CLI."""
from hermes_cli.config import get_env_value, save_env_value
from hermes_cli.cli_output import prompt, prompt_yes_no, print_info, print_success, print_warning
existing_id = get_env_value("TEAMS_CLIENT_ID")
@@ -787,7 +781,6 @@ def _install_hint() -> str:
def register(ctx) -> None:
"""Plugin entry point — called by the Hermes plugin system."""
ctx.register_platform(
name="teams", label="Microsoft Teams", adapter_factory=lambda cfg: TeamsAdapter(cfg),
check_fn=check_requirements, # PASSIVE probe — never installs