@@ -41,22 +41,34 @@ impl AgentmemoryAdapter {
4141 /// uses hybrid search semantics rather than loading large static artifacts.
4242 pub async fn build_startup_developer_instructions (
4343 & self ,
44- _codex_home : & Path ,
45- _token_budget : usize ,
44+ codex_home : & Path ,
45+ token_budget : usize ,
4646 ) -> Option < String > {
4747 let client = get_client ( ) ;
48- let url = format ! ( "{}/agentmemory/profile" , self . api_base( ) ) ;
49- let profile_result = client. get ( & url) . send ( ) . await ;
48+ let url = format ! ( "{}/agentmemory/context" , self . api_base( ) ) ;
49+ let project = std:: env:: current_dir ( )
50+ . unwrap_or_else ( |_| codex_home. to_path_buf ( ) )
51+ . to_string_lossy ( )
52+ . into_owned ( ) ;
53+
54+ let request_body = json ! ( {
55+ "sessionId" : "startup" , // We don't have a session ID at this exact moment easily accessible, but "startup" excludes it safely.
56+ "project" : project,
57+ "budget" : token_budget
58+ } ) ;
59+
60+ let context_result = client. post ( & url) . json ( & request_body) . send ( ) . await ;
5061
5162 let mut instructions = "Use the `AgentMemory` tools to search and retrieve relevant memory.\n \
5263 Your context is bounded; use targeted queries to expand details as needed.". to_string ( ) ;
5364
54- if let Ok ( res) = profile_result {
55- if let Ok ( text) = res. text ( ) . await {
56- if !text. is_empty ( ) {
57- instructions. push_str ( "\n \n <agentmemory_profile>\n " ) ;
58- instructions. push_str ( & text) ;
59- instructions. push_str ( "\n </agentmemory_profile>" ) ;
65+ if let Ok ( res) = context_result {
66+ if let Ok ( json_res) = res. json :: < serde_json:: Value > ( ) . await {
67+ if let Some ( context_str) = json_res. get ( "context" ) . and_then ( |v| v. as_str ( ) ) {
68+ if !context_str. is_empty ( ) {
69+ instructions. push_str ( "\n \n " ) ;
70+ instructions. push_str ( context_str) ;
71+ }
6072 }
6173 }
6274 }
@@ -68,12 +80,15 @@ impl AgentmemoryAdapter {
6880 /// expected by the `agentmemory` REST API. This provides a central, malleable
6981 /// place to adjust mapping logic in the future without touching the hooks engine.
7082 fn format_claude_parity_payload ( & self , event_name : & str , payload : serde_json:: Value ) -> serde_json:: Value {
71- // TODO: As agentmemory evolves, perform explicit property mapping here.
72- // For example, mapping Codex `turn_id` to Claude `message_id` or extracting specific nested fields.
83+ let session_id = payload. get ( "session_id" ) . and_then ( |v| v. as_str ( ) ) . unwrap_or ( "unknown" ) . to_string ( ) ;
84+
85+ let timestamp = chrono:: Utc :: now ( ) . to_rfc3339 ( ) ;
7386
7487 json ! ( {
75- "event" : event_name,
76- "payload" : payload,
88+ "sessionId" : session_id,
89+ "hookType" : event_name,
90+ "timestamp" : timestamp,
91+ "data" : payload,
7792 } )
7893 }
7994
@@ -118,4 +133,26 @@ impl AgentmemoryAdapter {
118133 }
119134 Ok ( ( ) )
120135 }
121- }
136+ }
137+ #[ cfg( test) ]
138+ mod tests {
139+ use super :: * ;
140+ use serde_json:: json;
141+
142+ #[ test]
143+ fn test_format_claude_parity_payload ( ) {
144+ let adapter = AgentmemoryAdapter :: new ( ) ;
145+ let raw_payload = json ! ( {
146+ "session_id" : "1234" ,
147+ "turn_id" : "turn-5" ,
148+ "command" : "echo hello"
149+ } ) ;
150+
151+ let formatted = adapter. format_claude_parity_payload ( "PreToolUse" , raw_payload. clone ( ) ) ;
152+
153+ assert_eq ! ( formatted[ "sessionId" ] , "1234" ) ;
154+ assert_eq ! ( formatted[ "hookType" ] , "PreToolUse" ) ;
155+ assert ! ( formatted. get( "timestamp" ) . is_some( ) ) ;
156+ assert_eq ! ( formatted[ "data" ] , raw_payload) ;
157+ }
158+ }
0 commit comments