Files
codex/codex-rs/cloud-client/src/wire.rs
T
Benjamin Carlsson 3e743d1578 Add cloud thread activation with resolved settings (#59343)
## What changed

Add `Client::activate` to load a cloud thread through `UpdateConfig`, sending only the thread ID and `exclude_turns=true`. Return serializable resolved settings, thread metadata, and history cursors while leaving turns for separate pagination. Preserve the original thread protobuf, including unknown fields.

Validate required fields and thread identity, reject unsupported security policies, and redact sensitive activation data in debug output. Treat activation as a mutation that is never retried, with uncertain outcomes reported through `MutationError::OutcomeUnknown`.

## Testing

Add coverage for activation request encoding, settings and metadata preservation, serialization, compatibility defaults, unsupported policies, debug redaction, invalid input rejection, and explicit successful gRPC trailers.

GitOrigin-RevId: cd925b7a05f518d782e5b4cf188556567dad9e21
2026-11-04 07:26:51 +00:00

58 lines
1.7 KiB
Rust

//! Minimal ThreadService protobuf envelopes; field numbers are the wire contract.
//! Length-delimited nested events remain intact, including unknown protobuf fields.
use bytes::Buf;
use bytes::Bytes;
use prost::Message;
use std::marker::PhantomData;
use tonic::codec::Codec;
#[derive(Clone, prost::Message)]
pub(crate) struct ResumeResponse {}
#[derive(Clone, prost::Message)]
pub(crate) struct AttachRequest {
#[prost(string, tag = "1")]
pub thread_id: String,
}
#[derive(Clone, prost::Message)]
pub(crate) struct AttachResponse {
#[prost(oneof = "Payload", tags = "1, 2")]
pub event: Option<Payload>,
}
#[derive(Clone, prost::Oneof)]
pub(crate) enum Payload {
#[prost(bytes = "bytes", tag = "1")]
Notification(bytes::Bytes),
#[prost(bytes = "bytes", tag = "2")]
ServerRequest(bytes::Bytes),
}
// Tonic enforces message bounds and status trailers while callers decode the raw payload.
pub(super) struct RawResponseCodec<T>(pub PhantomData<T>);
impl<T: Message + Send + 'static> Codec for RawResponseCodec<T> {
type Encode = T;
type Decode = Bytes;
type Encoder = tonic_prost::ProstEncoder<T>;
type Decoder = RawDecoder;
fn encoder(&mut self) -> Self::Encoder {
tonic_prost::ProstCodec::<T, ResumeResponse>::default().encoder()
}
fn decoder(&mut self) -> Self::Decoder {
RawDecoder
}
}
pub(super) struct RawDecoder;
impl tonic::codec::Decoder for RawDecoder {
type Item = Bytes;
type Error = tonic::Status;
fn decode(
&mut self,
buffer: &mut tonic::codec::DecodeBuf<'_>,
) -> Result<Option<Bytes>, tonic::Status> {
Ok(Some(buffer.copy_to_bytes(buffer.remaining())))
}
}