Skip to content

Commit 77d0309

Browse files
authored
fix: resolve ruff lint errors in hermes and openharness adapters (#1458)
## Summary - Remove unused imports (`os`, `Dict`, `List`) and add `contextlib` where needed - Replace `try`-`except`-`pass` patterns with `contextlib.suppress()` for cleaner error suppression (SIM105) - Use list unpacking `[*tsx.split(), str(candidate)]` instead of concatenation (RUF005) - Use `with open(...)` context manager for file handling in `daemon_manager.py` (SIM115) - Add `# noqa: E402` for intentional late imports after `sys.path` manipulation - Replace deprecated `typing.Dict`/`typing.List` with builtin `dict`/`list` (UP035) All 20 remaining ruff lint errors resolved. `ruff check apps/memos-local-plugin` now passes cleanly. ## Files Changed - `adapters/hermes/__init__.py` - `adapters/hermes/bridge_client.py` - `adapters/hermes/config.py` - `adapters/hermes/daemon_manager.py` - `adapters/openharness/scripts/bridge_client.py` - `adapters/openharness/scripts/config.py` - `adapters/openharness/scripts/daemon_manager.py` ## Test Plan - [x] `ruff check apps/memos-local-plugin` passes with no errors - [ ] Verify hermes adapter still loads and functions correctly - [ ] Verify openharness adapter still loads and functions correctly
2 parents 7df9f7d + 5f06d57 commit 77d0309

File tree

7 files changed

+177
-152
lines changed

7 files changed

+177
-152
lines changed

apps/memos-local-plugin/adapters/hermes/__init__.py

Lines changed: 36 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -8,22 +8,25 @@
88

99
from __future__ import annotations
1010

11+
import contextlib
1112
import json
1213
import logging
13-
import os
1414
import re
1515
import sys
1616
import threading
17+
1718
from pathlib import Path
18-
from typing import Any, Dict, List
19+
from typing import Any
20+
1921

2022
# Add this directory to sys.path so sibling modules (config, bridge_client, …) resolve
2123
_PLUGIN_DIR = Path(__file__).resolve().parent
2224
if str(_PLUGIN_DIR) not in sys.path:
2325
sys.path.insert(0, str(_PLUGIN_DIR))
2426

25-
from agent.memory_provider import MemoryProvider
26-
from tools.registry import tool_error
27+
from agent.memory_provider import MemoryProvider # noqa: E402
28+
from tools.registry import tool_error # noqa: E402
29+
2730

2831
logger = logging.getLogger(__name__)
2932

@@ -51,10 +54,10 @@
5154
re.compile(r'^\s*\{["\']?ok["\']?\s*:\s*true\s*\}\s*$', re.IGNORECASE),
5255
re.compile(r'^\s*\{["\']?success["\']?\s*:\s*true\s*\}\s*$', re.IGNORECASE),
5356
re.compile(r'^\s*\{["\']?status["\']?\s*:\s*["\']?ok["\']?\s*\}\s*$', re.IGNORECASE),
54-
re.compile(r'^Operation interrupted:', re.IGNORECASE),
55-
re.compile(r'^Error:', re.IGNORECASE),
56-
re.compile(r'waiting for model response.*elapsed', re.IGNORECASE),
57-
re.compile(r'^\s*$'),
57+
re.compile(r"^Operation interrupted:", re.IGNORECASE),
58+
re.compile(r"^Error:", re.IGNORECASE),
59+
re.compile(r"waiting for model response.*elapsed", re.IGNORECASE),
60+
re.compile(r"^\s*$"),
5861
]
5962

6063
_MIN_CONTENT_LENGTH = 6
@@ -74,7 +77,10 @@ def _is_trivial(text: str) -> bool:
7477
keys = {k.lower() for k in obj}
7578
if keys <= {"ok", "success", "status", "result", "error", "message"}:
7679
vals = list(obj.values())
77-
if all(isinstance(v, (bool, type(None))) or (isinstance(v, str) and len(v) < 20) for v in vals):
80+
if all(
81+
isinstance(v, (bool, type(None))) or (isinstance(v, str) and len(v) < 20)
82+
for v in vals
83+
):
7884
return True
7985
except (json.JSONDecodeError, TypeError):
8086
pass
@@ -100,6 +106,7 @@ def name(self) -> str:
100106
def is_available(self) -> bool:
101107
try:
102108
from config import find_bridge_script
109+
103110
find_bridge_script()
104111
return True
105112
except Exception:
@@ -109,6 +116,7 @@ def initialize(self, session_id: str, **kwargs) -> None:
109116
self._session_id = session_id
110117

