Skip to content

Add blueye bundle-model CLI for creating CV model packages - #219

Merged
jp-pino merged 21 commits into
masterfrom
jp-pino/bundle-model-cli
Aug 10, 2026
Merged

Add blueye bundle-model CLI for creating CV model packages#219
jp-pino merged 21 commits into
masterfrom
jp-pino/bundle-model-cli

Conversation

@jp-pino

@jp-pino jp-pino commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds the SDK's first console script: a blueye umbrella command whose bundle-model subcommand turns an exported ONNX model into a BlueyeCV-ready model package — a zip with model.onnx and an auto-generated model_meta.json at its root, ready to unzip onto the drone.

pip install "blueye.sdk[cli]"
blueye bundle-model yolov8n.onnx

What it does

  • Validates and introspects the ONNX file (graph shapes, embedded Ultralytics metadata, external weight files) and renders a summary panel. Clearly unsupported models (image classifiers, float16 inputs, non-image inputs) are rejected with an explanation of what BlueyeCV expects.
  • Auto-generates model_meta.json: infers the decoder output_format from the output tensor shapes (all 8 detection formats: yolov2_grid, yolov5/v8 flat, v8-seg, e2e, e2e-seg, ssd_multi, detr) and detects single-object trackers from the input structure (2 image inputs → ostrack, 3 → mixformerv2, template/search sizes from the dims). Class labels and input size come from embedded Ultralytics metadata when present. Per-format preprocessing defaults match the reference packages (ImageNet mean/std for DETR/SOT, raw pixels for YOLOv2/SSD).
  • Interactive, animated UI (rich + questionary): spinners for load/analyze stages, arrow-key selects with type-ahead, path autocompletion, byte-level progress while zipping. Anything inferable is pre-filled; low-confidence inferences are confirmed rather than assumed.
  • Runtime config with DLA guidance: an op-histogram analysis of the network recommends the Jetson DLA cores for convolution-style models (frees the GPU) and explains why not for NMS-in-graph/transformer models — the user can always pick any device. Rate defaults to unlimited; packages default to runtime.enabled: true (--no-runtime-enabled to opt out).
  • Scriptable: every prompt maps to a flag, --yes accepts all inferred defaults, --dry-run prints the JSON without writing.
  • Friendly dependency handling: the lightweight interactive-UI deps (rich, questionary) are core dependencies; only the heavyweight onnx package lives in the optional blueye.sdk[cli] extra, needed by bundle-model. A stdlib-only gate detects the missing extra and prints per-platform install guidance (uv vs pip, shell quoting for zsh/PowerShell, Python-version wheel hints) instead of an ImportError.

Structure

New blueye/sdk/cli/ subpackage with testable seams: introspect.py (only module importing onnx), heuristics.py (pure inference logic), meta.py (spec-compliant JSON build + validation), bundle.py (streamed zip, atomic rename), prompts.py (Prompter protocol: questionary vs non-interactive), ui.py, main.py (argparse umbrella + dependency gate). Nothing is imported from blueye/sdk/__init__.py, so the SDK still imports without the extra; the blueye/ PEP 420 namespace layout is untouched.

Testing

  • 89 new unit tests: per-format shape heuristics, Ultralytics metadata parsing, DLA fitness, unsupported-model rejection, introspection on synthetic onnx.helper models (incl. external-data and dynamic dims), meta validation per spec rule, zip content/atomicity, prompt seams, and main() end-to-end. Full suite green apart from the pre-existing connected_to_drone hardware tests.
  • Smoke-tested against real BlueyeCV models: YOLOv8n (format/classes/labels/size all inferred from metadata), TinyYOLOv2 (anchors flow), OSTrack (SOT flow) — generated JSON matches the checked-in reference packages. A generated bundle was unzipped and loaded by be-cv, which detected dog (47.0%) on the test image.
  • Dependency gate verified in a clean venv without the extra (guidance text, exit 2).

Docs

New "Bundling CV models" page + mkdocs nav and blueye.sdk.cli reference entries.

