4 Commits
Author SHA1 Message Date
Bailey Dixon 759ac490c9 fix(plugin): resolve Android screenshot media tokens for host tools 2026-09-23 16:37:50 -04:00
Bailey Dixon 7c5894213d fix(plugin): harden bridge credential recovery 2026-09-03 20:53:19 -04:00
Bailey DixonandClaude Fable 5 865c39bd86 fix(plugin): package-relative imports so the native plugin loader works (#165)
hermes-agent's native installer imports the plugin directory as
hermes_plugins.hermes_relay — no top-level 'plugin' package exists there,
so every absolute 'from plugin.X' import crashed 'hermes relay start'
with ModuleNotFoundError: No module named 'plugin'.

- Convert all runtime absolute plugin.* imports to package-relative form
  (relay voice/realtime chain, tailscale CLI, pair, enhancements, tools).
- android_tool's direct-script fallback now imports the sibling module
  bare instead of via 'plugin.tools.'.
- dashboard/plugin_api.py is exec'd standalone by the dashboard web
  server (spec_from_file_location, no parent package), so relative
  imports can't work there: add a _plugin_module() bootstrap that
  imports through the real parent package when one exists, and
  otherwise synthesizes it (bare ModuleType with __path__ at the plugin
  dir under a stable sys.modules alias) without exec'ing
  plugin/__init__.py side effects.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 18:49:07 -04:00
Bailey Dixon 1a2e3ff613 feat(phase3-θ): android_navigate vision-driven navigation tool
Adds the Phase 3 Tier 4 `android_navigate(intent, max_iterations=5)`
tool — a close-the-loop wrapper around the Wave 1 bridge HTTP routes
that takes a natural-language intent, screenshots the phone, asks a
vision model for the next action, executes it, and repeats until the
model emits `done` or the iteration cap is hit. Default cap 5,
hard-clamped to 20.

Hard plan constraint honoured: never continuous capture. Exactly one
/screenshot per iteration, only when the tool is invoked.

- plugin/tools/android_navigate.py — main loop, action dispatch, and
  registry registration. Shares _bridge_url()/_auth_headers() with
  android_tool.py so pairing config stays single-sourced.
- plugin/tools/android_navigate_prompt.py — prompt template + response
  parser. Kept separate so the parser tests don't need requests.
- plugin/tests/test_android_navigate.py — 35 stdlib unittest cases
  covering every valid action, every malformed-input branch, and the
  full loop (success / iteration cap / screenshot failure / parse
  error / action failure / llm_gap envelope / empty intent / clamping
  / schema sanity). Runs via `python -m unittest` without pulling in
  the conftest.py `responses` dependency.

LLM integration is a known gap documented in the module docstring: the
plan doesn't pick a vision provider, the plugin has no published LLM
client surface for tools, and the gateway's run loop is not re-entrant.
The loop defines a `call_vision_model` injection point — tests patch
it, production either sets HERMES_NAVIGATE_STUB_REPLY for smoke runs
or swaps _default_vision_model for a real Anthropic/OpenAI client.
Until that's wired, live calls return a clean {status: error, reason:
llm_gap} envelope instead of silently faking actions or crashing.

DEVLOG + CLAUDE.md Key Files rows updated for the three new files.
2026-04-12 18:16:02 -04:00