Skip to content

agcli-py: complete Phase 1 polish, Phase 2 extrinsics MVP, Phase 3 features, DX release#7

Merged
unarbos merged 8 commits into
mainfrom
orch/agcli-py/dx-release
May 29, 2026
Merged

agcli-py: complete Phase 1 polish, Phase 2 extrinsics MVP, Phase 3 features, DX release#7
unarbos merged 8 commits into
mainfrom
orch/agcli-py/dx-release

Conversation

@unarbos

@unarbos unarbos commented May 27, 2026

Copy link
Copy Markdown
Owner

Summary

Completes the agcli Python bindings roadmap on top of the merged Phase 1 base. The branch carries Phase 1 polish, Phase 2 extrinsics MVP, Phase 3 features (events / live / localnet / scaffold / admin), and the DX/release pipeline. After the audit/feature merge that landed on main while this work was in flight, this branch was force-rebased forward and fixed up so every required CI check passes.

Phase 1 polish (carry-forward in this branch):

  • Connection management (best_connection, reconnect, is_alive, invalidate_cache), block/hash queries, totals, get_balances_multi, get_all_dynamic_info, every pinned/historical _at_block/_at_hash variant.
  • Proxy / multisig / child-key reads, get_delegated, full weight commit/reveal queries, PoW helpers, fetch_portfolio.
  • agcli.Config with load/save/load_from/save_to/default_path.
  • AsyncClient mutators: set_dry_run, set_finalization_timeout, set_mortality_blocks, network getter.
  • Wallet.create_from_uri, sign_message, verify_message, coldkey_public_ss58.
  • Rich pyclass types (SubnetInfo, NeuronInfo, NeuronInfoLite, Metagraph, StakeInfo, DelegateInfo, DynamicInfo, SubnetHyperparameters, ChainIdentity, SubnetIdentity, AlphaBalance).
  • Typed error subclasses raised from map_error (NetworkError, AuthError, ValidationError, ChainError, TimeoutError, IOError).
  • agcli.SyncClient (private tokio runtime).

Rust SDK prep:

  • agcli::Client::network() accessor.
  • agcli::sdk re-export module (Client, Config, Wallet, Balance, Network, NetUid, types::chain_data, error).
  • [[bin]] required-features = ["cli"] so cargo check --no-default-features --features sdk-only works at the workspace root.

Phase 2 extrinsics MVP:

  • Transfer (transfer, transfer_all); staking (add_stake, remove_stake, *_limit, move_stake, swap_stake, swap_stake_limit, transfer_stake, unstake_all, unstake_all_alpha, recycle_alpha, burn_alpha, claim_root); weights (set_weights, commit_weights, reveal_weights); registration (register_network, burned_register, pow_register, root_register, dissolve_network); proxy (add_proxy, remove_proxy, create_pure_proxy, kill_pure_proxy, try_associate_hotkey, schedule_swap_coldkey, swap_hotkey, set_subnet_identity).
  • Per-call wait, mev, dry_run, finalization_timeout, mortality_blocks kwargs.
  • Binding-boundary validation (SS58, netuid bounds, weight vector shape, non-negative amounts), raised as agcli.ValidationError.
  • Wallet lifecycle: Wallet.session(password=...) context manager, unlock_coldkey_with_password, lock, is_coldkey_unlocked, is_hotkey_loaded.
  • python/tests/test_extrinsics_localnet.py covering transfer, stake, weights, register/dissolve, proxy add/remove behind @pytest.mark.localnet.

Phase 3 features:

  • agcli.events: async subscribe_events, subscribe_events_filtered, subscribe_blocks returning async iterators backed by tokio mpsc; EventFilter dataclass mirrors agcli::events::EventFilter.
  • agcli.live: live_dynamic, live_metagraph, live_portfolio async helpers.
  • agcli.localnet: start, stop, status, reset, logs, dev_accounts, plus LocalnetConfig, LocalnetInfo, LocalnetStatus, DevAccount pyclasses (with started_at plus a backwards-compatible uptime alias for the field rename that landed on main).
  • agcli.scaffold: load_config, async run, plus ScaffoldConfig, SubnetConfig, NeuronConfig, ScaffoldResult, SubnetResult, NeuronResult pyclasses.
  • agcli.admin: every set_* admin extrinsic from src/admin.rs, raw_admin_call, and known_params().

DX / release:

  • python/agcli/py.typed, exhaustive python/agcli/_native.pyi (including explicit admin signatures).
  • Pickle hardening (TypeError on __reduce__ / __getstate__) across every PyO3 class and Python facade; test coverage in python/tests/test_bindings.py.
  • python/SECURITY.md documenting binding-boundary guarantees and cargo audit -q findings.
  • examples/python/: connect_and_balance.py, wallet_lifecycle.py, transfer_dry_run.py, extrinsics_mvp.py, subscribe_events.py, localnet_smoke.py.
  • docs/tutorials/python-sdk.md covering install, async + sync clients, wallet lifecycle, reads, extrinsics, events, localnet, typed errors, config — code blocks sourced from examples/python/.
  • python/agcli/__about__.py with __version__; enriched python/pyproject.toml (readme, classifiers, project URLs); python/MANIFEST.in.

