Skip to content

Sync SDK parity: add Swift A2a aliases and Python parity endpoints#190

Merged
willwashburn merged 6 commits into
mainfrom
codex/review-sdks-for-functionality-parity
Jun 15, 2026
Merged

Sync SDK parity: add Swift A2a aliases and Python parity endpoints#190
willwashburn merged 6 commits into
mainfrom
codex/review-sdks-for-functionality-parity

Conversation

@willwashburn

Copy link
Copy Markdown
Member

Motivation

  • Ensure feature parity between the TypeScript SDK and the Swift/Python SDKs so clients can use the same surface across languages.
  • Mirror TypeScript A2A naming and higher-level Relay/top-level helpers in the other SDKs for consistency.
  • Add durable delivery and action invocation APIs to Python so agent clients have the same capabilities as TypeScript.

Description

  • Swift: added lower-case convenience aliases (registerA2a, listA2aAgents, removeA2aAgent, getA2aAgentCard) in RelayCast.swift so Swift exposes TypeScript-style A2a method names while preserving existing A2A methods.
  • Python (sync + async): added put support to HTTP clients in client.py to match TypeScript PUT usage.
  • Python Relay: added top-level typed helpers for registration shortcuts, A2A (register_a2a, list_a2a_agents, remove_a2a_agent, get_a2a_agent_card), routing, directory, skills, ratings, and routing config update endpoints in relay.py.
  • Python AgentClient: added durable delivery APIs (deliveries, ack_delivery, fail_delivery, defer_delivery), an actions namespace for invocation (actions.invoke, actions.complete_invocation, actions.get_invocation), channel update/mute/unmute helpers, and post convenience method (with async counterparts) in agent.py.
  • Python Models: added Pydantic models for durable deliveries, A2A, directory, routing, route feedback, and skill search in models.py.
  • Branches and PRs: changes committed on sdk-swift-parity-a2a-aliases (Swift) and sdk-python-ts-parity (Python) and PR records were created.

Testing

  • Ran swift test in packages/sdk-swift and all Swift unit tests passed.
  • Performed Python smoke checks: python -m compileall src and an import/parity smoke check succeeded for the modified Python surfaces.
  • Attempted python -m pytest / uv run pytest for Python tests but automated test runs were blocked by missing dev dependencies in the execution environment and a PyPI download failure for packaging==26.0, so full Python test suite could not be executed.

Codex Task

@gemini-code-assist

Copy link
Copy Markdown

Warning

You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again!

@coderabbitai

coderabbitai Bot commented Jun 12, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 0d54c9da-9e9c-4094-bdd2-3af2dc005ca1

📥 Commits

Reviewing files that changed from the base of the PR and between 66798ac and e956311.

📒 Files selected for processing (1)
  • memory/workspace/.relay/state.json
✅ Files skipped from review due to trivial changes (1)
  • memory/workspace/.relay/state.json

📝 Walkthrough

Walkthrough

This PR expands the Python, Rust, and Swift SDKs with a renamed DeliveryStatus vocabulary (Queued/Acked/DeadLettered replacing Accepted/Deferred), plus new API surface for durable delivery lifecycle, A2A agent bridge management, directory/skills/routing endpoints, fleet nodes, trigger CRUD, certification flows, and console observability. Channel operations gain mute/unmute, and the invite payload key is corrected to agent_name.

Changes

DeliveryStatus Vocabulary Rename (Cross-SDK)

Layer / File(s) Summary
DeliveryStatus redefinition across SDKs
packages/sdk-rust/src/types.rs, packages/sdk-swift/Sources/Relaycast/Models.swift, packages/sdk-python/src/relay_sdk/models.py, packages/sdk-python/src/relay_sdk/agent.py, packages/sdk-rust/src/agent.rs
Replaces Accepted/Deferred variants with Queued/Acked/DeadLettered in Rust, Swift, and Python; updates as_query_value mappings and agent doc comments to match.
Delivery status test updates
packages/sdk-rust/tests/parity.rs, packages/sdk-swift/Tests/RelaycastTests/RelaycastTests.swift
Updates all mocked /v1/deliveries fixture payloads and assertions to the new status strings; adds a unit test for as_query_value canonical values and a Swift test for rawValue and JSON decoding.

