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:
parent
49f73e5b46
commit
71041b92b1
@ -113,39 +113,43 @@ def dispatch(
|
|||||||
"--print", # non-interactive, just print the response
|
"--print", # non-interactive, just print the response
|
||||||
"--model", model_flag,
|
"--model", model_flag,
|
||||||
"--output-format", "json",
|
"--output-format", "json",
|
||||||
"--dangerously-skip-permissions", # full access, no prompts
|
|
||||||
]
|
]
|
||||||
|
|
||||||
if system_prompt:
|
if system_prompt:
|
||||||
cmd.extend(["--system-prompt", system_prompt])
|
cmd.extend(["--system-prompt", system_prompt])
|
||||||
|
|
||||||
# Prompt is a positional argument in Claude Code CLI
|
|
||||||
cmd.append(prompt)
|
|
||||||
|
|
||||||
start = time.monotonic()
|
start = time.monotonic()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
# Pipe the prompt via stdin to avoid shell escaping issues
|
||||||
result = subprocess.run(
|
result = subprocess.run(
|
||||||
cmd,
|
cmd,
|
||||||
|
input=prompt,
|
||||||
capture_output=True,
|
capture_output=True,
|
||||||
text=True,
|
text=True,
|
||||||
timeout=timeout_seconds,
|
timeout=timeout_seconds,
|
||||||
)
|
)
|
||||||
elapsed = time.monotonic() - start
|
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()
|
output_text = result.stdout.strip()
|
||||||
input_tokens = 0
|
input_tokens = 0
|
||||||
output_tokens = 0
|
output_tokens = 0
|
||||||
|
actual_cost_usd = 0.0
|
||||||
|
|
||||||
try:
|
try:
|
||||||
parsed = json.loads(output_text)
|
parsed = json.loads(output_text)
|
||||||
# Claude Code JSON output includes result and usage
|
|
||||||
if isinstance(parsed, dict):
|
if isinstance(parsed, dict):
|
||||||
output_text = parsed.get("result", output_text)
|
output_text = parsed.get("result", output_text)
|
||||||
|
# Claude Code gives us exact usage data
|
||||||
usage = parsed.get("usage", {})
|
usage = parsed.get("usage", {})
|
||||||
input_tokens = usage.get("input_tokens", 0)
|
input_tokens = usage.get("input_tokens", 0)
|
||||||
output_tokens = usage.get("output_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:
|
except json.JSONDecodeError:
|
||||||
pass # Plain text output, that's fine
|
pass # Plain text output, that's fine
|
||||||
|
|
||||||
@ -171,12 +175,15 @@ def dispatch(
|
|||||||
error=f"Exit code {result.returncode}: {stderr}",
|
error=f"Exit code {result.returncode}: {stderr}",
|
||||||
)
|
)
|
||||||
|
|
||||||
# Estimate cost for the ledger
|
# Use real cost from CLI if available, otherwise estimate
|
||||||
costs = MODEL_COSTS[tier]
|
if actual_cost_usd > 0:
|
||||||
estimated_cost = (
|
estimated_cost = actual_cost_usd
|
||||||
(input_tokens / 1_000_000) * costs["input"]
|
else:
|
||||||
+ (output_tokens / 1_000_000) * costs["output"]
|
costs = MODEL_COSTS[tier]
|
||||||
)
|
estimated_cost = (
|
||||||
|
(input_tokens / 1_000_000) * costs["input"]
|
||||||
|
+ (output_tokens / 1_000_000) * costs["output"]
|
||||||
|
)
|
||||||
|
|
||||||
dispatch_result = DispatchResult(
|
dispatch_result = DispatchResult(
|
||||||
success=True,
|
success=True,
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user