@myassis/gateway 1.0.18 → 1.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/dist/api/index.js +27 -19
- package/dist/cli.js +18 -5
- package/dist/config/index.js +34 -11
- package/dist/index.js +1 -2
- package/dist/main.js +76 -71
- package/dist/middleware/auth.js +9 -5
- package/dist/middleware/errorHandler.js +9 -4
- package/dist/routes/agent.js +39 -37
- package/dist/routes/auth.js +32 -30
- package/dist/routes/chat.js +7 -5
- package/dist/routes/config.js +5 -3
- package/dist/routes/models.js +28 -23
- package/dist/routes/service.js +29 -24
- package/dist/routes/settings.js +26 -21
- package/dist/routes/skillHub.js +22 -17
- package/dist/routes/skills.js +25 -20
- package/dist/routes/tasks.js +24 -19
- package/dist/routes/upload.js +24 -17
- package/dist/routes/version.js +20 -19
- package/dist/services/HMSPushService.js +4 -1
- package/dist/services/LocalTaskService.js +12 -9
- package/dist/services/NotificationService.js +14 -11
- package/dist/services/ServiceManager.js +77 -65
- package/dist/services/TaskSchedulerService.js +33 -30
- package/dist/services/TaskService.js +27 -24
- package/dist/services/WebSocketService.js +14 -11
- package/dist/services/agent/Agent.js +13 -9
- package/dist/services/agent/AgentManager.js +32 -24
- package/dist/services/agent/AgentStore.js +7 -3
- package/dist/services/dataService.js +72 -69
- package/dist/services/index.js +25 -9
- package/dist/services/llm/LLMClient.js +17 -9
- package/dist/services/memory/MemoryManager.js +22 -18
- package/dist/services/model/ModelCapabilities.js +11 -7
- package/dist/services/model/index.js +17 -1
- package/dist/services/models.js +5 -1
- package/dist/services/session/MigrationManager.js +18 -11
- package/dist/services/session/Session.js +33 -29
- package/dist/services/session/SessionManager.js +26 -21
- package/dist/services/session/SessionStore.js +32 -25
- package/dist/services/session/index.js +8 -2
- package/dist/services/skills.js +4 -1
- package/dist/services/systemPrompt.js +23 -16
- package/dist/services/task/PushTokenStore.js +9 -5
- package/dist/services/task/TaskStore.js +10 -6
- package/dist/services/tools/calculator.js +4 -1
- package/dist/services/tools/edit.js +16 -10
- package/dist/services/tools/exec.js +25 -16
- package/dist/services/tools/fetch.js +30 -4
- package/dist/services/tools/file.js +41 -35
- package/dist/services/tools/index.js +44 -24
- package/dist/services/tools/keyboard.js +41 -38
- package/dist/services/tools/model.js +12 -9
- package/dist/services/tools/mouse.js +12 -9
- package/dist/services/tools/screenshot.js +9 -3
- package/dist/services/tools/search.js +34 -4
- package/dist/services/tools/sessionsSpawn.js +11 -8
- package/dist/services/tools/skill.js +19 -16
- package/dist/services/tools/task.js +12 -9
- package/dist/services/tools/types.js +2 -1
- package/dist/services/tools/webFetch.js +34 -4
- package/dist/stores/authStore.js +25 -19
- package/dist/stores/index.js +9 -3
- package/dist/stores/memoryStore.js +5 -2
- package/dist/stores/persistStore.js +20 -14
- package/package.json +11 -20
package/dist/routes/version.js
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
const
|
|
13
|
-
const
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const express_1 = __importDefault(require("express"));
|
|
7
|
+
const axios_1 = __importDefault(require("axios"));
|
|
8
|
+
const index_js_1 = require("../config/index.js");
|
|
9
|
+
const auth_js_1 = require("../middleware/auth.js");
|
|
10
|
+
const fs_1 = require("fs");
|
|
11
|
+
const path_1 = require("path");
|
|
12
|
+
const shared_1 = require("@myassis/shared");
|
|
13
|
+
const logger = (0, shared_1.getLogger)('VersionRoutes');
|
|
14
|
+
const router = express_1.default.Router();
|
|
14
15
|
/**
|
|
15
16
|
* 获取 Gateway 本地版本及运行方式
|
|
16
17
|
* GET /api/v1/version/local
|
|
@@ -18,8 +19,8 @@ const __dirname = dirname(__filename);
|
|
|
18
19
|
router.get('/local', async (req, res) => {
|
|
19
20
|
try {
|
|
20
21
|
// 读取 package.json 获取版本
|
|
21
|
-
const packageJsonPath = resolve(__dirname, '../../package.json');
|
|
22
|
-
const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));
|
|
22
|
+
const packageJsonPath = (0, path_1.resolve)(__dirname, '../../package.json');
|
|
23
|
+
const packageJson = JSON.parse((0, fs_1.readFileSync)(packageJsonPath, 'utf-8'));
|
|
23
24
|
// 判断运行方式:pkg 打包的 exe 会有 (process as any).pkg
|
|
24
25
|
const runMode = process.pkg ? 'exe' : 'node';
|
|
25
26
|
res.json({
|
|
@@ -42,10 +43,10 @@ router.get('/local', async (req, res) => {
|
|
|
42
43
|
/**
|
|
43
44
|
* 转发到服务端接口
|
|
44
45
|
*/
|
|
45
|
-
router.get('/latest', requireAuth, async (req, res) => {
|
|
46
|
+
router.get('/latest', auth_js_1.requireAuth, async (req, res) => {
|
|
46
47
|
try {
|
|
47
|
-
const serverBaseUrl = appConfig.serverBaseUrl || 'http://localhost:9091';
|
|
48
|
-
const response = await
|
|
48
|
+
const serverBaseUrl = index_js_1.appConfig.serverBaseUrl || 'http://localhost:9091';
|
|
49
|
+
const response = await axios_1.default.get(`${serverBaseUrl}/api/v1/version/latest`, {
|
|
49
50
|
timeout: 10000,
|
|
50
51
|
headers: {
|
|
51
52
|
'Content-Type': 'application/json',
|
|
@@ -63,4 +64,4 @@ router.get('/latest', requireAuth, async (req, res) => {
|
|
|
63
64
|
});
|
|
64
65
|
}
|
|
65
66
|
});
|
|
66
|
-
|
|
67
|
+
exports.default = router;
|
|
@@ -1,6 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
/**
|
|
2
3
|
* HMS Push 服务(华为设备专用)
|
|
3
4
|
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.hmsPushService = void 0;
|
|
4
7
|
class HMSPushService {
|
|
5
8
|
/**
|
|
6
9
|
* 检查服务是否可用
|
|
@@ -21,4 +24,4 @@ class HMSPushService {
|
|
|
21
24
|
return { success: false, sent: 0, failed: tokens.length };
|
|
22
25
|
}
|
|
23
26
|
}
|
|
24
|
-
|
|
27
|
+
exports.hmsPushService = new HMSPushService();
|
|
@@ -1,17 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
/**
|
|
2
3
|
* Gateway 本地任务服务
|
|
3
4
|
* 提供本地任务的 CRUD 操作
|
|
4
5
|
*
|
|
5
6
|
* 使用 SQLite 数据库存储任务
|
|
6
7
|
*/
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
const
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.localTaskService = void 0;
|
|
10
|
+
const uuid_1 = require("uuid");
|
|
11
|
+
const TaskStore_js_1 = require("./task/TaskStore.js");
|
|
12
|
+
const shared_1 = require("@myassis/shared");
|
|
13
|
+
const logger = (0, shared_1.getLogger)('LocalTaskService');
|
|
11
14
|
class LocalTaskService {
|
|
12
15
|
store;
|
|
13
16
|
constructor() {
|
|
14
|
-
this.store = new TaskStore();
|
|
17
|
+
this.store = new TaskStore_js_1.TaskStore();
|
|
15
18
|
}
|
|
16
19
|
/**
|
|
17
20
|
* 创建本地任务
|
|
@@ -19,7 +22,7 @@ class LocalTaskService {
|
|
|
19
22
|
createTask(data) {
|
|
20
23
|
const now = Date.now();
|
|
21
24
|
const task = {
|
|
22
|
-
id:
|
|
25
|
+
id: (0, uuid_1.v4)(),
|
|
23
26
|
userId: data.userId,
|
|
24
27
|
title: data.title,
|
|
25
28
|
description: data.description,
|
|
@@ -130,7 +133,7 @@ class LocalTaskService {
|
|
|
130
133
|
const now = Date.now();
|
|
131
134
|
// 如果是重复任务,计算下次执行时间
|
|
132
135
|
if (task.taskType === 'recurring') {
|
|
133
|
-
const result = await sharedTaskService.calculateNextOccurrence(now, task.recurrenceRule, task.endTime, task.intervalValue, task.intervalUnit);
|
|
136
|
+
const result = await shared_1.sharedTaskService.calculateNextOccurrence(now, task.recurrenceRule, task.endTime, task.intervalValue, task.intervalUnit);
|
|
134
137
|
if (result) {
|
|
135
138
|
const newTask = {
|
|
136
139
|
...task,
|
|
@@ -144,7 +147,7 @@ class LocalTaskService {
|
|
|
144
147
|
logger.info(`Created recurring task instance`, {
|
|
145
148
|
originalId: task.id,
|
|
146
149
|
newId: newTask.id,
|
|
147
|
-
nextScheduledAt: formatUTCForLog(result),
|
|
150
|
+
nextScheduledAt: (0, shared_1.formatUTCForLog)(result),
|
|
148
151
|
});
|
|
149
152
|
}
|
|
150
153
|
else {
|
|
@@ -210,7 +213,7 @@ class LocalTaskService {
|
|
|
210
213
|
return this.store;
|
|
211
214
|
}
|
|
212
215
|
}
|
|
213
|
-
|
|
216
|
+
exports.localTaskService = new LocalTaskService();
|
|
214
217
|
/**
|
|
215
218
|
* 将时间转换为时间戳
|
|
216
219
|
*/
|
|
@@ -1,19 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
/**
|
|
2
3
|
* 通知服务
|
|
3
4
|
* 负责发送任务通知
|
|
4
5
|
* 优先级:WebSocket > HMS Push (华为) / Expo Push (其他)
|
|
5
6
|
*/
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
const
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.notificationService = void 0;
|
|
9
|
+
const PushTokenStore_js_1 = require("./task/PushTokenStore.js");
|
|
10
|
+
const WebSocketService_js_1 = require("./WebSocketService.js");
|
|
11
|
+
const HMSPushService_js_1 = require("./HMSPushService.js");
|
|
12
|
+
const shared_1 = require("@myassis/shared");
|
|
13
|
+
const logger = (0, shared_1.getLogger)('NotificationService');
|
|
11
14
|
const log = logger;
|
|
12
15
|
// 全局 PushTokenStore 实例
|
|
13
16
|
let pushTokenStore = null;
|
|
14
17
|
function getPushTokenStore() {
|
|
15
18
|
if (!pushTokenStore) {
|
|
16
|
-
pushTokenStore = new PushTokenStore();
|
|
19
|
+
pushTokenStore = new PushTokenStore_js_1.PushTokenStore();
|
|
17
20
|
}
|
|
18
21
|
return pushTokenStore;
|
|
19
22
|
}
|
|
@@ -25,8 +28,8 @@ class NotificationService {
|
|
|
25
28
|
*/
|
|
26
29
|
async sendTaskNotification(task) {
|
|
27
30
|
// 1. 优先尝试 WebSocket 发送(用户在线时)
|
|
28
|
-
if (webSocketService.isUserOnline(task.userId)) {
|
|
29
|
-
const sent = webSocketService.sendTaskNotification(task);
|
|
31
|
+
if (WebSocketService_js_1.webSocketService.isUserOnline(task.userId)) {
|
|
32
|
+
const sent = WebSocketService_js_1.webSocketService.sendTaskNotification(task);
|
|
30
33
|
if (sent) {
|
|
31
34
|
return true;
|
|
32
35
|
}
|
|
@@ -168,11 +171,11 @@ class NotificationService {
|
|
|
168
171
|
* 发送 HMS Push 通知(华为设备专用)
|
|
169
172
|
*/
|
|
170
173
|
async sendHMSPushNotification(hmsTokens, title, body, data) {
|
|
171
|
-
if (!hmsPushService.isAvailable()) {
|
|
174
|
+
if (!HMSPushService_js_1.hmsPushService.isAvailable()) {
|
|
172
175
|
log.warn('HMS Push 服务未配置');
|
|
173
176
|
return false;
|
|
174
177
|
}
|
|
175
|
-
const result = await hmsPushService.sendToMany(hmsTokens, {
|
|
178
|
+
const result = await HMSPushService_js_1.hmsPushService.sendToMany(hmsTokens, {
|
|
176
179
|
title,
|
|
177
180
|
body,
|
|
178
181
|
data: {
|
|
@@ -239,4 +242,4 @@ class NotificationService {
|
|
|
239
242
|
return { expoCount, hmsCount };
|
|
240
243
|
}
|
|
241
244
|
}
|
|
242
|
-
|
|
245
|
+
exports.notificationService = new NotificationService();
|
|
@@ -1,18 +1,22 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.updateService = exports.checkForUpdates = exports.restartService = exports.stopService = exports.startService = exports.uninstallService = exports.installService = exports.getServiceInfo = exports.SERVICE_DISPLAY_NAME = exports.SERVICE_NAME = void 0;
|
|
7
|
+
const child_process_1 = require("child_process");
|
|
8
|
+
const util_1 = require("util");
|
|
9
|
+
const path_1 = __importDefault(require("path"));
|
|
10
|
+
const fs_1 = __importDefault(require("fs"));
|
|
11
|
+
const axios_1 = __importDefault(require("axios"));
|
|
12
|
+
const execAsync = (0, util_1.promisify)(child_process_1.exec);
|
|
13
|
+
exports.SERVICE_NAME = 'myassis-gateway';
|
|
14
|
+
exports.SERVICE_DISPLAY_NAME = '我的助手 Desktop Gateway Service';
|
|
10
15
|
// ─── 平台无关工具 ────────────────────────────────────────────
|
|
11
16
|
function getServiceScript() {
|
|
12
17
|
// npm install -g 后,用当前模块位置定位包目录
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
return path.join(pkgRoot, 'dist', 'index.js');
|
|
18
|
+
const pkgRoot = path_1.default.resolve(__dirname, '..', '..');
|
|
19
|
+
return path_1.default.join(pkgRoot, 'dist', 'index.js');
|
|
16
20
|
}
|
|
17
21
|
function getNodeExec() {
|
|
18
22
|
return process.execPath;
|
|
@@ -20,7 +24,7 @@ function getNodeExec() {
|
|
|
20
24
|
// ─── Windows 实现 ───────────────────────────────────────────
|
|
21
25
|
async function queryServiceWindows() {
|
|
22
26
|
try {
|
|
23
|
-
const { stdout } = await execAsync(`sc query ${SERVICE_NAME}`, { timeout: 5000 });
|
|
27
|
+
const { stdout } = await execAsync(`sc query ${exports.SERVICE_NAME}`, { timeout: 5000 });
|
|
24
28
|
return { installed: true, running: stdout.includes('RUNNING') };
|
|
25
29
|
}
|
|
26
30
|
catch {
|
|
@@ -29,22 +33,22 @@ async function queryServiceWindows() {
|
|
|
29
33
|
}
|
|
30
34
|
async function installWindows() {
|
|
31
35
|
const script = getServiceScript();
|
|
32
|
-
const workDir =
|
|
36
|
+
const workDir = path_1.default.dirname(script);
|
|
33
37
|
const nodeExe = getNodeExec();
|
|
34
38
|
const { installed } = await queryServiceWindows();
|
|
35
39
|
if (installed)
|
|
36
40
|
await stopService();
|
|
37
|
-
const nssmPath =
|
|
38
|
-
const useNssm =
|
|
41
|
+
const nssmPath = path_1.default.join(path_1.default.dirname(process.execPath), 'nssm.exe');
|
|
42
|
+
const useNssm = fs_1.default.existsSync(nssmPath);
|
|
39
43
|
try {
|
|
40
44
|
if (useNssm) {
|
|
41
|
-
await execAsync(`"${nssmPath}" install ${SERVICE_NAME} "${nodeExe}" "${script}"`, { timeout: 15000, cwd: workDir });
|
|
42
|
-
await execAsync(`"${nssmPath}" set ${SERVICE_NAME} AppDirectory "${workDir}"`, { timeout: 10000 });
|
|
43
|
-
await execAsync(`"${nssmPath}" set ${SERVICE_NAME} DisplayName "${SERVICE_DISPLAY_NAME}"`, { timeout: 10000 });
|
|
44
|
-
await execAsync(`"${nssmPath}" set ${SERVICE_NAME} Start SERVICE_AUTO_START`, { timeout: 10000 });
|
|
45
|
+
await execAsync(`"${nssmPath}" install ${exports.SERVICE_NAME} "${nodeExe}" "${script}"`, { timeout: 15000, cwd: workDir });
|
|
46
|
+
await execAsync(`"${nssmPath}" set ${exports.SERVICE_NAME} AppDirectory "${workDir}"`, { timeout: 10000 });
|
|
47
|
+
await execAsync(`"${nssmPath}" set ${exports.SERVICE_NAME} DisplayName "${exports.SERVICE_DISPLAY_NAME}"`, { timeout: 10000 });
|
|
48
|
+
await execAsync(`"${nssmPath}" set ${exports.SERVICE_NAME} Start SERVICE_AUTO_START`, { timeout: 10000 });
|
|
45
49
|
}
|
|
46
50
|
else {
|
|
47
|
-
await execAsync(`sc create ${SERVICE_NAME} binPath= "\\"${nodeExe}\\" \\"${script}\\"" DisplayName= "${SERVICE_DISPLAY_NAME}" start= auto`, { timeout: 15000 });
|
|
51
|
+
await execAsync(`sc create ${exports.SERVICE_NAME} binPath= "\\"${nodeExe}\\" \\"${script}\\"" DisplayName= "${exports.SERVICE_DISPLAY_NAME}" start= auto`, { timeout: 15000 });
|
|
48
52
|
}
|
|
49
53
|
await startService();
|
|
50
54
|
return { success: true, message: '服务安装并启动成功' };
|
|
@@ -56,12 +60,12 @@ async function installWindows() {
|
|
|
56
60
|
async function uninstallWindows() {
|
|
57
61
|
try {
|
|
58
62
|
await stopService();
|
|
59
|
-
const nssmPath =
|
|
60
|
-
if (
|
|
61
|
-
await execAsync(`"${nssmPath}" remove ${SERVICE_NAME} confirm`, { timeout: 10000 });
|
|
63
|
+
const nssmPath = path_1.default.join(path_1.default.dirname(process.execPath), 'nssm.exe');
|
|
64
|
+
if (fs_1.default.existsSync(nssmPath)) {
|
|
65
|
+
await execAsync(`"${nssmPath}" remove ${exports.SERVICE_NAME} confirm`, { timeout: 10000 });
|
|
62
66
|
}
|
|
63
67
|
else {
|
|
64
|
-
await execAsync(`sc delete ${SERVICE_NAME}`, { timeout: 10000 });
|
|
68
|
+
await execAsync(`sc delete ${exports.SERVICE_NAME}`, { timeout: 10000 });
|
|
65
69
|
}
|
|
66
70
|
return { success: true, message: '服务卸载成功' };
|
|
67
71
|
}
|
|
@@ -71,7 +75,7 @@ async function uninstallWindows() {
|
|
|
71
75
|
}
|
|
72
76
|
async function startServiceWindows() {
|
|
73
77
|
try {
|
|
74
|
-
await execAsync(`sc start ${SERVICE_NAME}`, { timeout: 10000 });
|
|
78
|
+
await execAsync(`sc start ${exports.SERVICE_NAME}`, { timeout: 10000 });
|
|
75
79
|
return { success: true, message: '服务启动成功' };
|
|
76
80
|
}
|
|
77
81
|
catch (err) {
|
|
@@ -79,9 +83,9 @@ async function startServiceWindows() {
|
|
|
79
83
|
}
|
|
80
84
|
}
|
|
81
85
|
async function restartServiceWindows() {
|
|
82
|
-
const nssmPath =
|
|
86
|
+
const nssmPath = path_1.default.join(path_1.default.dirname(process.execPath), 'nssm.exe');
|
|
83
87
|
// 无 nssm 时需要用户手动更新
|
|
84
|
-
if (!
|
|
88
|
+
if (!fs_1.default.existsSync(nssmPath)) {
|
|
85
89
|
const info = await getServiceInfo();
|
|
86
90
|
if (info.installed) {
|
|
87
91
|
return {
|
|
@@ -96,7 +100,7 @@ async function restartServiceWindows() {
|
|
|
96
100
|
// 服务未安装时,可直接更新
|
|
97
101
|
}
|
|
98
102
|
try {
|
|
99
|
-
await execAsync(`"${nssmPath}" restart ${SERVICE_NAME}`, { timeout: 15000 });
|
|
103
|
+
await execAsync(`"${nssmPath}" restart ${exports.SERVICE_NAME}`, { timeout: 15000 });
|
|
100
104
|
return { success: true, message: '服务重启成功' };
|
|
101
105
|
}
|
|
102
106
|
catch (err) {
|
|
@@ -105,7 +109,7 @@ async function restartServiceWindows() {
|
|
|
105
109
|
}
|
|
106
110
|
async function stopServiceWindows() {
|
|
107
111
|
try {
|
|
108
|
-
await execAsync(`sc stop ${SERVICE_NAME}`, { timeout: 10000 });
|
|
112
|
+
await execAsync(`sc stop ${exports.SERVICE_NAME}`, { timeout: 10000 });
|
|
109
113
|
return { success: true, message: '服务停止成功' };
|
|
110
114
|
}
|
|
111
115
|
catch (err) {
|
|
@@ -115,7 +119,7 @@ async function stopServiceWindows() {
|
|
|
115
119
|
// ─── Linux / macOS 实现 ─────────────────────────────────────
|
|
116
120
|
async function queryServiceLinux() {
|
|
117
121
|
try {
|
|
118
|
-
const { stdout } = await execAsync(`systemctl is-active ${SERVICE_NAME}`, { timeout: 5000 });
|
|
122
|
+
const { stdout } = await execAsync(`systemctl is-active ${exports.SERVICE_NAME}`, { timeout: 5000 });
|
|
119
123
|
const status = stdout.trim();
|
|
120
124
|
return { installed: true, running: status === 'active' };
|
|
121
125
|
}
|
|
@@ -133,29 +137,29 @@ async function queryServiceLinux() {
|
|
|
133
137
|
}
|
|
134
138
|
async function installLinux() {
|
|
135
139
|
const script = getServiceScript();
|
|
136
|
-
const workDir =
|
|
140
|
+
const workDir = path_1.default.dirname(script);
|
|
137
141
|
const nodeExe = getNodeExec();
|
|
138
142
|
try {
|
|
139
143
|
const { installed } = await queryServiceLinux();
|
|
140
144
|
if (installed)
|
|
141
145
|
await stopService();
|
|
142
|
-
const unitContent = `[Unit]
|
|
143
|
-
Description=${SERVICE_DISPLAY_NAME}
|
|
144
|
-
After=network.target
|
|
145
|
-
|
|
146
|
-
[Service]
|
|
147
|
-
Type=simple
|
|
148
|
-
User=${process.env.USER || 'root'}
|
|
149
|
-
WorkingDirectory=${workDir}
|
|
150
|
-
ExecStart=${nodeExe} ${script}
|
|
151
|
-
Restart=always
|
|
152
|
-
RestartSec=5
|
|
153
|
-
Environment=NODE_ENV=production
|
|
154
|
-
|
|
155
|
-
[Install]
|
|
156
|
-
WantedBy=multi-user.target
|
|
146
|
+
const unitContent = `[Unit]
|
|
147
|
+
Description=${exports.SERVICE_DISPLAY_NAME}
|
|
148
|
+
After=network.target
|
|
149
|
+
|
|
150
|
+
[Service]
|
|
151
|
+
Type=simple
|
|
152
|
+
User=${process.env.USER || 'root'}
|
|
153
|
+
WorkingDirectory=${workDir}
|
|
154
|
+
ExecStart=${nodeExe} ${script}
|
|
155
|
+
Restart=always
|
|
156
|
+
RestartSec=5
|
|
157
|
+
Environment=NODE_ENV=production
|
|
158
|
+
|
|
159
|
+
[Install]
|
|
160
|
+
WantedBy=multi-user.target
|
|
157
161
|
`;
|
|
158
|
-
await
|
|
162
|
+
await fs_1.default.promises.writeFile('/tmp/myassis-gateway.service', unitContent, 'utf8');
|
|
159
163
|
await execAsync('cp /tmp/myassis-gateway.service /etc/systemd/system/myassis-gateway.service', { timeout: 10000 });
|
|
160
164
|
await execAsync('systemctl daemon-reload', { timeout: 10000 });
|
|
161
165
|
await execAsync('systemctl enable myassis-gateway', { timeout: 10000 });
|
|
@@ -180,7 +184,7 @@ async function uninstallLinux() {
|
|
|
180
184
|
}
|
|
181
185
|
async function startServiceLinux() {
|
|
182
186
|
try {
|
|
183
|
-
await execAsync(`systemctl start ${SERVICE_NAME}`, { timeout: 10000 });
|
|
187
|
+
await execAsync(`systemctl start ${exports.SERVICE_NAME}`, { timeout: 10000 });
|
|
184
188
|
return { success: true, message: '服务启动成功' };
|
|
185
189
|
}
|
|
186
190
|
catch (err) {
|
|
@@ -189,7 +193,7 @@ async function startServiceLinux() {
|
|
|
189
193
|
}
|
|
190
194
|
async function restartServiceLinux() {
|
|
191
195
|
try {
|
|
192
|
-
await execAsync(`systemctl restart ${SERVICE_NAME}`, { timeout: 15000 });
|
|
196
|
+
await execAsync(`systemctl restart ${exports.SERVICE_NAME}`, { timeout: 15000 });
|
|
193
197
|
return { success: true, message: '服务重启成功' };
|
|
194
198
|
}
|
|
195
199
|
catch (err) {
|
|
@@ -198,7 +202,7 @@ async function restartServiceLinux() {
|
|
|
198
202
|
}
|
|
199
203
|
async function stopServiceLinux() {
|
|
200
204
|
try {
|
|
201
|
-
await execAsync(`systemctl stop ${SERVICE_NAME}`, { timeout: 10000 });
|
|
205
|
+
await execAsync(`systemctl stop ${exports.SERVICE_NAME}`, { timeout: 10000 });
|
|
202
206
|
return { success: true, message: '服务停止成功' };
|
|
203
207
|
}
|
|
204
208
|
catch (err) {
|
|
@@ -206,7 +210,7 @@ async function stopServiceLinux() {
|
|
|
206
210
|
}
|
|
207
211
|
}
|
|
208
212
|
// ─── 平台分发 ───────────────────────────────────────────────
|
|
209
|
-
|
|
213
|
+
async function getServiceInfo() {
|
|
210
214
|
const platform = process.platform;
|
|
211
215
|
let installed = false;
|
|
212
216
|
let running = false;
|
|
@@ -223,12 +227,13 @@ export async function getServiceInfo() {
|
|
|
223
227
|
return {
|
|
224
228
|
installed,
|
|
225
229
|
running,
|
|
226
|
-
displayName: SERVICE_DISPLAY_NAME,
|
|
230
|
+
displayName: exports.SERVICE_DISPLAY_NAME,
|
|
227
231
|
canManage: platform === 'win32' || platform === 'linux',
|
|
228
232
|
platform,
|
|
229
233
|
};
|
|
230
234
|
}
|
|
231
|
-
|
|
235
|
+
exports.getServiceInfo = getServiceInfo;
|
|
236
|
+
async function installService() {
|
|
232
237
|
const platform = process.platform;
|
|
233
238
|
if (platform === 'win32')
|
|
234
239
|
return installWindows();
|
|
@@ -236,7 +241,8 @@ export async function installService() {
|
|
|
236
241
|
return installLinux();
|
|
237
242
|
return { success: false, message: `当前平台 ${platform} 不支持自动安装服务` };
|
|
238
243
|
}
|
|
239
|
-
|
|
244
|
+
exports.installService = installService;
|
|
245
|
+
async function uninstallService() {
|
|
240
246
|
const platform = process.platform;
|
|
241
247
|
if (platform === 'win32')
|
|
242
248
|
return uninstallWindows();
|
|
@@ -244,7 +250,8 @@ export async function uninstallService() {
|
|
|
244
250
|
return uninstallLinux();
|
|
245
251
|
return { success: false, message: `当前平台 ${platform} 不支持自动卸载服务` };
|
|
246
252
|
}
|
|
247
|
-
|
|
253
|
+
exports.uninstallService = uninstallService;
|
|
254
|
+
async function startService() {
|
|
248
255
|
const platform = process.platform;
|
|
249
256
|
if (platform === 'win32')
|
|
250
257
|
return startServiceWindows();
|
|
@@ -252,7 +259,8 @@ export async function startService() {
|
|
|
252
259
|
return startServiceLinux();
|
|
253
260
|
return { success: false, message: `当前平台 ${platform} 不支持自动启动服务` };
|
|
254
261
|
}
|
|
255
|
-
|
|
262
|
+
exports.startService = startService;
|
|
263
|
+
async function stopService() {
|
|
256
264
|
const platform = process.platform;
|
|
257
265
|
if (platform === 'win32')
|
|
258
266
|
return stopServiceWindows();
|
|
@@ -260,7 +268,8 @@ export async function stopService() {
|
|
|
260
268
|
return stopServiceLinux();
|
|
261
269
|
return { success: false, message: `当前平台 ${platform} 不支持自动停止服务` };
|
|
262
270
|
}
|
|
263
|
-
|
|
271
|
+
exports.stopService = stopService;
|
|
272
|
+
async function restartService() {
|
|
264
273
|
const platform = process.platform;
|
|
265
274
|
if (platform === 'win32')
|
|
266
275
|
return restartServiceWindows();
|
|
@@ -268,13 +277,14 @@ export async function restartService() {
|
|
|
268
277
|
return restartServiceLinux();
|
|
269
278
|
return { success: false, message: `当前平台 ${platform} 不支持自动重启服务` };
|
|
270
279
|
}
|
|
280
|
+
exports.restartService = restartService;
|
|
271
281
|
// ─── 版本更新 ─────────────────────────────────────────
|
|
272
282
|
function getPackageVersion() {
|
|
273
283
|
try {
|
|
274
|
-
const scriptDir =
|
|
275
|
-
const pkgPath =
|
|
276
|
-
if (
|
|
277
|
-
const pkg = JSON.parse(
|
|
284
|
+
const scriptDir = __dirname;
|
|
285
|
+
const pkgPath = path_1.default.join(scriptDir, '..', '..', 'package.json');
|
|
286
|
+
if (fs_1.default.existsSync(pkgPath)) {
|
|
287
|
+
const pkg = JSON.parse(fs_1.default.readFileSync(pkgPath, 'utf8'));
|
|
278
288
|
return pkg.version || '0.0.0';
|
|
279
289
|
}
|
|
280
290
|
}
|
|
@@ -296,10 +306,10 @@ function compareVersions(a, b) {
|
|
|
296
306
|
}
|
|
297
307
|
return 0;
|
|
298
308
|
}
|
|
299
|
-
|
|
309
|
+
async function checkForUpdates() {
|
|
300
310
|
try {
|
|
301
311
|
const currentVersion = getPackageVersion();
|
|
302
|
-
const response = await
|
|
312
|
+
const response = await axios_1.default.get('https://registry.npmjs.org/@myassis/gateway/latest', { timeout: 10000 });
|
|
303
313
|
const latestVersion = response.data.version;
|
|
304
314
|
if (!latestVersion) {
|
|
305
315
|
return { hasUpdate: false, currentVersion, latestVersion: currentVersion, error: '无法获取最新版本' };
|
|
@@ -311,7 +321,8 @@ export async function checkForUpdates() {
|
|
|
311
321
|
return { hasUpdate: false, currentVersion: '0.0.0', latestVersion: '0.0.0', error: err.message };
|
|
312
322
|
}
|
|
313
323
|
}
|
|
314
|
-
|
|
324
|
+
exports.checkForUpdates = checkForUpdates;
|
|
325
|
+
async function updateService() {
|
|
315
326
|
try {
|
|
316
327
|
const check = await checkForUpdates();
|
|
317
328
|
if (check.error) {
|
|
@@ -341,3 +352,4 @@ export async function updateService() {
|
|
|
341
352
|
return { success: false, message: `更新失败: ${err.message}` };
|
|
342
353
|
}
|
|
343
354
|
}
|
|
355
|
+
exports.updateService = updateService;
|