diff --git a/relaykit/relayconvert/internal/oai_chat/to_oai_responses_req.go b/relaykit/relayconvert/internal/oai_chat/to_oai_responses_req.go index 1c1795ac..104dfe8b 100644 --- a/relaykit/relayconvert/internal/oai_chat/to_oai_responses_req.go +++ b/relaykit/relayconvert/internal/oai_chat/to_oai_responses_req.go @@ -380,6 +380,14 @@ func ChatCompletionsRequestToResponsesRequest(req *dto.GeneralOpenAIRequest) (*d presencePenaltyRaw, _ = kitutil.Marshal(req.PresencePenalty) } + var promptCacheKeyRaw json.RawMessage + if req.PromptCacheKey != "" { + promptCacheKeyRaw, err = kitutil.Marshal(req.PromptCacheKey) + if err != nil { + return nil, fmt.Errorf("marshal prompt_cache_key: %w", err) + } + } + out := &dto.OpenAIResponsesRequest{ Model: req.Model, Input: inputRaw, @@ -396,6 +404,7 @@ func ChatCompletionsRequestToResponsesRequest(req *dto.GeneralOpenAIRequest) (*d ParallelToolCalls: parallelToolCallsRaw, Store: req.Store, Metadata: req.Metadata, + PromptCacheKey: promptCacheKeyRaw, EnableThinking: req.EnableThinking, ThinkingBudget: req.ThinkingBudget, } diff --git a/relaykit/relayconvert/internal/oai_chat/to_oai_responses_req_test.go b/relaykit/relayconvert/internal/oai_chat/to_oai_responses_req_test.go index 23711dae..915a9946 100644 --- a/relaykit/relayconvert/internal/oai_chat/to_oai_responses_req_test.go +++ b/relaykit/relayconvert/internal/oai_chat/to_oai_responses_req_test.go @@ -39,6 +39,38 @@ func TestChatCompletionsRequestToResponsesRequestInstructionsAndTools(t *testing assert.Equal(t, "function_call_output", gjson.GetBytes(got.Input, "3.type").String()) } +func TestChatCompletionsRequestToResponsesRequestPreservesPromptCacheKey(t *testing.T) { + t.Run("present", func(t *testing.T) { + key := "session-\"quoted\"\\path\n世界" + got, err := ChatCompletionsRequestToResponsesRequest(&dto.GeneralOpenAIRequest{ + Model: "gpt-test", + Messages: []dto.Message{{Role: "user", Content: "hello"}}, + PromptCacheKey: key, + }) + require.NoError(t, err) + + keyRaw, err := kitutil.Marshal(key) + require.NoError(t, err) + assert.Equal(t, keyRaw, []byte(got.PromptCacheKey)) + + encoded, err := kitutil.Marshal(got) + require.NoError(t, err) + assert.Equal(t, key, gjson.GetBytes(encoded, "prompt_cache_key").String()) + }) + + t.Run("absent", func(t *testing.T) { + got, err := ChatCompletionsRequestToResponsesRequest(&dto.GeneralOpenAIRequest{ + Model: "gpt-test", + Messages: []dto.Message{{Role: "user", Content: "hello"}}, + }) + require.NoError(t, err) + + encoded, err := kitutil.Marshal(got) + require.NoError(t, err) + assert.False(t, gjson.GetBytes(encoded, "prompt_cache_key").Exists()) + }) +} + func TestChatCompletionsRequestToResponsesRequestPreservesQwenThinkingBudget(t *testing.T) { tests := []struct { name string