mirror of
https://github.com/rennf93/roboco.git
synced 2026-08-03 07:23:24 +02:00
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:
@@ -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
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user