Repository navigation
Promote device-py SDK: mirurobotics/python-device-sdk-staging -> mirurobotics/python-device-sdk - #12
Merged
Merged
Conversation
…m cache) (#147) Stainless-Generated-From: 097dd3a49950a713b5410842ac6680f911bf2607
Stainless-Generated-From: 67a902eca03a9fcc2b2c9abd489f08d22978b885
… (#285) Stainless-Generated-From: ff7275bbcc2769850710869be2df9eeba287ae78
Stainless-Generated-From: a9d02554b0e04697604f55e7aeaf8a021666c231
…_rule_id} (#291) Stainless-Generated-From: 6b4dcc4c65ca27b288212e4c7e2b46aaab38909b
Stainless-Generated-From: 4a85f0562b4acc8f1fb20a2c05b3653f6174eeae
## Why Hand-written SDK changes (custom code on top of Stainless output) will land on staging `main` by pull request, once mirurobotics/infra#294 allows PR merges here. This adds the org's AI review to those PRs, like the other Miru repos. ## What New `.github/workflows/ai-review.yml`. It calls `mirurobotics/.github`'s reusable AI review workflow, pinned to the same commit as openapi's, and posts the `ai-review` status. - **`pull_request_target`:** runs from the base branch, so a PR can't edit or remove its own review. As a consequence, **this PR doesn't review itself**; the first PR reviewed is the one after it. - **Credential:** uses the org secret `CLAUDE_CODE_OAUTH_TOKEN`, which this repo already sees, so no new secrets are needed. - **Staging only:** the job runs only in `*-staging` repos. Promote copies this file to the public production repo, where it is skipped. - **Kept on regeneration:** this file is custom code. The next `stlc build` seals it, so codegen keeps it. ## Follow-up Once this is merged, a small infra PR adds `ai-review` as a required status in the staging `protect-sdk-main` ruleset. ## Merge order This can't merge until infra#294 is applied: today the ruleset blocks every change to `main`. 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- codesmith:footer --> --- <a href="https://app.blacksmith.sh/mirurobotics/codesmith/python-device-sdk-staging/pr/1?autoLogin=true&ref=codesmith_pr_footer"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"><source media="(prefers-color-scheme: light)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-light-v2.svg"><img alt="View with [code]smith" src="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"></picture></a> <a href="https://backend.blacksmith.sh/track/enable-autofix?expires=1793465555&installation_model_id=425273&pr_number=1&ref=codesmith_pr_footer&repository=mirurobotics%2Fpython-device-sdk-staging&return_to=https%3A%2F%2Fgithub.com%2Fmirurobotics%2Fpython-device-sdk-staging%2Fpull%2F1&signature=9246884df003a38fa1c2a62e0d8944614ba1040c6cdcc2a4beda46fb3979a29d"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-light.svg"><img alt="Autofix with [code]smith" src="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"></picture></a> <sup>Need help on this PR? Tag <code>@codesmith</code> with what you need. Autofix is disabled.</sup> <!-- codesmith:autofix:disabled --> <!-- /codesmith:footer --> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…back TCP API (#302) Stainless-Generated-From: 1a769a355d35ca905ebdfa44cd646d64e943aa88
…le (#3) ## Summary The Python device SDK can now reach the Miru Agent over loopback TCP, using the bearer token the agent publishes in its discovery file (mirurobotics/agent#273). TCP is the default on Windows; the Unix socket stays the default elsewhere. This replaces #2. The bearer token is now a **Stainless-generated** option, and our custom code feeds it through the generated client's own hooks instead of rewriting requests in a transport. ## Review the second commit - **`chore: regenerate ...`** is Stainless output for mirurobotics/openapi#302, not hand-written: the `agent_transport`, `discovery_file` and `bearer_token` options, plus the generated `Authorization: Bearer` header. Once #302 merges and codegen pushes the same output to `main`, I'll merge `main` into this branch and this commit drops out of the diff. - **`feat(client): ...`** is the hand-written code. Review this one. ## What **`src/miru_device_sdk/_client.py` (custom edits to the generated client):** - **Token:** `auth_headers` falls back to the discovery-file token when `bearer_token` isn't set. The header itself is still built by the generated code. - **Address:** a `_prepare_url` override points requests at `127.0.0.1:<port>` from the discovery file. It uses `127.0.0.1` rather than `localhost` because the agent listens on IPv4 loopback only and `localhost` can resolve to `::1`. - **Restarts:** a `_should_retry` override retries a 401 once, and only if the file now has a different token. - **Transport:** the builders pick the transport. The Unix socket is used as before, plain TCP when `bearer_token` is set, and TCP with discovery otherwise. **`src/miru_device_sdk/lib/device_api.py` (new).** It's in `lib/`, which Stainless never generates into. - `read_discovery`: reads the file and closes it straight away, because on Windows an open handle blocks the agent from replacing the file. - Reads the agent's `{"port", "token"}` file, checks the port (1–65535) and a non-empty token, and ignores other fields. - Raises `DiscoveryError` with a plain message for a missing file, a permission error (on Windows it names the `Miru Agent Users` group from agent#276), invalid JSON or invalid fields. - `DiscoveryFile`: caches the last read of each path. All clients using the same path share it, including `copy()`. - It re-reads only after being marked stale. - If the file is missing during an agent restart, it keeps the last values, so the request's retry gets another chance. - `DiscoveryTransport` / `AsyncDiscoveryTransport`: only mark the file stale when the agent refuses a connection, then re-raise. The client's retry, or its next request, reads the file again. They don't rewrite requests. - `resolve_transport` and `default_discovery_file`: unchanged from #2. **Setting `bearer_token` turns discovery off.** The client then uses `base_url` and the token as given. An empty `MIRU_AGENT_TOKEN` counts as unset. **`README.md`:** a "Connecting to the agent" section. It replaces the generated advice to keep `MIRU_AGENT_TOKEN` in a `.env` file, which doesn't fit a token that changes on every agent start. ## Testing `tests/test_device_api.py` has 43 tests: - reading and checking the file; - the cache: staleness, keeping the last values while the file is missing, the shared instance per path; - through the client with a scripted agent: - a 401 retried with a new token, and not retried when the token is unchanged; - a refused connection retried on a new port; - recovery with `max_retries=0`; - a missing file; - `copy()`; - an explicit token; - no token over the Unix socket; - end to end against a real local HTTP server that requires the token and switches to a new one mid-test, sync and async; - transport selection. `./scripts/lint` (ruff, pyright, mypy) and `./scripts/test` are clean: 521 tests pass on Pydantic v2 and 508 on v1. ## After merge Run openapi's `stlc-sync-tracking.yml` to record this as sealed custom code, then promote and release. ## Merge order 1. mirurobotics/openapi#302 (the bearer auth scheme and client options), then its codegen 2. this PR (the AI review must pass) 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- codesmith:footer --> --- <a href="https://app.blacksmith.sh/mirurobotics/codesmith/python-device-sdk-staging/pr/3?autoLogin=true&ref=codesmith_pr_footer"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"><source media="(prefers-color-scheme: light)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-light-v2.svg"><img alt="View with [code]smith" src="https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v2.svg"></picture></a> <a href="https://backend.blacksmith.sh/track/enable-autofix?expires=1793470816&installation_model_id=425273&pr_number=3&ref=codesmith_pr_footer&repository=mirurobotics%2Fpython-device-sdk-staging&return_to=https%3A%2F%2Fgithub.com%2Fmirurobotics%2Fpython-device-sdk-staging%2Fpull%2F3&signature=24ba6e774f0aad2e73c6698b7a5f5734747fbf3042ec8c9512a6acdd5c59c6e4"><picture><source media="(prefers-color-scheme: dark)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-light.svg"><img alt="Autofix with [code]smith" src="https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark.svg"></picture></a> <sup>Need help on this PR? Tag <code>@codesmith</code> with what you need. Autofix is disabled.</sup> <!-- codesmith:autofix:disabled --> <!-- /codesmith:footer --> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Promote the device-py SDK from staging to production.
mirurobotics/python-device-sdk-stagingmirurobotics/python-device-sdkThis PR is for review/visibility of the exact SHA being
promoted. Production
maindoes NOT advance by merging this PR:it advances by a fast-forward push of staging's reviewed
commit(s) (no merge commit). Once
mainis fast-forwarded tothe head of this branch, GitHub auto-closes this PR as merged with
no merge commit (head == base, a pure fast-forward).
Note: opened by the stlc Promoter Bot app (Pull requests: write).
Changes (production/main..origin/main):
Need help on this PR? Tag
@codesmith-botwith what you need. Autofix is disabled.