Skip to content

Commit 64caac9

Browse files
ericjutacodex
andcommitted
test(agentmemory): restore glob parity coverage
Co-authored-by: Codex <noreply@openai.com>
1 parent d5ee914 commit 64caac9

1 file changed

Lines changed: 106 additions & 0 deletions

File tree

codex-rs/core/tests/suite/agentmemory_hook_parity.rs

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use anyhow::Result;
22
use codex_config::types::MemoryBackend;
33
use codex_features::Feature;
4+
use codex_models_manager::bundled_models_response;
45
use core_test_support::responses::ev_apply_patch_function_call;
56
use core_test_support::responses::ev_assistant_message;
67
use core_test_support::responses::ev_completed;
@@ -256,3 +257,108 @@ async fn pre_tool_enrichment_skips_non_matching_tools() -> Result<()> {
256257

257258
Ok(())
258259
}
260+
261+
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
262+
#[serial(agentmemory_env)]
263+
async fn glob_lane_enrichment_and_post_tool_capture_use_native_contract() -> Result<()> {
264+
let model_server = start_mock_server().await;
265+
let agentmemory_server = MockServer::start().await;
266+
mount_agentmemory_runtime(&agentmemory_server).await;
267+
Mock::given(method("POST"))
268+
.and(path("/agentmemory/enrich"))
269+
.respond_with(ResponseTemplate::new(200).set_body_json(json!({
270+
"context": "<agentmemory-context>glob lane note</agentmemory-context>",
271+
})))
272+
.expect(1)
273+
.mount(&agentmemory_server)
274+
.await;
275+
276+
let mut builder = test_codex().with_config({
277+
let agentmemory_base_url = agentmemory_server.uri();
278+
move |config| {
279+
config.memories.backend = MemoryBackend::Agentmemory;
280+
config.memories.agentmemory.base_url = agentmemory_base_url;
281+
config.memories.agentmemory.inject_context = true;
282+
let mut model_catalog = bundled_models_response()
283+
.unwrap_or_else(|err| panic!("bundled models.json should parse: {err}"));
284+
let model = model_catalog
285+
.models
286+
.iter_mut()
287+
.find(|model| model.slug == "gpt-5.3-codex")
288+
.expect("gpt-5.3-codex exists in bundled models.json");
289+
model
290+
.experimental_supported_tools
291+
.push("list_dir".to_string());
292+
config.model_catalog = Some(model_catalog);
293+
config
294+
.features
295+
.disable(Feature::MemoryTool)
296+
.expect("test config should allow feature update");
297+
}
298+
});
299+
let test = builder.build(&model_server).await?;
300+
std::fs::write(test.config.cwd.join("glob_lane.txt"), "harbor note")?;
301+
let call_id = "agentmemory-list-dir";
302+
let args = json!({
303+
"dir_path": test.config.cwd.display().to_string(),
304+
"offset": 1,
305+
"limit": 5,
306+
"depth": 1,
307+
});
308+
let responses = mount_sse_sequence(
309+
&model_server,
310+
vec![
311+
sse(vec![
312+
ev_response_created("resp-1"),
313+
ev_function_call(call_id, "list_dir", &serde_json::to_string(&args)?),
314+
ev_completed("resp-1"),
315+
]),
316+
sse(vec![
317+
ev_response_created("resp-2"),
318+
ev_assistant_message("msg-1", "listed"),
319+
ev_completed("resp-2"),
320+
]),
321+
],
322+
)
323+
.await;
324+
325+
test.submit_turn("list the directory").await?;
326+
test.codex.shutdown_and_wait().await?;
327+
328+
let requests = responses.requests();
329+
assert_eq!(requests.len(), 2);
330+
let agentmemory_requests = agentmemory_server
331+
.received_requests()
332+
.await
333+
.unwrap_or_default();
334+
let agentmemory_paths = agentmemory_requests
335+
.iter()
336+
.map(|request| request.url.path().to_string())
337+
.collect::<Vec<_>>();
338+
let observe_bodies = agentmemory_requests
339+
.iter()
340+
.filter(|request| request.url.path() == "/agentmemory/observe")
341+
.map(|request| String::from_utf8_lossy(&request.body).into_owned())
342+
.collect::<Vec<_>>();
343+
assert!(
344+
requests[1].body_contains_text("glob lane note"),
345+
"glob lane enrichment should inject context into the follow-up model turn: body={}; paths={agentmemory_paths:?}; observe={observe_bodies:?}",
346+
requests[1].body_json(),
347+
);
348+
let post_tool_use = agentmemory_requests
349+
.into_iter()
350+
.filter(|request| request.url.path() == "/agentmemory/observe")
351+
.map(|request| {
352+
serde_json::from_slice::<serde_json::Value>(&request.body)
353+
.expect("agentmemory observe body should be valid json")
354+
})
355+
.find(|payload| {
356+
payload["hookType"] == "post_tool_use" && payload["data"]["tool_name"] == "Glob"
357+
})
358+
.expect("list_dir should emit glob post_tool_use observe payload");
359+
assert_eq!(post_tool_use["source"], "codex-native");
360+
assert_eq!(post_tool_use["payload_version"], "1");
361+
assert_eq!(post_tool_use["persistence_class"], "persistent");
362+
363+
Ok(())
364+
}

0 commit comments

Comments
 (0)