claw-subagent-service 0.0.9 → 0.0.11
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/cli.js +9 -21
- package/package.json +2 -1
- package/scripts/install-silent.js +34 -39
- package/scripts/pre-uninstall.js +25 -0
- package/service/modules/service-manager.js +16 -31
- package/service/rongcloud/env-polyfill.js +1 -0
package/cli.js
CHANGED
|
@@ -50,26 +50,14 @@ function installService() {
|
|
|
50
50
|
const execPath = process.execPath;
|
|
51
51
|
|
|
52
52
|
if (platform === 'win32') {
|
|
53
|
-
// Windows:
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
workingdirectory: os.homedir(),
|
|
62
|
-
nodeOptions: ['--harmony', '--max_old_space_size=4096']
|
|
63
|
-
});
|
|
64
|
-
svc.on('install', () => { console.log('[CLI] 服务安装成功'); svc.start(); });
|
|
65
|
-
svc.on('error', (err) => { console.error(`[CLI] 服务安装失败: ${err.message}`); });
|
|
66
|
-
svc.install();
|
|
67
|
-
} catch (err) {
|
|
68
|
-
// 回退到 sc 命令(pkg 或无 node-windows 环境)
|
|
69
|
-
console.log('[CLI] 使用 sc 命令安装服务...');
|
|
70
|
-
const binPath = process.pkg
|
|
71
|
-
? `"${execPath}" --run`
|
|
72
|
-
: `"${execPath}" "${DAEMON_PATH}"`;
|
|
53
|
+
// Windows: 使用 sc 命令直接创建服务,避免 node-windows 在包目录生成被锁定的 wrapper
|
|
54
|
+
console.log('[CLI] 使用 sc 命令安装服务...');
|
|
55
|
+
const binPath = process.pkg
|
|
56
|
+
? `"${execPath}" --run`
|
|
57
|
+
: `"${execPath}" "${DAEMON_PATH}"`;
|
|
58
|
+
|
|
59
|
+
// 先停止并删除旧服务(避免文件锁)
|
|
60
|
+
exec(`net stop ${SERVICE_NAME} 2>nul & sc delete ${SERVICE_NAME} 2>nul`, () => {
|
|
73
61
|
exec(`sc create ${SERVICE_NAME} binPath= "${binPath}" start= auto displayname= "OpenClaw Guard"`, (err2) => {
|
|
74
62
|
if (err2) return console.error(`[CLI] 服务安装失败: ${err2.message}`);
|
|
75
63
|
console.log('[CLI] 服务安装成功');
|
|
@@ -77,7 +65,7 @@ function installService() {
|
|
|
77
65
|
if (err3) console.error(`[CLI] 启动服务失败: ${err3.message}`);
|
|
78
66
|
});
|
|
79
67
|
});
|
|
80
|
-
}
|
|
68
|
+
});
|
|
81
69
|
} else if (platform === 'linux') {
|
|
82
70
|
// Linux: systemd
|
|
83
71
|
const execStart = `/usr/bin/node ${DAEMON_PATH}`;
|
package/package.json
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claw-subagent-service",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.11",
|
|
4
4
|
"description": "虾说静态服务",
|
|
5
5
|
"main": "cli.js",
|
|
6
6
|
"bin": {
|
|
7
7
|
"claw-subagent-service": "cli.js"
|
|
8
8
|
},
|
|
9
9
|
"scripts": {
|
|
10
|
+
"preuninstall": "node scripts/pre-uninstall.js",
|
|
10
11
|
"install-service": "node scripts/install-silent.js",
|
|
11
12
|
"uninstall-service": "node scripts/uninstall.js",
|
|
12
13
|
"dev": "nodemon cli.js --run",
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
const { Service } = require('node-windows');
|
|
2
1
|
const path = require('path');
|
|
3
2
|
const { exec } = require('child_process');
|
|
4
3
|
const fs = require('fs');
|
|
@@ -45,48 +44,44 @@ if (platform === 'win32') {
|
|
|
45
44
|
// 兜底超时
|
|
46
45
|
setTimeout(() => finish(1, '安装操作超时'), 60000);
|
|
47
46
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
47
|
+
// 先停止并删除旧服务(避免文件锁导致更新失败)
|
|
48
|
+
exec(`net stop "${SERVICE_NAME}" 2>nul & sc delete "${SERVICE_NAME}" 2>nul`, () => {
|
|
49
|
+
const binPath = `"${process.execPath}" "${DAEMON_PATH}"`;
|
|
50
|
+
|
|
51
|
+
// 使用 sc create 创建服务,避免 node-windows 在包目录生成被锁定的 wrapper
|
|
52
|
+
const createCmd = `sc create "${SERVICE_NAME}" binPath= "${binPath}" start= auto displayname= "Node.js 静默后台服务"`;
|
|
53
|
+
exec(createCmd, (err) => {
|
|
54
|
+
if (err) {
|
|
55
|
+
log(`创建服务失败: ${err.message}`);
|
|
56
|
+
return finish(1, `创建服务失败: ${err.message}`);
|
|
57
|
+
}
|
|
58
|
+
log('服务注册成功');
|
|
59
|
+
|
|
60
|
+
// 设置恢复策略:崩溃后自动重启
|
|
61
|
+
const recoveryCmd = `sc failure "${SERVICE_NAME}" reset= 0 actions= restart/0/restart/0/restart/0`;
|
|
62
|
+
exec(recoveryCmd, (err) => {
|
|
63
|
+
if (err) log(`设置恢复策略失败: ${err.message}`);
|
|
64
|
+
else log('恢复策略已设置:服务崩溃后系统自动无限重启');
|
|
65
|
+
});
|
|
60
66
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
67
|
+
// 设置自动启动
|
|
68
|
+
exec(`sc config "${SERVICE_NAME}" start= auto`, (err) => {
|
|
69
|
+
if (err) log(`设置自动启动失败: ${err.message}`);
|
|
70
|
+
else log('启动类型已设为:自动');
|
|
71
|
+
});
|
|
66
72
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
73
|
+
// 启动服务
|
|
74
|
+
exec(`net start "${SERVICE_NAME}"`, (err) => {
|
|
75
|
+
if (err) {
|
|
76
|
+
log(`启动服务失败: ${err.message}`);
|
|
77
|
+
finish(1, `启动服务失败: ${err.message}`);
|
|
78
|
+
} else {
|
|
79
|
+
log('服务已启动');
|
|
80
|
+
finish(0, '服务安装成功并已启动');
|
|
81
|
+
}
|
|
82
|
+
});
|
|
70
83
|
});
|
|
71
84
|
});
|
|
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
85
|
});
|
|
91
86
|
} else if (platform === 'linux') {
|
|
92
87
|
const serviceFile = `/etc/systemd/system/${SERVICE_NAME}.service`;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* npm preuninstall 钩子
|
|
3
|
+
* 在卸载旧版本前停止并删除 Windows 服务,释放文件锁
|
|
4
|
+
*/
|
|
5
|
+
const { execSync } = require('child_process');
|
|
6
|
+
|
|
7
|
+
const SERVICES = ['SilentNodeService', 'claw-subagent-service'];
|
|
8
|
+
|
|
9
|
+
if (process.platform === 'win32') {
|
|
10
|
+
for (const name of SERVICES) {
|
|
11
|
+
try {
|
|
12
|
+
execSync(`net stop "${name}" 2>nul`, { stdio: 'ignore', timeout: 10000 });
|
|
13
|
+
} catch (e) {}
|
|
14
|
+
try {
|
|
15
|
+
execSync(`sc delete "${name}" 2>nul`, { stdio: 'ignore', timeout: 10000 });
|
|
16
|
+
} catch (e) {}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// 等待系统释放文件句柄
|
|
20
|
+
try {
|
|
21
|
+
execSync('timeout /t 2 /nobreak >nul 2>&1', { stdio: 'ignore', timeout: 5000 });
|
|
22
|
+
} catch (e) {}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
process.exit(0);
|
|
@@ -155,38 +155,23 @@ class ServiceManager {
|
|
|
155
155
|
}
|
|
156
156
|
}
|
|
157
157
|
|
|
158
|
-
// Windows
|
|
158
|
+
// Windows 服务安装(使用 sc 命令,避免 node-windows 在包目录生成被锁定的 wrapper)
|
|
159
159
|
async installWindows() {
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
return new Promise((resolve, reject) => {
|
|
177
|
-
svc.on('install', () => {
|
|
178
|
-
this.log?.info('[ServiceManager] Windows 服务安装成功');
|
|
179
|
-
svc.start();
|
|
180
|
-
resolve(true);
|
|
181
|
-
});
|
|
182
|
-
|
|
183
|
-
svc.on('error', (err) => {
|
|
184
|
-
this.log?.error(`[ServiceManager] Windows 服务安装失败: ${err.message}`);
|
|
185
|
-
reject(err);
|
|
186
|
-
});
|
|
187
|
-
|
|
188
|
-
svc.install();
|
|
189
|
-
});
|
|
160
|
+
const binPath = `"${process.execPath}" "${this.scriptPath}"`;
|
|
161
|
+
|
|
162
|
+
// 先停止并删除旧服务(避免文件锁导致更新失败)
|
|
163
|
+
try { await this.execCommand(`net stop "${this.serviceName}" 2>nul`); } catch (e) {}
|
|
164
|
+
try { await this.execCommand(`sc delete "${this.serviceName}" 2>nul`); } catch (e) {}
|
|
165
|
+
|
|
166
|
+
// 使用 sc create 创建服务
|
|
167
|
+
await this.execCommand(`sc create "${this.serviceName}" binPath= "${binPath}" start= auto displayname= "${this.serviceDesc}"`);
|
|
168
|
+
this.log?.info('[ServiceManager] Windows 服务注册成功');
|
|
169
|
+
|
|
170
|
+
// 启动服务
|
|
171
|
+
await this.execCommand(`net start "${this.serviceName}"`);
|
|
172
|
+
this.log?.info('[ServiceManager] Windows 服务已启动');
|
|
173
|
+
|
|
174
|
+
return true;
|
|
190
175
|
}
|
|
191
176
|
|
|
192
177
|
// Linux 服务安装 (systemd)
|
|
@@ -78,6 +78,7 @@ defineWinProp('onLine', true);
|
|
|
78
78
|
defineWinProp('language', 'zh-CN');
|
|
79
79
|
defineGlobalProp('navigator', win.navigator);
|
|
80
80
|
|
|
81
|
+
defineWinProp('WebSocket', WebSocket);
|
|
81
82
|
defineGlobalProp('WebSocket', WebSocket);
|
|
82
83
|
defineGlobalProp('XMLHttpRequest', win.XMLHttpRequest);
|
|
83
84
|
defineGlobalProp('window', win);
|