CI:

  • New python-clippy job (cargo clippy -p agcli-py --no-deps --features pyo3/extension-module -- -D warnings).
  • New sdk-only job (cargo check --no-default-features --features sdk-only).
  • Existing Python tests job uses pytest -m "not network and not localnet".
  • New wheels matrix ({ubuntu-latest, macos-latest} × {3.10, 3.11, 3.12}) running maturin build --release --strip with artifact upload.
  • submodules: recursive added to checkout for check, python-clippy, sdk-only, test, and coverage jobs (the events exhaustiveness test reads from the subtensor/ submodule).
  • Shared Swatinem/rust-cache@v2 target cache across jobs.

Notes:

  • Localnet-dependent tests remain gated behind @pytest.mark.localnet. CI does not run them by default; a docker-capable runner can opt in by setting AGCLI_LOCALNET_WS.
  • PyPI publishing is intentionally not automated; the wheels job uploads artifacts and the release step remains manual for now.
  • This branch was rebased forward over main after a large audit/feature merge landed there (Merge main and fix agcli-py/CI regressions); see the merge commit and follow-on fix commits for the rename + clippy fixes.

Acceptance:

  • py.typed marker shipped in wheel; _native.pyi exhaustive.
  • docs/tutorials/python-sdk.md and examples/python/* present and cross-referenced.
  • Pickling wallets / clients raises TypeError (test exercised).
  • python/SECURITY.md present with audit findings.
  • CI workflow includes python-clippy, sdk-only, and wheels matrix jobs.
  • All required CI checks green: Check & Lint, Python clippy, SDK-only check, Test, Python bindings, Wheels (ubuntu × {3.10, 3.11, 3.12}), Wheels (macos × {3.10, 3.11, 3.12}). (Coverage and Build Release are skipped on PRs by design — they only run on push to main.)
  • Branch is MERGEABLE against main.
Open in Web Open in Cursor 

cursoragent and others added 8 commits May 27, 2026 15:00
Co-authored-by: Arbos <unarbos@users.noreply.github.com>
Co-authored-by: Arbos <unarbos@users.noreply.github.com>
- events module exposes EventFilter dataclass and async iterator subscriptions
  (subscribe_events, subscribe_events_filtered, subscribe_blocks) backed by a
  tokio mpsc-driven PyEventStream that cancels on drop.
- live module wraps live_dynamic/live_metagraph/live_portfolio.
- localnet module exposes LocalnetConfig/Info/Status/DevAccount pyclasses plus
  start/stop/status/reset/logs/dev_accounts; status falls back to inactive
  when docker is missing.
- scaffold module mirrors ScaffoldConfig/SubnetConfig/NeuronConfig/result types
  with load_config and an async run thin-wrapper.
- admin module exposes every set_* helper from src/admin.rs, raw_admin_call,
  and known_params() for AdminUtils sudo calls.

Wires AsyncClient.subscribe_* through the native EventStream, registers all new
submodules under agcli._agcli, and updates _native.pyi.

Tests cover EventFilter roundtrip, dev_accounts/LocalnetConfig/status without
docker, scaffold TOML round-trip, admin known_params and exported set_*
inventory, and a live-import smoke test. Localnet/network tests stay gated
behind the existing markers.

Co-authored-by: Arbos <unarbos@users.noreply.github.com>
Co-authored-by: Arbos <unarbos@users.noreply.github.com>
Co-authored-by: Arbos <unarbos@users.noreply.github.com>
…d-fix

Co-authored-by: Arbos <unarbos@users.noreply.github.com>
Co-authored-by: Arbos <unarbos@users.noreply.github.com>
The events::tests::pretty_subtensor_variants_are_exhaustive test reads
from the subtensor/ submodule which is not initialized by default.
Add submodules: recursive to the test and coverage jobs (parity with the
check, python-clippy, and sdk-only jobs already updated).

Co-authored-by: Arbos <unarbos@users.noreply.github.com>
@cursor cursor Bot marked this pull request as ready for review May 27, 2026 18:42
unarbos pushed a commit that referenced this pull request May 29, 2026
Reconcile merge conflicts after landing agcli-py Phase 1–3, update Python
extrinsic bindings for AlphaBalance/LimitPriceRao and renamed query methods,
and keep extrinsic encoding regression tests plus CI jobs from local work.

Co-authored-by: Cursor <cursoragent@cursor.com>
@unarbos unarbos merged commit 40a77c8 into main May 29, 2026
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants