feat: dimos spy - universal transport spy over LCM + Zenoh#2735
Open
leshy wants to merge 15 commits into
Open
Conversation
Design ratified in ticket f6c74d39 (subscribe_all non-conflating decision confirmed by Ivan). Task package for a worker to implement: - TASK.md: goal, decisions, implementation map, acceptance - docs/usage/transports/spy.md: design doc (why, architecture, decisions) - spec.py: subscribe_all contract tightened (every message, no conflation); SubscribeLatestMixin.subscribe_latest() stub = the explicit conflation opt-in - protocol/pubsub/spy.py: TopicStats / SpySource / LCMSpySource / ZenohSpySource / TransportSpy stubs (typed, NotImplementedError bodies) - utils/cli/spy/run_spy.py + `dimos spy` CLI registration (TUI stub) - test_spy.py: 17 contract tests, 15 failing until implemented; the zenoh subscribe_all conflation bug fails sharply (2 of 50 messages delivered) mypy clean (796 files); existing pubsub suites green.
Implement the spy core (TopicStats, LCM/Zenoh SpySources, TransportSpy) that taps the raw-bytes pubsub layer — per-message hot path is (topic, len, ts), never decoding a payload — plus the Textual TUI (dimos spy) and CLI wiring. Spec fix: subscribe_all is now non-conflating on every transport; conflation moves to the opt-in SubscribeLatestMixin.subscribe_latest() (lifted from zenoh, transport-agnostic). Zenoh subscribe_all widens dimos/** -> ** and keeps its drain-stop bookkeeping via _register/_unregister_drain_stop hooks. Rerun bridge migrates to subscribe_latest. dimos lcmspy becomes a deprecated alias for dimos spy --transport lcm. Also strip 14 decorative section-banner comments from the delivered test_spy.py to satisfy codebase_checks/test_no_sections (approved by brain; no logic change).
Contributor
|
Preview deployment for your docs. Learn more about Mintlify Previews.
💡 Tip: Enable Workflows to automatically generate PRs for you. |
- TransportSpy.start() rolls back already-started sources on failure - subscribe_latest stops+joins the drain thread if subscribe_all raises - SOURCE_FACTORIES registry: construct only the requested transports (a filtered-out transport is never imported or instantiated) - run_spy/SpyApp validate unknown --transport names up front - add contract tests for the failure-rollback paths and run_spy selection
Contributor
Greptile SummaryThis PR replaces the old LCM spy with a universal transport spy.
Confidence Score: 5/5This looks safe to merge.
Important Files Changed
Reviews (10): Last reviewed commit: "refactor: move spy core out of protocol/..." | Re-trigger Greptile |
- dimos lcmspy subcommand: drop deprecation/guard, just run spy --transport lcm - lcmspy console-script repointed to run_spy:lcm_main shim (LCM-only spy) - delete the superseded dimos/utils/cli/lcmspy/ module (TUI + stats + tests)
Codecov Report❌ Patch coverage is @@ Coverage Diff @@
## main #2735 +/- ##
==========================================
- Coverage 72.35% 72.33% -0.03%
==========================================
Files 902 907 +5
Lines 81820 82526 +706
Branches 7396 7430 +34
==========================================
+ Hits 59201 59693 +492
- Misses 20639 20850 +211
- Partials 1980 1983 +3
Flags with carried forward coverage won't be shown. Click here to find out more.
... and 7 files with indirect coverage changes 🚀 New features to boost your workflow:
|
- default_sources() skips backends that fail to import with a one-line stderr warning and errors only if no transport is available; an explicitly requested --transport keeps the hard error - spy web mode serves the child with sys.executable and forwards the --transport filter args (validated before serving) - restore the lcmspy --transport override guard dropped by the thin-alias refactor - tests: default degradation, explicit hard error, web command construction
dimos lcmspy web previously became spy --transport lcm web, which missed run_spy.main()'s web branch (web must be argv[0]) and silently launched the local TUI. Keep web first and forward the LCM filter behind it; the --transport override guard stays. Alias routing is now covered by CliRunner tests (tui, web, override rejection).
Reverses the ratified subscribe_all non-conflation spec change (Ivan's call): - zenoh subscribe_all: restore original latest-per-topic drain over dimos/** - spec: drop SubscribeLatestMixin/subscribe_latest entirely - rerun bridge: back to subscribe_all (its original conflating consumer) - spy is transport-agnostic — it just calls bus.subscribe_all(), accepting whatever delivery semantics each transport provides (LCM: every message; zenoh: latest-per-topic). No raw/session-level special-casing. - drop the now-invalid contract tests: subscribe_all-delivers-every[zenoh] and subscribe_latest[*]; docstrings updated to match. Keeps the three Greptile fixes already on feat/ivan/spy (default_sources degradation, web-mode filter forwarding, lcmspy-web routing).
Per maintainer decision, drop the browser 'web' mode entirely: - run_spy: remove the web branch + _web_command; main() just runs the TUI - docs: drop the 'dimos spy web' line Fix the standalone lcmspy console entry (Greptile P1): it discarded sys.argv[1:]. Extract _lcm_only_argv() — shared by lcm_main() and the dimos lcmspy alias — which forwards args to spy and rejects an explicit --transport override (LCM-only). Tests for forwarding + rejection on both entry points; drop the now-obsolete web tests.
…rror Two Greptile P1s on PR #2735: - run_spy._parse_transports now rejects unexpected positionals/flags (and a --transport with no value) instead of silently ignoring them, so an unrecognized argument fails loudly rather than quietly launching the TUI. - default_sources() catches any construction failure (native init, ctor error), not just ImportError: warn + skip on the default path, error only if nothing constructs. Explicit --transport still hard-fails. Tests: stray-positional rejection (unit + CLI for spy and lcmspy), --transport missing-value, and a non-ImportError backend-skip case.
Greptile P1 on PR #2735: default `dimos spy` could construct both sources then die if one failed during start()/tap(), because TransportSpy.start() always rolled everything back and re-raised. Add a best_effort mode to TransportSpy.start(): a source that fails to start/tap is stopped, warned, and skipped, leaving the survivors running; it raises only if no source starts at all. Track live sources so stop() only touches ones that actually started. SpyApp uses best_effort on the default (no --transport) path; an explicit --transport keeps strict all-or-nothing rollback. Ctrl-C/SystemExit still roll back and propagate in both modes. Tests: best-effort skip-with-survivor + all-fail-raises at the TransportSpy level, and SpyApp default-degrades vs explicit-hard-fails wiring.
The standalone transports/spy.md is now a few lines, so merge it into the Transports doc's CLI section (retitled 'Inspecting traffic') and drop the page from the nav. Update the spy.py module docstring to point at the transports doc instead of the removed page.
The spy core (TopicStats, SpySource, LCM/Zenoh sources, TransportSpy) is an observability tool built on top of the pubsub layer, not part of it — it only depends on the pubsub impls, and its only consumers are the spy CLI and tests. Sitting in protocol/pubsub/ was a layering inversion. Move it next to run_spy: dimos/protocol/pubsub/spy.py -> dimos/utils/cli/spy/core.py dimos/protocol/pubsub/test_spy.py -> dimos/utils/cli/spy/test_spy.py Imports updated; no behavior change. pubsub suite and spy tests green.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
replaces lcmspy