claw-subagent-service 0.0.0

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.
Files changed (48) hide show
  1. package/README.md +44 -0
  2. package/cli.js +254 -0
  3. package/command/linux/restart.sh +98 -0
  4. package/command/linux/start.sh +101 -0
  5. package/command/linux/status.sh +140 -0
  6. package/command/linux/stop.sh +112 -0
  7. package/command/win/restart.bat +39 -0
  8. package/command/win/start.bat +65 -0
  9. package/command/win/status.bat +52 -0
  10. package/command/win/stop.bat +55 -0
  11. package/command/win/windows/345/220/257/345/212/250/350/204/232/346/234/254 +0 -0
  12. package/package.json +37 -0
  13. package/scripts/install-silent.js +167 -0
  14. package/scripts/uninstall.js +61 -0
  15. package/service/daemon.js +189 -0
  16. package/service/logger.js +31 -0
  17. package/service/modules/auth.js +17 -0
  18. package/service/modules/business-message-handler.js +118 -0
  19. package/service/modules/command-handler.js +152 -0
  20. package/service/modules/config.js +44 -0
  21. package/service/modules/dashboard-collector.js +588 -0
  22. package/service/modules/heartbeat-dashboard.js +153 -0
  23. package/service/modules/mac-address.js +15 -0
  24. package/service/modules/message-processor-example.js +72 -0
  25. package/service/modules/message-processor.js +62 -0
  26. package/service/modules/normal-message-handler.js +60 -0
  27. package/service/modules/openclaw-control.js +128 -0
  28. package/service/modules/openclaw-enum.js +48 -0
  29. package/service/modules/opencode-service.js +199 -0
  30. package/service/modules/opencode-starter.js +194 -0
  31. package/service/modules/port-checker.js +31 -0
  32. package/service/modules/rongyun-message-handler.js +250 -0
  33. package/service/modules/rongyun-message-sender.js +157 -0
  34. package/service/modules/rongyun-message-types.js +28 -0
  35. package/service/modules/script-executor.js +550 -0
  36. package/service/modules/service-manager.js +319 -0
  37. package/service/modules/structured-message-router.js +118 -0
  38. package/service/rongcloud/env-polyfill.js +95 -0
  39. package/service/rongcloud/index.js +19 -0
  40. package/service/rongcloud/message-handler.js +147 -0
  41. package/service/rongcloud/message-types.js +22 -0
  42. package/service/rongcloud/openclaw-client.js +98 -0
  43. package/service/rongcloud/openclaw-config.js +108 -0
  44. package/service/rongcloud/rongcloud-client.js +273 -0
  45. package/service/rongcloud/types.js +9 -0
  46. package/service/updater.js +348 -0
  47. package/service/worker.js +376 -0
  48. package/version.json +4 -0
