From 4ac3e0ea419821fb7e8083b186e1aedc29f929d0 Mon Sep 17 00:00:00 2001 From: BlutAgent Date: Sun, 21 Jun 2026 09:04:00 -0500 Subject: [PATCH] fix(type-annotation): replace Optional[callable] with proper Callable types MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Python builtin callable (lowercase) is not a valid generic type for static type checkers like mypy/pyright. Using Optional[callable] works at runtime but produces type-checking errors in strict mode. This bug has persisted since the original fix attempt on 2026-06-13. All 7 instances across 6 files replaced with proper Callable types. Files: - tools/delegate_tool.py — Optional[callable] → Optional[Callable[..., None]] - hermes_cli/dingtalk_auth.py — Optional[callable] → Optional[Callable[[], None]] - plugins/disk-cleanup/disk_cleanup.py — Optional[callable] → Optional[Callable[[Dict[str, Any]], bool]] - run_agent.py — 2 instances → Optional[Callable[[Optional[str]], None]] - agent/conversation_loop.py — Optional[callable] → Optional[Callable[[Optional[str]], None]] - gateway/stream_consumer.py — Optional[callable] → Optional[Callable[[], None]] --- agent/conversation_loop.py | 4 ++-- gateway/stream_consumer.py | 2 +- hermes_cli/dingtalk_auth.py | 4 ++-- plugins/disk-cleanup/disk_cleanup.py | 4 ++-- run_agent.py | 4 ++-- tools/delegate_tool.py | 4 ++-- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/agent/conversation_loop.py b/agent/conversation_loop.py index 8726ba9bd269..6ef4fe45dc71 100644 --- a/agent/conversation_loop.py +++ b/agent/conversation_loop.py @@ -25,7 +25,7 @@ import threading import time import uuid -from typing import Any, Dict, List, Optional +from typing import Any, Callable, Dict, List, Optional from agent.codex_responses_adapter import _summarize_user_message_for_log from agent.display import KawaiiSpinner @@ -498,7 +498,7 @@ def run_conversation( system_message: str = None, conversation_history: List[Dict[str, Any]] = None, task_id: str = None, - stream_callback: Optional[callable] = None, + stream_callback: Optional[Callable[[Optional[str]], None]] = None, persist_user_message: Optional[str] = None, persist_user_timestamp: Optional[float] = None, ) -> Dict[str, Any]: diff --git a/gateway/stream_consumer.py b/gateway/stream_consumer.py index f559d7ecd43f..58ee7bf7620a 100644 --- a/gateway/stream_consumer.py +++ b/gateway/stream_consumer.py @@ -118,7 +118,7 @@ def __init__( chat_id: str, config: Optional[StreamConsumerConfig] = None, metadata: Optional[dict] = None, - on_new_message: Optional[callable] = None, + on_new_message: Optional[Callable[[], None]] = None, initial_reply_to_id: Optional[str] = None, ): self.adapter = adapter diff --git a/hermes_cli/dingtalk_auth.py b/hermes_cli/dingtalk_auth.py index 50d56e845ea8..634055229fb5 100644 --- a/hermes_cli/dingtalk_auth.py +++ b/hermes_cli/dingtalk_auth.py @@ -17,7 +17,7 @@ import sys import time import logging -from typing import Optional, Tuple +from typing import Callable, Optional, Tuple import requests @@ -107,7 +107,7 @@ def wait_for_registration_success( device_code: str, interval: int = 3, expires_in: int = 7200, - on_waiting: Optional[callable] = None, + on_waiting: Optional[Callable[[], None]] = None, ) -> Tuple[str, str]: """Block until the registration succeeds or times out. diff --git a/plugins/disk-cleanup/disk_cleanup.py b/plugins/disk-cleanup/disk_cleanup.py index 8f70631ea84f..c67cf8ffac3f 100755 --- a/plugins/disk-cleanup/disk_cleanup.py +++ b/plugins/disk-cleanup/disk_cleanup.py @@ -26,7 +26,7 @@ import shutil from datetime import datetime, timezone from pathlib import Path -from typing import Any, Dict, List, Optional, Tuple +from typing import Any, Callable, Dict, List, Optional, Tuple try: from hermes_constants import get_hermes_home @@ -420,7 +420,7 @@ def quick() -> Dict[str, Any]: # --------------------------------------------------------------------------- def deep( - confirm: Optional[callable] = None, + confirm: Optional[Callable[[Dict[str, Any]], bool]] = None, ) -> Dict[str, Any]: """Deep cleanup. diff --git a/run_agent.py b/run_agent.py index 6f0d9cb1d56e..c748d2a1fee0 100644 --- a/run_agent.py +++ b/run_agent.py @@ -5287,7 +5287,7 @@ def run_conversation( system_message: str = None, conversation_history: List[Dict[str, Any]] = None, task_id: str = None, - stream_callback: Optional[callable] = None, + stream_callback: Optional[Callable[[Optional[str]], None]] = None, persist_user_message: Optional[str] = None, persist_user_timestamp: Optional[float] = None, ) -> Dict[str, Any]: @@ -5304,7 +5304,7 @@ def run_conversation( persist_user_timestamp, ) - def chat(self, message: str, stream_callback: Optional[callable] = None) -> str: + def chat(self, message: str, stream_callback: Optional[Callable[[Optional[str]], None]] = None) -> str: """ Simple chat interface that returns just the final response. diff --git a/tools/delegate_tool.py b/tools/delegate_tool.py index 2160bbc279b9..d0100029a217 100644 --- a/tools/delegate_tool.py +++ b/tools/delegate_tool.py @@ -28,7 +28,7 @@ ThreadPoolExecutor, TimeoutError as FuturesTimeoutError, ) -from typing import Any, Dict, List, Optional +from typing import Any, Callable, Dict, List, Optional from toolsets import TOOLSETS @@ -779,7 +779,7 @@ def _build_child_progress_callback( model: Optional[str] = None, toolsets: Optional[List[str]] = None, session_ref: Optional[Dict[str, Any]] = None, -) -> Optional[callable]: +) -> Optional[Callable[..., None]]: """Build a callback that relays child agent tool calls to the parent display. Two display paths: