Clean up lint/LSP across gateway, Android, and desktop (alpha -> stable)

Gateway (gateway-plugin/):
- Fix interactive_setup broken imports: print helpers were imported from the
  wrong hermes module (hermes_cli.config instead of hermes_cli.cli_output) plus
  a non-existent print_code; the try/except swallowed the ImportError so
  `hermes gateway setup` for android always bailed out early.
- Fix release_scoped_lock type error (str | None passed where str required).
- Rewrite empty `except: pass` blocks as contextlib.suppress with rationale.
- Restructure two ambiguous ws_server try blocks (hello-auth, frame loop).
- Ruff cleanup: type annotations, import sorting, line wrapping, magic values
  -> named constants, `raise ... from e`, complexity. Add gateway-plugin/ruff.toml.
- Add pyrightconfig.json so the Python LSP resolves hermes-runtime imports.
- Suppress verified false positives inline (parameterized SQL, column-name
  "secrets", hermes-generated media path).

Android (app/androidApp + app/shared):
- Consolidate launcher icons into a single mipmap-anydpi (minSdk 29 >= 26) with
  the monochrome layer; clears ObsoleteSdkInt + MonochromeLauncherIcon.
- Bump core-splashscreen 1.0.1 -> 1.2.0; pin targetSdk 34 (deliberate).
- Suppress verified findings inline (LAN ws:// default, correct GCM IV usage).

Desktop (app/desktopApp):
- Move the desktop to a Java 21 runtime (org.gradle.java.home) and set the
  desktop jvmTarget to 21 (Android stays JVM 17 / minSdk 29). Fixes the startup
  UnsupportedClassVersionError and restores Markdown renderer 0.44.0.

Tooling/config:
- .pi-lens.json: disable verified-noisy heuristics (documented in docs).
- .gitleaks.toml: allowlist git-ignored false-positive paths.
- docs/18-code-review.md: full findings + verification.

Verified: ruff clean, pyright 0 errors, 64/64 gateway tests, all Kotlin tests,
Android lint 0 issues, Android installed+launched on device, desktop launches
on JDK 21.
This commit is contained in:
ARIA committed 2026-08-21 18:47:03 +02:00
1 parent 9f3f9842c8
commit 678c0344c8
27 files changed
+928 -454

No files matched your search

+3 -3
View File
@@ -56,8 +56,8 @@ def find_token(cli_token: str) -> str:
return env
for p in (REPO / "hermes-agent" / ".env", Path.home() / ".hermes" / ".env"):
try:
for line in p.read_text().splitlines():
line = line.strip()
for raw_line in p.read_text().splitlines():
line = raw_line.strip()
if line.startswith("ANDROID_TOKEN="):
return line.split("=", 1)[1].strip().strip('"').strip("'")
except OSError:
@@ -370,4 +370,4 @@ def main() -> int:
if __name__ == "__main__":
sys.exit(main())
sys.exit(main())
+11 -10
View File
@@ -126,7 +126,10 @@ def _print_frame(raw):
extra = (f" idx={payload.get('index')} name={payload.get('name')!r} "
f"preview={str(payload.get('preview'))[:80]!r}")
elif ftype == "tool.progress":
extra = f" idx={payload.get('index')} name={payload.get('name')!r} note={payload.get('note')!r}"
extra = (
f" idx={payload.get('index')} name={payload.get('name')!r} "
f"note={payload.get('note')!r}"
)
elif ftype == "tool.end":
extra = (f" idx={payload.get('index')} name={payload.get('name')!r} "
f"ok={payload.get('ok')} dur={payload.get('duration')}")
@@ -151,9 +154,7 @@ def _print_frame(raw):
elif ftype == "notification":
extra = (f" kind={payload.get('kind')} title={payload.get('title')!r} "
f"body={(payload.get('body') or '')[:100]!r}")
elif ftype == "sync":
extra = f" cursor={payload.get('cursor')}"
elif ftype == "sync.done":
elif ftype in {"sync", "sync.done"}:
extra = f" cursor={payload.get('cursor')}"
elif ftype == "search.results":
hits = payload.get("hits") or []
@@ -164,9 +165,7 @@ def _print_frame(raw):
extra = f" chat_id={payload.get('chat_id')}"
elif ftype == "channel.list":
extra = f" channels={len(payload.get('channels') or [])}"
elif ftype == "read.receipt":
extra = f" payload={ {k: payload[k] for k in list(payload)[:4]} }"
elif ftype == "status":
elif ftype in {"read.receipt", "status"}:
extra = f" payload={ {k: payload[k] for k in list(payload)[:4]} }"
scope = f" chat={chat}" if chat else ""
idpart = f" id={fid}" if fid is not None else ""
@@ -191,7 +190,8 @@ async def upload_file(ws, path: str, media_ref: str, next_id: int) -> int:
Returns the next free request id; raises on a non-ack terminal frame.
"""
data = open(path, "rb").read()
with open(path, "rb") as f:
data = f.read()
mime, _ = mimetypes.guess_type(path)
await ws.send(json.dumps({
"v": 1, "id": next_id, "type": "media.upload.start",
@@ -653,7 +653,8 @@ async def run(args) -> int:
data = _print_frame(raw)
if data is None:
continue
if data.get("type") == "media.offer" and (data.get("payload") or {}).get("media_id"):
is_offer = data.get("type") == "media.offer"
if is_offer and (data.get("payload") or {}).get("media_id"):
try:
await pull_media(
ws, data["payload"]["media_id"], next_id,
@@ -748,4 +749,4 @@ def main() -> int:
if __name__ == "__main__":
sys.exit(main())
sys.exit(main())