New API Surface: Delivery, A2A, Directory, Routing, Nodes, Triggers, Cert, Console

Layer / File(s) Summary
New data model types
packages/sdk-python/src/relay_sdk/models.py, packages/sdk-rust/src/types.rs, packages/sdk-swift/Sources/Relaycast/Models.swift
Adds A2A card/record, directory agent/skill, routing config/weights/feedback, skills search, WorkspaceLookup, fleet node, trigger, certification, console, and WorkspaceDMMessagesOptions types across all three SDKs.
Python HTTP client PUT support
packages/sdk-python/src/relay_sdk/client.py
Adds put() to HttpClient and AsyncHttpClient, delegating to existing request() infrastructure with HTTP verb PUT.
Python AgentClient channel/action namespaces and invite fix
packages/sdk-python/src/relay_sdk/agent.py, packages/sdk-python/tests/test_agent.py
Sync and async _ChannelsNamespace gain update/mute/unmute and fix invite payload key to agent_name; new _ActionsNamespace/_AsyncActionsNamespace with invoke, complete_invocation, get_invocation are wired as self.actions.
Python AgentClient delivery lifecycle and inbox/post additions
packages/sdk-python/src/relay_sdk/agent.py
Adds post() convenience wrapper, optional limit to inbox, and deliveries/ack_delivery/fail_delivery/defer_delivery to both sync and async clients.
Python Relay/AsyncRelay workspace-level convenience methods
packages/sdk-python/src/relay_sdk/relay.py
Expands model imports and adds 23+ methods to Relay and AsyncRelay: agent registration shortcuts, A2A management, routing, directory CRUD+ratings, skills search/import, and routing config get/update.
Rust AgentClient invite fix and mute/unmute
packages/sdk-rust/src/agent.rs
Changes invite_to_channel payload field from agent to agent_name; adds mute_channel and unmute_channel async methods posting to /v1/channels/{name}/mute and /unmute.
Rust RelayCast workspace-level APIs
packages/sdk-rust/src/relay.rs
Adds lookup_workspace (404-tolerant), A2A bridge CRUD, routing, directory search/publish/list/CRUD/ratings, skills import/search, fleet node list/get, trigger CRUD, certification submit/get/badge-url/monitor, and console endpoints.
Rust public re-exports and parity tests for new surface
packages/sdk-rust/src/lib.rs, packages/sdk-rust/tests/parity.rs
Extends pub use types block with all new types; appends 30+ new parity tests covering mute/unmute, invite, workspace lookup, A2A, directory, routing, nodes, triggers, certification, and console endpoints.
Swift RelayNodesService, RelayTriggersService, and new RelayCast methods
packages/sdk-swift/Sources/Relaycast/RelayCast.swift
Adds lazy nodes and triggers service properties; adds activity(limit:), allDMConversations(), and dmMessages(conversationID:options:) to RelayCast; defines RelayNodesService and RelayTriggersService classes.
Swift tests for nodes, triggers, DM, activity, and delivery status
packages/sdk-swift/Tests/RelaycastTests/RelaycastTests.swift
Adds XCTest cases for nodes list/capability filter, trigger create/update, DM conversation/message queries, activity feed, and DeliveryStatus rawValue/JSON decoding.

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Poem

🐇 Hop hop, the status is new,
No accepted — just queued will do!
A2A bridges, directories galore,
Triggers and nodes — a SDK encore.
The rabbit types fast, through Python and Rust,
In Swift and in schemes the reviewer must trust! 🌟

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 32.39% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main changes: adding Swift A2a aliases and Python parity endpoints to achieve feature parity across SDKs.
Description check ✅ Passed The description is comprehensive and directly related to the changeset, detailing motivations, specific changes across Swift/Python, and testing performed.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/review-sdks-for-functionality-parity

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

agent-relay-code Bot added a commit that referenced this pull request Jun 12, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d9b4b33e5e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

