aicodeswitch 1.10.2 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -51,19 +51,99 @@ const mapStopReason = (finishReason) => {
51
51
  }
52
52
  };
53
53
  exports.mapStopReason = mapStopReason;
54
+ /**
55
+ * 检查模型是否需要使用 developer 角色而不是 system 角色
56
+ * 某些 OpenAI 兼容的 API (如 DeepSeek) 不支持 system 角色,需要使用 developer
57
+ */
58
+ const shouldUseDeveloperRole = (model) => {
59
+ if (!model)
60
+ return false;
61
+ const lowerModel = model.toLowerCase();
62
+ // DeepSeek 模型使用 developer 角色
63
+ if (lowerModel.includes('deepseek')) {
64
+ return true;
65
+ }
66
+ // 其他可能需要 developer 角色的模型可以在这里添加
67
+ // 例如:某些国内的 GPT 兼容 API
68
+ return false;
69
+ };
70
+ /**
71
+ * 智能修复 messages 数组,确保最后一条消息是 role: user
72
+ * OpenAI Chat API 要求对话必须以用户消息结束
73
+ *
74
+ * 处理场景:
75
+ * 1. 最后是 assistant 消息(带 tool_calls):添加用户消息请求执行工具
76
+ * 2. 最后是 assistant 消息(不带 tool_calls):添加用户继续提示
77
+ * 3. 最后是 tool 消息:添加用户消息请求处理工具结果
78
+ * 4. 最后是 system/developer 消息:添加初始用户消息
79
+ * 5. 最后已经是 user 消息:不处理
80
+ */
81
+ const ensureLastMessageIsUser = (messages) => {
82
+ if (!messages || messages.length === 0) {
83
+ return;
84
+ }
85
+ const lastMessage = messages[messages.length - 1];
86
+ const lastRole = lastMessage === null || lastMessage === void 0 ? void 0 : lastMessage.role;
87
+ // 如果最后一条已经是 user,无需处理
88
+ if (lastRole === 'user') {
89
+ return;
90
+ }
91
+ // 场景1: 最后是 assistant 消息且带有 tool_calls
92
+ // 这种情况下,通常后面应该跟 tool 消息,但如果没有,我们需要添加一个用户消息
93
+ if (lastRole === 'assistant' && lastMessage.tool_calls && Array.isArray(lastMessage.tool_calls) && lastMessage.tool_calls.length > 0) {
94
+ messages.push({
95
+ role: 'user',
96
+ content: 'Please proceed with the tool calls.'
97
+ });
98
+ return;
99
+ }
100
+ // 场景2: 最后是 assistant 消息(不带 tool_calls)
101
+ if (lastRole === 'assistant') {
102
+ messages.push({
103
+ role: 'user',
104
+ content: 'Please continue.'
105
+ });
106
+ return;
107
+ }
108
+ // 场景3: 最后是 tool 消息
109
+ if (lastRole === 'tool') {
110
+ messages.push({
111
+ role: 'user',
112
+ content: 'Please analyze the tool results and continue.'
113
+ });
114
+ return;
115
+ }
116
+ // 场景4: 最后是 system/developer 消息
117
+ if (lastRole === 'system' || lastRole === 'developer') {
118
+ messages.push({
119
+ role: 'user',
120
+ content: 'Hello, I need your assistance.'
121
+ });
122
+ return;
123
+ }
124
+ // 其他未知角色,添加通用用户消息
125
+ messages.push({
126
+ role: 'user',
127
+ content: 'Please continue.'
128
+ });
129
+ };
54
130
  const transformClaudeRequestToOpenAIChat = (body, targetModel) => {
55
131
  var _a;
56
132
  const messages = [];
133
+ const useDeveloperRole = shouldUseDeveloperRole(targetModel);
134
+ const systemRoleName = useDeveloperRole ? 'developer' : 'system';
57
135
  if (body.system) {
58
136
  const systemText = toTextContent(body.system);
59
137
  if (systemText) {
60
- messages.push({ role: 'system', content: systemText });
138
+ messages.push({ role: systemRoleName, content: systemText });
61
139
  }
62
140
  }
63
141
  if (Array.isArray(body.messages)) {
64
142
  for (const message of body.messages) {
143
+ // 映射 system 角色到 developer (如果需要)
144
+ const mappedRole = (message.role === 'system' && useDeveloperRole) ? 'developer' : message.role;
65
145
  if (typeof message.content === 'string' || message.content === null) {
66
- messages.push({ role: message.role, content: message.content });
146
+ messages.push({ role: mappedRole, content: message.content });
67
147
  continue;
68
148
  }
69
149
  if (Array.isArray(message.content)) {
@@ -101,7 +181,7 @@ const transformClaudeRequestToOpenAIChat = (body, targetModel) => {
101
181
  }
102
182
  const content = textParts.length > 0 ? textParts.join('') : null;
103
183
  const openaiMessage = {
104
- role: message.role,
184
+ role: mappedRole,
105
185
  content,
106
186
  };
107
187
  if (toolCalls.length > 0) {
@@ -112,6 +192,9 @@ const transformClaudeRequestToOpenAIChat = (body, targetModel) => {
112
192
  }
113
193
  }
114
194
  }
195
+ // 智能修复:确保最后一条消息是 role: user
196
+ // OpenAI API 要求对话必须以用户消息结束
197
+ ensureLastMessageIsUser(messages);
115
198
  const openaiBody = {
116
199
  model: targetModel || body.model,
117
200
  messages,
@@ -88,7 +88,10 @@ class SSEParserTransform extends stream_1.Transform {
88
88
  exports.SSEParserTransform = SSEParserTransform;
89
89
  class SSESerializerTransform extends stream_1.Transform {
90
90
  constructor() {
91
- super({ writableObjectMode: true });
91
+ super({
92
+ writableObjectMode: true, // 接收对象
93
+ readableObjectMode: false, // 输出字符串/Buffer
94
+ });
92
95
  }
93
96
  _transform(event, _encoding, callback) {
94
97
  var _a;
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.checkPortUsable = checkPortUsable;
4
+ const net = require('net');
5
+ function checkPortUsable(port) {
6
+ return new Promise((resolve) => {
7
+ const server = net.createConnection({ port });
8
+ server.on('connect', () => {
9
+ server.end();
10
+ resolve(false);
11
+ });
12
+ server.on('error', () => {
13
+ resolve(true);
14
+ });
15
+ });
16
+ }