claw-subagent-service 0.0.153 → 0.0.154

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.153",
3
+ "version": "0.0.154",
4
4
  "description": "虾说智能助手",
5
5
  "main": "cli.js",
6
6
  "bin": {
@@ -10,7 +10,7 @@
10
10
  const { RongyunMessageTypeEnum } = require('./rongyun-message-types');
11
11
  const { OpenClawCommandEnum, getCommandName } = require('./openclaw-enum');
12
12
  const { executeCommand } = require('./openclaw-control');
13
- const { createOpencodeSession, deleteOpencodeSession, forwardChatMessage } = require('./opencode-service');
13
+ const { createOpencodeSession, deleteOpencodeSession, forwardChatMessage, getOrCreateGatewaySession } = require('./opencode-service');
14
14
  const { ServiceManager } = require('./service-manager');
15
15
  const { collectDashboardData } = require('./dashboard-collector');
16
16
  const { getOpenClawStatus } = require('./port-checker');
@@ -19,6 +19,34 @@ const fs = require('fs');
19
19
  const path = require('path');
20
20
  const os = require('os');
21
21
 
22
+ // 客服会话存储(内存缓存,生产环境建议用 Redis)
23
+ const serviceSessions = new Map();
24
+
25
+ // 客服系统提示词
26
+ const SERVICE_SYSTEM_PROMPT = `你是虾说App的智能客服助手,专门帮助用户解答使用问题。
27
+
28
+ ## 核心职责
29
+ 1. **解答产品使用问题**:帮助用户了解如何使用虾说App的各项功能
30
+ 2. **故障排查**:协助用户解决常见的技术问题
31
+ 3. **功能介绍**:介绍App的新功能和更新内容
32
+
33
+ ## 常用功能说明
34
+
35
+ | 功能 | 说明 |
36
+ |------|------|
37
+ | 会话 | 与好友进行一对一或群聊 |
38
+ | 通讯录 | 管理好友和群组 |
39
+ | 聊天室 | 加入公开聊天室 |
40
+ | 远程管理 | 管理远程设备 |
41
+ | AI助手 | 使用AI辅助功能 |
42
+
43
+ ## 回答原则
44
+ - 礼貌、专业、简洁
45
+ - 如果不知道答案,建议用户联系人工客服
46
+ - 不要透露系统内部信息
47
+ - 使用中文回答
48
+ `;
49
+
22
50
  class RongyunMessageHandler {
23
51
  constructor(rongcloudClient, config, log) {
24
52
  this.rongcloudClient = rongcloudClient;
@@ -99,6 +127,12 @@ class RongyunMessageHandler {
99
127
  case RongyunMessageTypeEnum.DEVICE_STATUS_REQUEST:
100
128
  await this.handleDeviceStatusRequest(data);
101
129
  break;
130
+ case RongyunMessageTypeEnum.CREATE_SERVICE_SESSION:
131
+ await this.handleCreateServiceSession(data);
132
+ break;
133
+ case RongyunMessageTypeEnum.SERVICE_CHAT_MESSAGE:
134
+ await this.handleServiceChatMessage(data);
135
+ break;
102
136
  default:
103
137
  this.logWarn(`未处理的消息类型: ${msgType}`);
104
138
  }
@@ -461,6 +495,136 @@ class RongyunMessageHandler {
461
495
  }
462
496
  }
463
497
 
498
+ async handleCreateServiceSession(data) {
499
+ const requestId = data.request_id;
500
+ const userId = data.userId || data.source_im_id;
501
+ const sourceId = data.source_im_id;
502
+
503
+ this.logInfo(`[RongyunMessageHandler] 创建客服会话, userId=${userId}, from=${sourceId}`);
504
+
505
+ try {
506
+ // 创建 OpenCode session 用于客服对话
507
+ const session = await createOpencodeSession(`客服会话-${userId}`);
508
+ const sessionId = session.id || session.session_id;
509
+
510
+ // 存储会话映射关系
511
+ serviceSessions.set(userId, {
512
+ sessionId: sessionId,
513
+ userId: userId,
514
+ createdAt: Date.now(),
515
+ });
516
+
517
+ this.logInfo(`[RongyunMessageHandler] 客服会话创建成功: ${sessionId}`);
518
+
519
+ await this.sendResponse(
520
+ RongyunMessageTypeEnum.SERVICE_SESSION_CREATED,
521
+ {
522
+ status: 'success',
523
+ sessionId: sessionId,
524
+ userId: userId,
525
+ },
526
+ requestId,
527
+ sourceId
528
+ );
529
+ } catch (e) {
530
+ const msg = e instanceof Error ? e.message : String(e);
531
+ this.logError(`创建客服会话失败: ${msg}`);
532
+ await this.sendResponse(
533
+ RongyunMessageTypeEnum.SERVICE_SESSION_CREATED,
534
+ {
535
+ status: 'error',
536
+ message: msg,
537
+ },
538
+ requestId,
539
+ sourceId
540
+ );
541
+ }
542
+ }
543
+
544
+ async handleServiceChatMessage(data) {
545
+ const requestId = data.request_id;
546
+ const userId = data.userId || data.source_im_id;
547
+ const sourceId = data.source_im_id;
548
+ const content = data.content || data._raw_content;
549
+
550
+ this.logInfo(`[RongyunMessageHandler] 收到客服消息, userId=${userId}, content=${content?.substring(0, 50)}`);
551
+
552
+ if (!content) {
553
+ this.logWarn('客服消息内容为空');
554
+ return;
555
+ }
556
+
557
+ try {
558
+ // 获取或创建用户会话
559
+ let sessionInfo = serviceSessions.get(userId);
560
+ let sessionId;
561
+
562
+ if (!sessionInfo) {
563
+ // 如果没有会话,创建一个
564
+ this.logInfo(`[RongyunMessageHandler] 用户 ${userId} 没有现有会话,创建新会话`);
565
+ const session = await createOpencodeSession(`客服会话-${userId}`);
566
+ sessionId = session.id || session.session_id;
567
+ serviceSessions.set(userId, {
568
+ sessionId: sessionId,
569
+ userId: userId,
570
+ createdAt: Date.now(),
571
+ });
572
+ } else {
573
+ sessionId = sessionInfo.sessionId;
574
+ }
575
+
576
+ this.logInfo(`[RongyunMessageHandler] 使用会话: ${sessionId}`);
577
+
578
+ // 调用 OpenCode 服务获取回复
579
+ let fullResponse = '';
580
+ await forwardChatMessage(
581
+ sessionId,
582
+ content,
583
+ (delta) => {
584
+ fullResponse += delta;
585
+ },
586
+ (level, message) => {
587
+ if (level === 'ERROR') {
588
+ this.logError(`[SERVICE-CHAT] ${message}`);
589
+ } else {
590
+ this.logInfo(`[SERVICE-CHAT] ${message}`);
591
+ }
592
+ },
593
+ 120000 // 2分钟超时
594
+ );
595
+
596
+ this.logInfo(`[RongyunMessageHandler] 客服回复生成完成, 长度: ${fullResponse.length}`);
597
+
598
+ // 发送客服回复给用户
599
+ await this.sendResponse(
600
+ RongyunMessageTypeEnum.SERVICE_CHAT_RESPONSE,
601
+ {
602
+ status: 'success',
603
+ content: fullResponse,
604
+ sessionId: sessionId,
605
+ userId: userId,
606
+ },
607
+ requestId,
608
+ sourceId
609
+ );
610
+ } catch (e) {
611
+ const msg = e instanceof Error ? e.message : String(e);
612
+ this.logError(`客服消息处理异常: ${msg}`);
613
+
614
+ // 发送错误回复
615
+ await this.sendResponse(
616
+ RongyunMessageTypeEnum.SERVICE_CHAT_RESPONSE,
617
+ {
618
+ status: 'error',
619
+ content: '抱歉,处理您的消息时出现问题,请稍后重试。',
620
+ userId: userId,
621
+ },
622
+ requestId,
623
+ sourceId
624
+ );
625
+ }
626
+ }
627
+
464
628
  async sendResponse(msgType, content, requestId, targetId) {
465
629
  if (!this.messageSender) {
466
630
  this.logError('MessageSender 未设置,无法发送响应');
@@ -26,7 +26,11 @@ const RongyunMessageTypeEnum = {
26
26
  DEVICE_CONTROL: "device_control",
27
27
  DEVICE_CONTROL_RESULT: "device_control_result",
28
28
  DEVICE_STATUS_REQUEST: "device_status_request",
29
- DEVICE_STATUS_REPORT: "device_status_report"
29
+ DEVICE_STATUS_REPORT: "device_status_report",
30
+ SERVICE_CHAT_MESSAGE: "service_chat_message",
31
+ SERVICE_CHAT_RESPONSE: "service_chat_response",
32
+ CREATE_SERVICE_SESSION: "create_service_session",
33
+ SERVICE_SESSION_CREATED: "service_session_created"
30
34
  };
31
35
 
32
36
  module.exports = { RongyunMessageTypeEnum };