Files
codex/codex-rs/state/src/delegated_preview_tests.rs
T
Benjamin Carlsson 09bced5ad9 Populate thread previews from delegated task inputs (#50462)
## Why

Delegated turns can begin without a user message, leaving threads without a task preview. Populate the preview from delegated input so these threads are discoverable before a user follow-up.

## What changed

- Extract previews from completed `create_thread` and `send_message_to_thread` outputs in the `codex_app` and `codex_tui` namespaces.
- Unwrap recognized `<codex_delegation>` inputs and decode their escaped task text for display, preserving model content. Keep plain or unrecognized wrappers as text and ignore blank inputs.
- Fill missing previews in state metadata extraction and live thread metadata updates without replacing existing previews or setting the title or `first_user_message`.

## Testing

Add tests for delegation decoding and tool filtering, preview-only metadata updates, preservation of later user-message metadata, and database listing before a user follow-up in both legacy and paginated history modes.

GitOrigin-RevId: f7b3c60ef75e08c76b4084d043e3967bf2bade22
2026-10-02 23:34:11 +00:00

50 lines
1.7 KiB
Rust

//! Verify delegated preview decoding and tool identity filtering.
use super::delegated_output_preview;
use codex_protocol::items::FunctionCallOutputItem;
use codex_protocol::models::FunctionCallOutputBody;
use pretty_assertions::assert_eq;
#[test]
fn delegated_previews_unwrap_only_recognized_inputs() {
let wrapped = "<codex_delegation>\n <source_thread_id>source</source_thread_id>\n <input>Check &lt;main&gt; &amp; &amp;lt;literal&amp;gt;</input>\n</codex_delegation>";
for (namespace, name, text, expected) in [
(
Some("codex_app"),
"create_thread",
wrapped,
Some("Check <main> & &lt;literal&gt;"),
),
(
Some("codex_tui"),
"send_message_to_thread",
wrapped,
Some("Check <main> & &lt;literal&gt;"),
),
(
Some("codex_app"),
"create_thread",
"plain &lt;text&gt;",
Some("plain &lt;text&gt;"),
),
(Some("codex_tui"), "create_thread", " ", None),
(Some("other"), "create_thread", wrapped, None),
(None, "create_thread", wrapped, None),
(Some("codex_app"), "shell", wrapped, None),
(
Some("codex_app"),
"create_thread",
"<codex_delegation>incomplete",
Some("<codex_delegation>incomplete"),
),
] {
let output = FunctionCallOutputItem {
id: "output".to_string(),
name: name.to_string(),
namespace: namespace.map(str::to_string),
output: FunctionCallOutputBody::Text(text.to_string()),
};
assert_eq!(delegated_output_preview(&output).as_deref(), expected);
}
}