feat(grok): price grok-build-0.1 + secret-scrub opencode plugin

- pricing.py: add grok-build-0.1 rates ($1/1M input, $0.20 cached, $2/1M
  output), verified against xAI's published pricing. Grok is a priced
  non-Anthropic model, so cost computes the moment usage is captured.
- secret-scrub.js: an opencode tool.execute.before plugin porting the
  security-critical bash-guard deny rules (git network ops, credential-file
  reads, /proc env, internal-host HTTP, roboco.* imports, ROBOCO_AGENT_ID
  forgery, env dumps, destructive rm) to the opencode runtime — restoring the
  guard the Claude Code hook can't provide there. Throwing denies the call
  (confirmed by opencode's env-protection example). Wired into the generated
  opencode.json plugin array + baked into the grok image.

Deny logic verified via node (9 deny + 5 allow cases). UNVALIDATED against a
live opencode runtime: confirm it fires in the live E2E spawn before a Grok
dev-agent touches a real repo; the bash permission is operator-tunable as a
second gate.

Cost CAPTURE (distinct from pricing) is intentionally NOT built yet: opencode's
plugin hooks expose model info but no token/usage object, so the capture path
is unconfirmed and needs the live spawn to settle.
This commit is contained in:
Renn F
2026-06-18 08:36:36 +02:00
parent a9b7b7ead5
commit 07f55117de
6 changed files with 200 additions and 3 deletions
+46
View File
@@ -39,6 +39,12 @@ _HAIKU_CACHE_WRITE = 1.25
_HAIKU3_INPUT = 0.25 # claude-haiku-3 is cheaper than haiku-3-5 / haiku-4
# xAI Grok — priced non-Anthropic (per the xAI API)
_GROK_INPUT = 1.00
_GROK_OUTPUT = 2.00
_GROK_CACHE_READ = 0.20
_GROK_CACHE_WRITE = 1.00
# Tolerance for floating-point comparisons
_TOL = 1e-4
@@ -214,6 +220,46 @@ class TestHaikuTier:
assert abs(cost - _HAIKU3_INPUT) < _TOL
# ---------------------------------------------------------------------------
# Grok tier (xAI — priced non-Anthropic)
# ---------------------------------------------------------------------------
class TestGrokTier:
"""grok-build-0.1 pricing — a non-Anthropic model that IS billed per token."""
def test_input_only(self) -> None:
cost = calculate_cost("grok-build-0.1", tokens_input=_M, tokens_output=0)
assert abs(cost - _GROK_INPUT) < _TOL
def test_output_only(self) -> None:
cost = calculate_cost("grok-build-0.1", tokens_input=0, tokens_output=_M)
assert abs(cost - _GROK_OUTPUT) < _TOL
def test_cached_input(self) -> None:
cost = calculate_cost(
"grok-build-0.1", tokens_input=0, tokens_output=0, tokens_cache_read=_M
)
assert abs(cost - _GROK_CACHE_READ) < _TOL
def test_all_token_types(self) -> None:
cost = calculate_cost(
"grok-build-0.1",
tokens_input=_M,
tokens_output=_M,
tokens_cache_read=_M,
tokens_cache_write=_M,
)
expected = _GROK_INPUT + _GROK_OUTPUT + _GROK_CACHE_READ + _GROK_CACHE_WRITE
assert abs(cost - expected) < _TOL
def test_grok_is_not_treated_as_anthropic(self) -> None:
"""Priced, but not an Anthropic model (no warn-on-unpriced path)."""
assert _is_anthropic_model("grok-build-0.1") is False
# Still resolves to a real (non-zero) per-token cost.
assert calculate_cost("grok-build-0.1", tokens_input=_M, tokens_output=0) > 0.0
# ---------------------------------------------------------------------------
# Unknown / edge cases — must return 0.0 without raising
# ---------------------------------------------------------------------------