@myassis/gateway 1.0.27 → 1.0.29
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.
|
@@ -189,21 +189,21 @@ async function installLinux() {
|
|
|
189
189
|
if (installed)
|
|
190
190
|
await stopService();
|
|
191
191
|
const execStart = isPkg ? exe : `${exe} ${script}`;
|
|
192
|
-
const unitContent = `[Unit]
|
|
193
|
-
Description=${exports.SERVICE_DISPLAY_NAME}
|
|
194
|
-
After=network.target
|
|
195
|
-
|
|
196
|
-
[Service]
|
|
197
|
-
Type=simple
|
|
198
|
-
User=${process.env.USER || 'root'}
|
|
199
|
-
WorkingDirectory=${workDir}
|
|
200
|
-
ExecStart=${execStart}
|
|
201
|
-
Restart=always
|
|
202
|
-
RestartSec=5
|
|
203
|
-
Environment=NODE_ENV=production
|
|
204
|
-
|
|
205
|
-
[Install]
|
|
206
|
-
WantedBy=multi-user.target
|
|
192
|
+
const unitContent = `[Unit]
|
|
193
|
+
Description=${exports.SERVICE_DISPLAY_NAME}
|
|
194
|
+
After=network.target
|
|
195
|
+
|
|
196
|
+
[Service]
|
|
197
|
+
Type=simple
|
|
198
|
+
User=${process.env.USER || 'root'}
|
|
199
|
+
WorkingDirectory=${workDir}
|
|
200
|
+
ExecStart=${execStart}
|
|
201
|
+
Restart=always
|
|
202
|
+
RestartSec=5
|
|
203
|
+
Environment=NODE_ENV=production
|
|
204
|
+
|
|
205
|
+
[Install]
|
|
206
|
+
WantedBy=multi-user.target
|
|
207
207
|
`;
|
|
208
208
|
await fs_1.default.promises.writeFile('/tmp/myassis-gateway.service', unitContent, 'utf8');
|
|
209
209
|
await execAsync('cp /tmp/myassis-gateway.service /etc/systemd/system/myassis-gateway.service', { timeout: 10000 });
|
|
@@ -381,7 +381,7 @@ async function updateService() {
|
|
|
381
381
|
if (isPackagedExe()) {
|
|
382
382
|
// pkg 环境:从 COS 下载对应平台的 exe
|
|
383
383
|
// ❗ 关键:不能在这里 stopService,进程本身即为服务进程,停止后后续代码不执行
|
|
384
|
-
//
|
|
384
|
+
// 方案:下载到临时文件后,派发一个独立延迟替换脚本,本进程直接返回
|
|
385
385
|
const platform = process.platform === 'win32' ? 'win' : 'linux';
|
|
386
386
|
const isWin = platform === 'win';
|
|
387
387
|
const downloadUrl = isWin
|
|
@@ -404,44 +404,123 @@ async function updateService() {
|
|
|
404
404
|
response.data.on('error', reject);
|
|
405
405
|
});
|
|
406
406
|
console.log('✅ 下载完成');
|
|
407
|
-
// 生成延迟替换脚本,
|
|
407
|
+
// 生成延迟替换脚本,Windows 通过 nssm 管理服务并使用 execAsync 派发脚本
|
|
408
408
|
if (isWin) {
|
|
409
|
+
const nssmPath = getNssmPath();
|
|
410
|
+
if (!nssmPath || !fs_1.default.existsSync(nssmPath)) {
|
|
411
|
+
throw new Error('未找到 nssm.exe,无法执行 Windows 服务更新');
|
|
412
|
+
}
|
|
413
|
+
const escapePowerShellString = (value) => value.replace(/'/g, "''");
|
|
414
|
+
const updateScriptPath = path_1.default.join(os_1.default.tmpdir(), 'myassis-gateway-update.ps1');
|
|
409
415
|
const psScript = [
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
`
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
416
|
+
`$ErrorActionPreference = 'Stop'`,
|
|
417
|
+
`$nssm = '${escapePowerShellString(nssmPath)}'`,
|
|
418
|
+
`$serviceName = '${escapePowerShellString(exports.SERVICE_NAME)}'`,
|
|
419
|
+
`$currentExe = '${escapePowerShellString(currentExe)}'`,
|
|
420
|
+
`$tmpExe = '${escapePowerShellString(tmpExe)}'`,
|
|
421
|
+
`$backupExe = '${escapePowerShellString(`${currentExe}.bak`)}'`,
|
|
422
|
+
`$logPath = Join-Path $env:TEMP 'myassis-gateway-update.log'`,
|
|
423
|
+
`$logDir = Split-Path -Parent $logPath`,
|
|
424
|
+
`if (-not (Test-Path $logDir)) { New-Item -ItemType Directory -Path $logDir -Force | Out-Null }`,
|
|
425
|
+
`function Write-UpdateLog { param([string]$Message) Add-Content -Path $logPath -Encoding UTF8 -Value \"$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') $Message\" }`,
|
|
426
|
+
`try {`,
|
|
427
|
+
` Write-UpdateLog 'update script started'`,
|
|
428
|
+
` Start-Sleep -Seconds 5`,
|
|
429
|
+
` Write-UpdateLog 'stopping service by nssm'`,
|
|
430
|
+
` & $nssm stop $serviceName | Out-Null`,
|
|
431
|
+
` Start-Sleep -Seconds 2`,
|
|
432
|
+
` Write-UpdateLog 'waiting executable unlock'`,
|
|
433
|
+
` $moved = $false`,
|
|
434
|
+
` for ($i = 0; $i -lt 60; $i++) {`,
|
|
435
|
+
` try {`,
|
|
436
|
+
` if (Test-Path $backupExe) { Remove-Item $backupExe -Force -ErrorAction SilentlyContinue }`,
|
|
437
|
+
` Move-Item $currentExe $backupExe -Force`,
|
|
438
|
+
` $moved = $true`,
|
|
439
|
+
` break`,
|
|
440
|
+
` } catch {`,
|
|
441
|
+
` Start-Sleep -Seconds 1`,
|
|
442
|
+
` }`,
|
|
443
|
+
` }`,
|
|
444
|
+
` if (-not $moved) { throw '等待旧版本可执行文件解锁超时' }`,
|
|
445
|
+
` Write-UpdateLog 'moving new executable'`,
|
|
446
|
+
` Move-Item $tmpExe $currentExe -Force`,
|
|
447
|
+
` Start-Sleep -Seconds 1`,
|
|
448
|
+
` Write-UpdateLog 'starting service by nssm'`,
|
|
449
|
+
` & $nssm start $serviceName | Out-Null`,
|
|
450
|
+
` Remove-Item $backupExe -Force -ErrorAction SilentlyContinue`,
|
|
451
|
+
` Remove-Item $tmpExe -Force -ErrorAction SilentlyContinue`,
|
|
452
|
+
` Write-UpdateLog 'update script finished'`,
|
|
453
|
+
`} catch {`,
|
|
454
|
+
` Write-UpdateLog \"update script failed: $($_.Exception.Message)\"`,
|
|
455
|
+
` try { & $nssm start $serviceName | Out-Null } catch { Write-UpdateLog \"restart service failed: $($_.Exception.Message)\" }`,
|
|
456
|
+
` throw`,
|
|
457
|
+
`}`,
|
|
458
|
+
].join('\r\n');
|
|
459
|
+
fs_1.default.writeFileSync(updateScriptPath, `\uFEFF${psScript}`, 'utf8');
|
|
460
|
+
await execAsync(`cmd.exe /c start \"\" powershell.exe -NoProfile -ExecutionPolicy Bypass -File \"${updateScriptPath}\"`, {
|
|
461
|
+
timeout: 10000,
|
|
462
|
+
windowsHide: true
|
|
425
463
|
});
|
|
426
|
-
child.unref();
|
|
427
464
|
}
|
|
428
465
|
else {
|
|
429
|
-
// Linux:
|
|
466
|
+
// Linux: 生成独立更新脚本,优先通过 systemd-run 派发,避免当前服务停止时更新脚本被一并终止
|
|
467
|
+
const escapeShellString = (value) => `'${value.replace(/'/g, `'\\''`)}'`;
|
|
468
|
+
const updateScriptPath = path_1.default.join(os_1.default.tmpdir(), 'myassis-gateway-update.sh');
|
|
469
|
+
const updateLogPath = path_1.default.join(os_1.default.tmpdir(), 'myassis-gateway-update.log');
|
|
470
|
+
const backupExe = `${currentExe}.bak`;
|
|
430
471
|
const bashScript = [
|
|
472
|
+
'#!/usr/bin/env bash',
|
|
473
|
+
'set -euo pipefail',
|
|
474
|
+
`SERVICE_NAME=${escapeShellString(exports.SERVICE_NAME)}`,
|
|
475
|
+
`CURRENT_EXE=${escapeShellString(currentExe)}`,
|
|
476
|
+
`TMP_EXE=${escapeShellString(tmpExe)}`,
|
|
477
|
+
`BACKUP_EXE=${escapeShellString(backupExe)}`,
|
|
478
|
+
`LOG_PATH=${escapeShellString(updateLogPath)}`,
|
|
479
|
+
'mkdir -p "$(dirname "$LOG_PATH")"',
|
|
480
|
+
'log() { echo "$(date \'+%Y-%m-%d %H:%M:%S\') $*" >> "$LOG_PATH"; }',
|
|
481
|
+
'log "update script started"',
|
|
431
482
|
'sleep 5',
|
|
432
|
-
|
|
483
|
+
'log "stopping service by systemctl"',
|
|
484
|
+
'systemctl stop "$SERVICE_NAME" >> "$LOG_PATH" 2>&1 || true',
|
|
433
485
|
'sleep 2',
|
|
434
|
-
|
|
435
|
-
|
|
486
|
+
'log "waiting executable unlock"',
|
|
487
|
+
'moved=0',
|
|
488
|
+
'for i in $(seq 1 60); do',
|
|
489
|
+
' if [ -f "$BACKUP_EXE" ]; then rm -f "$BACKUP_EXE" >> "$LOG_PATH" 2>&1 || true; fi',
|
|
490
|
+
' if mv -f "$CURRENT_EXE" "$BACKUP_EXE" >> "$LOG_PATH" 2>&1; then',
|
|
491
|
+
' moved=1',
|
|
492
|
+
' break',
|
|
493
|
+
' fi',
|
|
494
|
+
' sleep 1',
|
|
495
|
+
'done',
|
|
496
|
+
'if [ "$moved" != "1" ]; then',
|
|
497
|
+
' log "waiting old executable unlock timeout"',
|
|
498
|
+
' systemctl start "$SERVICE_NAME" >> "$LOG_PATH" 2>&1 || true',
|
|
499
|
+
' exit 1',
|
|
500
|
+
'fi',
|
|
501
|
+
'log "moving new executable"',
|
|
502
|
+
'mv -f "$TMP_EXE" "$CURRENT_EXE" >> "$LOG_PATH" 2>&1',
|
|
503
|
+
'chmod +x "$CURRENT_EXE" >> "$LOG_PATH" 2>&1 || true',
|
|
436
504
|
'sleep 1',
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
505
|
+
'log "starting service by systemctl"',
|
|
506
|
+
'systemctl start "$SERVICE_NAME" >> "$LOG_PATH" 2>&1 || true',
|
|
507
|
+
'rm -f "$BACKUP_EXE" "$TMP_EXE" >> "$LOG_PATH" 2>&1 || true',
|
|
508
|
+
'log "update script finished"',
|
|
509
|
+
].join('\n');
|
|
510
|
+
fs_1.default.writeFileSync(updateScriptPath, bashScript, 'utf8');
|
|
511
|
+
fs_1.default.chmodSync(updateScriptPath, 0o755);
|
|
512
|
+
const escapedUpdateScriptPath = escapeShellString(updateScriptPath);
|
|
513
|
+
try {
|
|
514
|
+
await execAsync(`systemd-run --unit=myassis-gateway-update --description="Myassis Gateway Update" /bin/bash ${escapedUpdateScriptPath}`, {
|
|
515
|
+
timeout: 10000,
|
|
516
|
+
});
|
|
517
|
+
}
|
|
518
|
+
catch (err) {
|
|
519
|
+
logger.warn(`systemd-run 启动更新脚本失败,回退到 nohup setsid: ${err.message}`);
|
|
520
|
+
await execAsync(`nohup setsid /bin/bash ${escapedUpdateScriptPath} >/dev/null 2>&1 < /dev/null &`, {
|
|
521
|
+
timeout: 10000,
|
|
522
|
+
});
|
|
523
|
+
}
|
|
445
524
|
}
|
|
446
525
|
console.log('✅ 后台替换进程已启动,服务将在几秒后自动重启');
|
|
447
526
|
return { success: true, message: `更新成功: ${check.currentVersion} → ${check.latestVersion},服务正在后台替换...` };
|
|
@@ -1,12 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
3
|
exports.getGlobalModelSelector = exports.parseAruments = exports.LLMClient = void 0;
|
|
7
4
|
const index_js_1 = require("../../stores/index.js");
|
|
8
5
|
const shared_1 = require("@myassis/shared");
|
|
9
|
-
const promises_1 = __importDefault(require("fs/promises"));
|
|
10
6
|
const logger = (0, shared_1.getLogger)('LLMClient');
|
|
11
7
|
/**
|
|
12
8
|
* LLM 调用器类
|
|
@@ -18,7 +14,7 @@ class LLMClient {
|
|
|
18
14
|
tools;
|
|
19
15
|
preferredModelId;
|
|
20
16
|
signal;
|
|
21
|
-
timeoutMs =
|
|
17
|
+
timeoutMs = 120000;
|
|
22
18
|
constructor(models, messages, signal, tools) {
|
|
23
19
|
this.models = models;
|
|
24
20
|
this.messages = messages;
|
|
@@ -80,7 +76,12 @@ class LLMClient {
|
|
|
80
76
|
}
|
|
81
77
|
selector.markTried(model.id);
|
|
82
78
|
clearTimeout(timer);
|
|
83
|
-
|
|
79
|
+
if (controller.signal.aborted) {
|
|
80
|
+
lastError = new Error('Request timed out');
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
lastError = error;
|
|
84
|
+
}
|
|
84
85
|
}
|
|
85
86
|
}
|
|
86
87
|
throw lastError || new Error('All models are unavailable or has been aborted');
|
|
@@ -401,8 +402,6 @@ class LLMClient {
|
|
|
401
402
|
const tokens = JSON.stringify(body).length;
|
|
402
403
|
logger.debug('tokens', tokens);
|
|
403
404
|
if (tokens > 200000 && !existAttachments) {
|
|
404
|
-
logger.warn('message is too large and has writen to the file debug.json');
|
|
405
|
-
await promises_1.default.writeFile('debug.json', JSON.stringify(body.messages), 'utf-8');
|
|
406
405
|
throw Error('exceed max message tokens');
|
|
407
406
|
}
|
|
408
407
|
return {
|
|
@@ -41,16 +41,13 @@ class MemoryManager {
|
|
|
41
41
|
let messages = this.session.getMessages();
|
|
42
42
|
if (this.childAgent) {
|
|
43
43
|
messages.splice(-1);
|
|
44
|
-
logger.debug('history', messages);
|
|
45
44
|
}
|
|
46
45
|
// 2. 消息少于摘要配置的阈值数,直接返回
|
|
47
|
-
logger.debug('message length:', messages.length);
|
|
48
46
|
if (messages.length < this.config.summaryThreshold) {
|
|
49
47
|
return messages;
|
|
50
48
|
}
|
|
51
49
|
// 3. 检查是否有摘要
|
|
52
50
|
const hasSummary = this.session.lastMessageSummary;
|
|
53
|
-
logger.debug('hasSummary', hasSummary);
|
|
54
51
|
if (!hasSummary) {
|
|
55
52
|
// 4A. 首次摘要生成
|
|
56
53
|
const summary = await this.generateSummaryAsync(messages.slice(0, -index_js_2.appConfig.messageKeep), null);
|
|
@@ -65,7 +62,6 @@ class MemoryManager {
|
|
|
65
62
|
else {
|
|
66
63
|
// 4B. 增量摘要更新
|
|
67
64
|
const newMessages = messages.filter((m) => m.createdAt > this.session.lastMessageSummaryAt);
|
|
68
|
-
logger.debug('new messages length:', newMessages.length);
|
|
69
65
|
if (newMessages.length < this.config.summaryThreshold) {
|
|
70
66
|
// 新消息少于阈值条:返回摘要 + 从摘要时刻起的所有消息
|
|
71
67
|
const fromSummary = messages.filter((m) => m.createdAt >= this.session.lastMessageSummaryAt);
|
|
@@ -120,7 +120,7 @@ exports.execTool = {
|
|
|
120
120
|
}
|
|
121
121
|
catch (e) {
|
|
122
122
|
const error = e;
|
|
123
|
-
resolve({ success: false, errorMessage: error
|
|
123
|
+
resolve({ success: false, errorMessage: (error?.stdout?.toLocaleString()?.substring(0, 100) ?? '') + (error?.stderr?.toLocaleString() ?? '') + (error?.message ?? '') });
|
|
124
124
|
return;
|
|
125
125
|
}
|
|
126
126
|
});
|