physicalai-studio-plugin 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,28 @@
1
+ """Public API for the Physical AI Studio plugin."""
2
+
3
+ from .assets import RobotAsset
4
+ from .catalog import (
5
+ BuildRobotCallable,
6
+ CatalogRobot,
7
+ PayloadContainer,
8
+ RobotAdapterOptions,
9
+ RobotCatalogDefinition,
10
+ RobotCatalogRegistry,
11
+ )
12
+ from .factory import CatalogRobotFactory
13
+ from .probe import PortScanner, RobotProbe
14
+ from .schemas import SerialPortInfo
15
+
16
+ __all__ = [
17
+ "BuildRobotCallable",
18
+ "CatalogRobot",
19
+ "CatalogRobotFactory",
20
+ "PayloadContainer",
21
+ "PortScanner",
22
+ "RobotAdapterOptions",
23
+ "RobotAsset",
24
+ "RobotCatalogDefinition",
25
+ "RobotCatalogRegistry",
26
+ "RobotProbe",
27
+ "SerialPortInfo",
28
+ ]
@@ -0,0 +1,20 @@
1
+ """Data structures describing robot visualization assets."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from dataclasses import dataclass
6
+ from typing import TYPE_CHECKING
7
+
8
+ if TYPE_CHECKING:
9
+ from collections.abc import Callable
10
+ from pathlib import Path
11
+
12
+
13
+ @dataclass(frozen=True)
14
+ class RobotAsset:
15
+ """Filesystem configuration for a robot's visual model and ROS packages."""
16
+
17
+ urdf_relative_path: Path
18
+ packages: dict[str, Path]
19
+ joint_map: dict[str, list[str]]
20
+ root_resolver: Callable[[], Path] | None = None
@@ -0,0 +1,71 @@
1
+ """Core plugin catalog protocol and definition types."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from collections.abc import Awaitable, Callable
6
+ from dataclasses import dataclass, field
7
+ from typing import TYPE_CHECKING, Any, Generic, Literal, Protocol, TypeVar
8
+
9
+ from physicalai.robot.interface import Robot as PhysicalAIRobot
10
+ from pydantic import BaseModel
11
+
12
+ from .factory import CatalogRobotFactory
13
+
14
+ if TYPE_CHECKING:
15
+ from .assets import RobotAsset
16
+ from .probe import RobotProbe
17
+
18
+
19
+ @dataclass(frozen=True)
20
+ class RobotAdapterOptions:
21
+ """Controls adapter behavior for velocity, timing, and effort handling."""
22
+
23
+ include_velocities: bool = False
24
+ goal_time_scale: float = 1.0
25
+ external_effort_gain: float | None = 0.1
26
+
27
+
28
+ _PayloadT = TypeVar("_PayloadT", bound=BaseModel)
29
+ _PayloadModelT = type[_PayloadT]
30
+
31
+
32
+ class PayloadContainer(Protocol[_PayloadT]):
33
+ """Object with a typed ``payload`` attribute."""
34
+
35
+ payload: _PayloadT
36
+
37
+
38
+ class CatalogRobot(PayloadContainer[_PayloadT], Protocol[_PayloadT]):
39
+ """Typed robot descriptor passed to catalog robot builders."""
40
+
41
+ type: str
42
+
43
+
44
+ _RobotT = TypeVar("_RobotT", bound=CatalogRobot[Any])
45
+ _FactoryT = TypeVar("_FactoryT", bound=CatalogRobotFactory)
46
+
47
+
48
+ BuildRobotCallable = Callable[[_RobotT, _FactoryT], Awaitable[PhysicalAIRobot]]
49
+
50
+
51
+ @dataclass
52
+ class RobotCatalogDefinition(Generic[_PayloadT]):
53
+ """Complete definition of a plugin robot type for Studio registration."""
54
+
55
+ type: str
56
+ display_name: str
57
+ role: Literal["follower", "leader"]
58
+ robot_builder: BuildRobotCallable | None = None
59
+ robot_payload: _PayloadModelT | None = None
60
+ asset: RobotAsset | None = None
61
+
62
+ adapter_options: RobotAdapterOptions = field(default_factory=RobotAdapterOptions)
63
+ probe: RobotProbe[_PayloadT] | None = None
64
+
65
+
66
+ class RobotCatalogRegistry(Protocol):
67
+ """Registry interface used by plugin entry points to add robot definitions."""
68
+
69
+ def register_robot(self, definition: RobotCatalogDefinition) -> None:
70
+ """Register one robot catalog definition with Studio."""
71
+ ...
@@ -0,0 +1,19 @@
1
+ """Factory protocol exposed to plugin robot-builder callables."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import TYPE_CHECKING, Protocol
6
+
7
+ if TYPE_CHECKING:
8
+ from .schemas import SerialPortInfo
9
+
10
+
11
+ class CatalogRobotFactory(Protocol):
12
+ """Factory protocol provided by Studio to robot builders.
13
+
14
+ Plugin ``robot_builder`` callables receive an instance of this protocol
15
+ so they can resolve serial ports at build time.
16
+ """
17
+
18
+ async def find_port(self, port_info: SerialPortInfo) -> str | None:
19
+ """Return the resolved connection port, if present."""
@@ -0,0 +1,56 @@
1
+ """Probe and scanner protocols used by plugin robot integrations."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import TYPE_CHECKING, Protocol, TypeVar, runtime_checkable
6
+
7
+ from pydantic import BaseModel
8
+
9
+ if TYPE_CHECKING:
10
+ from .schemas import SerialPortInfo
11
+
12
+ _PayloadT_contra = TypeVar("_PayloadT_contra", bound=BaseModel, contravariant=True)
13
+
14
+
15
+ class PortScanner(Protocol):
16
+ """Duck-type for serial port scanners (e.g. RobotConnectionManager).
17
+
18
+ Used by RobotProbe to accept scan results without coupling to a specific
19
+ manager implementation.
20
+ """
21
+
22
+ async def find_robots(self) -> None:
23
+ """Refresh discovered robot connections."""
24
+
25
+ @property
26
+ def robots(self) -> list[SerialPortInfo]:
27
+ """Return currently discovered robot connections."""
28
+
29
+
30
+ @runtime_checkable
31
+ class RobotProbe(Protocol[_PayloadT_contra]):
32
+ """Hardware interaction interface for a robot type.
33
+
34
+ Each built-in or plugin-provided robot type implements this protocol
35
+ to encapsulate device discovery, visual identification, and online
36
+ status checking. The type parameter ``_PayloadT`` is the robot's
37
+ payload model (a pydantic ``BaseModel`` subclass).
38
+ """
39
+
40
+ async def discover(self, manager: PortScanner) -> list[SerialPortInfo]:
41
+ """Discover robots and return current connection metadata."""
42
+
43
+ async def identify(
44
+ self,
45
+ payload: _PayloadT_contra,
46
+ manager: PortScanner | None,
47
+ joint: str | None = None,
48
+ ) -> None:
49
+ """Trigger physical identification behavior for a robot."""
50
+
51
+ async def is_online(
52
+ self,
53
+ payload: _PayloadT_contra,
54
+ manager: PortScanner | None = None,
55
+ ) -> bool:
56
+ """Return whether the robot appears online."""
@@ -0,0 +1,12 @@
1
+ """Pydantic schemas shared by plugin protocols."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from pydantic import BaseModel
6
+
7
+
8
+ class SerialPortInfo(BaseModel):
9
+ """Connection metadata for a discovered serial or network robot."""
10
+
11
+ connection_string: str | None
12
+ serial_number: str | None
@@ -0,0 +1,7 @@
1
+ Metadata-Version: 2.4
2
+ Name: physicalai-studio-plugin
3
+ Version: 0.1.0
4
+ Summary: Plugin SDK for Physical AI Studio — types and protocols for building robot catalog plugins
5
+ Requires-Python: >=3.12
6
+ Requires-Dist: physicalai
7
+ Requires-Dist: pydantic>=2.12
@@ -0,0 +1,9 @@
1
+ physicalai_studio_plugin/__init__.py,sha256=HbK5lwiMmM9hihsBJla9oHsKAxsAapnUTgzneOgqfjc,646
2
+ physicalai_studio_plugin/assets.py,sha256=GAGIE00TgQ7wfEydF8dOVaNKwgRKlwQUrPhGwu_5ISE,526
3
+ physicalai_studio_plugin/catalog.py,sha256=r8qnd3VMfOJoNK86VN7rUa7QggT4v8HbiK59y0rC7Pg,2056
4
+ physicalai_studio_plugin/factory.py,sha256=Y8UWSmBwYNnXv2fJJ2K_KmMynnqDLZURf5oeCefns5s,579
5
+ physicalai_studio_plugin/probe.py,sha256=m_c6BpOYb-qbseIg38g3g-sSFWRSZbxQjmWLnREDtB8,1751
6
+ physicalai_studio_plugin/schemas.py,sha256=7kjqR3xak_70OlZM4Z8P_mWFeDiVGMqhSbHqs0ow7Kc,291
7
+ physicalai_studio_plugin-0.1.0.dist-info/METADATA,sha256=AkoCAwbD-12f5ary_PDSGPf9ATMfZmPrKWWzmuAiyNA,250
8
+ physicalai_studio_plugin-0.1.0.dist-info/WHEEL,sha256=lCkmxWfQsSc9CfIClYeavTdQeEX2toPqufh9gI35EQA,87
9
+ physicalai_studio_plugin-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.31.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any