diff --git a/codex-rs/core/src/thread_manager.rs b/codex-rs/core/src/thread_manager.rs index af7c3023ed63..55071f19fe3e 100644 --- a/codex-rs/core/src/thread_manager.rs +++ b/codex-rs/core/src/thread_manager.rs @@ -242,7 +242,7 @@ pub fn build_models_manager( } fn configured_thread_store(config: &Config) -> Arc { - if let Some(endpoint) = config.experimental_thread_store_endpoint.clone() { + if let Some(endpoint) = config.experimental_thread_store_endpoint.as_deref() { return Arc::new(RemoteThreadStore::new(endpoint)); } Arc::new(LocalThreadStore::new(RolloutConfig::from_view(config))) diff --git a/codex-rs/thread-store/src/remote/helpers.rs b/codex-rs/thread-store/src/remote/helpers.rs index c02889e16828..5f5bf503a3dc 100644 --- a/codex-rs/thread-store/src/remote/helpers.rs +++ b/codex-rs/thread-store/src/remote/helpers.rs @@ -6,15 +6,25 @@ use chrono::Utc; use codex_git_utils::GitSha; use codex_protocol::AgentPath; use codex_protocol::ThreadId; +use codex_protocol::dynamic_tools::DynamicToolSpec; +use codex_protocol::models::BaseInstructions; use codex_protocol::openai_models::ReasoningEffort; use codex_protocol::protocol::AskForApproval; use codex_protocol::protocol::GitInfo; +use codex_protocol::protocol::RolloutItem; use codex_protocol::protocol::SandboxPolicy; use codex_protocol::protocol::SessionSource; use codex_protocol::protocol::SubAgentSource; +use codex_protocol::protocol::ThreadMemoryMode; use super::proto; +use crate::GitInfoPatch; +use crate::OptionalStringPatch; +use crate::SortDirection; use crate::StoredThread; +use crate::StoredThreadHistory; +use crate::ThreadEventPersistenceMode; +use crate::ThreadMetadataPatch; use crate::ThreadSortKey; use crate::ThreadStoreError; use crate::ThreadStoreResult; @@ -35,6 +45,22 @@ pub(super) fn remote_status_to_error(status: tonic::Status) -> ThreadStoreError } } +pub(super) fn remote_status_to_thread_error( + status: tonic::Status, + thread_id: ThreadId, +) -> ThreadStoreError { + if status.code() == tonic::Code::NotFound { + return ThreadStoreError::ThreadNotFound { thread_id }; + } + remote_status_to_error(status) +} + +pub(super) fn proto_thread_id_request(thread_id: ThreadId) -> proto::ThreadIdRequest { + proto::ThreadIdRequest { + thread_id: thread_id.to_string(), + } +} + pub(super) fn proto_sort_key(sort_key: ThreadSortKey) -> proto::ThreadSortKey { match sort_key { ThreadSortKey::CreatedAt => proto::ThreadSortKey::CreatedAt, @@ -42,6 +68,22 @@ pub(super) fn proto_sort_key(sort_key: ThreadSortKey) -> proto::ThreadSortKey { } } +pub(super) fn proto_sort_direction(sort_direction: SortDirection) -> proto::SortDirection { + match sort_direction { + SortDirection::Asc => proto::SortDirection::Asc, + SortDirection::Desc => proto::SortDirection::Desc, + } +} + +pub(super) fn proto_event_persistence_mode( + mode: ThreadEventPersistenceMode, +) -> proto::ThreadEventPersistenceMode { + match mode { + ThreadEventPersistenceMode::Limited => proto::ThreadEventPersistenceMode::Limited, + ThreadEventPersistenceMode::Extended => proto::ThreadEventPersistenceMode::Extended, + } +} + pub(super) fn proto_session_source(source: &SessionSource) -> proto::SessionSource { match source { SessionSource::Cli => proto_source(proto::SessionSourceKind::Cli), @@ -93,6 +135,114 @@ fn proto_source(kind: proto::SessionSourceKind) -> proto::SessionSource { } } +pub(super) fn serialize_json( + value: &T, + field_name: &str, +) -> ThreadStoreResult { + serde_json::to_string(value).map_err(|err| ThreadStoreError::InvalidRequest { + message: format!("failed to serialize {field_name} for remote thread store: {err}"), + }) +} + +fn deserialize_json( + json: &str, + field_name: &str, +) -> ThreadStoreResult { + serde_json::from_str(json).map_err(|err| ThreadStoreError::InvalidRequest { + message: format!("remote thread store returned invalid {field_name}: {err}"), + }) +} + +pub(super) fn serialize_json_vec( + values: &[T], + field_name: &str, +) -> ThreadStoreResult> { + values + .iter() + .map(|value| serialize_json(value, field_name)) + .collect() +} + +fn deserialize_json_vec( + values: &[String], + field_name: &str, +) -> ThreadStoreResult> { + values + .iter() + .map(|value| deserialize_json(value, field_name)) + .collect() +} + +pub(super) fn base_instructions_json( + base_instructions: &BaseInstructions, +) -> ThreadStoreResult { + serialize_json(base_instructions, "base_instructions") +} + +pub(super) fn dynamic_tools_json( + dynamic_tools: &[DynamicToolSpec], +) -> ThreadStoreResult> { + serialize_json_vec(dynamic_tools, "dynamic_tool") +} + +pub(super) fn rollout_items_json(items: &[RolloutItem]) -> ThreadStoreResult> { + serialize_json_vec(items, "rollout_item") +} + +pub(super) fn stored_thread_history_from_proto( + history: proto::StoredThreadHistory, +) -> ThreadStoreResult { + let thread_id = ThreadId::from_string(&history.thread_id).map_err(|err| { + ThreadStoreError::InvalidRequest { + message: format!("remote thread store returned invalid history thread_id: {err}"), + } + })?; + Ok(StoredThreadHistory { + thread_id, + items: deserialize_json_vec(&history.items_json, "rollout_item")?, + }) +} + +pub(super) fn proto_metadata_patch(patch: ThreadMetadataPatch) -> proto::ThreadMetadataPatch { + proto::ThreadMetadataPatch { + name: patch.name, + memory_mode: patch.memory_mode.map(proto_memory_mode).map(Into::into), + git_info: patch.git_info.map(proto_git_info_patch), + } +} + +fn proto_memory_mode(memory_mode: ThreadMemoryMode) -> proto::ThreadMemoryMode { + match memory_mode { + ThreadMemoryMode::Enabled => proto::ThreadMemoryMode::Enabled, + ThreadMemoryMode::Disabled => proto::ThreadMemoryMode::Disabled, + } +} + +fn proto_git_info_patch(patch: GitInfoPatch) -> proto::GitInfoPatch { + proto::GitInfoPatch { + sha: Some(proto_optional_string_patch(patch.sha)), + branch: Some(proto_optional_string_patch(patch.branch)), + origin_url: Some(proto_optional_string_patch(patch.origin_url)), + } +} + +fn proto_optional_string_patch(patch: OptionalStringPatch) -> proto::OptionalStringPatch { + match patch { + None => proto::OptionalStringPatch { + kind: proto::OptionalStringPatchKind::Unset.into(), + value: None, + }, + Some(None) => proto::OptionalStringPatch { + kind: proto::OptionalStringPatchKind::Clear.into(), + value: None, + }, + Some(Some(value)) => proto::OptionalStringPatch { + kind: proto::OptionalStringPatchKind::Set.into(), + value: Some(value), + }, + } +} + pub(super) fn stored_thread_from_proto( thread: proto::StoredThread, ) -> ThreadStoreResult { @@ -121,7 +271,7 @@ pub(super) fn stored_thread_from_proto( Ok(StoredThread { thread_id, - rollout_path: None, + rollout_path: thread.rollout_path.map(PathBuf::from), forked_from_id, preview: thread.preview, name: thread.name, @@ -142,11 +292,28 @@ pub(super) fn stored_thread_from_proto( agent_role: thread.agent_role, agent_path: thread.agent_path, git_info: thread.git_info.map(git_info_from_proto), - approval_mode: AskForApproval::OnRequest, - sandbox_policy: SandboxPolicy::new_read_only_policy(), - token_usage: None, + approval_mode: thread + .approval_mode_json + .as_deref() + .map(|json| deserialize_json(json, "approval_mode")) + .transpose()? + .unwrap_or(AskForApproval::OnRequest), + sandbox_policy: thread + .sandbox_policy_json + .as_deref() + .map(|json| deserialize_json(json, "sandbox_policy")) + .transpose()? + .unwrap_or_else(SandboxPolicy::new_read_only_policy), + token_usage: thread + .token_usage_json + .as_deref() + .map(|json| deserialize_json(json, "token_usage")) + .transpose()?, first_user_message: thread.first_user_message, - history: None, + history: thread + .history + .map(stored_thread_history_from_proto) + .transpose()?, }) } @@ -171,6 +338,26 @@ pub(super) fn stored_thread_to_proto(thread: StoredThread) -> proto::StoredThrea agent_path: thread.agent_path, reasoning_effort: thread.reasoning_effort.map(|effort| effort.to_string()), first_user_message: thread.first_user_message, + rollout_path: thread + .rollout_path + .map(|path| path.to_string_lossy().into_owned()), + approval_mode_json: Some(serialize_json(&thread.approval_mode, "approval_mode").unwrap()), + sandbox_policy_json: Some( + serialize_json(&thread.sandbox_policy, "sandbox_policy").unwrap(), + ), + token_usage_json: thread + .token_usage + .as_ref() + .map(|usage| serialize_json(usage, "token_usage").unwrap()), + history: thread.history.map(stored_thread_history_to_proto), + } +} + +#[cfg(test)] +fn stored_thread_history_to_proto(history: StoredThreadHistory) -> proto::StoredThreadHistory { + proto::StoredThreadHistory { + thread_id: history.thread_id.to_string(), + items_json: rollout_items_json(&history.items).unwrap(), } } diff --git a/codex-rs/thread-store/src/remote/list_threads.rs b/codex-rs/thread-store/src/remote/list_threads.rs index cbccb792f7a1..7fb0da6dc3e9 100644 --- a/codex-rs/thread-store/src/remote/list_threads.rs +++ b/codex-rs/thread-store/src/remote/list_threads.rs @@ -1,5 +1,6 @@ use super::RemoteThreadStore; use super::helpers::proto_session_source; +use super::helpers::proto_sort_direction; use super::helpers::proto_sort_key; use super::helpers::remote_status_to_error; use super::helpers::stored_thread_from_proto; @@ -22,6 +23,7 @@ pub(super) async fn list_threads( })?, cursor: params.cursor, sort_key: proto_sort_key(params.sort_key).into(), + sort_direction: proto_sort_direction(params.sort_direction).into(), allowed_sources: params .allowed_sources .iter() @@ -96,6 +98,10 @@ mod tests { proto::ThreadSortKey::try_from(request.sort_key), Ok(proto::ThreadSortKey::UpdatedAt) ); + assert_eq!( + proto::SortDirection::try_from(request.sort_direction), + Ok(proto::SortDirection::Desc) + ); assert_eq!(request.archived, true); assert_eq!(request.search_term.as_deref(), Some("needle")); assert!(request.use_state_db_only); @@ -144,6 +150,11 @@ mod tests { agent_path: None, reasoning_effort: Some("medium".to_string()), first_user_message: Some("hello".to_string()), + rollout_path: None, + approval_mode_json: None, + sandbox_policy_json: None, + token_usage_json: None, + history: None, }], next_cursor: Some("cursor-2".to_string()), })) @@ -249,12 +260,21 @@ mod tests { agent_path: Some("/root/review/backend".to_string()), reasoning_effort: Some("high".to_string()), first_user_message: Some("first message".to_string()), + rollout_path: None, + approval_mode_json: None, + sandbox_policy_json: None, + token_usage_json: None, + history: None, }; let stored = stored_thread_from_proto(thread.clone()).expect("proto to stored thread"); assert_eq!(stored.rollout_path, None); assert!(stored.history.is_none()); - assert_eq!(stored_thread_to_proto(stored), thread); + let roundtripped = stored_thread_to_proto(stored); + assert_eq!(roundtripped.thread_id, thread.thread_id); + assert_eq!(roundtripped.forked_from_id, thread.forked_from_id); + assert_eq!(roundtripped.source, thread.source); + assert_eq!(roundtripped.git_info, thread.git_info); } } diff --git a/codex-rs/thread-store/src/remote/mod.rs b/codex-rs/thread-store/src/remote/mod.rs index b3ddeecf7650..48fef2249bd1 100644 --- a/codex-rs/thread-store/src/remote/mod.rs +++ b/codex-rs/thread-store/src/remote/mod.rs @@ -52,43 +52,139 @@ impl ThreadStore for RemoteThreadStore { self } - async fn create_thread(&self, _params: CreateThreadParams) -> ThreadStoreResult<()> { - Err(not_implemented("create_thread")) - } - - async fn resume_thread(&self, _params: ResumeThreadParams) -> ThreadStoreResult<()> { - Err(not_implemented("resume_thread")) - } - - async fn append_items(&self, _params: AppendThreadItemsParams) -> ThreadStoreResult<()> { - Err(not_implemented("append_items")) + async fn create_thread(&self, params: CreateThreadParams) -> ThreadStoreResult<()> { + let thread_id = params.thread_id; + let request = proto::CreateThreadRequest { + thread_id: thread_id.to_string(), + forked_from_id: params.forked_from_id.map(|thread_id| thread_id.to_string()), + source: Some(helpers::proto_session_source(¶ms.source)), + base_instructions_json: helpers::base_instructions_json(¶ms.base_instructions)?, + dynamic_tools_json: helpers::dynamic_tools_json(¶ms.dynamic_tools)?, + event_persistence_mode: helpers::proto_event_persistence_mode( + params.event_persistence_mode, + ) + .into(), + }; + self.client() + .await? + .create_thread(request) + .await + .map_err(|status| helpers::remote_status_to_thread_error(status, thread_id))?; + Ok(()) + } + + async fn resume_thread(&self, params: ResumeThreadParams) -> ThreadStoreResult<()> { + let thread_id = params.thread_id; + let (has_history, history_json) = match params.history { + Some(history) => (true, helpers::rollout_items_json(&history)?), + None => (false, Vec::new()), + }; + let request = proto::ResumeThreadRequest { + thread_id: thread_id.to_string(), + rollout_path: params + .rollout_path + .map(|path| path.to_string_lossy().into_owned()), + history_json, + has_history, + include_archived: params.include_archived, + event_persistence_mode: helpers::proto_event_persistence_mode( + params.event_persistence_mode, + ) + .into(), + }; + self.client() + .await? + .resume_thread(request) + .await + .map_err(|status| helpers::remote_status_to_thread_error(status, thread_id))?; + Ok(()) + } + + async fn append_items(&self, params: AppendThreadItemsParams) -> ThreadStoreResult<()> { + let thread_id = params.thread_id; + let request = proto::AppendThreadItemsRequest { + thread_id: thread_id.to_string(), + items_json: helpers::rollout_items_json(¶ms.items)?, + }; + self.client() + .await? + .append_items(request) + .await + .map_err(|status| helpers::remote_status_to_thread_error(status, thread_id))?; + Ok(()) } - async fn persist_thread(&self, _thread_id: ThreadId) -> ThreadStoreResult<()> { - Err(not_implemented("persist_thread")) + async fn persist_thread(&self, thread_id: ThreadId) -> ThreadStoreResult<()> { + self.client() + .await? + .persist_thread(helpers::proto_thread_id_request(thread_id)) + .await + .map_err(|status| helpers::remote_status_to_thread_error(status, thread_id))?; + Ok(()) } - async fn flush_thread(&self, _thread_id: ThreadId) -> ThreadStoreResult<()> { - Err(not_implemented("flush_thread")) + async fn flush_thread(&self, thread_id: ThreadId) -> ThreadStoreResult<()> { + self.client() + .await? + .flush_thread(helpers::proto_thread_id_request(thread_id)) + .await + .map_err(|status| helpers::remote_status_to_thread_error(status, thread_id))?; + Ok(()) } - async fn shutdown_thread(&self, _thread_id: ThreadId) -> ThreadStoreResult<()> { - Err(not_implemented("shutdown_thread")) + async fn shutdown_thread(&self, thread_id: ThreadId) -> ThreadStoreResult<()> { + self.client() + .await? + .shutdown_thread(helpers::proto_thread_id_request(thread_id)) + .await + .map_err(|status| helpers::remote_status_to_thread_error(status, thread_id))?; + Ok(()) } - async fn discard_thread(&self, _thread_id: ThreadId) -> ThreadStoreResult<()> { - Err(not_implemented("discard_thread")) + async fn discard_thread(&self, thread_id: ThreadId) -> ThreadStoreResult<()> { + self.client() + .await? + .discard_thread(helpers::proto_thread_id_request(thread_id)) + .await + .map_err(|status| helpers::remote_status_to_thread_error(status, thread_id))?; + Ok(()) } async fn load_history( &self, - _params: LoadThreadHistoryParams, + params: LoadThreadHistoryParams, ) -> ThreadStoreResult { - Err(not_implemented("load_history")) - } - - async fn read_thread(&self, _params: ReadThreadParams) -> ThreadStoreResult { - Err(not_implemented("read_thread")) + let thread_id = params.thread_id; + let response = self + .client() + .await? + .load_history(proto::LoadThreadHistoryRequest { + thread_id: thread_id.to_string(), + include_archived: params.include_archived, + }) + .await + .map_err(|status| helpers::remote_status_to_thread_error(status, thread_id))? + .into_inner(); + helpers::stored_thread_history_from_proto(response) + } + + async fn read_thread(&self, params: ReadThreadParams) -> ThreadStoreResult { + let thread_id = params.thread_id; + let response = self + .client() + .await? + .read_thread(proto::ReadThreadRequest { + thread_id: thread_id.to_string(), + include_archived: params.include_archived, + include_history: params.include_history, + }) + .await + .map_err(|status| helpers::remote_status_to_thread_error(status, thread_id))? + .into_inner(); + let thread = response.thread.ok_or_else(|| ThreadStoreError::Internal { + message: "remote thread store omitted read_thread response thread".to_string(), + })?; + helpers::stored_thread_from_proto(thread) } async fn list_threads(&self, params: ListThreadsParams) -> ThreadStoreResult { @@ -97,25 +193,56 @@ impl ThreadStore for RemoteThreadStore { async fn update_thread_metadata( &self, - _params: UpdateThreadMetadataParams, + params: UpdateThreadMetadataParams, ) -> ThreadStoreResult { - Err(not_implemented("update_thread_metadata")) - } - - async fn archive_thread(&self, _params: ArchiveThreadParams) -> ThreadStoreResult<()> { - Err(not_implemented("archive_thread")) + let thread_id = params.thread_id; + let response = self + .client() + .await? + .update_thread_metadata(proto::UpdateThreadMetadataRequest { + thread_id: thread_id.to_string(), + patch: Some(helpers::proto_metadata_patch(params.patch)), + include_archived: params.include_archived, + }) + .await + .map_err(|status| helpers::remote_status_to_thread_error(status, thread_id))? + .into_inner(); + let thread = response.thread.ok_or_else(|| ThreadStoreError::Internal { + message: "remote thread store omitted update_thread_metadata response thread" + .to_string(), + })?; + helpers::stored_thread_from_proto(thread) + } + + async fn archive_thread(&self, params: ArchiveThreadParams) -> ThreadStoreResult<()> { + let thread_id = params.thread_id; + self.client() + .await? + .archive_thread(proto::ArchiveThreadRequest { + thread_id: thread_id.to_string(), + }) + .await + .map_err(|status| helpers::remote_status_to_thread_error(status, thread_id))?; + Ok(()) } async fn unarchive_thread( &self, - _params: ArchiveThreadParams, + params: ArchiveThreadParams, ) -> ThreadStoreResult { - Err(not_implemented("unarchive_thread")) - } -} - -fn not_implemented(method: &str) -> ThreadStoreError { - ThreadStoreError::Internal { - message: format!("remote thread store does not implement {method} yet"), + let thread_id = params.thread_id; + let response = self + .client() + .await? + .unarchive_thread(proto::ArchiveThreadRequest { + thread_id: thread_id.to_string(), + }) + .await + .map_err(|status| helpers::remote_status_to_thread_error(status, thread_id))? + .into_inner(); + let thread = response.thread.ok_or_else(|| ThreadStoreError::Internal { + message: "remote thread store omitted unarchive_thread response thread".to_string(), + })?; + helpers::stored_thread_from_proto(thread) } } diff --git a/codex-rs/thread-store/src/remote/proto/codex.thread_store.v1.proto b/codex-rs/thread-store/src/remote/proto/codex.thread_store.v1.proto index 267cb932066a..06a3cbd87440 100644 --- a/codex-rs/thread-store/src/remote/proto/codex.thread_store.v1.proto +++ b/codex-rs/thread-store/src/remote/proto/codex.thread_store.v1.proto @@ -3,7 +3,59 @@ syntax = "proto3"; package codex.thread_store.v1; service ThreadStore { + rpc CreateThread(CreateThreadRequest) returns (Empty); + rpc ResumeThread(ResumeThreadRequest) returns (Empty); + rpc AppendItems(AppendThreadItemsRequest) returns (Empty); + rpc PersistThread(ThreadIdRequest) returns (Empty); + rpc FlushThread(ThreadIdRequest) returns (Empty); + rpc ShutdownThread(ThreadIdRequest) returns (Empty); + rpc DiscardThread(ThreadIdRequest) returns (Empty); + rpc LoadHistory(LoadThreadHistoryRequest) returns (StoredThreadHistory); + rpc ReadThread(ReadThreadRequest) returns (StoredThreadResponse); rpc ListThreads(ListThreadsRequest) returns (ListThreadsResponse); + rpc UpdateThreadMetadata(UpdateThreadMetadataRequest) returns (StoredThreadResponse); + rpc ArchiveThread(ArchiveThreadRequest) returns (Empty); + rpc UnarchiveThread(ArchiveThreadRequest) returns (StoredThreadResponse); +} + +message Empty {} + +message ThreadIdRequest { + string thread_id = 1; +} + +message CreateThreadRequest { + string thread_id = 1; + optional string forked_from_id = 2; + SessionSource source = 3; + string base_instructions_json = 4; + repeated string dynamic_tools_json = 5; + ThreadEventPersistenceMode event_persistence_mode = 6; +} + +message ResumeThreadRequest { + string thread_id = 1; + optional string rollout_path = 2; + repeated string history_json = 3; + bool has_history = 4; + bool include_archived = 5; + ThreadEventPersistenceMode event_persistence_mode = 6; +} + +message AppendThreadItemsRequest { + string thread_id = 1; + repeated string items_json = 2; +} + +message LoadThreadHistoryRequest { + string thread_id = 1; + bool include_archived = 2; +} + +message ReadThreadRequest { + string thread_id = 1; + bool include_archived = 2; + bool include_history = 3; } message ListThreadsRequest { @@ -16,6 +68,7 @@ message ListThreadsRequest { optional string search_term = 7; optional CwdFilter cwd_filter = 8; bool use_state_db_only = 9; + SortDirection sort_direction = 10; } message ModelProviderFilter { @@ -31,11 +84,25 @@ enum ThreadSortKey { THREAD_SORT_KEY_UPDATED_AT = 1; } +enum SortDirection { + SORT_DIRECTION_ASC = 0; + SORT_DIRECTION_DESC = 1; +} + message ListThreadsResponse { repeated StoredThread threads = 1; optional string next_cursor = 2; } +message StoredThreadResponse { + StoredThread thread = 1; +} + +message StoredThreadHistory { + string thread_id = 1; + repeated string items_json = 2; +} + message StoredThread { // Mirrors Rust's StoredThread. Domain types that are not protobuf-native, // such as ThreadId, DateTime, and PathBuf, are represented as their @@ -58,6 +125,11 @@ message StoredThread { optional string agent_path = 16; optional string reasoning_effort = 17; optional string first_user_message = 18; + optional string rollout_path = 19; + optional string approval_mode_json = 20; + optional string sandbox_policy_json = 21; + optional string token_usage_json = 22; + optional StoredThreadHistory history = 23; } message SessionSource { @@ -90,3 +162,46 @@ message GitInfo { optional string branch = 2; optional string origin_url = 3; } + +message UpdateThreadMetadataRequest { + string thread_id = 1; + ThreadMetadataPatch patch = 2; + bool include_archived = 3; +} + +message ThreadMetadataPatch { + optional string name = 1; + optional ThreadMemoryMode memory_mode = 2; + optional GitInfoPatch git_info = 3; +} + +enum ThreadMemoryMode { + THREAD_MEMORY_MODE_ENABLED = 0; + THREAD_MEMORY_MODE_DISABLED = 1; +} + +message GitInfoPatch { + OptionalStringPatch sha = 1; + OptionalStringPatch branch = 2; + OptionalStringPatch origin_url = 3; +} + +message OptionalStringPatch { + OptionalStringPatchKind kind = 1; + optional string value = 2; +} + +enum OptionalStringPatchKind { + OPTIONAL_STRING_PATCH_KIND_UNSET = 0; + OPTIONAL_STRING_PATCH_KIND_CLEAR = 1; + OPTIONAL_STRING_PATCH_KIND_SET = 2; +} + +message ArchiveThreadRequest { + string thread_id = 1; +} + +enum ThreadEventPersistenceMode { + THREAD_EVENT_PERSISTENCE_MODE_LIMITED = 0; + THREAD_EVENT_PERSISTENCE_MODE_EXTENDED = 1; +} diff --git a/codex-rs/thread-store/src/remote/proto/codex.thread_store.v1.rs b/codex-rs/thread-store/src/remote/proto/codex.thread_store.v1.rs index 73262bc4a5e8..bf5612764cab 100644 --- a/codex-rs/thread-store/src/remote/proto/codex.thread_store.v1.rs +++ b/codex-rs/thread-store/src/remote/proto/codex.thread_store.v1.rs @@ -1,6 +1,66 @@ // This file is @generated by prost-build. #![allow(clippy::trivially_copy_pass_by_ref)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Empty {} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct ThreadIdRequest { + #[prost(string, tag = "1")] + pub thread_id: ::prost::alloc::string::String, +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct CreateThreadRequest { + #[prost(string, tag = "1")] + pub thread_id: ::prost::alloc::string::String, + #[prost(string, optional, tag = "2")] + pub forked_from_id: ::core::option::Option<::prost::alloc::string::String>, + #[prost(message, optional, tag = "3")] + pub source: ::core::option::Option, + #[prost(string, tag = "4")] + pub base_instructions_json: ::prost::alloc::string::String, + #[prost(string, repeated, tag = "5")] + pub dynamic_tools_json: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, + #[prost(enumeration = "ThreadEventPersistenceMode", tag = "6")] + pub event_persistence_mode: i32, +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct ResumeThreadRequest { + #[prost(string, tag = "1")] + pub thread_id: ::prost::alloc::string::String, + #[prost(string, optional, tag = "2")] + pub rollout_path: ::core::option::Option<::prost::alloc::string::String>, + #[prost(string, repeated, tag = "3")] + pub history_json: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, + #[prost(bool, tag = "4")] + pub has_history: bool, + #[prost(bool, tag = "5")] + pub include_archived: bool, + #[prost(enumeration = "ThreadEventPersistenceMode", tag = "6")] + pub event_persistence_mode: i32, +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct AppendThreadItemsRequest { + #[prost(string, tag = "1")] + pub thread_id: ::prost::alloc::string::String, + #[prost(string, repeated, tag = "2")] + pub items_json: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct LoadThreadHistoryRequest { + #[prost(string, tag = "1")] + pub thread_id: ::prost::alloc::string::String, + #[prost(bool, tag = "2")] + pub include_archived: bool, +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct ReadThreadRequest { + #[prost(string, tag = "1")] + pub thread_id: ::prost::alloc::string::String, + #[prost(bool, tag = "2")] + pub include_archived: bool, + #[prost(bool, tag = "3")] + pub include_history: bool, +} #[derive(Clone, PartialEq, ::prost::Message)] pub struct ListThreadsRequest { #[prost(uint32, tag = "1")] @@ -21,6 +81,8 @@ pub struct ListThreadsRequest { pub cwd_filter: ::core::option::Option, #[prost(bool, tag = "9")] pub use_state_db_only: bool, + #[prost(enumeration = "SortDirection", tag = "10")] + pub sort_direction: i32, } #[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] pub struct ModelProviderFilter { @@ -39,6 +101,18 @@ pub struct ListThreadsResponse { #[prost(string, optional, tag = "2")] pub next_cursor: ::core::option::Option<::prost::alloc::string::String>, } +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct StoredThreadResponse { + #[prost(message, optional, tag = "1")] + pub thread: ::core::option::Option, +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct StoredThreadHistory { + #[prost(string, tag = "1")] + pub thread_id: ::prost::alloc::string::String, + #[prost(string, repeated, tag = "2")] + pub items_json: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, +} #[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] pub struct StoredThread { /// Mirrors Rust's StoredThread. Domain types that are not protobuf-native, @@ -80,6 +154,16 @@ pub struct StoredThread { pub reasoning_effort: ::core::option::Option<::prost::alloc::string::String>, #[prost(string, optional, tag = "18")] pub first_user_message: ::core::option::Option<::prost::alloc::string::String>, + #[prost(string, optional, tag = "19")] + pub rollout_path: ::core::option::Option<::prost::alloc::string::String>, + #[prost(string, optional, tag = "20")] + pub approval_mode_json: ::core::option::Option<::prost::alloc::string::String>, + #[prost(string, optional, tag = "21")] + pub sandbox_policy_json: ::core::option::Option<::prost::alloc::string::String>, + #[prost(string, optional, tag = "22")] + pub token_usage_json: ::core::option::Option<::prost::alloc::string::String>, + #[prost(message, optional, tag = "23")] + pub history: ::core::option::Option, } #[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] pub struct SessionSource { @@ -109,6 +193,45 @@ pub struct GitInfo { #[prost(string, optional, tag = "3")] pub origin_url: ::core::option::Option<::prost::alloc::string::String>, } +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct UpdateThreadMetadataRequest { + #[prost(string, tag = "1")] + pub thread_id: ::prost::alloc::string::String, + #[prost(message, optional, tag = "2")] + pub patch: ::core::option::Option, + #[prost(bool, tag = "3")] + pub include_archived: bool, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ThreadMetadataPatch { + #[prost(string, optional, tag = "1")] + pub name: ::core::option::Option<::prost::alloc::string::String>, + #[prost(enumeration = "ThreadMemoryMode", optional, tag = "2")] + pub memory_mode: ::core::option::Option, + #[prost(message, optional, tag = "3")] + pub git_info: ::core::option::Option, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct GitInfoPatch { + #[prost(message, optional, tag = "1")] + pub sha: ::core::option::Option, + #[prost(message, optional, tag = "2")] + pub branch: ::core::option::Option, + #[prost(message, optional, tag = "3")] + pub origin_url: ::core::option::Option, +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct OptionalStringPatch { + #[prost(enumeration = "OptionalStringPatchKind", tag = "1")] + pub kind: i32, + #[prost(string, optional, tag = "2")] + pub value: ::core::option::Option<::prost::alloc::string::String>, +} +#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] +pub struct ArchiveThreadRequest { + #[prost(string, tag = "1")] + pub thread_id: ::prost::alloc::string::String, +} #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] #[repr(i32)] pub enum ThreadSortKey { @@ -137,6 +260,32 @@ impl ThreadSortKey { } #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] #[repr(i32)] +pub enum SortDirection { + Asc = 0, + Desc = 1, +} +impl SortDirection { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + Self::Asc => "SORT_DIRECTION_ASC", + Self::Desc => "SORT_DIRECTION_DESC", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "SORT_DIRECTION_ASC" => Some(Self::Asc), + "SORT_DIRECTION_DESC" => Some(Self::Desc), + _ => None, + } + } +} +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] +#[repr(i32)] pub enum SessionSourceKind { Unknown = 0, Cli = 1, @@ -192,6 +341,87 @@ impl SessionSourceKind { } } } +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] +#[repr(i32)] +pub enum ThreadMemoryMode { + Enabled = 0, + Disabled = 1, +} +impl ThreadMemoryMode { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + Self::Enabled => "THREAD_MEMORY_MODE_ENABLED", + Self::Disabled => "THREAD_MEMORY_MODE_DISABLED", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "THREAD_MEMORY_MODE_ENABLED" => Some(Self::Enabled), + "THREAD_MEMORY_MODE_DISABLED" => Some(Self::Disabled), + _ => None, + } + } +} +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] +#[repr(i32)] +pub enum OptionalStringPatchKind { + Unset = 0, + Clear = 1, + Set = 2, +} +impl OptionalStringPatchKind { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + Self::Unset => "OPTIONAL_STRING_PATCH_KIND_UNSET", + Self::Clear => "OPTIONAL_STRING_PATCH_KIND_CLEAR", + Self::Set => "OPTIONAL_STRING_PATCH_KIND_SET", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "OPTIONAL_STRING_PATCH_KIND_UNSET" => Some(Self::Unset), + "OPTIONAL_STRING_PATCH_KIND_CLEAR" => Some(Self::Clear), + "OPTIONAL_STRING_PATCH_KIND_SET" => Some(Self::Set), + _ => None, + } + } +} +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] +#[repr(i32)] +pub enum ThreadEventPersistenceMode { + Limited = 0, + Extended = 1, +} +impl ThreadEventPersistenceMode { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + Self::Limited => "THREAD_EVENT_PERSISTENCE_MODE_LIMITED", + Self::Extended => "THREAD_EVENT_PERSISTENCE_MODE_EXTENDED", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "THREAD_EVENT_PERSISTENCE_MODE_LIMITED" => Some(Self::Limited), + "THREAD_EVENT_PERSISTENCE_MODE_EXTENDED" => Some(Self::Extended), + _ => None, + } + } +} /// Generated client implementations. pub mod thread_store_client { #![allow( @@ -282,6 +512,170 @@ pub mod thread_store_client { self.inner = self.inner.max_encoding_message_size(limit); self } + pub async fn create_thread( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result, tonic::Status> { + self.inner.ready().await.map_err(|e| { + tonic::Status::unknown(format!("Service was not ready: {}", e.into())) + })?; + let codec = tonic_prost::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/codex.thread_store.v1.ThreadStore/CreateThread", + ); + let mut req = request.into_request(); + req.extensions_mut().insert(GrpcMethod::new( + "codex.thread_store.v1.ThreadStore", + "CreateThread", + )); + self.inner.unary(req, path, codec).await + } + pub async fn resume_thread( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result, tonic::Status> { + self.inner.ready().await.map_err(|e| { + tonic::Status::unknown(format!("Service was not ready: {}", e.into())) + })?; + let codec = tonic_prost::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/codex.thread_store.v1.ThreadStore/ResumeThread", + ); + let mut req = request.into_request(); + req.extensions_mut().insert(GrpcMethod::new( + "codex.thread_store.v1.ThreadStore", + "ResumeThread", + )); + self.inner.unary(req, path, codec).await + } + pub async fn append_items( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result, tonic::Status> { + self.inner.ready().await.map_err(|e| { + tonic::Status::unknown(format!("Service was not ready: {}", e.into())) + })?; + let codec = tonic_prost::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/codex.thread_store.v1.ThreadStore/AppendItems", + ); + let mut req = request.into_request(); + req.extensions_mut().insert(GrpcMethod::new( + "codex.thread_store.v1.ThreadStore", + "AppendItems", + )); + self.inner.unary(req, path, codec).await + } + pub async fn persist_thread( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result, tonic::Status> { + self.inner.ready().await.map_err(|e| { + tonic::Status::unknown(format!("Service was not ready: {}", e.into())) + })?; + let codec = tonic_prost::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/codex.thread_store.v1.ThreadStore/PersistThread", + ); + let mut req = request.into_request(); + req.extensions_mut().insert(GrpcMethod::new( + "codex.thread_store.v1.ThreadStore", + "PersistThread", + )); + self.inner.unary(req, path, codec).await + } + pub async fn flush_thread( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result, tonic::Status> { + self.inner.ready().await.map_err(|e| { + tonic::Status::unknown(format!("Service was not ready: {}", e.into())) + })?; + let codec = tonic_prost::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/codex.thread_store.v1.ThreadStore/FlushThread", + ); + let mut req = request.into_request(); + req.extensions_mut().insert(GrpcMethod::new( + "codex.thread_store.v1.ThreadStore", + "FlushThread", + )); + self.inner.unary(req, path, codec).await + } + pub async fn shutdown_thread( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result, tonic::Status> { + self.inner.ready().await.map_err(|e| { + tonic::Status::unknown(format!("Service was not ready: {}", e.into())) + })?; + let codec = tonic_prost::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/codex.thread_store.v1.ThreadStore/ShutdownThread", + ); + let mut req = request.into_request(); + req.extensions_mut().insert(GrpcMethod::new( + "codex.thread_store.v1.ThreadStore", + "ShutdownThread", + )); + self.inner.unary(req, path, codec).await + } + pub async fn discard_thread( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result, tonic::Status> { + self.inner.ready().await.map_err(|e| { + tonic::Status::unknown(format!("Service was not ready: {}", e.into())) + })?; + let codec = tonic_prost::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/codex.thread_store.v1.ThreadStore/DiscardThread", + ); + let mut req = request.into_request(); + req.extensions_mut().insert(GrpcMethod::new( + "codex.thread_store.v1.ThreadStore", + "DiscardThread", + )); + self.inner.unary(req, path, codec).await + } + pub async fn load_history( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result, tonic::Status> + { + self.inner.ready().await.map_err(|e| { + tonic::Status::unknown(format!("Service was not ready: {}", e.into())) + })?; + let codec = tonic_prost::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/codex.thread_store.v1.ThreadStore/LoadHistory", + ); + let mut req = request.into_request(); + req.extensions_mut().insert(GrpcMethod::new( + "codex.thread_store.v1.ThreadStore", + "LoadHistory", + )); + self.inner.unary(req, path, codec).await + } + pub async fn read_thread( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result, tonic::Status> + { + self.inner.ready().await.map_err(|e| { + tonic::Status::unknown(format!("Service was not ready: {}", e.into())) + })?; + let codec = tonic_prost::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/codex.thread_store.v1.ThreadStore/ReadThread", + ); + let mut req = request.into_request(); + req.extensions_mut().insert(GrpcMethod::new( + "codex.thread_store.v1.ThreadStore", + "ReadThread", + )); + self.inner.unary(req, path, codec).await + } pub async fn list_threads( &mut self, request: impl tonic::IntoRequest, @@ -301,6 +695,62 @@ pub mod thread_store_client { )); self.inner.unary(req, path, codec).await } + pub async fn update_thread_metadata( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result, tonic::Status> + { + self.inner.ready().await.map_err(|e| { + tonic::Status::unknown(format!("Service was not ready: {}", e.into())) + })?; + let codec = tonic_prost::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/codex.thread_store.v1.ThreadStore/UpdateThreadMetadata", + ); + let mut req = request.into_request(); + req.extensions_mut().insert(GrpcMethod::new( + "codex.thread_store.v1.ThreadStore", + "UpdateThreadMetadata", + )); + self.inner.unary(req, path, codec).await + } + pub async fn archive_thread( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result, tonic::Status> { + self.inner.ready().await.map_err(|e| { + tonic::Status::unknown(format!("Service was not ready: {}", e.into())) + })?; + let codec = tonic_prost::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/codex.thread_store.v1.ThreadStore/ArchiveThread", + ); + let mut req = request.into_request(); + req.extensions_mut().insert(GrpcMethod::new( + "codex.thread_store.v1.ThreadStore", + "ArchiveThread", + )); + self.inner.unary(req, path, codec).await + } + pub async fn unarchive_thread( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result, tonic::Status> + { + self.inner.ready().await.map_err(|e| { + tonic::Status::unknown(format!("Service was not ready: {}", e.into())) + })?; + let codec = tonic_prost::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/codex.thread_store.v1.ThreadStore/UnarchiveThread", + ); + let mut req = request.into_request(); + req.extensions_mut().insert(GrpcMethod::new( + "codex.thread_store.v1.ThreadStore", + "UnarchiveThread", + )); + self.inner.unary(req, path, codec).await + } } } /// Generated server implementations. @@ -316,10 +766,98 @@ pub mod thread_store_server { /// Generated trait containing gRPC methods that should be implemented for use with ThreadStoreServer. #[async_trait] pub trait ThreadStore: std::marker::Send + std::marker::Sync + 'static { + async fn create_thread( + &self, + request: tonic::Request, + ) -> std::result::Result, tonic::Status> { + let _ = request; + Err(tonic::Status::unimplemented("not implemented")) + } + async fn resume_thread( + &self, + request: tonic::Request, + ) -> std::result::Result, tonic::Status> { + let _ = request; + Err(tonic::Status::unimplemented("not implemented")) + } + async fn append_items( + &self, + request: tonic::Request, + ) -> std::result::Result, tonic::Status> { + let _ = request; + Err(tonic::Status::unimplemented("not implemented")) + } + async fn persist_thread( + &self, + request: tonic::Request, + ) -> std::result::Result, tonic::Status> { + let _ = request; + Err(tonic::Status::unimplemented("not implemented")) + } + async fn flush_thread( + &self, + request: tonic::Request, + ) -> std::result::Result, tonic::Status> { + let _ = request; + Err(tonic::Status::unimplemented("not implemented")) + } + async fn shutdown_thread( + &self, + request: tonic::Request, + ) -> std::result::Result, tonic::Status> { + let _ = request; + Err(tonic::Status::unimplemented("not implemented")) + } + async fn discard_thread( + &self, + request: tonic::Request, + ) -> std::result::Result, tonic::Status> { + let _ = request; + Err(tonic::Status::unimplemented("not implemented")) + } + async fn load_history( + &self, + request: tonic::Request, + ) -> std::result::Result, tonic::Status> + { + let _ = request; + Err(tonic::Status::unimplemented("not implemented")) + } + async fn read_thread( + &self, + request: tonic::Request, + ) -> std::result::Result, tonic::Status> + { + let _ = request; + Err(tonic::Status::unimplemented("not implemented")) + } async fn list_threads( &self, request: tonic::Request, ) -> std::result::Result, tonic::Status>; + async fn update_thread_metadata( + &self, + request: tonic::Request, + ) -> std::result::Result, tonic::Status> + { + let _ = request; + Err(tonic::Status::unimplemented("not implemented")) + } + async fn archive_thread( + &self, + request: tonic::Request, + ) -> std::result::Result, tonic::Status> { + let _ = request; + Err(tonic::Status::unimplemented("not implemented")) + } + async fn unarchive_thread( + &self, + request: tonic::Request, + ) -> std::result::Result, tonic::Status> + { + let _ = request; + Err(tonic::Status::unimplemented("not implemented")) + } } #[derive(Debug)] pub struct ThreadStoreServer { @@ -393,7 +931,98 @@ pub mod thread_store_server { Poll::Ready(Ok(())) } fn call(&mut self, req: http::Request) -> Self::Future { + macro_rules! unary_service { + ($svc:ident, $request:ty, $response:ty, $method:ident) => {{ + #[allow(non_camel_case_types)] + struct $svc(pub Arc); + impl tonic::server::UnaryService<$request> for $svc { + type Response = $response; + type Future = BoxFuture, tonic::Status>; + fn call(&mut self, request: tonic::Request<$request>) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = + async move { ::$method(&inner, request).await }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let method = $svc(inner); + let codec = tonic_prost::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + }}; + } match req.uri().path() { + "/codex.thread_store.v1.ThreadStore/CreateThread" => unary_service!( + CreateThreadSvc, + super::CreateThreadRequest, + super::Empty, + create_thread + ), + "/codex.thread_store.v1.ThreadStore/ResumeThread" => unary_service!( + ResumeThreadSvc, + super::ResumeThreadRequest, + super::Empty, + resume_thread + ), + "/codex.thread_store.v1.ThreadStore/AppendItems" => unary_service!( + AppendItemsSvc, + super::AppendThreadItemsRequest, + super::Empty, + append_items + ), + "/codex.thread_store.v1.ThreadStore/PersistThread" => unary_service!( + PersistThreadSvc, + super::ThreadIdRequest, + super::Empty, + persist_thread + ), + "/codex.thread_store.v1.ThreadStore/FlushThread" => unary_service!( + FlushThreadSvc, + super::ThreadIdRequest, + super::Empty, + flush_thread + ), + "/codex.thread_store.v1.ThreadStore/ShutdownThread" => unary_service!( + ShutdownThreadSvc, + super::ThreadIdRequest, + super::Empty, + shutdown_thread + ), + "/codex.thread_store.v1.ThreadStore/DiscardThread" => unary_service!( + DiscardThreadSvc, + super::ThreadIdRequest, + super::Empty, + discard_thread + ), + "/codex.thread_store.v1.ThreadStore/LoadHistory" => unary_service!( + LoadHistorySvc, + super::LoadThreadHistoryRequest, + super::StoredThreadHistory, + load_history + ), + "/codex.thread_store.v1.ThreadStore/ReadThread" => unary_service!( + ReadThreadSvc, + super::ReadThreadRequest, + super::StoredThreadResponse, + read_thread + ), "/codex.thread_store.v1.ThreadStore/ListThreads" => { #[allow(non_camel_case_types)] struct ListThreadsSvc(pub Arc); @@ -433,6 +1062,24 @@ pub mod thread_store_server { }; Box::pin(fut) } + "/codex.thread_store.v1.ThreadStore/UpdateThreadMetadata" => unary_service!( + UpdateThreadMetadataSvc, + super::UpdateThreadMetadataRequest, + super::StoredThreadResponse, + update_thread_metadata + ), + "/codex.thread_store.v1.ThreadStore/ArchiveThread" => unary_service!( + ArchiveThreadSvc, + super::ArchiveThreadRequest, + super::Empty, + archive_thread + ), + "/codex.thread_store.v1.ThreadStore/UnarchiveThread" => unary_service!( + UnarchiveThreadSvc, + super::ArchiveThreadRequest, + super::StoredThreadResponse, + unarchive_thread + ), _ => Box::pin(async move { let mut response = http::Response::new(tonic::body::Body::default()); let headers = response.headers_mut();