Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
e08a311
first shot at breaking up the g1 blueprints
jeff-hykin Feb 6, 2026
4f38e8f
the great unitree renaming
jeff-hykin Feb 7, 2026
d1e5de4
fixup imports for pickle, and docs
jeff-hykin Feb 7, 2026
9618a01
break up unitree go2 blueprints
jeff-hykin Feb 7, 2026
2129157
fix and switch to absolute pathed imports
jeff-hykin Feb 7, 2026
8136806
-
jeff-hykin Feb 7, 2026
05287b2
revert
jeff-hykin Feb 7, 2026
dbfb6d6
minor test fix
jeff-hykin Feb 7, 2026
0d28205
Merge branch 'jeff/fix_dirs' of github.com:dimensionalOS/dimos into j…
jeff-hykin Feb 7, 2026
829412b
make blueprint imports lazy
jeff-hykin Feb 7, 2026
c10a81c
Merge branch 'dev' into jeff/fix_dirs
jeff-hykin Feb 7, 2026
e992482
make all __init__ imports lazy
jeff-hykin Feb 7, 2026
0d8dd3f
mark cuda required tests
jeff-hykin Feb 8, 2026
9f76c6c
add hook filter for cuda
jeff-hykin Feb 8, 2026
1a530a1
add to toml
jeff-hykin Feb 8, 2026
a1f5352
fix var name
jeff-hykin Feb 8, 2026
5845f8d
Merge branch 'jeff/cuda_tests_marker' into jeff/fix_dirs
jeff-hykin Feb 8, 2026
a4e8a45
Merge branch 'dev' into jeff/fix_dirs
jeff-hykin Feb 8, 2026
e0aba66
make dimos --help fast
jeff-hykin Feb 8, 2026
290253a
name issue
jeff-hykin Feb 8, 2026
ba6e29a
CI code cleanup
jeff-hykin Feb 8, 2026
36c69bb
mypy stuff
jeff-hykin Feb 8, 2026
28271c1
remove dead/broken code (revealed by mypy)
jeff-hykin Feb 8, 2026
fe5b6a1
fix name (mypy revealed error)
jeff-hykin Feb 8, 2026
3614dca
another name fix
jeff-hykin Feb 8, 2026
72a9542
mypy fixes
jeff-hykin Feb 8, 2026
40f03ba
correct g1 blueprint name
jeff-hykin Feb 8, 2026
364ad8f
fix rpc typing
jeff-hykin Feb 8, 2026
e9891f8
undo the ignores for rpc calls
jeff-hykin Feb 8, 2026
49e174b
-
jeff-hykin Feb 8, 2026
52da9c7
mark test_tool_call_implicit_detections as tofix because it currently…
jeff-hykin Feb 8, 2026
f11ab9b
Merge branch 'jeff/fix_dirs' of github.com:dimensionalOS/dimos into j…
jeff-hykin Feb 8, 2026
6d43c42
undo unnecessary mypy changes
jeff-hykin Feb 8, 2026
1e8930e
fixup readme with naming changes
jeff-hykin Feb 8, 2026
c733587
fix
jeff-hykin Feb 8, 2026
5e653a8
revert
jeff-hykin Feb 8, 2026
9bf224d
use direct imports (for both performance and type hinting)
jeff-hykin Feb 8, 2026
d5575c0
fixup typing
jeff-hykin Feb 8, 2026
44ba48b
fix test
jeff-hykin Feb 8, 2026
dbe419d
fix test
jeff-hykin Feb 8, 2026
565b8a7
mypy
jeff-hykin Feb 9, 2026
1f685dc
more mypy
jeff-hykin Feb 9, 2026
300e6d5
Merge branch 'dev' into jeff/fix_dirs
jeff-hykin Feb 10, 2026
beb93f1
-
jeff-hykin Feb 10, 2026
dd552d0
pin langchain
paul-nechifor Feb 11, 2026
925e4aa
Merge branch 'jeff/fix_dirs' of github.com:dimensionalOS/dimos into j…
jeff-hykin Feb 11, 2026
1dd7961
Merge branch 'dev' into jeff/fix_dirs
jeff-hykin Feb 11, 2026
302877c
fix for CI
jeff-hykin Feb 11, 2026
7488427
-
jeff-hykin Feb 11, 2026
adffef3
Merge branch 'dev' into jeff/fix_dirs
jeff-hykin Feb 12, 2026
406bf99
fix mypy
jeff-hykin Feb 12, 2026
1833026
all_blueprints update
jeff-hykin Feb 12, 2026
bf1e3cb
fix mypy
jeff-hykin Feb 12, 2026
694d1b3
-
jeff-hykin Feb 12, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 6 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -148,11 +148,9 @@ Modules are subsystems on a robot that operate autonomously and communicate with