111118
from daemon_manager import ensure_daemon
119+
112120
try:
113121
info = ensure_daemon()
114122
logger.info(
@@ -121,6 +129,7 @@ def initialize(self, session_id: str, **kwargs) -> None:
121129
logger.warning("Failed to start MemTensor daemon: %s", e)
122130

123131
from bridge_client import MemosCoreBridge
132+
124133
try:
125134
self._bridge = MemosCoreBridge()
126135
logger.info("MemTensor bridge connected")
@@ -175,6 +184,7 @@ def _run():
175184
if pending and self._bridge:
176185
try:
177186
from config import OWNER
187+
178188
user_content, assistant_content, sid = pending
179189
messages = []
180190
if user_content:
@@ -201,9 +211,7 @@ def _do_recall(self, query: str) -> str:
201211
parts: list[str] = []
202212

203213
try:
204-
search_resp = self._bridge.search(
205-
query, max_results=5, min_score=0.4, owner=OWNER
206-
)
214+
search_resp = self._bridge.search(query, max_results=5, min_score=0.4, owner=OWNER)
207215
hits = search_resp.get("hits") or search_resp.get("memories") or []
208216
for h in hits:
209217
text = h.get("original_excerpt") or h.get("content") or h.get("summary", "")
@@ -225,9 +233,7 @@ def _do_recall(self, query: str) -> str:
225233

226234
return "\n".join(parts)
227235

228-
def sync_turn(
229-
self, user_content: str, assistant_content: str, *, session_id: str = ""
230-
) -> None:
236+
def sync_turn(self, user_content: str, assistant_content: str, *, session_id: str = "") -> None:
231237
"""Queue turn data for deferred ingest.
232238
233239
Hermes calls sync_all() BEFORE queue_prefetch_all(), so ingesting
@@ -239,8 +245,11 @@ def sync_turn(
239245
if not self._bridge:
240246
return
241247
if _is_trivial(user_content) and _is_trivial(assistant_content):
242-
logger.debug("sync_turn: skipping trivial turn (user=%r, assistant=%r)",
243-
user_content[:80] if user_content else "", assistant_content[:80] if assistant_content else "")
248+
logger.debug(
249+
"sync_turn: skipping trivial turn (user=%r, assistant=%r)",
250+
user_content[:80] if user_content else "",
251+
assistant_content[:80] if assistant_content else "",
252+
)
244253
return
245254
if _is_trivial(user_content):
246255
user_content = ""
@@ -249,10 +258,10 @@ def sync_turn(
249258
sid = session_id or self._session_id or "default"
250259
self._pending_ingest = (user_content, assistant_content, sid)
251260

252-
def get_tool_schemas(self) -> List[Dict[str, Any]]:
261+
def get_tool_schemas(self) -> list[dict[str, Any]]:
253262
return [MEMORY_SEARCH_SCHEMA]
254263

255-
def handle_tool_call(self, tool_name: str, args: Dict[str, Any], **kwargs) -> str:
264+
def handle_tool_call(self, tool_name: str, args: dict[str, Any], **kwargs) -> str:
256265
if tool_name != "memory_search":
257266
return tool_error(f"Unknown tool: {tool_name}")
258267

@@ -265,6 +274,7 @@ def handle_tool_call(self, tool_name: str, args: Dict[str, Any], **kwargs) -> st
265274

266275
try:
267276
from config import OWNER
277+
268278
resp = self._bridge.search(query, max_results=8, owner=OWNER)
269279
hits = resp.get("hits") or resp.get("memories") or []
270280
if not hits:
@@ -285,6 +295,7 @@ def on_memory_write(self, action: str, target: str, content: str) -> None:
285295
return
286296

287297
from config import OWNER
298+
288299
label = "user_profile" if target == "user" else "memory"
289300
messages = [
290301
{"role": "system", "content": f"[{label}] {content}"},
@@ -298,14 +309,16 @@ def _write():
298309
owner=OWNER,
299310
)
300311
self._bridge.flush()
301-
logger.info("MemTensor on_memory_write: %s %s (%d chars)", action, target, len(content))
312+
logger.info(
313+
"MemTensor on_memory_write: %s %s (%d chars)", action, target, len(content)
314+
)
302315
except Exception as e:
303316
logger.warning("MemTensor on_memory_write failed: %s", e)
304317

305318
t = threading.Thread(target=_write, daemon=True, name="memtensor-memory-write")
306319
t.start()
307320

308-
def on_session_end(self, messages: List[Dict[str, Any]]) -> None:
321+
def on_session_end(self, messages: list[dict[str, Any]]) -> None:
309322
if not self._bridge:
310323
return
311324
# Flush any deferred ingest that hasn't been picked up by queue_prefetch
@@ -314,6 +327,7 @@ def on_session_end(self, messages: List[Dict[str, Any]]) -> None:
314327
if pending:
315328
try:
316329
from config import OWNER
330+
317331
user_content, assistant_content, sid = pending
318332
msgs = []
319333
if user_content:
@@ -334,10 +348,8 @@ def shutdown(self) -> None:
334348
if t and t.is_alive():
335349
t.join(timeout=5.0)
336350
if self._bridge:
337-
try:
351+
with contextlib.suppress(Exception):
338352
self._bridge.shutdown()
339-
except Exception:
340-
pass
341353
self._bridge = None
342354

343355

apps/memos-local-plugin/adapters/hermes/bridge_client.py

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,18 @@
77

88
from __future__ import annotations
99

10+
import contextlib
1011
import json
1112
import logging
1213
import os
1314
import socket
1415
import subprocess
1516
import threading
17+
1618
from typing import Any
1719

18-
from config import find_bridge_script, get_bridge_config, get_daemon_port, OWNER, _get_plugin_root
20+
from config import OWNER, _get_plugin_root, find_bridge_script, get_bridge_config, get_daemon_port
21+
1922

2023
logger = logging.getLogger(__name__)
2124

@@ -45,10 +48,8 @@ def send(self, data: str) -> str:
4548

4649
def close(self) -> None:
4750
if self._sock:
48-
try:
51+
with contextlib.suppress(OSError):
4952
self._sock.close()
50-
except OSError:
51-
pass
5253
self._sock = None
5354

5455

@@ -133,20 +134,27 @@ def call(self, method: str, params: dict[str, Any] | None = None) -> Any:
133134
raise RuntimeError(f"Bridge error: {resp['error']}")
134135
return resp.get("result", {})
135136

136-
def search(self, query: str, max_results: int = 6, min_score: float = 0.45, owner: str = OWNER) -> dict:
137-
return self.call("search", {
138-
"query": query,
139-
"maxResults": max_results,
140-
"minScore": min_score,
141-
"owner": owner,
142-
})
137+
def search(
138+
self, query: str, max_results: int = 6, min_score: float = 0.45, owner: str = OWNER
139+
) -> dict:
140+
return self.call(
141+
"search",
142+
{
143+
"query": query,
144+
"maxResults": max_results,
145+
"minScore": min_score,
146+
"owner": owner,
147+
},
148+
)
143149

144150
def ingest(self, messages: list[dict], session_id: str = "default", owner: str = OWNER) -> None:
145151
params: dict[str, Any] = {"messages": messages, "sessionId": session_id, "owner": owner}
146152
self.call("ingest", params)
147153

148154
def build_prompt(self, query: str, max_results: int = 6, owner: str = OWNER) -> dict:
149-
return self.call("build_prompt", {"query": query, "maxResults": max_results, "owner": owner})
155+
return self.call(
156+
"build_prompt", {"query": query, "maxResults": max_results, "owner": owner}
157+
)
150158

151159
def flush(self) -> None:
152160
self.call("flush")

apps/memos-local-plugin/adapters/hermes/config.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@
44

55
import json
66
import os
7+
78
from pathlib import Path
89

10+
911
DAEMON_PORT = 18992
1012
VIEWER_PORT = 18901
1113
OWNER = "hermes"
@@ -139,6 +141,7 @@ def _resolve_tsx(plugin_root: Path) -> str:
139141
if local_tsx.exists():
140142
return str(local_tsx)
141143
import shutil
144+
142145
global_tsx = shutil.which("tsx")
143146
if global_tsx:
144147
return global_tsx
@@ -170,7 +173,7 @@ def find_bridge_script() -> list[str]:
170173
return ["node", str(candidate)]
171174
tsx = _resolve_tsx(candidate.parent)
172175
if " " in tsx:
173-
return tsx.split() + [str(candidate)]
176+
return [*tsx.split(), str(candidate)]
174177
return [tsx, str(candidate)]
175178

176179
raise FileNotFoundError(

0 commit comments

Comments
 (0)