mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
5e92f4af12
See the readme
254 lines
8.1 KiB
Rust
254 lines
8.1 KiB
Rust
use super::ArtifactRuntimeError;
|
|
use super::ArtifactRuntimePlatform;
|
|
use super::InstalledArtifactRuntime;
|
|
use super::ReleaseManifest;
|
|
use codex_package_manager::ManagedPackage;
|
|
use codex_package_manager::PackageManager;
|
|
use codex_package_manager::PackageManagerConfig;
|
|
use codex_package_manager::PackageManagerError;
|
|
use codex_package_manager::PackageReleaseArchive;
|
|
use reqwest::Client;
|
|
use std::path::Path;
|
|
use std::path::PathBuf;
|
|
use url::Url;
|
|
|
|
/// Release tag prefix used for artifact runtime assets.
|
|
pub const DEFAULT_RELEASE_TAG_PREFIX: &str = "artifact-runtime-v";
|
|
|
|
/// Relative cache root for installed artifact runtimes under `codex_home`.
|
|
pub const DEFAULT_CACHE_ROOT_RELATIVE: &str = "packages/artifacts";
|
|
|
|
/// Base URL used by default when downloading runtime assets from GitHub releases.
|
|
pub const DEFAULT_RELEASE_BASE_URL: &str = "https://github.com/openai/codex/releases/download/";
|
|
|
|
/// Describes where a particular artifact runtime release can be downloaded from.
|
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
|
pub struct ArtifactRuntimeReleaseLocator {
|
|
base_url: Url,
|
|
runtime_version: String,
|
|
release_tag_prefix: String,
|
|
}
|
|
|
|
impl ArtifactRuntimeReleaseLocator {
|
|
/// Creates a locator for a runtime version under a release base URL.
|
|
pub fn new(base_url: Url, runtime_version: impl Into<String>) -> Self {
|
|
Self {
|
|
base_url,
|
|
runtime_version: runtime_version.into(),
|
|
release_tag_prefix: DEFAULT_RELEASE_TAG_PREFIX.to_string(),
|
|
}
|
|
}
|
|
|
|
/// Overrides the release-tag prefix used when constructing asset names.
|
|
pub fn with_tag_prefix(mut self, release_tag_prefix: impl Into<String>) -> Self {
|
|
self.release_tag_prefix = release_tag_prefix.into();
|
|
self
|
|
}
|
|
|
|
/// Returns the release asset base URL.
|
|
pub fn base_url(&self) -> &Url {
|
|
&self.base_url
|
|
}
|
|
|
|
/// Returns the expected runtime version.
|
|
pub fn runtime_version(&self) -> &str {
|
|
&self.runtime_version
|
|
}
|
|
|
|
/// Returns the full release tag for the runtime version.
|
|
pub fn release_tag(&self) -> String {
|
|
format!("{}{}", self.release_tag_prefix, self.runtime_version)
|
|
}
|
|
|
|
/// Returns the expected manifest filename for the release.
|
|
pub fn manifest_file_name(&self) -> String {
|
|
format!("{}-manifest.json", self.release_tag())
|
|
}
|
|
|
|
/// Returns the manifest URL for this runtime release.
|
|
pub fn manifest_url(&self) -> Result<Url, PackageManagerError> {
|
|
self.base_url
|
|
.join(&format!(
|
|
"{}/{}",
|
|
self.release_tag(),
|
|
self.manifest_file_name()
|
|
))
|
|
.map_err(PackageManagerError::InvalidBaseUrl)
|
|
}
|
|
|
|
/// Returns the default GitHub-release locator for a runtime version.
|
|
pub fn default(runtime_version: impl Into<String>) -> Self {
|
|
Self::new(
|
|
match Url::parse(DEFAULT_RELEASE_BASE_URL) {
|
|
Ok(url) => url,
|
|
Err(error) => {
|
|
panic!("hard-coded artifact runtime release base URL must be valid: {error}")
|
|
}
|
|
},
|
|
runtime_version,
|
|
)
|
|
}
|
|
}
|
|
|
|
/// Configuration for resolving artifact runtimes under a Codex home directory.
|
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
|
pub struct ArtifactRuntimeManagerConfig {
|
|
package_manager: PackageManagerConfig<ArtifactRuntimePackage>,
|
|
release: ArtifactRuntimeReleaseLocator,
|
|
}
|
|
|
|
impl ArtifactRuntimeManagerConfig {
|
|
/// Creates a runtime-manager config from a Codex home and explicit release locator.
|
|
pub fn new(codex_home: PathBuf, release: ArtifactRuntimeReleaseLocator) -> Self {
|
|
Self {
|
|
package_manager: PackageManagerConfig::new(
|
|
codex_home,
|
|
ArtifactRuntimePackage::new(release.clone()),
|
|
),
|
|
release,
|
|
}
|
|
}
|
|
|
|
/// Creates a runtime-manager config that downloads from the default GitHub release location.
|
|
pub fn with_default_release(codex_home: PathBuf, runtime_version: impl Into<String>) -> Self {
|
|
Self::new(
|
|
codex_home,
|
|
ArtifactRuntimeReleaseLocator::default(runtime_version),
|
|
)
|
|
}
|
|
|
|
/// Overrides the runtime cache root.
|
|
pub fn with_cache_root(mut self, cache_root: PathBuf) -> Self {
|
|
self.package_manager = self.package_manager.with_cache_root(cache_root);
|
|
self
|
|
}
|
|
|
|
/// Returns the runtime cache root.
|
|
pub fn cache_root(&self) -> PathBuf {
|
|
self.package_manager.cache_root()
|
|
}
|
|
|
|
/// Returns the release locator used by this config.
|
|
pub fn release(&self) -> &ArtifactRuntimeReleaseLocator {
|
|
&self.release
|
|
}
|
|
}
|
|
|
|
/// Package-manager-backed artifact runtime resolver and installer.
|
|
#[derive(Clone, Debug)]
|
|
pub struct ArtifactRuntimeManager {
|
|
package_manager: PackageManager<ArtifactRuntimePackage>,
|
|
config: ArtifactRuntimeManagerConfig,
|
|
}
|
|
|
|
impl ArtifactRuntimeManager {
|
|
/// Creates a runtime manager using the default `reqwest` client.
|
|
pub fn new(config: ArtifactRuntimeManagerConfig) -> Self {
|
|
let package_manager = PackageManager::new(config.package_manager.clone());
|
|
Self {
|
|
package_manager,
|
|
config,
|
|
}
|
|
}
|
|
|
|
/// Creates a runtime manager with a caller-provided HTTP client.
|
|
pub fn with_client(config: ArtifactRuntimeManagerConfig, client: Client) -> Self {
|
|
let package_manager = PackageManager::with_client(config.package_manager.clone(), client);
|
|
Self {
|
|
package_manager,
|
|
config,
|
|
}
|
|
}
|
|
|
|
/// Returns the manager configuration.
|
|
pub fn config(&self) -> &ArtifactRuntimeManagerConfig {
|
|
&self.config
|
|
}
|
|
|
|
/// Returns the installed runtime if it is already present and valid.
|
|
pub async fn resolve_cached(
|
|
&self,
|
|
) -> Result<Option<InstalledArtifactRuntime>, ArtifactRuntimeError> {
|
|
self.package_manager.resolve_cached().await
|
|
}
|
|
|
|
/// Returns the installed runtime, downloading and caching it if necessary.
|
|
pub async fn ensure_installed(&self) -> Result<InstalledArtifactRuntime, ArtifactRuntimeError> {
|
|
self.package_manager.ensure_installed().await
|
|
}
|
|
}
|
|
|
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
|
struct ArtifactRuntimePackage {
|
|
release: ArtifactRuntimeReleaseLocator,
|
|
}
|
|
|
|
impl ArtifactRuntimePackage {
|
|
fn new(release: ArtifactRuntimeReleaseLocator) -> Self {
|
|
Self { release }
|
|
}
|
|
}
|
|
|
|
impl ManagedPackage for ArtifactRuntimePackage {
|
|
type Error = ArtifactRuntimeError;
|
|
type Installed = InstalledArtifactRuntime;
|
|
type ReleaseManifest = ReleaseManifest;
|
|
|
|
fn default_cache_root_relative(&self) -> &str {
|
|
DEFAULT_CACHE_ROOT_RELATIVE
|
|
}
|
|
|
|
fn version(&self) -> &str {
|
|
self.release.runtime_version()
|
|
}
|
|
|
|
fn manifest_url(&self) -> Result<Url, PackageManagerError> {
|
|
self.release.manifest_url()
|
|
}
|
|
|
|
fn archive_url(&self, archive: &PackageReleaseArchive) -> Result<Url, PackageManagerError> {
|
|
self.release
|
|
.base_url()
|
|
.join(&format!(
|
|
"{}/{}",
|
|
self.release.release_tag(),
|
|
archive.archive
|
|
))
|
|
.map_err(PackageManagerError::InvalidBaseUrl)
|
|
}
|
|
|
|
fn release_version<'a>(&self, manifest: &'a Self::ReleaseManifest) -> &'a str {
|
|
&manifest.runtime_version
|
|
}
|
|
|
|
fn platform_archive(
|
|
&self,
|
|
manifest: &Self::ReleaseManifest,
|
|
platform: ArtifactRuntimePlatform,
|
|
) -> Result<PackageReleaseArchive, Self::Error> {
|
|
manifest
|
|
.platforms
|
|
.get(platform.as_str())
|
|
.cloned()
|
|
.ok_or_else(|| {
|
|
PackageManagerError::MissingPlatform(platform.as_str().to_string()).into()
|
|
})
|
|
}
|
|
|
|
fn install_dir(&self, cache_root: &Path, platform: ArtifactRuntimePlatform) -> PathBuf {
|
|
cache_root.join(self.version()).join(platform.as_str())
|
|
}
|
|
|
|
fn installed_version<'a>(&self, package: &'a Self::Installed) -> &'a str {
|
|
package.runtime_version()
|
|
}
|
|
|
|
fn load_installed(
|
|
&self,
|
|
root_dir: PathBuf,
|
|
platform: ArtifactRuntimePlatform,
|
|
) -> Result<Self::Installed, Self::Error> {
|
|
InstalledArtifactRuntime::load(root_dir, platform)
|
|
}
|
|
}
|