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:
@@ -1,55 +0,0 @@
|
||||
"""AgentProvider interactive scaffolding: opt-in, declines by default."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
import pytest
|
||||
from roboco.llm.providers.base import (
|
||||
AgentProvider,
|
||||
InteractiveSpawnSpec,
|
||||
ProviderError,
|
||||
SpawnResult,
|
||||
)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from pathlib import Path
|
||||
|
||||
from roboco.models.runtime import OrchestratorAgentConfig as AgentConfig
|
||||
|
||||
|
||||
class _OneShotOnly(AgentProvider):
|
||||
"""A minimal provider that implements only the one-shot lifecycle."""
|
||||
|
||||
async def spawn(
|
||||
self,
|
||||
config: AgentConfig,
|
||||
initial_prompt: str | None = None,
|
||||
agent_settings_path: Path | None = None,
|
||||
) -> SpawnResult:
|
||||
return SpawnResult(instance_id="x")
|
||||
|
||||
async def stop(self, instance_id: str, graceful: bool = True) -> None: ...
|
||||
|
||||
async def health_check(self, instance_id: str) -> bool:
|
||||
return True
|
||||
|
||||
async def remove(self, instance_id: str) -> None: ...
|
||||
|
||||
|
||||
def _spec() -> InteractiveSpawnSpec:
|
||||
cfg = type("C", (), {"agent_id": "intake-1"})()
|
||||
return InteractiveSpawnSpec(
|
||||
config=cfg, image="img", session_id="s1", role="prompter"
|
||||
)
|
||||
|
||||
|
||||
def test_provider_declines_interactive_by_default() -> None:
|
||||
assert _OneShotOnly.supports_interactive is False
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_spawn_interactive_default_raises() -> None:
|
||||
# A one-shot-only provider declines interactive spawns rather than crashing.
|
||||
with pytest.raises(ProviderError):
|
||||
await _OneShotOnly().spawn_interactive(_spec())
|
||||
Reference in New Issue
Block a user