mirror of
https://github.com/openai/codex.git
synced 2026-10-22 17:58:46 +00:00
Add local diagnostic ZIP exports to the app server (#55940)
## What changed Add a save RPC that accepts the existing report options and an absolute `savePath` on the server host. Save the report, selected attachments, and a manifest without uploading, and return `savedPath`, `threadId`, and `promptHash`. Local exports remain available when uploads are disabled by configuration. Publish archives atomically without replacing existing files. Bound uncompressed contents to 200 MiB and attachments to 128, preserve duplicate attachment names safely, and fail without publishing a partial ZIP when a selected file cannot be read. Honor `includeLogs` and omit automatic rollouts for untouched threads without materializing them. Update protocol schemas and generated TypeScript and Python types. ## Testing Add coverage for local-only saves, disabled uploads, path validation, overwrite protection, log consent, archive budgets, duplicate names, missing files, and rollout selection before materialization and after writer shutdown. GitOrigin-RevId: 222c0fe7ab923904de9c8a9f12ad27f7a0104875
This commit is contained in:
@@ -411,6 +411,18 @@ impl LiveThread {
|
||||
.map(Some)
|
||||
}
|
||||
|
||||
/// Selects a local feedback input only after its writer has materialized it.
|
||||
pub async fn feedback_rollout_path(&self) -> ThreadStoreResult<Option<PathBuf>> {
|
||||
let Some(local_store) = self
|
||||
.thread_store
|
||||
.as_any()
|
||||
.downcast_ref::<LocalThreadStore>()
|
||||
else {
|
||||
return Ok(None);
|
||||
};
|
||||
local_store.feedback_rollout_path(self.thread_id).await
|
||||
}
|
||||
|
||||
async fn flush_pending_metadata_update(&self) -> ThreadStoreResult<()> {
|
||||
let update = self.metadata_sync.lock().await.take_pending_update();
|
||||
self.apply_pending_metadata_update(update, PersistContext::Standard)
|
||||
|
||||
@@ -339,6 +339,26 @@ impl LocalThreadStore {
|
||||
live_writer::rollout_path(self, thread_id).await
|
||||
}
|
||||
|
||||
/// Select only materialized rollout inputs without creating a file for untouched threads.
|
||||
pub(crate) async fn feedback_rollout_path(
|
||||
&self,
|
||||
thread_id: ThreadId,
|
||||
) -> ThreadStoreResult<Option<PathBuf>> {
|
||||
let (recorder, _, _) = live_writer::live_writer_parts(self, thread_id).await?;
|
||||
if recorder
|
||||
.unpersisted_session_meta()
|
||||
.await
|
||||
.map_err(|error| ThreadStoreError::Internal {
|
||||
message: error.to_string(),
|
||||
})?
|
||||
.is_some()
|
||||
{
|
||||
return Ok(None);
|
||||
}
|
||||
// Keep the path even if a materialized file was deleted: collection must report that error.
|
||||
Ok(Some(recorder.rollout_path().to_path_buf()))
|
||||
}
|
||||
|
||||
pub(super) async fn ensure_live_recorder_absent(
|
||||
&self,
|
||||
thread_id: ThreadId,
|
||||
|
||||
Reference in New Issue
Block a user