From 7dcddef91f47f958f57e6ef0b4ffbc511345f842 Mon Sep 17 00:00:00 2001 From: CJACK Date: Tue, 17 Feb 2026 13:36:19 +0800 Subject: [PATCH] feat: Update Claude model names and IDs across configuration, documentation, and tests, including the default model and thinking delta logic. --- API.en.md | 18 +++++++++--------- API.md | 18 +++++++++--------- README.MD | 6 +++--- README.en.md | 6 +++--- internal/adapter/claude/handler_stream_test.go | 10 +++++----- internal/config/models.go | 10 +++++++--- internal/testsuite/edge_cases.go | 2 +- internal/testsuite/runner.go | 6 +++--- internal/util/messages.go | 2 +- internal/util/messages_test.go | 2 +- 10 files changed, 42 insertions(+), 38 deletions(-) diff --git a/API.en.md b/API.en.md index 1c16cb3..13e39b4 100644 --- a/API.en.md +++ b/API.en.md @@ -246,9 +246,9 @@ No auth required. { "object": "list", "data": [ - {"id": "claude-sonnet-4-20250514", "object": "model", "created": 1715635200, "owned_by": "anthropic"}, - {"id": "claude-sonnet-4-20250514-fast", "object": "model", "created": 1715635200, "owned_by": "anthropic"}, - {"id": "claude-sonnet-4-20250514-slow", "object": "model", "created": 1715635200, "owned_by": "anthropic"} + {"id": "claude-sonnet-4-5", "object": "model", "created": 1715635200, "owned_by": "anthropic"}, + {"id": "claude-3-5-haiku-latest", "object": "model", "created": 1715635200, "owned_by": "anthropic"}, + {"id": "claude-opus-4-6", "object": "model", "created": 1715635200, "owned_by": "anthropic"} ] } ``` @@ -267,7 +267,7 @@ anthropic-version: 2023-06-01 | Field | Type | Required | Notes | | --- | --- | --- | --- | -| `model` | string | ✅ | `claude-sonnet-4-20250514` / `-fast` / `-slow` | +| `model` | string | ✅ | `claude-sonnet-4-5` / `claude-opus-4-6` / `claude-3-5-haiku-latest` | | `messages` | array | ✅ | Claude-style messages | | `max_tokens` | number | ❌ | Not strictly enforced by upstream bridge | | `stream` | boolean | ❌ | Default `false` | @@ -281,7 +281,7 @@ anthropic-version: 2023-06-01 "id": "msg_1738400000000000000", "type": "message", "role": "assistant", - "model": "claude-sonnet-4-20250514", + "model": "claude-sonnet-4-5", "content": [ {"type": "text", "text": "response"} ], @@ -325,7 +325,7 @@ data: {"type":"message_stop"} **Notes**: -- Thinking-enabled models (`-slow`) stream `thinking_delta` +- Models whose names contain `opus` / `reasoner` / `slow` stream `thinking_delta` - `signature_delta` is not emitted (DeepSeek does not provide verifiable thinking signatures) - In `tools` mode, the stream avoids leaking raw tool JSON and does not force `input_json_delta` @@ -335,7 +335,7 @@ data: {"type":"message_stop"} ```json { - "model": "claude-sonnet-4-20250514", + "model": "claude-sonnet-4-5", "messages": [ {"role": "user", "content": "Hello"} ] @@ -754,7 +754,7 @@ curl http://localhost:5001/anthropic/v1/messages \ -H "Content-Type: application/json" \ -H "anthropic-version: 2023-06-01" \ -d '{ - "model": "claude-sonnet-4-20250514", + "model": "claude-sonnet-4-5", "max_tokens": 1024, "messages": [{"role": "user", "content": "Hello"}] }' @@ -768,7 +768,7 @@ curl http://localhost:5001/anthropic/v1/messages \ -H "Content-Type: application/json" \ -H "anthropic-version: 2023-06-01" \ -d '{ - "model": "claude-sonnet-4-20250514-slow", + "model": "claude-opus-4-6", "max_tokens": 1024, "messages": [{"role": "user", "content": "Explain relativity"}], "stream": true diff --git a/API.md b/API.md index d173031..95ecbfe 100644 --- a/API.md +++ b/API.md @@ -246,9 +246,9 @@ data: [DONE] { "object": "list", "data": [ - {"id": "claude-sonnet-4-20250514", "object": "model", "created": 1715635200, "owned_by": "anthropic"}, - {"id": "claude-sonnet-4-20250514-fast", "object": "model", "created": 1715635200, "owned_by": "anthropic"}, - {"id": "claude-sonnet-4-20250514-slow", "object": "model", "created": 1715635200, "owned_by": "anthropic"} + {"id": "claude-sonnet-4-5", "object": "model", "created": 1715635200, "owned_by": "anthropic"}, + {"id": "claude-3-5-haiku-latest", "object": "model", "created": 1715635200, "owned_by": "anthropic"}, + {"id": "claude-opus-4-6", "object": "model", "created": 1715635200, "owned_by": "anthropic"} ] } ``` @@ -267,7 +267,7 @@ anthropic-version: 2023-06-01 | 字段 | 类型 | 必填 | 说明 | | --- | --- | --- | --- | -| `model` | string | ✅ | `claude-sonnet-4-20250514` / `-fast` / `-slow` | +| `model` | string | ✅ | `claude-sonnet-4-5` / `claude-opus-4-6` / `claude-3-5-haiku-latest` | | `messages` | array | ✅ | Claude 风格消息数组 | | `max_tokens` | number | ❌ | 当前实现不会硬性截断上游输出 | | `stream` | boolean | ❌ | 默认 `false` | @@ -281,7 +281,7 @@ anthropic-version: 2023-06-01 "id": "msg_1738400000000000000", "type": "message", "role": "assistant", - "model": "claude-sonnet-4-20250514", + "model": "claude-sonnet-4-5", "content": [ {"type": "text", "text": "回复内容"} ], @@ -325,7 +325,7 @@ data: {"type":"message_stop"} **说明**: -- 思维模型(`-slow`)会输出 `thinking_delta` +- 名称中包含 `opus` / `reasoner` / `slow` 的模型会输出 `thinking_delta` - 不会输出 `signature_delta`(上游 DeepSeek 未提供可验证签名) - `tools` 场景优先避免泄露原始工具 JSON,不强制发送 `input_json_delta` @@ -335,7 +335,7 @@ data: {"type":"message_stop"} ```json { - "model": "claude-sonnet-4-20250514", + "model": "claude-sonnet-4-5", "messages": [ {"role": "user", "content": "你好"} ] @@ -754,7 +754,7 @@ curl http://localhost:5001/anthropic/v1/messages \ -H "Content-Type: application/json" \ -H "anthropic-version: 2023-06-01" \ -d '{ - "model": "claude-sonnet-4-20250514", + "model": "claude-sonnet-4-5", "max_tokens": 1024, "messages": [{"role": "user", "content": "你好"}] }' @@ -768,7 +768,7 @@ curl http://localhost:5001/anthropic/v1/messages \ -H "Content-Type: application/json" \ -H "anthropic-version: 2023-06-01" \ -d '{ - "model": "claude-sonnet-4-20250514-slow", + "model": "claude-opus-4-6", "max_tokens": 1024, "messages": [{"role": "user", "content": "解释相对论"}], "stream": true diff --git a/README.MD b/README.MD index ebcf943..3182941 100644 --- a/README.MD +++ b/README.MD @@ -79,9 +79,9 @@ flowchart LR | 模型 | 默认映射 | | --- | --- | -| `claude-sonnet-4-20250514` | `deepseek-chat` | -| `claude-sonnet-4-20250514-fast` | `deepseek-chat` | -| `claude-sonnet-4-20250514-slow` | `deepseek-reasoner` | +| `claude-sonnet-4-5` | `deepseek-chat` | +| `claude-3-5-haiku-latest` | `deepseek-chat` | +| `claude-opus-4-6` | `deepseek-reasoner` | 可通过配置中的 `claude_mapping` 或 `claude_model_mapping` 覆盖映射关系。 diff --git a/README.en.md b/README.en.md index b2c9373..555859c 100644 --- a/README.en.md +++ b/README.en.md @@ -79,9 +79,9 @@ flowchart LR | Model | Default Mapping | | --- | --- | -| `claude-sonnet-4-20250514` | `deepseek-chat` | -| `claude-sonnet-4-20250514-fast` | `deepseek-chat` | -| `claude-sonnet-4-20250514-slow` | `deepseek-reasoner` | +| `claude-sonnet-4-5` | `deepseek-chat` | +| `claude-3-5-haiku-latest` | `deepseek-chat` | +| `claude-opus-4-6` | `deepseek-reasoner` | Override mapping via `claude_mapping` or `claude_model_mapping` in config. diff --git a/internal/adapter/claude/handler_stream_test.go b/internal/adapter/claude/handler_stream_test.go index 74086ae..701c8d7 100644 --- a/internal/adapter/claude/handler_stream_test.go +++ b/internal/adapter/claude/handler_stream_test.go @@ -81,7 +81,7 @@ func TestHandleClaudeStreamRealtimeTextIncrementsWithEventHeaders(t *testing.T) rec := httptest.NewRecorder() req := httptest.NewRequest(http.MethodPost, "/anthropic/v1/messages", nil) - h.handleClaudeStreamRealtime(rec, req, resp, "claude-sonnet-4-20250514", []any{map[string]any{"role": "user", "content": "hi"}}, false, false, nil) + h.handleClaudeStreamRealtime(rec, req, resp, "claude-sonnet-4-5", []any{map[string]any{"role": "user", "content": "hi"}}, false, false, nil) body := rec.Body.String() if !strings.Contains(body, "event: message_start") { @@ -122,7 +122,7 @@ func TestHandleClaudeStreamRealtimeThinkingDelta(t *testing.T) { rec := httptest.NewRecorder() req := httptest.NewRequest(http.MethodPost, "/anthropic/v1/messages", nil) - h.handleClaudeStreamRealtime(rec, req, resp, "claude-sonnet-4-20250514", []any{map[string]any{"role": "user", "content": "hi"}}, true, false, nil) + h.handleClaudeStreamRealtime(rec, req, resp, "claude-sonnet-4-5", []any{map[string]any{"role": "user", "content": "hi"}}, true, false, nil) frames := parseClaudeFrames(t, rec.Body.String()) foundThinkingDelta := false @@ -148,7 +148,7 @@ func TestHandleClaudeStreamRealtimeToolSafety(t *testing.T) { rec := httptest.NewRecorder() req := httptest.NewRequest(http.MethodPost, "/anthropic/v1/messages", nil) - h.handleClaudeStreamRealtime(rec, req, resp, "claude-sonnet-4-20250514", []any{map[string]any{"role": "user", "content": "use tool"}}, false, false, []string{"search"}) + h.handleClaudeStreamRealtime(rec, req, resp, "claude-sonnet-4-5", []any{map[string]any{"role": "user", "content": "use tool"}}, false, false, []string{"search"}) frames := parseClaudeFrames(t, rec.Body.String()) for _, f := range findClaudeFrames(frames, "content_block_delta") { @@ -191,7 +191,7 @@ func TestHandleClaudeStreamRealtimeUpstreamErrorEvent(t *testing.T) { rec := httptest.NewRecorder() req := httptest.NewRequest(http.MethodPost, "/anthropic/v1/messages", nil) - h.handleClaudeStreamRealtime(rec, req, resp, "claude-sonnet-4-20250514", []any{map[string]any{"role": "user", "content": "hi"}}, false, false, nil) + h.handleClaudeStreamRealtime(rec, req, resp, "claude-sonnet-4-5", []any{map[string]any{"role": "user", "content": "hi"}}, false, false, nil) frames := parseClaudeFrames(t, rec.Body.String()) errFrames := findClaudeFrames(frames, "error") @@ -228,7 +228,7 @@ func TestHandleClaudeStreamRealtimePingEvent(t *testing.T) { rec := httptest.NewRecorder() req := httptest.NewRequest(http.MethodPost, "/anthropic/v1/messages", nil) - h.handleClaudeStreamRealtime(rec, req, resp, "claude-sonnet-4-20250514", []any{map[string]any{"role": "user", "content": "hi"}}, false, false, nil) + h.handleClaudeStreamRealtime(rec, req, resp, "claude-sonnet-4-5", []any{map[string]any{"role": "user", "content": "hi"}}, false, false, nil) frames := parseClaudeFrames(t, rec.Body.String()) if len(findClaudeFrames(frames, "ping")) == 0 { diff --git a/internal/config/models.go b/internal/config/models.go index c6cbd5f..51f6126 100644 --- a/internal/config/models.go +++ b/internal/config/models.go @@ -16,9 +16,13 @@ var DeepSeekModels = []ModelInfo{ } var ClaudeModels = []ModelInfo{ - {ID: "claude-sonnet-4-20250514", Object: "model", Created: 1715635200, OwnedBy: "anthropic"}, - {ID: "claude-sonnet-4-20250514-fast", Object: "model", Created: 1715635200, OwnedBy: "anthropic"}, - {ID: "claude-sonnet-4-20250514-slow", Object: "model", Created: 1715635200, OwnedBy: "anthropic"}, + {ID: "claude-sonnet-4-5", Object: "model", Created: 1715635200, OwnedBy: "anthropic"}, + {ID: "claude-sonnet-4-5-20250929", Object: "model", Created: 1715635200, OwnedBy: "anthropic"}, + {ID: "claude-opus-4-6", Object: "model", Created: 1715635200, OwnedBy: "anthropic"}, + {ID: "claude-opus-4-1", Object: "model", Created: 1715635200, OwnedBy: "anthropic"}, + {ID: "claude-opus-4-1-20250805", Object: "model", Created: 1715635200, OwnedBy: "anthropic"}, + {ID: "claude-3-7-sonnet-latest", Object: "model", Created: 1715635200, OwnedBy: "anthropic"}, + {ID: "claude-3-5-haiku-latest", Object: "model", Created: 1715635200, OwnedBy: "anthropic"}, } func GetModelConfig(model string) (thinking bool, search bool, ok bool) { diff --git a/internal/testsuite/edge_cases.go b/internal/testsuite/edge_cases.go index 784f8ab..cba0b5a 100644 --- a/internal/testsuite/edge_cases.go +++ b/internal/testsuite/edge_cases.go @@ -275,7 +275,7 @@ func (r *Runner) caseSSEJSONIntegrity(ctx context.Context, cc *caseContext) erro "anthropic-version": "2023-06-01", }, Body: map[string]any{ - "model": "claude-sonnet-4-20250514", + "model": "claude-sonnet-4-5", "messages": []map[string]any{ {"role": "user", "content": "stream json integrity"}, }, diff --git a/internal/testsuite/runner.go b/internal/testsuite/runner.go index de8ea00..8af1b7d 100644 --- a/internal/testsuite/runner.go +++ b/internal/testsuite/runner.go @@ -1056,7 +1056,7 @@ func (r *Runner) caseAnthropicNonstream(ctx context.Context, cc *caseContext) er "content-type": "application/json", }, Body: map[string]any{ - "model": "claude-sonnet-4-20250514", + "model": "claude-sonnet-4-5", "messages": []map[string]any{ {"role": "user", "content": "hello"}, }, @@ -1084,7 +1084,7 @@ func (r *Runner) caseAnthropicStream(ctx context.Context, cc *caseContext) error "content-type": "application/json", }, Body: map[string]any{ - "model": "claude-sonnet-4-20250514", + "model": "claude-sonnet-4-5", "messages": []map[string]any{ {"role": "user", "content": "stream hello"}, }, @@ -1113,7 +1113,7 @@ func (r *Runner) caseAnthropicCountTokens(ctx context.Context, cc *caseContext) "content-type": "application/json", }, Body: map[string]any{ - "model": "claude-sonnet-4-20250514", + "model": "claude-sonnet-4-5", "messages": []map[string]any{ {"role": "user", "content": "count me"}, }, diff --git a/internal/util/messages.go b/internal/util/messages.go index 69eaf87..19f2948 100644 --- a/internal/util/messages.go +++ b/internal/util/messages.go @@ -9,7 +9,7 @@ import ( var markdownImagePattern = regexp.MustCompile(`!\[(.*?)\]\((.*?)\)`) -const ClaudeDefaultModel = "claude-sonnet-4-20250514" +const ClaudeDefaultModel = "claude-sonnet-4-5" type Message struct { Role string `json:"role"` diff --git a/internal/util/messages_test.go b/internal/util/messages_test.go index b8c1304..30b8cc0 100644 --- a/internal/util/messages_test.go +++ b/internal/util/messages_test.go @@ -36,7 +36,7 @@ func TestMessagesPrepareRoles(t *testing.T) { func TestConvertClaudeToDeepSeek(t *testing.T) { store := config.LoadStore() req := map[string]any{ - "model": "claude-sonnet-4-20250514-slow", + "model": "claude-opus-4-6", "messages": []any{map[string]any{"role": "user", "content": "Hi"}}, "system": "You are helpful", "stream": true,