Skip to content

Commit 4fe5793

Browse files
committed
feat: ensure memory commands pass through to agentmemory natively without bridging
This implements PR 7 of the agentmemory replacement spec. It routes the legacy UpdateMemories and DropMemories operations directly to the agentmemory adapter when configured. The interactive TUI slash commands and CLI debug commands (like `codex debug clear-memories`) will now gracefully flush the agentmemory instance instead of the native Codex database.
1 parent 0e0a554 commit 4fe5793

8 files changed

Lines changed: 91 additions & 0 deletions

File tree

codex-rs/cli/src/main.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1095,6 +1095,13 @@ async fn run_debug_clear_memories_command(
10951095
let config =
10961096
Config::load_with_cli_overrides_and_harness_overrides(cli_kv_overrides, overrides).await?;
10971097

1098+
if config.memories.backend == codex_core::config::types::MemoryBackend::Agentmemory {
1099+
let adapter = codex_core::agentmemory::AgentmemoryAdapter::new();
1100+
adapter.drop_memories().await.map_err(anyhow::Error::msg)?;
1101+
println!("Cleared Agentmemory store.");
1102+
return Ok(());
1103+
}
1104+
10981105
let state_path = state_db_path(config.sqlite_home.as_path());
10991106
let mut cleared_state_db = false;
11001107
if tokio::fs::try_exists(&state_path).await? {

codex-rs/core/src/agentmemory/mod.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,4 +44,16 @@ impl AgentmemoryAdapter {
4444
// The payload will typically be a hook request (e.g. `PostToolUseRequest`).
4545
// This is a stub for future PRs.
4646
}
47+
48+
/// Asynchronously triggers a memory refresh/update operation in `agentmemory`.
49+
pub async fn update_memories(&self) -> Result<(), String> {
50+
// TODO: Call agentmemory's sync/refresh endpoint.
51+
Ok(())
52+
}
53+
54+
/// Asynchronously drops/clears the memory store in `agentmemory`.
55+
pub async fn drop_memories(&self) -> Result<(), String> {
56+
// TODO: Call agentmemory's clear/drop endpoint.
57+
Ok(())
58+
}
4759
}

codex-rs/core/src/codex.rs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5064,6 +5064,29 @@ mod handlers {
50645064
}
50655065

50665066
pub async fn drop_memories(sess: &Arc<Session>, config: &Arc<Config>, sub_id: String) {
5067+
if config.memories.backend == crate::config::types::MemoryBackend::Agentmemory {
5068+
let adapter = crate::agentmemory::AgentmemoryAdapter::new();
5069+
if let Err(e) = adapter.drop_memories().await {
5070+
sess.send_event_raw(Event {
5071+
id: sub_id,
5072+
msg: EventMsg::Error(ErrorEvent {
5073+
message: format!("Agentmemory clear failed: {e}"),
5074+
codex_error_info: Some(CodexErrorInfo::Other),
5075+
}),
5076+
})
5077+
.await;
5078+
return;
5079+
}
5080+
sess.send_event_raw(Event {
5081+
id: sub_id,
5082+
msg: EventMsg::Warning(WarningEvent {
5083+
message: "Cleared Agentmemory contents.".to_string(),
5084+
}),
5085+
})
5086+
.await;
5087+
return;
5088+
}
5089+
50675090
let mut errors = Vec::new();
50685091

50695092
if let Some(state_db) = sess.services.state_db.as_deref() {
@@ -5112,6 +5135,29 @@ mod handlers {
51125135
state.session_configuration.session_source.clone()
51135136
};
51145137

5138+
if config.memories.backend == crate::config::types::MemoryBackend::Agentmemory {
5139+
let adapter = crate::agentmemory::AgentmemoryAdapter::new();
5140+
if let Err(e) = adapter.update_memories().await {
5141+
sess.send_event_raw(Event {
5142+
id: sub_id.clone(),
5143+
msg: EventMsg::Error(ErrorEvent {
5144+
message: format!("Agentmemory sync failed: {e}"),
5145+
codex_error_info: Some(CodexErrorInfo::Other),
5146+
}),
5147+
})
5148+
.await;
5149+
return;
5150+
}
5151+
sess.send_event_raw(Event {
5152+
id: sub_id.clone(),
5153+
msg: EventMsg::Warning(WarningEvent {
5154+
message: "Agentmemory sync triggered.".to_string(),
5155+
}),
5156+
})
5157+
.await;
5158+
return;
5159+
}
5160+
51155161
if config.memories.backend == crate::config::types::MemoryBackend::Native {
51165162
crate::memories::start_memories_startup_task(sess, Arc::clone(config), &session_source);
51175163
}

codex-rs/tui/src/bottom_pane/chat_composer.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,7 @@ pub(crate) struct ChatComposer {
409409
realtime_conversation_enabled: bool,
410410
audio_device_selection_enabled: bool,
411411
windows_degraded_sandbox_active: bool,
412+
agentmemory_enabled: bool,
412413
status_line_value: Option<Line<'static>>,
413414
status_line_enabled: bool,
414415
// Agent label injected into the footer's contextual row when multi-agent mode is active.
@@ -448,6 +449,7 @@ impl ChatComposer {
448449
realtime_conversation_enabled: self.realtime_conversation_enabled,
449450
audio_device_selection_enabled: self.audio_device_selection_enabled,
450451
allow_elevate_sandbox: self.windows_degraded_sandbox_active,
452+
agentmemory_enabled: self.agentmemory_enabled,
451453
}
452454
}
453455

@@ -533,6 +535,7 @@ impl ChatComposer {
533535
realtime_conversation_enabled: false,
534536
audio_device_selection_enabled: false,
535537
windows_degraded_sandbox_active: false,
538+
agentmemory_enabled: false,
536539
status_line_value: None,
537540
status_line_enabled: false,
538541
active_agent_label: None,
@@ -662,6 +665,10 @@ impl ChatComposer {
662665
pub fn set_windows_degraded_sandbox_active(&mut self, enabled: bool) {
663666
self.windows_degraded_sandbox_active = enabled;
664667
}
668+
669+
pub fn set_agentmemory_enabled(&mut self, enabled: bool) {
670+
self.agentmemory_enabled = enabled;
671+
}
665672
fn layout_areas(&self, area: Rect) -> [Rect; 4] {
666673
let footer_props = self.footer_props();
667674
let footer_hint_height = self
@@ -3500,6 +3507,7 @@ impl ChatComposer {
35003507
realtime_conversation_enabled,
35013508
audio_device_selection_enabled,
35023509
windows_degraded_sandbox_active: self.windows_degraded_sandbox_active,
3510+
agentmemory_enabled: self.agentmemory_enabled,
35033511
},
35043512
);
35053513
command_popup.on_composer_text_change(first_line.to_string());

codex-rs/tui/src/bottom_pane/command_popup.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ pub(crate) struct CommandPopupFlags {
4444
pub(crate) realtime_conversation_enabled: bool,
4545
pub(crate) audio_device_selection_enabled: bool,
4646
pub(crate) windows_degraded_sandbox_active: bool,
47+
pub(crate) agentmemory_enabled: bool,
4748
}
4849

4950
impl From<CommandPopupFlags> for slash_commands::BuiltinCommandFlags {
@@ -57,6 +58,7 @@ impl From<CommandPopupFlags> for slash_commands::BuiltinCommandFlags {
5758
realtime_conversation_enabled: value.realtime_conversation_enabled,
5859
audio_device_selection_enabled: value.audio_device_selection_enabled,
5960
allow_elevate_sandbox: value.windows_degraded_sandbox_active,
61+
agentmemory_enabled: value.agentmemory_enabled,
6062
}
6163
}
6264
}

codex-rs/tui/src/bottom_pane/mod.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,11 @@ impl BottomPane {
302302
self.request_redraw();
303303
}
304304

305+
pub fn set_agentmemory_enabled(&mut self, enabled: bool) {
306+
self.composer.set_agentmemory_enabled(enabled);
307+
self.request_redraw();
308+
}
309+
305310
pub fn set_collaboration_mode_indicator(
306311
&mut self,
307312
indicator: Option<CollaborationModeIndicator>,

codex-rs/tui/src/bottom_pane/slash_commands.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ pub(crate) struct BuiltinCommandFlags {
2020
pub(crate) realtime_conversation_enabled: bool,
2121
pub(crate) audio_device_selection_enabled: bool,
2222
pub(crate) allow_elevate_sandbox: bool,
23+
pub(crate) agentmemory_enabled: bool,
2324
}
2425

2526
/// Return the built-ins that should be visible/usable for the current input.
@@ -37,6 +38,7 @@ pub(crate) fn builtins_for_input(flags: BuiltinCommandFlags) -> Vec<(&'static st
3738
.filter(|(_, cmd)| flags.personality_command_enabled || *cmd != SlashCommand::Personality)
3839
.filter(|(_, cmd)| flags.realtime_conversation_enabled || *cmd != SlashCommand::Realtime)
3940
.filter(|(_, cmd)| flags.audio_device_selection_enabled || *cmd != SlashCommand::Settings)
41+
.filter(|(_, cmd)| !flags.agentmemory_enabled || !matches!(*cmd, SlashCommand::MemoryDrop | SlashCommand::MemoryUpdate))
4042
.collect()
4143
}
4244

codex-rs/tui/src/chatwidget.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3833,6 +3833,9 @@ impl ChatWidget {
38333833
widget.bottom_pane.set_voice_transcription_enabled(
38343834
widget.config.features.enabled(Feature::VoiceTranscription),
38353835
);
3836+
widget.bottom_pane.set_agentmemory_enabled(
3837+
widget.config.memories.backend == codex_core::config::types::MemoryBackend::Agentmemory
3838+
);
38363839
widget
38373840
.bottom_pane
38383841
.set_realtime_conversation_enabled(widget.realtime_conversation_enabled());
@@ -4037,6 +4040,9 @@ impl ChatWidget {
40374040
widget.bottom_pane.set_voice_transcription_enabled(
40384041
widget.config.features.enabled(Feature::VoiceTranscription),
40394042
);
4043+
widget.bottom_pane.set_agentmemory_enabled(
4044+
widget.config.memories.backend == codex_core::config::types::MemoryBackend::Agentmemory
4045+
);
40404046
widget
40414047
.bottom_pane
40424048
.set_realtime_conversation_enabled(widget.realtime_conversation_enabled());
@@ -4233,6 +4239,9 @@ impl ChatWidget {
42334239
widget.bottom_pane.set_voice_transcription_enabled(
42344240
widget.config.features.enabled(Feature::VoiceTranscription),
42354241
);
4242+
widget.bottom_pane.set_agentmemory_enabled(
4243+
widget.config.memories.backend == codex_core::config::types::MemoryBackend::Agentmemory
4244+
);
42364245
widget
42374246
.bottom_pane
42384247
.set_realtime_conversation_enabled(widget.realtime_conversation_enabled());

0 commit comments

Comments
 (0)