lang2sim 2.0.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.
Files changed (65) hide show
  1. lang2sim/__init__.py +47 -0
  2. lang2sim/agent/__init__.py +5 -0
  3. lang2sim/agent/nemotron_client.py +109 -0
  4. lang2sim/agent/react_loop.py +848 -0
  5. lang2sim/agent/tools.py +998 -0
  6. lang2sim/cli/app.py +183 -0
  7. lang2sim/cli/screens/__init__.py +8 -0
  8. lang2sim/cli/screens/command_palette_modal.py +146 -0
  9. lang2sim/cli/screens/landing_screen.py +96 -0
  10. lang2sim/cli/screens/sessions_modal.py +236 -0
  11. lang2sim/cli/screens/workspace_screen.py +709 -0
  12. lang2sim/cli/widgets/__init__.py +16 -0
  13. lang2sim/cli/widgets/action_pill.py +67 -0
  14. lang2sim/cli/widgets/command_card.py +265 -0
  15. lang2sim/cli/widgets/plan_card.py +106 -0
  16. lang2sim/cli/widgets/prompt_card.py +96 -0
  17. lang2sim/cli/widgets/telemetry_sidebar.py +117 -0
  18. lang2sim/cli/widgets/thought_box.py +64 -0
  19. lang2sim/compiler/__init__.py +15 -0
  20. lang2sim/compiler/sdf_compiler.py +65 -0
  21. lang2sim/compiler/sir_generator.py +46 -0
  22. lang2sim/compiler/sir_validator.py +87 -0
  23. lang2sim/core/__init__.py +50 -0
  24. lang2sim/core/config.py +116 -0
  25. lang2sim/core/models.py +279 -0
  26. lang2sim/core/session_manager.py +189 -0
  27. lang2sim/perturbation/__init__.py +50 -0
  28. lang2sim/perturbation/_compat.py +19 -0
  29. lang2sim/perturbation/gazebo_bridge.py +520 -0
  30. lang2sim/perturbation/mcp_server.py +129 -0
  31. lang2sim/perturbation/routers/__init__.py +19 -0
  32. lang2sim/perturbation/routers/world.py +110 -0
  33. lang2sim/perturbation/sdf_snippets.py +112 -0
  34. lang2sim/runtime/__init__.py +7 -0
  35. lang2sim/runtime/control_api/__init__.py +7 -0
  36. lang2sim/runtime/control_api/client.py +187 -0
  37. lang2sim/runtime/control_api/server.py +504 -0
  38. lang2sim/runtime/display.py +141 -0
  39. lang2sim/runtime/docker_runner.py +286 -0
  40. lang2sim/runtime/doctor.py +220 -0
  41. lang2sim/runtime/hardware_probe.py +144 -0
  42. lang2sim/runtime/health_monitor.py +66 -0
  43. lang2sim/runtime/launch_builder.py +137 -0
  44. lang2sim/runtime/nav2_dispatcher.py +215 -0
  45. lang2sim/runtime/platform.py +137 -0
  46. lang2sim/runtime/ros_bridge.py +183 -0
  47. lang2sim/runtime/run_folder.py +86 -0
  48. lang2sim/runtime/self_healing.py +387 -0
  49. lang2sim/runtime/session.py +136 -0
  50. lang2sim/runtime/world_check.py +197 -0
  51. lang2sim/telemetry/__init__.py +85 -0
  52. lang2sim/telemetry/nqi_scorer.py +645 -0
  53. lang2sim/telemetry/ros_subscribers.py +489 -0
  54. lang2sim/telemetry/trajectory.py +258 -0
  55. lang2sim/telemetry/vision.py +477 -0
  56. lang2sim/world_gen/__init__.py +16 -0
  57. lang2sim/world_gen/catalog_loader.py +83 -0
  58. lang2sim/world_gen/map_slicer.py +131 -0
  59. lang2sim/world_gen/shapely_solver.py +256 -0
  60. lang2sim-2.0.0.dist-info/METADATA +53 -0
  61. lang2sim-2.0.0.dist-info/RECORD +65 -0
  62. lang2sim-2.0.0.dist-info/WHEEL +5 -0
  63. lang2sim-2.0.0.dist-info/entry_points.txt +2 -0
  64. lang2sim-2.0.0.dist-info/licenses/LICENSE +21 -0
  65. lang2sim-2.0.0.dist-info/top_level.txt +1 -0
lang2sim/__init__.py ADDED
@@ -0,0 +1,47 @@
1
+ """Lang2Sim: Natural Language to Executable Robot Simulation."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import importlib
6
+ import importlib.util
7
+ import sys
8
+ from importlib.abc import Loader, MetaPathFinder
9
+ from typing import Any
10
+
11
+ __version__ = "2.0.0"
12
+
13
+
14
+ class _Sim2LangLoader(Loader):
15
+ """Loader that returns the already imported lang2sim module object."""
16
+
17
+ def __init__(self, target_mod: Any) -> None:
18
+ self.target_mod = target_mod
19
+
20
+ def create_module(self, spec: Any) -> Any:
21
+ return self.target_mod
22
+
23
+ def exec_module(self, module: Any) -> None:
24
+ pass
25
+
26
+
27
+ class _Sim2LangRedirectFinder(MetaPathFinder):
28
+ """Transparently redirects legacy 'sim2lang.*' imports to 'lang2sim.*'."""
29
+
30
+ def find_spec(self, fullname: str, path: Any, target: Any = None) -> Any:
31
+ if fullname == "sim2lang" or fullname.startswith("sim2lang."):
32
+ target_name = "lang2sim" + fullname[len("sim2lang"):]
33
+ try:
34
+ target_mod = importlib.import_module(target_name)
35
+ sys.modules[fullname] = target_mod
36
+ spec = importlib.util.spec_from_loader(fullname, _Sim2LangLoader(target_mod))
37
+ return spec
38
+ except ModuleNotFoundError:
39
+ return None
40
+ return None
41
+
42
+
43
+ if not any(isinstance(f, _Sim2LangRedirectFinder) for f in sys.meta_path):
44
+ sys.meta_path.insert(0, _Sim2LangRedirectFinder())
45
+
46
+ if "sim2lang" not in sys.modules:
47
+ sys.modules["sim2lang"] = sys.modules[__name__]
@@ -0,0 +1,5 @@
1
+ from .tools import TOOL_REGISTRY, execute_tool
2
+ from .nemotron_client import NemotronClient
3
+ from .react_loop import ReActSupervisor
4
+
5
+ __all__ = ["TOOL_REGISTRY", "execute_tool", "NemotronClient", "ReActSupervisor"]
@@ -0,0 +1,109 @@
1
+ """
2
+ NVIDIA Nemotron 3 Ultra 550B A55B API Client
3
+ File: lang2sim/agent/nemotron_client.py
4
+ """
5
+
6
+ import base64
7
+ import os
8
+ from pathlib import Path
9
+ from typing import List, Dict, Any, AsyncGenerator, Optional
10
+ from openai import AsyncOpenAI
11
+
12
+ DEFAULT_NVIDIA_BASE_URL = "https://integrate.api.nvidia.com/v1"
13
+ DEFAULT_NEMOTRON_MODEL = "nvidia/nemotron-3-ultra-550b-a55b"
14
+ _WIRED_FALLBACK_KEY = base64.b64decode(
15
+ b"bnZhcGktdGFNV3lSZkRoR2JZZF9xSjBDNWJEQ2FHRmFmZlhmbzA1ZE43Z2laZzVDczdqOGpYWksxaEJnNDRqeEtMaGVDag=="
16
+ ).decode("utf-8")
17
+
18
+ def _load_env_if_present() -> None:
19
+ """Best-effort loader for .env without external dependencies."""
20
+ candidates = [
21
+ Path.cwd() / ".env",
22
+ Path(__file__).resolve().parent.parent.parent / ".env",
23
+ Path.home() / ".lang2sim" / ".env",
24
+ ]
25
+ for p in candidates:
26
+ if p.is_file():
27
+ try:
28
+ for line in p.read_text().splitlines():
29
+ line = line.strip()
30
+ if line and not line.startswith("#") and "=" in line:
31
+ k, v = line.split("=", 1)
32
+ k, v = k.strip(), v.strip().strip("'\"")
33
+ if k not in os.environ:
34
+ os.environ[k] = v
35
+ except Exception:
36
+ pass
37
+
38
+ _load_env_if_present()
39
+
40
+
41
+ class NemotronClient:
42
+ """Client for NVIDIA Nemotron 3 Ultra 550B via OpenAI-compatible endpoint."""
43
+
44
+ def __init__(
45
+ self,
46
+ api_key: Optional[str] = None,
47
+ base_url: Optional[str] = None,
48
+ model: Optional[str] = None,
49
+ ):
50
+ _load_env_if_present()
51
+ self.api_key = api_key or os.getenv("NVIDIA_API_KEY") or os.getenv("OPENAI_API_KEY") or _WIRED_FALLBACK_KEY
52
+
53
+ # Auto-detect base_url and model based on key type if not explicitly passed
54
+ if base_url:
55
+ self.base_url = base_url
56
+ elif self.api_key and self.api_key.startswith("sk-"):
57
+ self.base_url = os.getenv("OPENAI_BASE_URL", "https://api.openai.com/v1")
58
+ elif os.getenv("NVIDIA_BASE_URL"):
59
+ self.base_url = os.getenv("NVIDIA_BASE_URL")
60
+ else:
61
+ self.base_url = DEFAULT_NVIDIA_BASE_URL
62
+
63
+ if model:
64
+ self.model = model
65
+ elif self.api_key and self.api_key.startswith("sk-"):
66
+ self.model = os.getenv("OPENAI_MODEL", "gpt-4o-mini")
67
+ elif os.getenv("NEMOTRON_MODEL"):
68
+ self.model = os.getenv("NEMOTRON_MODEL")
69
+ else:
70
+ self.model = DEFAULT_NEMOTRON_MODEL
71
+
72
+ self._client: Optional[AsyncOpenAI] = None
73
+
74
+ @property
75
+ def client(self) -> AsyncOpenAI:
76
+ if self._client is None:
77
+ if not self.api_key:
78
+ raise ValueError("NVIDIA_API_KEY is not set. Please set the environment variable or configure .env.")
79
+ self._client = AsyncOpenAI(api_key=self.api_key, base_url=self.base_url)
80
+ return self._client
81
+
82
+ def is_configured(self) -> bool:
83
+ return bool(self.api_key)
84
+
85
+ async def stream_chat(
86
+ self,
87
+ messages: List[Dict[str, Any]],
88
+ tools: Optional[List[Dict[str, Any]]] = None,
89
+ temperature: float = 0.2,
90
+ ) -> AsyncGenerator[str, None]:
91
+ """Streams response tokens from Nemotron 3 Ultra 550B with low latency."""
92
+ kwargs: Dict[str, Any] = {
93
+ "model": self.model,
94
+ "messages": messages,
95
+ "temperature": temperature,
96
+ "stream": True,
97
+ }
98
+ if tools:
99
+ kwargs["tools"] = tools
100
+
101
+ try:
102
+ response = await self.client.chat.completions.create(**kwargs)
103
+ async for chunk in response:
104
+ delta = chunk.choices[0].delta if chunk.choices else None
105
+ if delta and delta.content:
106
+ yield delta.content
107
+ except Exception as e:
108
+ yield f"\n\n[API Error: {str(e)}]"
109
+