mirror of
https://github.com/rennf93/roboco.git
synced 2026-08-03 07:23:24 +02:00
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.
This commit is contained in:
@@ -0,0 +1,92 @@
|
||||
"""Interactive intake/secretary builders fork a GROK route onto opencode.
|
||||
|
||||
A GROK route swaps the Claude SDK-driver image for the opencode-serve image and
|
||||
the ANTHROPIC_* env for OPENAI_* + the opencode store mount; every other
|
||||
provider keeps the Claude path's ANTHROPIC_* behaviour.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from roboco.runtime.orchestrator import (
|
||||
GROK_PROMPTER_IMAGE,
|
||||
GROK_SECRETARY_IMAGE,
|
||||
AgentOrchestrator,
|
||||
_IntakeRunSpec,
|
||||
_SecretaryRunSpec,
|
||||
)
|
||||
|
||||
_HOSTS = {
|
||||
"claude": "/h/.claude",
|
||||
"prompt": "/h/p.md",
|
||||
"workspaces": "/h/ws",
|
||||
"opencode": "/h/oc/intake-1",
|
||||
}
|
||||
|
||||
|
||||
def _intake_spec(
|
||||
provider_type: str, *, base_url: str | None, token: str | None
|
||||
) -> _IntakeRunSpec:
|
||||
return _IntakeRunSpec(
|
||||
container_name="roboco-agent-intake-1",
|
||||
image=GROK_PROMPTER_IMAGE
|
||||
if provider_type == "grok"
|
||||
else "roboco-agent-prompter",
|
||||
hosts=_HOSTS,
|
||||
session_id="sess-1",
|
||||
cwd="/data/workspace",
|
||||
cli_model="grok-build-0.1",
|
||||
api_url="http://roboco-orchestrator:8000",
|
||||
provider_base_url=base_url,
|
||||
provider_auth_token=token,
|
||||
provider_type=provider_type,
|
||||
model="grok-build-0.1",
|
||||
)
|
||||
|
||||
|
||||
def test_intake_grok_uses_openai_env_and_opencode_mount() -> None:
|
||||
cmd = AgentOrchestrator._build_intake_run_cmd(
|
||||
_intake_spec("grok", base_url="https://api.x.ai/v1", token="xai-key")
|
||||
)
|
||||
assert "OPENAI_BASE_URL=https://api.x.ai/v1" in cmd
|
||||
assert "OPENAI_API_KEY=xai-key" in cmd
|
||||
assert "ROBOCO_AGENT_MODEL=grok-build-0.1" in cmd
|
||||
assert "ROBOCO_SYSTEM_PROMPT=/app/system-prompt.md" in cmd
|
||||
assert "/h/oc/intake-1:/home/agent/.local/share/opencode" in cmd
|
||||
assert cmd[-1] == GROK_PROMPTER_IMAGE
|
||||
# The xAI endpoint is never mislabelled as Anthropic.
|
||||
assert not any(c.startswith("ANTHROPIC_") for c in cmd)
|
||||
|
||||
|
||||
def test_intake_anthropic_keeps_anthropic_env() -> None:
|
||||
cmd = AgentOrchestrator._build_intake_run_cmd(
|
||||
_intake_spec("anthropic", base_url="https://api.anthropic.com", token="sk-ant")
|
||||
)
|
||||
assert "ANTHROPIC_BASE_URL=https://api.anthropic.com" in cmd
|
||||
assert "ANTHROPIC_AUTH_TOKEN=sk-ant" in cmd
|
||||
assert not any(c.startswith("OPENAI_") for c in cmd)
|
||||
assert cmd[-1] == "roboco-agent-prompter"
|
||||
|
||||
|
||||
def test_secretary_grok_uses_openai_env_and_grok_image() -> None:
|
||||
spec = _SecretaryRunSpec(
|
||||
container_name="roboco-agent-secretary-1",
|
||||
image=GROK_SECRETARY_IMAGE,
|
||||
hosts={"claude": "/h/.claude", "prompt": "/h/p.md", "opencode": "/h/oc/sec-1"},
|
||||
session_id="sess-2",
|
||||
cwd="/app",
|
||||
cli_model="grok-build-0.1",
|
||||
api_url="http://roboco-orchestrator:8000",
|
||||
agent_uuid="uuid-sec",
|
||||
agent_token="hmac-secretary",
|
||||
provider_base_url="https://api.x.ai/v1",
|
||||
provider_auth_token="xai-key",
|
||||
provider_type="grok",
|
||||
model="grok-build-0.1",
|
||||
)
|
||||
cmd = AgentOrchestrator._build_secretary_run_cmd(spec)
|
||||
assert "OPENAI_API_KEY=xai-key" in cmd
|
||||
assert "/h/oc/sec-1:/home/agent/.local/share/opencode" in cmd
|
||||
# The HMAC identity the directive tools authenticate with survives.
|
||||
assert "ROBOCO_AGENT_TOKEN=hmac-secretary" in cmd
|
||||
assert cmd[-1] == GROK_SECRETARY_IMAGE
|
||||
assert not any(c.startswith("ANTHROPIC_") for c in cmd)
|
||||
Reference in New Issue
Block a user