Skip to content

fix(robot): repair /api/ai/commands + port back vision-tag stripping#2

Merged
Love4yzp merged 2 commits into
masterfrom
port-back-vision-tag-stripping-and-api-fix
Jun 4, 2026
Merged

fix(robot): repair /api/ai/commands + port back vision-tag stripping#2
Love4yzp merged 2 commits into
masterfrom
port-back-vision-tag-stripping-and-api-fix

Conversation

@Love4yzp

@Love4yzp Love4yzp commented Jun 4, 2026

Copy link
Copy Markdown
Collaborator

What & why

Triggered while validating robot movement on the deployed Jetson (reachy-claw:slv-v6). Found two real bugs in the REST control path plus device-only work that had never been committed back.

Bug 1 — /api/ai/commands always 503

dashboard_plugin.py looked up get_plugin("ConversationPlugin"), but the plugin registers as "conversation" (strict name match in app.get_plugin). The endpoint never resolved the plugin. One-char fix.

Bug 2 — endpoint 500 on the SLV deployment (only surfaced via on-device test)

This deployment uses the standalone conversation_plugin_slv.ConversationPlugin, which has the _cmd_* handlers but not the _execute_robot_command dispatcher the dashboard calls → AttributeError → 500. Added the dispatcher (exposing the 7 handlers the SLV plugin actually implements). Codex's static review missed this because it only inspected the legacy plugin; it was caught by real-device testing.

Port-back — streaming [Faces: ...] vision-tag stripping

edge_llm.py / llm.py had been hot-patched directly on the device (newer than master) to strip [Faces: ...] vision-context tags from the streamed LLM output so they don't leak into TTS. Never committed → would be lost on image rebuild. Ported back as a unit (the two files are interdependent via _extract_emotion). Adds _StreamingBracketStripper, _VISION_TAG_RE, _RESPONSE_STRIP_RE, and prompt guards.

Validation

  • On-device after hot-patching the same changes + restarting reachy-claw:
    • POST /api/ai/commands {command: reachy_status}{"status":"success","state":"idle","robot_connected":true}
    • POST /api/ai/commands {command: reachy_dance, args:{dance_name:"celebrate"}}{"status":"success","dance":"celebrate","steps":6} and the robot physically danced.
  • New TestStreamingBracketStripper (8 cases: split [emotion]/[Faces:...], unclosed [, trailing-space suppression, non-tag brackets, passthrough) — verified green against the real code inside the container (local Mac env can't resolve deps).

Follow-up (not in this PR)

The Jetson is currently running the hot-patched files (backups at *.bak-apifix). After merge, the reachy-claw:slv-v6 image must be rebuilt and redeployed for the fixes to persist across container recreation.

🤖 Generated with Claude Code

Love4yzp and others added 2 commits June 4, 2026 14:35
- dashboard: get_plugin("ConversationPlugin") → "conversation" so
  POST /api/ai/commands resolves the conversation plugin instead of
  always returning 503.
- conversation_plugin_slv: add _execute_robot_command dispatcher. The SLV
  plugin had the _cmd_* handlers but not the dispatch method the dashboard
  calls, so the endpoint 500'd on AttributeError. Validated on-device:
  status + dance now return 200 and the robot physically moves.
- llm / edge_llm: port back streaming [Faces: ...] vision-tag stripping
  that was hot-patched on the device but never committed (would be lost on
  image rebuild). Adds _StreamingBracketStripper, _VISION_TAG_RE,
  _RESPONSE_STRIP_RE and prompt guards; the two files are interdependent
  via _extract_emotion and land together.
- tests: add TestStreamingBracketStripper covering split tags, unclosed
  bracket, trailing-space suppression, and non-tag brackets.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ng lint

CI (and any checkout without the ../seeed-local-voice sibling) failed at
`uv sync` because tool.uv.sources pointed at an editable local path that
only exists on the device. Point it at the vendored torch-free wheel
(deploy/jetson/reachy/vendor/openvoicestream_agent-0.1.0-py3-none-any.whl)
so the project resolves on CI, fresh clones, and image builds; regenerate
uv.lock accordingly.

With sync working, ruff now runs and surfaced 4 pre-existing F401 unused
imports (proof_engine_e2e.py, e2e_slv_plugin_local.py) — removed.

Verified locally: `uv sync --extra dev` succeeds, `ruff check .` clean,
`pytest tests/` → 550 passed, 58 skipped.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@Love4yzp Love4yzp merged commit 669b430 into master Jun 4, 2026
4 checks passed
@Love4yzp Love4yzp deleted the port-back-vision-tag-stripping-and-api-fix branch June 17, 2026 07:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant