Commit Graph
3 Commits
Author SHA1 Message Date
Renn F 997a19e074 fix(grok): make the live interactive path work — store perms, error surfacing, variant
Found by actually running opencode serve locally (the path was doc-verified but
never executed). Three fixes:

1. EACCES on the opencode store mount (the live intake crash): on Linux docker
   auto-creates a missing bind source as root:root, so the non-root agent user
   could not mkdir/write in /home/agent/.local/share/opencode and opencode died
   at boot. _ensure_opencode_data_dir pre-creates the per-agent dir 0777 before
   the mount (one-shot via the _GrokHost seam, interactive in both spawns).

2. Silent blank reply on a model error: opencode reports a turn failure in
   info.error with parts=[], NOT as a part — verified live (a bad xAI key
   returns info.error APIError). send() / normalize_opencode_message now surface
   it as an "error" StreamChunk so a failed turn is never blank (the original
   intake bug class). Confirmed live: the error now renders.

3. Reasoning variant on the serve path: the live OpenAPI shows the message body
   accepts a "variant" field (it is NOT CLI-only, as the docs implied), so the
   pin is unblocked. send() passes ROBOCO_GROK_VARIANT as the per-turn variant;
   the orchestrator sets it per-role (_reasoning_effort_for) for interactive
   Grok, the same lever as the one-shot --variant.

opencode serve startup, POST /session, session-id extraction, the part-type
mapping (text/reasoning/tool), and the error path are all validated against a
live opencode 1.17.8. A real successful grok reply still needs a funded key.
2026-06-18 13:30:54 +02:00
Renn F 7681c47370 test(grok): mypy-clean the reaper watchdog + interactive spawn tests
The CI mypy scope (roboco/ tests/) flagged test-only typing issues my per-file
runs missed: direct method assignment (orch._remove_container = AsyncMock())
trips [method-assign], and a module-level dict[str,str] is invariant against
the dict[str, str|None] the run-spec expects.

- Use monkeypatch.setattr for _remove_container in the watchdog tests.
- Annotate the shared _HOSTS as dict[str, str | None].

Production code unchanged; mypy roboco/ tests/ is green.
2026-06-18 12:38:23 +02:00
Renn F 0d76ebf586 feat(grok): route interactive intake/secretary to opencode-serve images
Wire the GROK interactive path the in-place way (matching how the interactive
roles already choose ANTHROPIC_* per route), so a GROK route launches the
Grok-native opencode-serve image instead of the Claude SDK-driver image:

- _spawn_intake_container / _spawn_secretary_container pick the
  grok-prompter / grok-secretary image (ensuring the base→grok→interactive
  build chain) when the route is GROK, and stamp provider_type on the spec +
  AgentConfig so finalize routes usage to the opencode store.
- _build_intake_run_cmd / _build_secretary_run_cmd inject OPENAI_* + the
  opencode store mount + system-prompt env for GROK via a shared
  _append_interactive_provider_env, keeping ANTHROPIC_* for every other
  provider. The intake's minimal mounts (no gateway MCP) are preserved, so
  Grok intake matches the Claude intake's tool surface (the spec).
- Add a per-agent opencode store mount to the interactive host paths so
  interactive Grok usage/cost is captured like the one-shot path.

Removes the interim Phase-0 routing guard (the real path supersedes it) and
retires the unused AgentProvider.spawn_interactive/InteractiveSpawnSpec seam —
the interactive roles have a bespoke assembly that the one-shot provider
surface doesn't fit, so the fork lives in their own builders.

UNVERIFIED-LIVE: end-to-end intake/secretary chat on Grok needs the stack up +
opencode serve confirmed against grok-build-0.1.
2026-06-18 12:32:41 +02:00