Files
codex/codex-rs/ext/memories/src/extension.rs
T
jif-oaiandGitHub cccde930ce Move memory prompt injection to app-server extension (#22841)
## Why

Memory prompt injection should be owned by the extension path that
app-server composes at runtime, not by an inlined special case inside
`codex-core`. This keeps `codex-core` focused on session orchestration
while allowing the memories extension to own its app-server prompt
behavior.

## What Changed

- Registers `codex-memories-extension` in the app-server extension
registry.
- Moves the memory developer-instruction injection out of
`core/src/session/mod.rs` and into the memories extension prompt
contributor.
- Adds config-change handling so the extension keeps its per-thread
memory settings in sync after startup.
- Leaves memories read/retrieval tools unregistered for now so this PR
only changes prompt injection.
- Removes the stale `cargo-shear` ignore now that app-server depends on
the extension crate.

## Validation

Not run locally; validation is left to CI.
2026-05-15 16:19:34 +02:00

107 lines
3.4 KiB
Rust

use std::sync::Arc;
use codex_core::config::Config;
use codex_extension_api::ConfigContributor;
use codex_extension_api::ContextContributor;
use codex_extension_api::ExtensionData;
use codex_extension_api::ExtensionRegistryBuilder;
use codex_extension_api::PromptFragment;
use codex_extension_api::ThreadLifecycleContributor;
use codex_extension_api::ThreadStartInput;
use codex_extension_api::ToolContributor;
use codex_features::Feature;
use codex_memories_read::build_memory_tool_developer_instructions;
use codex_utils_absolute_path::AbsolutePathBuf;
use crate::local::LocalMemoriesBackend;
use crate::tools;
/// Contributes Codex memory read-path prompt context and memory read tools.
#[derive(Clone, Copy, Debug, Default)]
pub(crate) struct MemoriesExtension;
#[derive(Clone, Debug)]
pub(crate) struct MemoriesExtensionConfig {
pub(crate) enabled: bool,
pub(crate) codex_home: AbsolutePathBuf,
}
impl MemoriesExtensionConfig {
fn from_config(config: &Config) -> Self {
Self {
enabled: config.features.enabled(Feature::MemoryTool) && config.memories.use_memories,
codex_home: config.codex_home.clone(),
}
}
}
impl ContextContributor for MemoriesExtension {
fn contribute<'a>(
&'a self,
_session_store: &'a ExtensionData,
thread_store: &'a ExtensionData,
) -> std::pin::Pin<Box<dyn std::future::Future<Output = Vec<PromptFragment>> + Send + 'a>> {
Box::pin(async move {
let Some(config) = thread_store.get::<MemoriesExtensionConfig>() else {
return Vec::new();
};
if !config.enabled {
return Vec::new();
}
build_memory_tool_developer_instructions(&config.codex_home)
.await
.map(PromptFragment::developer_policy)
.into_iter()
.collect()
})
}
}
impl ThreadLifecycleContributor<Config> for MemoriesExtension {
fn on_thread_start(&self, input: ThreadStartInput<'_, Config>) {
input
.thread_store
.insert(MemoriesExtensionConfig::from_config(input.config));
}
}
impl ConfigContributor<Config> for MemoriesExtension {
fn on_config_changed(
&self,
_session_store: &ExtensionData,
thread_store: &ExtensionData,
_previous_config: &Config,
new_config: &Config,
) {
thread_store.insert(MemoriesExtensionConfig::from_config(new_config));
}
}
impl ToolContributor for MemoriesExtension {
fn tools(
&self,
_session_store: &ExtensionData,
thread_store: &ExtensionData,
) -> Vec<Arc<dyn codex_extension_api::ToolExecutor<codex_extension_api::ToolCall>>> {
let Some(config) = thread_store.get::<MemoriesExtensionConfig>() else {
return Vec::new();
};
if !config.enabled {
return Vec::new();
}
tools::memory_tools(LocalMemoriesBackend::from_codex_home(&config.codex_home))
}
}
/// Installs the memories extension contributors into the extension registry.
pub fn install(registry: &mut ExtensionRegistryBuilder<Config>) {
let extension = Arc::new(MemoriesExtension);
registry.thread_lifecycle_contributor(extension.clone());
registry.config_contributor(extension.clone());
registry.prompt_contributor(extension);
// Keep the read/retrieval tools out of app-server until that rollout is intentional.
// registry.tool_contributor(extension);
}