mirror of
https://github.com/Wei-Shaw/claude-relay-service.git
synced 2026-03-30 02:49:02 +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格式
|
||||
_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模型名的映射表
|
||||
const modelMapping = {
|
||||
// Claude Opus 4.6
|
||||
'claude-opus-4-6': 'global.anthropic.claude-opus-4-6-v1',
|
||||
|
||||
// Claude 4.5 Opus
|
||||
'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',
|
||||
@@ -482,21 +489,21 @@ class BedrockRelayService {
|
||||
|
||||
// 如果已经是Bedrock格式,直接返回
|
||||
// Bedrock模型格式:{region}.anthropic.{model-name} 或 anthropic.{model-name}
|
||||
if (modelName.includes('.anthropic.') || modelName.startsWith('anthropic.')) {
|
||||
return modelName
|
||||
if (cleanModelName.includes('.anthropic.') || cleanModelName.startsWith('anthropic.')) {
|
||||
return cleanModelName
|
||||
}
|
||||
|
||||
// 查找映射
|
||||
const mappedModel = modelMapping[modelName]
|
||||
const mappedModel = modelMapping[cleanModelName]
|
||||
if (mappedModel) {
|
||||
return mappedModel
|
||||
}
|
||||
|
||||
// 如果没有找到映射,返回原始模型名(可能会导致错误,但保持向后兼容)
|
||||
logger.warn(`⚠️ 未找到模型映射: ${modelName},使用原始模型名`, {
|
||||
logger.warn(`⚠️ 未找到模型映射: ${cleanModelName},使用原始模型名`, {
|
||||
metadata: { originalModel: modelName }
|
||||
})
|
||||
return modelName
|
||||
return cleanModelName
|
||||
}
|
||||
|
||||
// 选择使用的区域
|
||||
@@ -514,6 +521,35 @@ class BedrockRelayService {
|
||||
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格式
|
||||
_convertToBedrockFormat(requestBody) {
|
||||
const bedrockPayload = {
|
||||
@@ -553,6 +589,9 @@ class BedrockRelayService {
|
||||
bedrockPayload.tool_choice = requestBody.tool_choice
|
||||
}
|
||||
|
||||
// Sanitize cache_control for Bedrock compatibility (strip unsupported fields like "scope")
|
||||
this._sanitizeCacheControl(bedrockPayload)
|
||||
|
||||
return bedrockPayload
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user