[codex] Implement remote thread store methods (#19008)

This commit is contained in:
Tom
2026-04-23 10:49:28 -07:00
committed by GitHub
Unverified
parent f1923a38b1
commit f1061d9d07
6 changed files with 1133 additions and 37 deletions
+1 -1
View File
@@ -242,7 +242,7 @@ pub fn build_models_manager(
}
fn configured_thread_store(config: &Config) -> Arc<dyn ThreadStore> {
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)))
+192 -5
View File
@@ -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<T: serde::Serialize>(
value: &T,
field_name: &str,
) -> ThreadStoreResult<String> {
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<T: serde::de::DeserializeOwned>(
json: &str,
field_name: &str,
) -> ThreadStoreResult<T> {
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<T: serde::Serialize>(
values: &[T],
field_name: &str,
) -> ThreadStoreResult<Vec<String>> {
values
.iter()
.map(|value| serialize_json(value, field_name))
.collect()
}
fn deserialize_json_vec<T: serde::de::DeserializeOwned>(
values: &[String],
field_name: &str,
) -> ThreadStoreResult<Vec<T>> {
values
.iter()
.map(|value| deserialize_json(value, field_name))
.collect()
}
pub(super) fn base_instructions_json(
base_instructions: &BaseInstructions,
) -> ThreadStoreResult<String> {
serialize_json(base_instructions, "base_instructions")
}
pub(super) fn dynamic_tools_json(
dynamic_tools: &[DynamicToolSpec],
) -> ThreadStoreResult<Vec<String>> {
serialize_json_vec(dynamic_tools, "dynamic_tool")
}
pub(super) fn rollout_items_json(items: &[RolloutItem]) -> ThreadStoreResult<Vec<String>> {
serialize_json_vec(items, "rollout_item")
}
pub(super) fn stored_thread_history_from_proto(
history: proto::StoredThreadHistory,
) -> ThreadStoreResult<StoredThreadHistory> {
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<StoredThread> {
@@ -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(),
}
}
@@ -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);
}
}
+157 -30
View File
@@ -52,43 +52,139 @@ impl ThreadStore for RemoteThreadStore {
self
}
async fn create_thread(&self, _params: CreateThreadParams) -> ThreadStoreResult<()> {
Err(not_implemented("create_thread"))
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(&params.source)),
base_instructions_json: helpers::base_instructions_json(&params.base_instructions)?,
dynamic_tools_json: helpers::dynamic_tools_json(&params.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<()> {
Err(not_implemented("resume_thread"))
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<()> {
Err(not_implemented("append_items"))
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(&params.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<StoredThreadHistory> {
Err(not_implemented("load_history"))
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<StoredThread> {
Err(not_implemented("read_thread"))
async fn read_thread(&self, params: ReadThreadParams) -> ThreadStoreResult<StoredThread> {
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<ThreadPage> {
@@ -97,25 +193,56 @@ impl ThreadStore for RemoteThreadStore {
async fn update_thread_metadata(
&self,
_params: UpdateThreadMetadataParams,
params: UpdateThreadMetadataParams,
) -> ThreadStoreResult<StoredThread> {
Err(not_implemented("update_thread_metadata"))
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<()> {
Err(not_implemented("archive_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<StoredThread> {
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)
}
}
@@ -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<Utc>, 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;
}
@@ -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<SessionSource>,
#[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<CwdFilter>,
#[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<StoredThread>,
}
#[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<StoredThreadHistory>,
}
#[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<ThreadMetadataPatch>,
#[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<i32>,
#[prost(message, optional, tag = "3")]
pub git_info: ::core::option::Option<GitInfoPatch>,
}
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct GitInfoPatch {
#[prost(message, optional, tag = "1")]
pub sha: ::core::option::Option<OptionalStringPatch>,
#[prost(message, optional, tag = "2")]
pub branch: ::core::option::Option<OptionalStringPatch>,
#[prost(message, optional, tag = "3")]
pub origin_url: ::core::option::Option<OptionalStringPatch>,
}
#[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<Self> {
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<Self> {
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<Self> {
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<Self> {
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<super::CreateThreadRequest>,
) -> std::result::Result<tonic::Response<super::Empty>, 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<super::ResumeThreadRequest>,
) -> std::result::Result<tonic::Response<super::Empty>, 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<super::AppendThreadItemsRequest>,
) -> std::result::Result<tonic::Response<super::Empty>, 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<super::ThreadIdRequest>,
) -> std::result::Result<tonic::Response<super::Empty>, 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<super::ThreadIdRequest>,
) -> std::result::Result<tonic::Response<super::Empty>, 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<super::ThreadIdRequest>,
) -> std::result::Result<tonic::Response<super::Empty>, 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<super::ThreadIdRequest>,
) -> std::result::Result<tonic::Response<super::Empty>, 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<super::LoadThreadHistoryRequest>,
) -> std::result::Result<tonic::Response<super::StoredThreadHistory>, 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<super::ReadThreadRequest>,
) -> std::result::Result<tonic::Response<super::StoredThreadResponse>, 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<super::ListThreadsRequest>,
@@ -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<super::UpdateThreadMetadataRequest>,
) -> std::result::Result<tonic::Response<super::StoredThreadResponse>, 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<super::ArchiveThreadRequest>,
) -> std::result::Result<tonic::Response<super::Empty>, 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<super::ArchiveThreadRequest>,
) -> std::result::Result<tonic::Response<super::StoredThreadResponse>, 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<super::CreateThreadRequest>,
) -> std::result::Result<tonic::Response<super::Empty>, tonic::Status> {
let _ = request;
Err(tonic::Status::unimplemented("not implemented"))
}
async fn resume_thread(
&self,
request: tonic::Request<super::ResumeThreadRequest>,
) -> std::result::Result<tonic::Response<super::Empty>, tonic::Status> {
let _ = request;
Err(tonic::Status::unimplemented("not implemented"))
}
async fn append_items(
&self,
request: tonic::Request<super::AppendThreadItemsRequest>,
) -> std::result::Result<tonic::Response<super::Empty>, tonic::Status> {
let _ = request;
Err(tonic::Status::unimplemented("not implemented"))
}
async fn persist_thread(
&self,
request: tonic::Request<super::ThreadIdRequest>,
) -> std::result::Result<tonic::Response<super::Empty>, tonic::Status> {
let _ = request;
Err(tonic::Status::unimplemented("not implemented"))
}
async fn flush_thread(
&self,
request: tonic::Request<super::ThreadIdRequest>,
) -> std::result::Result<tonic::Response<super::Empty>, tonic::Status> {
let _ = request;
Err(tonic::Status::unimplemented("not implemented"))
}
async fn shutdown_thread(
&self,
request: tonic::Request<super::ThreadIdRequest>,
) -> std::result::Result<tonic::Response<super::Empty>, tonic::Status> {
let _ = request;
Err(tonic::Status::unimplemented("not implemented"))
}
async fn discard_thread(
&self,
request: tonic::Request<super::ThreadIdRequest>,
) -> std::result::Result<tonic::Response<super::Empty>, tonic::Status> {
let _ = request;
Err(tonic::Status::unimplemented("not implemented"))
}
async fn load_history(
&self,
request: tonic::Request<super::LoadThreadHistoryRequest>,
) -> std::result::Result<tonic::Response<super::StoredThreadHistory>, tonic::Status>
{
let _ = request;
Err(tonic::Status::unimplemented("not implemented"))
}
async fn read_thread(
&self,
request: tonic::Request<super::ReadThreadRequest>,
) -> std::result::Result<tonic::Response<super::StoredThreadResponse>, tonic::Status>
{
let _ = request;
Err(tonic::Status::unimplemented("not implemented"))
}
async fn list_threads(
&self,
request: tonic::Request<super::ListThreadsRequest>,
) -> std::result::Result<tonic::Response<super::ListThreadsResponse>, tonic::Status>;
async fn update_thread_metadata(
&self,
request: tonic::Request<super::UpdateThreadMetadataRequest>,
) -> std::result::Result<tonic::Response<super::StoredThreadResponse>, tonic::Status>
{
let _ = request;
Err(tonic::Status::unimplemented("not implemented"))
}
async fn archive_thread(
&self,
request: tonic::Request<super::ArchiveThreadRequest>,
) -> std::result::Result<tonic::Response<super::Empty>, tonic::Status> {
let _ = request;
Err(tonic::Status::unimplemented("not implemented"))
}
async fn unarchive_thread(
&self,
request: tonic::Request<super::ArchiveThreadRequest>,
) -> std::result::Result<tonic::Response<super::StoredThreadResponse>, tonic::Status>
{
let _ = request;
Err(tonic::Status::unimplemented("not implemented"))
}
}
#[derive(Debug)]
pub struct ThreadStoreServer<T> {
@@ -393,7 +931,98 @@ pub mod thread_store_server {
Poll::Ready(Ok(()))
}
fn call(&mut self, req: http::Request<B>) -> Self::Future {
macro_rules! unary_service {
($svc:ident, $request:ty, $response:ty, $method:ident) => {{
#[allow(non_camel_case_types)]
struct $svc<T: ThreadStore>(pub Arc<T>);
impl<T: ThreadStore> tonic::server::UnaryService<$request> for $svc<T> {
type Response = $response;
type Future = BoxFuture<tonic::Response<Self::Response>, tonic::Status>;
fn call(&mut self, request: tonic::Request<$request>) -> Self::Future {
let inner = Arc::clone(&self.0);
let fut =
async move { <T as ThreadStore>::$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<T: ThreadStore>(pub Arc<T>);
@@ -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();