File size: 8,177 Bytes
0133533
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
50852f0
0133533
 
 
 
 
 
 
 
 
 
 
 
50852f0
0133533
 
 
 
 
 
50852f0
0133533
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
import { getSystemPrompt, getModelReasoning, getUserAgent } from '../../configs/config.js'

export function transformToAnthropic(openaiRequest) {
  
  const anthropicRequest = {
    model: openaiRequest.model,
    messages: []
  };

  // 仅在客户端明确提供时添加 stream 参数
  if (openaiRequest.stream !== undefined) {
    anthropicRequest.stream = openaiRequest.stream;
  }

  // 处理 max_tokens
  if (openaiRequest.max_tokens) {
    anthropicRequest.max_tokens = openaiRequest.max_tokens;
  } else if (openaiRequest.max_completion_tokens) {
    anthropicRequest.max_tokens = openaiRequest.max_completion_tokens;
  } else {
    anthropicRequest.max_tokens = 64000;
  }

  // 提取系统消息并转换其他消息
  let systemContent = [];

  if (openaiRequest.messages && Array.isArray(openaiRequest.messages)) {
    for (const msg of openaiRequest.messages) {
      // 单独处理系统消息
      if (msg.role === 'system') {
        if (typeof msg.content === 'string') {
          systemContent.push({
            type: 'text',
            text: msg.content?.replace("You are Claude Code, Anthropic's official CLI for Claude.", 'you are bot.').replace("You are Claude Code, Anthropic's official CLI for Claude, running within the Claude Agent SDK.", "you are bot.")
          });
        } else if (Array.isArray(msg.content)) {
          for (const part of msg.content) {
            if (part.type === 'text') {
              systemContent.push({
                type: 'text',
                text: part.text?.replace("You are Claude Code, Anthropic's official CLI for Claude.", 'you are bot.').replace("You are Claude Code, Anthropic's official CLI for Claude, running within the Claude Agent SDK.", "you are bot.")
              });
            } else {
              systemContent.push(part);
            }
          }
        }
        continue; // 跳过将系统消息添加到消息数组
      }

      const anthropicMsg = {
        role: msg.role,
        content: []
      };

      if (typeof msg.content === 'string') {
        anthropicMsg.content.push({
          type: 'text',
          text: msg.content
        });
      } else if (Array.isArray(msg.content)) {
        for (const part of msg.content) {
          if (part.type === 'text') {
            anthropicMsg.content.push({
              type: 'text',
              text: part.text
            });
          } else if (part.type === 'image_url') {
            anthropicMsg.content.push({
              type: 'image',
              source: part.image_url
            });
          } else {
            anthropicMsg.content.push(part);
          }
        }
      }

      anthropicRequest.messages.push(anthropicMsg);
    }
  }

  // 添加系统参数,并在前面加上系统提示
  const systemPrompt = getSystemPrompt();
  if (systemPrompt || systemContent.length > 0) {
    anthropicRequest.system = [];
    // 如果存在系统提示,则将其作为第一个元素添加
    if (systemPrompt) {
      anthropicRequest.system.push({
        type: 'text',
        text: systemPrompt
      });
    }
    // 添加用户提供的系统内容
    anthropicRequest.system.push(...systemContent);
  }

  // 如果存在工具,则进行转换
  if (openaiRequest.tools && Array.isArray(openaiRequest.tools)) {
    anthropicRequest.tools = openaiRequest.tools.map(tool => {
      if (tool.type === 'function') {
        return {
          name: tool.function.name,
          description: tool.function.description,
          input_schema: tool.function.parameters || {}
        };
      }
      return tool;
    });
  }

  // 根据模型配置处理 thinking 字段
  const reasoningLevel = getModelReasoning(openaiRequest.model);
  if (reasoningLevel === 'auto') {
    // 自动模式:完全保留原始请求的 thinking 字段
    if (openaiRequest.thinking !== undefined) {
      anthropicRequest.thinking = openaiRequest.thinking;
    }
    // 如果原始请求没有 thinking 字段,则不添加
  } else if (reasoningLevel && ['low', 'medium', 'high'].includes(reasoningLevel)) {
    // 特定级别:使用模型配置覆盖
    const budgetTokens = {
      'low': 4096,
      'medium': 12288,
      'high': 24576
    };

    anthropicRequest.thinking = {
      type: 'enabled',
      budget_tokens: budgetTokens[reasoningLevel]
    };
  } else {
    // 关闭或无效:显式删除 thinking 字段
    // 这确保删除原始请求中的任何 thinking 字段
    delete anthropicRequest.thinking;
  }

  // 传递其他兼容参数
  if (openaiRequest.temperature !== undefined) {
    anthropicRequest.temperature = openaiRequest.temperature;
  }
  if (openaiRequest.top_p !== undefined) {
    anthropicRequest.top_p = openaiRequest.top_p;
  }
  if (openaiRequest.stop !== undefined) {
    anthropicRequest.stop_sequences = Array.isArray(openaiRequest.stop)
      ? openaiRequest.stop
      : [openaiRequest.stop];
  }

  return anthropicRequest;
}

