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
3 changes: 3 additions & 0 deletions .github/workflows/pypi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ jobs:
- name: Build distributions
run: uv build

- name: Check distribution metadata
run: uvx twine check dist/*

- name: Upload distribution artifacts
uses: actions/upload-artifact@v7
with:
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,8 @@ ipython_config.py
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
# uv.lock
.uv-cache/
.venv/

# poetry
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
Expand Down
674 changes: 674 additions & 0 deletions LICENSE

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion brokk_code/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "0.13.2"
__version__ = "0.13.3"
4 changes: 2 additions & 2 deletions brokk_code/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -166,8 +166,8 @@ def _passthrough_command_from_argv(

Only options before the passthrough subcommand are treated as Brokk globals.
The subcommand tail remains an exact passthrough to Anvil/Bifrost, so e.g.
`brokk mcp --bifrost-version 0.7.1` still forwards `--bifrost-version` to
Bifrost while `brokk --bifrost-version 0.7.1 mcp` selects that Bifrost binary.
`brokk mcp --bifrost-version 0.7.2` still forwards `--bifrost-version` to
Bifrost while `brokk --bifrost-version 0.7.2 mcp` selects that Bifrost binary.
"""
root_options_with_values = {
"--anvil-binary": "anvil_binary",
Expand Down
2 changes: 1 addition & 1 deletion brokk_code/rust_acp_install.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
_BIFROST_DOWNLOAD_TIMEOUT_SECONDS = 300.0
_BIFROST_LOCK_TIMEOUT_SECONDS = 600.0
_BIFROST_VERSION_PROBE_TIMEOUT_SECONDS = 5.0
_BIFROST_PINNED_VERSION = "0.6.8"
_BIFROST_PINNED_VERSION = "0.7.2"


class RustAcpInstallError(Exception):
Expand Down
55 changes: 52 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,55 @@
name = "brokk"
dynamic = ["version"]
description = "AI-native code platform for million-line repos with fragment-level context management and code intelligence"
license = { text = "GPL-3.0-only" }
readme = "README.md"
requires-python = ">=3.11"
license = "GPL-3.0-only"
license-files = ["LICENSE"]
authors = [
{ name = "foundev", email = "86598053+foundev@users.noreply.github.com" },
]
maintainers = [
{ name = "foundev", email = "86598053+foundev@users.noreply.github.com" },
]
keywords = [
"acp",
"agent-client-protocol",
"ai",
"brokk",
"cli",
"code-intelligence",
"coding-agent",
"developer-tools",
"mcp",
"model-context-protocol",
]
classifiers = [
"License :: OSI Approved :: GNU General Public License v3 (GPLv3)",
"Development Status :: 5 - Production/Stable",
"Environment :: Console",
"Intended Audience :: Developers",
"Natural Language :: English",
"Operating System :: MacOS",
"Operating System :: Microsoft :: Windows",
"Operating System :: POSIX :: Linux",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3 :: Only",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Topic :: Software Development",
"Topic :: Software Development :: Version Control :: Git",
"Topic :: Utilities",
]
requires-python = ">=3.11"
dependencies = [
"httpx>=0.25.0",
]

[project.urls]
Homepage = "https://github.com/BrokkAi/brokk-cli"
Repository = "https://github.com/BrokkAi/brokk-cli"
Issues = "https://github.com/BrokkAi/brokk-cli/issues"
Documentation = "https://github.com/BrokkAi/brokk-cli"

[dependency-groups]
dev = [
"pytest>=8.0.0",
Expand All @@ -25,6 +65,15 @@ brokk = "brokk_code.__main__:main"
requires = ["hatchling"]
build-backend = "hatchling.build"

[tool.hatch.build]
exclude = [
"/.bifrost",
"/.pytest_cache",
"/.uv-cache",
"/.venv",
"/dist",
]

[tool.hatch.build.targets.wheel]
packages = ["brokk_code"]

Expand Down
6 changes: 3 additions & 3 deletions tests/test_bifrost_launcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,10 @@ def fake_resolve(**kwargs: object) -> Path:
monkeypatch.setattr(os, "execvpe", lambda *_a: (_ for _ in ()).throw(RuntimeError("stop")))

with pytest.raises(RuntimeError, match="stop"):
bifrost_launcher.run_bifrost_server(workspace_dir=tmp_path, version="0.7.1")
bifrost_launcher.run_bifrost_server(workspace_dir=tmp_path, version="0.7.2")

assert captured["resolve_kwargs"] == {
"version": "0.7.1",
"version": "0.7.2",
"override": None,
"prefer_local": False,
}
Expand Down Expand Up @@ -157,7 +157,7 @@ def fake_download(version: str) -> Path:

assert resolved == resolved_binary
assert captured["version"] == rust_acp_install._BIFROST_PINNED_VERSION
assert captured["version"] == "0.6.8"
assert captured["version"] == "0.7.2"


# ---------------------------------------------------------------------------
Expand Down
16 changes: 8 additions & 8 deletions tests/test_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,38 +3,38 @@

def test_passthrough_parser_consumes_global_bifrost_version() -> None:
parsed = brokk_main._passthrough_command_from_argv(
["--bifrost-version", "0.7.1", "mcp", "--server", "searchtools"]
["--bifrost-version", "0.7.2", "mcp", "--server", "searchtools"]
)

assert parsed is not None
args, passthrough_args = parsed
assert args.command == "mcp"
assert args.bifrost_version == "0.7.1"
assert args.bifrost_version == "0.7.2"
assert passthrough_args == ["--server", "searchtools"]


def test_passthrough_parser_consumes_equals_form_global_bifrost_version() -> None:
parsed = brokk_main._passthrough_command_from_argv(
["--bifrost-version=0.7.1", "mcp", "--server", "searchtools"]
["--bifrost-version=0.7.2", "mcp", "--server", "searchtools"]
)

assert parsed is not None
args, passthrough_args = parsed
assert args.command == "mcp"
assert args.bifrost_version == "0.7.1"
assert args.bifrost_version == "0.7.2"
assert passthrough_args == ["--server", "searchtools"]


def test_passthrough_parser_leaves_subcommand_bifrost_version_as_passthrough() -> None:
parsed = brokk_main._passthrough_command_from_argv(
["mcp", "--bifrost-version", "0.7.1", "--server", "searchtools"]
["mcp", "--bifrost-version", "0.7.2", "--server", "searchtools"]
)

assert parsed is not None
args, passthrough_args = parsed
assert args.command == "mcp"
assert args.bifrost_version is None
assert passthrough_args == ["--bifrost-version", "0.7.1", "--server", "searchtools"]
assert passthrough_args == ["--bifrost-version", "0.7.2", "--server", "searchtools"]


def test_passthrough_parser_consumes_global_anvil_runtime_options(tmp_path) -> None:
Expand Down Expand Up @@ -68,12 +68,12 @@ def fake_run_bifrost_server(**kwargs: object) -> None:

monkeypatch.setattr(bifrost_launcher, "run_bifrost_server", fake_run_bifrost_server)

args = brokk_main.argparse.Namespace(command="mcp", bifrost_version="0.7.1")
args = brokk_main.argparse.Namespace(command="mcp", bifrost_version="0.7.2")
brokk_main._main_dispatch(args, tmp_path, ["--server", "searchtools"])

assert captured == {
"workspace_dir": tmp_path,
"version": "0.7.1",
"version": "0.7.2",
"passthrough_args": ["--server", "searchtools"],
}

Expand Down
57 changes: 57 additions & 0 deletions tests/test_package_metadata.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import tomllib
from pathlib import Path

ROOT = Path(__file__).resolve().parents[1]
ORIGIN_URL = "https://github.com/BrokkAi/brokk-cli"
FOUNDEV_AUTHOR = {
"name": "foundev",
"email": "86598053+foundev@users.noreply.github.com",
}


def _project_metadata() -> dict[str, object]:
with (ROOT / "pyproject.toml").open("rb") as pyproject_file:
return tomllib.load(pyproject_file)["project"]


def test_package_metadata_populates_pypi_project_page() -> None:
project = _project_metadata()

assert project["readme"] == "README.md"
assert (ROOT / project["readme"]).is_file()
assert project["license"] == "GPL-3.0-only"
assert project["license-files"] == ["LICENSE"]
assert (ROOT / "LICENSE").is_file()
assert project["authors"] == [FOUNDEV_AUTHOR]
assert project["maintainers"] == [FOUNDEV_AUTHOR]
assert project["urls"] == {
"Homepage": ORIGIN_URL,
"Repository": ORIGIN_URL,
"Issues": f"{ORIGIN_URL}/issues",
"Documentation": ORIGIN_URL,
}

keywords = project["keywords"]
assert "brokk" in keywords
assert "coding-agent" in keywords
assert "model-context-protocol" in keywords

classifiers = project["classifiers"]
assert "Development Status :: 5 - Production/Stable" in classifiers
assert "Intended Audience :: Developers" in classifiers
# The license is declared via the SPDX ``license`` expression (asserted
# above), so no ``License ::`` Trove classifier may be present: PEP 639
# forbids pairing a License-Expression with license classifiers and PyPI
# rejects such uploads.
assert not any(c.startswith("License ::") for c in classifiers)
assert "Programming Language :: Python :: 3.11" in classifiers
assert "Programming Language :: Python :: 3.12" in classifiers
assert "Programming Language :: Python :: 3.13" in classifiers


def test_package_license_file_contains_gplv3_text() -> None:
license_text = (ROOT / "LICENSE").read_text(encoding="utf-8")

assert "GNU GENERAL PUBLIC LICENSE" in license_text
assert "Version 3, 29 June 2007" in license_text
assert "https://www.gnu.org/licenses/" in license_text
Loading