claw-subagent-service 0.0.109 → 0.0.111

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.109",
3
+ "version": "0.0.111",
4
4
  "description": "虾说智能助手",
5
5
  "main": "cli.js",
6
6
  "bin": {
@@ -383,9 +383,9 @@ class OpenClawClient {
383
383
  }
384
384
 
385
385
  if (is404 && isLast) {
386
- this.log?.error(`[OpenClawClient] 所有 SSE 端点均返回 404。OpenClaw chatCompletions 端点未启用。`);
386
+ this.log?.error(`[OpenClawClient] 所有 SSE 端点均返回 404。OpenClaw responses 端点未启用。`);
387
387
  this.log?.error(`[OpenClawClient] 请检查 ~/.openclaw/openclaw.json 中是否包含:`);
388
- this.log?.error(`[OpenClawClient] gateway.http.endpoints.chatCompletions.enabled = true`);
388
+ this.log?.error(`[OpenClawClient] gateway.http.endpoints.responses.enabled = true`);
389
389
  this.log?.error(`[OpenClawClient] 修改后请重启 OpenClaw gateway: openclaw gateway`);
390
390
  } else {
391
391
  this.log?.error(`[OpenClawClient] SSE 请求失败: ${err.message}`);
@@ -393,13 +393,29 @@ class OpenClawClient {
393
393
  if (err.response) {
394
394
  this.log?.error(`[OpenClawClient] 错误状态码: ${err.response.status}`);
395
395
  // 安全地提取错误信息
396
- const errorData = err.response.data;
397
- if (typeof errorData === 'string') {
398
- this.log?.error(`[OpenClawClient] 错误响应: ${errorData}`);
399
- } else if (errorData && typeof errorData === 'object') {
400
- // 提取常见错误字段
401
- const errorMsg = errorData.error?.message || errorData.message || errorData.error || JSON.stringify(errorData);
402
- this.log?.error(`[OpenClawClient] 错误响应: ${errorMsg}`);
396
+ try {
397
+ const errorData = err.response.data;
398
+ if (typeof errorData === 'string') {
399
+ this.log?.error(`[OpenClawClient] 错误响应: ${errorData}`);
400
+ } else if (errorData && typeof errorData === 'object') {
401
+ // 检查是否是 IncomingMessage 对象(流)
402
+ if (errorData._readableState || errorData.socket) {
403
+ // 这是一个流对象,尝试读取其中的数据
404
+ const buffer = errorData._readableState?.buffer;
405
+ if (buffer && buffer.length > 0) {
406
+ const dataStr = buffer[0].toString('utf8');
407
+ this.log?.error(`[OpenClawClient] 错误响应(流): ${dataStr}`);
408
+ } else {
409
+ this.log?.error(`[OpenClawClient] 错误响应(流对象,无法读取)`);
410
+ }
411
+ } else {
412
+ // 提取常见错误字段
413
+ const errorMsg = errorData.error?.message || errorData.message || errorData.error || JSON.stringify(errorData);
414
+ this.log?.error(`[OpenClawClient] 错误响应: ${errorMsg}`);
415
+ }
416
+ }
417
+ } catch (e) {
418
+ this.log?.error(`[OpenClawClient] 无法解析错误响应: ${e.message}`);
403
419
  }
404
420
  }
405
421
  }
@@ -425,7 +441,11 @@ class OpenClawClient {
425
441
  const contentType = response.headers['content-type'] || 'image/jpeg';
426
442
  this.log?.info(`[OpenClawClient] 图片下载完成: ${imageUrl}, size=${buffer.length}, type=${contentType}`);
427
443
 
428
- return `data:${contentType};base64,${base64}`;
444
+ // 返回对象,包含纯 base64 和 MIME 类型
445
+ return {
446
+ base64: base64,
447
+ mediaType: contentType
448
+ };
429
449
  } catch (err) {
430
450
  this.log?.error(`[OpenClawClient] 图片下载失败: ${imageUrl}, ${err.message}`);
431
451
  throw err;
@@ -443,7 +463,10 @@ class OpenClawClient {
443
463
 
444
464
  // 检测消息是否包含图片 URL
445
465
  const imageUrlMatch = message.match(/\[图片\]\s*(https?:\/\/[^\s]+)/);
446
- let messages;
466
+ let payload;
467
+
468
+ // 判断使用哪个端点
469
+ const isResponsesEndpoint = apiUrl.includes('/v1/responses');
447
470
 
448
471
  if (imageUrlMatch) {
449
472
  // 多模态格式:图片 + 文本
@@ -452,32 +475,46 @@ class OpenClawClient {
452
475
 
453
476
  try {
454
477
  // 下载图片并转换为 base64
455
- const base64Image = await this._downloadImageAsBase64(imageUrl);
478
+ const imageData = await this._downloadImageAsBase64(imageUrl);
456
479
 
457
- messages = [{
458
- role: 'user',
459
- content: [
460
- { type: 'text', text: textContent || '描述这张图片' },
461
- { type: 'image_url', image_url: { url: base64Image } }
462
- ]
463
- }];
480
+ // 统一使用 messages 格式(OpenAI 兼容标准)
481
+ payload = {
482
+ model: 'openclaw',
483
+ messages: [{
484
+ role: 'user',
485
+ content: [
486
+ { type: 'text', text: textContent || '描述这张图片' },
487
+ {
488
+ type: 'image_url',
489
+ image_url: {
490
+ url: `data:${imageData.mediaType};base64,${imageData.base64}`
491
+ }
492
+ }
493
+ ]
494
+ }],
495
+ stream: true,
496
+ max_tokens: 2048
497
+ };
464
498
  } catch (err) {
465
499
  this.log?.warn(`[OpenClawClient] 图片处理失败,回退到文本模式: ${err.message}`);
466
500
  // 回退到纯文本模式
467
- messages = [{ role: 'user', content: message }];
501
+ payload = {
502
+ model: 'openclaw',
503
+ messages: [{ role: 'user', content: message }],
504
+ stream: true,
505
+ max_tokens: 2048
506
+ };
468
507
  }
469
508
  } else {
470
- // 纯文本格式
471
- messages = [{ role: 'user', content: message }];
509
+ // 纯文本格式 - 统一使用 messages 格式
510
+ payload = {
511
+ model: 'openclaw',
512
+ messages: [{ role: 'user', content: message }],
513
+ stream: true,
514
+ max_tokens: 2048
515
+ };
472
516
  }
473
517
 
474
- const payload = {
475
- model: 'openclaw',
476
- messages: messages,
477
- stream: true,
478
- max_tokens: 2048
479
- };
480
-
481
518
  this.log?.info(`[OpenClawClient] SSE 请求 payload: ${JSON.stringify(payload)}`);
482
519
 
483
520
  let fullText = '';