Skip to content

Add reusable Rust SDK relay helpers#134

Merged
willwashburn merged 2 commits into
mainfrom
codex/rust-sdk-relay-helpers
May 19, 2026
Merged

Add reusable Rust SDK relay helpers#134
willwashburn merged 2 commits into
mainfrom
codex/rust-sdk-relay-helpers

Conversation

@willwashburn
Copy link
Copy Markdown
Member

Summary

  • add raw websocket event subscriptions and SDK-owned event normalization helpers
  • add reusable agent registration, identity, channel ensure/join, and DM participant cache helpers
  • document the new Rust SDK surface without bumping the crate version

Tests

  • cargo test

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 19, 2026

Review Change Stack

Warning

Rate limit exceeded

@willwashburn has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 51 minutes and 45 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 73a38c51-1947-4867-9803-20a3d0af77ab

📥 Commits

Reviewing files that changed from the base of the PR and between bb4e0e5 and a667080.

📒 Files selected for processing (2)
  • packages/sdk-rust/src/lib.rs
  • packages/sdk-rust/src/ws.rs
📝 Walkthrough

Walkthrough

Adds raw WebSocket event subscription, stable event normalization types and functions, identity comparison helpers, DM participant caching, idempotent channel/agent creation helpers, and expands the public API. Includes documentation and parity tests.

Changes

Rust SDK event normalization and client enhancements

Layer / File(s) Summary
WebSocket raw event infrastructure
packages/sdk-rust/src/ws.rs
WsClient adds broadcast channel infrastructure for raw JSON events. Text frames are parsed to serde_json::Value, broadcast to raw subscribers, then independently decoded as typed WsEvent. New subscribe_raw_events() method and RawEventReceiver type exposed.
Event normalization types and implementation
packages/sdk-rust/src/events.rs
Defines NormalizedEventKind, SenderKind, RelayPriority, NormalizedInboundEvent, and NormalizedCommandInvocation structures. Implements normalize_inbound_event to transform raw JSON into routable events with sender classification, priority assignment, and special DM/reaction/presence handling. Includes internal EventAccessor abstraction and helpers for field extraction, event id synthesis, and sender identity normalization. Comprehensive unit tests validate normalization paths.
Identity comparison utilities
packages/sdk-rust/src/identity.rs
Adds agent_name_eq for case-insensitive name equality and is_self_name to check whether a name matches any candidate from an iterator.
DM participant caching with TTL and eviction
packages/sdk-rust/src/dm_participants.rs
Implements DmParticipantsCache, an in-memory bounded cache for DM conversation participants keyed by workspace_id:conversation_id. Supports configurable success/failure TTLs and max capacity. When at capacity, evicts oldest entry by timestamp. Provides async resolve with caching logic and resolve_or_empty that converts failures to empty lists with warnings.
Agent client channel and registration helpers
packages/sdk-rust/src/agent.rs, packages/sdk-rust/tests/parity.rs
Adds EnsureChannelOutcome struct to report channel creation and join status. Implements ensure_joined_channel and ensure_joined_channels to idempotently create/join channels while treating HTTP 409 conflicts as success. Reformats existing dm/dm_typed/send_dm_message/send_dm_message_typed methods for readability without changing behavior. Parity test verifies 409 conflict handling.
Registration client token helper and agent creation
packages/sdk-rust/src/registration.rs
Adds registered_agent_client to AgentRegistrationClient, which obtains (or reuses cached) a registered token and converts it to an AgentClient via relay.as_agent. Includes test verifying token caching and client configuration.
Public module and type exports
packages/sdk-rust/src/lib.rs
Expands module declarations to include dm_participants, events, and identity. Re-exports normalized event types (NormalizedEventKind, SenderKind, RelayPriority, NormalizedInboundEvent, NormalizedCommandInvocation), normalization helpers (normalize_inbound_event, normalize_command_invocation, normalize_sender_identity), cache types (DmParticipantsCache, DmParticipantsCacheEntry) and TTL constants, identity utilities, EnsureChannelOutcome, and RawEventReceiver.
CHANGELOG and README examples
packages/sdk-rust/CHANGELOG.md, packages/sdk-rust/README.md
Documents new Unreleased features in CHANGELOG. Updates README with ensure_joined_channel example, raw WebSocket event subscription and normalization example, and AgentRegistrationClient usage example.

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant WsClient
  participant RawBroadcast as Raw Events
  participant Normalizer
  participant TypedBroadcast as Typed Events
  Client->>WsClient: subscribe_raw_events()
  WsClient-->>Client: RawEventReceiver
  Note over WsClient: incoming text frame
  WsClient->>RawBroadcast: broadcast raw JSON Value
  Client->>Normalizer: normalize_inbound_event(raw_json)
  Normalizer->>Normalizer: extract sender, target, kind, priority
  Normalizer-->>Client: NormalizedInboundEvent
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Poem

🐰 Raw events now stream through the socket wide,
Normalized and typed, no secrets to hide,
Cache keeps DMs swift, identities match with care,
Idempotent joins and registration—SDK's everywhere!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main changes: addition of reusable Rust SDK relay helpers including WebSocket events, event normalization, registration, identity, channel, and DM cache utilities.
Description check ✅ Passed The description is directly related to the changeset, covering the three main areas: raw WebSocket event subscriptions, event normalization, reusable helpers, and documentation updates.
Docstring Coverage ✅ Passed Docstring coverage is 80.00% which is sufficient. The required threshold is 80.00%.
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/rust-sdk-relay-helpers

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.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

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 (1)
packages/sdk-rust/src/lib.rs (1)