```py
import threading, time, numpy as np
from dimos.core import In, Module, Out, rpc
from dimos.core.blueprints import autoconnect
from dimos.core import In, Module, Out, rpc, autoconnect
from dimos.msgs.geometry_msgs import Twist
from dimos.msgs.sensor_msgs import Image
from dimos.msgs.sensor_msgs.Image import ImageFormat
from dimos.msgs.sensor_msgs import Image, ImageFormat

class RobotConnection(Module):
cmd_vel: In[Twist]
Expand Down Expand Up @@ -195,10 +193,9 @@ Blueprints can be composed, remapped, and have transports overridden if `autocon

A blueprint example that connects the image stream from a robot to an LLM Agent for reasoning and action execution.
```py
from dimos.core.blueprints import autoconnect
from dimos.core.transport import LCMTransport
from dimos.core import autoconnect, LCMTransport
from dimos.msgs.sensor_msgs import Image
from dimos.robot.unitree.connection.go2 import go2_connection
from dimos.robot.unitree.go2.connection import go2_connection
from dimos.agents.agent import llm_agent

blueprint = autoconnect(
Expand All @@ -207,7 +204,8 @@ blueprint = autoconnect(
).transports({("color_image", Image): LCMTransport("/color_image", Image)})

# Run the blueprint
blueprint.build().loop()
if __name__ == "__main__":
blueprint.build().loop()
Copy link
Member Author

@jeff-hykin jeff-hykin Feb 8, 2026

Choose a reason for hiding this comment

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

without this change, the example code does not work!! (its broken on dev!)

```

# Development
Expand Down
28 changes: 11 additions & 17 deletions dimos/agents/__init__.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,12 @@
from dimos.agents.agent import Agent, deploy
from dimos.agents.spec import AgentSpec
from dimos.agents.vlm_agent import VLMAgent
from dimos.agents.vlm_stream_tester import VlmStreamTester
from dimos.protocol.skill.skill import skill
from dimos.protocol.skill.type import Output, Reducer, Stream
import lazy_loader as lazy

__all__ = [
"Agent",
"AgentSpec",
"Output",
"Reducer",
"Stream",
"VLMAgent",
"VlmStreamTester",
"deploy",
"skill",
]
__getattr__, __dir__, __all__ = lazy.attach(
__name__,
submod_attrs={
"agent": ["Agent", "deploy"],
"spec": ["AgentSpec"],
"vlm_agent": ["VLMAgent"],
"vlm_stream_tester": ["VlmStreamTester"],
"_skill_exports": ["skill", "Output", "Reducer", "Stream"],
},
)
18 changes: 18 additions & 0 deletions dimos/agents/_skill_exports.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Copyright 2026 Dimensional Inc.
Copy link
Member Author

@jeff-hykin jeff-hykin Feb 8, 2026

Choose a reason for hiding this comment

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

This file exists so that an __init__.py can lazy load it. For them to be exported on the same attribute, they need to all be exported from a real file somewhere else.

#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from dimos.protocol.skill.skill import skill
from dimos.protocol.skill.type import Output, Reducer, Stream

__all__ = ["Output", "Reducer", "Stream", "skill"]
2 changes: 1 addition & 1 deletion dimos/agents/skills/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
from dimos.agents.skills.gps_nav_skill import GpsNavSkillContainer
from dimos.agents.skills.navigation import NavigationSkillContainer
from dimos.agents.system_prompt import SYSTEM_PROMPT
from dimos.robot.unitree_webrtc.unitree_skill_container import UnitreeSkillContainer
from dimos.robot.unitree.unitree_skill_container import UnitreeSkillContainer