export function getAnthropicHeaders(authHeader, clientHeaders = {}, isStreaming = true, modelId = null) {
  // 如果未提供则生成唯一 ID
  const sessionId = clientHeaders['x-session-id'] || generateUUID();
  const messageId = clientHeaders['x-assistant-message-id'] || generateUUID();

  const headers = {
    'accept': 'application/json',
    'content-type': 'application/json',
    'anthropic-version': clientHeaders['anthropic-version'] || '2023-06-01',
    'authorization': authHeader || '',
    'x-api-key': 'placeholder',
    'x-api-provider': 'anthropic',
    'x-factory-client': 'cli',
    'x-session-id': sessionId,
    'x-assistant-message-id': messageId,
    'user-agent': getUserAgent(),
    'x-stainless-timeout': '600',
    'connection': 'keep-alive'
  }

  // 根据推理配置处理 anthropic-beta 头
  const reasoningLevel = modelId ? getModelReasoning(modelId) : null;
  let betaValues = [];

  // 从客户端头添加现有的 beta 值
  if (clientHeaders['anthropic-beta']) {
    const existingBeta = clientHeaders['anthropic-beta'];
    betaValues = existingBeta.split(',').map(v => v.trim());
  }

  // 根据推理配置处理 thinking beta
  const thinkingBeta = 'interleaved-thinking-2025-05-14';
  if (reasoningLevel === 'auto') {
    // 自动模式:不修改 anthropic-beta 头,保留原始值
    // betaValues 保持客户端头的不变
  } else if (reasoningLevel && ['low', 'medium', 'high'].includes(reasoningLevel)) {
    // 如果尚未存在,则添加 thinking beta
    if (!betaValues.includes(thinkingBeta)) {
      betaValues.push(thinkingBeta);
    }
  } else {
    // 如果推理关闭或无效,则删除 thinking beta
    betaValues = betaValues.filter(v => v !== thinkingBeta);
  }

  // 如果有任何值,则设置 anthropic-beta 头
  if (betaValues.length > 0) {
    headers['anthropic-beta'] = betaValues.join(', ');
  }

  // 使用默认值传递 Stainless SDK 头
  const stainlessDefaults = {
    'x-stainless-arch': 'x64',
    'x-stainless-lang': 'js',
    'x-stainless-os': 'MacOS',
    'x-stainless-runtime': 'node',
    'x-stainless-retry-count': '0',
    'x-stainless-package-version': '0.57.0',
    'x-stainless-runtime-version': 'v24.3.0'
  };

  // 根据流式传输设置 helper-method
  if (isStreaming) {
    headers['x-stainless-helper-method'] = 'stream';
  }

  // 从客户端复制 Stainless 头或使用默认值
  Object.keys(stainlessDefaults).forEach(header => {
    headers[header] = clientHeaders[header] || stainlessDefaults[header];
  });

  // 如果客户端提供,则覆盖默认超时
  if (clientHeaders['x-stainless-timeout']) {
    headers['x-stainless-timeout'] = clientHeaders['x-stainless-timeout'];
  }

  return headers;
}

function generateUUID() {
  return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
    const r = Math.random() * 16 | 0;
    const v = c == 'x' ? r : (r & 0x3 | 0x8);
    return v.toString(16);
  });
}