1-66: ⚡ Quick win

Consider adding examples for new features in top-level documentation.

The doc comment examples demonstrate the Quick Start and basic WebSocket event handling, but don't showcase the newly added features (raw event subscription, event normalization, registration helpers, or ensure_joined_channel). Users browsing the crate documentation would benefit from seeing these patterns here.

📚 Suggested documentation additions

Consider adding a third example section after the WebSocket Events example:

//! ## Raw Events and Normalization
//!
//! ```rust,no_run
//! use relaycast::{normalize_inbound_event, WsClient, WsClientOptions};
//!
//! #[tokio::main]
//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
//!     let mut ws = WsClient::new(WsClientOptions::new("at_live_agent_token"));
//!     let mut raw_events = ws.subscribe_raw_events();
//!     ws.connect().await?;
//!
//!     while let Ok(raw) = raw_events.recv().await {
//!         if let Some(event) = normalize_inbound_event(&raw) {
//!             println!("{} -> {}: {}", event.from, event.target, event.text);
//!         }
//!     }
//!
//!     Ok(())
//! }
//! ```
🤖 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/lib.rs` around lines 1 - 66, Add a new documentation
example showing the newly added features: create a short third example titled
"Raw Events and Normalization" that demonstrates using WsClient and
WsClientOptions to connect, calling subscribe_raw_events (or the actual raw
subscription method), receiving raw events, and passing them to
normalize_inbound_event to produce normalized events; also show a brief snippet
using the registration helpers (e.g., RegisterAgent/registration helper
function) and calling ensure_joined_channel to guarantee the agent is in a
channel before sending messages so users can see the end-to-end flow. Reference
the symbols WsClient, WsClientOptions, subscribe_raw_events,
normalize_inbound_event, ensure_joined_channel, and the registration helper
functions/classes so the example maps directly to the new APIs.
🤖 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-rust/src/ws.rs`:
- Around line 347-354: The log truncation currently uses a byte-slice
&text[..text.len().min(200)] which can panic on multi-byte UTF-8 boundaries; add
a safe truncation helper (e.g., fn truncate_str(s: &str, max_chars: usize) ->
&str { ... }) near reconnect_delay_ms and replace occurrences of
&text[..text.len().min(200)] in the WebSocket message handler (the warn! calls
that log dropped messages in ws.rs) with truncate_str(&text, 200) so you
truncate by character boundaries instead of bytes.

---

Nitpick comments:
In `@packages/sdk-rust/src/lib.rs`:
- Around line 1-66: Add a new documentation example showing the newly added
features: create a short third example titled "Raw Events and Normalization"
that demonstrates using WsClient and WsClientOptions to connect, calling
subscribe_raw_events (or the actual raw subscription method), receiving raw
events, and passing them to normalize_inbound_event to produce normalized
events; also show a brief snippet using the registration helpers (e.g.,
RegisterAgent/registration helper function) and calling ensure_joined_channel to
guarantee the agent is in a channel before sending messages so users can see the
end-to-end flow. Reference the symbols WsClient, WsClientOptions,
subscribe_raw_events, normalize_inbound_event, ensure_joined_channel, and the
registration helper functions/classes so the example maps directly to the new
APIs.
🪄 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: 4e50dd88-dc2d-424e-869e-2875ec2f279a

📥 Commits

Reviewing files that changed from the base of the PR and between 9bc9630 and bb4e0e5.

📒 Files selected for processing (10)
  • packages/sdk-rust/CHANGELOG.md
  • packages/sdk-rust/README.md
  • packages/sdk-rust/src/agent.rs
  • packages/sdk-rust/src/dm_participants.rs
  • packages/sdk-rust/src/events.rs
  • packages/sdk-rust/src/identity.rs
  • packages/sdk-rust/src/lib.rs
  • packages/sdk-rust/src/registration.rs
  • packages/sdk-rust/src/ws.rs
  • packages/sdk-rust/tests/parity.rs

Comment thread packages/sdk-rust/src/ws.rs Outdated
@github-actions
Copy link
Copy Markdown

Preview deployed!

Environment URL
API https://pr134-api.relaycast.dev
Health https://pr134-api.relaycast.dev/health
Observer https://pr134-observer.relaycast.dev/observer

This preview shares the staging database and will be cleaned up when the PR is merged or closed.

Run E2E tests

npm run e2e -- https://pr134-api.relaycast.dev --ci

Open observer dashboard

https://pr134-observer.relaycast.dev/observer

Copy link
Copy Markdown

@devin-ai-integration devin-ai-integration Bot left a comment

Choose a reason for hiding this comment

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

Devin Review found 1 potential issue.

View 5 additional findings in Devin Review.

Open in Devin Review

Comment thread packages/sdk-rust/src/ws.rs Outdated
@willwashburn
Copy link
Copy Markdown
Member Author

Addressed review bot feedback in a667080:

  • Fixed the WebSocket log truncation panic by replacing byte-index slices with a char-boundary-safe truncate_str helper.
  • Added unit coverage for UTF-8 truncation.
  • Added crate-level docs examples for raw event normalization and registration/channel startup helpers.

Local validation: cargo test and git diff --check pass.

@willwashburn willwashburn merged commit d4af8e1 into main May 19, 2026
6 checks passed
@willwashburn willwashburn deleted the codex/rust-sdk-relay-helpers branch May 19, 2026 12:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant