mirror of
https://github.com/openai/codex.git
synced 2026-05-09 22:02:32 +00:00
Compare commits
5 Commits
xli-codex/
...
codex/exac
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
555cc029e9 | ||
|
|
5ba10e9eed | ||
|
|
c5c404c7f4 | ||
|
|
ec11708d43 | ||
|
|
e1f4aa728c |
@@ -3628,6 +3628,17 @@
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"searchMode": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ThreadListSearchMode"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Optional search matching mode. Defaults to substring title matching."
|
||||
},
|
||||
"searchTerm": {
|
||||
"description": "Optional substring filter for the extracted thread title.",
|
||||
"type": [
|
||||
@@ -3674,6 +3685,13 @@
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"ThreadListSearchMode": {
|
||||
"enum": [
|
||||
"contains",
|
||||
"exactName"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"ThreadLoadedListParams": {
|
||||
"properties": {
|
||||
"cursor": {
|
||||
|
||||
@@ -16123,6 +16123,17 @@
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"searchMode": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/v2/ThreadListSearchMode"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Optional search matching mode. Defaults to substring title matching."
|
||||
},
|
||||
"searchTerm": {
|
||||
"description": "Optional substring filter for the extracted thread title.",
|
||||
"type": [
|
||||
@@ -16200,6 +16211,13 @@
|
||||
"title": "ThreadListResponse",
|
||||
"type": "object"
|
||||
},
|
||||
"ThreadListSearchMode": {
|
||||
"enum": [
|
||||
"contains",
|
||||
"exactName"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"ThreadLoadedListParams": {
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"properties": {
|
||||
|
||||
@@ -14009,6 +14009,17 @@
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"searchMode": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ThreadListSearchMode"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Optional search matching mode. Defaults to substring title matching."
|
||||
},
|
||||
"searchTerm": {
|
||||
"description": "Optional substring filter for the extracted thread title.",
|
||||
"type": [
|
||||
@@ -14086,6 +14097,13 @@
|
||||
"title": "ThreadListResponse",
|
||||
"type": "object"
|
||||
},
|
||||
"ThreadListSearchMode": {
|
||||
"enum": [
|
||||
"contains",
|
||||
"exactName"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"ThreadLoadedListParams": {
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"properties": {
|
||||
|
||||
@@ -21,6 +21,13 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"ThreadListSearchMode": {
|
||||
"enum": [
|
||||
"contains",
|
||||
"exactName"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"ThreadSortKey": {
|
||||
"enum": [
|
||||
"created_at",
|
||||
@@ -89,6 +96,17 @@
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"searchMode": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ThreadListSearchMode"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Optional search matching mode. Defaults to substring title matching."
|
||||
},
|
||||
"searchTerm": {
|
||||
"description": "Optional substring filter for the extracted thread title.",
|
||||
"type": [
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
import type { SortDirection } from "./SortDirection";
|
||||
import type { ThreadListSearchMode } from "./ThreadListSearchMode";
|
||||
import type { ThreadSortKey } from "./ThreadSortKey";
|
||||
import type { ThreadSourceKind } from "./ThreadSourceKind";
|
||||
|
||||
@@ -51,4 +52,8 @@ useStateDbOnly?: boolean,
|
||||
/**
|
||||
* Optional substring filter for the extracted thread title.
|
||||
*/
|
||||
searchTerm?: string | null, };
|
||||
searchTerm?: string | null,
|
||||
/**
|
||||
* Optional search matching mode. Defaults to substring title matching.
|
||||
*/
|
||||
searchMode?: ThreadListSearchMode | null, };
|
||||
|
||||
5
codex-rs/app-server-protocol/schema/typescript/v2/ThreadListSearchMode.ts
generated
Normal file
5
codex-rs/app-server-protocol/schema/typescript/v2/ThreadListSearchMode.ts
generated
Normal file
@@ -0,0 +1,5 @@
|
||||
// GENERATED CODE! DO NOT MODIFY BY HAND!
|
||||
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
|
||||
export type ThreadListSearchMode = "contains" | "exactName";
|
||||
@@ -363,6 +363,7 @@ export type { ThreadInjectItemsResponse } from "./ThreadInjectItemsResponse";
|
||||
export type { ThreadItem } from "./ThreadItem";
|
||||
export type { ThreadListParams } from "./ThreadListParams";
|
||||
export type { ThreadListResponse } from "./ThreadListResponse";
|
||||
export type { ThreadListSearchMode } from "./ThreadListSearchMode";
|
||||
export type { ThreadLoadedListParams } from "./ThreadLoadedListParams";
|
||||
export type { ThreadLoadedListResponse } from "./ThreadLoadedListResponse";
|
||||
export type { ThreadMetadataGitInfoUpdateParams } from "./ThreadMetadataGitInfoUpdateParams";
|
||||
|
||||
@@ -4325,6 +4325,9 @@ pub struct ThreadListParams {
|
||||
/// Optional substring filter for the extracted thread title.
|
||||
#[ts(optional = nullable)]
|
||||
pub search_term: Option<String>,
|
||||
/// Optional search matching mode. Defaults to substring title matching.
|
||||
#[ts(optional = nullable)]
|
||||
pub search_mode: Option<ThreadListSearchMode>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema)]
|
||||
@@ -4334,6 +4337,14 @@ pub enum ThreadListCwdFilter {
|
||||
Many(Vec<String>),
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, JsonSchema, TS)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(rename_all = "camelCase", export_to = "v2/")]
|
||||
pub enum ThreadListSearchMode {
|
||||
Contains,
|
||||
ExactName,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, JsonSchema, TS)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(rename_all = "camelCase", export_to = "v2/")]
|
||||
@@ -8234,10 +8245,12 @@ mod tests {
|
||||
fn thread_list_params_accepts_state_db_only_flag() {
|
||||
let params = serde_json::from_value::<ThreadListParams>(json!({
|
||||
"useStateDbOnly": true,
|
||||
"searchMode": "exactName",
|
||||
}))
|
||||
.expect("state db only flag should deserialize");
|
||||
|
||||
assert!(params.use_state_db_only);
|
||||
assert_eq!(params.search_mode, Some(ThreadListSearchMode::ExactName));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -1127,6 +1127,7 @@ async fn thread_list(endpoint: &Endpoint, config_overrides: &[String], limit: u3
|
||||
cwd: None,
|
||||
use_state_db_only: false,
|
||||
search_term: None,
|
||||
search_mode: None,
|
||||
})?;
|
||||
println!("< thread/list response: {response:?}");
|
||||
|
||||
|
||||
@@ -146,7 +146,7 @@ Example with notification opt-out:
|
||||
- `thread/resume` — reopen an existing thread by id so subsequent `turn/start` calls append to it. Accepts the same permission override rules as `thread/start`.
|
||||
- `thread/fork` — fork an existing thread into a new thread id by copying the stored history; if the source thread is currently mid-turn, the fork records the same interruption marker as `turn/interrupt` instead of inheriting an unmarked partial turn suffix. The returned `thread.forkedFromId` points at the source thread when known. Accepts `ephemeral: true` for an in-memory temporary fork, emits `thread/started` (including the current `thread.status`), and auto-subscribes you to turn/item events for the new thread. Experimental clients can pass `excludeTurns: true` when they plan to page fork history via `thread/turns/list` instead of receiving the full turn array immediately. Accepts the same permission override rules as `thread/start`.
|
||||
- `thread/start`, `thread/resume`, and `thread/fork` responses include the legacy `sandbox` compatibility projection. Experimental clients can read response `permissionProfile` for the exact active runtime permissions and `activePermissionProfile` for the named or implicit built-in profile identity/provenance when known.
|
||||
- `thread/list` — page through stored rollouts; supports cursor-based pagination and optional `modelProviders`, `sourceKinds`, `archived`, `cwd`, and `searchTerm` filters. Each returned `thread` includes `status` (`ThreadStatus`), defaulting to `notLoaded` when the thread is not currently loaded.
|
||||
- `thread/list` — page through stored rollouts; supports cursor-based pagination and optional `modelProviders`, `sourceKinds`, `archived`, `cwd`, `searchTerm`, and `searchMode` filters. Each returned `thread` includes `status` (`ThreadStatus`), defaulting to `notLoaded` when the thread is not currently loaded.
|
||||
- `thread/loaded/list` — list the thread ids currently loaded in memory.
|
||||
- `thread/read` — read a stored thread by id without resuming it; optionally include turns via `includeTurns`. The returned `thread` includes `status` (`ThreadStatus`), defaulting to `notLoaded` when the thread is not currently loaded.
|
||||
- `thread/turns/list` — experimental; page through a stored thread’s turn history without resuming it; supports cursor-based pagination with `sortDirection`, `nextCursor`, and `backwardsCursor`.
|
||||
@@ -321,6 +321,7 @@ Like `thread/resume`, experimental clients can pass `excludeTurns: true` to `thr
|
||||
- `cwd` — restrict results to threads whose session cwd exactly matches this path, or one of these paths when an array is provided. Relative paths are resolved against the app-server process cwd before matching.
|
||||
- `useStateDbOnly` — when `true`, return from the state DB without scanning JSONL rollouts to repair metadata. Omit or pass `false` to preserve the default scan-and-repair behavior.
|
||||
- `searchTerm` — restrict results to threads whose extracted title contains this substring (case-sensitive).
|
||||
- `searchMode` — optional search matching mode for `searchTerm`: `contains` (default) or `exactName` to narrow to exact user-facing thread names.
|
||||
- Responses include `nextCursor` to continue in the same direction and `backwardsCursor` to pass as `cursor` when reversing `sortDirection`.
|
||||
- Responses include `agentNickname` and `agentRole` for AgentControl-spawned thread sub-agents when available.
|
||||
|
||||
|
||||
@@ -178,6 +178,7 @@ use codex_app_server_protocol::ThreadItem;
|
||||
use codex_app_server_protocol::ThreadListCwdFilter;
|
||||
use codex_app_server_protocol::ThreadListParams;
|
||||
use codex_app_server_protocol::ThreadListResponse;
|
||||
use codex_app_server_protocol::ThreadListSearchMode;
|
||||
use codex_app_server_protocol::ThreadLoadedListParams;
|
||||
use codex_app_server_protocol::ThreadLoadedListResponse;
|
||||
use codex_app_server_protocol::ThreadMemoryModeSetParams;
|
||||
|
||||
@@ -9,6 +9,7 @@ struct ThreadListFilters {
|
||||
archived: bool,
|
||||
cwd_filters: Option<Vec<PathBuf>>,
|
||||
search_term: Option<String>,
|
||||
search_mode: Option<ThreadListSearchMode>,
|
||||
use_state_db_only: bool,
|
||||
}
|
||||
|
||||
@@ -1826,6 +1827,7 @@ impl ThreadRequestProcessor {
|
||||
cwd,
|
||||
use_state_db_only,
|
||||
search_term,
|
||||
search_mode,
|
||||
} = params;
|
||||
let cwd_filters = normalize_thread_list_cwd_filters(cwd)?;
|
||||
|
||||
@@ -1850,6 +1852,7 @@ impl ThreadRequestProcessor {
|
||||
archived: archived.unwrap_or(false),
|
||||
cwd_filters,
|
||||
search_term,
|
||||
search_mode,
|
||||
use_state_db_only,
|
||||
},
|
||||
)
|
||||
@@ -3228,6 +3231,7 @@ impl ThreadRequestProcessor {
|
||||
archived,
|
||||
cwd_filters,
|
||||
search_term,
|
||||
search_mode,
|
||||
use_state_db_only,
|
||||
} = filters;
|
||||
let mut cursor_obj = cursor;
|
||||
@@ -3287,6 +3291,12 @@ impl ThreadRequestProcessor {
|
||||
path_utils::paths_match_after_normalization(&it.cwd, expected_cwd)
|
||||
})
|
||||
})
|
||||
&& match (search_mode, search_term.as_deref()) {
|
||||
(Some(ThreadListSearchMode::ExactName), Some(search_term)) => {
|
||||
it.name.as_deref() == Some(search_term)
|
||||
}
|
||||
_ => true,
|
||||
}
|
||||
{
|
||||
filtered.push(it);
|
||||
if filtered.len() >= remaining {
|
||||
|
||||
@@ -331,6 +331,7 @@ async fn external_agent_config_import_creates_session_rollouts() -> Result<()> {
|
||||
cwd: None,
|
||||
use_state_db_only: false,
|
||||
search_term: None,
|
||||
search_mode: None,
|
||||
})
|
||||
.await?;
|
||||
let response: JSONRPCResponse = timeout(
|
||||
@@ -500,6 +501,7 @@ async fn external_agent_config_import_accepts_detected_session_payload_after_res
|
||||
cwd: None,
|
||||
use_state_db_only: false,
|
||||
search_term: None,
|
||||
search_mode: None,
|
||||
})
|
||||
.await?;
|
||||
let response: JSONRPCResponse = timeout(
|
||||
@@ -586,6 +588,7 @@ async fn external_agent_config_import_skips_already_imported_session_versions()
|
||||
cwd: None,
|
||||
use_state_db_only: false,
|
||||
search_term: None,
|
||||
search_mode: None,
|
||||
})
|
||||
.await?;
|
||||
let response: JSONRPCResponse = timeout(
|
||||
@@ -724,6 +727,7 @@ async fn external_agent_config_import_returns_before_background_session_import_f
|
||||
cwd: None,
|
||||
use_state_db_only: false,
|
||||
search_term: None,
|
||||
search_mode: None,
|
||||
})
|
||||
.await?;
|
||||
let response: JSONRPCResponse = timeout(
|
||||
@@ -808,6 +812,7 @@ async fn external_agent_config_import_rejects_undetected_session_paths() -> Resu
|
||||
cwd: None,
|
||||
use_state_db_only: false,
|
||||
search_term: None,
|
||||
search_mode: None,
|
||||
})
|
||||
.await?;
|
||||
let response: JSONRPCResponse = timeout(
|
||||
@@ -931,6 +936,7 @@ async fn external_agent_config_import_compacts_huge_session_before_first_follow_
|
||||
cwd: None,
|
||||
use_state_db_only: false,
|
||||
search_term: None,
|
||||
search_mode: None,
|
||||
})
|
||||
.await?;
|
||||
let response: JSONRPCResponse = timeout(
|
||||
|
||||
@@ -153,6 +153,7 @@ async fn thread_start_with_non_local_thread_store_does_not_create_local_persiste
|
||||
cwd: None,
|
||||
use_state_db_only: false,
|
||||
search_term: None,
|
||||
search_mode: None,
|
||||
},
|
||||
})
|
||||
.await?
|
||||
|
||||
@@ -690,6 +690,7 @@ async fn thread_fork_ephemeral_remains_pathless_and_omits_listing() -> Result<()
|
||||
cwd: None,
|
||||
use_state_db_only: false,
|
||||
search_term: None,
|
||||
search_mode: None,
|
||||
})
|
||||
.await?;
|
||||
let list_resp: JSONRPCResponse = timeout(
|
||||
|
||||
@@ -17,6 +17,9 @@ use codex_app_server_protocol::SessionSource;
|
||||
use codex_app_server_protocol::SortDirection;
|
||||
use codex_app_server_protocol::ThreadListCwdFilter;
|
||||
use codex_app_server_protocol::ThreadListResponse;
|
||||
use codex_app_server_protocol::ThreadListSearchMode;
|
||||
use codex_app_server_protocol::ThreadSetNameParams;
|
||||
use codex_app_server_protocol::ThreadSetNameResponse;
|
||||
use codex_app_server_protocol::ThreadSortKey;
|
||||
use codex_app_server_protocol::ThreadSourceKind;
|
||||
use codex_app_server_protocol::ThreadStartParams;
|
||||
@@ -93,6 +96,7 @@ async fn list_threads_with_sort(
|
||||
cwd: None,
|
||||
use_state_db_only: false,
|
||||
search_term: None,
|
||||
search_mode: None,
|
||||
})
|
||||
.await?;
|
||||
let resp: JSONRPCResponse = timeout(
|
||||
@@ -533,6 +537,7 @@ async fn thread_list_respects_cwd_filters() -> Result<()> {
|
||||
])),
|
||||
use_state_db_only: false,
|
||||
search_term: None,
|
||||
search_mode: None,
|
||||
})
|
||||
.await?;
|
||||
let resp: JSONRPCResponse = timeout(
|
||||
@@ -630,6 +635,24 @@ sqlite = true
|
||||
assert_eq!(repaired_page.items.len(), 3);
|
||||
|
||||
let mut mcp = init_mcp(codex_home.path()).await?;
|
||||
let set_name_id = mcp
|
||||
.send_thread_set_name_request(ThreadSetNameParams {
|
||||
thread_id: newer_match.clone(),
|
||||
name: "needle exact".to_string(),
|
||||
})
|
||||
.await?;
|
||||
let set_name_resp: JSONRPCResponse = timeout(
|
||||
DEFAULT_READ_TIMEOUT,
|
||||
mcp.read_stream_until_response_message(RequestId::Integer(set_name_id)),
|
||||
)
|
||||
.await??;
|
||||
let _: ThreadSetNameResponse = to_response::<ThreadSetNameResponse>(set_name_resp)?;
|
||||
let _ = timeout(
|
||||
DEFAULT_READ_TIMEOUT,
|
||||
mcp.read_stream_until_notification_message("thread/name/updated"),
|
||||
)
|
||||
.await??;
|
||||
|
||||
let request_id = mcp
|
||||
.send_thread_list_request(codex_app_server_protocol::ThreadListParams {
|
||||
cursor: None,
|
||||
@@ -642,6 +665,7 @@ sqlite = true
|
||||
cwd: None,
|
||||
use_state_db_only: false,
|
||||
search_term: Some("needle".to_string()),
|
||||
search_mode: None,
|
||||
})
|
||||
.await?;
|
||||
let resp: JSONRPCResponse = timeout(
|
||||
@@ -655,7 +679,37 @@ sqlite = true
|
||||
|
||||
assert_eq!(next_cursor, None);
|
||||
let ids: Vec<_> = data.iter().map(|thread| thread.id.as_str()).collect();
|
||||
assert_eq!(ids, vec![newer_match, older_match]);
|
||||
assert_eq!(ids, vec![newer_match.as_str(), older_match.as_str()]);
|
||||
|
||||
let exact_request_id = mcp
|
||||
.send_thread_list_request(codex_app_server_protocol::ThreadListParams {
|
||||
cursor: None,
|
||||
limit: Some(10),
|
||||
sort_key: None,
|
||||
sort_direction: None,
|
||||
model_providers: Some(vec!["mock_provider".to_string()]),
|
||||
source_kinds: None,
|
||||
archived: None,
|
||||
cwd: None,
|
||||
use_state_db_only: false,
|
||||
search_term: Some("needle exact".to_string()),
|
||||
search_mode: Some(ThreadListSearchMode::ExactName),
|
||||
})
|
||||
.await?;
|
||||
let exact_resp: JSONRPCResponse = timeout(
|
||||
DEFAULT_READ_TIMEOUT,
|
||||
mcp.read_stream_until_response_message(RequestId::Integer(exact_request_id)),
|
||||
)
|
||||
.await??;
|
||||
let ThreadListResponse {
|
||||
data: exact_data,
|
||||
next_cursor: exact_next_cursor,
|
||||
..
|
||||
} = to_response::<ThreadListResponse>(exact_resp)?;
|
||||
|
||||
assert_eq!(exact_next_cursor, None);
|
||||
let exact_ids: Vec<_> = exact_data.iter().map(|thread| thread.id.as_str()).collect();
|
||||
assert_eq!(exact_ids, vec![newer_match.as_str()]);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -703,6 +757,7 @@ sqlite = true
|
||||
cwd: None,
|
||||
use_state_db_only: false,
|
||||
search_term: None,
|
||||
search_mode: None,
|
||||
})
|
||||
.await?;
|
||||
let resp: JSONRPCResponse = timeout(
|
||||
@@ -741,6 +796,7 @@ sqlite = true
|
||||
)),
|
||||
use_state_db_only: true,
|
||||
search_term: None,
|
||||
search_mode: None,
|
||||
})
|
||||
.await?;
|
||||
let resp: JSONRPCResponse = timeout(
|
||||
@@ -770,6 +826,7 @@ sqlite = true
|
||||
)),
|
||||
use_state_db_only: false,
|
||||
search_term: None,
|
||||
search_mode: None,
|
||||
})
|
||||
.await?;
|
||||
let resp: JSONRPCResponse = timeout(
|
||||
@@ -1464,6 +1521,7 @@ async fn thread_list_backwards_cursor_can_seed_forward_delta_sync() -> Result<()
|
||||
cwd: None,
|
||||
use_state_db_only: false,
|
||||
search_term: None,
|
||||
search_mode: None,
|
||||
})
|
||||
.await?;
|
||||
let resp: JSONRPCResponse = timeout(
|
||||
@@ -1506,6 +1564,7 @@ async fn thread_list_backwards_cursor_can_seed_forward_delta_sync() -> Result<()
|
||||
cwd: None,
|
||||
use_state_db_only: false,
|
||||
search_term: None,
|
||||
search_mode: None,
|
||||
})
|
||||
.await?;
|
||||
let resp: JSONRPCResponse = timeout(
|
||||
@@ -1744,6 +1803,7 @@ async fn thread_list_invalid_cursor_returns_error() -> Result<()> {
|
||||
cwd: None,
|
||||
use_state_db_only: false,
|
||||
search_term: None,
|
||||
search_mode: None,
|
||||
})
|
||||
.await?;
|
||||
let error: JSONRPCError = timeout(
|
||||
|
||||
@@ -483,6 +483,7 @@ async fn thread_list_includes_store_thread_without_rollout_path() -> Result<()>
|
||||
cwd: None,
|
||||
use_state_db_only: false,
|
||||
search_term: None,
|
||||
search_mode: None,
|
||||
},
|
||||
})
|
||||
.await?
|
||||
@@ -804,6 +805,7 @@ async fn thread_name_set_is_reflected_in_read_list_and_resume() -> Result<()> {
|
||||
cwd: None,
|
||||
use_state_db_only: false,
|
||||
search_term: None,
|
||||
search_mode: None,
|
||||
})
|
||||
.await?;
|
||||
let list_resp: JSONRPCResponse = timeout(
|
||||
|
||||
@@ -185,6 +185,7 @@ impl AppServerClient {
|
||||
cwd: None,
|
||||
use_state_db_only: false,
|
||||
search_term: None,
|
||||
search_mode: None,
|
||||
},
|
||||
};
|
||||
self.send(&request)?;
|
||||
|
||||
@@ -1349,6 +1349,7 @@ async fn resolve_resume_thread_id(
|
||||
cwd: None,
|
||||
use_state_db_only: false,
|
||||
search_term: None,
|
||||
search_mode: None,
|
||||
},
|
||||
},
|
||||
"thread/list",
|
||||
@@ -1414,6 +1415,7 @@ async fn resolve_resume_thread_id(
|
||||
cwd: None,
|
||||
use_state_db_only: false,
|
||||
search_term: Some(session_id.to_string()),
|
||||
search_mode: None,
|
||||
},
|
||||
},
|
||||
"thread/list",
|
||||
|
||||
@@ -32,6 +32,7 @@ use codex_app_server_protocol::ConfigWarningNotification;
|
||||
use codex_app_server_protocol::Thread as AppServerThread;
|
||||
use codex_app_server_protocol::ThreadListCwdFilter;
|
||||
use codex_app_server_protocol::ThreadListParams;
|
||||
use codex_app_server_protocol::ThreadListSearchMode;
|
||||
use codex_app_server_protocol::ThreadSortKey as AppServerThreadSortKey;
|
||||
use codex_app_server_protocol::ThreadSourceKind;
|
||||
use codex_cloud_requirements::cloud_requirements_loader_for_storage;
|
||||
@@ -546,34 +547,26 @@ async fn lookup_session_target_by_name_with_app_server(
|
||||
app_server: &mut AppServerSession,
|
||||
name: &str,
|
||||
) -> color_eyre::Result<Option<resume_picker::SessionTarget>> {
|
||||
let mut cursor = None;
|
||||
loop {
|
||||
let response = app_server
|
||||
.thread_list(ThreadListParams {
|
||||
cursor: cursor.clone(),
|
||||
limit: Some(100),
|
||||
sort_key: Some(AppServerThreadSortKey::UpdatedAt),
|
||||
sort_direction: None,
|
||||
model_providers: None,
|
||||
source_kinds: Some(vec![ThreadSourceKind::Cli, ThreadSourceKind::VsCode]),
|
||||
archived: Some(false),
|
||||
cwd: None,
|
||||
use_state_db_only: false,
|
||||
search_term: Some(name.to_string()),
|
||||
})
|
||||
.await?;
|
||||
if let Some(thread) = response
|
||||
.data
|
||||
.into_iter()
|
||||
.find(|thread| thread.name.as_deref() == Some(name))
|
||||
{
|
||||
return Ok(session_target_from_app_server_thread(thread));
|
||||
}
|
||||
if response.next_cursor.is_none() {
|
||||
return Ok(None);
|
||||
}
|
||||
cursor = response.next_cursor;
|
||||
}
|
||||
let response = app_server
|
||||
.thread_list(ThreadListParams {
|
||||
cursor: None,
|
||||
limit: Some(1),
|
||||
sort_key: Some(AppServerThreadSortKey::UpdatedAt),
|
||||
sort_direction: None,
|
||||
model_providers: None,
|
||||
source_kinds: Some(vec![ThreadSourceKind::Cli, ThreadSourceKind::VsCode]),
|
||||
archived: Some(false),
|
||||
cwd: None,
|
||||
use_state_db_only: false,
|
||||
search_term: Some(name.to_string()),
|
||||
search_mode: Some(ThreadListSearchMode::ExactName),
|
||||
})
|
||||
.await?;
|
||||
Ok(response
|
||||
.data
|
||||
.into_iter()
|
||||
.next()
|
||||
.and_then(session_target_from_app_server_thread))
|
||||
}
|
||||
|
||||
async fn lookup_session_target_with_app_server(
|
||||
@@ -653,6 +646,7 @@ fn latest_session_lookup_params(
|
||||
cwd: cwd_filter.map(|cwd| ThreadListCwdFilter::One(cwd.to_string_lossy().to_string())),
|
||||
use_state_db_only: false,
|
||||
search_term: None,
|
||||
search_mode: None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2047,6 +2041,29 @@ mod tests {
|
||||
.upsert_thread(&metadata)
|
||||
.await
|
||||
.map_err(std::io::Error::other)?;
|
||||
let newer_thread_id = ThreadId::new();
|
||||
let newer_rollout_path = temp_dir.path().join("sessions/2025/02/01").join(format!(
|
||||
"rollout-2025-02-01T11-00-00-{newer_thread_id}.jsonl"
|
||||
));
|
||||
std::fs::write(&newer_rollout_path, "")?;
|
||||
let newer_created_at = chrono::DateTime::parse_from_rfc3339("2025-02-01T11:00:00Z")
|
||||
.expect("timestamp should parse")
|
||||
.with_timezone(&chrono::Utc);
|
||||
let mut newer_builder = codex_state::ThreadMetadataBuilder::new(
|
||||
newer_thread_id,
|
||||
newer_rollout_path,
|
||||
newer_created_at,
|
||||
serde_json::from_value(serde_json::json!("cli"))
|
||||
.expect("cli session source should deserialize"),
|
||||
);
|
||||
newer_builder.cwd = temp_dir.path().join("other-project");
|
||||
let mut newer_metadata = newer_builder.build(config.model_provider_id.as_str());
|
||||
newer_metadata.title = "saved-session-copy".to_string();
|
||||
newer_metadata.first_user_message = Some("other preview text".to_string());
|
||||
state_runtime
|
||||
.upsert_thread(&newer_metadata)
|
||||
.await
|
||||
.map_err(std::io::Error::other)?;
|
||||
|
||||
let mut app_server =
|
||||
AppServerSession::new(codex_app_server_client::AppServerClient::InProcess(
|
||||
|
||||
@@ -1017,6 +1017,7 @@ fn thread_list_params(
|
||||
cwd: cwd_filter.map(|cwd| ThreadListCwdFilter::One(cwd.to_string_lossy().into_owned())),
|
||||
use_state_db_only: false,
|
||||
search_term: None,
|
||||
search_mode: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user