mirror of
https://github.com/openai/codex.git
synced 2026-10-21 17:48:44 +00:00
## What changed - Add `thread/section/move` to atomically move a thread into, within, or out of a section. Threads can be inserted before an existing member or appended, and moves within a section preserve `sectionEnteredAt`. - Add `section_position` sorting to `thread/list`, with ascending order as its default, and expose `sectionEnteredAt` in thread responses. - Persist section positions and entry times in SQLite, including migration of existing section members into recency order. Section membership is no longer updated through `thread/metadata/update`. ## Testing - Cover section moves, reordering, pagination, persistence across restarts and rollout reconciliation, concurrent updates, and rank renumbering. GitOrigin-RevId: aec6d7ddedca5277029b5caf5c074975397e956c
59 lines
1.7 KiB
Rust
59 lines
1.7 KiB
Rust
use super::LocalThreadStore;
|
|
use crate::MoveThreadToSectionParams;
|
|
use crate::ThreadStoreError;
|
|
use crate::ThreadStoreResult;
|
|
|
|
pub(super) async fn move_thread_to_section(
|
|
store: &LocalThreadStore,
|
|
params: MoveThreadToSectionParams,
|
|
) -> ThreadStoreResult<()> {
|
|
if params
|
|
.section
|
|
.as_deref()
|
|
.is_some_and(|section| section.trim().is_empty())
|
|
{
|
|
return Err(ThreadStoreError::InvalidRequest {
|
|
message: "section must not be empty".to_owned(),
|
|
});
|
|
}
|
|
if params.section.is_none() && params.before_thread_id.is_some() {
|
|
return Err(ThreadStoreError::InvalidRequest {
|
|
message: "before thread cannot be specified without a section".to_owned(),
|
|
});
|
|
}
|
|
|
|
let Some(state_db) = store.state_db().await else {
|
|
return Err(ThreadStoreError::Unsupported {
|
|
operation: "thread/section/move",
|
|
});
|
|
};
|
|
|
|
let updated = state_db
|
|
.move_thread_to_section(
|
|
params.thread_id,
|
|
params.section.as_deref(),
|
|
params.before_thread_id,
|
|
)
|
|
.await
|
|
.map_err(|err| {
|
|
let message = err.to_string();
|
|
if message.starts_with("before thread ")
|
|
|| message.starts_with("thread ")
|
|
|| message.starts_with("section ")
|
|
{
|
|
ThreadStoreError::InvalidRequest { message }
|
|
} else {
|
|
ThreadStoreError::Internal {
|
|
message: format!("failed to move thread {}: {message}", params.thread_id),
|
|
}
|
|
}
|
|
})?;
|
|
if !updated {
|
|
return Err(ThreadStoreError::ThreadNotFound {
|
|
thread_id: params.thread_id,
|
|
});
|
|
}
|
|
|
|
Ok(())
|
|
}
|