self._client = client

def invoke(self, name: str, input: dict[str, Any] | None = None) -> Any:
return self._client.post(f"/v1/actions/{_enc(name)}/invoke", {"input": input})

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Omit input when invoking actions without payload

When invoke() is called without an input, this sends {"input": null}. The action route validates the body with invokeActionSchema in packages/engine/src/routes/action.ts, where input is an optional record but not nullable, so the common no-argument invocation path returns 400 invalid invocation body instead of invoking the action. Build the body without the input key when it is None; the async twin has the same issue.

Useful? React with 👍 / 👎.

return A2aAgentCard.model_validate(result)

def route(self, skill: str, message: str | None = None) -> RouteResult:
result = self._client.post("/v1/route", {"skill": skill, "message": message})

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Omit message when routing without a message

When callers use route(skill) without the optional message, this posts message: null. The /route handler validates message as an optional string with a default in packages/engine/src/routes/routing.ts, so omission is accepted but null is rejected and route('skill') returns 400 skill is required. Only include message when it is not None; the async variant has the same bug.

Useful? React with 👍 / 👎.

return DirectoryAgent.model_validate(result)

def delete_directory_agent(self, slug: str) -> None:
self._client.delete(f"/v1/directory/agents/{_enc(slug)}")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Handle 204 responses for directory deletion

The directory delete endpoint succeeds with c.body(null, 204) in packages/engine/src/routes/directory.ts, but this new wrapper calls HttpClient.delete(), whose response handling always attempts to parse JSON. As a result, a successful delete_directory_agent() raises a JSON parse error instead of returning None; the async wrapper has the same behavior.

Useful? React with 👍 / 👎.

agent-relay-code Bot added a commit that referenced this pull request Jun 12, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
packages/sdk-python/src/relay_sdk/agent.py (1)

162-179: 💤 Low value

Parameter input shadows Python builtin.

The parameter name input shadows the built-in input() function. While unlikely to cause issues in this context, renaming it improves clarity.

♻️ Suggested rename
-    def invoke(self, name: str, input: dict[str, Any] | None = None) -> Any:
-        return self._client.post(f"/v1/actions/{_enc(name)}/invoke", {"input": input})
+    def invoke(self, name: str, input_data: dict[str, Any] | None = None) -> Any:
+        return self._client.post(f"/v1/actions/{_enc(name)}/invoke", {"input": input_data})

Apply the same change to _AsyncActionsNamespace.invoke() at line 561.

Also applies to: 555-572

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/sdk-python/src/relay_sdk/agent.py` around lines 162 - 179, Rename
the parameter named input in _ActionsNamespace.invoke to avoid shadowing the
builtin (e.g., use input_data or payload), update its type hint from input:
dict[str, Any] | None to input_data: dict[str, Any] | None, and replace all
internal uses such as {"input": input} with {"input": input_data} (and likewise
pass input_data to any downstream calls). Make the same change in
_AsyncActionsNamespace.invoke (rename parameter and update its type hint and
usage) so both synchronous and async invoke methods remain consistent.

Source: Linters/SAST tools

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@packages/sdk-python/src/relay_sdk/agent.py`:
- Around line 162-179: Rename the parameter named input in
_ActionsNamespace.invoke to avoid shadowing the builtin (e.g., use input_data or
payload), update its type hint from input: dict[str, Any] | None to input_data:
dict[str, Any] | None, and replace all internal uses such as {"input": input}
with {"input": input_data} (and likewise pass input_data to any downstream
calls). Make the same change in _AsyncActionsNamespace.invoke (rename parameter
and update its type hint and usage) so both synchronous and async invoke methods
remain consistent.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: af879e0a-6be4-40c1-bc87-e8d357092649

📥 Commits

Reviewing files that changed from the base of the PR and between ee64c94 and 495a7af.

📒 Files selected for processing (5)
  • memory/workspace/.relay/state.json
  • packages/sdk-python/src/relay_sdk/agent.py
  • packages/sdk-python/src/relay_sdk/client.py
  • packages/sdk-python/src/relay_sdk/models.py
  • packages/sdk-python/src/relay_sdk/relay.py

