Compare commits

..

2 Commits

Author SHA1 Message Date
d38276a533 fix(deps): promote websockets to a runtime dependency
`websockets` is used by `ria_toolkit_oss.agent.ws_client`, which is
imported as part of `ria-agent stream`. It was only declared in the
optional `[tool.poetry.group.agent]` poetry group, so a vanilla
`pip install ria-toolkit-oss` left `ria-agent stream` failing with
`ModuleNotFoundError: No module named 'websockets'`.

Moved into PEP 621 `[project].dependencies` with the same constraint
(`>=12.0,<14.0`). The duplicate in the optional poetry group is left
in place so `poetry install --with agent` remains self-sufficient.

poetry.lock: `websockets` now joins the `main` dependency group; the
generator-header bump (2.1.4 → 2.3.4) and the `jsonschema-specifications`
version-string normalization are auto-regenerated noise from the
locally-installed poetry version.

Note: `requests` has the same packaging gap (used by the legacy agent
path, declared only in the optional `agent` group); leaving that for a
follow-up since the immediate complaint is websockets.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-01 13:12:20 -04:00
5b7f487a5f feat(agent): default ria-agent register --hub to https://riahub.ai
Most users register against the production hub, so requiring --hub on
every invocation was friction. Default the flag to https://riahub.ai
via a module-level DEFAULT_HUB_URL constant; explicit --hub still wins,
so dev and self-hosted setups (e.g. http://whitehorse:3005) keep working.

The legacy `ria-agent run` path keeps its own --hub handling unchanged
— it has a config-file fallback and existing operators rely on it.

Bumps version to 0.1.8.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-01 13:05:11 -04:00
6 changed files with 95 additions and 13 deletions

View File

@ -1,5 +1,17 @@
# Changelog
## [0.1.8] - 2026-06-01
### Changed
- **`ria-agent register --hub` now defaults to `https://riahub.ai`** — most users can run `ria-agent register --api-key ria_reg_...` without the `--hub` flag. Dev and self-hosted users keep the existing override (`--hub http://my-hub:3005`). The default lives in `ria_toolkit_oss.agent.cli.DEFAULT_HUB_URL`.
### Fixed
- **`websockets` is now a runtime dependency** — previously declared only in the optional `agent` poetry group, so a vanilla `pip install ria-toolkit-oss` left `ria-agent stream` failing with `ModuleNotFoundError: No module named 'websockets'`. Added to `[project].dependencies` with the same constraint (`>=12.0,<14.0`).
---
## [0.1.7] - 2026-05-26
### Added

View File

@ -14,7 +14,7 @@ sys.path.insert(0, os.path.abspath(os.path.join('..', '..')))
project = 'ria-toolkit-oss'
copyright = '2026, Qoherent Inc'
author = 'Qoherent Inc.'
release = '0.1.7'
release = '0.1.8'
# -- General configuration ---------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration

8
poetry.lock generated
View File

@ -1,4 +1,4 @@
# This file is automatically @generated by Poetry 2.1.4 and should not be changed by hand.
# This file is automatically @generated by Poetry 2.3.4 and should not be changed by hand.
[[package]]
name = "alabaster"
@ -1264,7 +1264,7 @@ files = [
[package.dependencies]
attrs = ">=22.2.0"
jsonschema-specifications = ">=2023.03.6"
jsonschema-specifications = ">=2023.3.6"
referencing = ">=0.28.4"
rpds-py = ">=0.25.0"
@ -3613,7 +3613,7 @@ version = "13.1"
description = "An implementation of the WebSocket Protocol (RFC 6455 & 7692)"
optional = false
python-versions = ">=3.8"
groups = ["agent", "docs", "server", "test"]
groups = ["main", "agent", "docs", "server", "test"]
files = [
{file = "websockets-13.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:f48c749857f8fb598fb890a75f540e3221d0976ed0bf879cf3c7eef34151acee"},
{file = "websockets-13.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c7e72ce6bda6fb9409cc1e8164dd41d7c91466fb599eb047cfda72fe758a34a7"},
@ -3706,4 +3706,4 @@ files = [
[metadata]
lock-version = "2.1"
python-versions = ">=3.10"
content-hash = "66c9adf647316db90f963da05e8a83574378bfa4db2c69ce751446b5ee7c408c"
content-hash = "17b45f12030cda8eabd0ecd10d51c98e5fa7d9b342952c1c4924b7425800cd0f"

View File

@ -1,6 +1,6 @@
[project]
name = "ria-toolkit-oss"
version = "0.1.7"
version = "0.1.8"
description = "An open-source version of the RIA Toolkit, including the fundamental tools to get started developing, testing, and deploying radio intelligence applications"
license = { text = "AGPL-3.0-only" }
readme = "README.md"
@ -50,7 +50,8 @@ dependencies = [
"pyyaml (>=6.0.3,<7.0.0)",
"click (>=8.1.0,<9.0.0)",
"matplotlib (>=3.8.0,<4.0.0)",
"paramiko (>=3.5.1)"
"paramiko (>=3.5.1)",
"websockets (>=12.0,<14.0)"
]
# [project.optional-dependencies] Commented out to prevent Tox tests from failing

View File

@ -5,11 +5,13 @@ Subcommands:
- ``ria-agent run [legacy args]`` legacy long-poll NodeAgent (unchanged).
- ``ria-agent stream`` new WebSocket-based IQ streamer.
- ``ria-agent detect`` print SDR drivers whose modules import cleanly.
- ``ria-agent register --hub URL --api-key KEY`` register with the hub
using a personal registration key (minted from **Settings RIA Agents**
on the hub, shown once at mint time) and save credentials (and optional
TX interlocks) to ``~/.ria/agent.json``. The hub also accepts the legacy
shared ``[wac] API_KEY`` for back-compat, but that path is deprecated.
- ``ria-agent register --api-key KEY`` register with the production hub
(``https://riahub.ai`` by default; override with ``--hub URL`` for dev
or self-hosted) using a personal registration key (minted from
**Settings RIA Agents** on the hub, shown once at mint time) and save
credentials (and optional TX interlocks) to ``~/.ria/agent.json``. The
hub also accepts the legacy shared ``[wac] API_KEY`` for back-compat,
but that path is deprecated.
Invoking ``ria-agent`` with no subcommand falls through to the legacy
long-poll behavior for back-compatibility with existing deployments.
@ -52,6 +54,10 @@ def _user_agent() -> str:
# small DB lookup + insert; anything past this is a stuck hub, not a slow one.
_REGISTER_TIMEOUT_S = 15
# Production hub URL — used as the default for `ria-agent register` so most
# users don't need to pass --hub. Dev / self-hosted users override explicitly.
DEFAULT_HUB_URL = "https://riahub.ai"
REGISTRATION_REASON_MESSAGES = {
"invalid_key": (
@ -226,7 +232,14 @@ def main() -> None:
sub.add_parser("detect", help="List available SDR drivers")
p_reg = sub.add_parser("register", help="Register agent with RIA Hub and save credentials")
p_reg.add_argument("--hub", required=True, help="RIA Hub URL (e.g. http://whitehorse:3005)")
p_reg.add_argument(
"--hub",
default=DEFAULT_HUB_URL,
help=(
f"RIA Hub URL (default: {DEFAULT_HUB_URL}). "
"Override for dev or self-hosted hubs, e.g. http://whitehorse:3005."
),
)
p_reg.add_argument(
"--api-key",
dest="api_key",

View File

@ -140,3 +140,59 @@ def test_register_surfaces_reason_on_http_error(tmp_path, capsys):
assert "Settings → RIA Agents" in captured.err
# Config must NOT be written on failure.
assert not cfg_path.exists()
def test_default_hub_url_is_production():
"""Lock in the constant so a future typo doesn't silently redirect users."""
assert agent_cli.DEFAULT_HUB_URL == "https://riahub.ai"
def test_register_defaults_hub_to_production(tmp_path):
"""Omitting --hub uses the production hub URL constant."""
cfg_path = tmp_path / "agent.json"
captured: dict = {}
def _fake_urlopen(req, *args, **kwargs):
captured["url"] = req.full_url
raise urllib.error.HTTPError(
url=req.full_url, code=403, msg="", hdrs=None, # type: ignore[arg-type]
fp=BytesIO(_structured("invalid_key")),
)
with (
patch.dict("os.environ", {"RIA_AGENT_CONFIG": str(cfg_path)}, clear=False),
patch("urllib.request.urlopen", side_effect=_fake_urlopen),
patch.object(sys, "argv", ["ria-agent", "register", "--api-key", "ria_reg_x"]),
):
with pytest.raises(SystemExit):
agent_cli.main()
assert captured["url"] == f"{agent_cli.DEFAULT_HUB_URL}/screens/agents/register"
def test_register_hub_override_wins_over_default(tmp_path):
"""Explicit --hub still wins; default is only a fallback."""
cfg_path = tmp_path / "agent.json"
captured: dict = {}
def _fake_urlopen(req, *args, **kwargs):
captured["url"] = req.full_url
raise urllib.error.HTTPError(
url=req.full_url, code=403, msg="", hdrs=None, # type: ignore[arg-type]
fp=BytesIO(_structured("invalid_key")),
)
with (
patch.dict("os.environ", {"RIA_AGENT_CONFIG": str(cfg_path)}, clear=False),
patch("urllib.request.urlopen", side_effect=_fake_urlopen),
patch.object(
sys,
"argv",
["ria-agent", "register", "--hub", "http://whitehorse:3005", "--api-key", "ria_reg_x"],
),
):
with pytest.raises(SystemExit):
agent_cli.main()
assert captured["url"] == "http://whitehorse:3005/screens/agents/register"
assert agent_cli.DEFAULT_HUB_URL not in captured["url"]