🤖 Generated with Claude Code

jp-pino and others added 2 commits July 8, 2026 14:33
Adds the SDK's first console script: a `blueye` umbrella command whose
`bundle-model` subcommand turns an exported ONNX model into a
BlueyeCV-ready package zip (model.onnx + auto-generated model_meta.json
at the zip root).

- Introspects the ONNX graph and embedded Ultralytics metadata to infer
  the decoder format (all 8 detection formats plus OSTrack/MixFormerV2
  single-object trackers), class count, labels, and input size; clearly
  unsupported models (classifiers, fp16 inputs, non-image inputs) are
  rejected with an explanation.
- Interactive rich/questionary UI: model summary and inference panels,
  spinners, byte-level progress while zipping, prompts with
  autocompletion for everything that cannot be inferred. Every prompt
  can be pre-answered by a flag, and --yes/--dry-run enable scripting.
- Runtime configuration prompts include a DLA-fitness analysis of the
  network (op-histogram heuristic) that recommends the Jetson DLA cores
  for convolution-style models and explains why not for
  NMS-in-graph/transformer models; the rate prompt defaults to
  unlimited.
- Dependencies live in a new optional extra `blueye.sdk[cli]`; a
  stdlib-only gate prints per-platform install guidance (uv vs pip,
  shell quoting, Python-version wheel hints) instead of an ImportError
  when the extra is missing.
- Generated metadata is validated against the BlueyeCV model-meta spec
  and matches the reference packages byte-for-semantics; smoke-tested by
  loading a generated bundle with be-cv.
- 88 unit tests (heuristics, introspection, meta building/validation,
  zip writing, prompt seams, end-to-end main()) plus a docs page and
  mkdocs nav/reference entries.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The runtime.enabled confirm now defaults to true (and --yes runs write
enabled: true), so a bundled model runs on the drone out of the box.
--runtime-enabled becomes a --runtime-enabled/--no-runtime-enabled pair
for explicit control in scripted runs.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@codecov

codecov Bot commented Jul 8, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 90.74713% with 161 lines in your changes missing coverage. Please review.
✅ Project coverage is 84.34%. Comparing base (d5ab7a4) to head (2a37bc6).

Files with missing lines Patch % Lines
blueye/sdk/cli/commands/bundle_model/command.py 74.07% 70 Missing ⚠️
blueye/sdk/cli/commands/models/command.py 86.92% 20 Missing ⚠️
blueye/sdk/cli/commands/tools/command.py 90.57% 13 Missing ⚠️
blueye/sdk/cli/prompts.py 86.48% 10 Missing ⚠️
blueye/sdk/cli/commands/bundle_model/meta.py 93.61% 9 Missing ⚠️
blueye/sdk/cli/commands/bundle_model/introspect.py 90.00% 8 Missing ⚠️
blueye/sdk/cli/commands/logs/command.py 95.95% 7 Missing ⚠️
blueye/sdk/cli/commands/bundle_model/heuristics.py 97.00% 6 Missing ⚠️
blueye/sdk/cli/main.py 86.36% 6 Missing ⚠️
blueye/sdk/cli/external/metadata.py 94.73% 4 Missing ⚠️
... and 4 more
Additional details and impacted files
@@            Coverage Diff             @@
##           master     #219      +/-   ##
==========================================
+ Coverage   77.88%   84.34%   +6.46%     
==========================================
  Files          11       36      +25     
  Lines        1723     3463    +1740     
