mirror of
https://github.com/openai/codex.git
synced 2026-11-13 06:45:07 +00:00
Add installed voice host lifecycle support (#41902)
## What changed - Add `VoiceHost` to resolve the packaged voice helper, launch it with an allowlisted environment, perform the protocol handshake, and enforce bounded shutdown and process cleanup. - Preserve native executable path encoding in the pipe process APIs. - Add `third_party/voice/assemble_package.py` to create a fresh package copy containing a target-compatible helper and a provenance manifest with file hashes. ## Testing - Cover installed helper lifecycle, build matching, missing and symlinked helpers, non-UTF-8 package paths, environment filtering, package validation, target pairing, and failure cleanup. GitOrigin-RevId: f893074b36ae6bb9bcedc00fbe7af6bb72745f4c
This commit is contained in:
1 parent
f88ff940c0
commit
13bc770eaf
12 files changed
+493
-10
No files matched your search
@@ -1,11 +1,14 @@
|
||||
//! Exercise the real helper through installed paths and bounded process I/O.
|
||||
|
||||
use std::fs;
|
||||
use std::process::Stdio;
|
||||
use std::time::Duration;
|
||||
|
||||
use anyhow::Context;
|
||||
use anyhow::Result;
|
||||
use codex_install_context::InstallContext;
|
||||
use codex_realtime_webrtc::Message;
|
||||
use codex_realtime_webrtc::VoiceHost;
|
||||
use codex_realtime_webrtc::decode_frame;
|
||||
use codex_realtime_webrtc::encode_frame;
|
||||
use codex_utils_cargo_bin::cargo_bin;
|
||||
@@ -121,3 +124,81 @@ async fn rejects_invalid_input_without_echoing_it() -> Result<()> {
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
#[tokio::test]
|
||||
async fn installed_client_rejects_mixed_builds_and_missing_helper() -> Result<()> {
|
||||
let directory = tempfile::Builder::new()
|
||||
.prefix("voice package ")
|
||||
.tempdir()?;
|
||||
let bin = directory.path().join("bin");
|
||||
let helper_dir = directory.path().join("codex-resources/voice/bin");
|
||||
fs::create_dir_all(&bin)?;
|
||||
fs::create_dir_all(&helper_dir)?;
|
||||
fs::write(directory.path().join("codex-package.json"), "{}")?;
|
||||
let app = bin.join(if cfg!(windows) { "codex.exe" } else { "codex" });
|
||||
fs::write(&app, [])?;
|
||||
let source = cargo_bin("codex-voice-host")?;
|
||||
let helper = helper_dir.join(source.file_name().unwrap());
|
||||
fs::copy(&source, &helper)?;
|
||||
let package = InstallContext::from_exe(
|
||||
/*is_macos*/ cfg!(target_os = "macos"),
|
||||
Some(&app),
|
||||
/*method_override*/ None,
|
||||
)
|
||||
.package_layout
|
||||
.unwrap();
|
||||
VoiceHost::connect(&package, &build_commit().await?)
|
||||
.await?
|
||||
.close()
|
||||
.await?;
|
||||
assert!(VoiceHost::connect(&package, "wrong-build").await.is_err());
|
||||
// The same executable elsewhere in the package must not become a fallback.
|
||||
fs::rename(&helper, bin.join(source.file_name().unwrap()))?;
|
||||
assert!(
|
||||
VoiceHost::connect(&package, &build_commit().await?)
|
||||
.await
|
||||
.is_err()
|
||||
);
|
||||
#[cfg(unix)]
|
||||
{
|
||||
std::os::unix::fs::symlink(&source, &helper)?;
|
||||
assert!(
|
||||
VoiceHost::connect(&package, &build_commit().await?)
|
||||
.await
|
||||
.is_err()
|
||||
);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Linux permits raw-byte filenames; macOS filesystems reject this name themselves.
|
||||
#[cfg(target_os = "linux")]
|
||||
#[tokio::test]
|
||||
async fn installed_client_accepts_non_utf8_package_path() -> Result<()> {
|
||||
use std::ffi::OsString;
|
||||
use std::os::unix::ffi::OsStringExt;
|
||||
|
||||
let directory = tempfile::tempdir()?;
|
||||
let root = directory
|
||||
.path()
|
||||
.join(OsString::from_vec(b"voice-\xff".to_vec()));
|
||||
let bin = root.join("bin");
|
||||
let helper_dir = root.join("codex-resources/voice/bin");
|
||||
fs::create_dir_all(&bin)?;
|
||||
fs::create_dir_all(&helper_dir)?;
|
||||
fs::write(root.join("codex-package.json"), "{}")?;
|
||||
let app = bin.join("codex");
|
||||
fs::write(&app, [])?;
|
||||
let source = cargo_bin("codex-voice-host")?;
|
||||
fs::copy(&source, helper_dir.join(source.file_name().unwrap()))?;
|
||||
let package = InstallContext::from_exe(
|
||||
/*is_macos*/ cfg!(target_os = "macos"),
|
||||
Some(&app),
|
||||
/*method_override*/ None,
|
||||
)
|
||||
.package_layout
|
||||
.context("package layout")?;
|
||||
VoiceHost::connect(&package, &build_commit().await?)
|
||||
.await?
|
||||
.close()
|
||||
.await
|
||||
}
|
||||
Reference in new issue
Block a user