mirror of
https://github.com/openai/codex.git
synced 2026-11-13 22:47:20 +00:00
Initialize the packaged GStreamer runtime in the voice host (#42631)
## Why The voice helper previously supported only handshake and shutdown, without validating that its packaged native runtime could be initialized safely. ## What changed - Add an `initializeRuntime` protocol exchange that loads GStreamer and the required plugins from physical package paths without opening audio devices. - Restrict plugin discovery, registry access, and native library search paths, and keep loaded libraries alive until the helper exits. - Give initialization a dedicated deadline and terminate the owned helper when initialization is cancelled or fails. - Allow binary-only Rust targets to disable the default Bazel library target. ## Testing - Cover helper-only packages, cancellation, and environment filtering. - Add an ignored integration test for initialization from a relocated prepared runtime and rejection of duplicate initialization. GitOrigin-RevId: 8fff68fe26e52cb2e0722dc98fb5f124eddb0d4d
This commit is contained in:
1 parent
280ae8b9fc
commit
d979df154c
13 files changed
+386
-16
No files matched your search
@@ -151,6 +151,9 @@ async fn installed_client_rejects_mixed_builds_and_missing_helper() -> Result<()
|
||||
.close()
|
||||
.await?;
|
||||
assert!(VoiceHost::connect(&package, "wrong-build").await.is_err());
|
||||
// Helper-only installations still handshake, but cannot claim native readiness.
|
||||
let host = VoiceHost::connect(&package, &build_commit().await?).await?;
|
||||
assert!(host.initialize_runtime().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!(
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
//! Exercise native initialization with real prepared libraries in a relocated package.
|
||||
|
||||
use std::fs;
|
||||
use std::time::Duration;
|
||||
|
||||
use anyhow::Context;
|
||||
use anyhow::Result;
|
||||
use anyhow::ensure;
|
||||
use codex_install_context::InstallContext;
|
||||
use codex_realtime_webrtc::VoiceHost;
|
||||
use codex_utils_cargo_bin::cargo_bin;
|
||||
use tokio::process::Command;
|
||||
use tokio::time::timeout;
|
||||
|
||||
const DEADLINE: Duration = Duration::from_secs(/*secs*/ 10);
|
||||
|
||||
#[tokio::test]
|
||||
#[ignore = "requires CODEX_TEST_VOICE_RUNTIME containing real prepared native libraries"]
|
||||
async fn relocated_runtime_initializes_closes_and_rejects_duplicate_initialization() -> Result<()> {
|
||||
let source = std::env::var_os("CODEX_TEST_VOICE_RUNTIME")
|
||||
.context("set CODEX_TEST_VOICE_RUNTIME to a matching prepared runtime")?;
|
||||
let source = fs::canonicalize(source)?;
|
||||
ensure!(
|
||||
source.join("runtime.json").is_file(),
|
||||
"prepared runtime receipt missing"
|
||||
);
|
||||
let directory = tempfile::Builder::new()
|
||||
.prefix("voice native package ")
|
||||
.tempdir()?;
|
||||
let root = directory.path().join("staging");
|
||||
let runtime = root.join("codex-resources/voice");
|
||||
fs::create_dir_all(&runtime)?;
|
||||
let mut pending = vec![(source, runtime.clone())];
|
||||
while let Some((source, destination)) = pending.pop() {
|
||||
for entry in fs::read_dir(source)? {
|
||||
let entry = entry?;
|
||||
let target = destination.join(entry.file_name());
|
||||
let kind = entry.file_type()?;
|
||||
if kind.is_dir() {
|
||||
fs::create_dir(&target)?;
|
||||
pending.push((entry.path(), target));
|
||||
} else {
|
||||
ensure!(kind.is_file(), "runtime inputs must be physical files");
|
||||
fs::copy(entry.path(), target)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
let helper_source = cargo_bin("codex-voice-host")?;
|
||||
let name = helper_source.file_name().context("helper filename")?;
|
||||
fs::create_dir_all(runtime.join("bin"))?;
|
||||
fs::copy(&helper_source, runtime.join("bin").join(name))?;
|
||||
fs::create_dir(root.join("bin"))?;
|
||||
let app_name = if cfg!(windows) { "codex.exe" } else { "codex" };
|
||||
fs::write(root.join("bin").join(app_name), [])?;
|
||||
fs::write(root.join("codex-package.json"), "{}")?;
|
||||
let moved = directory.path().join("relocated package");
|
||||
fs::rename(root, &moved)?;
|
||||
let package = InstallContext::from_exe(
|
||||
/*is_macos*/ cfg!(target_os = "macos"),
|
||||
Some(&moved.join("bin").join(app_name)),
|
||||
/*method_override*/ None,
|
||||
)
|
||||
.package_layout
|
||||
.context("package layout")?;
|
||||
let output = timeout(
|
||||
DEADLINE,
|
||||
Command::new(&helper_source)
|
||||
.arg("--build-commit")
|
||||
.kill_on_drop(true)
|
||||
.output(),
|
||||
)
|
||||
.await??;
|
||||
ensure!(output.status.success(), "helper build identity failed");
|
||||
let build_commit = String::from_utf8(output.stdout)?.trim().to_owned();
|
||||
VoiceHost::connect(&package, &build_commit)
|
||||
.await?
|
||||
.initialize_runtime()
|
||||
.await?
|
||||
.close()
|
||||
.await?;
|
||||
|
||||
let host = VoiceHost::connect(&package, &build_commit)
|
||||
.await?
|
||||
.initialize_runtime()
|
||||
.await?;
|
||||
assert!(host.initialize_runtime().await.is_err());
|
||||
Ok(())
|
||||
}
|
||||
Reference in new issue
Block a user