==========================================
+ Hits         1342     2921    +1579     
- Misses        381      542     +161     
Flag Coverage Δ
macos-latest_3.10 84.17% <90.40%> (+6.28%) ⬆️
macos-latest_3.11 84.08% <90.22%> (+6.20%) ⬆️
macos-latest_3.12 84.08% <90.22%> (+6.20%) ⬆️
macos-latest_3.13 84.08% <90.22%> (+6.20%) ⬆️
macos-latest_3.14 84.20% <90.45%> (+6.31%) ⬆️
ubuntu-latest_3.10 84.17% <90.40%> (+6.28%) ⬆️
ubuntu-latest_3.11 84.08% <90.22%> (+6.20%) ⬆️
ubuntu-latest_3.12 84.08% <90.22%> (+6.20%) ⬆️
ubuntu-latest_3.13 84.08% <90.22%> (+6.20%) ⬆️
ubuntu-latest_3.14 84.20% <90.45%> (+6.31%) ⬆️
windows-latest_3.10 84.14% <90.34%> (+6.25%) ⬆️
windows-latest_3.11 84.06% <90.17%> (+6.17%) ⬆️
windows-latest_3.12 84.06% <90.17%> (+6.17%) ⬆️
windows-latest_3.13 84.06% <90.17%> (+6.17%) ⬆️
windows-latest_3.14 84.17% <90.40%> (+6.28%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@jp-pino

jp-pino commented Jul 8, 2026

Copy link
Copy Markdown
Contributor Author
Screen.Recording.2026-07-08.at.3.01.02.PM.mov

@jp-pino
jp-pino requested review from Copilot and sindrehan and removed request for Copilot July 8, 2026 13:28
@jp-pino
jp-pino marked this pull request as draft July 8, 2026 13:29
@jp-pino jp-pino self-assigned this Jul 8, 2026
@jp-pino jp-pino added enhancement New feature or request blueye-cv labels Jul 8, 2026
@jp-pino
jp-pino requested a review from Copilot July 8, 2026 13:30
@jp-pino jp-pino added this to the Blunux v5.1 milestone Jul 8, 2026
CI fails on windows-latest + Python 3.14 (on master too, verified with a
canary run of master HEAD): pyzmq 26.4.0 has no cp314 Windows wheel, so
uv compiles it from source, and the current runner image breaks that
build (FindVcvars cannot locate the MSVC scripts). pyzmq 27.x ships a
cp312-abi3 Windows wheel that covers 3.12+, so widening the constraint
to >=26,<28 and locking 27.1.0 removes the source build entirely. The
SDK only uses basic zmq APIs (Context, PUB/SUB, Poller), which are
unchanged in 27.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces the SDK’s first end-user CLI entrypoint (blueye) and adds a bundle-model subcommand to validate/introspect ONNX exports and produce a BlueyeCV-ready model package (zip with model.onnx + generated model_meta.json). It also adds docs + mkdocs nav/reference entries and a fairly comprehensive new unit test suite around the CLI modules.

Changes:

  • Add a blueye console script and a new blueye.sdk.cli subpackage implementing bundle-model (dependency gate, prompting, ONNX introspection, heuristics, metadata generation, bundle writer, rich UI).
  • Add optional dependency extra blueye.sdk[cli] (onnx/rich/questionary) plus dev-group deps and lockfile updates.
  • Add docs (“Bundling CV models”) + API reference entries, and add unit tests covering the CLI flows.

Reviewed changes

Copilot reviewed 20 out of 21 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
uv.lock Adds CLI extra deps and updates lock resolution markers/entries.
pyproject.toml Registers blueye console script and adds [cli] optional dependencies + dev-group repeats.
mkdocs.yml Adds “Bundling CV models” page and blueye.sdk.cli reference entry to nav.
docs/reference/blueye/sdk/cli.md Adds mkdocstrings reference stubs for CLI modules.
docs/bundling-cv-models.md New user documentation for installing/using blueye bundle-model.
blueye/sdk/cli/init.py Exposes main for console script while keeping imports stdlib-safe.
blueye/sdk/cli/main.py Umbrella CLI parser + dependency gate + lazy subcommand import/dispatch.
blueye/sdk/cli/deps.py Stdlib-only optional-dependency detection and install guidance output.
blueye/sdk/cli/bundle_model.py bundle-model argparse definitions + orchestration of introspection/inference/prompts/bundling.
blueye/sdk/cli/bundle.py Stdlib-only streaming zip writer + atomic .part rename behavior.
blueye/sdk/cli/introspect.py ONNX-only module for loading model IO shapes/metadata/external-data refs/op histogram.
blueye/sdk/cli/heuristics.py Pure inference logic for output format detection + DLA fitness heuristic.
blueye/sdk/cli/meta.py Stdlib-only model_meta.json builder + validation rules.
blueye/sdk/cli/prompts.py Prompt seam (questionary vs non-interactive) and abort handling.
blueye/sdk/cli/ui.py Rich UI helpers (panels/progress/meta preview).
tests/test_cli_prompts.py Tests prompting behavior + dependency guidance output.
tests/test_cli_meta.py Tests model_meta construction defaults and validation rules.
tests/test_cli_main.py End-to-end-ish CLI tests (help, dep gate, bundle flow, flags, dry-run, etc.).
tests/test_cli_introspect.py Tests ONNX model info extraction/checking/external-data detection.
tests/test_cli_heuristics.py Tests output-shape heuristics, metadata parsing, DLA fitness decisions.
tests/test_cli_bundle.py Tests zip contents/atomicity/progress reporting/external-data validation.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread blueye/sdk/cli/commands/bundle_model/command.py
Comment thread blueye/sdk/cli/commands/bundle_model/command.py
Comment thread blueye/sdk/cli/commands/bundle_model/command.py Outdated
Comment thread blueye/sdk/cli/commands/bundle_model/command.py
Comment thread blueye/sdk/cli/commands/bundle_model/bundle.py
Comment thread blueye/sdk/cli/deps.py Outdated
Comment thread blueye/sdk/cli/commands/bundle_model/meta.py Outdated
jp-pino and others added 2 commits July 9, 2026 11:12
Restructures the `blueye` CLI so commands are pluggable rather than
hard-coded, and adds a discovery mechanism for user-provided tools.

First-party commands: each lives in its own package under
blueye/sdk/cli/commands/<name>/ exposing a CommandSpec (name, help,
required optional deps, add_parser, run); main.py iterates the registry
and gates dependencies per command instead of globally. CliError moves
to cli/errors.py (removing the prompts->main cycle hazard);
bundle-model's introspect/heuristics/meta/bundle modules move into its
command package. The CommandSpec contract is designed to double as the
payload for future pip-installable plugins (blueye.cli entry-point
group, documented as future work).

Third-party tools: single-file Python scripts with PEP 723 inline
metadata extended by a [tool.blueye] table (name, description, optional
min-sdk-version). Discovery scans a per-user tools directory
(BLUEYE_CLI_TOOLS_DIR, defaulting per OS), parses only the metadata
(never executes code to list), shows tools in `blueye --help`, and
dispatches `blueye <tool> args...` as a subprocess with verbatim args
and propagated exit code — via `uv run` when the script declares PEP
723 dependencies and uv is available (isolated deps for free). Tool
names are intercepted before argparse because a REMAINDER positional
cannot forward leading-dash arguments. Built-ins always win name
collisions. TOML parsing tiers tomllib -> tomli (added to the [cli]
extra for 3.10) -> a minimal regex fallback so a stdlib-only 3.10
install can still discover tools.

New `blueye tools` built-in (runs with zero extras — it is the
bootstrap surface): list, validate (per-check report), install
(validate + copy as <name>.py, --force to replace), uninstall (by name,
incl. hand-copied files), and dir.

Verified in a no-extras venv: --help with the tools epilog, tools list,
tool dispatch with leading-dash args, and the bundle-model dependency
gate (exit 2) all work stdlib-only.

Docs: new "Extending the blueye CLI" page (third-party authoring guide
with a worked example, per-OS directory table, first-party command
recipe, future entry-points note) + mkdocs nav and updated reference
page. +59 tests (metadata parser incl. forced-fallback path, directory
resolution per platform, discovery/shadowing, subprocess dispatch and
uv preference, tools subcommands, per-command gating), 369 total.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
All seven review findings, verified and fixed:

- _parse_anchors and the --runtime-hz flag/custom-rate prompt let
  ValueError escape as a traceback for non-numeric input; they now
  raise CliError with a message naming the offending value.
- bundle_size() ran before write_bundle()'s external-data validation,
  so a missing weight file surfaced as an uncaught FileNotFoundError;
  the checks moved into a shared _validate_external_files() that both
  entry points call.
- build_meta() defaulted empty labels to ["tracked"] for every kind of
  package — a 1-class detection model without labels would validate
  with a nonsense label. Detection packages now keep an empty list so
  validation fails with the direct message; only SOT packages default.
- Overwrite semantics: non-interactive runs (--yes or no TTY) now
  require an explicit --force to overwrite an existing zip (erroring
  with the flag named); the interactive confirm defaults to No.
- The install guidance on Windows suggested single quotes but printed a
  double-quoted uv command; the quoting now matches the platform.

+7 regression tests (376 total).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@jp-pino

jp-pino commented Jul 9, 2026

Copy link
Copy Markdown
Contributor Author

@sindrehan an idea on how to also allow for third party tools to run on the blueye cli:

Screen.Recording.2026-07-09.at.12.41.28.PM.mov

We're using PEP 723 inline metadata do declare the name and description that is shown in the cli. And it uses uv to execute if available to pull in the requested dependencies.

# /// script
# requires-python = ">=3.10"
# dependencies = ["pandas"]
#
# [tool.blueye]
# name = "export-logs"
# description = "Export dive logs to CSV"
# min-sdk-version = "2.7.0"
# ///
import sys

import pandas as pd


def main() -> int:
    print(f"exporting with args: {sys.argv[1:]}")

    # Print a dummy Pandas table
    df = pd.DataFrame(
        {
            "Dive Number": [1, 2, 3],
            "Date": ["2024-01-01", "2024-01-02", "2024-01-03"],
            "Depth (m)": [30, 25, 20],
            "Duration (min)": [45, 50, 40],
        }
    )
    print(df)
    return 0


if __name__ == "__main__":
    sys.exit(main())

Comment thread docs/extending-the-cli.md Outdated
Comment thread docs/bundling-cv-models.md Outdated
Comment thread pyproject.toml
jp-pino and others added 2 commits July 10, 2026 12:21
…e models`

Wraps the drone's CV-model management HTTP API (http://<ip>/api/cv-models,
served by the onboard backend) in three layers:

- SDK: new blueye/sdk/cv_models.py with drone.cv_models — list, upload
  (multipart 'file' field), delete, download, set_enabled, set_device,
  set_hz, warmup, rescan, returning CvModel dataclasses. Non-2xx
  responses raise HTTPError with the drone's text/plain reason included
  (raise_for_status would discard it). Plain HTTP, independent of the
  control connection: works on Drone(auto_connect=False) and takes no
  control of the drone.
- bundle-model: new --push and --drone-ip (default 192.168.1.101)
  flags; interactive runs offer the upload after the zip is written
  (default No). An unreachable drone or a server rejection fails
  gracefully with the bundle kept on disk and the path in the message;
  exit code 1 so scripts notice.
- New `blueye models` built-in (requires rich+questionary, no onnx —
  the per-command gate at work): list (table incl. runtime
  device/hz/enabled), enable/disable, set-device, set-hz (choices match
  the server's accepted values), warmup (600s, engine-build note),
  delete (confirm or --force), upload, download, rescan — and an
  interactive management loop when invoked bare on a terminal
  (pick model -> toggle/device/rate/warmup/delete, refreshed each
  round). Docs and help note that `enabled` is the autolaunch
  configuration; the API has no live running status.

Docs: the bundling page's deploy section now covers --push,
`blueye models`, the drone.cv_models snippet, and the Blunux Web App
(Computer Vision tab) as the manual alternative; new
blueye.sdk.cv_models reference page + nav entry.

+42 tests (SDK client incl. multipart/error-body assertions, models
subcommands, interactive loop via the prompter seam, push flow incl.
graceful failure), 418 total.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Surfaces the documented drone.logs workflow as a CLI built-in:

- `blueye logs list` — table of the drone's binary logs (name, time,
  max depth, size, dive flag).
- `blueye logs download [NAME ...] [--latest N | --all] [-o DIR]` —
  downloads .bez files; unknown names error listing what is available.
- Bare `blueye logs` on a terminal opens an interactive picker: the
  table plus a checkbox multi-select and a destination prompt. The
  Prompter seam gains a checkbox method (questionary.checkbox
  interactively; a CliError naming the flags non-interactively).
- Connects to the drone as an observer (connect_as_observer=True), so
  no control is taken and no SDK changes were needed; an unreachable
  drone fails with the friendly message and exit 1. The connection is
  released on exit.
- The --drone-ip/--timeout parent parser and the failure-translation
  helper are lifted into commands/_common.py, now shared with the
  models command.

Verified against the bench drone (list + `--latest 1` downloaded a
real 2.5 MiB .bez) and an unreachable address. +14 tests (432 total);
docs gain a "From the command line" section in the logs guide.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
jp-pino and others added 7 commits July 10, 2026 13:04
`blueye logs download ... --mcap` converts each downloaded .bez to a
Foxglove-ready .mcap next to it; the interactive picker offers the same
conversion after selecting logs. The converter
(commands/logs/mcap.py) is adapted from
examples/foxglove_bez_to_mcap.py: a first LogStream pass anchors the
dive start time (last record's wall clock minus its monotonic delta, so
logs where the clock was set mid-dive stay continuous), a second pass
writes every protobuf message via mcap_protobuf.writer.

mcap-protobuf-support joins the [cli] extra (and dev group); the --mcap
path gates on it at runtime with the standard install guidance, so the
rest of the logs command works without it.

Verified against the bench drone: `blueye logs download --latest 1
--mcap` produced a valid 8.5 MB .mcap (217k messages, correct MCAP
magic) from a real dive log. +6 tests incl. a real protobuf-built .bez
round trip (438 total); the Foxglove doc gains a one-step
download-and-convert tip.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ndpoint

Applies sindrehan's review suggestions:

- The CLI is no longer optional: rich, questionary, and the tomli
  backport move into the core dependencies, so `blueye` (including the
  models and tools commands) works after a plain `pip install
  blueye.sdk`. The `[cli]` extra now carries only the heavyweight onnx
  dependency needed by bundle-model, which keeps gating on it with the
  existing install guidance (verified in a fresh no-extra venv).
- CLI documentation consolidated into a single docs/cli.md with one
  section per command (bundle-model, models, third-party tools),
  replacing bundling-cv-models.md and extending-the-cli.md in the nav.
  The "Future work: pip-installable plugins" section is dropped from
  the docs (the design note lives in the blueye.sdk.cli.commands
  docstring); the built-in-command recipe becomes a pointer to that
  docstring.
- The deploy section now documents the raw HTTP upload endpoint
  (curl -F "file=@pkg.zip" http://192.168.1.101/api/cv-models/upload)
  alongside the Web App, for uploads without the SDK installed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Follow-up to the review changes merged from jp-pino/bundle-model-cli:

- The logs command joins the consolidated docs/cli.md as a
  "Downloading dive logs" section (incl. --mcap); the logs guide and
  the Foxglove doc keep short pointers to the CLI page.
- The quick start gains a "Try the command line interface" section
  showcasing `blueye logs download --latest 1` with links to the CLI
  page.
- With rich/questionary in the core dependencies, the logs command
  declares requires=() (the --mcap path keeps its runtime gate);
  mcap-protobuf-support stays in the [cli] extra alongside onnx.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…example

Follow-ups on the logs command:

- New `blueye logs convert <file.bez ...> [-o DIR]` converts
  already-downloaded logs to .mcap without touching the drone (dispatch
  happens before the observer connection; same runtime mcap gate).
- Interactive view redesigned: instead of printing the full table and
  then a duplicate checkbox list, it is now a single scrollable
  multi-select table (each choice is a column-aligned row under one
  header line) with type-to-filter (questionary use_search_filter),
  sorted descending alphabetically — newest logs first. An explicit
  instruction string works around questionary 2.1.1 showing <ctrl-a>
  for both toggle-all and invert (the real invert binding is
  ctrl-i/tab).
- New --dives-only / --since / --until filters shared by list,
  download, and the interactive view; list output is sorted descending
  too.
- The example converter (examples/foxglove_bez_to_mcap.py) is retired
  in favor of the first-party command: the Foxglove doc now walks
  through `blueye logs download --latest 1 --mcap` and
  `blueye logs convert`, and mcap-protobuf-support leaves the
  [examples] extra (its only consumer).

Verified against the bench drone: filtered+sorted list, download, and a
local `blueye logs convert` producing a valid .mcap (1.19M messages).
+13 tests (451 total); docs build clean with the embed removed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
jp-pino and others added 4 commits July 10, 2026 17:15
Works around a second questionary 2.1.1 search-filter bug (user-found):
with a filter active, ctrl-a (toggle all) and ctrl-i/tab (invert)
operated on every choice — selecting files not even in view — because
questionary's handlers iterate ic.choices instead of
ic.filtered_choices. The prompter now replaces both key bindings on the
constructed prompt with versions scoped to the visible rows: toggle-all
selects/deselects only what the filter shows, invert flips only the
visible rows, and selections hidden by the filter are left untouched.

The selection logic lives in pure helpers (_toggle_all_visible,
_invert_visible) with unit tests, plus an integration test asserting the
rebinding attaches to a real questionary prompt. +5 tests (456 total).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
prompt_toolkit raises NoConsoleScreenBufferError when questionary builds
a prompt without a console; the test now uses a pipe input and
DummyOutput app session.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Addresses the Copilot review on #220: names/--latest/--all are now
mutually exclusive instead of silently prioritized, and --latest must
be at least 1 rather than succeeding with an empty selection.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The BlueyeCV package format gains four optional informational top-level
fields in model_meta.json, so packages stay self-describing wherever
they travel (drone web UI, Blueye App, Blueye Cloud). bundle-model now
collects them: --model-version defaults to "1.0.0" (prompted after the
name), and description/author/license sit behind an optional
"package details" prompt, each answerable with a flag. build_meta emits
the fields between name and preprocessing; validate_meta type-checks
them. Non-interactive runs omit the optional fields instead of failing
on the empty prompt default.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@follesoe
follesoe requested review from Copilot and follesoe July 22, 2026 10:14

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 40 out of 41 changed files in this pull request and generated 6 comments.

Comment thread blueye/sdk/cv_models.py Outdated
Comment thread blueye/sdk/cv_models.py
Comment thread blueye/sdk/cli/ui.py
Comment thread blueye/sdk/cli/ui.py
Comment thread blueye/sdk/cli/commands/bundle_model/command.py Outdated
Comment thread pyproject.toml
follesoe and others added 3 commits July 22, 2026 12:35
- CvModels.list() now sorts by directory so the docstring matches the
  behaviour and callers get a deterministic order.
- Content-Disposition filename parsing no longer over-captures when the
  header carries additional parameters.
- ui.py docstring cross-references point at the actual
  commands.bundle_model module paths.
- The interactive device prompt only offers the four devices the drone
  exposes; cpu/coreml stay reachable via an explicit --runtime-device
  for local be-cv testing, with a printed note when chosen.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Add `blueye logs` command for listing and downloading dive logs
@jp-pino
jp-pino marked this pull request as ready for review August 10, 2026 12:12
@jp-pino
jp-pino enabled auto-merge (squash) August 10, 2026 12:13
@jp-pino
jp-pino disabled auto-merge August 10, 2026 12:13
@jp-pino
jp-pino merged commit c9fb250 into master Aug 10, 2026
18 checks passed
@jp-pino
jp-pino deleted the jp-pino/bundle-model-cli branch August 10, 2026 12:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

blueye-cv enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants