-
Notifications
You must be signed in to change notification settings - Fork 805
Create SDK applications and prepare DimOS contributor checkouts #4047
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Draft
Draft
Changes from all commits
Commits
Show all changes
46 commits
Select commit
Hold shift + click to select a range
29cee20
feat(installer): validate onboarding and ship dimup release assets
TomCC7 c8348c3
feat(installer): create pinned SDK applications with shared activation
TomCC7 d7f90f2
feat(cli): diagnose SDK applications without loading the runtime
TomCC7 9e0bf01
test(installer): preserve setup logs when acceptance fails
TomCC7 54e6303
fix(installer): make repository bootstrap usable before release
TomCC7 8973edd
fix(installer): allow application creation on manually prepared platf…
TomCC7 72db54a
Merge branch 'feat/dimup-init' into feat/dimos-doctor
TomCC7 3e0a00e
Merge branch 'fix/sdk-native-builds' into feat/dimup-init
TomCC7 8409a5c
Merge branch 'feat/dimos-doctor' into feat/dimup-release
TomCC7 6c066f4
docs(installer): deliver and explain manually prepared platform support
TomCC7 bc645bc
fix(ci): use LCM for Point-LIO acceptance and correct docs branding
TomCC7 308b5a5
test(cli): cover SDK diagnostics and subprocess failures
TomCC7 dc5cf8b
Merge branch 'feat/dimos-doctor' into feat/dimup-release
TomCC7 e0e357c
Merge branch 'fix/sdk-native-builds' into feat/dimup-init
TomCC7 2849c32
Merge branch 'feat/dimup-init' into feat/dimos-doctor
TomCC7 3dca333
Merge branch 'feat/dimos-doctor' into feat/dimup-release
TomCC7 ef1371d
fix(installer): use managed Python for reproducible SDK environments
TomCC7 e987adf
Merge branch 'feat/dimup-init' into feat/dimos-doctor
TomCC7 60c6fa7
fix(cli): diagnose Python builds without SQLite extension support
TomCC7 f4053be
Merge branch 'feat/dimos-doctor' into feat/dimup-release
TomCC7 85c9cb9
fix(installer): ship managed-Python project creation in bootstrap
TomCC7 ae101ae
Merge branch 'fix/sdk-native-builds' into feat/dimup-init
TomCC7 84ad423
feat(installer): present project creation as clear CLI stages
TomCC7 13977d6
Merge branch 'feat/dimup-init' into feat/dimos-doctor
TomCC7 dabaaaf
Merge branch 'feat/dimos-doctor' into feat/dimup-release
TomCC7 ce5cfb2
Merge branch 'fix/sdk-native-builds' into feat/dimup-init
TomCC7 72cdfcf
Merge branch 'feat/dimos-doctor' into feat/dimup-release
TomCC7 b6ec6d9
Merge branch 'feat/dimup-init' into feat/dimos-doctor
TomCC7 c747e17
Merge branch 'feat/dimos-doctor' into feat/dimup-release
TomCC7 01ce4c9
Merge branch 'fix/sdk-native-builds' into feat/dimup-init
TomCC7 c6442ce
Merge branch 'feat/dimup-init' into feat/dimos-doctor
TomCC7 6e816b7
test(installer): ship and verify the polished CLI transcript
TomCC7 54ecccd
Merge branch 'fix/sdk-native-builds' into feat/dimup-init
TomCC7 eb95543
Merge branch 'feat/dimup-init' into feat/dimos-doctor
TomCC7 f5ac245
Merge branch 'feat/dimos-doctor' into feat/dimup-release
TomCC7 15c315f
chore(installer): refresh bootstrap after review cleanup
TomCC7 fe0f492
refactor(installer): consolidate the complete application workflow
TomCC7 7fc4c11
chore(installer): pin bootstrap to consolidated application feature
TomCC7 a30fde0
refactor(installer): exercise source bootstrap in application CI
TomCC7 37d3fd2
docs(installer): lead with the current PR test journey
TomCC7 cd14dd5
Merge branch 'fix/sdk-native-builds' into feat/dimup-release
TomCC7 e2cb004
Merge branch 'fix/sdk-native-builds' into feat/dimup-release
TomCC7 e53f4ef
feat(dimup): clone and prepare contributor checkouts
TomCC7 f4bedf6
fix(dimup): avoid repeating explicit contributor commit
TomCC7 7d0843f
Merge branch 'fix/sdk-native-builds' into feat/dimup-release
TomCC7 2aa46e6
fix(dimup): keep Python onboarding independent of Deno
TomCC7 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,179 @@ | ||
| # 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. | ||
|
|
||
| """Read-only diagnostics for a DimOS application or contributor checkout.""" | ||
|
|
||
| import argparse | ||
| import json | ||
| from pathlib import Path | ||
| import shutil | ||
| import subprocess | ||
| import sys | ||
| from typing import Any | ||
|
|
||
| if sys.version_info >= (3, 11): | ||
| import tomllib | ||
| else: | ||
| import tomli as tomllib | ||
|
|
||
|
|
||
| def project_root(path: Path) -> Path: | ||
| for root in (path.resolve(), *path.resolve().parents): | ||
| manifest = root / "pyproject.toml" | ||
| if manifest.is_file(): | ||
| config = tomllib.loads(manifest.read_text()) | ||
| if "dimos" in config.get("tool", {}).get("uv", {}).get("sources", {}) or ( | ||
| config.get("project", {}).get("name") == "dimos" and (root / "dimos").is_dir() | ||
| ): | ||
| return root | ||
| raise ValueError( | ||
| "No DimOS project found. Run inside an application created by dimup init or a checkout prepared by dimup dev." | ||
| ) | ||
|
|
||
|
|
||
| def probe(python: Path, script: str, *args: str, cwd: Path) -> tuple[bool, str]: | ||
| try: | ||
| result = subprocess.run( | ||
| [str(python), "-I", "-c", script, *args], | ||
| capture_output=True, | ||
| text=True, | ||
| timeout=45, | ||
| check=False, | ||
| cwd=cwd, | ||
| ) | ||
| except (OSError, subprocess.TimeoutExpired) as error: | ||
| return False, str(error) | ||
| if result.returncode: | ||
| return False, (result.stderr or result.stdout).strip()[-1500:] | ||
| return True, result.stdout.strip() | ||
|
|
||
|
|
||
| METADATA_CHECK = """import importlib.metadata as m, json, sys | ||
| from pathlib import Path | ||
| app = m.distribution(sys.argv[1]) | ||
| sdk = m.distribution("dimos") | ||
| print(json.dumps({ | ||
| "editable": json.loads(app.read_text("direct_url.json") or "{}"), | ||
| "sdk": json.loads(sdk.read_text("direct_url.json") or "{}"), | ||
| "entries": [e.name for e in app.entry_points if e.group == "dimos.blueprints"], | ||
| "version": sdk.version, | ||
| "source": str(Path(__import__("dimos").__file__).resolve()), | ||
| })) | ||
| """ | ||
| LIBRARY_CHECK = """import ctypes | ||
| from ctypes.util import find_library | ||
| import numpy as np | ||
| import sqlite3, sqlite_vec | ||
| from turbojpeg import TurboJPEG | ||
| import zenoh, lcm | ||
| with sqlite3.connect(":memory:") as connection: | ||
| if not hasattr(connection, "enable_load_extension"): | ||
| raise RuntimeError( | ||
| "Python lacks SQLite extension loading. Recreate .venv with uv-managed Python: " | ||
| "uv venv --clear --managed-python --python 3.12 && uv sync --locked" | ||
| ) | ||
| connection.enable_load_extension(True) | ||
| sqlite_vec.load(connection) | ||
| connection.enable_load_extension(False) | ||
| connection.execute("SELECT vec_version()").fetchone() | ||
| for name in ("portaudio", "sndfile"): | ||
| path = find_library(name) | ||
| if not path: | ||
| raise RuntimeError(f"Missing host library: {name}; run dimup setup") | ||
| ctypes.CDLL(path) | ||
| codec = TurboJPEG() | ||
| image = np.zeros((8, 8, 3), dtype=np.uint8) | ||
| assert codec.decode(codec.encode(image)).shape == image.shape | ||
| """ | ||
|
|
||
|
|
||
| def diagnose(root: Path) -> list[tuple[bool, str, str]]: | ||
| manifest = tomllib.loads((root / "pyproject.toml").read_text()) | ||
| name = manifest["project"]["name"] | ||
| contributor = name == "dimos" | ||
| python = root / ".venv/bin/python" | ||
| results = [ | ||
| ( | ||
| Path(sys.prefix).resolve() == (root / ".venv").resolve(), | ||
| "Active environment", | ||
| "source .dimos/activate.sh selects this project's interpreter", | ||
| ) | ||
| ] | ||
| if not python.is_file(): | ||
| return [*results, (False, "Application environment", "Run uv sync --locked")] | ||
| ok, detail = probe(python, METADATA_CHECK, name, cwd=root) | ||
| if ok: | ||
| metadata: dict[str, Any] = json.loads(detail) | ||
| app = metadata["editable"] | ||
| editable = app.get("dir_info", {}).get("editable") and app.get("url") == root.as_uri() | ||
| if contributor: | ||
| source = metadata.get("source") | ||
| results.append( | ||
| ( | ||
| bool(editable) and source == str(root / "dimos/__init__.py"), | ||
| "Editable DimOS checkout", | ||
| f"Expected {root}; imported {source}. Run uv sync --locked if they differ", | ||
| ) | ||
| ) | ||
| else: | ||
| results.append( | ||
| ( | ||
| bool(editable), | ||
| "Editable application", | ||
| "Run uv sync --locked to install this application", | ||
| ) | ||
| ) | ||
| results.append( | ||
| ( | ||
| bool(metadata["entries"]), | ||
| "Blueprint registration", | ||
| ", ".join(metadata["entries"]) or "Run uv sync to refresh entry points", | ||
| ) | ||
| ) | ||
| expected = manifest["tool"]["uv"]["sources"]["dimos"]["rev"] | ||
| commit = metadata["sdk"].get("vcs_info", {}).get("commit_id") | ||
| results.append( | ||
| ( | ||
| commit == expected, | ||
| "SDK revision", | ||
| f"Expected {expected}; installed {commit}. Run uv sync --locked if they differ", | ||
| ) | ||
| ) | ||
| else: | ||
| results.append((False, "Installed metadata", f"{detail}\nRun uv sync --locked")) | ||
| for tool in ("uv", "cargo", "nix", "git"): | ||
| found = shutil.which(tool) | ||
| results.append( | ||
| (found is not None, tool, found or "Run dimup setup, then activate the project") | ||
| ) | ||
| ok, detail = probe(python, LIBRARY_CHECK, cwd=root) | ||
| results.append((ok, "Native libraries and image codec", detail or "Image round trip passed")) | ||
| return results | ||
|
|
||
|
|
||
| def main(argv: list[str] | None = None) -> int: | ||
| parser = argparse.ArgumentParser(prog="dimos doctor", description=__doc__) | ||
| parser.add_argument("--project-dir", type=Path, default=Path.cwd()) | ||
| args = parser.parse_args(argv) | ||
| try: | ||
| results = diagnose(project_root(args.project_dir)) | ||
| except (OSError, ValueError, KeyError, TypeError) as error: | ||
| results = [(False, "Application", str(error))] | ||
| for ok, label, detail in results: | ||
| print(f"{'PASS' if ok else 'FAIL'} {label}: {detail}") | ||
| return int(any(not ok for ok, _, _ in results)) | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| raise SystemExit(main()) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| # 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. | ||
|
|
||
| """Keep diagnostics accessible before importing the robotics runtime.""" | ||
|
|
||
| from importlib import import_module | ||
| import sys | ||
|
|
||
|
|
||
| def cli_main() -> None: | ||
| if sys.argv[1:2] == ["doctor"]: | ||
| raise SystemExit(import_module("dimos.cli.doctor").main(sys.argv[2:])) | ||
| import_module("dimos.cli.dimos").cli_main() | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why we need this file?