@@ -0,0 +1,112 @@
1
+ #!/bin/bash
2
+
3
+ # OpenClaw 服务停止脚本
4
+ # 用法: ./stop.sh [选项]
5
+
6
+ set -e
7
+
8
+ # 颜色定义
9
+ RED='\033[0;31m'
10
+ GREEN='\033[0;32m'
11
+ YELLOW='\033[1;33m'
12
+ NC='\033[0m' # No Color
13
+
14
+ # 日志函数
15
+ log_info() {
16
+ echo -e "${GREEN}[INFO]${NC} $1"
17
+ }
18
+
19
+ log_warn() {
20
+ echo -e "${YELLOW}[WARN]${NC} $1"
21
+ }
22
+
23
+ log_error() {
24
+ echo -e "${RED}[ERROR]${NC} $1"
25
+ }
26
+
27
+ # 服务名称
28
+ SERVICE_NAME="openclaw-gateway.service"
29
+
30
+ # 检查服务是否存在
31
+ check_service() {
32
+ if ! systemctl --user list-unit-files "$SERVICE_NAME" &>/dev/null; then
33
+ log_error "服务 $SERVICE_NAME 不存在。"
34
+ exit 1
35
+ fi
36
+ }
37
+
38
+ # 显示帮助信息
39
+ show_help() {
40
+ echo "OpenClaw 服务停止脚本"
41
+ echo ""
42
+ echo "用法: $0 [选项]"
43
+ echo ""
44
+ echo "选项:"
45
+ echo " -f, --force 强制停止服务"
46
+ echo " -h, --help 显示此帮助信息"
47
+ echo ""
48
+ echo "示例:"
49
+ echo " $0 正常停止服务"
50
+ echo " $0 -f 强制停止服务"
51
+ }
52
+
53
+ # 主函数
54
+ main() {
55
+ local force=""
56
+
57
+ # 解析命令行参数
58
+ while [[ $# -gt 0 ]]; do
59
+ case $1 in
60
+ -f|--force)
61
+ force="--force"
62
+ shift
63
+ ;;
64
+ -h|--help)
65
+ show_help
66
+ exit 0
67
+ ;;
68
+ *)
69
+ log_error "未知选项: $1"
70
+ show_help
71
+ exit 1
72
+ ;;
73
+ esac
74
+ done
75
+
76
+ # 检查服务是否存在
77
+ check_service
78
+
79
+ # 检查服务状态
80
+ log_info "检查 OpenClaw 服务状态..."
81
+ if systemctl --user is-active --quiet "$SERVICE_NAME"; then
82
+ log_info "OpenClaw 服务正在运行,准备停止..."
83
+ else
84
+ log_warn "OpenClaw 服务未在运行。"
85
+ exit 0
86
+ fi
87
+
88
+ # 停止服务
89
+ log_info "正在停止 OpenClaw 服务..."
90
+
91
+ if systemctl --user stop "$SERVICE_NAME"; then
92
+ log_info "OpenClaw 服务停止成功!"
93
+
94
+ # 等待服务完全停止
95
+ sleep 2
96
+
97
+ # 验证服务状态
98
+ if systemctl --user is-active --quiet "$SERVICE_NAME"; then
99
+ log_warn "服务可能仍在运行,请检查进程。"
100
+ systemctl --user status "$SERVICE_NAME" --no-pager
101
+ else
102
+ log_info "服务已成功停止。"
103
+ log_info "Success"
104
+ fi
105
+ else
106
+ log_error "OpenClaw 服务停止失败!"
107
+ exit 1
108
+ fi
109
+ }
110
+
111
+ # 执行主函数
112
+ main "$@"
@@ -0,0 +1,39 @@
1
+ @echo off
2
+ echo ==========================================
3
+ echo OpenClaw Service Restart Script
4
+ echo ==========================================
5
+ echo.
6
+
7
+ REM Get the directory where this script is located
8
+ set "SCRIPT_DIR=%~dp0"
9
+
10
+ echo [INFO] Step 1: Stopping service...
11
+ call "%SCRIPT_DIR%stop.bat"
12
+ if errorlevel 1 (
13
+ echo [WARN] Stop returned error, continuing...
14
+ )
15
+
16
+ echo.
17
+ echo [INFO] Step 2: Waiting for service to stop...
18
+ timeout /t 3 /nobreak >nul
19
+
20
+ REM Verify stopped
21
+ openclaw gateway status 2>&1 | findstr /C:"RPC probe: ok" >nul
22
+ if errorlevel 1 (
23
+ echo [OK] Service stopped
24
+ ) else (
25
+ echo [WARN] Service may still be running, proceeding anyway
26
+ )
27
+
28
+ echo.
29
+ echo [INFO] Step 3: Starting service...
30
+ call "%SCRIPT_DIR%start.bat"
31
+ if errorlevel 1 (
32
+ echo [ERROR] Start failed
33
+ exit /b 1
34
+ )
35
+
36
+ echo.
37
+ echo [OK] Restart completed successfully
38
+ echo Success
39
+ exit /b 0
@@ -0,0 +1,65 @@
1
+ @echo off
2
+ echo ==========================================
3
+ echo OpenClaw Service Start Script
4
+ echo ==========================================
5
+ echo.
6
+
7
+ REM Check if openclaw exists
8
+ where openclaw >nul 2>&1
9
+ if errorlevel 1 (
10
+ echo [ERROR] openclaw command not found in PATH
11
+ exit /b 1
12
+ )
13
+
14
+ echo [OK] openclaw command found
15
+ echo.
16
+
17
+ REM Check if service is already running
18
+ netstat -an | findstr ":18789 " | findstr "LISTENING" >nul
19
+ if not errorlevel 1 (
20
+ echo [INFO] OpenClaw is already running
21
+ echo [INFO] Dashboard URL: http://127.0.0.1:18789/
22
+ echo.
23
+ echo Success
24
+ exit /b 0
25
+ )
26
+
27
+ echo [INFO] OpenClaw is not running
28
+ echo.
29
+ echo Starting OpenClaw service...
30
+ echo.
31
+
32
+ REM Start openclaw gateway using START (creates new process, no waiting)
33
+ echo [INFO] Launching openclaw gateway...
34
+ start "OpenClaw Gateway" /min cmd /c "openclaw gateway"
35
+
36
+ echo [OK] Start command sent
37
+ echo.
38
+ echo Waiting for service to start...
39
+ echo.
40
+
41
+ REM Wait loop - max 60 seconds
42
+ REM Using ping for delay instead of timeout (more compatible with redirected stdout)
43
+ set /a count=0
44
+ :LOOP
45
+ set /a count+=1
46
+ if %count% gtr 30 (
47
+ echo [ERROR] Timeout waiting for service to start
48
+ exit /b 1
49
+ )
50
+
51
+ REM Use ping for 2 second delay (more reliable than timeout when stdout is redirected)
52
+ ping -n 3 127.0.0.1 >nul 2>&1
53
+
54
+ REM Check if service is ready
55
+ netstat -an | findstr ":18789 " | findstr "LISTENING" >nul
56
+ if not errorlevel 1 (
57
+ echo [OK] Service is running
58
+ echo [INFO] Dashboard URL: http://127.0.0.1:18789/
59
+ echo.
60
+ echo Success
61
+ exit /b 0
62
+ )
63
+
64
+ echo Waiting... (%count%/30)
65
+ goto LOOP
@@ -0,0 +1,52 @@
1
+ @echo off
2
+ echo ==========================================
3
+ echo OpenClaw Service Status Script
4
+ echo ==========================================
5
+ echo.
6
+
7
+ set QUIET=
8
+ if "%~1"=="-q" set QUIET=1
9
+ if "%~1"=="--quiet" set QUIET=1
10
+
11
+ REM Check if openclaw exists
12
+ where openclaw >nul 2>&1
13
+ if errorlevel 1 (
14
+ if defined QUIET (
15
+ echo not_installed
16
+ ) else (
17
+ echo [ERROR] openclaw command not found in PATH
18
+ )
19
+ exit /b 1
20
+ )
21
+
22
+ if defined QUIET (
23
+ netstat -an | findstr ":18789 " | findstr "LISTENING" >nul
24
+ if errorlevel 1 (
25
+ echo stopped
26
+ ) else (
27
+ echo running
28
+ )
29
+ exit /b 0
30
+ )
31
+
32
+ echo === OpenClaw Status ===
33
+ echo.
34
+
35
+ REM Check if port 18789 is listening (simple check)
36
+ netstat -an | findstr ":18789 " | findstr "LISTENING" >nul
37
+ if errorlevel 1 (
38
+ echo [INFO] Status: Not running
39
+ echo.
40
+ echo [ERROR] OpenClaw service is not running
41
+ exit /b 1
42
+ )
43
+
44
+ REM Service is running, now get detailed status
45
+ cmd /c openclaw gateway status
46
+
47
+ echo.
48
+ echo ==========================================
49
+ echo [INFO] Status: Running
50
+ echo.
51
+ echo Success
52
+ exit /b 0
@@ -0,0 +1,55 @@
1
+ @echo off
2
+ echo ==========================================
3
+ echo OpenClaw Service Stop Script
4
+ echo ==========================================
5
+ echo.
6
+
7
+ set FORCE=
8
+ if "%~1"=="-f" set FORCE=1
9
+ if "%~1"=="--force" set FORCE=1
10
+
11
+ REM Check if openclaw exists
12
+ where openclaw >nul 2>&1
13
+ if errorlevel 1 (
14
+ echo [ERROR] openclaw command not found in PATH
15
+ exit /b 1
16
+ )
17
+
18
+ REM Check if service is running (using port detection)
19
+ netstat -an | findstr ":18789 " | findstr "LISTENING" >nul
20
+ if errorlevel 1 (
21
+ echo [INFO] OpenClaw is not running
22
+ exit /b 0
23
+ )
24
+
25
+ echo [INFO] OpenClaw is running
26
+ echo [INFO] Stopping service...
27
+ echo.
28
+
29
+ if defined FORCE (
30
+ echo [INFO] Force stopping...
31
+ taskkill /f /im openclaw.exe >nul 2>&1
32
+ taskkill /f /im node.exe >nul 2>&1
33
+ ) else (
34
+ REM Simple stop command without extra cmd wrapper
35
+ openclaw gateway stop
36
+ )
37
+
38
+ echo.
39
+ echo [OK] Stop command executed
40
+ echo Waiting for service to stop...
41
+ echo.
42
+
43
+ REM Wait and verify stopped
44
+ timeout /t 3 /nobreak >nul
45
+
46
+ netstat -an | findstr ":18789 " | findstr "LISTENING" >nul
47
+ if errorlevel 1 (
48
+ echo [OK] Service stopped successfully
49
+ echo.
50
+ echo Success
51
+ exit /b 0
52
+ ) else (
53
+ echo [WARN] Service may still be running
54
+ exit /b 0
55
+ )
package/package.json ADDED
@@ -0,0 +1,37 @@
1
+ {
2
+ "name": "claw-subagent-service",
3
+ "version": "0.0.0",
4
+ "description": "claw-subagent-service 静默后台服务,开机自启,崩溃自动恢复,支持自动更新和融云消息监听",
5
+ "main": "cli.js",
6
+ "bin": {
7
+ "claw-subagent-service": "cli.js"
8
+ },
9
+ "scripts": {
10
+ "install-service": "node scripts/install-silent.js",
11
+ "uninstall-service": "node scripts/uninstall.js",
12
+ "dev": "nodemon cli.js --run",
13
+ "publish:patch": "npm version patch && npm publish",
14
+ "publish:minor": "npm version minor && npm publish",
15
+ "publish:major": "npm version major && npm publish"
16
+ },
17
+ "files": [
18
+ "cli.js",
19
+ "service/",
20
+ "scripts/",
21
+ "command/",
22
+ "version.json",
23
+ "README.md"
24
+ ],
25
+ "dependencies": {
26
+ "@rongcloud/imlib-next": "^5.36.6",
27
+ "axios": "^1.15.2",
28
+ "fake-indexeddb": "^6.2.5",
29
+ "jsdom": "^24.0.0",
30
+ "node-windows": "^1.0.0-beta.8",
31
+ "ws": "^8.16.0"
32
+ },
33
+ "engines": {
34
+ "node": ">=14.0.0"
35
+ },
36
+ "license": "MIT"
37
+ }
@@ -0,0 +1,167 @@
1
+ const { Service } = require('node-windows');
2
+ const path = require('path');
3
+ const { exec } = require('child_process');
4
+ const fs = require('fs');
5
+
6
+ const ROOT = process.argv[2] || process.env.SILENT_SERVICE_DIR || path.join(__dirname, '..');
7
+ const DAEMON_PATH = path.join(ROOT, 'service', 'daemon.js');
8
+ const SERVICE_NAME = 'SilentNodeService';
9
+ const LOG_FILE = path.join(ROOT, 'logs', 'install.log');
10
+
11
+ if (!fs.existsSync(path.dirname(LOG_FILE))) {
12
+ fs.mkdirSync(path.dirname(LOG_FILE), { recursive: true });
13
+ }
14
+
15
+ const log = (msg) => {
16
+ const line = `[${new Date().toISOString()}] ${msg}\n`;
17
+ fs.appendFileSync(LOG_FILE, line);
18
+ console.log(msg);
19
+ };
20
+
21
+ const platform = process.platform;
22
+
23
+ function done(code, label) {
24
+ if (label) log(label);
25
+ setTimeout(() => process.exit(code), 500);
26
+ }
27
+
28
+ if (platform === 'win32') {
29
+ exec('net session', (err) => {
30
+ if (err) {
31
+ const msg = '错误:请以管理员身份运行此脚本';
32
+ fs.writeFileSync(LOG_FILE, `[${new Date().toISOString()}] ${msg}\n`);
33
+ console.error(msg);
34
+ process.exit(1);
35
+ }
36
+
37
+ let completed = false;
38
+ function finish(code, label) {
39
+ if (!completed) {
40
+ completed = true;
41
+ done(code, label);
42
+ }
43
+ }
44
+
45
+ // 兜底超时
46
+ setTimeout(() => finish(1, '安装操作超时'), 60000);
47
+
48
+ const svc = new Service({
49
+ name: SERVICE_NAME,
50
+ description: 'Node.js 静默后台服务(开机自启/崩溃自动恢复/自动更新)',
51
+ script: DAEMON_PATH,
52
+ wait: 2,
53
+ grow: 0.5,
54
+ abortOnError: false
55
+ });
56
+
57
+ svc.on('install', () => {
58
+ log('服务安装成功,正在启动...');
59
+ svc.start();
60
+
61
+ const cmd = `sc failure "${SERVICE_NAME}" reset= 0 actions= restart/0/restart/0/restart/0`;
62
+ exec(cmd, (err) => {
63
+ if (err) log(`设置恢复策略失败: ${err.message}`);
64
+ else log('恢复策略已设置:服务崩溃后系统自动无限重启');
65
+ });
66
+
67
+ exec(`sc config "${SERVICE_NAME}" start= auto`, (err) => {
68
+ if (err) log(`设置自动启动失败: ${err.message}`);
69
+ else log('启动类型已设为:自动');
70
+ });
71
+ });
72
+
73
+ svc.on('alreadyinstalled', () => {
74
+ log('服务已存在,尝试启动...');
75
+ svc.start();
76
+ });
77
+
78
+ svc.on('start', () => {
79
+ log('服务已启动');
80
+ finish(0);
81
+ });
82
+
83
+ svc.on('error', (err) => {
84
+ log(`安装错误: ${err.message}`);
85
+ finish(1);
86
+ });
87
+
88
+ log('开始安装服务...');
89
+ svc.install();
90
+ });
91
+ } else if (platform === 'linux') {
92
+ const serviceFile = `/etc/systemd/system/${SERVICE_NAME}.service`;
93
+ const serviceContent = `[Unit]
94
+ Description=Node.js 静默后台服务(开机自启/崩溃自动恢复/自动更新)
95
+ After=network.target
96
+
97
+ [Service]
98
+ Type=simple
99
+ ExecStart=/usr/bin/node ${DAEMON_PATH}
100
+ Restart=always
101
+ RestartSec=10
102
+ WorkingDirectory=${path.dirname(DAEMON_PATH)}
103
+ Environment="SILENT_SERVICE_DIR=${ROOT}"
104
+
105
+ [Install]
106
+ WantedBy=multi-user.target
107
+ `;
108
+
109
+ try {
110
+ fs.writeFileSync(serviceFile, serviceContent);
111
+ exec('systemctl daemon-reload && systemctl enable ' + SERVICE_NAME, (err) => {
112
+ if (err) {
113
+ done(1, `安装失败: ${err.message}`);
114
+ } else {
115
+ log('服务安装成功');
116
+ exec('systemctl start ' + SERVICE_NAME, (err2) => {
117
+ if (err2) {
118
+ done(1, `启动失败: ${err2.message}`);
119
+ } else {
120
+ done(0, '服务已启动');
121
+ }
122
+ });
123
+ }
124
+ });
125
+ } catch (err) {
126
+ done(1, `安装失败: ${err.message}`);
127
+ }
128
+ } else if (platform === 'darwin') {
129
+ const plistFile = `/Library/LaunchDaemons/${SERVICE_NAME}.plist`;
130
+ const plistContent = `<?xml version="1.0" encoding="UTF-8"?>
131
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
132
+ <plist version="1.0">
133
+ <dict>
134
+ <key>Label</key>
135
+ <string>${SERVICE_NAME}</string>
136
+ <key>ProgramArguments</key>
137
+ <array>
138
+ <string>/usr/local/bin/node</string>
139
+ <string>${DAEMON_PATH}</string>
140
+ </array>
141
+ <key>RunAtLoad</key>
142
+ <true/>
143
+ <key>KeepAlive</key>
144
+ <true/>
145
+ <key>EnvironmentVariables</key>
146
+ <dict>
147
+ <key>SILENT_SERVICE_DIR</key>
148
+ <string>${ROOT}</string>
149
+ </dict>
150
+ </dict>
151
+ </plist>`;
152
+
153
+ try {
154
+ fs.writeFileSync(plistFile, plistContent);
155
+ exec(`launchctl load ${plistFile} && launchctl start ${SERVICE_NAME}`, (err) => {
156
+ if (err) {
157
+ done(1, `安装失败: ${err.message}`);
158
+ } else {
159
+ done(0, '服务安装成功并已启动');
160
+ }
161
+ });
162
+ } catch (err) {
163
+ done(1, `安装失败: ${err.message}`);
164
+ }
165
+ } else {
166
+ done(1, `不支持的平台: ${platform}`);
167
+ }
@@ -0,0 +1,61 @@
1
+ const { Service } = require('node-windows');
2
+ const path = require('path');
3
+ const { exec } = require('child_process');
4
+ const fs = require('fs');
5
+
6
+ const ROOT = process.argv[2] || process.env.SILENT_SERVICE_DIR || path.join(__dirname, '..');
7
+ const SERVICE_NAME = 'SilentNodeService';
8
+ const platform = process.platform;
9
+
10
+ function done(code, label) {
11
+ if (label) console.log(label);
12
+ setTimeout(() => process.exit(code), 500);
13
+ }
14
+
15
+ if (platform === 'win32') {
16
+ let completed = false;
17
+ function finish(code, label) {
18
+ if (!completed) {
19
+ completed = true;
20
+ done(code, label);
21
+ }
22
+ }
23
+
24
+ // 兜底超时
25
+ setTimeout(() => finish(1, '卸载操作超时'), 60000);
26
+
27
+ const svc = new Service({
28
+ name: SERVICE_NAME,
29
+ script: path.join(ROOT, 'service', 'daemon.js')
30
+ });
31
+
32
+ svc.on('uninstall', () => {
33
+ finish(0, '服务已卸载完成');
34
+ });
35
+
36
+ svc.on('error', (err) => {
37
+ finish(1, `卸载错误: ${err.message}`);
38
+ });
39
+
40
+ console.log('正在卸载服务...');
41
+ svc.uninstall();
42
+ } else if (platform === 'linux') {
43
+ exec(`systemctl stop "${SERVICE_NAME}" && systemctl disable "${SERVICE_NAME}" && rm -f /etc/systemd/system/${SERVICE_NAME}.service && systemctl daemon-reload`, (err) => {
44
+ if (err) {
45
+ done(1, `卸载失败: ${err.message}`);
46
+ } else {
47
+ done(0, '服务已卸载');
48
+ }
49
+ });
50
+ } else if (platform === 'darwin') {
51
+ const plistFile = `/Library/LaunchDaemons/${SERVICE_NAME}.plist`;
52
+ exec(`launchctl stop "${SERVICE_NAME}" && launchctl unload "${plistFile}" && rm -f "${plistFile}"`, (err) => {
53
+ if (err) {
54
+ done(1, `卸载失败: ${err.message}`);
55
+ } else {
56
+ done(0, '服务已卸载');
57
+ }
58
+ });
59
+ } else {
60
+ done(1, `不支持的平台: ${platform}`);
61
+ }