agent-relay-code Bot added a commit that referenced this pull request Jun 12, 2026
willwashburn and others added 2 commits June 15, 2026 14:04
Rebased #190 onto main (resolving the #188 origin-contract changes:
origin_surface is gone; only origin_actor + origin_client/origin_version
remain — confirmed no origin_surface references survive).

Correctness fixes layered on top of #190's parity additions:

- DeliveryStatus: updated the stale Literal["accepted","delivered",
  "deferred","failed"] to the canonical #193 enum
  Literal["queued","delivered","acked","failed","dead_lettered"]
  (packages/types/src/delivery.ts). "delivered" now means in-flight
  awaiting ack; "acked" is terminal success; accepted/deferred removed.

- Delivery model: aligned with the canonical DeliverySchema by adding the
  missing fields seq, location_type, location_node_id, expires_at,
  delivered_at, acked_at, dead_lettered_at to match the TS SDK surface.

- channels.set_topic: corrected the route from PATCH /v1/channels/{name}
  to PATCH /v1/channels/{name}/topic to match the TS setTopic() and the
  dedicated openapi endpoint (it was colliding with channels.update).

- channels.invite: corrected the request body field from {"agent": ...}
  to {"agent_name": ...} to match InviteRequestSchema / the TS SDK wire
  shape (Python sends keys verbatim with no camel->snake conversion).

- Updated test_channels_set_topic to assert the corrected /topic route.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@willwashburn willwashburn force-pushed the codex/review-sdks-for-functionality-parity branch from 22f0e93 to faccfb4 Compare June 15, 2026 18:13
willwashburn and others added 3 commits June 15, 2026 14:42
Add the relay-level surfaces that were missing from the Swift SDK:

- nodes namespace: list (GET /v1/nodes, capability/name filters), get
  (GET /v1/nodes/{name}) with NodeRosterEntry + NodeCapability models
- triggers namespace: create/list/get/update/delete full lifecycle
  (POST/GET/PATCH/DELETE /v1/triggers[/{id}]) with Trigger,
  CreateTriggerRequest, UpdateTriggerRequest models
- activity feed: activity(limit) -> GET /v1/activity
- workspace-level DM queries: allDMConversations (GET
  /v1/dm/conversations/all) and dmMessages (GET
  /v1/dm/conversations/{id}/messages)

Fix the stale DeliveryStatus enum to the current statuses
(queued|delivered|acked|failed|dead_lettered), replacing the old
accepted/deferred values.

All routes verified present in openapi.yaml. Adds tests for nodes,
triggers, workspace DM queries, activity, and the delivery-status enum.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Bring the Rust SDK to 100% feature parity with the TypeScript reference
SDK. Every new route is documented in openapi.yaml.

New RelayCast surfaces:
- Workspace bootstrap: lookup_workspace (GET /v1/workspaces/by-name/{name})
- A2A: register_a2a, list_a2a_agents, remove_a2a_agent, get_a2a_agent_card
- Routing: route, route_feedback, get_routing_config, update_routing_config
- Directory: search_directory, publish_to_directory, list_directory,
  get_directory_agent, update_directory_agent, delete_directory_agent,
  list_directory_ratings, rate_directory_agent
- Skills: import_skills, search_skills
- Fleet nodes: list_nodes, get_node
- Triggers: create_trigger, list_triggers, get_trigger, update_trigger,
  delete_trigger
- Certification: certify, get_certification, certification_badge_url,
  monitor_certification
- Console: console_messages, console_stats (ConsoleOverview), console_agents,
  console_costs

New AgentClient surfaces:
- channels mute_channel / unmute_channel
- invite_to_channel fixed to send documented `agent_name` body

Models: added serde structs for A2A cards/records, directory agents/skills/
ratings, routing config/weights, skill search results, node roster with
capability objects, triggers, certification runs, and console stats —
all snake_case to match the wire contract.

DeliveryStatus enum updated to the canonical lifecycle
(queued|delivered|acked|failed|dead_lettered); tests updated to match.

