Skip to content

Comments

sdk-rust: add reconnect lifecycle and DM parity APIs#50

Merged
willwashburn merged 1 commit intomainfrom
rust-sdk-improvements
Feb 22, 2026
Merged

sdk-rust: add reconnect lifecycle and DM parity APIs#50
willwashburn merged 1 commit intomainfrom
rust-sdk-improvements

Conversation

@willwashburn
Copy link
Member

Summary

  • add reconnect/lifecycle support to the Rust WebSocket client, including automatic re-subscribe of channels
  • add runtime token update support across AgentClient and WsClient
  • add typed DM helper APIs and DM response structs in the Rust SDK
  • align DM parsing/payload parity (participants/last_message compatibility and agent_name participant payload)
  • update the Rust SDK changelog with 0.2.5 release notes

Testing

  • cargo test (in packages/sdk-rust)

@github-actions
Copy link

Preview deployed!

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

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://pr50-api.relaycast.dev --ci

Open observer dashboard

https://pr50-observer.relaycast.dev

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adds WebSocket reconnection lifecycle support, runtime token updates, and typed DM helper APIs to the Rust SDK. The changes enable long-lived agents to handle connection failures gracefully with automatic reconnection and channel re-subscription, while also improving the ergonomics of DM-related operations.

Changes:

  • Added WebSocket lifecycle events (Open, Close, Error, Reconnecting) with automatic reconnection using exponential backoff
  • Added runtime token update support via AgentClient::set_token() and WsClient::set_token() for long-lived clients
  • Added typed DM helper methods (dm_typed, create_group_dm_typed, send_dm_message_typed, add_dm_participant_typed) with corresponding response structs, fixing the agent_name payload compatibility issue

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
packages/sdk-rust/src/ws.rs Implements WebSocket reconnection logic with exponential backoff, lifecycle events, token updates, and automatic channel re-subscription
packages/sdk-rust/src/types.rs Adds typed DM response structs and custom deserializers for flexible participant/last_message parsing
packages/sdk-rust/src/agent.rs Adds typed DM helper methods, token update propagation, and fixes add_dm_participant payload to use agent_name
packages/sdk-rust/src/lib.rs Exports new lifecycle types and DM response structs
packages/sdk-rust/tests/parity.rs Adds tests for DM deserialization parity and agent_name payload compatibility
packages/sdk-rust/CHANGELOG.md Documents 0.2.5 release with all new features and changes

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 224 to 226
*is_connected.lock().await = true;

// Spawn the WebSocket handler task
Copy link

Copilot AI Feb 22, 2026

Choose a reason for hiding this comment

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

The initial WebSocket connection does not emit a WsLifecycleEvent::Open event. The Open event is only sent during reconnections (line 301), not during the initial connection. This creates inconsistent behavior where lifecycle subscribers won't receive an Open event for the first connection. Consider sending an Open event after setting is_connected to true and before spawning the task, or ensuring the spawned task sends it for both initial and reconnect scenarios.

Copilot uses AI. Check for mistakes.
Comment on lines +40 to +41
/// Maximum reconnect delay in milliseconds (default: 30000).
pub max_reconnect_delay_ms: Option<u64>,
Copy link

Copilot AI Feb 22, 2026

Choose a reason for hiding this comment

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

The reconnect_delay_ms function enforces a minimum delay of 1000ms even if max_reconnect_delay_ms is set lower. This behavior is not documented in the field's doc comment (line 40) or the setter method (line 90-93). Consider documenting this minimum to avoid user confusion, for example: "Maximum reconnect delay in milliseconds (default: 30000, minimum: 1000)".

Copilot uses AI. Check for mistakes.
Comment on lines +262 to +265
reconnect_attempt += 1;
let _ = lifecycle_tx.send(WsLifecycleEvent::Reconnecting {
attempt: reconnect_attempt,
});
Copy link

Copilot AI Feb 22, 2026

Choose a reason for hiding this comment

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

The reconnect attempt counter is incremented in two places: once after a connection drops (line 401) and again if the subsequent reconnect fails (line 262). This can lead to double-counting reconnect attempts. For example, if a connection drops and the first reconnect attempt fails, the counter goes from 0→1→2, emitting two Reconnecting lifecycle events (attempt 1 and attempt 2) for what is logically a single reconnect cycle. This also means max_reconnect_attempts is effectively halved in scenarios with repeated connection failures.

Consider restructuring the logic so that the attempt counter is only incremented once per reconnect cycle, not both when entering the reconnect loop AND when a connection attempt fails.

Suggested change
reconnect_attempt += 1;
let _ = lifecycle_tx.send(WsLifecycleEvent::Reconnecting {
attempt: reconnect_attempt,
});

Copilot uses AI. Check for mistakes.
@willwashburn willwashburn merged commit be9b002 into main Feb 22, 2026
7 checks passed
@willwashburn willwashburn deleted the rust-sdk-improvements branch February 22, 2026 16:08
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