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: 3 additions & 2 deletions .github/workflows/build_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ jobs:
uses: OpenVoiceOS/gh-automations/.github/workflows/build-tests.yml@dev
with:
python_versions: '["3.10", "3.11", "3.12", "3.13"]'
# full policy stack for e2e ACL tests; hivemind-core git pin until #89 merges
pre_install_pip: '"hivescope==0.3.0a1" "hivemind-plugin-manager==0.6.0a1" "hivemind-ovos-agent-plugin==0.2.0a1" "hivemind-core==4.3.0a2"'
# the [e2e] extra pins the full bus-client 2.x stack (hivescope, hivemind-core,
# policy plugins) as prerelease floors — no pre_install_pip / --pre needed
install_extras: 'e2e'
test_path: 'tests/'
16 changes: 16 additions & 0 deletions .github/workflows/coverage.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
name: Code Coverage

on:
pull_request:
branches: [dev]
workflow_dispatch:

jobs:
coverage:
uses: OpenVoiceOS/gh-automations/.github/workflows/coverage.yml@dev
with:
python_version: '3.11'
coverage_source: 'hivemind_cli_terminal'
test_path: 'tests/'
test_extras: 'e2e'
min_coverage: 0
13 changes: 13 additions & 0 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
name: Lint

on:
pull_request:
branches: [dev, master]
workflow_dispatch:

jobs:
lint:
uses: OpenVoiceOS/gh-automations/.github/workflows/lint.yml@dev
with:
ruff: true
pre_commit: false
10 changes: 10 additions & 0 deletions .github/workflows/pip_audit.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
name: PIP Audit

on:
pull_request:
branches: [dev]
workflow_dispatch:

jobs:
pip_audit:
uses: OpenVoiceOS/gh-automations/.github/workflows/pip-audit.yml@dev
13 changes: 13 additions & 0 deletions .github/workflows/release_preview.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
name: Release Preview

on:
pull_request:
branches: [dev]
workflow_dispatch:

jobs:
release_preview:
uses: OpenVoiceOS/gh-automations/.github/workflows/release-preview.yml@dev
with:
package_name: 'HiveMind-cli'
version_file: 'hivemind_cli_terminal/version.py'
12 changes: 12 additions & 0 deletions .github/workflows/repo_health.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
name: Repo Health

on:
pull_request:
branches: [dev, master]
workflow_dispatch:

jobs:
repo_health:
uses: OpenVoiceOS/gh-automations/.github/workflows/repo-health.yml@dev
with:
version_file: 'hivemind_cli_terminal/version.py'
9 changes: 9 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
__pycache__/
*.py[cod]
*.egg-info/
build/
dist/
.pytest_cache/
.coverage
htmlcov/
.venv/
1 change: 0 additions & 1 deletion MANIFEST.in

This file was deleted.

31 changes: 30 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ hive**: the "hello world" of HiveMind clients.
The curses UI shows a split-pane conversation view. `--no-curses` streams plain
output, which is useful for scripting or SSH sessions with minimal terminal support.

![HiveMind CLI terminal](./cli_terminal.png)

## Where it fits — the satellite spectrum

| Client | Local processing | Remote processing |
Expand All @@ -27,6 +29,18 @@ engine. Every other satellite adds layers on top of this foundation.
pip install HiveMind-cli
```

From source:

```bash
git clone https://github.com/JarbasHiveMind/HiveMind-cli
cd HiveMind-cli
pip install -e .
```

HiveMind CLI tracks the **HiveMind bus-client 2.x** stack (`ovos-bus-client>=2.0`).
`pyproject.toml` is the single source of truth for dependencies — there is no
`requirements.txt`.

## Quickstart

**1. Pair** — issue credentials on the server:
Expand Down Expand Up @@ -88,7 +102,22 @@ scripting.

## Docs

Full documentation lives in [`docs/`](docs/index.md).
Full documentation lives in [`docs/`](docs/index.md). Contributors should read
[`docs/development.md`](docs/development.md) for the dependency stack and how to run
the end-to-end test suite.

## Testing

The end-to-end suite boots a real `hivemind-core` master in-process (via
[hivescope](https://github.com/JarbasHiveMind/hivescope)) and drives the real
terminal client over a real bus — only stdin/stdout is mocked:

```bash
pip install -e ".[e2e]"
pytest tests/
```

See [`docs/development.md`](docs/development.md) for details.

## License

Expand Down
125 changes: 125 additions & 0 deletions docs/development.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
# Development & Testing

This page covers building HiveMind CLI from source, the dependency stack, and
running the end-to-end test suite.

---

## Install from source

```bash
git clone https://github.com/JarbasHiveMind/HiveMind-cli
cd HiveMind-cli
pip install -e .
```

`pyproject.toml` is the single source of truth for packaging — there is no
`requirements.txt`, `setup.py`, or `setup.cfg`. Runtime dependencies live in
`[project.dependencies]`; test dependencies live in the `[project.optional-dependencies]`
extras described below.

---

## Dependency stack — HiveMind bus 2.x

HiveMind CLI tracks the **HiveMind bus-client 2.x** stack. The pinned floors are
prereleases, declared as minimum versions so a normal resolver picks them up with
no `--pre` flag:

| Dependency | Floor | Role |
|---|---|---|
| `hivemind-bus-client` | `>=0.9.2a1` | WebSocket client + HiveMessage protocol |
| `hivemind-presence` | `>=0.0.2a2` | UDP local-network node discovery |
| `ovos-bus-client` | `>=2.0.0a3` | OVOS `Message` type and session model (2.x) |
| `ovos-spec-tools` | `>=0.8.0a1` | Shared OVOS spec primitives |

> The `ovos-bus-client>=2.0.0a3` floor is required: stable `1.5.0` bundled an older
> HiveMind protocol that collides with `hivemind-bus-client`. Staying on the 2.x
> line avoids that collision.

---

## Test extras

| Extra | Installs | Use |
|---|---|---|
| `[e2e]` | `pytest`, `hivescope>=0.5.2a1`, `hivemind-core>=4.6.2a1`, the HiveMind policy plugins | Full end-to-end suite (real master + real client) |
| `[test]` | alias for `[e2e]` | Back-compat name |
| `[license]` | `pytest`, `lichecker` | Local license-compliance checking (CI uses the shared `license-check` workflow) |

```bash
pip install -e ".[e2e]"
```

---

## Running the tests

The suite lives in a single `tests/` directory:

```
tests/
└── e2e/
├── conftest.py # cli_harness fixture: real master + real client
├── test_cli_client.py # the terminal client driven over a real bus
├── test_acl.py # ACL policy admission
└── test_bridge1_conformance.py # OVOS-BRIDGE-1 / SESSION-1 conformance
```

Run everything:

```bash
pytest tests/
```

Run only the terminal-client tests:

```bash
pytest tests/e2e/test_cli_client.py
```

---

## How the end-to-end tests work

The e2e tests are **real**, not mocked transports:

1. [hivescope](https://github.com/JarbasHiveMind/hivescope) boots a real
`hivemind-core` master **in-process** over a loopback WebSocket server
(`ws://127.0.0.1:<random-port>/`).
2. A credential is pre-registered in the master's client database.
3. The real `JarbasCliTerminal` connects to that loopback URL through a real
`HiveMessageBusClient`, completing the full handshake.
4. The test drives the terminal:
- **stdin is mocked** — instead of a blocking `input()` call, the test calls the
same `say()` path the run loop uses per typed line.
- **stdout is mocked** — `terminal.speak` is replaced with a list `.append`, so
the test asserts on exactly what the user would have seen rendered, with no TTY.
5. Assertions confirm that a typed utterance reaches the hub's OVOS agent bus, and
that a `speak` emitted by the hub is rendered back at the terminal.

