From 790dad3f0ba34ef964cb50269c9b58ca9d4b9c81 Mon Sep 17 00:00:00 2001 From: Aliya Alias Date: Fri, 2 Oct 2026 20:24:14 +0800 Subject: [PATCH 1/2] fix(cli): make demo --serve start the web app demo called the serve command function directly, so Typer's OptionInfo defaults were passed as host/port and serving crashed with a TypeError. Move the body into a plain _serve() helper used by both commands, and add a regression test. --- glaive/cli.py | 9 ++++++++- tests/v02/test_cli.py | 22 ++++++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/glaive/cli.py b/glaive/cli.py index c9dd4f5..173a956 100644 --- a/glaive/cli.py +++ b/glaive/cli.py @@ -191,7 +191,7 @@ def demo( html_path, _ = _write_reports(session, ev.to_markdown()) console.print(f"\nReport: [bold]{html_path}[/]") if serve_after: - serve(out / "case") + _serve(out / "case") @app.command() @@ -202,6 +202,13 @@ def serve( no_browser: bool = typer.Option(False, help="Do not open a browser."), ) -> None: """Open the web app for a case.""" + _serve(case, host, port, no_browser) + + +def _serve(case: Path, host: str = "127.0.0.1", port: int = 8765, + no_browser: bool = False) -> None: + # Plain function so other commands can call it: calling a Typer command directly + # would pass its typer.Option(...) defaults instead of real values. import secrets import uvicorn diff --git a/tests/v02/test_cli.py b/tests/v02/test_cli.py index 9e519bd..477235d 100644 --- a/tests/v02/test_cli.py +++ b/tests/v02/test_cli.py @@ -41,3 +41,25 @@ def test_demo_investigate_verify(tmp_path: Path) -> None: assert _cli("report", "c2", cwd=tmp_path).returncode == 0 assert "Default model" in _cli("models", cwd=tmp_path).stdout + + + +def test_demo_serve_starts_local_server(tmp_path: Path, monkeypatch) -> None: # noqa: ANN001 + import uvicorn + from typer.testing import CliRunner + + from glaive import cli + + started: dict = {} + monkeypatch.setattr(uvicorn, "run", lambda app, **kw: started.update(kw)) + monkeypatch.setattr(cli.webbrowser, "open", lambda url: started.update(url=url)) + for key in [k for k in os.environ if k.endswith("_API_KEY")]: + monkeypatch.delenv(key) + monkeypatch.delenv("GLAIVE_WEB_TOKEN", raising=False) + + r = CliRunner().invoke(cli.app, ["demo", "--out", str(tmp_path / "d"), "--offline", + "--serve"]) + assert r.exit_code == 0, r.output + assert started["host"] == "127.0.0.1" and started["port"] == 8765 + assert started["url"] == "http://127.0.0.1:8765/" + assert "token" not in r.output From db5f0370a5d0cd5c737880db23cd80f9e9cdb3a5 Mon Sep 17 00:00:00 2001 From: Aliya Alias Date: Fri, 2 Oct 2026 20:43:35 +0800 Subject: [PATCH 2/2] chore(release): 0.2.1 --- CHANGELOG.md | 5 +++++ glaive/__init__.py | 2 +- pyproject.toml | 2 +- tests/test_smoke.py | 4 ++-- 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cdace22..ce5a4af 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog +## 0.2.1 - 2026-10 + +### Fixed +- `glaive demo --serve` crashed with `TypeError: argument of type 'OptionInfo' is not iterable` instead of opening the web app. + ## 0.2.0 - 2026-10 ### Fixed (found by auditing and running v0.1) diff --git a/glaive/__init__.py b/glaive/__init__.py index 353a69c..9c6b77e 100644 --- a/glaive/__init__.py +++ b/glaive/__init__.py @@ -4,4 +4,4 @@ typed evidence graph. """ -__version__ = "0.2.0" +__version__ = "0.2.1" diff --git a/pyproject.toml b/pyproject.toml index 21d000d..e9e6bbf 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "glaive" -version = "0.2.0" +version = "0.2.1" readme = "README.md" description = "AI forensic investigator whose every finding is verified against the evidence. Works with any model (Claude, GPT, DeepSeek, Qwen, Kimi, GLM, local) or none." requires-python = ">=3.11" diff --git a/tests/test_smoke.py b/tests/test_smoke.py index 14507b1..210cf03 100644 --- a/tests/test_smoke.py +++ b/tests/test_smoke.py @@ -8,7 +8,7 @@ def test_package_imports() -> None: import glaive - assert glaive.__version__ == "0.2.0" + assert glaive.__version__ == "0.2.1" def test_cli_version_runs() -> None: @@ -18,7 +18,7 @@ def test_cli_version_runs() -> None: text=True, ) assert result.returncode == 0, result.stderr - assert "glaive 0.2.0" in result.stdout + assert "glaive 0.2.1" in result.stdout def test_cli_investigate_missing_path_exits_2() -> None: