grid-cortex-client 0.3.0__tar.gz

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 (58) hide show
  1. grid_cortex_client-0.3.0/.gitignore +12 -0
  2. grid_cortex_client-0.3.0/CLAUDE.md +109 -0
  3. grid_cortex_client-0.3.0/PKG-INFO +143 -0
  4. grid_cortex_client-0.3.0/README.md +121 -0
  5. grid_cortex_client-0.3.0/pyproject.toml +56 -0
  6. grid_cortex_client-0.3.0/src/grid_cortex_client/__init__.py +30 -0
  7. grid_cortex_client-0.3.0/src/grid_cortex_client/client.py +262 -0
  8. grid_cortex_client-0.3.0/src/grid_cortex_client/cortex_client.py +661 -0
  9. grid_cortex_client-0.3.0/src/grid_cortex_client/cortex_hub_client.py +523 -0
  10. grid_cortex_client-0.3.0/src/grid_cortex_client/model_type.py +621 -0
  11. grid_cortex_client-0.3.0/src/grid_cortex_client/models/__init__.py +40 -0
  12. grid_cortex_client-0.3.0/src/grid_cortex_client/models/base_model.py +106 -0
  13. grid_cortex_client-0.3.0/src/grid_cortex_client/models/da3metric.py +144 -0
  14. grid_cortex_client-0.3.0/src/grid_cortex_client/models/fast_foundation_stereo.py +163 -0
  15. grid_cortex_client-0.3.0/src/grid_cortex_client/models/finetune_pi05.py +176 -0
  16. grid_cortex_client-0.3.0/src/grid_cortex_client/models/foundation_stereo.py +161 -0
  17. grid_cortex_client-0.3.0/src/grid_cortex_client/models/graspgen.py +206 -0
  18. grid_cortex_client-0.3.0/src/grid_cortex_client/models/gsam2.py +182 -0
  19. grid_cortex_client-0.3.0/src/grid_cortex_client/models/locate_anything.py +107 -0
  20. grid_cortex_client-0.3.0/src/grid_cortex_client/models/metric3d.py +95 -0
  21. grid_cortex_client-0.3.0/src/grid_cortex_client/models/moondream.py +131 -0
  22. grid_cortex_client-0.3.0/src/grid_cortex_client/models/oneformer.py +117 -0
  23. grid_cortex_client-0.3.0/src/grid_cortex_client/models/owlv2.py +167 -0
  24. grid_cortex_client-0.3.0/src/grid_cortex_client/models/pi05.py +288 -0
  25. grid_cortex_client-0.3.0/src/grid_cortex_client/models/qwen_vl.py +112 -0
  26. grid_cortex_client-0.3.0/src/grid_cortex_client/models/sam2.py +141 -0
  27. grid_cortex_client-0.3.0/src/grid_cortex_client/models/sam3.py +267 -0
  28. grid_cortex_client-0.3.0/src/grid_cortex_client/models/ur5e_pyroki_collision_batch.py +360 -0
  29. grid_cortex_client-0.3.0/src/grid_cortex_client/models/ur5e_pyroki_fk.py +122 -0
  30. grid_cortex_client-0.3.0/src/grid_cortex_client/models/zoedepth.py +145 -0
  31. grid_cortex_client-0.3.0/src/grid_cortex_client/preprocessing.py +113 -0
  32. grid_cortex_client-0.3.0/src/grid_cortex_client/tools/__init__.py +1 -0
  33. grid_cortex_client-0.3.0/src/grid_cortex_client/tools/generate_enum.py +219 -0
  34. grid_cortex_client-0.3.0/src/grid_cortex_client/tools/registry.py +104 -0
  35. grid_cortex_client-0.3.0/src/grid_cortex_client/utils.py +33 -0
  36. grid_cortex_client-0.3.0/src/grid_cortex_client/ws.py +74 -0
  37. grid_cortex_client-0.3.0/tests/README.md +73 -0
  38. grid_cortex_client-0.3.0/tests/__init__.py +1 -0
  39. grid_cortex_client-0.3.0/tests/conftest.py +275 -0
  40. grid_cortex_client-0.3.0/tests/test_cortex_hub_client.py +470 -0
  41. grid_cortex_client-0.3.0/tests/test_da3metric.py +119 -0
  42. grid_cortex_client-0.3.0/tests/test_fast_foundation_stereo.py +287 -0
  43. grid_cortex_client-0.3.0/tests/test_finetune_pi05.py +428 -0
  44. grid_cortex_client-0.3.0/tests/test_foundation_stereo.py +278 -0
  45. grid_cortex_client-0.3.0/tests/test_graspgen.py +378 -0
  46. grid_cortex_client-0.3.0/tests/test_gsam2.py +201 -0
  47. grid_cortex_client-0.3.0/tests/test_locate_anything.py +199 -0
  48. grid_cortex_client-0.3.0/tests/test_metric3d.py +128 -0
  49. grid_cortex_client-0.3.0/tests/test_moondream.py +238 -0
  50. grid_cortex_client-0.3.0/tests/test_oneformer.py +206 -0
  51. grid_cortex_client-0.3.0/tests/test_owlv2.py +234 -0
  52. grid_cortex_client-0.3.0/tests/test_pi05.py +212 -0
  53. grid_cortex_client-0.3.0/tests/test_qwen_vl.py +180 -0
  54. grid_cortex_client-0.3.0/tests/test_sam2.py +225 -0
  55. grid_cortex_client-0.3.0/tests/test_sam3.py +313 -0
  56. grid_cortex_client-0.3.0/tests/test_ur5e_pyroki_collision_batch.py +252 -0
  57. grid_cortex_client-0.3.0/tests/test_ur5e_pyroki_fk.py +267 -0
  58. grid_cortex_client-0.3.0/tests/test_zoedepth.py +125 -0
