Commit Graph

16689 Commits

Author SHA1 Message Date
Cœur
0cd11628a4 Fix: "attempt to insert nil object from objects[0]" (#8035) 2025-12-31 22:02:55 -06:00
github-actions[bot]
5ce17df2e5 chore: update copyright years (#8039)
* chore: update copyright year in COPYING

* chore: update copyright year in user-facing files (1)

* chore: update copyright year in user-facing files (2)

* chore: update copyright year in cmake/transmission.rc.in

---------

Co-authored-by: github-actions <github-actions@github.com>
2025-12-31 21:59:44 -06:00
Yat Ho
2491ea10cb docs: deprecate session_get.tcp_enabled (#8036)
* docs: deprecate `session_get.tcp_enabled`

* docs: fix typo
2025-12-31 09:00:00 -06:00
namoen0301
398fe70b02 GHA CI: Add support for Windows arm64 (#7758) 2025-12-31 06:25:27 +00:00
Yat Ho
be80b149b1 fix: torrent dates were not bumped in some cases (#8029)
* refactor: new `tr_torrent::bump_date_edited()`

* fix: `mark_edited()` should also bump `date_changed_`

* fix: torrent should be marked edited when setting labels

* fix: torrent should be marked change when setting file priority
2025-12-29 09:32:37 -06:00
Yat Ho
4542c1bf8a docs(rpc): add missing changelog for recent commits (#8031) 2025-12-29 06:19:41 -06:00
Yat Ho
332c58995c fix(remote): attach id to methods that can return errors (#8028)
* fix(remote): attach id to `session_set` requests

* fix(remote): attach id to `torrent_set` requests

* fix(remote): attach id to `torrent_set_location` requests

* fix(remote): attach id to `torrent_rename_path` requests
2025-12-28 23:08:17 -06:00
Yat Ho
c9c5d780a0 feat(remote): console message for HTTP 204 response (#8027) 2025-12-28 22:43:59 -06:00
Charles Kerr
109ee8e6ff Revert "fix: cache the value of tr_peerMgrGetDesiredAvailable() (#7961)" (#8026)
This reverts commit c0a8f3bbe6.
2025-12-28 18:43:04 -06:00
Elek, David
6392f0c306 fix: opening torrent opens in an new tr instance (#7629) (#7841) 2025-12-28 15:50:45 -06:00
Elek, David
8beb761a3f fix: increase the width of up/down ratio display to 8 (#8019) 2025-12-28 09:52:55 -06:00
Charles Kerr
91f39c56a8 refactor: register converters in tr_lib_init() (#8023) 2025-12-28 09:36:49 -06:00
Yat Ho
80a0e4d048 feat(remote): print blocklist size after update (#8021) 2025-12-28 09:36:40 -06:00
Yat Ho
1ff6e75c61 chore: deprecate non-semver rpc version scheme (#8022) 2025-12-28 09:36:30 -06:00
Evgeny Kulikov
116412b27c Fix. Mac GUI. Incorrect filter selected when hiding the Filter Bar and then showing it again (#7844)
* Set filter to "All" when hiding the filter bar

Otherwise the filters will reset but the tab, for example "Downloading" will still be selected
when the filter is shown again. We want to keep the tabs synchronized with filters state.

* Remove unused BOOL parameter (the method is always called with YES)

---------

Co-authored-by: beyondcompute <beyondcompute@users.noreply.github.com>
2025-12-26 12:01:22 -06:00
Yat Ho
d0bcda1623 fix: discard any non-int tag when converting to tr4 (#8017)
Co-authored-by: reardonia <2925104+reardonia@users.noreply.github.com>
2025-12-26 11:59:17 -06:00
Yat Ho
ccba9ecd9d fix: rpcimpl array size (#8014) 2025-12-26 11:36:38 -06:00
Yat Ho
6a4c1bae3f fix: dedupe Access-Control-Expose-Headers header (#8018)
Co-authored-by: reardonia <2925104+reardonia@users.noreply.github.com>
2025-12-26 10:28:29 -06:00
Yat Ho
9794e41ae0 fix: detect is_torrent in rpc response too (#8015) 2025-12-26 08:39:18 -06:00
Charles Kerr
291482f82c refactor: remove now-unused api_compat::get_export_settings_style() (#8012) 2025-12-26 01:20:34 -06:00
Charles Kerr
64f9c512da refactor: remove tr_quark_convert() (#8009)
* refactor: remove tr_quark_convert() call from makeState()

* refactor: remove tr_quark_convert() call from tr_variant::merge()

* refactor: remove tr_quark_convert()
2025-12-25 14:53:51 -06:00
Charles Kerr
ae44cacc31 chore: silence MSVC C4702 unreachable code warning (#8010) 2025-12-25 14:53:37 -06:00
Charles Kerr
c0a8f3bbe6 fix: cache the value of tr_peerMgrGetDesiredAvailable() (#7961)
* perf: cache the value of tr_peerMgrGetDesiredAvailable()

* fix: invalidate swarm piece availability when a peer connection closes
2025-12-25 14:32:40 -06:00
Charles Kerr
850d2a277f refactor: use snake_case for action names in GTK client (#8008)
* refactor use snake_case for action names in GTK app

* refactor: remove tr_quark_convert() use
2025-12-25 14:01:23 -06:00
Yat Ho
1859201e01 refactor: rename cache_size_mb to cache_size_mib (#7971) 2025-12-25 14:00:07 -06:00
Cœur
3da2a2543e refactor: removing menu icons on older Macs (#7994) 2025-12-25 13:59:11 -06:00
Yat Ho
a1184061a0 feat: torrent_get.wanted is now boolean (#7997) 2025-12-25 11:42:43 -06:00
Yat Ho
11ead87f8d refactor: rename peer_socket_tos to peer_socket_diffserv (#8004) 2025-12-25 11:05:50 -06:00
Charles Kerr
5602bcc74b refactor: use serializer in tr_stats::save(), tr_stats::load() (#7956) 2025-12-24 18:25:16 -06:00
Elek, David
df19af2f17 fix(qt): assertion fails on debug Windows Qt build (#8000)
Thanks!
2025-12-24 17:49:04 -06:00
Charles Kerr
c6c4a8144b refactor: remove unused tr_variant initializer-list methods (#8002) 2025-12-24 15:18:13 -06:00
Charles Kerr
e1a403c9ca refactor: mark more keys as APICOMPAT (#8001) 2025-12-24 15:18:03 -06:00
Yat Ho
62c8edc039 refactor: use api_compat for rpc (#7995)
* fix: legacy RPC tag should ignore non-integers

* refactor: delegate legacy RPC callback to api-compat

* refactor: move `TR_KEY_alt_speed_down_kebab` handling

* refactor: move `TR_KEY_alt_speed_enabled_kebab` handling

* refactor: move `TR_KEY_alt_speed_time_begin_kebab` handling

* refactor: move `TR_KEY_alt_speed_time_day_kebab` handling

* refactor: move `TR_KEY_alt_speed_time_enabled_kebab` handling

* refactor: move `TR_KEY_alt_speed_time_end_kebab` handling

* refactor: move `TR_KEY_alt_speed_up_kebab` handling

* refactor: move `TR_KEY_anti_brute_force_enabled_kebab` handling

* refactor: move `TR_KEY_anti_brute_force_threshold_kebab` handling

* refactor: move `TR_KEY_blocklist_enabled_kebab` handling

* refactor: move `TR_KEY_blocklist_size_kebab` handling

* refactor: move `TR_KEY_blocklist_url_kebab` handling

* refactor: move `TR_KEY_cache_size_mb_kebab` handling

* refactor: move `TR_KEY_config_dir_kebab` handling

* refactor: move `TR_KEY_default_trackers_kebab` handling

* refactor: move `TR_KEY_dht_enabled_kebab` handling

* refactor: move `TR_KEY_download_dir_kebab` handling

* refactor: move `TR_KEY_download_dir_free_space_kebab` handling

* refactor: move `TR_KEY_download_queue_enabled_kebab` handling

* refactor: move `TR_KEY_download_queue_size_kebab` handling

* refactor: move `TR_KEY_idle_seeding_limit_kebab` handling

* refactor: move `TR_KEY_idle_seeding_limit_enabled_kebab` handling

* refactor: move `TR_KEY_incomplete_dir_kebab` handling

* refactor: move `TR_KEY_incomplete_dir_enabled_kebab` handling

* refactor: move `TR_KEY_lpd_enabled_kebab` handling

* refactor: move `TR_KEY_peer_limit_global_kebab` handling

* refactor: move `TR_KEY_peer_limit_per_torrent_kebab` handling

* refactor: move `TR_KEY_peer_port_kebab` handling

* refactor: move `TR_KEY_peer_port_random_on_start_kebab` handling

* refactor: move `TR_KEY_pex_enabled_kebab` handling

* refactor: move `TR_KEY_port_forwarding_enabled_kebab` handling

* refactor: move `TR_KEY_queue_stalled_enabled_kebab` handling

* refactor: move `TR_KEY_queue_stalled_minutes_kebab` handling

* refactor: move `TR_KEY_rename_partial_files_kebab` handling

* refactor: move `TR_KEY_rpc_version_kebab` handling

* refactor: move `TR_KEY_rpc_version_minimum_kebab` handling

* refactor: move `TR_KEY_rpc_version_semver_kebab` handling

* refactor: move `TR_KEY_script_torrent_added_enabled_kebab` handling

* refactor: move `TR_KEY_script_torrent_added_filename_kebab` handling

* refactor: move `TR_KEY_script_torrent_done_enabled_kebab` handling

* refactor: move `TR_KEY_script_torrent_done_filename_kebab` handling

* refactor: move `TR_KEY_script_torrent_done_seeding_enabled_kebab` handling

* refactor: move `TR_KEY_script_torrent_done_seeding_filename_kebab` handling

* refactor: remove `tr_quark_convert` usage for `tr_session::Scripts`

* refactor: move `TR_KEY_seed_ratio_limit_camel` handling

* refactor: move `TR_KEY_seed_ratio_limited_camel` handling

* refactor: move `TR_KEY_seed_queue_enabled_kebab` handling

* refactor: move `TR_KEY_seed_queue_size_kebab` handling

* refactor: move `TR_KEY_session_id_kebab` handling

* refactor: move `TR_KEY_speed_limit_down_kebab` handling

* refactor: move `TR_KEY_speed_limit_down_enabled_kebab` handling

* refactor: move `TR_KEY_speed_limit_up_kebab` handling

* refactor: move `TR_KEY_speed_limit_up_enabled_kebab` handling

* refactor: move `TR_KEY_start_added_torrents_kebab` handling

* refactor: move `TR_KEY_tcp_enabled_kebab` handling

* refactor: move `TR_KEY_trash_original_torrent_files_kebab` handling

* refactor: move `TR_KEY_utp_enabled_kebab` handling

* refactor: move `TR_KEY_recently_active_kebab` handling

* refactor: move `TR_KEY_delete_local_data_kebab` handling

* refactor: move `TR_KEY_activity_date_camel` handling

* refactor: move `TR_KEY_added_date_camel` handling

* refactor: move `TR_KEY_bandwidth_priority_camel` handling

* refactor: move `TR_KEY_bytes_completed_camel` handling

* refactor: move `TR_KEY_corrupt_ever_camel` handling

* refactor: move `TR_KEY_date_created_camel` handling

* refactor: move `TR_KEY_desired_available_camel` handling

* refactor: move `TR_KEY_done_date_camel` handling

* refactor: move `TR_KEY_download_dir_camel` handling

* refactor: move `TR_KEY_download_limit_camel` handling

* refactor: move `TR_KEY_download_limited_camel` handling

* refactor: move `TR_KEY_downloaded_ever_camel` handling

* refactor: move `TR_KEY_edit_date_camel` handling

* refactor: move `TR_KEY_error_string_camel` handling

* refactor: move `TR_KEY_eta_idle_camel` handling

* refactor: move `TR_KEY_file_stats_camel` handling

* refactor: move `TR_KEY_file_count_kebab` handling

* refactor: move `TR_KEY_hash_string_camel` handling

* refactor: move `TR_KEY_have_unchecked_camel` handling

* refactor: move `TR_KEY_have_valid_camel` handling

* refactor: move `TR_KEY_honors_session_limits_camel` handling

* refactor: move `TR_KEY_is_finished_camel` handling

* refactor: move `TR_KEY_is_private_camel` handling

* refactor: move `TR_KEY_is_stalled_camel` handling

* refactor: move `TR_KEY_left_until_done_camel` handling

* refactor: move `TR_KEY_magnet_link_camel` handling

* refactor: move `TR_KEY_manual_announce_time_camel` handling

* refactor: move `TR_KEY_max_connected_peers_camel` handling

* refactor: move `TR_KEY_metadata_percent_complete_camel` handling

* refactor: move `TR_KEY_peer_limit_kebab` handling

* refactor: move `TR_KEY_peers_connected_camel` handling

* refactor: move `TR_KEY_peers_from_camel` handling

* refactor: move `TR_KEY_peers_getting_from_us_camel` handling

* refactor: move `TR_KEY_peers_sending_to_us_camel` handling

* refactor: move `TR_KEY_percent_complete_camel` handling

* refactor: move `TR_KEY_percent_done_camel` handling

* refactor: move `TR_KEY_piece_count_camel` handling

* refactor: move `TR_KEY_piece_size_camel` handling

* refactor: move `TR_KEY_primary_mime_type_kebab` handling

* refactor: move `TR_KEY_queue_position_camel` handling

* refactor: move `TR_KEY_rate_download_camel` handling

* refactor: move `TR_KEY_rate_upload_camel` handling

* refactor: move `TR_KEY_recheck_progress_camel` handling

* refactor: move `TR_KEY_seconds_downloading_camel` handling

* refactor: move `TR_KEY_seconds_seeding_camel` handling

* refactor: move `TR_KEY_seed_idle_limit_camel` handling

* refactor: move `TR_KEY_seed_idle_mode_camel` handling

* refactor: move `TR_KEY_seed_ratio_mode_camel` handling

* refactor: move `TR_KEY_size_when_done_camel` handling

* refactor: move `TR_KEY_start_date_camel` handling

* refactor: move `TR_KEY_torrent_file_camel` handling

* refactor: move `TR_KEY_total_size_camel` handling

* refactor: move `TR_KEY_tracker_list_camel` handling

* refactor: move `TR_KEY_tracker_stats_camel` handling

* refactor: move `TR_KEY_upload_limit_camel` handling

* refactor: move `TR_KEY_upload_limited_camel` handling

* refactor: move `TR_KEY_upload_ratio_camel` handling

* refactor: move `TR_KEY_uploaded_ever_camel` handling

* refactor: move `TR_KEY_webseeds_sending_to_us_camel` handling

* refactor: move `TR_KEY_announce_state_camel` handling

* refactor: move `TR_KEY_download_count_camel` handling

* refactor: move `TR_KEY_has_announced_camel` handling

* refactor: move `TR_KEY_has_scraped_camel` handling

* refactor: move `TR_KEY_is_backup_camel` handling

* refactor: move `TR_KEY_last_announce_peer_count_camel` handling

* refactor: move `TR_KEY_last_announce_result_camel` handling

* refactor: move `TR_KEY_last_announce_start_time_camel` handling

* refactor: move `TR_KEY_last_announce_succeeded_camel` handling

* refactor: move `TR_KEY_last_announce_time_camel` handling

* refactor: move `TR_KEY_last_announce_timed_out_camel` handling

* refactor: move `TR_KEY_last_scrape_result_camel` handling

* refactor: move `TR_KEY_last_scrape_start_time_camel` handling

* refactor: move `TR_KEY_last_scrape_succeeded_camel` handling

* refactor: move `TR_KEY_last_scrape_time_camel` handling

* refactor: move `TR_KEY_last_scrape_timed_out_camel` handling

* refactor: move `TR_KEY_leecher_count_camel` handling

* refactor: move `TR_KEY_next_announce_time_camel` handling

* refactor: move `TR_KEY_next_scrape_time_camel` handling

* refactor: move `TR_KEY_scrape_state_camel` handling

* refactor: move `TR_KEY_seeder_count_camel` handling

* refactor: move `TR_KEY_client_is_choked_camel` handling

* refactor: move `TR_KEY_client_is_interested_camel` handling

* refactor: move `TR_KEY_client_name_camel` handling

* refactor: move `TR_KEY_flag_str_camel` handling

* refactor: move `TR_KEY_is_downloading_from_camel` handling

* refactor: move `TR_KEY_is_encrypted_camel` handling

* refactor: move `TR_KEY_is_incoming_camel` handling

* refactor: move `TR_KEY_is_utp_camel` handling

* refactor: move `TR_KEY_is_uploading_to_camel` handling

* refactor: move `TR_KEY_peer_is_choked_camel` handling

* refactor: move `TR_KEY_peer_is_interested_camel` handling

* refactor: move `TR_KEY_rate_to_client_camel` handling

* refactor: move `TR_KEY_rate_to_peer_camel` handling

* refactor: move `TR_KEY_from_cache_camel` handling

* refactor: move `TR_KEY_from_dht_camel` handling

* refactor: move `TR_KEY_from_incoming_camel` handling

* refactor: move `TR_KEY_from_lpd_camel` handling

* refactor: move `TR_KEY_from_ltep_camel` handling

* refactor: move `TR_KEY_from_pex_camel` handling

* refactor: move `TR_KEY_from_pex_camel` handling

* refactor: move `TR_KEY_tracker_add_camel` handling

* refactor: move `TR_KEY_tracker_remove_camel` handling

* refactor: move `TR_KEY_tracker_replace_camel` handling

* refactor: move `TR_KEY_downloaded_bytes_camel` handling

* refactor: move `TR_KEY_files_added_camel` handling

* refactor: move `TR_KEY_seconds_active_camel` handling

* refactor: move `TR_KEY_session_count_camel` handling

* refactor: move `TR_KEY_uploaded_bytes_camel` handling

* refactor: move `TR_KEY_active_torrent_count_camel` handling

* refactor: move `TR_KEY_cumulative_stats_kebab` handling

* refactor: move `TR_KEY_cumulative_stats_kebab` handling

* refactor: move `TR_KEY_download_speed_camel` handling

* refactor: move `TR_KEY_paused_torrent_count_camel` handling

* refactor: move `TR_KEY_torrent_count_camel` handling

* refactor: move `TR_KEY_upload_speed_camel` handling

* refactor: move `TR_KEY_files_unwanted_kebab` handling

* refactor: move `TR_KEY_files_wanted_kebab` handling

* refactor: move `TR_KEY_priority_high_kebab` handling

* refactor: move `TR_KEY_priority_low_kebab` handling

* refactor: move `TR_KEY_priority_normal_kebab` handling

* refactor: move `TR_KEY_port_is_open_kebab` handling

* refactor: move `TR_KEY_torrent_duplicate_kebab` handling

* refactor: move `TR_KEY_torrent_added_kebab` handling

* refactor: move `TR_KEY_memory_bytes_kebab` handling

* refactor: move `TR_KEY_memory_units_kebab` handling

* refactor: move `TR_KEY_size_bytes_kebab` handling

* refactor: move `TR_KEY_size_units_kebab` handling

* refactor: move `TR_KEY_speed_bytes_kebab` handling

* refactor: move `TR_KEY_speed_units_kebab` handling

* refactor: remove DoneCb

* perf: adjust reserve capacity
2025-12-24 13:29:59 -06:00
Charles Kerr
cf37c7daff refactor: migrate transmission-remote to JSON-RPC (#7986)
* feat: sniff TR_RPC_RPC_VERSION_HEADER in 409 headers

* refactor: use api_compat::convert() when sending requests

* refactor: update to JSON-RPC: print_session()

refactor: update to JSON-RPC: print_session_stats()

* refactor: update to JSON-RPC: print_session()

refactor: update to JSON-RPC: print_details()

* refactor: update to JSON-RPC: print_file_list()

* refactor: update to JSON-RPC: print_torrent_list()

* refactor: update to JSON-RPC: print_trackers()

* refactor: update to JSON-RPC: print_port_test()

* refactor: update to JSON-RPC: print_pieces()

* refactor: update the rest

* feat: check the JSON-RPC version number too

* feat: better errmsg detection

* chore: remove accidentally-committed tracer

* fix: regression

* chore: remove accidentally-committed tracer

* fix: return the right variable in serialize_payload()

* fix: check for blocklist_update too

* perf: reserve the right number of args

* refactor: remove unnecesary logic branch

* perf: avoid unnecessary tr_variant.clone() call

* fixup! feat: check the JSON-RPC version number too

tearfur's code was fine; I introduced this bug as committer

* fix: handle http 204 replies silently

---------

Co-authored-by: Yat Ho <lagoho7@gmail.com>
2025-12-24 11:59:35 -06:00
Charles Kerr
27f0e2e20d test: always call tr_lib_init() in libtransmission tests (#7992)
* test: add TransmissionTest fixture that calls tr_lib_init()

* refactor: use std::call_once() in tr_lib_init()

* test: ensure quarks are sorted in RpcTest::sessionGet

* refactor: use ::libtransmission::test::TransmissionTest

prefer this over ::testing::Test to ensure tr_lib_init() is called once
2025-12-23 14:32:29 -06:00
Yat Ho
dbd4ea5be8 fix(daemon): missing break statement in switch (#7991) 2025-12-23 13:13:32 -06:00
Yat Ho
8241fdab5f fix: handle unaligned torrents in wishlist (#7944)
* fix: handle unaligned torrent pieces and blocks in wishlist

* test: unaligned tests
2025-12-22 23:31:56 -06:00
Yat Ho
dcd516b673 feat: update daemon args for preferred_transports (#7988)
* feat: add `--preferred-transports` to daemon

* chore: deprecate `--(no-)utp` in daemon

* fix: `--(no-)utp` args in daemon
2025-12-22 23:11:41 -06:00
Charles Kerr
257b870604 fix: work around a dumb rapidjson bug (#7985) 2025-12-22 23:10:53 -06:00
Charles Kerr
71ab8cb09f refactor: remove redundant calls to tr_quark_convert() (#7987) 2025-12-22 23:05:55 -06:00
Yat Ho
f2600cf058 chore(remote): deprecate --(no-)utp (#7990) 2025-12-22 23:05:16 -06:00
Charles Kerr
d5314e2c44 refactor: add libtransmission-app (#7978)
* refactor: add libtransmission-app

* refactor: add libtransmission-app/display-modes.h

* refactor: use app::SortMode, app:ShowMode in Qt client

* feat: add to_variant(), to_value() in serializer

* refactor: use app::SortMode in GTK client

* refactor: use app::ShowMode in GTK client

* refactor: make naming consistent with libtransmission-app
2025-12-22 20:05:57 -06:00
Yat Ho
888f90ca1e fix: race condition in tr_torrentStat() (#7948)
* fix: acquire session lock in `tr_torrent::stats()`

* refactor(mac): lock once for the whole updateUI operation
2025-12-22 15:29:15 -06:00
Charles Kerr
62c362eacb fix: clang-tidy warnings in Qt client (#7981)
* fix: readability-identifier-naming

* fix: misc-unused-using-decls

* fix: google-readability-braces-around-statements,hicpp-braces-around-statements,readability-braces-around-statements

* fix: cert-err58-cpp

* fix: bugprone-unchecked-optional-access

* Revert "fix: cert-err58-cpp"

This reverts commit 6e6d97228f.

* fix: better to keep QStringLiteral; disable spurious cert-err58-cpp warning
2025-12-22 09:34:04 -06:00
Yat Ho
1afbe8b675 feat: sync the values of preferred_transports and *_enabled (#7980)
* feat: sync the values of `preferred_transports` and `*_enabled`

* refactor: avoid using `tr_session::allowsTCP()`

* code review: implement fixup methods in source file
2025-12-22 09:15:53 -06:00
Yat Ho
91d9f1f776 feat: generic support for optional fields in serializer (#7979) 2025-12-22 07:58:09 -06:00
Charles Kerr
8f445496c2 refactor: use unmanaged_string for periodic torrent_get fields (#7977)
* refactor: remove Session::addKeyName()

refactor: remove Session::removeKeyName()

these should have been removed a long time ago

* fix: better logging on error in Converters

* refactor: add Qt-app-specific variant converters

* refactor: use tr_variant::unmanaged_string(tr_quark) when in torrent_get table mode
2025-12-21 20:49:41 -06:00
Charles Kerr
0607ea472f perf: use unmanaged strings when populating initial prefs (#7976) 2025-12-21 19:35:14 -06:00
Charles Kerr
433203f82f perf: unmanaged strings in rpcimpl (#7975)
* perf: in rpcimpl, use tr_variant::unmanaged_string() for unit strings

* perf: in rpcimpl, use tr_variant::unmanaged_string() encryption mode

* perf: in rpcimpl, use tr_variant::unmanaged_string() for TrRpcVersionSemver
2025-12-21 11:17:53 -06:00
Charles Kerr
e9c847d965 perf: api_compat::convert() operates inplace rather than creating a new variant (#7973)
* perf: api_compat::convert() operates inplace rather than creating a new variant

* refactor: update bandwidth groups calls
2025-12-21 06:22:05 -06:00