@@ -10,6 +10,7 @@ import (
1010
1111 openai "github.com/openai/openai-go/v3"
1212
13+ "neo-code/internal/provider"
1314 "neo-code/internal/provider/openaicompat/chatcompletions"
1415)
1516
@@ -54,6 +55,12 @@ func TestResolveChatEndpointPathByMode(t *testing.T) {
5455 mode : "responses" ,
5556 want : "/responses" ,
5657 },
58+ {
59+ name : "fills chat completions path for explicit completions mode" ,
60+ path : "" ,
61+ mode : "chat_completions" ,
62+ want : "/chat/completions" ,
63+ },
5764 }
5865
5966 for _ , tt := range tests {
@@ -65,6 +72,116 @@ func TestResolveChatEndpointPathByMode(t *testing.T) {
6572 }
6673}
6774
75+ func TestResolveChatEndpointUsesExplicitModeFallbackAndCustomPath (t * testing.T ) {
76+ t .Parallel ()
77+
78+ tests := []struct {
79+ name string
80+ cfg provider.RuntimeConfig
81+ want string
82+ }{
83+ {
84+ name : "explicit responses mode falls back to responses path" ,
85+ cfg : provider.RuntimeConfig {
86+ BaseURL : "https://api.example.com/v1" ,
87+ ChatAPIMode : provider .ChatAPIModeResponses ,
88+ ChatEndpointPath : "" ,
89+ },
90+ want : "https://api.example.com/v1/responses" ,
91+ },
92+ {
93+ name : "explicit completions mode falls back to completions path" ,
94+ cfg : provider.RuntimeConfig {
95+ BaseURL : "https://api.example.com/v1" ,
96+ ChatAPIMode : provider .ChatAPIModeChatCompletions ,
97+ ChatEndpointPath : "" ,
98+ },
99+ want : "https://api.example.com/v1/chat/completions" ,
100+ },
101+ {
102+ name : "custom path stays unchanged when explicit mode is set" ,
103+ cfg : provider.RuntimeConfig {
104+ BaseURL : "https://api.example.com/v1" ,
105+ ChatAPIMode : provider .ChatAPIModeChatCompletions ,
106+ ChatEndpointPath : "/v1/text/chatcompletion_v2" ,
107+ },
108+ want : "https://api.example.com/v1/v1/text/chatcompletion_v2" ,
109+ },
110+ {
111+ name : "slash keeps direct base url mode" ,
112+ cfg : provider.RuntimeConfig {
113+ BaseURL : "https://api.example.com/v1" ,
114+ ChatAPIMode : provider .ChatAPIModeResponses ,
115+ ChatEndpointPath : "/" ,
116+ },
117+ want : "https://api.example.com/v1" ,
118+ },
119+ }
120+
121+ for _ , tt := range tests {
122+ t .Run (tt .name , func (t * testing.T ) {
123+ got , err := resolveChatEndpoint (tt .cfg )
124+ if err != nil {
125+ t .Fatalf ("resolveChatEndpoint() error = %v" , err )
126+ }
127+ if got != tt .want {
128+ t .Fatalf ("resolveChatEndpoint() = %q, want %q" , got , tt .want )
129+ }
130+ })
131+ }
132+ }
133+
134+ func TestShouldUseCompatibleChatCompletionsEndpoint (t * testing.T ) {
135+ t .Parallel ()
136+
137+ tests := []struct {
138+ name string
139+ cfg provider.RuntimeConfig
140+ want bool
141+ }{
142+ {
143+ name : "default completions endpoint uses sdk path" ,
144+ cfg : provider.RuntimeConfig {
145+ BaseURL : "https://api.example.com/v1" ,
146+ ChatEndpointPath : "" ,
147+ },
148+ want : false ,
149+ },
150+ {
151+ name : "explicit default completions endpoint uses sdk path" ,
152+ cfg : provider.RuntimeConfig {
153+ BaseURL : "https://api.example.com/v1" ,
154+ ChatEndpointPath : "/chat/completions" ,
155+ },
156+ want : false ,
157+ },
158+ {
159+ name : "custom completions endpoint uses compatible path" ,
160+ cfg : provider.RuntimeConfig {
161+ BaseURL : "https://api.example.com" ,
162+ ChatEndpointPath : "/v1/text/chatcompletion_v2" ,
163+ },
164+ want : true ,
165+ },
166+ {
167+ name : "direct base url mode uses compatible path" ,
168+ cfg : provider.RuntimeConfig {
169+ BaseURL : "https://api.example.com/v1/text/chatcompletion_v2" ,
170+ ChatEndpointPath : "/" ,
171+ },
172+ want : true ,
173+ },
174+ }
175+
176+ for _ , tt := range tests {
177+ t .Run (tt .name , func (t * testing.T ) {
178+ if got := shouldUseCompatibleChatCompletionsEndpoint (tt .cfg ); got != tt .want {
179+ t .Fatalf ("shouldUseCompatibleChatCompletionsEndpoint() = %v, want %v" , got , tt .want )
180+ }
181+ })
182+ }
183+ }
184+
68185func TestConvertToSDKMessageMapsToolRoleAndAssistantToolCalls (t * testing.T ) {
69186 t .Parallel ()
70187
0 commit comments