Adds parity tests for every new surface.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (3)
packages/sdk-python/src/relay_sdk/agent.py (1)

168-169: 💤 Low value

Consider renaming input parameter to avoid shadowing Python builtin.

The parameter name input shadows the Python builtin function. While the scope is limited and the name is semantically appropriate for action invocation, renaming to input_data or action_input would satisfy linters.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/sdk-python/src/relay_sdk/agent.py` around lines 168 - 169, The
parameter name `input` in the invoke method shadows Python's builtin function.
Rename the parameter `input` to `input_data` (or a similar alternative like
`action_input`) in the method signature, and update the corresponding reference
to this parameter in the dictionary being passed to `self._client.post()` to use
the new parameter name.

Source: Linters/SAST tools

packages/sdk-python/src/relay_sdk/relay.py (1)

200-202: 💤 Low value

Inconsistent DELETE request pattern.

remove_a2a_agent uses self._client.request("DELETE", ...) while other delete methods like delete_directory_agent (line 266) use self._client.delete(...). Consider using the delete() helper for consistency.

♻️ Suggested change for consistency
     def remove_a2a_agent(self, name: str) -> RemoveA2aAgentResponse:
-        result = self._client.request("DELETE", f"/v1/a2a/agents/{_enc(name)}")
+        result = self._client.delete(f"/v1/a2a/agents/{_enc(name)}")
         return RemoveA2aAgentResponse.model_validate(result)

Note: This assumes delete() returns the response body. If delete() returns None and the endpoint returns a response body, the current request() approach is correct.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/sdk-python/src/relay_sdk/relay.py` around lines 200 - 202, The
remove_a2a_agent method uses self._client.request("DELETE", ...) while other
delete methods like delete_directory_agent use self._client.delete(...). Replace
the self._client.request("DELETE", ...) call with self._client.delete(...) to
match the pattern used by other delete methods, but first verify that the
delete() method returns the response body rather than None, since the code needs
to pass the result to RemoveA2aAgentResponse.model_validate().
packages/sdk-rust/src/relay.rs (1)

721-759: ⚡ Quick win

Consolidate workspace bootstrap request handling to avoid drift.

Line 732 introduces a second standalone bootstrap request path with duplicated header/error mapping. Please extract/reuse a shared helper with create_workspace so future contract/header changes stay consistent in both flows.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/sdk-rust/src/relay.rs` around lines 721 - 759, The lookup_workspace
function contains duplicated request handling logic (headers setup and error
mapping) that already exists in create_workspace, creating a maintenance risk.
Extract a shared helper function that encapsulates the common pattern of setting
the standard headers (Content-Type, X-SDK-Version, X-Relaycast-Origin-Client,
X-Relaycast-Origin-Version) and handling the ApiResponse error mapping logic
(checking json.ok, handling 404 status, creating default ApiErrorInfo). Refactor
both lookup_workspace and create_workspace to use this shared helper so that
future changes to request headers or error handling remain consistent across
both functions.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/sdk-python/src/relay_sdk/agent.py`:
- Around line 412-419: The `DeliveryStatus` enum is being assigned directly to
the query dictionary which expects string values, causing incorrect
serialization. In packages/sdk-python/src/relay_sdk/agent.py at lines 412-419 in
the sync `deliveries()` method, change `query["status"] = status` to
`query["status"] = status.value` to extract the string value from the enum.
Apply the identical fix in packages/sdk-python/src/relay_sdk/agent.py at lines
802-809 in the async `deliveries()` method by changing `query["status"] =
status` to `query["status"] = status.value`.

---

Nitpick comments:
In `@packages/sdk-python/src/relay_sdk/agent.py`:
- Around line 168-169: The parameter name `input` in the invoke method shadows
Python's builtin function. Rename the parameter `input` to `input_data` (or a
similar alternative like `action_input`) in the method signature, and update the
corresponding reference to this parameter in the dictionary being passed to
`self._client.post()` to use the new parameter name.

