mirror of
https://github.com/openai/codex.git
synced 2026-10-18 17:18:52 +00:00
Attach connector caches to diagnostic uploads (#32891)
## What changed - Include the active Codex Apps tools cache and connector directory cache, when available, in diagnostic uploads that include logs. - Resolve cache paths from the current authentication context and use stable attachment filenames. - List both optional cache files in the upload consent dialog. ## Testing - Add coverage for selecting existing active cache files, including a directory cache without an account ID. - Update consent dialog snapshots to include the optional attachments. GitOrigin-RevId: 1d4ffbf2bcb96653f03dc25f91d80dd65038d585
This commit is contained in:
@@ -1,4 +1,9 @@
|
||||
use super::*;
|
||||
use codex_connectors::ConnectorDirectoryCacheContext;
|
||||
use codex_connectors::ConnectorDirectoryCacheKey;
|
||||
use codex_connectors::connector_runtime_cache_path;
|
||||
use codex_feedback::CODEX_APP_DIRECTORY_CACHE_ATTACHMENT_FILENAME;
|
||||
use codex_feedback::CODEX_APPS_TOOLS_CACHE_ATTACHMENT_FILENAME;
|
||||
#[cfg(target_os = "windows")]
|
||||
use codex_feedback::WINDOWS_SANDBOX_LOG_ATTACHMENT_FILENAME;
|
||||
|
||||
@@ -70,17 +75,16 @@ impl FeedbackRequestProcessor {
|
||||
None => None,
|
||||
};
|
||||
|
||||
if let Some(chatgpt_user_id) = self
|
||||
.auth_manager
|
||||
.auth_cached()
|
||||
.and_then(|auth| auth.get_chatgpt_user_id())
|
||||
let auth = self.auth_manager.auth_cached();
|
||||
if let Some(chatgpt_user_id) = auth
|
||||
.as_ref()
|
||||
.and_then(codex_login::CodexAuth::get_chatgpt_user_id)
|
||||
{
|
||||
tracing::info!(target: "feedback_tags", chatgpt_user_id);
|
||||
}
|
||||
if let Some(account_id) = self
|
||||
.auth_manager
|
||||
.auth_cached()
|
||||
.and_then(|auth| auth.get_account_id())
|
||||
if let Some(account_id) = auth
|
||||
.as_ref()
|
||||
.and_then(codex_login::CodexAuth::get_account_id)
|
||||
{
|
||||
tracing::info!(target: "feedback_tags", account_id);
|
||||
}
|
||||
@@ -197,6 +201,15 @@ impl FeedbackRequestProcessor {
|
||||
{
|
||||
attachment_paths.push(sandbox_log_attachment);
|
||||
}
|
||||
for cache_attachment in tool_cache_feedback_attachments(
|
||||
self.config.codex_home.as_path(),
|
||||
&self.config.chatgpt_base_url,
|
||||
auth.as_ref(),
|
||||
) {
|
||||
if seen_attachment_paths.insert(cache_attachment.path.clone()) {
|
||||
attachment_paths.push(cache_attachment);
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Some(extra_log_files) = extra_log_files {
|
||||
for extra_log_file in extra_log_files {
|
||||
@@ -272,6 +285,47 @@ impl FeedbackRequestProcessor {
|
||||
}
|
||||
}
|
||||
|
||||
fn tool_cache_feedback_attachments(
|
||||
codex_home: &Path,
|
||||
chatgpt_base_url: &str,
|
||||
auth: Option<&CodexAuth>,
|
||||
) -> Vec<FeedbackAttachmentPath> {
|
||||
let mut attachments = Vec::with_capacity(2);
|
||||
let tools_cache_path = connector_runtime_cache_path(codex_home, auth);
|
||||
if tools_cache_path.is_file() {
|
||||
attachments.push(FeedbackAttachmentPath {
|
||||
path: tools_cache_path,
|
||||
attachment_filename_override: Some(
|
||||
CODEX_APPS_TOOLS_CACHE_ATTACHMENT_FILENAME.to_string(),
|
||||
),
|
||||
});
|
||||
}
|
||||
|
||||
let Some(auth) = auth.filter(|auth| auth.uses_codex_backend()) else {
|
||||
return attachments;
|
||||
};
|
||||
let directory_cache_context = ConnectorDirectoryCacheContext::new(
|
||||
codex_home.to_path_buf(),
|
||||
ConnectorDirectoryCacheKey::new(
|
||||
chatgpt_base_url.to_string(),
|
||||
auth.get_account_id(),
|
||||
auth.get_chatgpt_user_id(),
|
||||
auth.is_workspace_account(),
|
||||
),
|
||||
);
|
||||
let directory_cache_path = directory_cache_context.cache_path();
|
||||
if directory_cache_path.is_file() {
|
||||
attachments.push(FeedbackAttachmentPath {
|
||||
path: directory_cache_path,
|
||||
attachment_filename_override: Some(
|
||||
CODEX_APP_DIRECTORY_CACHE_ATTACHMENT_FILENAME.to_string(),
|
||||
),
|
||||
});
|
||||
}
|
||||
|
||||
attachments
|
||||
}
|
||||
|
||||
fn auto_review_rollout_filename(thread_id: ThreadId) -> String {
|
||||
format!("auto-review-rollout-{thread_id}.jsonl")
|
||||
}
|
||||
@@ -292,11 +346,106 @@ fn windows_sandbox_log_attachment(_codex_home: &Path) -> Option<FeedbackAttachme
|
||||
None
|
||||
}
|
||||
|
||||
#[cfg(all(test, target_os = "windows"))]
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use pretty_assertions::assert_eq;
|
||||
|
||||
#[test]
|
||||
fn tool_cache_feedback_attachments_include_existing_active_cache_files() {
|
||||
let codex_home = tempfile::tempdir().expect("create tempdir");
|
||||
let auth = CodexAuth::create_dummy_chatgpt_auth_for_testing();
|
||||
let tools_cache_path = connector_runtime_cache_path(codex_home.path(), Some(&auth));
|
||||
std::fs::create_dir_all(tools_cache_path.parent().expect("tools cache parent"))
|
||||
.expect("create tools cache directory");
|
||||
std::fs::write(&tools_cache_path, b"tools").expect("write tools cache");
|
||||
|
||||
let account_id = auth.get_account_id().expect("dummy auth account id");
|
||||
let directory_cache_context = ConnectorDirectoryCacheContext::new(
|
||||
codex_home.path().to_path_buf(),
|
||||
ConnectorDirectoryCacheKey::new(
|
||||
"https://chatgpt.com/backend-api".to_string(),
|
||||
Some(account_id),
|
||||
auth.get_chatgpt_user_id(),
|
||||
auth.is_workspace_account(),
|
||||
),
|
||||
);
|
||||
let directory_cache_path = directory_cache_context.cache_path();
|
||||
std::fs::create_dir_all(
|
||||
directory_cache_path
|
||||
.parent()
|
||||
.expect("directory cache parent"),
|
||||
)
|
||||
.expect("create directory cache directory");
|
||||
std::fs::write(&directory_cache_path, b"directory").expect("write directory cache");
|
||||
|
||||
let attachments = tool_cache_feedback_attachments(
|
||||
codex_home.path(),
|
||||
"https://chatgpt.com/backend-api",
|
||||
Some(&auth),
|
||||
)
|
||||
.into_iter()
|
||||
.map(|attachment| (attachment.path, attachment.attachment_filename_override))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
assert_eq!(
|
||||
attachments,
|
||||
vec![
|
||||
(
|
||||
tools_cache_path,
|
||||
Some(CODEX_APPS_TOOLS_CACHE_ATTACHMENT_FILENAME.to_string()),
|
||||
),
|
||||
(
|
||||
directory_cache_path,
|
||||
Some(CODEX_APP_DIRECTORY_CACHE_ATTACHMENT_FILENAME.to_string()),
|
||||
),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tool_cache_feedback_attachments_include_directory_cache_without_account_id() {
|
||||
let codex_home = tempfile::tempdir().expect("create tempdir");
|
||||
let auth = CodexAuth::Headers(codex_login::AuthHeaders::new(
|
||||
reqwest::header::HeaderMap::new(),
|
||||
));
|
||||
let directory_cache_context = ConnectorDirectoryCacheContext::new(
|
||||
codex_home.path().to_path_buf(),
|
||||
ConnectorDirectoryCacheKey::new(
|
||||
"https://chatgpt.com/backend-api".to_string(),
|
||||
/*account_id*/ None,
|
||||
auth.get_chatgpt_user_id(),
|
||||
auth.is_workspace_account(),
|
||||
),
|
||||
);
|
||||
let directory_cache_path = directory_cache_context.cache_path();
|
||||
std::fs::create_dir_all(
|
||||
directory_cache_path
|
||||
.parent()
|
||||
.expect("directory cache parent"),
|
||||
)
|
||||
.expect("create directory cache directory");
|
||||
std::fs::write(&directory_cache_path, b"directory").expect("write directory cache");
|
||||
|
||||
let attachments = tool_cache_feedback_attachments(
|
||||
codex_home.path(),
|
||||
"https://chatgpt.com/backend-api",
|
||||
Some(&auth),
|
||||
)
|
||||
.into_iter()
|
||||
.map(|attachment| (attachment.path, attachment.attachment_filename_override))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
assert_eq!(
|
||||
attachments,
|
||||
vec![(
|
||||
directory_cache_path,
|
||||
Some(CODEX_APP_DIRECTORY_CACHE_ATTACHMENT_FILENAME.to_string()),
|
||||
)]
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
#[test]
|
||||
fn windows_sandbox_log_attachment_uses_current_log() {
|
||||
let codex_home = tempfile::tempdir().expect("create tempdir");
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
//! owned by the connector metadata store, not by this module.
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
use std::sync::Mutex;
|
||||
@@ -75,6 +76,15 @@ pub fn connector_runtime_context_key(auth: Option<&CodexAuth>) -> ConnectorRunti
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the persisted connector runtime tools cache path for the active auth identity.
|
||||
pub fn connector_runtime_cache_path(codex_home: &Path, auth: Option<&CodexAuth>) -> PathBuf {
|
||||
let identity = ConnectorRuntimeIdentity {
|
||||
codex_home: codex_home.to_path_buf(),
|
||||
key: connector_runtime_context_key(auth),
|
||||
};
|
||||
tools_cache_path(&identity)
|
||||
}
|
||||
|
||||
/// One atomically published connector runtime state.
|
||||
///
|
||||
/// Tools remain raw and in response order. Local and managed configuration is
|
||||
|
||||
@@ -26,7 +26,8 @@ impl ConnectorDirectoryCacheContext {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn cache_path(&self) -> PathBuf {
|
||||
/// Returns the persisted connector directory cache path for this identity.
|
||||
pub fn cache_path(&self) -> PathBuf {
|
||||
let cache_key_json = serde_json::to_string(&self.cache_key).unwrap_or_default();
|
||||
let cache_key_hash = sha1_hex(&cache_key_json);
|
||||
self.codex_home
|
||||
|
||||
@@ -36,6 +36,7 @@ pub use connector_runtime::ConnectorRuntimeFetchTicket;
|
||||
pub use connector_runtime::ConnectorRuntimeManager;
|
||||
pub use connector_runtime::ConnectorRuntimePayload;
|
||||
pub use connector_runtime::ConnectorRuntimeSnapshot;
|
||||
pub use connector_runtime::connector_runtime_cache_path;
|
||||
pub use connector_runtime::connector_runtime_context_key;
|
||||
pub use directory_cache::ConnectorDirectoryCacheContext;
|
||||
pub use plugin_config::parse_plugin_app_config;
|
||||
|
||||
@@ -31,6 +31,10 @@ pub use feedback_diagnostics::FeedbackDiagnostics;
|
||||
|
||||
/// Filename used for the redacted `codex doctor --json` feedback attachment.
|
||||
pub const DOCTOR_REPORT_ATTACHMENT_FILENAME: &str = "codex-doctor-report.json";
|
||||
/// Filename used for the raw Codex Apps MCP tools cache feedback attachment.
|
||||
pub const CODEX_APPS_TOOLS_CACHE_ATTACHMENT_FILENAME: &str = "codex-apps-tools-cache.json";
|
||||
/// Filename used for the raw connector directory cache feedback attachment.
|
||||
pub const CODEX_APP_DIRECTORY_CACHE_ATTACHMENT_FILENAME: &str = "codex-app-directory-cache.json";
|
||||
/// Filename used for the Windows sandbox log feedback attachment.
|
||||
pub const WINDOWS_SANDBOX_LOG_ATTACHMENT_FILENAME: &str = "windows-sandbox.log";
|
||||
const DEFAULT_MAX_BYTES: usize = 4 * 1024 * 1024; // 4 MiB
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use codex_feedback::CODEX_APP_DIRECTORY_CACHE_ATTACHMENT_FILENAME;
|
||||
use codex_feedback::CODEX_APPS_TOOLS_CACHE_ATTACHMENT_FILENAME;
|
||||
use codex_feedback::DOCTOR_REPORT_ATTACHMENT_FILENAME;
|
||||
use codex_feedback::FEEDBACK_DIAGNOSTICS_ATTACHMENT_FILENAME;
|
||||
use codex_feedback::FeedbackDiagnostics;
|
||||
@@ -510,6 +512,16 @@ pub(crate) fn feedback_upload_consent_params(
|
||||
DOCTOR_REPORT_ATTACHMENT_FILENAME.into(),
|
||||
])
|
||||
.into(),
|
||||
Line::from(vec![
|
||||
" • ".into(),
|
||||
format!("{CODEX_APPS_TOOLS_CACHE_ATTACHMENT_FILENAME} (if available)").into(),
|
||||
])
|
||||
.into(),
|
||||
Line::from(vec![
|
||||
" • ".into(),
|
||||
format!("{CODEX_APP_DIRECTORY_CACHE_ATTACHMENT_FILENAME} (if available)").into(),
|
||||
])
|
||||
.into(),
|
||||
];
|
||||
if include_windows_sandbox_log {
|
||||
header_lines.push(
|
||||
|
||||
+3
-1
@@ -1,6 +1,6 @@
|
||||
---
|
||||
source: tui/src/bottom_pane/feedback_view.rs
|
||||
assertion_line: 716
|
||||
assertion_line: 728
|
||||
expression: rendered
|
||||
---
|
||||
Upload logs?
|
||||
@@ -8,5 +8,7 @@ Upload logs?
|
||||
The following files will be sent:
|
||||
• codex-logs.log
|
||||
• codex-doctor-report.json
|
||||
• codex-apps-tools-cache.json (if available)
|
||||
• codex-app-directory-cache.json (if available)
|
||||
• rollout.jsonl
|
||||
• auto-review-rollout.jsonl
|
||||
|
||||
+3
-1
@@ -1,6 +1,6 @@
|
||||
---
|
||||
source: tui/src/bottom_pane/feedback_view.rs
|
||||
assertion_line: 734
|
||||
assertion_line: 746
|
||||
expression: rendered
|
||||
---
|
||||
Upload logs?
|
||||
@@ -8,6 +8,8 @@ Upload logs?
|
||||
The following files will be sent:
|
||||
• codex-logs.log
|
||||
• codex-doctor-report.json
|
||||
• codex-apps-tools-cache.json (if available)
|
||||
• codex-app-directory-cache.json (if available)
|
||||
• windows-sandbox.log
|
||||
• rollout.jsonl
|
||||
• auto-review-rollout.jsonl
|
||||
|
||||
+2
@@ -7,6 +7,8 @@ expression: popup
|
||||
The following files will be sent:
|
||||
• codex-logs.log
|
||||
• codex-doctor-report.json
|
||||
• codex-apps-tools-cache.json (if available)
|
||||
• codex-app-directory-cache.json (if available)
|
||||
• auto-review-rollout-thread-1.jsonl
|
||||
• codex-connectivity-diagnostics.txt
|
||||
|
||||
|
||||
+2
-1
@@ -1,6 +1,5 @@
|
||||
---
|
||||
source: tui/src/chatwidget/tests/popups_and_settings.rs
|
||||
assertion_line: 2562
|
||||
expression: popup
|
||||
---
|
||||
Upload logs?
|
||||
@@ -8,6 +7,8 @@ expression: popup
|
||||
The following files will be sent:
|
||||
• codex-logs.log
|
||||
• codex-doctor-report.json
|
||||
• codex-apps-tools-cache.json (if available)
|
||||
• codex-app-directory-cache.json (if available)
|
||||
• windows-sandbox.log
|
||||
• auto-review-rollout-thread-1.jsonl
|
||||
• codex-connectivity-diagnostics.txt
|
||||
|
||||
Reference in New Issue
Block a user