@@ -60,3 +60,37 @@ func TestExpandPreviousResponseLeavesBodyUntouchedOnCacheMiss(t *testing.T) {
6060 t .Fatalf ("body mutated on cache miss; got=%s want=%s" , got , body )
6161 }
6262}
63+
64+ func TestCacheCompletedResponseStripsItemIDsAndSkipsReasoning (t * testing.T ) {
65+ resetResponseCacheForTest ()
66+
67+ cacheCompletedResponse (
68+ []byte (`[{"type":"message","id":"msg_input","role":"user","content":"call a tool"}]` ),
69+ []byte (`{"type":"response.completed","response":{"id":"resp_strip","output":[` +
70+ `{"type":"reasoning","id":"rs_0609","encrypted_content":"opaque"},` +
71+ `{"type":"message","id":"msg_output","role":"assistant","content":[{"type":"output_text","text":"thinking"}]},` +
72+ `{"type":"function_call","id":"fc_123","call_id":"call_abc","name":"lookup","arguments":"{}"}` +
73+ `]}}` ),
74+ )
75+
76+ cached := getResponseCache ("resp_strip" )
77+ if len (cached ) != 2 {
78+ t .Fatalf ("cached items = %d, want input message + function_call only (reasoning/message output should be skipped)" , len (cached ))
79+ }
80+ if typ := gjson .GetBytes (cached [0 ], "type" ).String (); typ != "message" {
81+ t .Fatalf ("cached[0].type = %q, want message" , typ )
82+ }
83+ if id := gjson .GetBytes (cached [0 ], "id" ); id .Exists () {
84+ t .Fatalf ("cached input id should be stripped, got %s" , id .Raw )
85+ }
86+ if typ := gjson .GetBytes (cached [1 ], "type" ).String (); typ != "function_call" {
87+ t .Fatalf ("cached[1].type = %q, want function_call" , typ )
88+ }
89+ if id := gjson .GetBytes (cached [1 ], "id" ); id .Exists () {
90+ t .Fatalf ("cached function_call id should be stripped, got %s" , id .Raw )
91+ }
92+ // call_id 必须保留——它是续链所依赖的关键字段
93+ if callID := gjson .GetBytes (cached [1 ], "call_id" ).String (); callID != "call_abc" {
94+ t .Fatalf ("cached function_call call_id = %q, want call_abc (must be preserved)" , callID )
95+ }
96+ }
0 commit comments