diff --git a/codex-rs/Cargo.lock b/codex-rs/Cargo.lock index 61ffd3a01..2c50f268f 100644 --- a/codex-rs/Cargo.lock +++ b/codex-rs/Cargo.lock @@ -2596,6 +2596,18 @@ dependencies = [ "urlencoding", ] +[[package]] +name = "codex-connectors-extension" +version = "0.0.0" +dependencies = [ + "codex-connectors", + "codex-core-plugins", + "codex-plugin", + "codex-utils-path-uri", + "serde_json", + "thiserror 2.0.18", +] + [[package]] name = "codex-context-fragments" version = "0.0.0" diff --git a/codex-rs/Cargo.toml b/codex-rs/Cargo.toml index abf5e0411..ef17cb9ce 100644 --- a/codex-rs/Cargo.toml +++ b/codex-rs/Cargo.toml @@ -48,6 +48,7 @@ members = [ "exec-server", "execpolicy", "execpolicy-legacy", + "ext/connectors", "ext/extension-api", "ext/goal", "ext/guardian", diff --git a/codex-rs/ext/connectors/BUILD.bazel b/codex-rs/ext/connectors/BUILD.bazel new file mode 100644 index 000000000..304349b8a --- /dev/null +++ b/codex-rs/ext/connectors/BUILD.bazel @@ -0,0 +1,6 @@ +load("//:defs.bzl", "codex_rust_crate") + +codex_rust_crate( + name = "connectors", + crate_name = "codex_connectors_extension", +) diff --git a/codex-rs/ext/connectors/Cargo.toml b/codex-rs/ext/connectors/Cargo.toml new file mode 100644 index 000000000..1103ae4e2 --- /dev/null +++ b/codex-rs/ext/connectors/Cargo.toml @@ -0,0 +1,22 @@ +[package] +edition.workspace = true +license.workspace = true +name = "codex-connectors-extension" +version.workspace = true + +[lib] +name = "codex_connectors_extension" +path = "src/lib.rs" +doctest = false +test = false + +[lints] +workspace = true + +[dependencies] +codex-connectors = { workspace = true } +codex-core-plugins = { workspace = true } +codex-plugin = { workspace = true } +codex-utils-path-uri = { workspace = true } +serde_json = { workspace = true } +thiserror = { workspace = true } diff --git a/codex-rs/ext/connectors/src/executor_plugin.rs b/codex-rs/ext/connectors/src/executor_plugin.rs new file mode 100644 index 000000000..c27ae3ac6 --- /dev/null +++ b/codex-rs/ext/connectors/src/executor_plugin.rs @@ -0,0 +1,64 @@ +use codex_connectors::parse_plugin_app_config; +use codex_core_plugins::ResolvedExecutorPlugin; +use codex_plugin::AppDeclaration; +use codex_plugin::PluginResourceLocator; +use codex_utils_path_uri::PathUri; +use std::io; +use thiserror::Error; + +/// Loads connector declarations from a resolved plugin through its owning executor. +#[derive(Clone, Copy, Debug, Default)] +pub struct ExecutorPluginConnectorProvider; + +/// Failure to load connector declarations from an executor plugin. +#[derive(Debug, Error)] +pub enum ExecutorPluginConnectorProviderError { + #[error("failed to read app config for selected plugin `{plugin_id}` at `{path}`: {source}")] + ReadConfig { + plugin_id: String, + path: PathUri, + #[source] + source: io::Error, + }, + #[error("failed to parse app config for selected plugin `{plugin_id}` at `{path}`: {source}")] + ParseConfig { + plugin_id: String, + path: PathUri, + #[source] + source: serde_json::Error, + }, +} + +impl ExecutorPluginConnectorProvider { + /// Returns the connector declarations contributed by `plugin`. + pub async fn load( + &self, + plugin: &ResolvedExecutorPlugin, + ) -> Result, ExecutorPluginConnectorProviderError> { + let resolved_plugin = plugin.plugin(); + let plugin_id = resolved_plugin.selected_root_id(); + let Some(PluginResourceLocator::Environment { + path: config_path, .. + }) = resolved_plugin.manifest().paths.apps.as_ref() + else { + return Ok(Vec::new()); + }; + let contents = plugin + .file_system() + .read_file_text(config_path, /*sandbox*/ None) + .await + .map_err(|source| ExecutorPluginConnectorProviderError::ReadConfig { + plugin_id: plugin_id.to_string(), + path: config_path.clone(), + source, + })?; + + parse_plugin_app_config(&contents).map_err(|source| { + ExecutorPluginConnectorProviderError::ParseConfig { + plugin_id: plugin_id.to_string(), + path: config_path.clone(), + source, + } + }) + } +} diff --git a/codex-rs/ext/connectors/src/lib.rs b/codex-rs/ext/connectors/src/lib.rs new file mode 100644 index 000000000..f60e5f916 --- /dev/null +++ b/codex-rs/ext/connectors/src/lib.rs @@ -0,0 +1,6 @@ +//! Executor-backed connector declaration loading. + +mod executor_plugin; + +pub use executor_plugin::ExecutorPluginConnectorProvider; +pub use executor_plugin::ExecutorPluginConnectorProviderError;