In `@packages/sdk-python/src/relay_sdk/relay.py`:
- Around line 200-202: The remove_a2a_agent method uses
self._client.request("DELETE", ...) while other delete methods like
delete_directory_agent use self._client.delete(...). Replace the
self._client.request("DELETE", ...) call with self._client.delete(...) to match
the pattern used by other delete methods, but first verify that the delete()
method returns the response body rather than None, since the code needs to pass
the result to RemoveA2aAgentResponse.model_validate().

In `@packages/sdk-rust/src/relay.rs`:
- Around line 721-759: The lookup_workspace function contains duplicated request
handling logic (headers setup and error mapping) that already exists in
create_workspace, creating a maintenance risk. Extract a shared helper function
that encapsulates the common pattern of setting the standard headers
(Content-Type, X-SDK-Version, X-Relaycast-Origin-Client,
X-Relaycast-Origin-Version) and handling the ApiResponse error mapping logic
(checking json.ok, handling 404 status, creating default ApiErrorInfo). Refactor
both lookup_workspace and create_workspace to use this shared helper so that
future changes to request headers or error handling remain consistent across
both functions.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: db9d69d1-90f8-4413-a875-c6012214b7b3

📥 Commits

Reviewing files that changed from the base of the PR and between 495a7af and 66798ac.

📒 Files selected for processing (13)
  • packages/sdk-python/src/relay_sdk/agent.py
  • packages/sdk-python/src/relay_sdk/client.py
  • packages/sdk-python/src/relay_sdk/models.py
  • packages/sdk-python/src/relay_sdk/relay.py
  • packages/sdk-python/tests/test_agent.py
  • packages/sdk-rust/src/agent.rs
  • packages/sdk-rust/src/lib.rs
  • packages/sdk-rust/src/relay.rs
  • packages/sdk-rust/src/types.rs
  • packages/sdk-rust/tests/parity.rs
  • packages/sdk-swift/Sources/Relaycast/Models.swift
  • packages/sdk-swift/Sources/Relaycast/RelayCast.swift
  • packages/sdk-swift/Tests/RelaycastTests/RelaycastTests.swift
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/sdk-python/src/relay_sdk/client.py
  • packages/sdk-python/src/relay_sdk/models.py

Comment on lines +412 to +419
def deliveries(self, *, status: DeliveryStatus | None = None, limit: int | None = None) -> list[DeliveryItem]:
query: dict[str, str] = {}
if status:
query["status"] = status
if limit is not None:
query["limit"] = str(limit)
result = self.client.get("/v1/deliveries", query or None)
return [DeliveryItem.model_validate(d) for d in result]

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Type mismatch: DeliveryStatus enum assigned where str is expected. Both sync and async deliveries() methods assign the DeliveryStatus enum directly to the query dictionary, which expects string values. This will serialize incorrectly (e.g., "DeliveryStatus.queued" instead of "queued").

  • packages/sdk-python/src/relay_sdk/agent.py#L412-L419: Change query["status"] = status to query["status"] = status.value in sync deliveries().
  • packages/sdk-python/src/relay_sdk/agent.py#L802-L809: Apply the same fix in async deliveries().
📍 Affects 1 file
  • packages/sdk-python/src/relay_sdk/agent.py#L412-L419 (this comment)
  • packages/sdk-python/src/relay_sdk/agent.py#L802-L809
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/sdk-python/src/relay_sdk/agent.py` around lines 412 - 419, The
`DeliveryStatus` enum is being assigned directly to the query dictionary which
expects string values, causing incorrect serialization. In
packages/sdk-python/src/relay_sdk/agent.py at lines 412-419 in the sync
`deliveries()` method, change `query["status"] = status` to `query["status"] =
status.value` to extract the string value from the enum. Apply the identical fix
in packages/sdk-python/src/relay_sdk/agent.py at lines 802-809 in the async
`deliveries()` method by changing `query["status"] = status` to `query["status"]
= status.value`.

@willwashburn willwashburn merged commit f374f18 into main Jun 15, 2026
5 checks passed
@willwashburn willwashburn deleted the codex/review-sdks-for-functionality-parity branch June 15, 2026 19:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant