mirror of
https://github.com/Wei-Shaw/claude-relay-service.git
synced 2026-04-19 12:58:39 +00:00
Merge pull request #965 from bensonz/main [skip ci]
fix: Bedrock compatibility — 修复了 bedrock 不能用的问题. cache_control sanitization, Opus 4.6 mapping, [1m] suffix stripping
This commit is contained in:
@@ -436,8 +436,15 @@ class BedrockRelayService {
|
|||||||
|
|
||||||
// 将标准Claude模型名映射为Bedrock格式
|
// 将标准Claude模型名映射为Bedrock格式
|
||||||
_mapToBedrockModel(modelName) {
|
_mapToBedrockModel(modelName) {
|
||||||
|
// Strip [1m] suffix (long context variant) — Bedrock uses the same model ID
|
||||||
|
// but supports 1M context natively for models that have it
|
||||||
|
const cleanModelName = modelName.replace(/\[1m\]$/, '')
|
||||||
|
|
||||||
// 标准Claude模型名到Bedrock模型名的映射表
|
// 标准Claude模型名到Bedrock模型名的映射表
|
||||||
const modelMapping = {
|
const modelMapping = {
|
||||||
|
// Claude Opus 4.6
|
||||||
|
'claude-opus-4-6': 'global.anthropic.claude-opus-4-6-v1',
|
||||||
|
|
||||||
// Claude 4.5 Opus
|
// Claude 4.5 Opus
|
||||||
'claude-opus-4-5': 'us.anthropic.claude-opus-4-5-20251101-v1:0',
|
'claude-opus-4-5': 'us.anthropic.claude-opus-4-5-20251101-v1:0',
|
||||||
'claude-opus-4-5-20251101': 'us.anthropic.claude-opus-4-5-20251101-v1:0',
|
'claude-opus-4-5-20251101': 'us.anthropic.claude-opus-4-5-20251101-v1:0',
|
||||||
@@ -482,21 +489,21 @@ class BedrockRelayService {
|
|||||||
|
|
||||||
// 如果已经是Bedrock格式,直接返回
|
// 如果已经是Bedrock格式,直接返回
|
||||||
// Bedrock模型格式:{region}.anthropic.{model-name} 或 anthropic.{model-name}
|
// Bedrock模型格式:{region}.anthropic.{model-name} 或 anthropic.{model-name}
|
||||||
if (modelName.includes('.anthropic.') || modelName.startsWith('anthropic.')) {
|
if (cleanModelName.includes('.anthropic.') || cleanModelName.startsWith('anthropic.')) {
|
||||||
return modelName
|
return cleanModelName
|
||||||
}
|
}
|
||||||
|
|
||||||
// 查找映射
|
// 查找映射
|
||||||
const mappedModel = modelMapping[modelName]
|
const mappedModel = modelMapping[cleanModelName]
|
||||||
if (mappedModel) {
|
if (mappedModel) {
|
||||||
return mappedModel
|
return mappedModel
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果没有找到映射,返回原始模型名(可能会导致错误,但保持向后兼容)
|
// 如果没有找到映射,返回原始模型名(可能会导致错误,但保持向后兼容)
|
||||||
logger.warn(`⚠️ 未找到模型映射: ${modelName},使用原始模型名`, {
|
logger.warn(`⚠️ 未找到模型映射: ${cleanModelName},使用原始模型名`, {
|
||||||
metadata: { originalModel: modelName }
|
metadata: { originalModel: modelName }
|
||||||
})
|
})
|
||||||
return modelName
|
return cleanModelName
|
||||||
}
|
}
|
||||||
|
|
||||||
// 选择使用的区域
|
// 选择使用的区域
|
||||||
@@ -514,6 +521,35 @@ class BedrockRelayService {
|
|||||||
return this.defaultRegion
|
return this.defaultRegion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sanitize cache_control fields for Bedrock compatibility.
|
||||||
|
// Bedrock only supports { type: "ephemeral" } — extra fields like "scope"
|
||||||
|
// (added in Claude Code v2.1.38+) cause ValidationException.
|
||||||
|
_sanitizeCacheControl(obj) {
|
||||||
|
if (obj === null || obj === undefined || typeof obj !== 'object') {
|
||||||
|
return obj
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Array.isArray(obj)) {
|
||||||
|
obj.forEach((item) => this._sanitizeCacheControl(item))
|
||||||
|
return obj
|
||||||
|
}
|
||||||
|
|
||||||
|
if (obj.cache_control && typeof obj.cache_control === 'object') {
|
||||||
|
// Keep only the "type" field that Bedrock accepts
|
||||||
|
obj.cache_control = { type: obj.cache_control.type || 'ephemeral' }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Recurse into known nested structures (messages[].content, tool input_schema, etc.)
|
||||||
|
for (const key of Object.keys(obj)) {
|
||||||
|
const val = obj[key]
|
||||||
|
if (val && typeof val === 'object') {
|
||||||
|
this._sanitizeCacheControl(val)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return obj
|
||||||
|
}
|
||||||
|
|
||||||
// 转换Claude格式请求到Bedrock格式
|
// 转换Claude格式请求到Bedrock格式
|
||||||
_convertToBedrockFormat(requestBody) {
|
_convertToBedrockFormat(requestBody) {
|
||||||
const bedrockPayload = {
|
const bedrockPayload = {
|
||||||
@@ -553,6 +589,9 @@ class BedrockRelayService {
|
|||||||
bedrockPayload.tool_choice = requestBody.tool_choice
|
bedrockPayload.tool_choice = requestBody.tool_choice
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sanitize cache_control for Bedrock compatibility (strip unsupported fields like "scope")
|
||||||
|
this._sanitizeCacheControl(bedrockPayload)
|
||||||
|
|
||||||
return bedrockPayload
|
return bedrockPayload
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user