@@ -324,10 +324,17 @@ describe("openai transport stream", () => {
324324 output ,
325325 { push : vi . fn ( ) } ,
326326 model ,
327- { sessionId : "session-123" } ,
327+ { authProfileId : "openai-codex:oauth" , sessionId : "session-123" } ,
328328 ) ;
329329
330- const thinkingBlock = output . content [ 0 ] as { thinkingSignature ?: string } ;
330+ const expectedReplayMetadata = testing . buildOpenAIResponsesReasoningReplayMetadata ( model , {
331+ authProfileId : "openai-codex:oauth" ,
332+ sessionId : "session-123" ,
333+ } ) ;
334+ const thinkingBlock = output . content [ 0 ] as {
335+ thinkingSignature ?: string ;
336+ openclawReasoningReplay ?: unknown ;
337+ } ;
331338 const replayItem = JSON . parse ( thinkingBlock . thinkingSignature ?? "{}" ) as Record <
332339 string ,
333340 unknown
@@ -336,10 +343,9 @@ describe("openai transport stream", () => {
336343 type : "reasoning" ,
337344 id : "rs_123" ,
338345 encrypted_content : "ciphertext" ,
339- __openclaw_replay : testing . buildOpenAIResponsesReasoningReplayMetadata ( model , {
340- sessionId : "session-123" ,
341- } ) ,
342346 } ) ;
347+ expect ( replayItem ) . not . toHaveProperty ( "__openclaw_replay" ) ;
348+ expect ( thinkingBlock . openclawReasoningReplay ) . toEqual ( expectedReplayMetadata ) ;
343349 } ) ;
344350
345351 it ( "clamps Responses cached prompt usage at zero" , async ( ) => {
@@ -2308,16 +2314,17 @@ describe("openai transport stream", () => {
23082314 {
23092315 type : "thinking" ,
23102316 thinking : "Need a tool." ,
2311- thinkingSignature : JSON . stringify (
2312- testing . tagOpenAIResponsesReasoningReplayItem (
2313- {
2314- type : "reasoning" ,
2315- id : "rs_prior" ,
2316- encrypted_content : "ciphertext" ,
2317- } ,
2318- model ,
2319- { sessionId : "session-123" } ,
2320- ) ,
2317+ thinkingSignature : JSON . stringify ( {
2318+ type : "reasoning" ,
2319+ id : "rs_prior" ,
2320+ encrypted_content : "ciphertext" ,
2321+ } ) ,
2322+ openclawReasoningReplay : testing . buildOpenAIResponsesReasoningReplayMetadata (
2323+ model ,
2324+ {
2325+ authProfileId : "openai-codex:oauth" ,
2326+ sessionId : "session-123" ,
2327+ } ,
23212328 ) ,
23222329 } ,
23232330 {
@@ -2340,7 +2347,7 @@ describe("openai transport stream", () => {
23402347 ] ,
23412348 tools : [ ] ,
23422349 } as never ,
2343- { sessionId : "session-123" } ,
2350+ { authProfileId : "openai-codex:oauth" , sessionId : "session-123" } ,
23442351 ) as {
23452352 input ?: Array < {
23462353 type ?: string ;
@@ -2390,6 +2397,152 @@ describe("openai transport stream", () => {
23902397 maxTokens : 8192 ,
23912398 } satisfies Model < "openai-codex-responses" > ;
23922399
2400+ const params = buildOpenAIResponsesParams (
2401+ model ,
2402+ {
2403+ systemPrompt : "system" ,
2404+ messages : [
2405+ {
2406+ role : "assistant" ,
2407+ api : "openai-codex-responses" ,
2408+ provider : "openai-codex" ,
2409+ model : "gpt-5.4" ,
2410+ usage : {
2411+ input : 0 ,
2412+ output : 0 ,
2413+ cacheRead : 0 ,
2414+ cacheWrite : 0 ,
2415+ totalTokens : 0 ,
2416+ cost : { input : 0 , output : 0 , cacheRead : 0 , cacheWrite : 0 , total : 0 } ,
2417+ } ,
2418+ stopReason : "toolUse" ,
2419+ timestamp : 1 ,
2420+ content : [
2421+ {
2422+ type : "thinking" ,
2423+ thinking : "Need a tool." ,
2424+ thinkingSignature : JSON . stringify ( {
2425+ type : "reasoning" ,
2426+ id : "rs_prior" ,
2427+ encrypted_content : "ciphertext" ,
2428+ } ) ,
2429+ openclawReasoningReplay : testing . buildOpenAIResponsesReasoningReplayMetadata (
2430+ model ,
2431+ {
2432+ authProfileId : "openai-codex:oauth" ,
2433+ sessionId : "different-session" ,
2434+ } ,
2435+ ) ,
2436+ } ,
2437+ ] ,
2438+ } ,
2439+ ] ,
2440+ tools : [ ] ,
2441+ } as never ,
2442+ { authProfileId : "openai-codex:oauth" , sessionId : "session-123" } ,
2443+ ) as {
2444+ input ?: Array < {
2445+ type ?: string ;
2446+ id ?: string ;
2447+ encrypted_content ?: string ;
2448+ } > ;
2449+ } ;
2450+
2451+ const reasoningItem = params . input ?. find ( ( item ) => item . type === "reasoning" ) ;
2452+ expectRecordFields ( reasoningItem , {
2453+ type : "reasoning" ,
2454+ id : "rs_prior" ,
2455+ } ) ;
2456+ expect ( reasoningItem ) . not . toHaveProperty ( "encrypted_content" ) ;
2457+ } ) ;
2458+
2459+ it ( "strips encrypted reasoning replay when the auth profile provenance changes" , ( ) => {
2460+ const model = {
2461+ id : "gpt-5.4" ,
2462+ name : "GPT-5.4" ,
2463+ api : "openai-codex-responses" ,
2464+ provider : "openai-codex" ,
2465+ baseUrl : "https://proxy.example.com/v1" ,
2466+ reasoning : true ,
2467+ input : [ "text" ] ,
2468+ cost : { input : 0 , output : 0 , cacheRead : 0 , cacheWrite : 0 } ,
2469+ contextWindow : 200000 ,
2470+ maxTokens : 8192 ,
2471+ } satisfies Model < "openai-codex-responses" > ;
2472+
2473+ const params = buildOpenAIResponsesParams (
2474+ model ,
2475+ {
2476+ systemPrompt : "system" ,
2477+ messages : [
2478+ {
2479+ role : "assistant" ,
2480+ api : "openai-codex-responses" ,
2481+ provider : "openai-codex" ,
2482+ model : "gpt-5.4" ,
2483+ usage : {
2484+ input : 0 ,
2485+ output : 0 ,
2486+ cacheRead : 0 ,
2487+ cacheWrite : 0 ,
2488+ totalTokens : 0 ,
2489+ cost : { input : 0 , output : 0 , cacheRead : 0 , cacheWrite : 0 , total : 0 } ,
2490+ } ,
2491+ stopReason : "toolUse" ,
2492+ timestamp : 1 ,
2493+ content : [
2494+ {
2495+ type : "thinking" ,
2496+ thinking : "Need a tool." ,
2497+ thinkingSignature : JSON . stringify ( {
2498+ type : "reasoning" ,
2499+ id : "rs_prior" ,
2500+ encrypted_content : "ciphertext" ,
2501+ } ) ,
2502+ openclawReasoningReplay : testing . buildOpenAIResponsesReasoningReplayMetadata (
2503+ model ,
2504+ {
2505+ authProfileId : "openai-codex:old-oauth" ,
2506+ sessionId : "session-123" ,
2507+ } ,
2508+ ) ,
2509+ } ,
2510+ ] ,
2511+ } ,
2512+ ] ,
2513+ tools : [ ] ,
2514+ } as never ,
2515+ { authProfileId : "openai-codex:new-oauth" , sessionId : "session-123" } ,
2516+ ) as {
2517+ input ?: Array < {
2518+ type ?: string ;
2519+ id ?: string ;
2520+ encrypted_content ?: string ;
2521+ } > ;
2522+ } ;
2523+
2524+ const reasoningItem = params . input ?. find ( ( item ) => item . type === "reasoning" ) ;
2525+ expectRecordFields ( reasoningItem , {
2526+ type : "reasoning" ,
2527+ id : "rs_prior" ,
2528+ } ) ;
2529+ expect ( reasoningItem ) . not . toHaveProperty ( "encrypted_content" ) ;
2530+ } ) ;
2531+
2532+ it ( "keeps embedded replay provenance as a compatibility fallback" , ( ) => {
2533+ const model = {
2534+ id : "gpt-5.4" ,
2535+ name : "GPT-5.4" ,
2536+ api : "openai-codex-responses" ,
2537+ provider : "openai-codex" ,
2538+ baseUrl : "https://proxy.example.com/v1" ,
2539+ reasoning : true ,
2540+ input : [ "text" ] ,
2541+ cost : { input : 0 , output : 0 , cacheRead : 0 , cacheWrite : 0 } ,
2542+ contextWindow : 200000 ,
2543+ maxTokens : 8192 ,
2544+ } satisfies Model < "openai-codex-responses" > ;
2545+
23932546 const params = buildOpenAIResponsesParams (
23942547 model ,
23952548 {
@@ -2422,7 +2575,10 @@ describe("openai transport stream", () => {
24222575 encrypted_content : "ciphertext" ,
24232576 } ,
24242577 model ,
2425- { sessionId : "different-session" } ,
2578+ {
2579+ authProfileId : "openai-codex:oauth" ,
2580+ sessionId : "session-123" ,
2581+ } ,
24262582 ) ,
24272583 ) ,
24282584 } ,
@@ -2431,7 +2587,7 @@ describe("openai transport stream", () => {
24312587 ] ,
24322588 tools : [ ] ,
24332589 } as never ,
2434- { sessionId : "session-123" } ,
2590+ { authProfileId : "openai-codex:oauth" , sessionId : "session-123" } ,
24352591 ) as {
24362592 input ?: Array < {
24372593 type ?: string ;
@@ -2444,8 +2600,9 @@ describe("openai transport stream", () => {
24442600 expectRecordFields ( reasoningItem , {
24452601 type : "reasoning" ,
24462602 id : "rs_prior" ,
2603+ encrypted_content : "ciphertext" ,
24472604 } ) ;
2448- expect ( reasoningItem ) . not . toHaveProperty ( "encrypted_content " ) ;
2605+ expect ( reasoningItem ) . not . toHaveProperty ( "__openclaw_replay " ) ;
24492606 } ) ;
24502607
24512608 it ( "strips nested encrypted reasoning content from retry payloads without changing ids" , ( ) => {
0 commit comments