@@ -0,0 +1,12 @@
1
+ # Build artefacts
2
+ build/
3
+ dist/
4
+ *.egg-info/
5
+ .venv/
6
+ __pycache__/
7
+ *.pyc
8
+
9
+ # Test
10
+ .pytest_cache/
11
+ .coverage
12
+ htmlcov/
@@ -0,0 +1,109 @@
1
+ # grid-cortex-client
2
+
3
+ Python client for the Cortex ML inference API. Published to **public PyPI**.
4
+
5
+ ## Build & Test
6
+
7
+ ```bash
8
+ uv run --package grid-cortex-client pytest
9
+ ```
10
+
11
+ - Build tool: hatchling + hatch-vcs
12
+ - Version: set via `BUILD_VERSION` env (auto-bumped on main from squash-commit type — see `knowledge/golden-rules/cortex/client-versioning.md`)
13
+ - PyPI history: pre-PR-#44 versions up to `0.2.118` were published by the old pipeline; the new auto-pipeline starts at `0.3.0` and uses `cortex-client/v*` git tags as the version source of truth (first auto-publish lands via PR #45's `feat(cortex):` merge once its review feedback is addressed)
14
+
15
+ ## Key Details
16
+
17
+ - Public API: `CortexClient`, `AsyncCortexClient`, `CortexHubClient`, `ModelType`, `registry`
18
+ - `ModelType` enum is **auto-generated** by the `generate-enum` pre-commit hook — do not edit manually
19
+ - One model handler file per Cortex model in `src/grid_cortex_client/models/`
20
+ - Tests mirror model structure: `tests/test_<model>.py`. CI runs them against a live Ray Serve + CortexHub via `.ci/cortex/run_model_tests.py`.
21
+
22
+ ## Endpoints
23
+
24
+ | Env | REST base | CortexHub WebSocket |
25
+ |---|---|---|
26
+ | Local | `http://localhost:8000/cortex` | `ws://localhost:8000/cortex/ws/ws` |
27
+ | Stage | `https://cortex-stage.generalrobotics.dev/cortex` | `wss://cortex-stage.generalrobotics.dev/cortex/ws/ws` |
28
+ | Prod | `https://cortex-prod.generalrobotics.dev/cortex` | `wss://cortex-prod.generalrobotics.dev/cortex/ws/ws` |
29
+
30
+ Override via `GRID_CORTEX_BASE_URL` (REST) and `GRID_CORTEX_WS_URL` (WebSocket). Default is prod.
31
+
32
+ ## Publishing
33
+
34
+ Client and server release on different cadences. Server deploys touch `cortex/services/ray-serve/**`; client publishes touch `cortex/packages/grid-cortex-client/**`. The two never piggyback — a server-only PR doesn't bump the client, so PyPI users only see versions when the client API actually changed.
35
+
36
+ ### Auto path (MINOR / PATCH)
37
+
38
+ The squash-merge title's conventional-commit type drives the bump:
39
+
40
+ | Subject prefix | Bump | Example |
41
+ |---|---|---|
42
+ | `feat:` (incl. `feat(scope):`) | MINOR | `feat(cortex-client): add ZoeDepth method` → `0.3.4 → 0.4.0` |
43
+ | `fix:` / `perf:` | PATCH | `fix(cortex-client): retry transient 503s` → `0.3.4 → 0.3.5` |
44
+ | `chore:` / `docs:` / `ci:` / `refactor:` / `test:` / `build:` / `style:` / `revert:` | none | no release fires |
45
+ | `feat!:` / `fix!:` / `BREAKING CHANGE:` footer | none (manual) | see Manual MAJOR path below |
46
+
47
+ Flow when a release-bumping client PR lands on main:
48
+
49
+ 1. `cortex-main.yaml` fires (path filter matches `cortex/packages/grid-cortex-client/**`)
50
+ 2. `resolve` parses the commit subject, computes the new version
51
+ 3. `build-wheel` builds with `BUILD_VERSION=<new>`, uploads as an artifact
52
+ 4. `validate-stage` + `validate-prod` install the wheel in fresh venvs, discover deployed models via `CortexClient.get_info()`, run the per-model integration tests against the live env
53
+ 5. `publish-client` (gated on **validate-prod green only** — stage is advisory) uploads to PyPI using `PYPI_API_TOKEN`
54
+ 6. `tag-client` creates and pushes `cortex-client/v<new>` after the wheel is on PyPI
55
+
56
+ ### Manual MAJOR path
57
+
58
+ Auto-publish refuses to bump MAJOR. When you're ready:
59
+
60
+ ```bash
61
+ gh release create cortex-client/v<X>.0.0 \
62
+ --target main \
63
+ --notes-file cortex/packages/grid-cortex-client/MIGRATION.md
64
+ ```
65
+
66
+ The `release: published` event fires `release.yaml` → routes to `release-cortex-client` → `cortex-publish-client.yaml` builds from the tag and uploads. **Validate against deployed prod manually before cutting the release** — the manual path does not gate.
67
+
68
+ ### Implementation details
69
+
70
+ - `pyproject.toml` declares `dynamic = ["version"]`; hatchling reads `BUILD_VERSION` from the workflow env.
71
+ - Wheel is built once in `build-wheel`, then passed by artifact to `validate-{stage,prod}` and `publish-client` so all three use identical bits.
72
+ - Tag creation happens only after a confirmed successful PyPI upload — `cortex-client/v*` means "this version is on PyPI." Recoverable if the tag-push step fails: `git tag cortex-client/v<x> <sha> && git push origin cortex-client/v<x>`.
73
+
74
+ ### Validate workflow shape (`.github/workflows/cortex-validate-client.yaml`)
75
+
76
+ One job per env (no matrix). The job:
77
+
78
+ 1. Calls `CortexClient.get_info()` once via a Python heredoc that imports `CLIENT_HANDLER_OVERRIDES` + `SKIP_DEPLOYED` from `.ci/cortex/_client_overrides.py` (kept stdlib-only so the validate venv doesn't need pyyaml).
79
+ 2. Python writes a bash-sourceable `/tmp/discover.sh` with `DEPLOYED`, `SKIP_SET`, `OVERRIDES` — we do not parse JSON in bash because `cortex-aws-gpu` has no `jq`.
80
+ 3. Loops over `$DEPLOYED` sequentially. Per server name: SKIP entries short-circuit; missing test files become `NO-TEST` rows; remaining models run `pytest tests/test_<client>.py --tb=short`.
81
+ 4. `::group::pytest output (<client>)` block surfaces the full pytest log on FAIL so on-call doesn't have to reach the runner's `/tmp`.
82
+ 5. Exits 1 if discover python errors, if `DEPLOYED` is empty, or if `tested == 0` (the publish-gate invariant: validate must exercise at least one model before `publish-client` can run).
83
+
84
+ Replaces the earlier discover+matrix shape, which fired N env-reviewer prompts per env without delivering real parallelism (single shared runner).
85
+
86
+ ### One-time repo setup
87
+
88
+ 1. **GitHub environment** `prod` — already used by `cortex-deploy.yaml`. Required reviewers on this environment also gate `cortex-publish-client`.
89
+ 2. **Repo secret `PYPI_API_TOKEN`** — project-scoped PyPI token for `grid-cortex-client`. Created on pypi.org → manage project → API tokens → create.
90
+ 3. **Repo secret `CORTEX_VALIDATE_API_KEY`** — an API key the workflow uses to talk to deployed stage/prod for the validate step. Must work on both envs (or, if scoped, use the prod-capable one — validate-prod is the gating call).
91
+
92
+ ### `MIN_SERVER_VERSION`
93
+
94
+ `MIN_SERVER_VERSION` is a constant exported from this package; the client checks `/health` on construction and refuses to talk to a server older than its declared minimum. Bumping it = MAJOR client release. *Not yet implemented — tracked as a follow-up to the publish wiring.*
95
+
96
+ ## Consumed By
97
+
98
+ - `nexus/packages/zenoh-dataflow` (imports grid_cortex_client)
99
+ - `nexus/packages/grid-robot-api` (imports grid_cortex_client)
100
+ - `cortex/services/ray-serve` (the service this client talks to — code-shared via `ModelType`)
101
+ - External users via PyPI
102
+
103
+ ## Adding a New Model Handler
104
+
105
+ 1. Add handler in `src/grid_cortex_client/models/<model>.py` (copy `zoedepth.py`/`owlv2.py`/`pi05.py` as starting point)
106
+ 2. Add test in `tests/test_<model>.py` (copy the matching test_*.py)
107
+ 3. The `generate-enum` hook updates `ModelType` automatically
108
+
109
+ The `/add-new-model` skill does all of the above end-to-end. See `.claude/skills/add-new-model/SKILL.md`.
@@ -0,0 +1,143 @@
1
+ Metadata-Version: 2.4
2
+ Name: grid-cortex-client
3
+ Version: 0.3.0
4
+ Summary: Python client for Grid Cortex
5
+ Classifier: Programming Language :: Python :: 3
6
+ Classifier: Programming Language :: Python :: 3.8
7
+ Classifier: Programming Language :: Python :: 3.9
8
+ Classifier: Programming Language :: Python :: 3.10
9
+ Classifier: Programming Language :: Python :: 3.11
10
+ Classifier: Programming Language :: Python :: 3.12
11
+ Classifier: Programming Language :: Python :: 3.13
12
+ Requires-Python: >=3.8
13
+ Requires-Dist: httpx>=0.28.1
14
+ Requires-Dist: msgpack-numpy>=0.4.0
15
+ Requires-Dist: msgpack>=1.0.0
16
+ Requires-Dist: numpy<2
17
+ Requires-Dist: pillow>=10.0.0
18
+ Requires-Dist: requests>=2.20.0
19
+ Requires-Dist: rerun-sdk==0.22.1
20
+ Requires-Dist: websockets>=12.0
21
+ Description-Content-Type: text/markdown
22
+
23
+ # Grid Cortex Client
24
+
25
+ [![PyPI version](https://img.shields.io/pypi/v/grid-cortex-client.svg)](https://pypi.org/project/grid-cortex-client/)
26
+ [![Python](https://img.shields.io/pypi/pyversions/grid-cortex-client.svg)](https://pypi.org/project/grid-cortex-client/)
27
+
28
+ Python client for [GRID Cortex](https://cortex.generalrobotics.dev).
29
+
30
+ ## Installation
31
+
32
+ ```bash
33
+ pip install grid-cortex-client
34
+ ```
35
+
36
+ ## Quick Start
37
+
38
+ ```python
39
+ from grid_cortex_client import CortexClient, ModelType
40
+
41
+ client = CortexClient(api_key="your-api-key")
42
+
43
+ # Monocular depth estimation
44
+ depth_map = client.run(ModelType.ZOEDEPTH, image_input="path/to/image.jpg")
45
+ ```
46
+
47
+ ## Configuration
48
+
49
+ Pass your API key and base URL directly, or set them as environment variables:
50
+
51
+ ```bash
52
+ export GRID_CORTEX_API_KEY="your-api-key"
53
+ export GRID_CORTEX_BASE_URL="https://cortex-prod.generalrobotics.dev/cortex"
54
+ ```
55
+
56
+ ```python
57
+ # Explicit configuration
58
+ client = CortexClient(api_key="your-key", base_url="https://...")
59
+
60
+ # Or rely on environment variables
61
+ client = CortexClient()
62
+ ```
63
+
64
+ ## Input Formats
65
+
66
+ All image-based models accept multiple input types:
67
+
68
+ - **File path:** `"path/to/image.jpg"`
69
+ - **URL:** `"https://example.com/image.jpg"`
70
+ - **PIL Image:** `Image.open("image.jpg")`
71
+ - **NumPy array:** `np.ndarray` with shape `(H, W, 3)`
72
+
73
+ ## Async & Concurrent Inference
74
+
75
+ The async client lets you call multiple models concurrently so total latency equals the **slowest** model, not the sum of all of them.
76
+
77
+ ### Concurrent multi-model example
78
+
79
+ ```python
80
+ import asyncio
81
+ import numpy as np
82
+ from grid_cortex_client import AsyncCortexClient, ModelType
83
+
84
+ async def run_perception_pipeline(image: np.ndarray):
85
+ """Run depth, detection, and segmentation concurrently on the same frame."""
86
+ async with AsyncCortexClient() as client:
87
+ depth, detections, mask = await asyncio.gather(
88
+ client.run(ModelType.ZOEDEPTH, image_input=image),
89
+ client.run(ModelType.OWLV2, image_input=image, prompt="bottle"),
90
+ client.run(ModelType.GSAM2, image_input=image, prompt="bottle"),
91
+ )
92
+ return depth, detections, mask
93
+
94
+ depth, detections, mask = asyncio.run(
95
+ run_perception_pipeline(np.array(Image.open("scene.jpg")))
96
+ )
97
+ ```
98
+
99
+ ### High-throughput streaming with pub/sub
100
+
101
+ For continuous streams (e.g. camera feeds), the `CortexHubClient` uses WebSockets to overlap sending and receiving. While frame N's result is being returned, frame N+1 is already being processed server-side:
102
+
103
+ ```python
104
+ import asyncio
105
+ import numpy as np
106
+ from grid_cortex_client import CortexHubClient, ModelType
107
+
108
+ async def publisher(hub: CortexHubClient, frames: list[np.ndarray]):
109
+ """Send frames as fast as possible."""
110
+ for i, frame in enumerate(frames):
111
+ await hub.publish(ModelType.ZOEDEPTH, request_id=f"frame_{i}", image_input=frame)
112
+
113
+ async def subscriber(hub: CortexHubClient, num_frames: int):
114
+ """Receive results as they arrive."""
115
+ count = 0
116
+ async for result in hub.subscribe():
117
+ if result.ok:
118
+ print(f"{result.request_id}: shape={result.data.shape}")
119
+ count += 1
120
+ if count >= num_frames:
121
+ break
122
+
123
+ async def main():
124
+ frames = [np.random.randint(0, 255, (480, 640, 3), dtype=np.uint8)] * 100
125
+
126
+ async with CortexHubClient() as hub:
127
+ await asyncio.gather(
128
+ publisher(hub, frames),
129
+ subscriber(hub, len(frames)),
130
+ )
131
+
132
+ asyncio.run(main())
133
+ ```
134
+
135
+ ## Documentation
136
+
137
+ For model-specific usage examples, parameter references, and detailed guides, see the full documentation:
138
+
139
+ **[docs.generalrobotics.dev/models/cortex](https://docs.generalrobotics.dev/models/cortex)**
140
+
141
+ ## Requirements
142
+
143
+ - Python >= 3.8
@@ -0,0 +1,121 @@
1
+ # Grid Cortex Client
2
+
3
+ [![PyPI version](https://img.shields.io/pypi/v/grid-cortex-client.svg)](https://pypi.org/project/grid-cortex-client/)
4
+ [![Python](https://img.shields.io/pypi/pyversions/grid-cortex-client.svg)](https://pypi.org/project/grid-cortex-client/)
5
+
6
+ Python client for [GRID Cortex](https://cortex.generalrobotics.dev).
7
+
8
+ ## Installation
9
+
10
+ ```bash
11
+ pip install grid-cortex-client
12
+ ```
13
+
14
+ ## Quick Start
15
+
16
+ ```python
17
+ from grid_cortex_client import CortexClient, ModelType
18
+
19
+ client = CortexClient(api_key="your-api-key")
20
+
21
+ # Monocular depth estimation
22
+ depth_map = client.run(ModelType.ZOEDEPTH, image_input="path/to/image.jpg")
23
+ ```
24
+
25
+ ## Configuration
26
+
27
+ Pass your API key and base URL directly, or set them as environment variables:
28
+
29
+ ```bash
30
+ export GRID_CORTEX_API_KEY="your-api-key"
31
+ export GRID_CORTEX_BASE_URL="https://cortex-prod.generalrobotics.dev/cortex"
32
+ ```
33
+
34
+ ```python
35
+ # Explicit configuration
36
+ client = CortexClient(api_key="your-key", base_url="https://...")
37
+
38
+ # Or rely on environment variables
39
+ client = CortexClient()
40
+ ```
41
+
42
+ ## Input Formats
43
+
44
+ All image-based models accept multiple input types:
45
+
46
+ - **File path:** `"path/to/image.jpg"`
47
+ - **URL:** `"https://example.com/image.jpg"`
48
+ - **PIL Image:** `Image.open("image.jpg")`
49
+ - **NumPy array:** `np.ndarray` with shape `(H, W, 3)`
50
+
51
+ ## Async & Concurrent Inference
52
+
53
+ The async client lets you call multiple models concurrently so total latency equals the **slowest** model, not the sum of all of them.
54
+
55
+ ### Concurrent multi-model example
56
+
57
+ ```python
58
+ import asyncio
59
+ import numpy as np
60
+ from grid_cortex_client import AsyncCortexClient, ModelType
61
+
62
+ async def run_perception_pipeline(image: np.ndarray):
63
+ """Run depth, detection, and segmentation concurrently on the same frame."""
64
+ async with AsyncCortexClient() as client:
65
+ depth, detections, mask = await asyncio.gather(
66
+ client.run(ModelType.ZOEDEPTH, image_input=image),
67
+ client.run(ModelType.OWLV2, image_input=image, prompt="bottle"),
68
+ client.run(ModelType.GSAM2, image_input=image, prompt="bottle"),
69
+ )
70
+ return depth, detections, mask
71
+
72
+ depth, detections, mask = asyncio.run(
73
+ run_perception_pipeline(np.array(Image.open("scene.jpg")))
74
+ )
75
+ ```
76
+
77
+ ### High-throughput streaming with pub/sub
78
+
79
+ For continuous streams (e.g. camera feeds), the `CortexHubClient` uses WebSockets to overlap sending and receiving. While frame N's result is being returned, frame N+1 is already being processed server-side:
80
+
81
+ ```python
82
+ import asyncio
83
+ import numpy as np
84
+ from grid_cortex_client import CortexHubClient, ModelType
85
+
86
+ async def publisher(hub: CortexHubClient, frames: list[np.ndarray]):
87
+ """Send frames as fast as possible."""
88
+ for i, frame in enumerate(frames):
89
+ await hub.publish(ModelType.ZOEDEPTH, request_id=f"frame_{i}", image_input=frame)
90
+
91
+ async def subscriber(hub: CortexHubClient, num_frames: int):
92
+ """Receive results as they arrive."""
93
+ count = 0
94
+ async for result in hub.subscribe():
95
+ if result.ok:
96
+ print(f"{result.request_id}: shape={result.data.shape}")
97
+ count += 1
98
+ if count >= num_frames:
99
+ break
100
+
101
+ async def main():
102
+ frames = [np.random.randint(0, 255, (480, 640, 3), dtype=np.uint8)] * 100
103
+
104
+ async with CortexHubClient() as hub:
105
+ await asyncio.gather(
106
+ publisher(hub, frames),
107
+ subscriber(hub, len(frames)),
108
+ )
109
+
110
+ asyncio.run(main())
111
+ ```
112
+
113
+ ## Documentation
114
+
115
+ For model-specific usage examples, parameter references, and detailed guides, see the full documentation:
116
+
117
+ **[docs.generalrobotics.dev/models/cortex](https://docs.generalrobotics.dev/models/cortex)**
118
+
119
+ ## Requirements
120
+
121
+ - Python >= 3.8
@@ -0,0 +1,56 @@
1
+ [project]
2
+ name = "grid-cortex-client"
3
+ dynamic = ["version"]
4
+ description = "Python client for Grid Cortex"
5
+ readme = "README.md"
6
+ requires-python = ">=3.8"
7
+ classifiers = [
8
+ "Programming Language :: Python :: 3",
9
+ "Programming Language :: Python :: 3.8",
10
+ "Programming Language :: Python :: 3.9",
11
+ "Programming Language :: Python :: 3.10",
12
+ "Programming Language :: Python :: 3.11",
13
+ "Programming Language :: Python :: 3.12",
14
+ "Programming Language :: Python :: 3.13",
15
+ ]
16
+ dependencies = [
17
+ "httpx>=0.28.1",
18
+ "numpy<2",
19
+ "rerun-sdk==0.22.1",
20
+ "Pillow>=10.0.0",
21
+ "requests>=2.20.0",
22
+ "websockets>=12.0",
23
+ "msgpack>=1.0.0",
24
+ "msgpack-numpy>=0.4.0",
25
+ ]
26
+
27
+ [build-system]
28
+ requires = ["hatchling", "hatch-vcs"]
29
+ build-backend = "hatchling.build"
30
+
31
+ [tool.uv]
32
+ required-version = ">=0.7.20"
33
+ exclude-newer = "7 days"
34
+
35
+ [tool.hatch.version]
36
+ source = "env"
37
+ variable = "BUILD_VERSION"
38
+
39
+ [tool.hatch.version.raw-options]
40
+ root = "../.."
41
+ local_scheme = "no-local-version"
42
+
43
+ [tool.pytest.ini_options]
44
+ testpaths = ["tests"]
45
+ python_files = ["test_*.py"]
46
+ python_classes = ["Test*"]
47
+ python_functions = ["test_*"]
48
+ markers = [
49
+ "slow: marks tests as slow (deselect with '-m \"not slow\"')",
50
+ "integration: marks tests as integration tests",
51
+ ]
52
+
53
+ [dependency-groups]
54
+ dev = [
55
+ "pytest>=8.3.5",
56
+ ]
@@ -0,0 +1,30 @@
1
+ """Grid Cortex Python client.
2
+
3
+ This package provides :class:`CortexClient` for high-level model inference.
4
+ Use :class:`ModelType` enum to specify which model to run.
5
+ """
6
+
7
+ import os
8
+
9
+ # Public API first (ruff E402)
10
+ from .model_type import ModelType # re-export static enum
11
+ from .tools.registry import registry # shared model registry instance
12
+
13
+ if os.environ.get("GRID_CORTEX_SKIP_PUBLIC_API") != "1":
14
+ from .cortex_client import AsyncCortexClient, CortexClient
15
+ from .cortex_hub_client import CortexHubClient, CortexHubError, HubResult
16
+
17
+ # Configure the library logger to be silent by default **after** imports to satisfy E402.
18
+ import logging
19
+
20
+ logging.getLogger(__name__).addHandler(logging.NullHandler())
21
+
22
+ __all__ = [
23
+ "AsyncCortexClient",
24
+ "CortexClient",
25
+ "CortexHubClient",
26
+ "CortexHubError",
27
+ "HubResult",
28
+ "ModelType",
29
+ "registry",
30
+ ]