Files
wehub-resource-sync 2c632336aa
CI / Viewer CI (push) Successful in 13m37s
CI / Core CI (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:32:38 +08:00

314 lines
9.4 KiB
Python

from __future__ import annotations
import json
from pathlib import Path
import pytest
from agent import runner
def test_runner_help_text(capsys: pytest.CaptureFixture[str]) -> None:
with pytest.raises(SystemExit, match="0"):
runner.main(["--help"])
help_text = capsys.readouterr().out
assert "--prompt" in help_text
assert "--image" in help_text
assert (
"--provider {anthropic,codex-cli,dashscope,gemini,openai,openrouter,deepseek}" in help_text
)
assert "--openai-transport {http,websocket}" in help_text
assert "--data-dir DATA_DIR" in help_text
assert "--category CATEGORY" in help_text
assert "--max-cost-usd MAX_COST_USD" in help_text
assert "--flash" not in help_text
assert "--hybrid-sdk" not in help_text
assert "--openai-reasoning-summary" not in help_text
assert "Currently supported only with --provider openai." not in help_text
def test_runner_rejects_removed_flash_flag(capsys: pytest.CaptureFixture[str]) -> None:
with pytest.raises(SystemExit, match="2"):
runner.main(["--prompt", "test", "--flash"])
assert "unrecognized arguments: --flash" in capsys.readouterr().err
def test_runner_rejects_removed_collection_flag(
capsys: pytest.CaptureFixture[str],
) -> None:
with pytest.raises(SystemExit, match="2"):
runner.main(["--prompt", "test", "--collection", "dataset"])
assert "unrecognized arguments: --collection dataset" in capsys.readouterr().err
def test_runner_dump_provider_payload_supports_sdk(
capsys: pytest.CaptureFixture[str],
) -> None:
exit_code = runner.main(
[
"--prompt",
"test prompt",
"--dump-provider-payload",
]
)
assert exit_code == 0
payload = json.loads(capsys.readouterr().out)
docs_message = payload["input"][0]["content"][0]["text"]
assert "## docs/sdk/references/quickstart.md" in docs_message
assert "Import from `sdk` in `model.py`." in docs_message
def test_runner_accepts_openai_api_keys_env(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
) -> None:
captured: dict[str, object] = {}
async def _fake_run_from_input(*args, **kwargs) -> int: # type: ignore[no-untyped-def]
captured.update(kwargs)
return 0
monkeypatch.setattr(runner, "run_from_input", _fake_run_from_input)
monkeypatch.delenv("OPENAI_API_KEY", raising=False)
monkeypatch.setenv("OPENAI_API_KEYS", "sk-first,sk-second")
monkeypatch.setenv("ARTICRAFT_MAX_COST_USD", "1.25")
monkeypatch.setenv("ARTICRAFT_THINKING_LEVEL", "xhigh")
exit_code = runner.main(
[
"--prompt",
"test prompt",
"--provider",
"openai",
"--repo-root",
str(tmp_path),
]
)
assert exit_code == 0
assert captured["max_cost_usd"] == 1.25
assert captured["thinking_level"] == "xhigh"
def test_runner_rejects_codex_cli_without_explicit_model(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
capsys: pytest.CaptureFixture[str],
) -> None:
async def _fake_run_from_input(*args, **kwargs) -> int: # type: ignore[no-untyped-def]
raise AssertionError("run_from_input should not be called")
monkeypatch.setattr(runner, "run_from_input", _fake_run_from_input)
monkeypatch.delenv("ARTICRAFT_CODEX_MODEL", raising=False)
exit_code = runner.main(
[
"--prompt",
"test prompt",
"--provider",
"codex-cli",
"--repo-root",
str(tmp_path),
]
)
assert exit_code == 1
assert "requires an explicit model" in capsys.readouterr().err
def test_runner_dump_provider_payload_supports_openrouter(
capsys: pytest.CaptureFixture[str],
) -> None:
exit_code = runner.main(
[
"--prompt",
"test prompt",
"--provider",
"openrouter",
"--thinking",
"high",
"--dump-provider-payload",
]
)
assert exit_code == 0
payload = json.loads(capsys.readouterr().out)
assert payload["base_url"] == "https://openrouter.ai/api/v1"
assert payload["model"] == "tencent/hy3-preview:free"
assert payload["extra_body"]["reasoning"]["enabled"] is True
assert payload["extra_body"]["reasoning"]["effort"] == "high"
assert payload["messages"][0]["role"] == "system"
assert "<process>" in payload["messages"][0]["content"]
assert (
"Work evidence-first. Before editing, read `model.py`" in payload["messages"][0]["content"]
)
assert payload["messages"][1]["role"] == "user"
def test_runner_dump_provider_payload_supports_dashscope(
capsys: pytest.CaptureFixture[str],
) -> None:
exit_code = runner.main(
[
"--prompt",
"test prompt",
"--provider",
"dashscope",
"--dump-provider-payload",
]
)
assert exit_code == 0
payload = json.loads(capsys.readouterr().out)
assert payload["base_url"] == "https://dashscope.aliyuncs.com/compatible-mode/v1"
assert payload["model"] == "qwen3.6-flash"
assert payload["extra_body"] == {"enable_thinking": True}
assert payload["messages"][0]["role"] == "system"
assert "<process>" in payload["messages"][0]["content"]
assert payload["messages"][1]["role"] == "user"
def test_runner_dump_provider_payload_supports_anthropic(
capsys: pytest.CaptureFixture[str],
) -> None:
exit_code = runner.main(
[
"--prompt",
"test prompt",
"--provider",
"anthropic",
"--thinking",
"high",
"--dump-provider-payload",
]
)
assert exit_code == 0
payload = json.loads(capsys.readouterr().out)
assert payload["base_url"] == "https://api.anthropic.com"
assert payload["model"] == "claude-opus-4-7"
assert payload["thinking"] == {"type": "adaptive"}
assert payload["output_config"] == {"effort": "high"}
system_text = payload["system"][0]["text"]
assert payload["system"][0]["cache_control"] == {"type": "ephemeral"}
assert "<process>" in system_text
assert "Work evidence-first. Before editing, read `model.py`" in system_text
assert payload["messages"][0]["role"] == "user"
def test_runner_dump_provider_payload_uses_openai_env_defaults(
monkeypatch: pytest.MonkeyPatch,
capsys: pytest.CaptureFixture[str],
) -> None:
monkeypatch.setenv("ARTICRAFT_MODEL", "gpt-5.5")
monkeypatch.setenv("ARTICRAFT_THINKING_LEVEL", "xhigh")
exit_code = runner.main(
[
"--prompt",
"test prompt",
"--provider",
"openai",
"--dump-provider-payload",
]
)
assert exit_code == 0
payload = json.loads(capsys.readouterr().out)
assert payload["model"] == "gpt-5.5"
assert payload["reasoning"]["effort"] == "xhigh"
def test_runner_infers_provider_from_env_default_model(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
capsys: pytest.CaptureFixture[str],
) -> None:
repo_root = tmp_path / "repo"
repo_root.mkdir()
(repo_root / ".env").write_text(
"ARTICRAFT_MODEL=gemini-3-flash-preview\nARTICRAFT_THINKING_LEVEL=high\n",
encoding="utf-8",
)
monkeypatch.delenv("ARTICRAFT_MODEL", raising=False)
monkeypatch.delenv("ARTICRAFT_THINKING_LEVEL", raising=False)
exit_code = runner.main(
[
"--prompt",
"test prompt",
"--repo-root",
str(repo_root),
"--dump-provider-payload",
]
)
assert exit_code == 0
payload = json.loads(capsys.readouterr().out)
assert payload["model"] == "gemini-3-flash-preview"
assert "contents" in payload
assert "reasoning" not in payload
def test_runner_rejects_invalid_env_thinking_level(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
capsys: pytest.CaptureFixture[str],
) -> None:
repo_root = tmp_path / "repo"
repo_root.mkdir()
(repo_root / ".env").write_text("ARTICRAFT_THINKING_LEVEL=not-a-level\n", encoding="utf-8")
monkeypatch.delenv("ARTICRAFT_THINKING_LEVEL", raising=False)
with pytest.raises(SystemExit, match="2"):
runner.main(
[
"--prompt",
"test prompt",
"--repo-root",
str(repo_root),
"--dump-provider-payload",
]
)
assert "ARTICRAFT_THINKING_LEVEL must be one of" in capsys.readouterr().err
def test_runner_loads_env_defaults_from_repo_root(
monkeypatch: pytest.MonkeyPatch,
tmp_path: Path,
capsys: pytest.CaptureFixture[str],
) -> None:
repo_root = tmp_path / "repo"
repo_root.mkdir()
(repo_root / ".env").write_text(
"ARTICRAFT_MODEL=gpt-5.5-direct-runner\nARTICRAFT_THINKING_LEVEL=xhigh\n",
encoding="utf-8",
)
other_cwd = tmp_path / "cwd"
other_cwd.mkdir()
monkeypatch.chdir(other_cwd)
monkeypatch.delenv("ARTICRAFT_MODEL", raising=False)
monkeypatch.delenv("ARTICRAFT_THINKING_LEVEL", raising=False)
exit_code = runner.main(
[
"--prompt",
"test prompt",
"--provider",
"openai",
"--repo-root",
str(repo_root),
"--dump-provider-payload",
]
)
assert exit_code == 0
payload = json.loads(capsys.readouterr().out)
assert payload["model"] == "gpt-5.5-direct-runner"
assert payload["reasoning"]["effort"] == "xhigh"