@pytest.fixture(autouse=True)
Expand Down
2 changes: 1 addition & 1 deletion dimos/agents/skills/person_follow.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ def __init__(

# Use MuJoCo camera intrinsics in simulation mode
if self._global_config.simulation:
from dimos.robot.unitree_webrtc.mujoco_connection import MujocoConnection
from dimos.robot.unitree.mujoco_connection import MujocoConnection

camera_info = MujocoConnection.camera_info_static

Expand Down
28 changes: 25 additions & 3 deletions dimos/agents/spec.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
if TYPE_CHECKING:
from dimos.protocol.skill.skill import SkillContainer

from langchain.chat_models.base import _SUPPORTED_PROVIDERS
from langchain_core.language_models.chat_models import BaseChatModel
from langchain_core.messages import (
AIMessage,
Expand All @@ -45,8 +44,31 @@
logger = setup_logger()


# Dynamically create ModelProvider enum from LangChain's supported providers
_providers = {provider.upper(): provider for provider in _SUPPORTED_PROVIDERS}
# FIXME: I dont see a stable (and dynamic) way to get these, this is only for type-hints and Paul's PR should replace this in a couple of days (this is a stop-gap change to get CI passing)
_providers = [
"ANTHROPIC",
"AZURE_AI",
"AZURE_OPENAI",
"BEDROCK",
"BEDROCK_CONVERSE",
"COHERE",
"DEEPSEEK",
"FIREWORKS",
"GOOGLE_ANTHROPIC_VERTEX",
"GOOGLE_GENAI",
"GOOGLE_VERTEXAI",
"GROQ",
"HUGGINGFACE",
"IBM",
"MISTRALAI",
"NVIDIA",
"OLLAMA",
"OPENAI",
"PERPLEXITY",
"TOGETHER",
"UPSTAGE",
"XAI",
]
Provider = Enum("Provider", _providers, type=str) # type: ignore[misc]


Expand Down
2 changes: 1 addition & 1 deletion dimos/agents/test_mock_agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
from dimos.msgs.geometry_msgs import PoseStamped, Vector3
from dimos.msgs.sensor_msgs import Image, PointCloud2
from dimos.protocol.skill.test_coordinator import SkillContainerTest
from dimos.robot.unitree.connection.go2 import GO2Connection
from dimos.robot.unitree.go2.connection import GO2Connection


@pytest.mark.integration
Expand Down
78 changes: 30 additions & 48 deletions dimos/control/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,52 +49,34 @@
>>> coord.start()
"""

from dimos.control.components import (
HardwareComponent,
HardwareId,
HardwareType,
JointName,
JointState,
make_joints,
)
from dimos.control.coordinator import (
ControlCoordinator,
ControlCoordinatorConfig,
TaskConfig,
control_coordinator,
)
from dimos.control.hardware_interface import ConnectedHardware
from dimos.control.task import (
ControlMode,
ControlTask,
CoordinatorState,
JointCommandOutput,
JointStateSnapshot,
ResourceClaim,
)
from dimos.control.tick_loop import TickLoop
import lazy_loader as lazy

__all__ = [
# Connected hardware
"ConnectedHardware",
# Coordinator
"ControlCoordinator",
"ControlCoordinatorConfig",
"ControlMode",
# Task protocol and types
"ControlTask",
"CoordinatorState",
"HardwareComponent",
"HardwareId",
"HardwareType",
"JointCommandOutput",
"JointName",
"JointState",
"JointStateSnapshot",
"ResourceClaim",
"TaskConfig",
# Tick loop
"TickLoop",
"control_coordinator",
"make_joints",
]
__getattr__, __dir__, __all__ = lazy.attach(
__name__,
submod_attrs={
"components": [
"HardwareComponent",
"HardwareId",
"HardwareType",
"JointName",
"JointState",
"make_joints",
],
"coordinator": [
"ControlCoordinator",
"ControlCoordinatorConfig",
"TaskConfig",
"control_coordinator",
],
"hardware_interface": ["ConnectedHardware"],
"task": [
"ControlMode",
"ControlTask",
"CoordinatorState",
"JointCommandOutput",
"JointStateSnapshot",
"ResourceClaim",
],
"tick_loop": ["TickLoop"],
},
)
5 changes: 3 additions & 2 deletions dimos/control/tasks/cartesian_ik_task.py
Original file line number Diff line number Diff line change
Expand Up @@ -248,10 +248,11 @@ def _get_current_joints(self, state: CoordinatorState) -> NDArray[np.floating[An
if pos is None:
# Fallback to last solution
if self._last_q_solution is not None:
return self._last_q_solution.copy()
result: NDArray[np.floating[Any]] = self._last_q_solution.copy()
return result
return None
positions.append(pos)
return np.array(positions)
return np.array(positions, dtype=np.float64)

def _solve_ik(
self,
Expand Down
76 changes: 30 additions & 46 deletions dimos/core/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,60 +5,41 @@
import time
from typing import TYPE_CHECKING, cast

from dask.distributed import Client, LocalCluster
from rich.console import Console

import dimos.core.colors as colors
from dimos.core.core import rpc
from dimos.core.module import Module, ModuleBase, ModuleConfig, ModuleConfigT
from dimos.core.rpc_client import RPCClient
from dimos.core.stream import In, Out, RemoteIn, RemoteOut, Transport
from dimos.core.transport import (
LCMTransport,
Copy link
Member Author

Choose a reason for hiding this comment

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

we can lazy re-export most of this

SHMTransport,
ZenohTransport,
pLCMTransport,
pSHMTransport,
)
from dimos.protocol.rpc import LCMRPC
from dimos.protocol.rpc.spec import RPCSpec
from dimos.protocol.tf import LCMTF, TF, PubSubTF, TFConfig, TFSpec
from dimos.utils.actor_registry import ActorRegistry
from dimos.utils.logging_config import setup_logger
import lazy_loader as lazy

if TYPE_CHECKING:
# Avoid runtime import to prevent circular import; ruff's TC001 would otherwise move it.
from dask.distributed import LocalCluster

from dimos.core._dask_exports import DimosCluster
from dimos.core.module import Module
from dimos.core.rpc_client import ModuleProxy

logger = setup_logger()

__all__ = [
"LCMRPC",
"LCMTF",
"TF",
"DimosCluster",
"In",
"LCMTransport",
"Module",
"ModuleBase",
"ModuleConfig",
"ModuleConfigT",
"Out",
"PubSubTF",
"RPCSpec",
"RemoteIn",
"RemoteOut",
"SHMTransport",
"TFConfig",
"TFSpec",
"Transport",
"ZenohTransport",
"colors",
"pLCMTransport",
"pSHMTransport",
"rpc",
"start",
]
__getattr__, __dir__, __all__ = lazy.attach(
__name__,
submodules=["colors"],
submod_attrs={
"blueprints": ["autoconnect", "Blueprint"],
"_dask_exports": ["DimosCluster"],
"_protocol_exports": ["LCMRPC", "RPCSpec", "LCMTF", "TF", "PubSubTF", "TFConfig", "TFSpec"],
"module": ["Module", "ModuleBase", "ModuleConfig", "ModuleConfigT"],
"stream": ["In", "Out", "RemoteIn", "RemoteOut", "Transport"],
"transport": [
"LCMTransport",
"SHMTransport",
"ZenohTransport",
"pLCMTransport",
"pSHMTransport",
],
},
)
__all__ += ["DimosCluster", "Module", "rpc", "start", "wait_exit"]


class CudaCleanupPlugin:
Expand Down Expand Up @@ -91,10 +72,10 @@ def teardown(self, worker) -> None: # type: ignore[no-untyped-def]
def patch_actor(actor, cls) -> None: ... # type: ignore[no-untyped-def]


DimosCluster = Client
Copy link
Member Author

Choose a reason for hiding this comment

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

in order to make dask lazy loaded, this needed to be done not-toplevel in an __init__.py file

def patchdask(dask_client: DimosCluster, local_cluster: LocalCluster) -> DimosCluster:
from dimos.core.rpc_client import RPCClient
from dimos.utils.actor_registry import ActorRegistry


def patchdask(dask_client: Client, local_cluster: LocalCluster) -> DimosCluster:
def deploy( # type: ignore[no-untyped-def]
actor_class: type[Module],
*args,
Expand Down Expand Up @@ -129,6 +110,7 @@ def deploy( # type: ignore[no-untyped-def]
def check_worker_memory() -> None:
"""Check memory usage of all workers."""
info = dask_client.scheduler_info()

console = Console()
total_workers = len(info.get("workers", {}))
total_memory_used = 0
Expand Down Expand Up @@ -263,6 +245,8 @@ def start(n: int | None = None, memory_limit: str = "auto") -> DimosCluster:
DimosCluster: A patched Dask client with deploy(), check_worker_memory(), stop(), and close_all() methods
"""

from dask.distributed import Client, LocalCluster

console = Console()
if not n:
n = mp.cpu_count()
Expand Down
17 changes: 17 additions & 0 deletions dimos/core/_dask_exports.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Copyright 2026 Dimensional Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from dask.distributed import Client as DimosCluster

__all__ = ["DimosCluster"]
Loading