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
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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)
Expand Down
2 changes: 1 addition & 1 deletion glaive/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@
typed evidence graph.
"""

__version__ = "0.2.0"
__version__ = "0.2.1"
9 changes: 8 additions & 1 deletion glaive/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand All @@ -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
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -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"
Expand Down
4 changes: 2 additions & 2 deletions tests/test_smoke.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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:
Expand Down
22 changes: 22 additions & 0 deletions tests/v02/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Loading