Skip to content

Commit 19d75e3

Browse files
committed
chore: make model optional
1 parent d0dd47b commit 19d75e3

6 files changed

Lines changed: 45 additions & 14 deletions

File tree

cmd/desktop/frontend/src/i18n/en.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -87,9 +87,9 @@ export default {
8787
modelPlaceholder: 'e.g., claude-sonnet-4-5-20250929',
8888
modelHelp: 'Optional: Override the model specified in requests',
8989
modelHelpClaude: 'Optional: Override the model specified in requests',
90-
modelHelpOpenAI: 'Required: Specify the OpenAI model to use',
91-
modelHelpOpenAI2: 'Required: Specify the OpenAI model (Responses API)',
92-
modelHelpGemini: 'Required: Specify the Gemini model to use',
90+
modelHelpOpenAI: 'Specify the OpenAI model to use',
91+
modelHelpOpenAI2: 'Specify the OpenAI model (Responses API)',
92+
modelHelpGemini: 'Specify the Gemini model to use',
9393
remark: 'Remark',
9494
remarkHelp: 'Optional: Add a remark for this endpoint',
9595
cancel: 'Cancel',

cmd/desktop/frontend/src/i18n/zh-CN.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -87,9 +87,9 @@ export default {
8787
modelPlaceholder: '例如:claude-sonnet-4-5-20250929',
8888
modelHelp: '可选:覆盖请求中指定的模型',
8989
modelHelpClaude: '可选:覆盖请求中指定的模型',
90-
modelHelpOpenAI: '必填:指定要使用的 OpenAI 模型',
91-
modelHelpOpenAI2: '必填:指定 OpenAI 模型(Responses API)',
92-
modelHelpGemini: '必填:指定要使用的 Gemini 模型',
90+
modelHelpOpenAI: '指定要使用的 OpenAI 模型',
91+
modelHelpOpenAI2: '指定 OpenAI 模型(Responses API)',
92+
modelHelpGemini: '指定要使用的 Gemini 模型',
9393
remark: '备注',
9494
remarkHelp: '可选:为此端点添加备注说明',
9595
cancel: '取消',

cmd/desktop/frontend/src/modules/modal.js

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -259,10 +259,7 @@ export async function saveEndpoint() {
259259
return;
260260
}
261261

262-
if (transformer !== 'claude' && !model) {
263-
showError(t('modal.modelRequired').replace('{transformer}', transformer));
264-
return;
265-
}
262+
// Model is optional: only override when provided.
266263

267264
// Check for duplicate endpoint name
268265
const configStr = await window.go.main.App.GetConfig();
@@ -322,20 +319,17 @@ export function handleTransformerChange() {
322319
// Clear fetched models when transformer changes
323320
clearFetchedModels();
324321

322+
modelRequired.style.display = 'none';
325323
if (transformer === 'claude') {
326-
modelRequired.style.display = 'none';
327324
modelInput.placeholder = 'e.g., claude-3-5-sonnet-20241022';
328325
modelHelpText.textContent = t('modal.modelHelpClaude');
329326
} else if (transformer === 'openai') {
330-
modelRequired.style.display = 'inline';
331327
modelInput.placeholder = 'e.g., gpt-4-turbo';
332328
modelHelpText.textContent = t('modal.modelHelpOpenAI');
333329
} else if (transformer === 'openai2') {
334-
modelRequired.style.display = 'inline';
335330
modelInput.placeholder = 'e.g., gpt-4.1';
336331
modelHelpText.textContent = t('modal.modelHelpOpenAI2');
337332
} else if (transformer === 'gemini') {
338-
modelRequired.style.display = 'inline';
339333
modelInput.placeholder = 'e.g., gemini-pro';
340334
modelHelpText.textContent = t('modal.modelHelpGemini');
341335
}

internal/proxy/proxy.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -444,6 +444,9 @@ func (p *Proxy) handleProxy(w http.ResponseWriter, r *http.Request) {
444444
cleanedBody = transformedBody
445445
}
446446
transformedBody = cleanedBody
447+
if config.NormalizeAuthMode(endpoint.AuthMode) == config.AuthModeCodexTokenPool {
448+
transformedBody = overrideModelInPayload(transformedBody, endpoint.Model)
449+
}
447450

448451
var thinkingEnabled bool
449452
if strings.Contains(transformerName, "openai") {

internal/proxy/request.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,27 @@ func ensureCodexResponsesPayload(payload []byte) []byte {
328328
return updated
329329
}
330330

331+
func overrideModelInPayload(payload []byte, model string) []byte {
332+
if strings.TrimSpace(model) == "" {
333+
return payload
334+
}
335+
trimmed := strings.TrimSpace(string(payload))
336+
if trimmed == "" || strings.HasPrefix(trimmed, "[") {
337+
return payload
338+
}
339+
340+
var body map[string]interface{}
341+
if err := json.Unmarshal(payload, &body); err != nil {
342+
return payload
343+
}
344+
body["model"] = model
345+
updated, err := json.Marshal(body)
346+
if err != nil {
347+
return payload
348+
}
349+
return updated
350+
}
351+
331352
// sendRequest sends the HTTP request and returns the response
332353
func sendRequest(ctx context.Context, proxyReq *http.Request, httpClient *http.Client, cfg *config.Config) (*http.Response, error) {
333354
proxyReq = proxyReq.WithContext(ctx)

internal/proxy/request_test.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,19 @@ func TestNormalizeTargetPathForBaseURLOnCodexBackend(t *testing.T) {
5555
}
5656
}
5757

58+
func TestOverrideModelInPayload(t *testing.T) {
59+
raw := []byte(`{"model":"gpt-5.3-codex","stream":true}`)
60+
out := overrideModelInPayload(raw, "gpt-5.2-codex")
61+
62+
var payload map[string]interface{}
63+
if err := json.Unmarshal(out, &payload); err != nil {
64+
t.Fatalf("unmarshal failed: %v", err)
65+
}
66+
if payload["model"] != "gpt-5.2-codex" {
67+
t.Fatalf("expected model override to gpt-5.2-codex, got %#v", payload["model"])
68+
}
69+
}
70+
5871
func TestShouldHandleAsStreamingResponseForCodexWithoutContentType(t *testing.T) {
5972
endpoint := config.Endpoint{
6073
Name: "TokenPool",

0 commit comments

Comments
 (0)