mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
## Why The memories extension already has dedicated `list`, `read`, `search`, and `add_ad_hoc_note` tools, but app-server registration was still disabled. The memories app collaborator needs an explicit config switch so those native extension tools can be exposed intentionally, without making ordinary memory prompt usage automatically register the dedicated tool surface. ## What changed - Added `[memories].dedicated_tools`, defaulting to `false`, to `MemoriesToml` / `MemoriesConfig`. - Regenerated `core/config.schema.json` for the new setting. - Registered the memories extension as a `ToolContributor`, while keeping tool contribution gated on both memories being enabled and `dedicated_tools = true`. - Added tests for the disabled default, the enabled dedicated-tools path, and installer registration. ## Verification - `just test -p codex-config -p codex-memories-extension`
124 lines
3.8 KiB
Rust
124 lines
3.8 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_otel::MetricsClient;
|
|
use codex_utils_absolute_path::AbsolutePathBuf;
|
|
|
|
use crate::local::LocalMemoriesBackend;
|
|
use crate::prompts::build_memory_tool_developer_instructions;
|
|
use crate::tools;
|
|
|
|
/// Contributes Codex memory read-path prompt context and memory read tools.
|
|
#[derive(Clone, Default)]
|
|
pub(crate) struct MemoriesExtension {
|
|
metrics_client: Option<MetricsClient>,
|
|
}
|
|
|
|
impl MemoriesExtension {
|
|
fn new(metrics_client: Option<MetricsClient>) -> Self {
|
|
Self { metrics_client }
|
|
}
|
|
}
|
|
|
|
#[derive(Clone, Debug)]
|
|
pub(crate) struct MemoriesExtensionConfig {
|
|
pub(crate) enabled: bool,
|
|
pub(crate) dedicated_tools: 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,
|
|
dedicated_tools: config.memories.dedicated_tools,
|
|
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()
|
|
})
|
|
}
|
|
}
|
|
|
|
#[async_trait::async_trait]
|
|
impl ThreadLifecycleContributor<Config> for MemoriesExtension {
|
|
async 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 || !config.dedicated_tools {
|
|
return Vec::new();
|
|
}
|
|
|
|
tools::memory_tools(
|
|
LocalMemoriesBackend::from_codex_home(&config.codex_home),
|
|
self.metrics_client.clone(),
|
|
)
|
|
}
|
|
}
|
|
|
|
/// Installs the memories extension contributors into the extension registry.
|
|
pub fn install(
|
|
registry: &mut ExtensionRegistryBuilder<Config>,
|
|
metrics_client: Option<MetricsClient>,
|
|
) {
|
|
let extension = Arc::new(MemoriesExtension::new(metrics_client));
|
|
registry.thread_lifecycle_contributor(extension.clone());
|
|
registry.config_contributor(extension.clone());
|
|
registry.prompt_contributor(extension.clone());
|
|
registry.tool_contributor(extension);
|
|
}
|