There is no network beyond the localhost loopback socket, and no `importorskip` /
`skipif` guards — the `[e2e]` extra installs the entire stack, so every test runs
for real on every CI run.

---

## Continuous integration

CI is wired entirely to the shared
[OpenVoiceOS/gh-automations](https://github.com/OpenVoiceOS/gh-automations) reusable
workflows (referenced `@dev`):

| Workflow | What it does |
|---|---|
| `build_tests` | Builds the sdist/wheel and runs `pytest tests/` with the `[e2e]` extra across Python 3.10–3.13 |
| `coverage` | Coverage report for `hivemind_cli_terminal` |
| `lint` | `ruff check` |
| `license_tests` | License compliance (`license-check`) |
| `pip_audit` | CVE scan of the dependency tree |
| `release_preview` | Predicts the next version from PR labels |
| `repo_health` | Checks required files are present |
| `release_workflow` / `publish_stable` | Alpha release on merge to `dev`, stable on merge to `master` |

Versions bump automatically from conventional-commit prefixes — never hand-edit
`hivemind_cli_terminal/version.py`.
1 change: 1 addition & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ works.
| [Configuration](configuration.md) | All users | Every CLI flag, wss vs ws, ports, self-signed certs, scripting |
| [Architecture](architecture.md) | Developers | Wire protocol, HiveMessage anatomy, session identity, auth |
| [Usage](usage.md) | All users | Practical recipes: skill testing, debugging, SSH, scripting, accessibility |
| [Development & Testing](development.md) | Developers | Install from source, the bus-client 2.x stack, running the e2e suite, CI |
| [Troubleshooting](troubleshooting.md) | All users | Connection errors, SSL, auth failures, curses rendering issues |

## Quick reference
Expand Down
2 changes: 1 addition & 1 deletion hivemind_cli_terminal/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ def main():
self_signed=args.self_signed)
scanner.stop()
connect_to_hivemind(curses=not args.no_curses, bus=bus)
except:
except Exception:
print("failed to connect!")
exit(2)
elif not args.host.startswith("ws"):
Expand Down
31 changes: 28 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,36 @@ readme = "README.md"
authors = [{ name = "jarbasAI", email = "jarbasai@mailfence.com" }]
license = { text = "Apache-2.0" }
requires-python = ">=3.10"
dynamic = ["version", "dependencies"]
dynamic = ["version"]
dependencies = [
# HiveMind bus 2.x stack — prerelease floor pins (resolved with no --pre)
"hivemind-bus-client>=0.9.2a1",
"hivemind-presence>=0.0.2a2",
"ovos-bus-client>=2.0.0a3",
"ovos-spec-tools>=0.8.0a1",
]

[project.optional-dependencies]
test = ["pytest", "hivescope==0.3.0a3"]
# End-to-end test stack: hivescope boots a real hivemind-core master in-process
# (loopback WebSocket) and drives the real CLI client over a real bus client.
# Prerelease floor pins keep the whole graph on the bus-client 2.x stack with no
# --pre flag required.
e2e = [
"pytest",
"hivescope>=0.5.2a1",
"hivemind-core>=4.6.2a1",
"hivemind-plugin-manager>=0.6.0a1",
"hivemind-ovos-agent-plugin>=0.3.0a1",
]
# License-compliance test deps (license_tests.py).
license = [
"pytest",
"lichecker",
]
# Back-compat alias: `pip install -e .[test]` == the e2e stack.
test = [
"HiveMind-cli[e2e]",
]

[project.urls]
Homepage = "https://github.com/JarbasHiveMind/HiveMind-cli"
Expand All @@ -26,4 +52,3 @@ include-package-data = true

[tool.setuptools.dynamic]
version = { attr = "hivemind_cli_terminal.version.__version__" }
dependencies = { file = ["requirements.txt"] }
33 changes: 0 additions & 33 deletions readme.md

This file was deleted.

Binary file removed remote_cli.png
Binary file not shown.
4 changes: 0 additions & 4 deletions requirements.txt

This file was deleted.

Loading
Loading