feat: auto-discover runners (#12)

This commit is contained in:
banteg
2026-01-01 20:31:11 +04:00
committed by GitHub
parent 936ea5109b
commit d35752fc55
21 changed files with 1069 additions and 698 deletions
+1 -1
View File
@@ -149,7 +149,7 @@ async def test_run_serializes_same_session() -> None:
finally:
in_flight -= 1
runner._run = run_stub # type: ignore[assignment]
runner.run_impl = run_stub # type: ignore[assignment]
async def drain(prompt: str, resume: ResumeToken | None) -> None:
async for _event in runner.run(prompt, resume):
+39
View File
@@ -0,0 +1,39 @@
from typing import cast
import click
import typer
from takopi import cli, engines
def test_engine_discovery_skips_non_backend() -> None:
ids = engines.list_backend_ids()
assert "codex" in ids
assert "claude" in ids
assert "mock" not in ids
def test_cli_registers_engine_commands_sorted() -> None:
command_names = [cmd.name for cmd in cli.app.registered_commands]
engine_ids = engines.list_backend_ids()
assert set(engine_ids) <= set(command_names)
engine_commands = [name for name in command_names if name in engine_ids]
assert engine_commands == engine_ids
def test_engine_commands_do_not_expose_engine_id_option() -> None:
group = cast(click.Group, typer.main.get_command(cli.app))
engine_ids = engines.list_backend_ids()
ctx = group.make_context("takopi", [])
for engine_id in engine_ids:
command = group.get_command(ctx, engine_id)
assert command is not None
options: set[str] = set()
for param in command.params:
options.update(getattr(param, "opts", []))
options.update(getattr(param, "secondary_opts", []))
assert "--final-notify" in options
assert "--debug" in options
assert not any(opt.lstrip("-") == "engine-id" for opt in options)
+3 -3
View File
@@ -39,7 +39,7 @@ async def test_run_serializes_same_session() -> None:
finally:
in_flight -= 1
runner._run = run_stub # type: ignore[assignment]
runner.run_impl = run_stub # type: ignore[assignment]
async def drain(prompt: str, resume: ResumeToken | None) -> None:
async for _event in runner.run(prompt, resume):
@@ -76,7 +76,7 @@ async def test_run_allows_parallel_new_sessions() -> None:
finally:
in_flight -= 1
runner._run = run_stub # type: ignore[assignment]
runner.run_impl = run_stub # type: ignore[assignment]
async def drain(prompt: str, resume: ResumeToken | None) -> None:
async for _event in runner.run(prompt, resume):
@@ -112,7 +112,7 @@ async def test_run_allows_parallel_different_sessions() -> None:
finally:
in_flight -= 1
runner._run = run_stub # type: ignore[assignment]
runner.run_impl = run_stub # type: ignore[assignment]
async def drain(prompt: str, resume: ResumeToken | None) -> None:
async for _event in runner.run(prompt, resume):
+7 -7
View File
@@ -7,7 +7,7 @@ from takopi import engines, onboarding
def test_check_setup_marks_missing_codex(monkeypatch, tmp_path: Path) -> None:
backend = engines.get_backend("codex")
monkeypatch.setattr(engines.shutil, "which", lambda _name: None)
monkeypatch.setattr(onboarding.shutil, "which", lambda _name: None)
monkeypatch.setattr(
onboarding,
"load_telegram_config",
@@ -17,14 +17,14 @@ def test_check_setup_marks_missing_codex(monkeypatch, tmp_path: Path) -> None:
result = onboarding.check_setup(backend)
titles = {issue.title for issue in result.issues}
assert "Install the Codex CLI" in titles
assert "Create a config" not in titles
assert "install codex" in titles
assert "create a config" not in titles
assert result.ok is False
def test_check_setup_marks_missing_config(monkeypatch) -> None:
backend = engines.get_backend("codex")
monkeypatch.setattr(engines.shutil, "which", lambda _name: "/usr/bin/codex")
monkeypatch.setattr(onboarding.shutil, "which", lambda _name: "/usr/bin/codex")
def _raise() -> None:
raise onboarding.ConfigError("Missing config file")
@@ -34,13 +34,13 @@ def test_check_setup_marks_missing_config(monkeypatch) -> None:
result = onboarding.check_setup(backend)
titles = {issue.title for issue in result.issues}
assert "Create a config" in titles
assert "create a config" in titles
assert result.config_path == onboarding.HOME_CONFIG_PATH
def test_check_setup_marks_invalid_chat_id(monkeypatch, tmp_path: Path) -> None:
backend = engines.get_backend("codex")
monkeypatch.setattr(engines.shutil, "which", lambda _name: "/usr/bin/codex")
monkeypatch.setattr(onboarding.shutil, "which", lambda _name: "/usr/bin/codex")
monkeypatch.setattr(
onboarding,
"load_telegram_config",
@@ -50,4 +50,4 @@ def test_check_setup_marks_invalid_chat_id(monkeypatch, tmp_path: Path) -> None:
result = onboarding.check_setup(backend)
titles = {issue.title for issue in result.issues}
assert "Create a config" in titles
assert "create a config" in titles