claw-subagent-service 0.0.19 → 0.0.20
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 +17 -3
- package/package.json +1 -1
- package/scripts/install-silent.js +2 -1
- package/scripts/post-install.js +16 -2
- package/scripts/pre-uninstall.js +53 -17
- package/service/modules/config.js +8 -1
- package/service/modules/service-manager.js +2 -1
package/cli.js
CHANGED
|
@@ -47,11 +47,24 @@ function installService() {
|
|
|
47
47
|
console.log('[CLI] 安装系统服务...');
|
|
48
48
|
|
|
49
49
|
const platform = process.platform;
|
|
50
|
-
const execPath = process.execPath;
|
|
51
50
|
|
|
52
51
|
if (platform === 'win32') {
|
|
53
52
|
// Windows: 使用 node-windows 注册服务(正确处理路径引号)
|
|
54
53
|
console.log('[CLI] 使用 node-windows 安装服务...');
|
|
54
|
+
|
|
55
|
+
// 强制删除可能存在的旧服务(确保配置更新,包括环境变量)
|
|
56
|
+
try {
|
|
57
|
+
console.log('[CLI] 清理旧服务...');
|
|
58
|
+
execSync(`net stop "${SERVICE_NAME}" 2>nul`, { stdio: 'ignore', timeout: 10000 });
|
|
59
|
+
} catch (e) {}
|
|
60
|
+
try {
|
|
61
|
+
execSync(`sc.exe delete "${SERVICE_NAME}" 2>nul`, { stdio: 'ignore', timeout: 10000 });
|
|
62
|
+
console.log('[CLI] 旧服务已删除');
|
|
63
|
+
} catch (e) {}
|
|
64
|
+
try {
|
|
65
|
+
execSync('timeout /t 2 /nobreak >nul 2>&1', { stdio: 'ignore', timeout: 5000 });
|
|
66
|
+
} catch (e) {}
|
|
67
|
+
|
|
55
68
|
try {
|
|
56
69
|
const userHome = process.env.USERPROFILE || os.homedir();
|
|
57
70
|
const Service = require('node-windows').Service;
|
|
@@ -62,10 +75,11 @@ function installService() {
|
|
|
62
75
|
nodeOptions: ['--harmony', '--max_old_space_size=4096'],
|
|
63
76
|
env: {
|
|
64
77
|
USERPROFILE: userHome,
|
|
65
|
-
HOME: userHome
|
|
78
|
+
HOME: userHome,
|
|
79
|
+
CLAW_SERVICE_HOME: userHome
|
|
66
80
|
}
|
|
67
81
|
});
|
|
68
|
-
console.log(`[CLI] 服务环境变量 USERPROFILE=${userHome}`);
|
|
82
|
+
console.log(`[CLI] 服务环境变量 USERPROFILE=${userHome}, CLAW_SERVICE_HOME=${userHome}`);
|
|
69
83
|
|
|
70
84
|
svc.on('install', () => {
|
|
71
85
|
console.log('[CLI] 服务安装成功');
|
package/package.json
CHANGED
package/scripts/post-install.js
CHANGED
|
@@ -51,6 +51,19 @@ function installAndStartService() {
|
|
|
51
51
|
|
|
52
52
|
console.log('[postinstall] 正在注册系统服务...');
|
|
53
53
|
|
|
54
|
+
// 强制删除可能存在的旧服务(确保配置更新,包括环境变量)
|
|
55
|
+
try {
|
|
56
|
+
console.log('[postinstall] 清理旧服务...');
|
|
57
|
+
execSync(`net stop "${SERVICE_NAME}" 2>nul`, { stdio: 'ignore', timeout: 10000 });
|
|
58
|
+
} catch (e) {}
|
|
59
|
+
try {
|
|
60
|
+
execSync(`sc.exe delete "${SERVICE_NAME}" 2>nul`, { stdio: 'ignore', timeout: 10000 });
|
|
61
|
+
console.log('[postinstall] 旧服务已删除');
|
|
62
|
+
} catch (e) {}
|
|
63
|
+
try {
|
|
64
|
+
execSync('timeout /t 2 /nobreak >nul 2>&1', { stdio: 'ignore', timeout: 5000 });
|
|
65
|
+
} catch (e) {}
|
|
66
|
+
|
|
54
67
|
try {
|
|
55
68
|
// 使用 node-windows 注册服务(正确处理路径引号)
|
|
56
69
|
const Service = require('node-windows').Service;
|
|
@@ -62,10 +75,11 @@ function installAndStartService() {
|
|
|
62
75
|
nodeOptions: ['--harmony', '--max_old_space_size=4096'],
|
|
63
76
|
env: {
|
|
64
77
|
USERPROFILE: userHome,
|
|
65
|
-
HOME: userHome
|
|
78
|
+
HOME: userHome,
|
|
79
|
+
CLAW_SERVICE_HOME: userHome
|
|
66
80
|
}
|
|
67
81
|
});
|
|
68
|
-
console.log(`[postinstall] 服务环境变量 USERPROFILE=${userHome}`);
|
|
82
|
+
console.log(`[postinstall] 服务环境变量 USERPROFILE=${userHome}, CLAW_SERVICE_HOME=${userHome}`);
|
|
69
83
|
|
|
70
84
|
svc.on('install', () => {
|
|
71
85
|
console.log('[postinstall] 服务注册成功,正在启动...');
|
package/scripts/pre-uninstall.js
CHANGED
|
@@ -8,29 +8,65 @@ const { execSync } = require('child_process');
|
|
|
8
8
|
const SERVICES = ['SilentNodeService', 'claw-subagent-service'];
|
|
9
9
|
const DAEMON_PATH = path.join(__dirname, '..', 'service', 'daemon.js');
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
try {
|
|
14
|
-
execSync(`net stop "${name}" 2>nul`, { stdio: 'ignore', timeout: 10000 });
|
|
15
|
-
} catch (e) {}
|
|
16
|
-
|
|
17
|
-
// 使用 node-windows 卸载服务(删除 wrapper 文件,释放文件锁)
|
|
11
|
+
function uninstallServiceSync(name) {
|
|
12
|
+
return new Promise((resolve) => {
|
|
18
13
|
try {
|
|
19
14
|
const Service = require('node-windows').Service;
|
|
20
15
|
const svc = new Service({ name, script: DAEMON_PATH });
|
|
16
|
+
|
|
17
|
+
let resolved = false;
|
|
18
|
+
function done(result) {
|
|
19
|
+
if (!resolved) {
|
|
20
|
+
resolved = true;
|
|
21
|
+
resolve(result);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
svc.on('uninstall', () => {
|
|
26
|
+
console.log(`[preuninstall] 服务 ${name} 已卸载`);
|
|
27
|
+
done(true);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
svc.on('error', (err) => {
|
|
31
|
+
console.error(`[preuninstall] 卸载服务 ${name} 失败:`, err.message);
|
|
32
|
+
done(false);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
// 超时兜底
|
|
36
|
+
setTimeout(() => {
|
|
37
|
+
console.log(`[preuninstall] 卸载服务 ${name} 超时`);
|
|
38
|
+
done(false);
|
|
39
|
+
}, 15000);
|
|
40
|
+
|
|
21
41
|
svc.uninstall();
|
|
22
|
-
} catch (e) {
|
|
42
|
+
} catch (e) {
|
|
43
|
+
resolve(false);
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
(async function () {
|
|
49
|
+
if (process.platform === 'win32') {
|
|
50
|
+
for (const name of SERVICES) {
|
|
51
|
+
// 1. 停止服务
|
|
52
|
+
try {
|
|
53
|
+
execSync(`net stop "${name}" 2>nul`, { stdio: 'ignore', timeout: 10000 });
|
|
54
|
+
} catch (e) {}
|
|
55
|
+
|
|
56
|
+
// 2. 使用 node-windows 卸载(等待完成)
|
|
57
|
+
await uninstallServiceSync(name);
|
|
23
58
|
|
|
24
|
-
|
|
59
|
+
// 3. 兜底 - 使用 sc.exe 删除服务
|
|
60
|
+
try {
|
|
61
|
+
execSync(`sc.exe delete "${name}" 2>nul`, { stdio: 'ignore', timeout: 10000 });
|
|
62
|
+
} catch (e) {}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// 4. 等待系统释放文件句柄
|
|
25
66
|
try {
|
|
26
|
-
execSync(
|
|
67
|
+
execSync('timeout /t 2 /nobreak >nul 2>&1', { stdio: 'ignore', timeout: 5000 });
|
|
27
68
|
} catch (e) {}
|
|
28
69
|
}
|
|
29
70
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
execSync('timeout /t 2 /nobreak >nul 2>&1', { stdio: 'ignore', timeout: 5000 });
|
|
33
|
-
} catch (e) {}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
process.exit(0);
|
|
71
|
+
process.exit(0);
|
|
72
|
+
})();
|
|
@@ -3,8 +3,12 @@ const path = require('path');
|
|
|
3
3
|
const os = require('os');
|
|
4
4
|
|
|
5
5
|
function loadConfig() {
|
|
6
|
+
// 优先使用 CLAW_SERVICE_HOME(服务注册时硬编码的实际用户目录)
|
|
7
|
+
// 回退到 USERPROFILE / os.homedir()
|
|
8
|
+
const homeDir = process.env.CLAW_SERVICE_HOME || process.env.USERPROFILE || os.homedir();
|
|
9
|
+
|
|
6
10
|
// Read from ~/.claw-bridge/config.json
|
|
7
|
-
const clawBridgePath = path.join(
|
|
11
|
+
const clawBridgePath = path.join(homeDir, '.claw-bridge', 'config.json');
|
|
8
12
|
let clawBridgeConfig = {};
|
|
9
13
|
if (fs.existsSync(clawBridgePath)) {
|
|
10
14
|
try {
|
|
@@ -13,6 +17,9 @@ function loadConfig() {
|
|
|
13
17
|
console.error('读取 claw-bridge 配置失败:', e);
|
|
14
18
|
}
|
|
15
19
|
}
|
|
20
|
+
if (!fs.existsSync(clawBridgePath)) {
|
|
21
|
+
console.warn(`[CONFIG] 未找到 ${clawBridgePath} (home=${homeDir})`);
|
|
22
|
+
}
|
|
16
23
|
|
|
17
24
|
// Read from local rongcloud-config.json
|
|
18
25
|
const localConfigPath = path.join(__dirname, '..', '..', 'rongcloud-config.json');
|