mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
12e8764a9c
## Why Standalone image generation returns image bytes to the model, but the model also needs the host artifact path to reference the generated file in follow-up work. ## What changed - Append the default saved-image path hint alongside the generated image tool output. - Reuse the existing core image-generation hint text. - Pass the thread ID and Codex home directory needed to compute the artifact path. - Add app-server and extension coverage for the model-visible hint. ## Validation - `just fmt` - `just bazel-lock-check` - `just test -p codex-app-server standalone_image_generation_returns_saved_path_hint_to_model`
100 lines
3.3 KiB
Rust
100 lines
3.3 KiB
Rust
use std::sync::Arc;
|
|
|
|
use codex_core::config::Config;
|
|
use codex_extension_api::ConfigContributor;
|
|
use codex_extension_api::ExtensionData;
|
|
use codex_extension_api::ExtensionRegistryBuilder;
|
|
use codex_extension_api::ThreadLifecycleContributor;
|
|
use codex_extension_api::ThreadStartInput;
|
|
use codex_extension_api::ToolCall;
|
|
use codex_extension_api::ToolContributor;
|
|
use codex_extension_api::ToolExecutor;
|
|
use codex_features::Feature;
|
|
use codex_login::AuthManager;
|
|
use codex_model_provider::create_model_provider;
|
|
use codex_model_provider_info::ModelProviderInfo;
|
|
use codex_utils_absolute_path::AbsolutePathBuf;
|
|
|
|
use crate::backend::CodexImagesBackend;
|
|
use crate::tool::ImageGenerationTool;
|
|
|
|
#[derive(Clone)]
|
|
struct ImageGenerationExtension {
|
|
auth_manager: Arc<AuthManager>,
|
|
}
|
|
|
|
#[derive(Clone)]
|
|
struct ImageGenerationExtensionConfig {
|
|
enabled: bool,
|
|
provider: ModelProviderInfo,
|
|
codex_home: AbsolutePathBuf,
|
|
}
|
|
|
|
impl From<&Config> for ImageGenerationExtensionConfig {
|
|
/// Resolves whether standalone image generation should be available for a thread.
|
|
fn from(config: &Config) -> Self {
|
|
Self {
|
|
enabled: config.features.enabled(Feature::ImageGenExt)
|
|
&& config.model_provider.is_openai(),
|
|
provider: config.model_provider.clone(),
|
|
codex_home: config.codex_home.clone(),
|
|
}
|
|
}
|
|
}
|
|
|
|
#[async_trait::async_trait]
|
|
impl ThreadLifecycleContributor<Config> for ImageGenerationExtension {
|
|
/// Seeds image-generation availability when a thread begins.
|
|
async fn on_thread_start(&self, input: ThreadStartInput<'_, Config>) {
|
|
input
|
|
.thread_store
|
|
.insert(ImageGenerationExtensionConfig::from(input.config));
|
|
}
|
|
}
|
|
|
|
impl ConfigContributor<Config> for ImageGenerationExtension {
|
|
/// Refreshes image-generation availability after thread configuration changes.
|
|
fn on_config_changed(
|
|
&self,
|
|
_session_store: &ExtensionData,
|
|
thread_store: &ExtensionData,
|
|
_previous_config: &Config,
|
|
new_config: &Config,
|
|
) {
|
|
thread_store.insert(ImageGenerationExtensionConfig::from(new_config));
|
|
}
|
|
}
|
|
|
|
impl ToolContributor for ImageGenerationExtension {
|
|
/// Creates the image-generation tool exposed by this installed extension.
|
|
fn tools(
|
|
&self,
|
|
_session_store: &ExtensionData,
|
|
thread_store: &ExtensionData,
|
|
) -> Vec<Arc<dyn ToolExecutor<ToolCall>>> {
|
|
let Some(config) = thread_store.get::<ImageGenerationExtensionConfig>() else {
|
|
return Vec::new();
|
|
};
|
|
if !config.enabled || !self.auth_manager.current_auth_uses_codex_backend() {
|
|
return Vec::new();
|
|
}
|
|
|
|
vec![Arc::new(ImageGenerationTool::new(
|
|
CodexImagesBackend::new(create_model_provider(
|
|
config.provider.clone(),
|
|
Some(self.auth_manager.clone()),
|
|
)),
|
|
config.codex_home.clone(),
|
|
thread_store.level_id().to_string(),
|
|
))]
|
|
}
|
|
}
|
|
|
|
/// Installs the feature-gated standalone image-generation extension contributors.
|
|
pub fn install(registry: &mut ExtensionRegistryBuilder<Config>, auth_manager: Arc<AuthManager>) {
|
|
let extension = Arc::new(ImageGenerationExtension { auth_manager });
|
|
registry.thread_lifecycle_contributor(extension.clone());
|
|
registry.config_contributor(extension.clone());
|
|
registry.tool_contributor(extension);
|
|
}
|