Pass turn id with feedback uploads (#17314)

## Summary
- Add an optional `tags` dictionary to feedback upload params.
- Capture the active app-server turn id in the TUI and submit it as
`tags.turn_id` with `/feedback` uploads.
- Merge client-provided feedback tags into Sentry feedback tags while
preserving reserved system fields like `thread_id`, `classification`,
`cli_version`, `session_source`, and `reason`.

## Behavior / impact
Existing feedback upload callers remain compatible because `tags` is
optional and nullable. The wire shape is still a normal JSON object /
TypeScript dictionary, so adding future feedback metadata will not
require a new top-level protocol field each time. This change only adds
feedback metadata for Codex CLI/TUI uploads; it does not affect existing
pipelines, DAGs, exports, or downstream consumers unless they choose to
read the new `turn_id` feedback tag.

## Tests
- `cargo fmt -- --config imports_granularity=Item` passed; stable
rustfmt warned that `imports_granularity` is nightly-only.
- `cargo run -p codex-app-server-protocol --bin write_schema_fixtures`
- `cargo test -p codex-feedback
upload_tags_include_client_tags_and_preserve_reserved_fields`
- `cargo test -p codex-app-server-protocol
schema_fixtures_match_generated`
- `cargo test -p codex-tui build_feedback_upload_params`
- `cargo test -p codex-tui
live_app_server_turn_started_sets_feedback_turn_id`
- `cargo check -p codex-app-server --tests`
- `git diff --check`

---------

Co-authored-by: Codex <noreply@openai.com>
This commit is contained in:
ningyi-oai
2026-04-11 00:23:50 -07:00
committed by GitHub
Unverified
parent dbfe855f4f
commit be13f03c39
14 changed files with 290 additions and 65 deletions
@@ -243,6 +243,7 @@ use codex_features::FEATURES;
use codex_features::Feature;
use codex_features::Stage;
use codex_feedback::CodexFeedback;
use codex_feedback::FeedbackUploadOptions;
use codex_git_utils::git_diff_to_remote;
use codex_git_utils::resolve_root_git_project_for_trust;
use codex_login::AuthManager;
@@ -7726,6 +7727,7 @@ impl CodexMessageProcessor {
thread_id,
include_logs,
extra_log_files,
tags,
} = params;
let conversation_id = match thread_id.as_deref() {
@@ -7853,14 +7855,15 @@ impl CodexMessageProcessor {
let session_source = self.thread_manager.session_source();
let upload_result = tokio::task::spawn_blocking(move || {
snapshot.upload_feedback(
&classification,
reason.as_deref(),
snapshot.upload_feedback(FeedbackUploadOptions {
classification: &classification,
reason: reason.as_deref(),
tags: tags.as_ref(),
include_logs,
&attachment_paths,
Some(session_source),
sqlite_feedback_logs,
)
extra_attachment_paths: &attachment_paths,
session_source: Some(session_source),
logs_override: sqlite_feedback_logs,
})
})
.await;