Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions roles/evaluator.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,23 @@ def _call_llm(prompt: str, cfg: dict) -> tuple[str, int, float]:
tokens = resp.usage.total_tokens
return resp.choices[0].message.content, tokens, tokens * 3e-6

if provider == "claude_cli":
import subprocess
proc = subprocess.run(
["claude", "-p", "--model", model, "--output-format", "json"],
input=prompt,
capture_output=True,
text=True,
)
Comment on lines +46 to +51
if proc.returncode != 0:
raise RuntimeError(f"claude -p failed (exit {proc.returncode}): {proc.stderr[:200]}")
data = json.loads(proc.stdout)
text = data.get("result", "")
usage = data.get("usage", {})
tokens = usage.get("input_tokens", 0) + usage.get("output_tokens", 0)
cost = float(data.get("total_cost_usd", 0.0))
return text, tokens, cost

raise ValueError(f"unknown llm.provider: {provider!r}")


Expand Down
17 changes: 17 additions & 0 deletions roles/goal_evaluator.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,21 @@ def _call_openai(prompt: str, model: str, api_key_env: str) -> str:
return resp.choices[0].message.content


def _call_claude_cli(prompt: str, model: str) -> str:
"""Call Claude via the local Claude Code CLI (no API key required)."""
import subprocess
proc = subprocess.run(
["claude", "-p", "--model", model, "--output-format", "json"],
input=prompt,
capture_output=True,
text=True,
)
Comment on lines +44 to +49
if proc.returncode != 0:
raise RuntimeError(f"claude -p failed (exit {proc.returncode}): {proc.stderr[:200]}")
data = json.loads(proc.stdout)
return data.get("result", "")


def main() -> None:
parser = argparse.ArgumentParser()
parser.add_argument("--input", required=True)
Expand Down Expand Up @@ -81,6 +96,8 @@ def main() -> None:
text = _call_anthropic(prompt, model, api_key_env)
elif provider == "openai":
text = _call_openai(prompt, model, api_key_env)
elif provider == "claude_cli":
text = _call_claude_cli(prompt, model)
else:
print(f"error: unknown llm.provider: {provider!r}", file=sys.stderr)
sys.exit(1)
Expand Down
25 changes: 25 additions & 0 deletions roles/planner.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,29 @@ def _call_openai(prompt: str, model: str, api_key_env: str) -> tuple[str, int, f
return resp.choices[0].message.content, tokens, cost


def _call_claude_cli(prompt: str, model: str) -> tuple[str, int, float]:
"""Call Claude via the local Claude Code CLI (no API key required).

Uses --output-format json to recover the response text plus real
token / cost numbers, so kernel-level cost guards keep working.
"""
import subprocess
proc = subprocess.run(
["claude", "-p", "--model", model, "--output-format", "json"],
input=prompt,
capture_output=True,
text=True,
)
Comment on lines +55 to +60
if proc.returncode != 0:
raise RuntimeError(f"claude -p failed (exit {proc.returncode}): {proc.stderr[:200]}")
data = json.loads(proc.stdout)
text = data.get("result", "")
usage = data.get("usage", {})
tokens = usage.get("input_tokens", 0) + usage.get("output_tokens", 0)
cost = float(data.get("total_cost_usd", 0.0))
return text, tokens, cost


def main() -> None:
parser = argparse.ArgumentParser()
parser.add_argument("--input", required=True)
Expand Down Expand Up @@ -104,6 +127,8 @@ def main() -> None:
text, tokens, cost = _call_anthropic(prompt, model, api_key_env)
elif provider == "openai":
text, tokens, cost = _call_openai(prompt, model, api_key_env)
elif provider == "claude_cli":
text, tokens, cost = _call_claude_cli(prompt, model)
else:
print(f"error: unknown llm.provider: {provider!r}", file=sys.stderr)
sys.exit(1)
Expand Down
17 changes: 17 additions & 0 deletions roles/strategist.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,21 @@ def _call_openai(prompt: str, model: str, api_key_env: str) -> str:
return resp.choices[0].message.content


def _call_claude_cli(prompt: str, model: str) -> str:
"""Call Claude via the local Claude Code CLI (no API key required)."""
import subprocess
proc = subprocess.run(
["claude", "-p", "--model", model, "--output-format", "json"],
input=prompt,
capture_output=True,
text=True,
)
Comment on lines +44 to +49
if proc.returncode != 0:
raise RuntimeError(f"claude -p failed (exit {proc.returncode}): {proc.stderr[:200]}")
data = json.loads(proc.stdout)
return data.get("result", "")


def main() -> None:
parser = argparse.ArgumentParser()
parser.add_argument("--input", required=True)
Expand Down Expand Up @@ -80,6 +95,8 @@ def main() -> None:
text = _call_anthropic(prompt, model, api_key_env)
elif provider == "openai":
text = _call_openai(prompt, model, api_key_env)
elif provider == "claude_cli":
text = _call_claude_cli(prompt, model)
else:
print(f"error: unknown llm.provider: {provider!r}", file=sys.stderr)
sys.exit(1)
Expand Down
Loading