@yeaft/webchat-agent 0.1.212 → 0.1.213
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 +1 -1
- package/service/doctor.js +11 -90
- package/service/linux.js +31 -3
- package/service/macos.js +27 -10
- package/service/windows.js +24 -1
package/package.json
CHANGED
package/service/doctor.js
CHANGED
|
@@ -1,30 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Service — doctor command
|
|
3
3
|
* Diagnoses service configuration issues: checks paths, service status, version consistency.
|
|
4
|
+
*
|
|
5
|
+
* Reuses path and status functions from platform modules to avoid duplication.
|
|
4
6
|
*/
|
|
5
7
|
import { execSync } from 'child_process';
|
|
6
8
|
import { existsSync, readFileSync, statSync } from 'fs';
|
|
7
|
-
import { join, dirname } from 'path';
|
|
8
9
|
import { platform, homedir } from 'os';
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
// ── Platform-specific service config paths ─────────────────────────────────
|
|
15
|
-
|
|
16
|
-
function getMacPlistPath() {
|
|
17
|
-
return join(homedir(), 'Library', 'LaunchAgents', 'com.yeaft.agent.plist');
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
function getLinuxServicePath() {
|
|
21
|
-
return join(homedir(), '.config', 'systemd', 'user', `${SERVICE_NAME}.service`);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
function getWindowsEcosystemPath() {
|
|
25
|
-
const appData = process.env.APPDATA || join(homedir(), 'AppData', 'Roaming');
|
|
26
|
-
return join(appData, SERVICE_NAME, 'ecosystem.config.cjs');
|
|
27
|
-
}
|
|
10
|
+
import { getNodePath } from './config.js';
|
|
11
|
+
import { getLaunchdPlistPath, getMacServiceStatus } from './macos.js';
|
|
12
|
+
import { getSystemdServicePath, getLinuxServiceStatus } from './linux.js';
|
|
13
|
+
import { getEcosystemPath, getWinServiceStatus } from './windows.js';
|
|
28
14
|
|
|
29
15
|
// ── Parse paths from service config files ──────────────────────────────────
|
|
30
16
|
|
|
@@ -107,78 +93,13 @@ function getCliVersion(nodePath, cliPath) {
|
|
|
107
93
|
}
|
|
108
94
|
|
|
109
95
|
function getCurrentNodePath() {
|
|
110
|
-
return
|
|
96
|
+
return getNodePath();
|
|
111
97
|
}
|
|
112
98
|
|
|
113
99
|
function getCurrentNodeVersion() {
|
|
114
100
|
return process.version;
|
|
115
101
|
}
|
|
116
102
|
|
|
117
|
-
// ── Service status checks ──────────────────────────────────────────────────
|
|
118
|
-
|
|
119
|
-
function getMacServiceStatus() {
|
|
120
|
-
try {
|
|
121
|
-
const output = execSync('launchctl list | grep com.yeaft.agent', {
|
|
122
|
-
encoding: 'utf-8',
|
|
123
|
-
stdio: ['pipe', 'pipe', 'pipe'],
|
|
124
|
-
});
|
|
125
|
-
if (output.trim()) {
|
|
126
|
-
const parts = output.trim().split(/\s+/);
|
|
127
|
-
const pid = parts[0];
|
|
128
|
-
if (pid !== '-') {
|
|
129
|
-
return { running: true, pid };
|
|
130
|
-
}
|
|
131
|
-
return { running: false, pid: null };
|
|
132
|
-
}
|
|
133
|
-
return { running: false, pid: null };
|
|
134
|
-
} catch {
|
|
135
|
-
return { running: false, pid: null };
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
function getLinuxServiceStatus() {
|
|
140
|
-
try {
|
|
141
|
-
const output = execSync(`systemctl --user is-active ${SERVICE_NAME}`, {
|
|
142
|
-
encoding: 'utf-8',
|
|
143
|
-
stdio: ['pipe', 'pipe', 'pipe'],
|
|
144
|
-
}).trim();
|
|
145
|
-
if (output === 'active') {
|
|
146
|
-
// Try to get PID
|
|
147
|
-
let pid = null;
|
|
148
|
-
try {
|
|
149
|
-
pid = execSync(`systemctl --user show ${SERVICE_NAME} --property=MainPID --value`, {
|
|
150
|
-
encoding: 'utf-8',
|
|
151
|
-
stdio: ['pipe', 'pipe', 'pipe'],
|
|
152
|
-
}).trim();
|
|
153
|
-
if (pid === '0') pid = null;
|
|
154
|
-
} catch {}
|
|
155
|
-
return { running: true, pid };
|
|
156
|
-
}
|
|
157
|
-
return { running: false, pid: null };
|
|
158
|
-
} catch {
|
|
159
|
-
return { running: false, pid: null };
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
function getWindowsServiceStatus() {
|
|
164
|
-
try {
|
|
165
|
-
const output = execSync('pm2 jlist', {
|
|
166
|
-
encoding: 'utf-8',
|
|
167
|
-
stdio: ['pipe', 'pipe', 'pipe'],
|
|
168
|
-
});
|
|
169
|
-
const apps = JSON.parse(output);
|
|
170
|
-
const app = Array.isArray(apps) && apps.find(a => a.name === 'yeaft-agent');
|
|
171
|
-
if (app) {
|
|
172
|
-
const running = app.pm2_env && app.pm2_env.status === 'online';
|
|
173
|
-
const pid = running ? app.pid : null;
|
|
174
|
-
return { running, pid: pid ? String(pid) : null };
|
|
175
|
-
}
|
|
176
|
-
return { running: false, pid: null };
|
|
177
|
-
} catch {
|
|
178
|
-
return { running: false, pid: null };
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
|
|
182
103
|
// ── Tilde shorthand for display ────────────────────────────────────────────
|
|
183
104
|
|
|
184
105
|
function tildeify(filePath) {
|
|
@@ -201,17 +122,17 @@ export function doctor() {
|
|
|
201
122
|
|
|
202
123
|
// 1. Determine platform and config path
|
|
203
124
|
if (os === 'darwin') {
|
|
204
|
-
configPath =
|
|
125
|
+
configPath = getLaunchdPlistPath();
|
|
205
126
|
parsePaths = parseMacPaths;
|
|
206
127
|
getServiceStatus = getMacServiceStatus;
|
|
207
128
|
} else if (os === 'linux') {
|
|
208
|
-
configPath =
|
|
129
|
+
configPath = getSystemdServicePath();
|
|
209
130
|
parsePaths = parseLinuxPaths;
|
|
210
131
|
getServiceStatus = getLinuxServiceStatus;
|
|
211
132
|
} else if (os === 'win32') {
|
|
212
|
-
configPath =
|
|
133
|
+
configPath = getEcosystemPath();
|
|
213
134
|
parsePaths = parseWindowsPaths;
|
|
214
|
-
getServiceStatus =
|
|
135
|
+
getServiceStatus = getWinServiceStatus;
|
|
215
136
|
} else {
|
|
216
137
|
console.log(`\u26a0\ufe0f Unsupported platform: ${os}`);
|
|
217
138
|
console.log(` The doctor command supports macOS, Linux, and Windows.`);
|
package/service/linux.js
CHANGED
|
@@ -7,10 +7,9 @@ import { join, dirname } from 'path';
|
|
|
7
7
|
import { homedir } from 'os';
|
|
8
8
|
import { SERVICE_NAME, getLogDir, getNodePath, getCliPath } from './config.js';
|
|
9
9
|
|
|
10
|
+
/** Pure path getter — no side effects (no directory creation). */
|
|
10
11
|
export function getSystemdServicePath() {
|
|
11
|
-
|
|
12
|
-
mkdirSync(dir, { recursive: true });
|
|
13
|
-
return join(dir, `${SERVICE_NAME}.service`);
|
|
12
|
+
return join(homedir(), '.config', 'systemd', 'user', `${SERVICE_NAME}.service`);
|
|
14
13
|
}
|
|
15
14
|
|
|
16
15
|
function generateSystemdUnit(config) {
|
|
@@ -50,6 +49,8 @@ WantedBy=default.target
|
|
|
50
49
|
|
|
51
50
|
export function linuxInstall(config) {
|
|
52
51
|
const servicePath = getSystemdServicePath();
|
|
52
|
+
// Ensure systemd user directory exists before writing
|
|
53
|
+
mkdirSync(join(homedir(), '.config', 'systemd', 'user'), { recursive: true });
|
|
53
54
|
writeFileSync(servicePath, generateSystemdUnit(config));
|
|
54
55
|
execSync('systemctl --user daemon-reload');
|
|
55
56
|
execSync(`systemctl --user enable ${SERVICE_NAME}`);
|
|
@@ -88,6 +89,33 @@ export function linuxRestart() {
|
|
|
88
89
|
console.log('Service restarted.');
|
|
89
90
|
}
|
|
90
91
|
|
|
92
|
+
/**
|
|
93
|
+
* Query systemd for the current service status.
|
|
94
|
+
* Returns { running: boolean, pid: string|null }.
|
|
95
|
+
*/
|
|
96
|
+
export function getLinuxServiceStatus() {
|
|
97
|
+
try {
|
|
98
|
+
const output = execSync(`systemctl --user is-active ${SERVICE_NAME}`, {
|
|
99
|
+
encoding: 'utf-8',
|
|
100
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
101
|
+
}).trim();
|
|
102
|
+
if (output === 'active') {
|
|
103
|
+
let pid = null;
|
|
104
|
+
try {
|
|
105
|
+
pid = execSync(`systemctl --user show ${SERVICE_NAME} --property=MainPID --value`, {
|
|
106
|
+
encoding: 'utf-8',
|
|
107
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
108
|
+
}).trim();
|
|
109
|
+
if (pid === '0') pid = null;
|
|
110
|
+
} catch {}
|
|
111
|
+
return { running: true, pid };
|
|
112
|
+
}
|
|
113
|
+
return { running: false, pid: null };
|
|
114
|
+
} catch {
|
|
115
|
+
return { running: false, pid: null };
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
91
119
|
export function linuxStatus() {
|
|
92
120
|
try {
|
|
93
121
|
execSync(`systemctl --user status ${SERVICE_NAME}`, { stdio: 'inherit' });
|
package/service/macos.js
CHANGED
|
@@ -7,10 +7,9 @@ import { join } from 'path';
|
|
|
7
7
|
import { homedir } from 'os';
|
|
8
8
|
import { getLogDir, getNodePath, getCliPath } from './config.js';
|
|
9
9
|
|
|
10
|
+
/** Pure path getter — no side effects (no directory creation). */
|
|
10
11
|
export function getLaunchdPlistPath() {
|
|
11
|
-
|
|
12
|
-
mkdirSync(dir, { recursive: true });
|
|
13
|
-
return join(dir, 'com.yeaft.agent.plist');
|
|
12
|
+
return join(homedir(), 'Library', 'LaunchAgents', 'com.yeaft.agent.plist');
|
|
14
13
|
}
|
|
15
14
|
|
|
16
15
|
function generateLaunchdPlist(config) {
|
|
@@ -61,6 +60,8 @@ ${envDict.join('\n')}
|
|
|
61
60
|
|
|
62
61
|
export function macInstall(config) {
|
|
63
62
|
const plistPath = getLaunchdPlistPath();
|
|
63
|
+
// Ensure LaunchAgents directory exists before writing
|
|
64
|
+
mkdirSync(join(homedir(), 'Library', 'LaunchAgents'), { recursive: true });
|
|
64
65
|
// Unload first if exists
|
|
65
66
|
if (existsSync(plistPath)) {
|
|
66
67
|
try { execSync(`launchctl unload ${plistPath} 2>/dev/null`); } catch {}
|
|
@@ -107,22 +108,38 @@ export function macRestart() {
|
|
|
107
108
|
macStart();
|
|
108
109
|
}
|
|
109
110
|
|
|
110
|
-
|
|
111
|
+
/**
|
|
112
|
+
* Query launchd for the current service status.
|
|
113
|
+
* Returns { running: boolean, pid: string|null, exitCode: string|null }.
|
|
114
|
+
*/
|
|
115
|
+
export function getMacServiceStatus() {
|
|
111
116
|
try {
|
|
112
|
-
const output = execSync(
|
|
117
|
+
const output = execSync('launchctl list | grep com.yeaft.agent', {
|
|
118
|
+
encoding: 'utf-8',
|
|
119
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
120
|
+
});
|
|
113
121
|
if (output.trim()) {
|
|
114
122
|
const parts = output.trim().split(/\s+/);
|
|
115
123
|
const pid = parts[0];
|
|
116
124
|
const exitCode = parts[1];
|
|
117
125
|
if (pid !== '-') {
|
|
118
|
-
|
|
119
|
-
} else {
|
|
120
|
-
console.log(`Service is stopped (last exit code: ${exitCode})`);
|
|
126
|
+
return { running: true, pid, exitCode };
|
|
121
127
|
}
|
|
122
|
-
|
|
123
|
-
console.log('Service is not installed.');
|
|
128
|
+
return { running: false, pid: null, exitCode };
|
|
124
129
|
}
|
|
130
|
+
return { running: false, pid: null, exitCode: null };
|
|
125
131
|
} catch {
|
|
132
|
+
return { running: false, pid: null, exitCode: null };
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export function macStatus() {
|
|
137
|
+
const status = getMacServiceStatus();
|
|
138
|
+
if (status.running) {
|
|
139
|
+
console.log(`Service is running (PID: ${status.pid})`);
|
|
140
|
+
} else if (status.exitCode !== null) {
|
|
141
|
+
console.log(`Service is stopped (last exit code: ${status.exitCode})`);
|
|
142
|
+
} else {
|
|
126
143
|
console.log('Service is not installed.');
|
|
127
144
|
}
|
|
128
145
|
}
|
package/service/windows.js
CHANGED
|
@@ -22,7 +22,7 @@ function ensurePm2() {
|
|
|
22
22
|
}
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
function getEcosystemPath() {
|
|
25
|
+
export function getEcosystemPath() {
|
|
26
26
|
return join(getConfigDir(), 'ecosystem.config.cjs');
|
|
27
27
|
}
|
|
28
28
|
|
|
@@ -156,6 +156,29 @@ export function winRestart() {
|
|
|
156
156
|
}
|
|
157
157
|
}
|
|
158
158
|
|
|
159
|
+
/**
|
|
160
|
+
* Query pm2 for the current service status.
|
|
161
|
+
* Returns { running: boolean, pid: string|null }.
|
|
162
|
+
*/
|
|
163
|
+
export function getWinServiceStatus() {
|
|
164
|
+
try {
|
|
165
|
+
const output = execSync('pm2 jlist', {
|
|
166
|
+
encoding: 'utf-8',
|
|
167
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
168
|
+
});
|
|
169
|
+
const apps = JSON.parse(output);
|
|
170
|
+
const app = Array.isArray(apps) && apps.find(a => a.name === 'yeaft-agent');
|
|
171
|
+
if (app) {
|
|
172
|
+
const running = app.pm2_env && app.pm2_env.status === 'online';
|
|
173
|
+
const pid = running ? app.pid : null;
|
|
174
|
+
return { running, pid: pid ? String(pid) : null };
|
|
175
|
+
}
|
|
176
|
+
return { running: false, pid: null };
|
|
177
|
+
} catch {
|
|
178
|
+
return { running: false, pid: null };
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
159
182
|
export function winStatus() {
|
|
160
183
|
try {
|
|
161
184
|
execSync(`pm2 describe ${PM2_APP_NAME}`, { stdio: 'inherit' });
|