Skip to content

Seed prompt history from resumed messages#24298

Merged
etraut-openai merged 6 commits into
mainfrom
etraut/seed-resumed-prompt-history
May 29, 2026
Merged

Seed prompt history from resumed messages#24298
etraut-openai merged 6 commits into
mainfrom
etraut/seed-resumed-prompt-history

Conversation

@etraut-openai
Copy link
Copy Markdown
Collaborator

Why

When the TUI resumes a thread, transcript replay renders prior user messages but did not seed the composer history. That leaves the resumed session with empty in-memory prompt history, so pressing Up can fall through to persisted global history and surface a prompt from another thread.

The expected behavior is that prompts from the resumed thread are recalled first, with global history only as a fallback.

What changed

  • Record replayed user messages into the composer history during resume replay.
  • Preserve the existing persisted history format and avoid any startup history scan.
  • Add focused TUI coverage showing replayed prompts are recalled before persisted global history.

Validation

  • Added replayed_user_messages_seed_composer_history in codex-rs/tui/src/chatwidget/tests/history_replay.rs.
  • just test -p codex-tui replayed_user_messages_seed_composer_history passed.

Copy link
Copy Markdown
Contributor

@fcoury-oai fcoury-oai left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Found two issues with Codex help. I only reproduced the first with the following test:

export SMOKE_CODEX_HOME="$(mktemp -d)"
cp ~/.codex/auth.json "$SMOKE_CODEX_HOME"/
cp ~/.codex/config.toml "$SMOKE_CODEX_HOME"/

CODEX_HOME="$SMOKE_CODEX_HOME" ./codex-rs/target/debug/codex

Then I renamed the session /rename smoke-1 and sent two prompts: Reply with exactly: first-ok then Reply with exactly: second-ok.

Then I quit this initial session and ran:

CODEX_HOME="$SMOKE_CODEX_HOME" ./codex-rs/target/debug/codex resume smoke-1

When pressing Up to retrieve items from history I expected to see:

Reply with exactly: second-ok
Reply with exactly: first-ok

But instead I see:

Reply with exactly: second-ok
Reply with exactly: first-ok
/rename smoke-1

Then it repeats:

Reply with exactly: second-ok
Reply with exactly: first-ok

Comment thread codex-rs/tui/src/chatwidget.rs Outdated
fn on_committed_user_message(&mut self, items: &[UserInput], from_replay: bool) {
let display = Self::user_message_display_from_inputs(items);
if from_replay {
self.bottom_pane.record_replayed_user_message_history(
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Recording replayed prompts as local submissions makes them take precedence over persistent history, but the persistent history snapshot still includes those same submitted prompts. Once the user presses Up past the replay-seeded local entries, navigation can fall through to the unchanged persistent offsets and recall the resumed prompts again. Can we either skip/de-dupe those persistent entries at the boundary or cover the fallthrough case in the test?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, good find. I had a somewhat incorrect understanding of how persistent history was restored prior to this change, and that led me to miss this detail. Should be fixed now.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[codex] Good catch. This is fixed in the latest push: replay-seeded local entries now take precedence, and when normal history navigation falls through into persisted history we skip persistent entries whose text duplicates those local replay entries. The updated replayed_user_messages_seed_composer_history test now covers the fallthrough path by simulating the duplicate persisted responses before continuing to the next older persisted entry.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Codex] The fallthrough test covers replay duplicates, but the implementation skips more than replay-seeded entries: persistent_entry_duplicates_local compares against every local_history entry, which also contains ordinary submissions made during the current UI session. If the user submits text that already exists in persisted history, navigating into older persisted entries now silently skips that legitimate entry (and can skip an entry with different hidden mention bindings). Please scope this de-duplication to entries seeded from replay rather than all local history.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be fixed now

text_elements,
local_image_paths,
remote_image_urls,
mention_bindings: Vec::new(),
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Second issue found with Codex: please preserve structured mention bindings when recording replayed prompts. The app-server UserInput already carries Skill/Mention items, but this path records an empty binding list, so recalled resumed prompts can lose the exact selected mention target.

record_replayed_user_message_history stores mention_bindings: Vec::new(), and the replay display builder ignores structured UserInput::Skill / UserInput::Mention items. That means a recalled resumed prompt can look correct but lose the exact selected skill/app mention path. On resubmit, the TUI falls back to text-based mention discovery instead of the original binding. This is especially risky because the new local replay entry takes precedence over the existing persistent history path, which encodes mention bindings specifically so future recall can reconstruct them.

Impact: A user who resumes a thread and recalls a prompt containing an app, plugin, or skill mention may resubmit a prompt that no longer targets the same resource.

Repro steps: Static repro: submit a prompt with an explicitly selected mention, resume the thread, press Up to recall that prompt, then resubmit. The replay-seeded HistoryEntry has no mention_bindings, so resubmission cannot use the original selected path.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. Fixed.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[codex] Fixed in the latest push. Replay now extracts structured Skill and Mention items from the replayed UserInput and stores them as MentionBindings on the replay-seeded HistoryEntry, instead of recording an empty binding list. The updated replayed_user_messages_seed_composer_history test verifies that a recalled replayed skill mention preserves its selected binding.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Codex] This is still not fixed for app/plugin mentions. The new replay path builds MentionBinding { mention: name, path } from UserInput::Mention, but normal submission uses the app/plugin display name for UserInput::Mention.name while the visible token can be a different slug. For example, the existing plugin test submits visible text $sample but emits UserInput::Mention { name: "Sample Plugin", path: "plugin://sample@test" }. After replay, bind_mentions_from_snapshot looks for $Sample Plugin, does not find $sample, and the selected binding is lost on resubmit. The added test only covers Skill, where the name happens to match the token; please cover an app/plugin Mention case and preserve the visible mention key.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be fixed now

@etraut-openai etraut-openai force-pushed the etraut/seed-resumed-prompt-history branch 4 times, most recently from f3cb689 to 9d58c8b Compare May 27, 2026 19:53
@etraut-openai etraut-openai force-pushed the etraut/seed-resumed-prompt-history branch from 9d58c8b to 7c92c0f Compare May 27, 2026 20:01
@etraut-openai
Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector
Copy link
Copy Markdown
Contributor

Codex Review: Didn't find any major issues. Nice work!

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@etraut-openai etraut-openai requested a review from fcoury-oai May 27, 2026 20:46
Copy link
Copy Markdown
Contributor

@fcoury-oai fcoury-oai left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Codex found an issue that I was able to replicate: the /review instructions prompt is usually hidden from the history but that's not the case in this PR. The fix seems very straightforward.

I am approving this PR with this restriction. This way, once it's fixed you're welcome to merge it.

Comment on lines +1244 to +1252
self.bottom_pane
.record_replayed_user_message_history(HistoryEntry {
text: display.message.clone(),
text_elements: display.text_elements.clone(),
local_image_paths: display.local_images.clone(),
remote_image_urls: display.remote_image_urls.clone(),
mention_bindings,
pending_pastes: Vec::new(),
});
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Codex identified a bug that I was able to replicate. I started a session, entered /review and waited for the review to start then cancelled and quit the session.

When I resume the same session and press up arrow, I get the review prompt:

› Review the code changes against the base branch 'main'. The merge base commit for this comparison is
  7d47056ea42636271ac020b86347fbbef49490aa. Run `git diff 7d47056ea42636271ac020b86347fbbef49490aa` to inspect the changes relative to main.
  Provide prioritized, actionable findings.

I believe the fix would be to record replayed history only inside the if !self.review.is_review_mode block below.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, good find. Fixed.

Copy link
Copy Markdown
Contributor

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 412f7e7bf8

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread codex-rs/tui/src/chatwidget.rs Outdated
Copy link
Copy Markdown
Contributor

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8de100485d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread codex-rs/tui/src/chatwidget.rs
Comment thread codex-rs/tui/src/chatwidget.rs Outdated
Copy link
Copy Markdown
Contributor

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7a3af59aa4

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread codex-rs/tui/src/chatwidget.rs Outdated
Copy link
Copy Markdown
Contributor

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 619477e5e3

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread codex-rs/tui/src/bottom_pane/chat_composer_history.rs
@etraut-openai etraut-openai merged commit 56958f2 into main May 29, 2026
31 checks passed
@etraut-openai etraut-openai deleted the etraut/seed-resumed-prompt-history branch May 29, 2026 05:08
@github-actions github-actions Bot locked and limited conversation to collaborators May 29, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants