feat(grok): Grok-native interactive runtime (opencode serve) — container side

Builds the Grok analogue of the Claude intake/secretary live-session runtime,
satisfying the same IntakeSession seam so the existing IntakeDriver loop,
message source, relay, and StreamChunk panel contract are reused unchanged:

- OpencodeServeSession: a held-open `opencode serve` session (context persists
  across turns) where each human turn is one synchronous POST /session/:id/
  message; normalize_opencode_message maps the reply parts to text/thinking/
  tool_use/draft/turn_end chunks (draft via a propose_draft tool part or the
  fenced roboco-draft fallback). Doc-verified against opencode's server API.
- grok_intake_main / grok_secretary_main: container entrypoints mirroring the
  Claude mains but yielding an OpencodeServeSession; they render opencode.json
  (xAI provider + MCP + system prompt) first, then run the receiver + driver.
- roboco-agent-grok-prompter / -secretary images (FROM roboco-agent-grok) +
  their builder services in all three compose files.

UNVERIFIED-LIVE: the opencode serve flow + exact Part schema + draft path need
a live run against grok-build-0.1 (the part mapping is defensive). The
orchestrator wiring that routes a GROK intake/secretary route to these images
is the next step (a design decision is open — see the handoff notes).
This commit is contained in:
Renn F
2026-06-18 12:13:08 +02:00
parent 6f60d180e9
commit 3753fbccc4
9 changed files with 540 additions and 0 deletions
+22
View File
@@ -0,0 +1,22 @@
# GROK Intake (Prompter) Agent — interactive opencode-serve session on Grok.
# =============================================================================
# The Grok analogue of agent-prompter. Unlike the one-shot Grok runtime (a
# single `opencode run` that exits), this holds a PERSISTENT `opencode serve`
# session open, receives the human's messages over HTTP (POST /turn on :9000),
# and streams each reply back to the panel via the relay. Builds on the Grok
# runtime image (opencode + @ai-sdk/openai + the secret-scrub plugin); the
# driver renders opencode.json from the spawn env, then drives the session.
# =============================================================================
FROM roboco-agent-grok
USER agent
LABEL role="grok-prompter"
LABEL description="Intake interviewer on Grok — a long-lived opencode serve session driven by the panel"
# The in-container receiver the orchestrator delivers the human's turns to.
EXPOSE 9000
# Override the base grok one-shot entrypoint with the interactive intake driver.
ENTRYPOINT ["python", "-m", "roboco.agent_sdk.grok_intake_main"]
+22
View File
@@ -0,0 +1,22 @@
# GROK Secretary Agent — interactive opencode-serve session on Grok.
# =============================================================================
# The Grok analogue of agent-secretary. Holds a PERSISTENT `opencode serve`
# session open, receives the CEO's messages over HTTP (POST /turn on :9000), and
# streams each reply back to the panel via the relay. The Secretary's CEO-
# authority tools (read_company_state / read_task / submit_directive) reach the
# API through the mounted MCP gateway + the HMAC agent token. Builds on the Grok
# runtime image; the driver renders opencode.json from the spawn env first.
# =============================================================================
FROM roboco-agent-grok
USER agent
LABEL role="grok-secretary"
LABEL description="Secretary on Grok — a long-lived opencode serve session driven by the panel"
# The in-container receiver the orchestrator delivers the CEO's turns to.
EXPOSE 9000
# Override the base grok one-shot entrypoint with the interactive secretary driver.
ENTRYPOINT ["python", "-m", "roboco.agent_sdk.grok_secretary_main"]