diff --git a/AGENTS.md b/AGENTS.md
index 893fea7cfc..e5d0bc4ef1 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -81,10 +81,10 @@ from dimos.agents.mcp.mcp_client import McpClient
from dimos.agents.mcp.mcp_server import McpServer
unitree_go2_agentic = autoconnect(
- unitree_go2_spatial, # robot stack
- McpServer.blueprint(), # HTTP MCP server — exposes all @skill methods on port 9990
- McpClient.blueprint(), # LLM agent — fetches tools from McpServer
- _common_agentic, # skill containers
+ unitree_go2_spatial, # robot stack
+ McpServer.blueprint(), # HTTP MCP server — exposes all @skill methods on port 9990
+ McpClient.blueprint(), # LLM agent — fetches tools from McpServer
+ _common_agentic, # skill containers
)
```
@@ -159,6 +159,7 @@ from dimos.core.stream import In, Out
from dimos.core.core import rpc
from dimos.msgs.sensor_msgs import Image
+
class MyModule(Module):
color_image: In[Image]
processed: Out[Image]
@@ -263,6 +264,7 @@ from dimos.agents.annotation import skill
from dimos.core.core import rpc
from dimos.core.module import Module
+
class MySkillContainer(Module):
@rpc
def start(self) -> None:
@@ -282,6 +284,7 @@ class MySkillContainer(Module):
"""
return f"Moving at {x} m/s for {duration}s"
+
my_skill_container = MySkillContainer.blueprint
```
@@ -303,13 +306,15 @@ To call methods on another module, declare a `Spec` Protocol and annotate an att
from typing import Protocol
from dimos.spec.utils import Spec
+
class NavigatorSpec(Spec, Protocol):
def set_goal(self, goal: PoseStamped) -> bool: ...
def cancel_goal(self) -> bool: ...
+
# my_skill_container.py
class MySkillContainer(Module):
- _navigator: NavigatorSpec # injected by blueprint at build time
+ _navigator: NavigatorSpec # injected by blueprint at build time
@skill
def go_to(self, x: float, y: float) -> str:
diff --git a/README.md b/README.md
index fc7bd0013f..fbfd4cb47c 100644
--- a/README.md
+++ b/README.md
@@ -255,6 +255,7 @@ from dimos.core.stream import In, Out
from dimos.msgs.geometry_msgs import Twist
from dimos.msgs.sensor_msgs import Image, ImageFormat
+
class RobotConnection(Module):
cmd_vel: In[Twist]
color_image: Out[Image]
@@ -273,6 +274,7 @@ class RobotConnection(Module):
self.color_image.publish(img)
time.sleep(0.2)
+
class Listener(Module):
color_image: In[Image]
@@ -280,6 +282,7 @@ class Listener(Module):
def start(self):
self.color_image.subscribe(lambda img: print(f"image {img.width}x{img.height}"))
+
if __name__ == "__main__":
autoconnect(
RobotConnection.blueprint(),
diff --git a/dimos/agents/mcp/test_mcp_server.py b/dimos/agents/mcp/test_mcp_server.py
index 0e2a74925b..e6566fec01 100644
--- a/dimos/agents/mcp/test_mcp_server.py
+++ b/dimos/agents/mcp/test_mcp_server.py
@@ -31,10 +31,7 @@ def _make_rpc_calls(
rpc_calls: dict[str, MagicMock] = {}
for skill in skills:
mock_call = MagicMock()
- if skill.func_name in call_results:
- mock_call.return_value = call_results[skill.func_name]
- else:
- mock_call.return_value = None
+ mock_call.return_value = call_results.get(skill.func_name, None)
rpc_calls[skill.func_name] = mock_call
return rpc_calls
diff --git a/dimos/agents/mcp/test_tool_stream.py b/dimos/agents/mcp/test_tool_stream.py
index 13c47e1f12..e8bec1ea73 100644
--- a/dimos/agents/mcp/test_tool_stream.py
+++ b/dimos/agents/mcp/test_tool_stream.py
@@ -121,31 +121,33 @@ def _read_sse_notifications(
deadline = time.monotonic() + timeout
# A scalar timeout is requests' read timeout: the SSE stream stays open
# across the whole request, an idle read (no bytes for `timeout`s) trips it.
- with requests.Session() as session:
- with session.get(
+ with (
+ requests.Session() as session,
+ session.get(
url,
headers={"Accept": "text/event-stream"},
stream=True,
timeout=timeout,
- ) as response:
- assert response.headers["content-type"].startswith("text/event-stream")
- for raw in response.iter_lines():
- if time.monotonic() > deadline:
- break
- line = raw.decode("utf-8", "replace")
- if not line or not line.startswith("data: "):
- continue
- try:
- data = json.loads(line[6:])
- except json.JSONDecodeError:
- continue
- if data.get("method") not in _NOTIFICATION_METHODS:
- continue
- if tool_name is not None and _frame_tool_name(data) != tool_name:
- continue
- collected.append(data)
- if len(collected) >= expected:
- return collected
+ ) as response,
+ ):
+ assert response.headers["content-type"].startswith("text/event-stream")
+ for raw in response.iter_lines():
+ if time.monotonic() > deadline:
+ break
+ line = raw.decode("utf-8", "replace")
+ if not line or not line.startswith("data: "):
+ continue
+ try:
+ data = json.loads(line[6:])
+ except json.JSONDecodeError:
+ continue
+ if data.get("method") not in _NOTIFICATION_METHODS:
+ continue
+ if tool_name is not None and _frame_tool_name(data) != tool_name:
+ continue
+ collected.append(data)
+ if len(collected) >= expected:
+ return collected
return collected
diff --git a/dimos/agents/testing/vlm_stream_tester.py b/dimos/agents/testing/vlm_stream_tester.py
index ffa9979b87..16825f40bd 100644
--- a/dimos/agents/testing/vlm_stream_tester.py
+++ b/dimos/agents/testing/vlm_stream_tester.py
@@ -79,8 +79,7 @@ def _on_image(self, image: Image) -> None:
now = time.time()
if self._last_image_wall_ts is not None:
gap = now - self._last_image_wall_ts
- if gap > self._max_gap_seen_s:
- self._max_gap_seen_s = gap
+ self._max_gap_seen_s = max(self._max_gap_seen_s, gap)
self._last_image_wall_ts = now
self._latest_image_wall_ts = now
self._latest_image = image
diff --git a/dimos/cli/agentspy/agentspy.py b/dimos/cli/agentspy/agentspy.py
index 8d844d8304..af291ebcc4 100644
--- a/dimos/cli/agentspy/agentspy.py
+++ b/dimos/cli/agentspy/agentspy.py
@@ -61,7 +61,6 @@ def __init__(self, topic: str = "/agent", max_messages: int = 1000) -> None:
self.transport = make_transport(self.topic)
self.transport.start()
self.callbacks: list[callable] = [] # type: ignore[valid-type]
- pass
def start(self) -> None:
"""Start monitoring messages."""
diff --git a/dimos/cli/dimos.py b/dimos/cli/dimos.py
index ee6a92f457..9b4e587eb3 100644
--- a/dimos/cli/dimos.py
+++ b/dimos/cli/dimos.py
@@ -648,7 +648,7 @@ def list_blueprints() -> None:
list_external_blueprint_names,
)
- blueprints = [name for name in all_blueprints.keys() if not name.startswith("demo-")]
+ blueprints = [name for name in all_blueprints if not name.startswith("demo-")]
typer.echo("Built-in blueprints:")
for blueprint_name in sorted(blueprints):
typer.echo(f" {blueprint_name}")
diff --git a/dimos/cli/test_dimos.py b/dimos/cli/test_dimos.py
index e2731b79f2..21e95c7e6b 100644
--- a/dimos/cli/test_dimos.py
+++ b/dimos/cli/test_dimos.py
@@ -27,16 +27,14 @@
_with_relay_bridge,
main,
)
-import dimos.cli.spy.run_spy as run_spy
-import dimos.core.coordination.module_coordinator as module_coordinator
-import dimos.core.coordination.process_lifecycle as process_lifecycle
+from dimos.cli.spy import run_spy
+from dimos.core import run_registry
+from dimos.core.coordination import module_coordinator, process_lifecycle
from dimos.core.global_config import global_config
from dimos.core.module import Module, ModuleConfig
-import dimos.core.run_registry as run_registry
-from dimos.robot import external_blueprints as external
-import dimos.robot.get_all_blueprints as get_all_blueprints
+from dimos.robot import external_blueprints as external, get_all_blueprints
+from dimos.utils import logging_config
import dimos.utils.cache as cache_utils
-import dimos.utils.logging_config as logging_config
class RunConfigA(ModuleConfig):
@@ -135,7 +133,7 @@ def test_list_blueprints_groups_builtin_and_external(monkeypatch: pytest.MonkeyP
def test_list_blueprints_without_external_names(monkeypatch: pytest.MonkeyPatch) -> None:
- monkeypatch.setattr(external, "list_external_blueprint_names", lambda: [])
+ monkeypatch.setattr(external, "list_external_blueprint_names", list)
result = CliRunner().invoke(main, ["list"])
diff --git a/dimos/codebase_checks/test_get_logger.py b/dimos/codebase_checks/test_get_logger.py
index f0671288c1..0de2e9f5fc 100644
--- a/dimos/codebase_checks/test_get_logger.py
+++ b/dimos/codebase_checks/test_get_logger.py
@@ -111,16 +111,20 @@ def test_no_get_logger():
violations = find_get_logger_usages()
if violations:
report_lines = [
- f"Found {len(violations)} forbidden use(s) of `logging.getLogger`. "
- "Use `setup_logger` instead:",
+ (
+ f"Found {len(violations)} forbidden use(s) of `logging.getLogger`. "
+ "Use `setup_logger` instead:"
+ ),
"",
" from dimos.utils.logging_config import setup_logger",
"",
" logger = setup_logger()",
"",
- "If the usage is legitimate (e.g. standalone script, logging "
- "infrastructure, or third-party logger suppression), add it to the "
- "WHITELIST in dimos/codebase_checks/test_get_logger.py.",
+ (
+ "If the usage is legitimate (e.g. standalone script, logging "
+ "infrastructure, or third-party logger suppression), add it to the "
+ "WHITELIST in dimos/codebase_checks/test_get_logger.py."
+ ),
"",
]
for path, lineno, text in violations:
diff --git a/dimos/codebase_checks/test_no_sections.py b/dimos/codebase_checks/test_no_sections.py
index 19489ef2eb..0e8b4d4b55 100644
--- a/dimos/codebase_checks/test_no_sections.py
+++ b/dimos/codebase_checks/test_no_sections.py
@@ -135,9 +135,11 @@ def test_no_section_markers():
violations = find_section_markers()
if violations:
report_lines = [
- f"Found {len(violations)} section marker(s). "
- "If a file is too complicated to be understood without sections, "
- 'then the sections should be files. We don\'t need "subfiles".',
+ (
+ f"Found {len(violations)} section marker(s). "
+ "If a file is too complicated to be understood without sections, "
+ 'then the sections should be files. We don\'t need "subfiles".'
+ ),
"",
]
for path, lineno, text in violations:
diff --git a/dimos/control/README.md b/dimos/control/README.md
index 66c64b418d..9895881797 100644
--- a/dimos/control/README.md
+++ b/dimos/control/README.md
@@ -156,6 +156,7 @@ Tasks output commands in one of three modes:
```python
from dimos.control.task import ControlTask, ResourceClaim, JointCommandOutput, ControlMode
+
class PIDController:
def __init__(self, joints: list[str], priority: int = 10):
self._name = "pid_controller"
@@ -183,8 +184,10 @@ class PIDController:
# PID
self._integral = [i + e * state.dt for i, e in zip(self._integral, error)]
derivative = [(e - le) / state.dt for e, le in zip(error, self._last_error)]
- output = [self.Kp*e + self.Ki*i + self.Kd*d
- for e, i, d in zip(error, self._integral, derivative)]
+ output = [
+ self.Kp * e + self.Ki * i + self.Kd * d
+ for e, i, d in zip(error, self._integral, derivative)
+ ]
self._last_error = error
return JointCommandOutput(
@@ -238,6 +241,7 @@ A deployment needing more subclasses it and annotates the extra ports:
class _Go2Coordinator(PathFollowingCoordinator):
go2_joints: Out[JointState]
+
blueprint = _Go2Coordinator.blueprint(
instance_name="ControlCoordinator", # RPC clients look the coordinator up by class name
publish_robot_joint_states=True,
diff --git a/dimos/control/benchmarking/tuning.py b/dimos/control/benchmarking/tuning.py
index fbe4a2ab2c..0dc95a4195 100644
--- a/dimos/control/benchmarking/tuning.py
+++ b/dimos/control/benchmarking/tuning.py
@@ -634,11 +634,15 @@ class default 0.05). A profile-supplied ``min_speed_floor > 0``
caveats.extend(
[
- f"Valid only for surface={provenance.surface!r}, "
- f"mode={provenance.mode!r}, {provenance.sim_or_hw}. Re-run "
- f"characterization on any surface or gait-mode change.",
- f"Plant fitted from {provenance.characterization_session_dir or 'n/a'} "
- f"on {provenance.date} (git {provenance.git_sha}).",
+ (
+ f"Valid only for surface={provenance.surface!r}, "
+ f"mode={provenance.mode!r}, {provenance.sim_or_hw}. Re-run "
+ f"characterization on any surface or gait-mode change."
+ ),
+ (
+ f"Plant fitted from {provenance.characterization_session_dir or 'n/a'} "
+ f"on {provenance.date} (git {provenance.git_sha})."
+ ),
]
)
valid_for_tuning = provenance.sim_or_hw == "hw"
diff --git a/dimos/control/coordinator.py b/dimos/control/coordinator.py
index eeed8dead0..80fc00657c 100644
--- a/dimos/control/coordinator.py
+++ b/dimos/control/coordinator.py
@@ -87,7 +87,7 @@ class TaskConfig:
name: str
type: str = "trajectory"
- joint_names: list[str] = field(default_factory=lambda: [])
+ joint_names: list[str] = field(default_factory=list)
priority: int = 10
auto_start: bool = False
params: dict[str, Any] = field(default_factory=dict)
@@ -104,8 +104,8 @@ class ControlCoordinatorConfig(ModuleConfig):
publish_robot_joint_states: bool = False
joint_state_frame_id: str = "coordinator"
log_ticks: bool = False
- hardware: list[HardwareComponent] = field(default_factory=lambda: [])
- tasks: list[TaskConfig] = field(default_factory=lambda: [])
+ hardware: list[HardwareComponent] = field(default_factory=list)
+ tasks: list[TaskConfig] = field(default_factory=list)
class ControlCoordinator(Module):
diff --git a/dimos/control/task.py b/dimos/control/task.py
index 84bbb38896..136767185d 100644
--- a/dimos/control/task.py
+++ b/dimos/control/task.py
@@ -31,7 +31,7 @@
from typing import TYPE_CHECKING, Protocol, runtime_checkable
from dimos.control.components import JointName
-from dimos.hardware.manipulators.spec import ControlMode as ControlMode
+from dimos.hardware.manipulators.spec import ControlMode
from dimos.hardware.whole_body.spec import IMUState
if TYPE_CHECKING:
diff --git a/dimos/control/tasks/g1_groot_wbc_task/g1_groot_wbc_task.py b/dimos/control/tasks/g1_groot_wbc_task/g1_groot_wbc_task.py
index 1fae10de3d..0a9e0db248 100644
--- a/dimos/control/tasks/g1_groot_wbc_task/g1_groot_wbc_task.py
+++ b/dimos/control/tasks/g1_groot_wbc_task/g1_groot_wbc_task.py
@@ -813,16 +813,16 @@ def create_task(cfg: Any, hardware: Any) -> G1GrootWBCTask:
)
model_dir = Path(params.model_path)
- kwargs: dict[str, Any] = dict(
- balance_onnx=model_dir / "balance.onnx",
- walk_onnx=model_dir / "walk.onnx",
- joint_names=cfg.joint_names,
- all_joint_names=hw.joint_names,
- priority=cfg.priority,
- auto_arm=params.auto_arm,
- auto_dry_run=params.auto_dry_run,
- default_ramp_seconds=params.default_ramp_seconds,
- )
+ kwargs: dict[str, Any] = {
+ "balance_onnx": model_dir / "balance.onnx",
+ "walk_onnx": model_dir / "walk.onnx",
+ "joint_names": cfg.joint_names,
+ "all_joint_names": hw.joint_names,
+ "priority": cfg.priority,
+ "auto_arm": params.auto_arm,
+ "auto_dry_run": params.auto_dry_run,
+ "default_ramp_seconds": params.default_ramp_seconds,
+ }
if params.decimation is not None:
kwargs["decimation"] = params.decimation
return G1GrootWBCTask(
diff --git a/dimos/control/tasks/path_follower_task/path_follower_task.py b/dimos/control/tasks/path_follower_task/path_follower_task.py
index 3dea8a176d..16bd7a1e52 100644
--- a/dimos/control/tasks/path_follower_task/path_follower_task.py
+++ b/dimos/control/tasks/path_follower_task/path_follower_task.py
@@ -373,8 +373,7 @@ def _step_path_following(self) -> tuple[float, float, float]:
pos = np.array([self._current_odom.position.x, self._current_odom.position.y])
closest = self._windowed_closest(pos)
- if closest > self._max_progress_idx:
- self._max_progress_idx = closest
+ self._max_progress_idx = max(self._max_progress_idx, closest)
# Arrival is only valid AFTER we've traversed enough of the path.
# Otherwise closed paths (goal==start) would arrive on tick 1.
@@ -426,11 +425,11 @@ def configure(
lookahead_min: float | None = None,
lookahead_max: float | None = None,
lookahead_speed_scale: float | None = None,
- max_yaw_rate: float | None | object = _UNSET,
+ max_yaw_rate: float | object | None = _UNSET,
forward_only: bool | None = None,
- ff_config: FeedforwardGainConfig | None | object = _UNSET,
- velocity_profile_config: VelocityProfileConfig | None | object = _UNSET,
- external_profile_cap: PathSpeedCapProtocol | None | object = _UNSET,
+ ff_config: FeedforwardGainConfig | object | None = _UNSET,
+ velocity_profile_config: VelocityProfileConfig | object | None = _UNSET,
+ external_profile_cap: PathSpeedCapProtocol | object | None = _UNSET,
**ignored: Any,
) -> bool:
"""Override per-run knobs before start_path. ``ff_config``,
diff --git a/dimos/control/test_control.py b/dimos/control/test_control.py
index cbd3dd9f48..a2b47dddd2 100644
--- a/dimos/control/test_control.py
+++ b/dimos/control/test_control.py
@@ -849,9 +849,7 @@ def test_higher_priority_wins(self):
if values is None:
continue
for i, joint in enumerate(output.joint_names):
- if joint not in winners:
- winners[joint] = (claim.priority, values[i], output.mode, task.name)
- elif claim.priority > winners[joint][0]:
+ if joint not in winners or claim.priority > winners[joint][0]:
winners[joint] = (claim.priority, values[i], output.mode, task.name)
assert winners["j1"][3] == "high_priority"
diff --git a/dimos/core/coordination/blueprint_config/merging.py b/dimos/core/coordination/blueprint_config/merging.py
index e51e34bf00..a555b786c7 100644
--- a/dimos/core/coordination/blueprint_config/merging.py
+++ b/dimos/core/coordination/blueprint_config/merging.py
@@ -133,12 +133,7 @@ def merge_cli(
index = 0
while index < len(tokens):
token = tokens[index]
- if (
- token == "-o"
- or token.startswith("-o=")
- or token == "--option"
- or token.startswith("--option=")
- ):
+ if token == "-o" or token.startswith(("-o=", "--option=")) or token == "--option":
raise BlueprintConfigError(
"The legacy -o/--option syntax was removed. "
"Use a blueprint option directly, for example "
diff --git a/dimos/core/coordination/blueprint_config/parser.py b/dimos/core/coordination/blueprint_config/parser.py
index ce8338ec66..637e07efe7 100644
--- a/dimos/core/coordination/blueprint_config/parser.py
+++ b/dimos/core/coordination/blueprint_config/parser.py
@@ -349,9 +349,7 @@ def _build_aliases(
for target in targets:
canonical_names = {target.qualified_name}
shorthand_names: set[str] = set()
- if target.section == "global":
- shorthand_names.add(target.relative_name)
- elif target.section == "transport":
+ if target.section == "global" or target.section == "transport":
shorthand_names.add(target.relative_name)
else:
escaped = cli_path((config_key(target.root), *target.path))
diff --git a/dimos/core/coordination/blueprints.py b/dimos/core/coordination/blueprints.py
index b02453e7f5..54c5ebfb67 100644
--- a/dimos/core/coordination/blueprints.py
+++ b/dimos/core/coordination/blueprints.py
@@ -53,7 +53,6 @@ def _noop(*_args: Any, **_kwargs: Any) -> None:
method=name,
spec=spec,
)
- return None
return _noop
@@ -125,19 +124,14 @@ def create(cls, module: type[ModuleBase], kwargs: dict[str, Any]) -> Self:
StreamRef(name=name, type=type_, direction=direction) # type: ignore[arg-type]
)
# linking to unknown module via Spec
- elif is_spec(annotation):
- module_refs.append(ModuleRef(name=name, spec=annotation))
- # linking to specific/known module directly
- elif is_module_type(annotation):
+ elif is_spec(annotation) or is_module_type(annotation):
module_refs.append(ModuleRef(name=name, spec=annotation))
# Optional Spec or Module: SomeSpec | None
elif origin in (Union, types_mod.UnionType):
args = [a for a in get_args(annotation) if a is not type(None)]
if len(args) == 1:
inner = args[0]
- if is_spec(inner):
- module_refs.append(ModuleRef(name=name, spec=inner, optional=True))
- elif is_module_type(inner):
+ if is_spec(inner) or is_module_type(inner):
module_refs.append(ModuleRef(name=name, spec=inner, optional=True))
instance_name = kwargs.get("instance_name")
@@ -292,7 +286,7 @@ def namespace(self, prefix: str, *, expose: Iterable[str] = ()) -> "Blueprint":
)
new_atoms = []
- new_remap: dict[tuple[str, str], str | type[ModuleBase] | type[Spec]] = {}
+ new_remap: dict[tuple[str, str], type[ModuleBase | Spec] | str] = {}
for atom in self.blueprints:
new_name = f"{prefix}/{atom.name}"
diff --git a/dimos/core/coordination/module_coordinator.py b/dimos/core/coordination/module_coordinator.py
index 332f17c093..6a3145d386 100644
--- a/dimos/core/coordination/module_coordinator.py
+++ b/dimos/core/coordination/module_coordinator.py
@@ -309,7 +309,7 @@ def _connect_streams(
if isinstance(remapped_name, str):
streams[remapped_name, conn.type].append((bp.name, conn.name))
- for remapped_name, stream_type in streams.keys():
+ for remapped_name, stream_type in streams:
key = (remapped_name, stream_type)
if key in self._transport_registry:
transport = self._transport_registry[key]
@@ -698,7 +698,7 @@ def _coerce_transport_to_backend(transport: Transport[Any]) -> Transport[Any]:
raw, msg_type = transport.topic.topic, transport.topic.lcm_type
# Strip the Zenoh 'dimos/' namespace (if present) back to the logical name.
# The factory re-applies the right prefix for the target backend.
- logical = raw[len("dimos/") :] if raw.startswith("dimos/") else raw
+ logical = raw.removeprefix("dimos/")
return make_transport(logical, msg_type)
diff --git a/dimos/core/introspection/blueprint/dot.py b/dimos/core/introspection/blueprint/dot.py
index 0b1cef8384..b786743f8c 100644
--- a/dimos/core/introspection/blueprint/dot.py
+++ b/dimos/core/introspection/blueprint/dot.py
@@ -174,8 +174,8 @@ def get_group(mod_class: type[ModuleBase]) -> str:
group_a = sorted_groups[i]
group_b = sorted_groups[i + 1]
# Pick first node from each cluster
- node_a = sorted(by_group[group_a])[0]
- node_b = sorted(by_group[group_b])[0]
+ node_a = min(by_group[group_a])
+ node_b = min(by_group[group_b])
lines.append(f" {node_a} -> {node_b} [style=invis, weight=10];")
lines.append("")
diff --git a/dimos/core/module.py b/dimos/core/module.py
index f5aab99421..fc88c3a3c5 100644
--- a/dimos/core/module.py
+++ b/dimos/core/module.py
@@ -352,9 +352,7 @@ def is_stream(hint: type, stream_type: type) -> bool:
origin = get_origin(hint)
if origin is stream_type:
return True
- if isinstance(hint, type) and issubclass(hint, stream_type):
- return True
- return False
+ return bool(isinstance(hint, type) and issubclass(hint, stream_type))
def format_stream(name: str, hint: type) -> str:
args = get_args(hint)
@@ -402,9 +400,7 @@ def is_stream(hint: type, stream_type: type) -> bool:
origin = get_origin(hint)
if origin is stream_type:
return True
- if isinstance(hint, type) and issubclass(hint, stream_type):
- return True
- return False
+ return bool(isinstance(hint, type) and issubclass(hint, stream_type))
def format_stream(name: str, hint: type) -> str:
args = get_args(hint)
diff --git a/dimos/core/native_module.py b/dimos/core/native_module.py
index 461bd4d0ed..91afb35570 100644
--- a/dimos/core/native_module.py
+++ b/dimos/core/native_module.py
@@ -77,9 +77,9 @@ def _set_process_to_die_when_parent_dies() -> None:
_set_process_to_die_when_parent_dies = None # type: ignore[assignment]
if sys.version_info < (3, 13):
- from typing_extensions import TypeVar
+ pass
else:
- from typing import TypeVar
+ pass
logger = setup_logger()
@@ -171,9 +171,6 @@ def to_cli_args(self) -> list[str]:
return args
-_NativeConfig = TypeVar("_NativeConfig", bound=NativeModuleConfig, default=NativeModuleConfig)
-
-
class NativeModule(Module):
"""
Module that wraps a native executable as a managed subprocess.
diff --git a/dimos/core/stream.py b/dimos/core/stream.py
index 0a5f19f96d..b9bfb3f2ef 100644
--- a/dimos/core/stream.py
+++ b/dimos/core/stream.py
@@ -28,9 +28,8 @@
from reactivex.disposable import Disposable
from dimos.core.resource import Resource
-from dimos.utils import colors
+from dimos.utils import colors, reactive
from dimos.utils.logging_config import setup_logger
-import dimos.utils.reactive as reactive
from dimos.utils.reactive import backpressure
if TYPE_CHECKING:
diff --git a/dimos/core/test_cli_stop_status.py b/dimos/core/test_cli_stop_status.py
index 883d136da0..90ed124b11 100644
--- a/dimos/core/test_cli_stop_status.py
+++ b/dimos/core/test_cli_stop_status.py
@@ -60,12 +60,12 @@ def _make():
def _entry(run_id: str, pid: int, blueprint: str = "test", **kwargs) -> RunEntry:
- defaults = dict(
- started_at=datetime.now(timezone.utc).isoformat(),
- log_dir="/tmp/dimos-test",
- cli_args=[blueprint],
- config_overrides={},
- )
+ defaults = {
+ "started_at": datetime.now(timezone.utc).isoformat(),
+ "log_dir": "/tmp/dimos-test",
+ "cli_args": [blueprint],
+ "config_overrides": {},
+ }
defaults.update(kwargs)
e = RunEntry(run_id=run_id, pid=pid, blueprint=blueprint, **defaults)
e.save()
diff --git a/dimos/core/test_zenoh_transport.py b/dimos/core/test_zenoh_transport.py
index b19f1aebb7..b6495415f0 100644
--- a/dimos/core/test_zenoh_transport.py
+++ b/dimos/core/test_zenoh_transport.py
@@ -59,8 +59,6 @@ def lcm_encode() -> bytes:
class UntypedMsg:
"""A message without lcm_encode. Triggers pickle transport."""
- pass
-
class ProducerModule(Module):
typed_data: Out[TypedMsg]
diff --git a/dimos/experimental/scene_cooking/command.py b/dimos/experimental/scene_cooking/command.py
index e67559ca1f..148b69a83c 100644
--- a/dimos/experimental/scene_cooking/command.py
+++ b/dimos/experimental/scene_cooking/command.py
@@ -171,12 +171,10 @@ def blender_output_line_is_interesting(line: str) -> bool:
"""Return true for Blender output worth streaming during normal cooks."""
return (
- line.startswith("DIMOS_")
+ line.startswith(("DIMOS_", "Blender ", "Error:"))
or "Read blend:" in line
or "Finished glTF" in line
- or line.startswith("Blender ")
or line == "Blender quit"
or "Traceback" in line
or "ERROR" in line
- or line.startswith("Error:")
)
diff --git a/dimos/hardware/drive_trains/unitree_go2/adapter.py b/dimos/hardware/drive_trains/unitree_go2/adapter.py
index 61eefefbaf..45cce2131c 100644
--- a/dimos/hardware/drive_trains/unitree_go2/adapter.py
+++ b/dimos/hardware/drive_trains/unitree_go2/adapter.py
@@ -51,7 +51,7 @@
def _clip(x: float, lo: float, hi: float) -> float:
- return lo if x < lo else hi if x > hi else x
+ return lo if x < lo else min(x, hi)
@dataclass
@@ -356,10 +356,9 @@ def write_enable(self, enable: bool) -> bool:
session = self._get_session()
if enable:
- if not session.locomotion_ready:
- if not self._initialize_locomotion():
- logger.error("[Go2] Failed to initialize locomotion")
- return False
+ if not session.locomotion_ready and not self._initialize_locomotion():
+ logger.error("[Go2] Failed to initialize locomotion")
+ return False
session.enabled = True
logger.info("[Go2] Enabled")
return True
diff --git a/dimos/hardware/manipulators/README.md b/dimos/hardware/manipulators/README.md
index 23125ab845..e8a63f139c 100644
--- a/dimos/hardware/manipulators/README.md
+++ b/dimos/hardware/manipulators/README.md
@@ -93,6 +93,7 @@ class MyArmAdapter: # No inheritance needed - just match the Protocol
def disconnect(self) -> None: ...
def read_joint_positions(self) -> list[float]: ...
def write_joint_positions(self, positions: list[float], velocity: float = 1.0) -> bool: ...
+
# ... implement other Protocol methods
```
@@ -112,6 +113,7 @@ from dimos.core.module import Module, ModuleConfig
from dimos.core.stream import In, Out
from .adapter import MyArmAdapter
+
class MyArm(Module[MyArmConfig]):
joint_state: Out[JointState]
robot_state: Out[RobotState]
diff --git a/dimos/hardware/manipulators/galaxea_a1z/test_adapter.py b/dimos/hardware/manipulators/galaxea_a1z/test_adapter.py
index 560ac1118e..24531adf02 100644
--- a/dimos/hardware/manipulators/galaxea_a1z/test_adapter.py
+++ b/dimos/hardware/manipulators/galaxea_a1z/test_adapter.py
@@ -614,14 +614,18 @@ def test_socketcan_connect_fails_closed_before_sdk_construction(
(
"mttcan",
"0x1\n",
- "SocketCAN interface 'can7' belongs to kernel driver 'mttcan', not the HHS "
- "adapter driver 'gs_usb'. Pass the HHS SocketCAN interface with --can-port.",
+ (
+ "SocketCAN interface 'can7' belongs to kernel driver 'mttcan', not the HHS "
+ "adapter driver 'gs_usb'. Pass the HHS SocketCAN interface with --can-port."
+ ),
),
(
"gs_usb",
"0x0\n",
- "SocketCAN interface 'can7' is DOWN. Configure it for 1 Mbit/s and bring it UP "
- "before starting DimOS.",
+ (
+ "SocketCAN interface 'can7' is DOWN. Configure it for 1 Mbit/s and bring it UP "
+ "before starting DimOS."
+ ),
),
("gs_usb", "0x1\n", None),
],
diff --git a/dimos/hardware/sensors/camera/spec.py b/dimos/hardware/sensors/camera/spec.py
index 53002e736b..24f0d691d0 100644
--- a/dimos/hardware/sensors/camera/spec.py
+++ b/dimos/hardware/sensors/camera/spec.py
@@ -64,17 +64,14 @@ class DepthCameraHardware(ABC):
@abstractmethod
def get_color_camera_info(self) -> CameraInfo | None:
"""Get color camera intrinsics."""
- pass
@abstractmethod
def get_depth_camera_info(self) -> CameraInfo | None:
"""Get depth camera intrinsics."""
- pass
@abstractmethod
def get_depth_scale(self) -> float:
"""Get the depth scale factor (meters per unit)."""
- pass
@property
@abstractmethod
diff --git a/dimos/hardware/sensors/camera/zed/camera.py b/dimos/hardware/sensors/camera/zed/camera.py
index fd777339df..68d195d748 100644
--- a/dimos/hardware/sensors/camera/zed/camera.py
+++ b/dimos/hardware/sensors/camera/zed/camera.py
@@ -19,7 +19,7 @@
import time
from pydantic import Field
-import pyzed.sl as sl
+from pyzed import sl
import reactivex as rx
from dimos.constants import DEFAULT_THREAD_JOIN_TIMEOUT
diff --git a/dimos/hardware/sensors/camera/zed/compat.py b/dimos/hardware/sensors/camera/zed/compat.py
index f7e78fc5d6..e4fca89adb 100644
--- a/dimos/hardware/sensors/camera/zed/compat.py
+++ b/dimos/hardware/sensors/camera/zed/compat.py
@@ -29,8 +29,8 @@
if HAS_ZED_SDK:
from dimos.hardware.sensors.camera.zed.camera import (
- ZEDCamera as ZEDCamera,
- ZEDModule as ZEDModule,
+ ZEDCamera,
+ ZEDModule,
)
else:
# Provide stub classes when SDK is not available
diff --git a/dimos/hardware/sensors/lidar/fastlio2/tools/pcap_to_db.py b/dimos/hardware/sensors/lidar/fastlio2/tools/pcap_to_db.py
index 6d73c7c0e0..ea69ed4b9c 100644
--- a/dimos/hardware/sensors/lidar/fastlio2/tools/pcap_to_db.py
+++ b/dimos/hardware/sensors/lidar/fastlio2/tools/pcap_to_db.py
@@ -236,9 +236,12 @@ def _build_blueprint(
from dimos.hardware.sensors.lidar.fastlio2.recorder import FastLio2Recorder
from dimos.hardware.sensors.lidar.virtual_mid360.module import VirtualMid360
- fastlio_kwargs: dict[str, Any] = dict(
- host_ip=args.host_ip, lidar_ip=args.lidar_ip, odom_freq=args.odom_freq, debug=False
- )
+ fastlio_kwargs: dict[str, Any] = {
+ "host_ip": args.host_ip,
+ "lidar_ip": args.lidar_ip,
+ "odom_freq": args.odom_freq,
+ "debug": False,
+ }
fastlio_kwargs.update(overrides)
return (
diff --git a/dimos/hardware/sensors/lidar/pointlio/scripts/pcap_to_db.py b/dimos/hardware/sensors/lidar/pointlio/scripts/pcap_to_db.py
index c05e497690..e49a4a2f35 100644
--- a/dimos/hardware/sensors/lidar/pointlio/scripts/pcap_to_db.py
+++ b/dimos/hardware/sensors/lidar/pointlio/scripts/pcap_to_db.py
@@ -315,9 +315,12 @@ def _build_blueprint(
from dimos.hardware.sensors.lidar.pointlio.recorder import PointlioRecorder
from dimos.hardware.sensors.lidar.virtual_mid360.module import VirtualMid360
- pointlio_kwargs: dict[str, Any] = dict(
- host_ip=args.host_ip, lidar_ip=args.lidar_ip, odom_freq=args.odom_freq, debug=False
- )
+ pointlio_kwargs: dict[str, Any] = {
+ "host_ip": args.host_ip,
+ "lidar_ip": args.lidar_ip,
+ "odom_freq": args.odom_freq,
+ "debug": False,
+ }
pointlio_kwargs.update(overrides)
return (
diff --git a/dimos/imitation/dataprep/formats/hdf5/reader.py b/dimos/imitation/dataprep/formats/hdf5/reader.py
index 92ec10820e..4d3618211e 100644
--- a/dimos/imitation/dataprep/formats/hdf5/reader.py
+++ b/dimos/imitation/dataprep/formats/hdf5/reader.py
@@ -23,6 +23,8 @@
from pathlib import Path
from typing import Any
+from typing_extensions import Self
+
from dimos.imitation.dataprep.core import summarize_lengths
@@ -47,7 +49,7 @@ def __init__(self, path: Path) -> None:
self._episodes_g = self._h5["episodes"]
self._ep_names = sorted(self._episodes_g.keys())
- def __enter__(self) -> _Hdf5Reader:
+ def __enter__(self) -> Self:
return self
def __exit__(self, *exc: object) -> None:
diff --git a/dimos/manipulation/blueprints.py b/dimos/manipulation/blueprints.py
index 5c81178271..669766918a 100644
--- a/dimos/manipulation/blueprints.py
+++ b/dimos/manipulation/blueprints.py
@@ -16,16 +16,3 @@
Robot-owned manipulation blueprints now live under ``dimos.robot.manipulators``.
"""
-
-from dimos.robot.manipulators.xarm.blueprints.agentic import (
- xarm7_planner_coordinator_agent as xarm7_planner_coordinator_agent,
- xarm_perception_agent as xarm_perception_agent,
- xarm_perception_sim_agent as xarm_perception_sim_agent,
-)
-from dimos.robot.manipulators.xarm.blueprints.basic import (
- xarm7_planner_coordinator as xarm7_planner_coordinator,
-)
-from dimos.robot.manipulators.xarm.blueprints.perception import xarm_perception as xarm_perception
-from dimos.robot.manipulators.xarm.blueprints.simulation import (
- xarm_perception_sim as xarm_perception_sim,
-)
diff --git a/dimos/manipulation/control/servo_control/README.md b/dimos/manipulation/control/servo_control/README.md
index 2e0847f4d7..622cb2feb2 100644
--- a/dimos/manipulation/control/servo_control/README.md
+++ b/dimos/manipulation/control/servo_control/README.md
@@ -82,7 +82,7 @@ controller = CartesianMotionController(
control_frequency=20.0,
position_kp=1.0,
max_linear_velocity=0.15, # m/s
- )
+ ),
)
# 3. Set up topic connections (shared memory)
@@ -103,8 +103,8 @@ controller.start()
# 5. Send Cartesian goal (move 10cm in X)
controller.set_target_pose(
position=[0.3, 0.0, 0.5], # xyz in meters
- orientation=[0, 0, 0], # roll, pitch, yaw in radians
- frame_id="world"
+ orientation=[0, 0, 0], # roll, pitch, yaw in radians
+ frame_id="world",
)
# 6. Wait for convergence
@@ -137,14 +137,11 @@ from dimos.msgs.geometry_msgs import PoseStamped
target = PoseStamped(
frame_id="world",
position=[0.3, 0.2, 0.5],
- orientation=[0, 0, 0, 1] # quaternion
+ orientation=[0, 0, 0, 1], # quaternion
)
# Option 1: Via RPC
-controller.set_target_pose(
- position=list(target.position),
- orientation=list(target.orientation)
-)
+controller.set_target_pose(position=list(target.position), orientation=list(target.orientation))
# Option 2: Via topic (if connected)
controller.target_pose.publish(target)
@@ -162,22 +159,22 @@ Target poses can be published to the controller's `/target_pose` topic via LCM t
class CartesianMotionControllerConfig:
# Control loop
control_frequency: float = 20.0 # Hz (recommend 10-50Hz)
- command_timeout: float = 1.0 # seconds
+ command_timeout: float = 1.0 # seconds
# PID gains (position)
- position_kp: float = 1.0 # m/s per meter of error
- position_ki: float = 0.0 # Integral gain
- position_kd: float = 0.1 # Derivative gain (damping)
+ position_kp: float = 1.0 # m/s per meter of error
+ position_ki: float = 0.0 # Integral gain
+ position_kd: float = 0.1 # Derivative gain (damping)
# PID gains (orientation)
- orientation_kp: float = 2.0 # rad/s per radian of error
+ orientation_kp: float = 2.0 # rad/s per radian of error
orientation_ki: float = 0.0
orientation_kd: float = 0.2
# Safety limits
- max_linear_velocity: float = 0.2 # m/s
+ max_linear_velocity: float = 0.2 # m/s
max_angular_velocity: float = 1.0 # rad/s
- max_position_error: float = 0.5 # m (emergency stop threshold)
+ max_position_error: float = 0.5 # m (emergency stop threshold)
max_orientation_error: float = 1.57 # rad (~90°)
# Convergence
diff --git a/dimos/manipulation/grasping/test_grasp_gen_x.py b/dimos/manipulation/grasping/test_grasp_gen_x.py
index 5621eeb711..612426ae9a 100644
--- a/dimos/manipulation/grasping/test_grasp_gen_x.py
+++ b/dimos/manipulation/grasping/test_grasp_gen_x.py
@@ -25,8 +25,8 @@
import pytest
from pytest_mock import MockerFixture
+from dimos.manipulation.grasping import grasp_gen_x
from dimos.manipulation.grasping.grasp_gen_spec import GraspGenSpec, LegacyGraspGenSpec
-import dimos.manipulation.grasping.grasp_gen_x as grasp_gen_x
from dimos.manipulation.grasping.grasp_gen_x import (
GraspGenXConfig,
GraspGenXError,
diff --git a/dimos/manipulation/grasping/visualize_grasps.py b/dimos/manipulation/grasping/visualize_grasps.py
index fe3c88428b..2662b1a2fe 100644
--- a/dimos/manipulation/grasping/visualize_grasps.py
+++ b/dimos/manipulation/grasping/visualize_grasps.py
@@ -17,6 +17,7 @@
import json
from pathlib import Path
+import sys
from typing import Any
import numpy as np
@@ -90,4 +91,4 @@ def main() -> int:
if __name__ == "__main__":
- exit(main())
+ sys.exit(main())
diff --git a/dimos/manipulation/manipulation_module.py b/dimos/manipulation/manipulation_module.py
index 59340b6797..ad034a59c2 100644
--- a/dimos/manipulation/manipulation_module.py
+++ b/dimos/manipulation/manipulation_module.py
@@ -284,7 +284,7 @@ def _initialize_planning(self) -> None:
self._world_monitor.add_obstacle(floor_obs)
logger.info(f"Floor obstacle added at z={fz:.3f}")
- for _, (robot_id, _) in self._robots.items():
+ for robot_id, _ in self._robots.values():
self._world_monitor.start_state_monitor(robot_id)
if self._world_monitor.visualization is not None:
@@ -1030,7 +1030,7 @@ def generate_cartesian_plan(
self._fail("Cartesian target groups must be unique")
return None
auxiliary_ids = tuple(planning_group_id_from_selector(group) for group in auxiliary_groups)
- group_ids = tuple((*normalized_targets.keys(), *auxiliary_ids))
+ group_ids = (*normalized_targets.keys(), *auxiliary_ids)
planning_epoch = self._begin_group_planning()
if planning_epoch is None:
return None
@@ -1096,10 +1096,9 @@ def preview_plan(
except Exception as exc:
logger.error("Generated plan cannot be resolved: %s", exc)
return False
- if robot_name is not None:
- if robot_name not in affected:
- logger.error("Generated plan does not affect robot '%s'", robot_name)
- return False
+ if robot_name is not None and robot_name not in affected:
+ logger.error("Generated plan does not affect robot '%s'", robot_name)
+ return False
if self._world_monitor is None:
return False
self._world_monitor.animate_trajectory(plan.trajectory, duration)
diff --git a/dimos/manipulation/planning/README.md b/dimos/manipulation/planning/README.md
index 33974b5d9a..a8ee3c827d 100644
--- a/dimos/manipulation/planning/README.md
+++ b/dimos/manipulation/planning/README.md
@@ -19,11 +19,11 @@ python -i -m dimos.manipulation.planning.examples.manipulation_client # termina
In the interactive client:
```python skip
-commands() # List available commands
-joints() # Get current joint positions
-plan([0.1] * 7) # Plan to target
-preview() # Preview in Meshcat (url() for link)
-execute() # Execute via coordinator
+commands() # List available commands
+joints() # Get current joint positions
+plan([0.1] * 7) # Plan to target
+preview() # Preview in Meshcat (url() for link)
+execute() # Execute via coordinator
```
## Architecture
diff --git a/dimos/manipulation/planning/kinematics/test_pink_ik.py b/dimos/manipulation/planning/kinematics/test_pink_ik.py
index d0324edb56..a8866c331b 100644
--- a/dimos/manipulation/planning/kinematics/test_pink_ik.py
+++ b/dimos/manipulation/planning/kinematics/test_pink_ik.py
@@ -27,8 +27,8 @@
from dimos.manipulation.planning.factory import create_kinematics
from dimos.manipulation.planning.groups.models import PlanningGroup, PlanningGroupDefinition
+from dimos.manipulation.planning.kinematics import pink_ik
from dimos.manipulation.planning.kinematics.config import PinkKinematicsConfig
-import dimos.manipulation.planning.kinematics.pink_ik as pink_ik
from dimos.manipulation.planning.kinematics.pink_ik import (
PinkIK,
PinkIKConfig,
diff --git a/dimos/manipulation/planning/monitor/test_world_monitor.py b/dimos/manipulation/planning/monitor/test_world_monitor.py
index cb19f79389..af293ce99e 100644
--- a/dimos/manipulation/planning/monitor/test_world_monitor.py
+++ b/dimos/manipulation/planning/monitor/test_world_monitor.py
@@ -112,7 +112,6 @@ def get_obstacles(self):
def finalize(self) -> None:
self.calls.append(("finalize",))
- return None
@property
def is_finalized(self):
@@ -130,7 +129,6 @@ def sync_from_joint_state(self, robot_id, joint_state) -> None:
def set_joint_state(self, ctx, robot_id, joint_state) -> None:
self.calls.append(("set_joint_state", ctx, robot_id, joint_state))
- return None
def get_joint_state(self, ctx, robot_id):
return None
diff --git a/dimos/manipulation/planning/monitor/world_monitor.py b/dimos/manipulation/planning/monitor/world_monitor.py
index bcbb2b7ed8..994ca9ccbc 100644
--- a/dimos/manipulation/planning/monitor/world_monitor.py
+++ b/dimos/manipulation/planning/monitor/world_monitor.py
@@ -250,7 +250,7 @@ def stop_all_monitors(self) -> None:
self.stop_visualization_thread()
with self._lock:
- for _robot_id, monitor in self._state_monitors.items():
+ for monitor in self._state_monitors.values():
monitor.stop()
self._state_monitors.clear()
diff --git a/dimos/manipulation/planning/world/drake_world.py b/dimos/manipulation/planning/world/drake_world.py
index b856379cc7..c12807257a 100644
--- a/dimos/manipulation/planning/world/drake_world.py
+++ b/dimos/manipulation/planning/world/drake_world.py
@@ -1186,27 +1186,27 @@ def _get_group_jacobian(self, ctx: Context, group_id: PlanningGroupID) -> NDArra
def initialize(self, session: VisualizationSession) -> None:
"""Embedded Meshcat observes the Drake world directly; no extra sync needed."""
- return None
+ return
def add_vis_obstacle(self, obstacle_id: str, obstacle: Obstacle) -> None:
"""Embedded Meshcat observes native WorldSpec obstacle mutations."""
- return None
+ return
def update_vis_obstacle(self, obstacle: Obstacle) -> None:
"""Embedded Meshcat observes native WorldSpec obstacle replacement."""
- return None
+ return
def update_vis_obstacle_pose(self, obstacle_id: str, pose: PoseStamped) -> None:
"""Embedded Meshcat observes native WorldSpec obstacle pose updates."""
- return None
+ return
def remove_vis_obstacle(self, obstacle_id: str) -> None:
"""Embedded Meshcat observes native WorldSpec obstacle mutations."""
- return None
+ return
def clear_vis_obstacles(self) -> None:
"""Embedded Meshcat observes native WorldSpec obstacle mutations."""
- return None
+ return
def get_visualization_url(self) -> str | None:
"""Get visualization URL if enabled."""
diff --git a/dimos/manipulation/test_manipulation_monitor_preview.py b/dimos/manipulation/test_manipulation_monitor_preview.py
index ae69ddb25f..55baf9a98d 100644
--- a/dimos/manipulation/test_manipulation_monitor_preview.py
+++ b/dimos/manipulation/test_manipulation_monitor_preview.py
@@ -335,7 +335,7 @@ def test_visualization_routing_and_stop_all_monitors(self):
assert monitor.visualization is viz
assert viz.published is True
assert viz.preview_animation_cancellations == 2
- assert viz.animations == [(tuple(), [], 4.5)]
+ assert viz.animations == [((), [], 4.5)]
monitor.stop_all_monitors()
@@ -361,8 +361,8 @@ def test_clear_planned_path_invalidates_before_dismissing_preview(self, module_f
module._last_plan = plan
module._world_monitor = MagicMock()
plan_during_dismissal: list[GeneratedPlan | None] = []
- module._world_monitor.cancel_preview_animation.side_effect = (
- lambda: plan_during_dismissal.append(module._last_plan)
+ module._world_monitor.cancel_preview_animation.side_effect = lambda: (
+ plan_during_dismissal.append(module._last_plan)
)
assert module.clear_planned_path() is True
diff --git a/dimos/manipulation/visualization/viser/runtime.py b/dimos/manipulation/visualization/viser/runtime.py
index fb4cc20ff9..d86f138a27 100644
--- a/dimos/manipulation/visualization/viser/runtime.py
+++ b/dimos/manipulation/visualization/viser/runtime.py
@@ -22,7 +22,7 @@
VISER_URDF_INSTALL_HINT = VISER_INSTALL_HINT
try:
- from viser import ViserServer as ViserServer
+ from viser import ViserServer
except ModuleNotFoundError as e:
if e.name != "viser":
raise
diff --git a/dimos/manipulation/visualization/viser/state.py b/dimos/manipulation/visualization/viser/state.py
index 38c0503b70..e858e65dd0 100644
--- a/dimos/manipulation/visualization/viser/state.py
+++ b/dimos/manipulation/visualization/viser/state.py
@@ -174,7 +174,7 @@ def can_cancel(self) -> bool:
def can_execute(self, action_status: ActionStatus | None = None) -> bool:
plan = self.plan_state
effective_action_status = action_status or self.action_status
- if not (
+ return (
self.runtime == PanelRuntime.RUNNING
and self.backend_status == BackendConnectionStatus.READY
and effective_action_status == ActionStatus.IDLE
@@ -184,9 +184,7 @@ def can_execute(self, action_status: ActionStatus | None = None) -> bool:
and plan.plan is not None
and plan.group_ids == self.selected_group_ids
and plan.target_sequence_id == self.latest_sequence_id
- ):
- return False
- return True
+ )
@property
def connected(self) -> bool:
diff --git a/dimos/manipulation/visualization/viser/test_viser_visualization.py b/dimos/manipulation/visualization/viser/test_viser_visualization.py
index 485fe8b5a3..45c08fbe6a 100644
--- a/dimos/manipulation/visualization/viser/test_viser_visualization.py
+++ b/dimos/manipulation/visualization/viser/test_viser_visualization.py
@@ -26,6 +26,8 @@
pytest.importorskip("viser", reason="Viser optional dependency is not installed")
+from typing_extensions import Self
+
from dimos.manipulation.planning.groups.models import PlanningGroup, PlanningGroupSelection
from dimos.manipulation.planning.spec.enums import ObstacleType, PlanningStatus
from dimos.manipulation.planning.spec.models import (
@@ -106,7 +108,7 @@ def __init__(self, label: str, **kwargs: bool) -> None:
super().__init__(label=label)
self.kwargs = kwargs
- def __enter__(self) -> Folder:
+ def __enter__(self) -> Self:
return self
def __exit__(self, *_: object) -> bool:
@@ -407,11 +409,9 @@ def plan_cartesian(self, request: object) -> GeneratedPlan | None:
tuple(request.auxiliary_group_ids), # type: ignore[attr-defined]
)
)
- group_ids = tuple(
- (
- *request.pose_targets.keys(), # type: ignore[attr-defined]
- *request.auxiliary_group_ids, # type: ignore[attr-defined]
- )
+ group_ids = (
+ *request.pose_targets.keys(), # type: ignore[attr-defined]
+ *request.auxiliary_group_ids, # type: ignore[attr-defined]
)
return self.module.make_plan(group_ids) if self.module.cartesian_plan_success else None
@@ -1571,8 +1571,8 @@ def add_box(path: str, **kwargs: object) -> Handle:
return Handle(visible=bool(kwargs["visible"]))
server.scene.add_box = add_box
- server.scene.add_label = (
- lambda path, text, **kwargs: calls.append((path, {"text": text, **kwargs})) or Handle()
+ server.scene.add_label = lambda path, text, **kwargs: (
+ calls.append((path, {"text": text, **kwargs})) or Handle()
)
scene = ViserManipulationScene(server, Urdf)
@@ -1588,8 +1588,8 @@ def test_scene_replaces_invalid_box_geometry_with_a_visible_proxy() -> None:
server.scene.add_grid = lambda *_args, **_kwargs: Handle()
calls: list[tuple[str, dict[str, object]]] = []
server.scene.add_box = lambda path, **kwargs: calls.append((path, kwargs)) or Handle()
- server.scene.add_label = (
- lambda path, text, **kwargs: calls.append((path, {"text": text, **kwargs})) or Handle()
+ server.scene.add_label = lambda path, text, **kwargs: (
+ calls.append((path, {"text": text, **kwargs})) or Handle()
)
scene = ViserManipulationScene(server, Urdf)
@@ -1623,8 +1623,8 @@ def test_scene_mesh_rendering_accepts_scene_meshes_and_falls_back_on_load_failur
assert mesh_calls[0][2].shape == (1, 3)
fallback_paths: list[str] = []
- server.scene.add_box = lambda path, **kwargs: fallback_paths.append(path) or Handle(
- visible=bool(kwargs["visible"])
+ server.scene.add_box = lambda path, **kwargs: (
+ fallback_paths.append(path) or Handle(visible=bool(kwargs["visible"]))
)
server.scene.add_label = lambda path, *_args, **_kwargs: fallback_paths.append(path) or Handle()
monkeypatch.setattr(
@@ -1643,9 +1643,8 @@ def test_scene_obstacle_visibility_replacement_cleanup_and_closed_state() -> Non
server = Server()
server.scene.add_grid = lambda *_args, **_kwargs: Handle()
handles: list[Handle] = []
- server.scene.add_box = (
- lambda _path, **kwargs: handles.append(Handle(visible=bool(kwargs["visible"])))
- or handles[-1]
+ server.scene.add_box = lambda _path, **kwargs: (
+ handles.append(Handle(visible=bool(kwargs["visible"]))) or handles[-1]
)
scene = ViserManipulationScene(server, Urdf)
item = obstacle(ObstacleType.BOX, (1.0, 1.0, 1.0))
diff --git a/dimos/mapping/osm/README.md b/dimos/mapping/osm/README.md
index cb94c0160b..f042026c2a 100644
--- a/dimos/mapping/osm/README.md
+++ b/dimos/mapping/osm/README.md
@@ -32,12 +32,12 @@ curr_map = CurrentLocationMap(QwenVlModel())
curr_map.update_position(LatLon(lat=..., lon=...))
# If you want to get back a GPS position of a feature (Qwen gets your current position).
-curr_map.query_for_one_position('Where is the closest farmacy?')
+curr_map.query_for_one_position("Where is the closest farmacy?")
# Returns:
# LatLon(lat=..., lon=...)
# If you also want to get back a description of the result.
-curr_map.query_for_one_position_and_context('Where is the closest pharmacy?')
+curr_map.query_for_one_position_and_context("Where is the closest pharmacy?")
# Returns:
# (LatLon(lat=..., lon=...), "Lloyd's Pharmacy on Main Street")
```
diff --git a/dimos/mapping/ray_tracing/voxel_map.pyi b/dimos/mapping/ray_tracing/voxel_map.pyi
index 2d7e3cc5d6..5cb7b59790 100644
--- a/dimos/mapping/ray_tracing/voxel_map.pyi
+++ b/dimos/mapping/ray_tracing/voxel_map.pyi
@@ -41,18 +41,15 @@ class VoxelRayMapper:
origin: tuple[float, float, float],
) -> None:
"""Update the map with a frame of lidar points. Shape (N, 3) float32."""
- ...
def global_map(self) -> NDArray[np.float32]:
"""Return the centers of all healthy voxels as (M, 3) float32."""
- ...
def global_map_normals(self) -> tuple[NDArray[np.float32], NDArray[np.float32]]:
"""Return healthy voxel centers and their surface normals, both (M, 3) float32.
Matching order. The normal is the zero vector where the voxel has no plane.
"""
- ...
def local_map(
self,
@@ -62,18 +59,14 @@ class VoxelRayMapper:
z_max: float,
) -> NDArray[np.float32]:
"""Return healthy voxels inside the cylinder around origin as (M, 3) float32."""
- ...
def voxel_count(self) -> int:
"""Number of healthy voxels currently in the map."""
- ...
def clear(self) -> None:
"""Reset the map to empty."""
- ...
def __len__(self) -> int: ...
- def __repr__(self) -> str: ...
def local_bounds(
points: NDArray[np.float32],
@@ -85,6 +78,5 @@ def local_bounds(
Non-finite points are ignored.
"""
- ...
__all__ = ["VoxelRayMapper", "local_bounds"]
diff --git a/dimos/memory2/architecture.md b/dimos/memory2/architecture.md
index c4a90a7085..d677980d53 100644
--- a/dimos/memory2/architecture.md
+++ b/dimos/memory2/architecture.md
@@ -91,11 +91,15 @@ latest = images.last()
edges = images.transform(Canny()).save(store.stream("edges"))
edges.drain() # actually run the pipeline; .save() is lazy
+
def running_avg(upstream):
total, n = 0.0, 0
for obs in upstream:
- total += obs.data; n += 1
+ total += obs.data
+ n += 1
yield obs.derive(data=total / n)
+
+
avgs = stream.transform(running_avg).to_list()
# Live
diff --git a/dimos/memory2/blobstore/blobstore.md b/dimos/memory2/blobstore/blobstore.md
index 00006cf468..78174c9d2d 100644
--- a/dimos/memory2/blobstore/blobstore.md
+++ b/dimos/memory2/blobstore/blobstore.md
@@ -7,7 +7,7 @@ Separates payload blob storage from metadata indexing. Observation payloads vary
```python
class BlobStore(Resource):
def put(self, stream_name: str, key: int, data: bytes) -> None: ...
- def get(self, stream_name: str, key: int) -> bytes: ... # raises KeyError if missing
+ def get(self, stream_name: str, key: int) -> bytes: ... # raises KeyError if missing
def delete(self, stream_name: str, key: int) -> None: ... # silent if missing
```
@@ -67,9 +67,9 @@ WHERE m.ts > ?
```python
# Per-stream blob store choice
-poses = store.stream("poses", PoseStamped) # default, lazy
-images = store.stream("images", Image, eager_blobs=True) # eager
-images = store.stream("images", Image, blob_store=file_blobs) # override
+poses = store.stream("poses", PoseStamped) # default, lazy
+images = store.stream("images", Image, eager_blobs=True) # eager
+images = store.stream("images", Image, blob_store=file_blobs) # override
```
## Files
diff --git a/dimos/memory2/codecs/README.md b/dimos/memory2/codecs/README.md
index 8ad40e95fd..69a3b1abaf 100644
--- a/dimos/memory2/codecs/README.md
+++ b/dimos/memory2/codecs/README.md
@@ -25,10 +25,10 @@ class Codec(Protocol[T]):
```python
from dimos.memory2.codecs import codec_for
-codec_for(Image) # → JpegCodec(quality=50)
-codec_for(SomeLcmMsg) # → LcmCodec(SomeLcmMsg) (if has lcm_encode/lcm_decode)
-codec_for(dict) # → PickleCodec() (fallback)
-codec_for(None) # → PickleCodec()
+codec_for(Image) # → JpegCodec(quality=50)
+codec_for(SomeLcmMsg) # → LcmCodec(SomeLcmMsg) (if has lcm_encode/lcm_decode)
+codec_for(dict) # → PickleCodec() (fallback)
+codec_for(None) # → PickleCodec()
```
## Writing a new codec
@@ -37,11 +37,9 @@ codec_for(None) # → PickleCodec()
```python
class MyCodec:
- def encode(self, value: MyType) -> bytes:
- ...
+ def encode(self, value: MyType) -> bytes: ...
- def decode(self, data: bytes) -> MyType:
- ...
+ def decode(self, data: bytes) -> MyType: ...
```
2. Add a branch in `codec_for()` in `base.py` to auto-select it for the relevant type.
@@ -50,8 +48,7 @@ class MyCodec:
```python
@pytest.fixture(params=[..., ("mycodec", MyCodec(), sample_value)])
-def codec_case(request):
- ...
+def codec_case(request): ...
```
No base class needed — `Codec` is a protocol. Just implement `encode` and `decode`.
diff --git a/dimos/memory2/embeddings.md b/dimos/memory2/embeddings.md
index 3e3f341c70..eed83447fc 100644
--- a/dimos/memory2/embeddings.md
+++ b/dimos/memory2/embeddings.md
@@ -17,10 +17,11 @@ class Observation(Generic[T]):
_data: T | _Unloaded = ...
_loader: Callable[[], T] | None = None # lazy loading via blob store
+
@dataclass
class EmbeddedObservation(Observation[T]):
- embedding: Embedding | None = None # populated by Embed transformer
- similarity: float | None = None # populated by .search()
+ embedding: Embedding | None = None # populated by Embed transformer
+ similarity: float | None = None # populated by .search()
```
`EmbeddedObservation` is a subclass — passes anywhere `Observation` is accepted (LSP).
@@ -60,11 +61,13 @@ results = images.transform(Embed(clip)).search(query_vec, k=20).to_list()
# results[0].similarity → 0.93
# Chainable with other filters
-results = images.transform(Embed(clip)) \
- .search(query_vec, k=50) \
- .after(one_hour_ago) \
- .near(kitchen_pose, 5.0) \
+results = (
+ images.transform(Embed(clip))
+ .search(query_vec, k=50)
+ .after(one_hour_ago)
+ .near(kitchen_pose, 5.0)
.to_list()
+)
```
## Backend Handles Storage Strategy
@@ -87,8 +90,8 @@ When a downstream transform replaces `.data` (e.g., Image → Detection), use te
```python
detection = detections.first()
-detection.data # → Detection
-detection.ts # → timestamp preserved by derive()
+detection.data # → Detection
+detection.ts # → timestamp preserved by derive()
# Get the source image via temporal join
source_image = images.at(detection.ts).first()
@@ -102,12 +105,10 @@ source_image = images.at(detection.ts).first()
unified = store.stream("clip_unified")
for obs in images.transform(Embed(clip.vision)):
- unified.append(obs.data, ts=obs.ts,
- tags={"modality": "image"}, embedding=obs.embedding)
+ unified.append(obs.data, ts=obs.ts, tags={"modality": "image"}, embedding=obs.embedding)
for obs in logs.transform(Embed(clip.text)):
- unified.append(obs.data, ts=obs.ts,
- tags={"modality": "text"}, embedding=obs.embedding)
+ unified.append(obs.data, ts=obs.ts, tags={"modality": "text"}, embedding=obs.embedding)
results = unified.search(query_vec, k=20).to_list()
# results[i].tags["modality"] tells you what it is
@@ -120,11 +121,12 @@ results = unified.search(query_vec, k=20).to_list()
```python
smoke_query = clip.embed_text("smoke or fire")
-detections = images.transform(Embed(clip)) \
- .search(smoke_query, k=100) \
- .transform(ExpensiveVLMDetector())
+detections = (
+ images.transform(Embed(clip)).search(smoke_query, k=100).transform(ExpensiveVLMDetector())
+)
# VLM only runs on 100 most promising frames
+
# Smart transformer can use embedding directly
class SmartDetector(Transformer[Image, Detection]):
def __call__(self, upstream: Iterator[EmbeddedObservation[Image]]) -> ...:
diff --git a/dimos/memory2/intro.md b/dimos/memory2/intro.md
index 1b2153908b..091238f12c 100644
--- a/dimos/memory2/intro.md
+++ b/dimos/memory2/intro.md
@@ -86,6 +86,7 @@ Live queries backfill existing matches, then emit new ones as they arrive:
```python session=memory ansi=false
import time
+
def emit_some_logs():
last_ts = logs.last().ts
logs.append("Heartbeat ok", ts=last_ts + 1, pose=(3.0, 1.5, 0.0), tags={"level": "info"})
@@ -102,7 +103,6 @@ with logs.tags(level="error").live() as errors:
sub = errors.subscribe(lambda obs: print(f"{obs.ts} - {obs.data}"))
emit_some_logs()
sub.dispose()
-
```
@@ -145,7 +145,9 @@ from dimos.memory2.embed import EmbedText
clip = CLIPModel()
-for obs in logs.transform(EmbedText(clip)).search(clip.embed_text("hardware problem"), k=3).to_list():
+for obs in (
+ logs.transform(EmbedText(clip)).search(clip.embed_text("hardware problem"), k=3).to_list()
+):
print(f"{obs.similarity:.3f} {obs.data}")
```
@@ -160,12 +162,7 @@ The embedded stream above was ephemeral — built on the fly for one query. To p
```python skip
embedded_logs = store.stream("embedded_logs", str)
-handle = (
- logs.live()
- .transform(EmbedText(clip))
- .save(embedded_logs)
- .drain_thread()
-)
+handle = logs.live().transform(EmbedText(clip)).save(embedded_logs).drain_thread()
# every new log is now automatically embedded and stored
# embedded_logs.search(query, k=5).to_list() to query at any time
diff --git a/dimos/memory2/module.py b/dimos/memory2/module.py
index b8289ebd12..d09a2681dd 100644
--- a/dimos/memory2/module.py
+++ b/dimos/memory2/module.py
@@ -65,7 +65,7 @@ def stream_to_port(stream: Stream[T], out: Out[T]) -> DisposableBase:
"""
def _on_error(e: Exception) -> None:
- logger.error("stream_to_port() pipeline error: %s", e, exc_info=True)
+ logger.error("stream_to_port() pipeline error: %s", e)
return stream.observable().subscribe(
on_next=lambda obs: out.publish(obs.data),
diff --git a/dimos/memory2/notes.md b/dimos/memory2/notes.md
index 8a9a05c30c..5d9e11dcd2 100644
--- a/dimos/memory2/notes.md
+++ b/dimos/memory2/notes.md
@@ -1,8 +1,8 @@
```python
with db() as db:
- with db.stream as image:
- image.put(...)
+ with db.stream as image:
+ image.put(...)
```
DB specifies some general configuration for all sessions/streams.
diff --git a/dimos/memory2/store/README.md b/dimos/memory2/store/README.md
index 4766c24998..e8e1886f8e 100644
--- a/dimos/memory2/store/README.md
+++ b/dimos/memory2/store/README.md
@@ -42,6 +42,7 @@ The **Backend** is the glue — on `append()` it encodes the payload, inserts me
```python
from dimos.memory2.observationstore.base import ObservationStore
+
class MyObservationStore(ObservationStore[T]):
def __init__(self, name: str, **kwargs: Any) -> None:
super().__init__(**kwargs)
@@ -87,6 +88,7 @@ from dimos.memory2.backend import Backend
from dimos.memory2.codecs.base import codec_for
from dimos.memory2.store.base import Store
+
class MyStore(Store):
def _create_backend(
self, name: str, payload_type: type | None = None, **config: Any
@@ -122,6 +124,7 @@ def my_store() -> Iterator[MyStore]:
with MyStore() as store:
yield store
+
@pytest.fixture(params=["memory_store", "sqlite_store", "my_store"])
def session(request):
return request.getfixturevalue(request.param)
@@ -149,7 +152,8 @@ def query(self, q: StreamQuery) -> Iterator[Observation[T]]:
# Delegate remaining operations to Python
remaining = StreamQuery(
search_text=q.search_text,
- offset_val=q.offset_val, limit_val=q.limit_val,
+ offset_val=q.offset_val,
+ limit_val=q.limit_val,
)
return remaining.apply(iter(rows))
```
diff --git a/dimos/memory2/stream.py b/dimos/memory2/stream.py
index 1ed4651398..61ebe28cfc 100644
--- a/dimos/memory2/stream.py
+++ b/dimos/memory2/stream.py
@@ -614,7 +614,7 @@ def chain(self, other: Stream[R, Any]) -> Stream[R]:
store.stream("lidar").live().chain(pipeline)
"""
ops: list[tuple[Transformer[Any, Any] | None, StreamQuery]] = []
- current: Stream[Any, Any] | None | Any = other
+ current: Stream[Any, Any] | Any | None = other
found_root = False
while isinstance(current, Stream):
ops.append((current._transform, current._query))
diff --git a/dimos/memory2/streaming.md b/dimos/memory2/streaming.md
index 3ddae6d438..980cc35b11 100644
--- a/dimos/memory2/streaming.md
+++ b/dimos/memory2/streaming.md
@@ -92,13 +92,13 @@ stream.live().transform(process).drain()
**One-shot** — get a single observation:
```python
-obs = stream.live().transform(xf).first() # blocks until one arrives
-has_data = stream.exists() # quick check
+obs = stream.live().transform(xf).first() # blocks until one arrives
+has_data = stream.exists() # quick check
```
**Bounded live** — collect a fixed number from a live stream:
```python
-batch = stream.live().limit(100).to_list() # OK — limit makes it finite
+batch = stream.live().limit(100).to_list() # OK — limit makes it finite
```
### Error summary
diff --git a/dimos/memory2/type/filter.py b/dimos/memory2/type/filter.py
index 1250c4c31f..4a83ea7a5c 100644
--- a/dimos/memory2/type/filter.py
+++ b/dimos/memory2/type/filter.py
@@ -184,7 +184,7 @@ def apply(
key = self.order_field
desc = self.order_desc
items = sorted(
- list(it),
+ it,
key=lambda obs: getattr(obs, key) if getattr(obs, key, None) is not None else 0,
reverse=desc,
)
diff --git a/dimos/memory2/utils/test_progress.py b/dimos/memory2/utils/test_progress.py
index 309ca71408..62a271b1e5 100644
--- a/dimos/memory2/utils/test_progress.py
+++ b/dimos/memory2/utils/test_progress.py
@@ -43,10 +43,9 @@ def test_early_exit_finalizes_partial_bar(capsys: pytest.CaptureFixture[str]) ->
def test_cleanup_on_exception(capsys: pytest.CaptureFixture[str]) -> None:
- with pytest.raises(RuntimeError, match="boom"):
- with progress(10, "crashy") as bar:
- bar(_obs(0.0))
- raise RuntimeError("boom")
+ with pytest.raises(RuntimeError, match="boom"), progress(10, "crashy") as bar:
+ bar(_obs(0.0))
+ raise RuntimeError("boom")
out = capsys.readouterr().out
assert out.count("crashy 10% [1/10]") == 1
diff --git a/dimos/memory2/vis/plot/rerun.py b/dimos/memory2/vis/plot/rerun.py
index e5ce9365ab..43d657eef5 100644
--- a/dimos/memory2/vis/plot/rerun.py
+++ b/dimos/memory2/vis/plot/rerun.py
@@ -24,4 +24,3 @@
def render(plot: Plot, app_id: str = "plot", spawn: bool = True) -> None:
"""Placeholder — does nothing. Real rerun output for Plot is future work."""
- pass
diff --git a/dimos/memory2/vis/space/space.py b/dimos/memory2/vis/space/space.py
index cf7d8be0b3..d0a01ed655 100644
--- a/dimos/memory2/vis/space/space.py
+++ b/dimos/memory2/vis/space/space.py
@@ -112,17 +112,13 @@ def add(self, element: Any, **kwargs: Any) -> Space:
def add_dimos_msg(self, msg: DimosMsg, **kwargs: Any) -> None:
"""Dispatch a DimosMsg to its default element type."""
- if isinstance(msg, PoseStamped):
- self._elements.append(Pose(msg=msg, **kwargs))
- elif isinstance(msg, GeoPose):
+ if isinstance(msg, (PoseStamped, GeoPose)):
self._elements.append(Pose(msg=msg, **kwargs))
elif isinstance(msg, GeoPoint):
self._elements.append(Point(msg=msg, **kwargs))
elif isinstance(msg, NavPath):
self._elements.append(Polyline(msg=msg, **kwargs))
- elif isinstance(msg, OccupancyGrid):
- self._elements.append(msg)
- elif isinstance(msg, PointCloud2):
+ elif isinstance(msg, (OccupancyGrid, PointCloud2)):
self._elements.append(msg)
elif isinstance(msg, Detection3D):
self._elements.append(
diff --git a/dimos/memory2/vis/space/svg.py b/dimos/memory2/vis/space/svg.py
index f95119973b..6ce52c10ad 100644
--- a/dimos/memory2/vis/space/svg.py
+++ b/dimos/memory2/vis/space/svg.py
@@ -174,9 +174,11 @@ def _render_box3d(el: Box3D, b: Bounds) -> str:
b.include(x + w, y + h)
stroke, alpha = _style(el)
parts = [
- f''
+ (
+ f''
+ )
]
if el.label:
font_size = max(h * 0.3, 0.2)
@@ -209,8 +211,10 @@ def _render_camera(el: Camera, b: Bounds) -> str:
b.include(px, py)
parts = [
- f''
+ (
+ f''
+ )
]
else:
r = 0.15
@@ -329,10 +333,12 @@ def render(
svg_h = width_px * aspect
parts: list[str] = [
- f'