Expose typed message sources across all SDKs - #2550
Conversation
Add opt-in user/system source builders for MessageOptions and SendRequest while preserving default payloads and existing send semantics. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Copilot review overview
🟢 Approval recommended
The implementation is compatible, focused, documented, and comprehensively tested.
Review tier: Balanced
Findings: None
What changed in this PR
Adds typed Rust message provenance while preserving existing wire behavior.
Changes:
- Adds
MessageSource::{User, System}and builders for both send APIs. - Serializes explicit sources while omitting unset values.
- Documents and thoroughly tests payload, waiting, error, and tracing behavior.
| File | Description |
|---|---|
rust/src/types.rs |
Defines typed sources and extends MessageOptions. |
rust/src/session.rs |
Adds source to outgoing requests when set. |
rust/src/rpc.rs |
Adds the raw RPC request builder. |
rust/tests/session_test.rs |
Covers serialization and behavioral compatibility. |
rust/README.md |
Documents both supported send paths. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Expose optional typed user/system provenance in Node.js, Python, Go, .NET and Java, preserving omitted defaults, clone behavior and existing send-and-wait semantics. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
This comment has been minimized.
This comment has been minimized.
Convert invalid Content-Length numbers to IOException and reject negative lengths, with regression coverage for malformed and overflowing values. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
SDK Consistency Review — PR #2550 (
|
| SDK | Type | Field on MessageOptions/equivalent |
Wire field | Default when unset |
|---|---|---|---|---|
| Node.js/TS | export type MessageSource = "user" | "system" |
source?: MessageSource |
source |
omitted |
| Python | MessageSource = Literal["user", "system"] |
source: MessageSource | None (kwarg on send/send_and_wait) |
source (only added to params if not None) |
omitted |
| Go | type MessageSource string w/ MessageSourceUser/MessageSourceSystem consts |
Source MessageSource on MessageOptions |
source,omitempty |
omitted (empty string) |
| .NET | enum MessageSource { User, System } w/ JsonStringEnumConverter |
MessageSource? Source on MessageOptions |
Source (nullable, serializer omits when null) |
omitted |
| Java | enum MessageSource { USER, SYSTEM } w/ @JsonValue/@JsonCreator |
MessageSource source w/ getter/fluent setter on MessageOptions, propagated to SendMessageRequest |
source |
omitted (null) |
| Rust | pub enum MessageSource { User, System } (#[non_exhaustive], serde lowercase) |
pub source: Option<MessageSource> + with_source() builder on MessageOptions; also a SendRequest::with_source() helper in rpc.rs |
source (only inserted into JSON if Some) |
omitted |
Observations:
- Naming follows each language's idiom correctly (
camelCasefield in TS/Java,snake_casein Python/Rust,PascalCaseproperty in Go/.NET, with wire-level JSON key uniformlysource/"user"/"system"). - Semantics are identical everywhere:
Sourceis independent ofMode/AgentMode, defaults to omitted (runtime treats as user message) when unset. - Tests were added in parallel for every SDK (
message_source_test.go,MessageSourceTest.java,message-source.test.ts,test_session.pyadditions,session_test.rs,.NETlifetime/clone tests) and each README was updated with matching documentation. - Minor non-issue: Rust additionally exposes a
SendRequest::with_source()helper in the low-levelrpc.rs(generated RPC layer) alongside the higher-levelMessageOptions::with_source()— this is Rust-specific plumbing for the generated request type and doesn't need a mirror in other SDKs.
No cross-language inconsistencies found. This is a clean, well-synchronized feature addition across all six SDKs — no changes requested.
Generated by SDK Consistency Review Agent for #2550 · copilot · sonnet50 · 24.9 AIC · ⌖ 12.9 AIC · ⊞ 9.7K · ◷
Applications need to distinguish automated messages from human input when using ordinary
session.send. The runtime already acceptssource, but the SDKs' high-level send APIs did not expose it.Add an optional
MessageSourceAPI across all six SDKs. Unset source remains omitted, preserving existing human-message payloads. Explicit values serialize as"user"or"system".MessageSourceunion andMessageOptions.sourceMessageSourceliteral type andsource=onsend/send_and_waitMessageSourceUser/MessageSourceSystemandMessageOptions.SourceMessageOptions.SourcewithMessageSource.User/SystemMessageOptions.setSource(MessageSource.USER / SYSTEM)MessageOptions::with_sourceand handwrittenrpc::SendRequest::with_sourcewithMessageSource::{User, System}Send-and-wait methods forward the same option without changing completion or error handling. Java and .NET clones retain source. Rust's raw request builder sets its existing crate-visible field; generated RPC code stays untouched. Each language README includes usage guidance.
This does not change runtime/schema files, CLI pins, dependencies, billing flags, hooks, delivery modes, or system-prompt configuration. Both human and automated messages still use ordinary
session.send, not the dedicated notification API.Coverage
Focused regressions cover default omission, explicit user/system serialization, companion options and tracing where supported, clone preservation, idle completion without assistant output, and genuine errors. Existing waiter behavior remains covered.