Fix dispatcher: pipe via stdin, use real cost from CLI JSON

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Symbiont 2026-03-19 19:33:09 +00:00
parent 49f73e5b46
commit 71041b92b1

View File

@ -113,39 +113,43 @@ def dispatch(
"--print", # non-interactive, just print the response
"--model", model_flag,
"--output-format", "json",
"--dangerously-skip-permissions", # full access, no prompts
]
if system_prompt:
cmd.extend(["--system-prompt", system_prompt])
# Prompt is a positional argument in Claude Code CLI
cmd.append(prompt)
start = time.monotonic()
try:
# Pipe the prompt via stdin to avoid shell escaping issues
result = subprocess.run(
cmd,
input=prompt,
capture_output=True,
text=True,
timeout=timeout_seconds,
)
elapsed = time.monotonic() - start
# Try to parse JSON output for token counts
# Parse the rich JSON output from Claude Code CLI
output_text = result.stdout.strip()
input_tokens = 0
output_tokens = 0
actual_cost_usd = 0.0
try:
parsed = json.loads(output_text)
# Claude Code JSON output includes result and usage
if isinstance(parsed, dict):
output_text = parsed.get("result", output_text)
# Claude Code gives us exact usage data
usage = parsed.get("usage", {})
input_tokens = usage.get("input_tokens", 0)
output_tokens = usage.get("output_tokens", 0)
# Real cost from the CLI (even on Pro, this tracks the equivalent)
actual_cost_usd = parsed.get("total_cost_usd", 0.0)
# Also capture cache stats for efficiency tracking
cache_read = usage.get("cache_read_input_tokens", 0)
cache_create = usage.get("cache_creation_input_tokens", 0)
except json.JSONDecodeError:
pass # Plain text output, that's fine
@ -171,12 +175,15 @@ def dispatch(
error=f"Exit code {result.returncode}: {stderr}",
)
# Estimate cost for the ledger
costs = MODEL_COSTS[tier]
estimated_cost = (
(input_tokens / 1_000_000) * costs["input"]
+ (output_tokens / 1_000_000) * costs["output"]
)
# Use real cost from CLI if available, otherwise estimate
if actual_cost_usd > 0:
estimated_cost = actual_cost_usd
else:
costs = MODEL_COSTS[tier]
estimated_cost = (
(input_tokens / 1_000_000) * costs["input"]
+ (output_tokens / 1_000_000) * costs["output"]
)
dispatch_result = DispatchResult(
success=True,