claw-subagent-service 0.0.86 → 0.0.87

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.
@@ -30,17 +30,58 @@ is_docker() {
30
30
 
31
31
  # 获取 openclaw 进程 PID
32
32
  get_openclaw_pid() {
33
- # 只通过端口查找进程(最可靠,避免僵尸进程和误匹配)
33
+ local port=18789
34
+ local pid=""
35
+
36
+ # 按优先级尝试多种工具(适配精简 Docker 镜像)
37
+ if command -v lsof &>/dev/null; then
38
+ pid=$(lsof -i :${port} -t 2>/dev/null | head -1)
39
+ if [ -n "$pid" ]; then
40
+ echo "$pid"
41
+ return
42
+ fi
43
+ fi
44
+
45
+ if command -v fuser &>/dev/null; then
46
+ pid=$(fuser ${port}/tcp 2>/dev/null | tr -d ' ')
47
+ if [ -n "$pid" ]; then
48
+ echo "$pid"
49
+ return
50
+ fi
51
+ fi
52
+
53
+ if command -v ss &>/dev/null; then
54
+ pid=$(ss -tlnp 2>/dev/null | grep ":${port} " | head -1 | sed -n 's/.*pid=\\([0-9]*\\).*/\\1/p')
55
+ if [ -n "$pid" ]; then
56
+ echo "$pid"
57
+ return
58
+ fi
59
+ fi
60
+
34
61
  if command -v netstat &>/dev/null; then
35
- local pid
36
- pid=$(netstat -tnlp 2>/dev/null | grep ":18789 " | head -1 | awk '{print $7}' | cut -d'/' -f1)
62
+ pid=$(netstat -tnlp 2>/dev/null | grep ":${port} " | head -1 | awk '{print $7}' | cut -d'/' -f1)
37
63
  if [ -n "$pid" ]; then
38
64
  echo "$pid"
39
65
  return
40
66
  fi
41
67
  fi
42
68
 
43
- # 没有监听端口,返回空(不再使用 pgrep 避免误匹配)
69
+ # 最后尝试 /proc 文件系统(最可靠,无需外部工具)
70
+ for proc_dir in /proc/[0-9]*; do
71
+ if [ -d "$proc_dir/fd" ]; then
72
+ for fd in $proc_dir/fd/*; do
73
+ if [ -L "$fd" ]; then
74
+ local target
75
+ target=$(readlink "$fd" 2>/dev/null)
76
+ if [ -n "$target" ] && echo "$target" | grep -q ":${port}"; then
77
+ basename "$proc_dir"
78
+ return
79
+ fi
80
+ fi
81
+ done
82
+ fi
83
+ done
84
+
44
85
  echo ""
45
86
  }
46
87
 
@@ -48,12 +89,21 @@ get_openclaw_pid() {
48
89
  check_port() {
49
90
  local port=$1
50
91
  if command -v ss &>/dev/null; then
51
- ss -tln | grep -q ":$port "
92
+ ss -tln 2>/dev/null | grep -q ":$port "
93
+ return $?
52
94
  elif command -v netstat &>/dev/null; then
53
- netstat -tln | grep -q ":$port "
95
+ netstat -tln 2>/dev/null | grep -q ":$port "
96
+ return $?
97
+ elif command -v lsof &>/dev/null; then
98
+ lsof -i :$port 2>/dev/null | grep -q LISTEN
99
+ return $?
100
+ elif command -v fuser &>/dev/null; then
101
+ fuser $port/tcp 2>/dev/null | grep -q '[0-9]'
102
+ return $?
54
103
  else
55
104
  # 降级:直接检查进程
56
105
  [ -n "$(get_openclaw_pid)" ]
106
+ return $?
57
107
  fi
58
108
  }
59
109
 
@@ -30,17 +30,58 @@ is_docker() {
30
30
 
31
31
  # 获取 openclaw 进程 PID
32
32
  get_openclaw_pid() {
33
- # 只通过端口查找进程(最可靠,避免僵尸进程和误匹配)
33
+ local port=18789
34
+ local pid=""
35
+
36
+ # 按优先级尝试多种工具(适配精简 Docker 镜像)
37
+ if command -v lsof &>/dev/null; then
38
+ pid=$(lsof -i :${port} -t 2>/dev/null | head -1)
39
+ if [ -n "$pid" ]; then
40
+ echo "$pid"
41
+ return
42
+ fi
43
+ fi
44
+
45
+ if command -v fuser &>/dev/null; then
46
+ pid=$(fuser ${port}/tcp 2>/dev/null | tr -d ' ')
47
+ if [ -n "$pid" ]; then
48
+ echo "$pid"
49
+ return
50
+ fi
51
+ fi
52
+
53
+ if command -v ss &>/dev/null; then
54
+ pid=$(ss -tlnp 2>/dev/null | grep ":${port} " | head -1 | sed -n 's/.*pid=\\([0-9]*\\).*/\\1/p')
55
+ if [ -n "$pid" ]; then
56
+ echo "$pid"
57
+ return
58
+ fi
59
+ fi
60
+
34
61
  if command -v netstat &>/dev/null; then
35
- local pid
36
- pid=$(netstat -tnlp 2>/dev/null | grep ":18789 " | head -1 | awk '{print $7}' | cut -d'/' -f1)
62
+ pid=$(netstat -tnlp 2>/dev/null | grep ":${port} " | head -1 | awk '{print $7}' | cut -d'/' -f1)
37
63
  if [ -n "$pid" ]; then
38
64
  echo "$pid"
39
65
  return
40
66
  fi
41
67
  fi
42
68
 
43
- # 没有监听端口,返回空(不再使用 pgrep 避免误匹配)
69
+ # 最后尝试 /proc 文件系统(最可靠,无需外部工具)
70
+ for proc_dir in /proc/[0-9]*; do
71
+ if [ -d "$proc_dir/fd" ]; then
72
+ for fd in $proc_dir/fd/*; do
73
+ if [ -L "$fd" ]; then
74
+ local target
75
+ target=$(readlink "$fd" 2>/dev/null)
76
+ if [ -n "$target" ] && echo "$target" | grep -q ":${port}"; then
77
+ basename "$proc_dir"
78
+ return
79
+ fi
80
+ fi
81
+ done
82
+ fi
83
+ done
84
+
44
85
  echo ""
45
86
  }
46
87
 
@@ -48,12 +89,21 @@ get_openclaw_pid() {
48
89
  check_port() {
49
90
  local port=$1
50
91
  if command -v ss &>/dev/null; then
51
- ss -tln | grep -q ":$port "
92
+ ss -tln 2>/dev/null | grep -q ":$port "
93
+ return $?
52
94
  elif command -v netstat &>/dev/null; then
53
- netstat -tln | grep -q ":$port "
95
+ netstat -tln 2>/dev/null | grep -q ":$port "
96
+ return $?
97
+ elif command -v lsof &>/dev/null; then
98
+ lsof -i :$port 2>/dev/null | grep -q LISTEN
99
+ return $?
100
+ elif command -v fuser &>/dev/null; then
101
+ fuser $port/tcp 2>/dev/null | grep -q '[0-9]'
102
+ return $?
54
103
  else
55
104
  # 降级:直接检查进程
56
105
  [ -n "$(get_openclaw_pid)" ]
106
+ return $?
57
107
  fi
58
108
  }
59
109
 
@@ -44,17 +44,58 @@ is_docker() {
44
44
 
45
45
  # 获取 openclaw 进程 PID
46
46
  get_openclaw_pid() {
47
- # 只通过端口查找进程(最可靠,避免僵尸进程和误匹配)
47
+ local port=18789
48
+ local pid=""
49
+
50
+ # 按优先级尝试多种工具(适配精简 Docker 镜像)
51
+ if command -v lsof &>/dev/null; then
52
+ pid=$(lsof -i :${port} -t 2>/dev/null | head -1)
53
+ if [ -n "$pid" ]; then
54
+ echo "$pid"
55
+ return
56
+ fi
57
+ fi
58
+
59
+ if command -v fuser &>/dev/null; then
60
+ pid=$(fuser ${port}/tcp 2>/dev/null | tr -d ' ')
61
+ if [ -n "$pid" ]; then
62
+ echo "$pid"
63
+ return
64
+ fi
65
+ fi
66
+
67
+ if command -v ss &>/dev/null; then
68
+ pid=$(ss -tlnp 2>/dev/null | grep ":${port} " | head -1 | sed -n 's/.*pid=\([0-9]*\).*/\1/p')
69
+ if [ -n "$pid" ]; then
70
+ echo "$pid"
71
+ return
72
+ fi
73
+ fi
74
+
48
75
  if command -v netstat &>/dev/null; then
49
- local pid
50
- pid=$(netstat -tnlp 2>/dev/null | grep ":18789 " | head -1 | awk '{print $7}' | cut -d'/' -f1)
76
+ pid=$(netstat -tnlp 2>/dev/null | grep ":${port} " | head -1 | awk '{print $7}' | cut -d'/' -f1)
51
77
  if [ -n "$pid" ]; then
52
78
  echo "$pid"
53
79
  return
54
80
  fi
55
81
  fi
56
82
 
57
- # 没有监听端口,返回空(不再使用 pgrep 避免误匹配)
83
+ # 最后尝试 /proc 文件系统(最可靠,无需外部工具)
84
+ for proc_dir in /proc/[0-9]*; do
85
+ if [ -d "$proc_dir/fd" ]; then
86
+ for fd in $proc_dir/fd/*; do
87
+ if [ -L "$fd" ]; then
88
+ local target
89
+ target=$(readlink "$fd" 2>/dev/null)
90
+ if [ -n "$target" ] && echo "$target" | grep -q ":${port}"; then
91
+ basename "$proc_dir"
92
+ return
93
+ fi
94
+ fi
95
+ done
96
+ fi
97
+ done
98
+
58
99
  echo ""
59
100
  }
60
101
 
@@ -62,12 +103,21 @@ get_openclaw_pid() {
62
103
  check_port() {
63
104
  local port=$1
64
105
  if command -v ss &>/dev/null; then
65
- ss -tln | grep -q ":$port "
106
+ ss -tln 2>/dev/null | grep -q ":$port "
107
+ return $?
66
108
  elif command -v netstat &>/dev/null; then
67
- netstat -tln | grep -q ":$port "
109
+ netstat -tln 2>/dev/null | grep -q ":$port "
110
+ return $?
111
+ elif command -v lsof &>/dev/null; then
112
+ lsof -i :$port 2>/dev/null | grep -q LISTEN
113
+ return $?
114
+ elif command -v fuser &>/dev/null; then
115
+ fuser $port/tcp 2>/dev/null | grep -q '[0-9]'
116
+ return $?
68
117
  else
69
118
  # 降级:直接检查进程
70
119
  [ -n "$(get_openclaw_pid)" ]
120
+ return $?
71
121
  fi
72
122
  }
73
123
 
@@ -42,27 +42,79 @@ PORT="18789"
42
42
  # 检查端口是否监听
43
43
  check_port() {
44
44
  local port=$1
45
- if command -v netstat &>/dev/null; then
46
- netstat -tnlp 2>/dev/null | grep -q ":$port "
45
+ if command -v ss &>/dev/null; then
46
+ ss -tln 2>/dev/null | grep -q ":$port "
47
+ return $?
48
+ elif command -v netstat &>/dev/null; then
49
+ netstat -tln 2>/dev/null | grep -q ":$port "
50
+ return $?
51
+ elif command -v lsof &>/dev/null; then
52
+ lsof -i :$port 2>/dev/null | grep -q LISTEN
53
+ return $?
54
+ elif command -v fuser &>/dev/null; then
55
+ fuser $port/tcp 2>/dev/null | grep -q '[0-9]'
56
+ return $?
47
57
  else
48
- # 降级:直接检查进程
58
+ # 最后降级:直接检查进程
49
59
  [ -n "$(get_openclaw_pid)" ]
60
+ return $?
50
61
  fi
51
62
  }
52
63
 
53
64
  # 获取 openclaw 进程 PID
54
65
  get_openclaw_pid() {
55
- # 只通过端口查找进程(最可靠,避免僵尸进程和误匹配)
66
+ local port=18789
67
+ local pid=""
68
+
69
+ # 按优先级尝试多种工具(适配精简 Docker 镜像)
70
+ if command -v lsof &>/dev/null; then
71
+ pid=$(lsof -i :${port} -t 2>/dev/null | head -1)
72
+ if [ -n "$pid" ]; then
73
+ echo "$pid"
74
+ return
75
+ fi
76
+ fi
77
+
78
+ if command -v fuser &>/dev/null; then
79
+ pid=$(fuser ${port}/tcp 2>/dev/null | tr -d ' ')
80
+ if [ -n "$pid" ]; then
81
+ echo "$pid"
82
+ return
83
+ fi
84
+ fi
85
+
86
+ if command -v ss &>/dev/null; then
87
+ pid=$(ss -tlnp 2>/dev/null | grep ":${port} " | head -1 | sed -n 's/.*pid=\\([0-9]*\\).*/\\1/p')
88
+ if [ -n "$pid" ]; then
89
+ echo "$pid"
90
+ return
91
+ fi
92
+ fi
93
+
56
94
  if command -v netstat &>/dev/null; then
57
- local pid
58
- pid=$(netstat -tnlp 2>/dev/null | grep ":18789 " | head -1 | awk '{print $7}' | cut -d'/' -f1)
95
+ pid=$(netstat -tnlp 2>/dev/null | grep ":${port} " | head -1 | awk '{print $7}' | cut -d'/' -f1)
59
96
  if [ -n "$pid" ]; then
60
97
  echo "$pid"
61
98
  return
62
99
  fi
63
100
  fi
64
101
 
65
- # 没有监听端口,返回空(不再使用 pgrep 避免误匹配)
102
+ # 最后尝试 /proc 文件系统(最可靠,无需外部工具)
103
+ for proc_dir in /proc/[0-9]*; do
104
+ if [ -d "$proc_dir/fd" ]; then
105
+ for fd in $proc_dir/fd/*; do
106
+ if [ -L "$fd" ]; then
107
+ local target
108
+ target=$(readlink "$fd" 2>/dev/null)
109
+ if [ -n "$target" ] && echo "$target" | grep -q ":${port}"; then
110
+ basename "$proc_dir"
111
+ return
112
+ fi
113
+ fi
114
+ done
115
+ fi
116
+ done
117
+
66
118
  echo ""
67
119
  }
68
120
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claw-subagent-service",
3
- "version": "0.0.86",
3
+ "version": "0.0.87",
4
4
  "description": "虾说智能助手",
5
5
  "main": "cli.js",
6
6
  "bin": {
@@ -25,6 +25,7 @@ class RongyunMessageHandler {
25
25
  this.config = config;
26
26
  this.log = log;
27
27
  this.commandLock = false;
28
+ this.commandLockTimer = null;
28
29
  this.messageSender = null;
29
30
  }
30
31
 
@@ -126,6 +127,13 @@ class RongyunMessageHandler {
126
127
  }
127
128
 
128
129
  this.commandLock = true;
130
+ // 设置 60 秒超时保护,防止命令永久卡住导致锁无法释放
131
+ this.commandLockTimer = setTimeout(() => {
132
+ this.logWarn('[RongyunMessageHandler] 命令锁超时(60秒),自动释放');
133
+ this.commandLock = false;
134
+ this.commandLockTimer = null;
135
+ }, 60000);
136
+
129
137
  try {
130
138
  await executeCommand(command, null, async (response) => {
131
139
  // 增加短暂延迟,避免融云 SDK 在收到消息后立刻回复时消息丢失
@@ -146,6 +154,10 @@ class RongyunMessageHandler {
146
154
  }, requestId, sourceId);
147
155
  } finally {
148
156
  this.commandLock = false;
157
+ if (this.commandLockTimer) {
158
+ clearTimeout(this.commandLockTimer);
159
+ this.commandLockTimer = null;
160
+ }
149
161
  }
150
162
  }
151
163
 
@@ -285,15 +285,6 @@ class ScriptExecutor {
285
285
  }
286
286
  });
287
287
 
288
- // 错误处理
289
- child.on('error', (err) => {
290
- console.error(`[ScriptExecutor] 子进程错误: ${err.message}`);
291
- if (!killed) {
292
- killed = true;
293
- clearTimeout(timer);
294
- reject(err);
295
- }
296
- });
297
288
  });
298
289
  }
299
290
 
@@ -356,6 +347,7 @@ class ScriptExecutor {
356
347
 
357
348
  if (
358
349
  upper.includes('OPENCLAW COMMAND NOT FOUND') ||
350
+ upper.includes('OPENCLAW 命令未找到') ||
359
351
  output.includes('服务 openclaw-gateway.service 未安装') ||
360
352
  output.includes('服务 openclaw-gateway.service 不存在') ||
361
353
  upper.includes('OPENCLAW-GATEWAY.SERVICE 不存在')