claw-subagent-service 0.0.75 → 0.0.77

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claw-subagent-service",
3
- "version": "0.0.75",
3
+ "version": "0.0.77",
4
4
  "description": "虾说智能助手",
5
5
  "main": "cli.js",
6
6
  "bin": {
@@ -369,17 +369,17 @@ class MessageHandler {
369
369
 
370
370
  this.log?.info(`[MessageHandler] 流式消息完成,streamId=${streamId}, 总长度: ${fullText.length}`);
371
371
 
372
- // 清理已存储的 messageUID,防止内存泄漏
373
- this._streamMessageUIDs.delete(streamId);
374
-
375
372
  // 发送持久化的普通文本消息作为历史记录(融云会保存 RC:TxtMsg)
376
373
  if (buffer.trim()) {
377
374
  try {
378
- this.log?.info(`[MessageHandler] 发送历史记录文本消息: length=${buffer.length}`);
375
+ // 使用融云首流返回的 messageUID 作为 streamId,确保与前端匹配
376
+ const rongCloudMsgUID = this._streamMessageUIDs.get(streamId);
377
+ const historyStreamId = rongCloudMsgUID || streamId;
378
+ this.log?.info(`[MessageHandler] 发送历史记录文本消息: length=${buffer.length}, streamId=${historyStreamId}`);
379
379
  // 使用 JSON 格式包含 streamId,前端可据此关联并更新流式消息内容
380
380
  const historyContent = JSON.stringify({
381
381
  __stream_history__: true,
382
- streamId: streamId,
382
+ streamId: historyStreamId,
383
383
  text: buffer,
384
384
  sentTime: Date.now()
385
385
  });
@@ -388,6 +388,9 @@ class MessageHandler {
388
388
  this.log?.error(`[MessageHandler] 发送历史记录失败: ${err.message}`);
389
389
  }
390
390
  }
391
+
392
+ // 清理已存储的 messageUID,防止内存泄漏
393
+ this._streamMessageUIDs.delete(streamId);
391
394
  }
392
395
  );
393
396
  } catch (err) {
@@ -63,11 +63,22 @@ class RongCloudServerAPI {
63
63
  };
64
64
  }
65
65
 
66
+ _getFormHeaders(appKey, appSecret) {
67
+ const sign = this._generateSignature(appSecret);
68
+ return {
69
+ 'App-Key': appKey,
70
+ 'Nonce': sign.nonce,
71
+ 'Timestamp': String(sign.timestamp),
72
+ 'Signature': sign.signature,
73
+ 'Content-Type': 'application/x-www-form-urlencoded'
74
+ };
75
+ }
76
+
66
77
  async request(path, data, appKey, appSecret, retry = true) {
67
78
  const url = `https://${this.currentHost}${path}`;
68
79
  const headers = this._getHeaders(appKey, appSecret);
69
80
 
70
- this.log?.info(`[RongCloudServerAPI] 请求: POST ${url}`);
81
+ this.log?.info(`[RongCloudServerAPI] 请求: POST ${url} (JSON)`);
71
82
 
72
83
  try {
73
84
  const response = await axios.post(url, data, {
@@ -99,6 +110,50 @@ class RongCloudServerAPI {
99
110
  }
100
111
  }
101
112
 
113
+ async requestForm(path, data, appKey, appSecret, retry = true) {
114
+ const url = `https://${this.currentHost}${path}`;
115
+ const headers = this._getFormHeaders(appKey, appSecret);
116
+
117
+ // 将对象转换为 URLSearchParams (form-urlencoded)
118
+ const params = new URLSearchParams();
119
+ for (const [key, value] of Object.entries(data)) {
120
+ if (value !== undefined && value !== null) {
121
+ params.append(key, typeof value === 'object' ? JSON.stringify(value) : String(value));
122
+ }
123
+ }
124
+
125
+ this.log?.info(`[RongCloudServerAPI] 请求: POST ${url} (Form)`);
126
+
127
+ try {
128
+ const response = await axios.post(url, params.toString(), {
129
+ headers,
130
+ timeout: this.timeout,
131
+ responseType: 'json'
132
+ });
133
+
134
+ const result = response.data;
135
+
136
+ if (result.code && result.code !== 200) {
137
+ throw new Error(`[${result.code}] ${result.errorMessage || 'Unknown error'}`);
138
+ }
139
+
140
+ return result;
141
+ } catch (err) {
142
+ if (err.response?.status === 401) {
143
+ this.log?.error('[RongCloudServerAPI] 签名验证失败,请检查 App Key 和 App Secret');
144
+ throw err;
145
+ }
146
+
147
+ if (retry && this._switchHost()) {
148
+ this.log?.warn(`[RongCloudServerAPI] 请求失败,使用备用域名重试: ${err.message}`);
149
+ return this.requestForm(path, data, appKey, appSecret, false);
150
+ }
151
+
152
+ this.log?.error(`[RongCloudServerAPI] 请求失败: ${err.message}`);
153
+ throw err;
154
+ }
155
+ }
156
+
102
157
  /**
103
158
  * 获取融云配置
104
159
  */
@@ -227,9 +282,9 @@ class RongCloudServerAPI {
227
282
  this.log?.info(`[RongCloudServerAPI] 发送 typing 状态: ${fromUserId} -> ${toUserId}`);
228
283
 
229
284
  if (conversationType === 3) {
230
- return this.request('/message/group/publish.json', data, appKey, appSecret);
285
+ return this.requestForm('/message/group/publish.json', data, appKey, appSecret);
231
286
  }
232
- return this.request('/message/private/publish.json', data, appKey, appSecret);
287
+ return this.requestForm('/message/private/publish.json', data, appKey, appSecret);
233
288
  }
234
289
  }
235
290