hermes-web-ui 0.3.8 → 0.4.0
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/README.md +7 -10
- package/dist/client/assets/{Add-s316k4Av.js → Add-BChxDDdy.js} +1 -1
- package/dist/client/assets/{Button-BkA_RI8a.js → Button-uvjCWO-i.js} +1 -1
- package/dist/client/assets/{ChannelsView-DPmPn8DW.js → ChannelsView-D3a0g0rb.js} +1 -1
- package/dist/client/assets/{ChatView-DEtziOPB.js → ChatView-T8LH7dwU.js} +1 -1
- package/dist/client/assets/{Close-CrLD0IXG.js → Close-DbXijZpL.js} +1 -1
- package/dist/client/assets/{FormItem-CQLdFrl9.js → FormItem-BRiLD3TC.js} +1 -1
- package/dist/client/assets/{GatewaysView-CC1Y0tZZ.js → GatewaysView-rfzh1nqy.js} +1 -1
- package/dist/client/assets/{Input-nXKlujwJ.js → Input-CjlUbV0M.js} +1 -1
- package/dist/client/assets/{InputNumber-DLZwwIyX.js → InputNumber-CPEjoOAv.js} +1 -1
- package/dist/client/assets/{JobsView-BC0bBrJO.js → JobsView-D6AFr9Xe.js} +2 -2
- package/dist/client/assets/{LoginView-PqpFR9bV.js → LoginView-DJB_TSHN.js} +1 -1
- package/dist/client/assets/{LogsView-DtR88N0b.js → LogsView-Ul8pAp42.js} +1 -1
- package/dist/client/assets/{MarkdownRenderer-BSLfTurm.js → MarkdownRenderer-CY7d2L7Z.js} +1 -1
- package/dist/client/assets/{MemoryView-CJRWnePL.js → MemoryView-BR5Dl_fa.js} +1 -1
- package/dist/client/assets/{Modal-Bp9RK8LZ.js → Modal-DDUFP8vh.js} +1 -1
- package/dist/client/assets/{ModelsView-7Obe34Cz.js → ModelsView-DAi9Jdmk.js} +1 -1
- package/dist/client/assets/{Popconfirm-DTdUi7r_.js → Popconfirm-Cnb_uQVo.js} +1 -1
- package/dist/client/assets/{Popover-_M3o0B7L.js → Popover-DiVI0l6E.js} +1 -1
- package/dist/client/assets/{ProfilesView-1_GmRx-S.js → ProfilesView-BB0Zrfhi.js} +1 -1
- package/dist/client/assets/{Select-aHPR3urY.js → Select-BqUA1wxE.js} +1 -1
- package/dist/client/assets/{SettingRow-DKasLuS5.js → SettingRow-CK0bHtaz.js} +1 -1
- package/dist/client/assets/{SettingsView-DZCA7_CM.js → SettingsView-BKKk44FG.js} +1 -1
- package/dist/client/assets/{SkillsView-Dk7O05cK.js → SkillsView-whSlyc23.js} +1 -1
- package/dist/client/assets/{Spin-Bt_9cTiO.js → Spin-DwHJdgNz.js} +1 -1
- package/dist/client/assets/{Suffix-XaH8SDbR.js → Suffix-D6x-7akR.js} +1 -1
- package/dist/client/assets/{Switch-D1_psmjT.js → Switch-BvHRSSqt.js} +1 -1
- package/dist/client/assets/{Tag-3FaOhoJN.js → Tag-BMMlXaEi.js} +1 -1
- package/dist/client/assets/{TerminalView-DNU7oQxK.js → TerminalView-el6o2Q0a.js} +1 -1
- package/dist/client/assets/{Tooltip-YHrHWGPa.js → Tooltip-BM4wl764.js} +1 -1
- package/dist/client/assets/{UsageView-COCrOiiV.js → UsageView-DQ_YKoEV.js} +1 -1
- package/dist/client/assets/{Warning-B6CM9aBl.js → Warning-CEC7rgvY.js} +1 -1
- package/dist/client/assets/{_plugin-vue_export-helper-BGG8ORDx.js → _plugin-vue_export-helper-DgUZPfuZ.js} +1 -1
- package/dist/client/assets/app-DPUhLGXq.js +1 -0
- package/dist/client/assets/{app-B7ktf7Fh.js → app-DUt8TNq3.js} +1 -1
- package/dist/client/assets/{browser-f5W8abIG.js → browser-vxCOMmsq.js} +1 -1
- package/dist/client/assets/{chat-6q6pkzEW.js → chat-i_Ge_Lfr.js} +2 -2
- package/dist/client/assets/composables-jrQPIjcq.js +1 -0
- package/dist/client/assets/{fade-in.cssr-ifHK7yH1.js → fade-in.cssr-DVg2CkO3.js} +1 -1
- package/dist/client/assets/{index-CSCYx7ux.js → index-COwJ2oY0.js} +1 -1
- package/dist/client/assets/{jobs-DObWfhbO.js → jobs-Czr1RcSG.js} +1 -1
- package/dist/client/assets/{light-DgLcPjgU.js → light-3rSjNeC-.js} +1 -1
- package/dist/client/assets/{light-CxjyoF0s.js → light-CKDlpgGU.js} +1 -1
- package/dist/client/assets/{light-D1yfed_s.js → light-CiIDFs7y.js} +1 -1
- package/dist/client/assets/{light-TGFKT-UB.js → light-CoJqT8Vu.js} +1 -1
- package/dist/client/assets/{light-D_3MwJj1.js → light-DPRJ1OEN.js} +1 -1
- package/dist/client/assets/{light-DWy-mwyK.js → light-vTpJevRf.js} +1 -1
- package/dist/client/assets/{models-DQ4CT-vv.js → models-BzEeJuoO.js} +1 -1
- package/dist/client/assets/{pinia-DcAkZ8vx.js → pinia-BoNLlsLy.js} +1 -1
- package/dist/client/assets/{profiles-DzkigJwq.js → profiles-B-DFTmc2.js} +1 -1
- package/dist/client/assets/{router-D8sJ39Io.js → router-HHMeDEaP.js} +2 -2
- package/dist/client/assets/{sessions-Dg8n9PBo.js → sessions-BmxS_BoH.js} +1 -1
- package/dist/client/assets/{skills-BehzdECn.js → skills-Be8Mzr1r.js} +1 -1
- package/dist/client/assets/{use-message-DBz2JSTt.js → use-message-DBTY4945.js} +1 -1
- package/dist/client/assets/{useTheme-UdVT814n.js → useTheme-D58Cg7k2.js} +1 -1
- package/dist/client/index.html +27 -27
- package/dist/server/index.js +19 -199
- package/dist/server/routes/health.d.ts +4 -0
- package/dist/server/routes/health.js +109 -0
- package/dist/server/routes/hermes/group-chat.d.ts +2 -0
- package/dist/server/routes/hermes/group-chat.js +112 -101
- package/dist/server/routes/update.d.ts +2 -0
- package/dist/server/routes/update.js +69 -0
- package/dist/server/services/auth.js +1 -1
- package/dist/server/services/gateway-bootstrap.d.ts +2 -0
- package/dist/server/services/gateway-bootstrap.js +51 -0
- package/dist/server/services/hermes/group-chat/agent-clients.d.ts +133 -0
- package/dist/server/services/hermes/group-chat/agent-clients.js +364 -0
- package/dist/server/services/hermes/group-chat/index.d.ts +72 -0
- package/dist/server/services/hermes/group-chat/index.js +307 -0
- package/dist/server/services/shutdown.d.ts +1 -0
- package/dist/server/services/shutdown.js +37 -0
- package/package.json +1 -1
- package/dist/client/assets/app-BPvTl2-V.js +0 -1
- package/dist/client/assets/composables-xV7dhNpf.js +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
import{o as e}from"./router-
|
|
1
|
+
import{o as e}from"./router-HHMeDEaP.js";async function t(t,n){let r=new URLSearchParams;t&&r.set(`source`,t),n&&r.set(`limit`,String(n));let i=r.toString();return(await e(`/api/hermes/sessions${i?`?${i}`:``}`)).sessions}async function n(t){try{return(await e(`/api/hermes/sessions/${t}`)).session}catch{return null}}async function r(t){try{return await e(`/api/hermes/sessions/${t}`,{method:`DELETE`}),!0}catch{return!1}}async function i(t,n){try{return await e(`/api/hermes/sessions/${t}/rename`,{method:`POST`,body:JSON.stringify({title:n})}),!0}catch{return!1}}export{i,n,t as r,r as t};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{o as e}from"./router-
|
|
1
|
+
import{o as e}from"./router-HHMeDEaP.js";async function t(){return(await e(`/api/hermes/skills`)).categories}async function n(t){return(await e(`/api/hermes/skills/${t}`)).content}async function r(t,n){return(await e(`/api/hermes/skills/${t}/${n}/files`)).files}async function i(){return e(`/api/hermes/memory`)}async function a(t,n){await e(`/api/hermes/memory`,{method:`POST`,body:JSON.stringify({section:t,content:n})})}async function o(t,n){await e(`/api/hermes/skills/toggle`,{method:`PUT`,body:JSON.stringify({name:t,enabled:n})})}export{a,t as i,n,o,r,i as t};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{F as e}from"./router-
|
|
1
|
+
import{F as e}from"./router-HHMeDEaP.js";import{$ as t,Y as n}from"./browser-vxCOMmsq.js";var r=t(`n-message-api`),i=t(`n-message-provider`);function a(){let t=e(r,null);return t===null&&n(`use-message`,"No outer <n-message-provider /> founded. See prerequisite in https://www.naiveui.com/en-US/os-theme/components/message for more details. If you want to use `useMessage` outside setup, please check https://www.naiveui.com/zh-CN/os-theme/components/message#Q-&-A."),t}export{r as n,i as r,a as t};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{X as e,ct as t}from"./router-
|
|
1
|
+
import{X as e,ct as t}from"./router-HHMeDEaP.js";var n=`hermes_theme`,r=t(localStorage.getItem(n)||`system`),i=t(!1);function a(e){i.value=e,document.documentElement.classList.toggle(`dark`,e)}function o(e){return e===`system`?window.matchMedia(`(prefers-color-scheme: dark)`).matches:e===`dark`}a(o(r.value)),window.matchMedia(`(prefers-color-scheme: dark)`).addEventListener(`change`,()=>{r.value===`system`&&a(o(`system`))}),e(r,e=>{localStorage.setItem(n,e),a(o(e))});function s(){function e(e){r.value=e}function t(){r.value=i.value?`light`:`dark`}return{mode:r,isDark:i,setMode:e,toggleTheme:t}}export{s as t};
|
package/dist/client/index.html
CHANGED
|
@@ -6,36 +6,36 @@
|
|
|
6
6
|
<link rel="icon" type="image/svg+xml" href="/favicon.ico" />
|
|
7
7
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
8
8
|
<title>Hermes</title>
|
|
9
|
-
<script type="module" crossorigin src="/assets/index-
|
|
10
|
-
<link rel="modulepreload" crossorigin href="/assets/router-
|
|
11
|
-
<link rel="modulepreload" crossorigin href="/assets/_plugin-vue_export-helper-
|
|
12
|
-
<link rel="modulepreload" crossorigin href="/assets/browser-
|
|
13
|
-
<link rel="modulepreload" crossorigin href="/assets/fade-in.cssr-
|
|
14
|
-
<link rel="modulepreload" crossorigin href="/assets/Suffix-
|
|
15
|
-
<link rel="modulepreload" crossorigin href="/assets/Close-
|
|
16
|
-
<link rel="modulepreload" crossorigin href="/assets/Popover-
|
|
17
|
-
<link rel="modulepreload" crossorigin href="/assets/Button-
|
|
18
|
-
<link rel="modulepreload" crossorigin href="/assets/Tag-
|
|
9
|
+
<script type="module" crossorigin src="/assets/index-COwJ2oY0.js"></script>
|
|
10
|
+
<link rel="modulepreload" crossorigin href="/assets/router-HHMeDEaP.js">
|
|
11
|
+
<link rel="modulepreload" crossorigin href="/assets/_plugin-vue_export-helper-DgUZPfuZ.js">
|
|
12
|
+
<link rel="modulepreload" crossorigin href="/assets/browser-vxCOMmsq.js">
|
|
13
|
+
<link rel="modulepreload" crossorigin href="/assets/fade-in.cssr-DVg2CkO3.js">
|
|
14
|
+
<link rel="modulepreload" crossorigin href="/assets/Suffix-D6x-7akR.js">
|
|
15
|
+
<link rel="modulepreload" crossorigin href="/assets/Close-DbXijZpL.js">
|
|
16
|
+
<link rel="modulepreload" crossorigin href="/assets/Popover-DiVI0l6E.js">
|
|
17
|
+
<link rel="modulepreload" crossorigin href="/assets/Button-uvjCWO-i.js">
|
|
18
|
+
<link rel="modulepreload" crossorigin href="/assets/Tag-BMMlXaEi.js">
|
|
19
19
|
<link rel="modulepreload" crossorigin href="/assets/create-5zWq3BEB.js">
|
|
20
|
-
<link rel="modulepreload" crossorigin href="/assets/Select-
|
|
21
|
-
<link rel="modulepreload" crossorigin href="/assets/Warning-
|
|
22
|
-
<link rel="modulepreload" crossorigin href="/assets/Modal-
|
|
23
|
-
<link rel="modulepreload" crossorigin href="/assets/Input-
|
|
24
|
-
<link rel="modulepreload" crossorigin href="/assets/light-
|
|
20
|
+
<link rel="modulepreload" crossorigin href="/assets/Select-BqUA1wxE.js">
|
|
21
|
+
<link rel="modulepreload" crossorigin href="/assets/Warning-CEC7rgvY.js">
|
|
22
|
+
<link rel="modulepreload" crossorigin href="/assets/Modal-DDUFP8vh.js">
|
|
23
|
+
<link rel="modulepreload" crossorigin href="/assets/Input-CjlUbV0M.js">
|
|
24
|
+
<link rel="modulepreload" crossorigin href="/assets/light-CiIDFs7y.js">
|
|
25
25
|
<link rel="modulepreload" crossorigin href="/assets/omit-1BRB6K75.js">
|
|
26
|
-
<link rel="modulepreload" crossorigin href="/assets/pinia-
|
|
27
|
-
<link rel="modulepreload" crossorigin href="/assets/profiles-
|
|
28
|
-
<link rel="modulepreload" crossorigin href="/assets/sessions-
|
|
29
|
-
<link rel="modulepreload" crossorigin href="/assets/app-
|
|
30
|
-
<link rel="modulepreload" crossorigin href="/assets/chat-
|
|
31
|
-
<link rel="modulepreload" crossorigin href="/assets/light-
|
|
32
|
-
<link rel="modulepreload" crossorigin href="/assets/use-message-
|
|
33
|
-
<link rel="modulepreload" crossorigin href="/assets/light-
|
|
34
|
-
<link rel="modulepreload" crossorigin href="/assets/light-
|
|
26
|
+
<link rel="modulepreload" crossorigin href="/assets/pinia-BoNLlsLy.js">
|
|
27
|
+
<link rel="modulepreload" crossorigin href="/assets/profiles-B-DFTmc2.js">
|
|
28
|
+
<link rel="modulepreload" crossorigin href="/assets/sessions-BmxS_BoH.js">
|
|
29
|
+
<link rel="modulepreload" crossorigin href="/assets/app-DUt8TNq3.js">
|
|
30
|
+
<link rel="modulepreload" crossorigin href="/assets/chat-i_Ge_Lfr.js">
|
|
31
|
+
<link rel="modulepreload" crossorigin href="/assets/light-CoJqT8Vu.js">
|
|
32
|
+
<link rel="modulepreload" crossorigin href="/assets/use-message-DBTY4945.js">
|
|
33
|
+
<link rel="modulepreload" crossorigin href="/assets/light-vTpJevRf.js">
|
|
34
|
+
<link rel="modulepreload" crossorigin href="/assets/light-CKDlpgGU.js">
|
|
35
35
|
<link rel="modulepreload" crossorigin href="/assets/_common-Yp55QE79.js">
|
|
36
|
-
<link rel="modulepreload" crossorigin href="/assets/light-
|
|
37
|
-
<link rel="modulepreload" crossorigin href="/assets/light-
|
|
38
|
-
<link rel="modulepreload" crossorigin href="/assets/useTheme-
|
|
36
|
+
<link rel="modulepreload" crossorigin href="/assets/light-DPRJ1OEN.js">
|
|
37
|
+
<link rel="modulepreload" crossorigin href="/assets/light-3rSjNeC-.js">
|
|
38
|
+
<link rel="modulepreload" crossorigin href="/assets/useTheme-D58Cg7k2.js">
|
|
39
39
|
<link rel="modulepreload" crossorigin href="/assets/logo-Cd-t_oGE.js">
|
|
40
40
|
<link rel="stylesheet" crossorigin href="/assets/index-BEcRccNA.css">
|
|
41
41
|
</head>
|
package/dist/server/index.js
CHANGED
|
@@ -1,37 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
2
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
4
|
};
|
|
@@ -42,130 +9,41 @@ const cors_1 = __importDefault(require("@koa/cors"));
|
|
|
42
9
|
const bodyparser_1 = __importDefault(require("@koa/bodyparser"));
|
|
43
10
|
const koa_static_1 = __importDefault(require("koa-static"));
|
|
44
11
|
const koa_send_1 = __importDefault(require("koa-send"));
|
|
12
|
+
const os_1 = __importDefault(require("os"));
|
|
45
13
|
const path_1 = require("path");
|
|
46
14
|
const promises_1 = require("fs/promises");
|
|
47
|
-
const fs_1 = require("fs");
|
|
48
15
|
const config_1 = require("./config");
|
|
49
16
|
const hermes_1 = require("./routes/hermes");
|
|
50
17
|
const upload_1 = require("./routes/upload");
|
|
51
18
|
const webhook_1 = require("./routes/webhook");
|
|
52
|
-
const
|
|
19
|
+
const update_1 = require("./routes/update");
|
|
20
|
+
const health_1 = require("./routes/health");
|
|
53
21
|
const auth_1 = require("./services/auth");
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
// dev: packages/server/src → ../../../package.json
|
|
57
|
-
const candidates = [
|
|
58
|
-
(0, path_1.resolve)(__dirname, '../../package.json'),
|
|
59
|
-
(0, path_1.resolve)(__dirname, '../../../package.json'),
|
|
60
|
-
];
|
|
61
|
-
for (const p of candidates) {
|
|
62
|
-
try {
|
|
63
|
-
return JSON.parse((0, fs_1.readFileSync)(p, 'utf-8')).version;
|
|
64
|
-
}
|
|
65
|
-
catch { }
|
|
66
|
-
}
|
|
67
|
-
return '0.0.0';
|
|
68
|
-
}
|
|
69
|
-
const LOCAL_VERSION = getLocalVersion();
|
|
70
|
-
let cachedLatestVersion = '';
|
|
71
|
-
async function checkLatestVersion() {
|
|
72
|
-
try {
|
|
73
|
-
const res = await fetch('https://registry.npmjs.org/hermes-web-ui/latest', {
|
|
74
|
-
signal: AbortSignal.timeout(5000),
|
|
75
|
-
headers: { 'Cache-Control': 'no-cache' },
|
|
76
|
-
});
|
|
77
|
-
if (res.ok) {
|
|
78
|
-
const data = await res.json();
|
|
79
|
-
const latest = data.version || '';
|
|
80
|
-
if (latest && latest !== cachedLatestVersion) {
|
|
81
|
-
cachedLatestVersion = latest;
|
|
82
|
-
if (latest !== LOCAL_VERSION) {
|
|
83
|
-
console.log(`⬆ New version available: v${LOCAL_VERSION} → v${latest}`);
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
catch { }
|
|
89
|
-
}
|
|
90
|
-
const app = new koa_1.default();
|
|
91
|
-
const { restartGateway, startGateway, startGatewayBackground, getVersion } = hermesCli;
|
|
22
|
+
const gateway_bootstrap_1 = require("./services/gateway-bootstrap");
|
|
23
|
+
const shutdown_1 = require("./services/shutdown");
|
|
92
24
|
let server = null;
|
|
93
|
-
let isShuttingDown = false;
|
|
94
|
-
// 👉 如果你有子进程,一定要存
|
|
95
|
-
let gatewayPid = null;
|
|
96
|
-
let gatewayManager = null;
|
|
97
25
|
async function bootstrap() {
|
|
98
26
|
await (0, promises_1.mkdir)(config_1.config.uploadDir, { recursive: true });
|
|
99
27
|
await (0, promises_1.mkdir)(config_1.config.dataDir, { recursive: true });
|
|
100
|
-
// Auth (after mkdir so data dir exists)
|
|
101
28
|
const authToken = await (0, auth_1.getToken)();
|
|
29
|
+
const app = new koa_1.default();
|
|
102
30
|
if (authToken) {
|
|
103
31
|
app.use(await (0, auth_1.authMiddleware)(authToken));
|
|
104
32
|
console.log(`🔐 Auth enabled — token: ${authToken}`);
|
|
105
33
|
}
|
|
106
|
-
await initGatewayManager();
|
|
34
|
+
await (0, gateway_bootstrap_1.initGatewayManager)();
|
|
107
35
|
app.use((0, cors_1.default)({ origin: config_1.config.corsOrigins }));
|
|
108
36
|
app.use((0, bodyparser_1.default)());
|
|
37
|
+
// Shared routes (no agent prefix)
|
|
109
38
|
app.use(webhook_1.webhookRoutes.routes());
|
|
110
39
|
app.use(upload_1.uploadRoutes.routes());
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
if (ctx.path === '/api/hermes/update' && ctx.method === 'POST') {
|
|
114
|
-
const isWin = process.platform === 'win32';
|
|
115
|
-
// Run npm install directly — calling `hermes-web-ui update` would kill this
|
|
116
|
-
// process (stopDaemon) before the response can be sent to the client.
|
|
117
|
-
const cmd = isWin
|
|
118
|
-
? 'cmd /c npm install -g hermes-web-ui@latest'
|
|
119
|
-
: 'npm install -g hermes-web-ui@latest';
|
|
120
|
-
try {
|
|
121
|
-
const { execSync } = await Promise.resolve().then(() => __importStar(require('child_process')));
|
|
122
|
-
const output = execSync(cmd, {
|
|
123
|
-
encoding: 'utf-8',
|
|
124
|
-
timeout: 120000,
|
|
125
|
-
stdio: ['pipe', 'pipe', 'pipe'],
|
|
126
|
-
});
|
|
127
|
-
ctx.body = { success: true, message: output.trim() };
|
|
128
|
-
// Restart the server after response is sent
|
|
129
|
-
setTimeout(() => process.exit(0), 1000);
|
|
130
|
-
}
|
|
131
|
-
catch (err) {
|
|
132
|
-
ctx.status = 500;
|
|
133
|
-
ctx.body = { success: false, message: err.stderr || err.message };
|
|
134
|
-
}
|
|
135
|
-
return;
|
|
136
|
-
}
|
|
137
|
-
await next();
|
|
138
|
-
});
|
|
40
|
+
app.use(update_1.updateRoutes.routes());
|
|
41
|
+
// Hermes routes (must be after update — proxy catch-all matches everything)
|
|
139
42
|
app.use(hermes_1.hermesRoutes.routes());
|
|
140
43
|
app.use(hermes_1.proxyMiddleware);
|
|
141
|
-
//
|
|
142
|
-
app.use(
|
|
143
|
-
|
|
144
|
-
const raw = await getVersion();
|
|
145
|
-
const hermesVersion = raw.split('\n')[0].replace('Hermes Agent ', '') || '';
|
|
146
|
-
let gatewayOk = false;
|
|
147
|
-
try {
|
|
148
|
-
const upstream = gatewayManager?.getUpstream() || config_1.config.upstream;
|
|
149
|
-
const res = await fetch(`${upstream.replace(/\/$/, '')}/health`, {
|
|
150
|
-
signal: AbortSignal.timeout(5000),
|
|
151
|
-
});
|
|
152
|
-
gatewayOk = res.ok;
|
|
153
|
-
}
|
|
154
|
-
catch { }
|
|
155
|
-
ctx.body = {
|
|
156
|
-
status: gatewayOk ? 'ok' : 'error',
|
|
157
|
-
platform: 'hermes-agent',
|
|
158
|
-
version: hermesVersion,
|
|
159
|
-
gateway: gatewayOk ? 'running' : 'stopped',
|
|
160
|
-
webui_version: LOCAL_VERSION,
|
|
161
|
-
webui_latest: cachedLatestVersion,
|
|
162
|
-
webui_update_available: cachedLatestVersion && cachedLatestVersion !== LOCAL_VERSION,
|
|
163
|
-
};
|
|
164
|
-
return;
|
|
165
|
-
}
|
|
166
|
-
await next();
|
|
167
|
-
});
|
|
168
|
-
// SPA
|
|
44
|
+
// Health check
|
|
45
|
+
app.use(health_1.healthRoutes.routes());
|
|
46
|
+
// SPA fallback
|
|
169
47
|
const distDir = (0, path_1.resolve)(__dirname, '..', 'client');
|
|
170
48
|
app.use((0, koa_static_1.default)(distDir));
|
|
171
49
|
app.use(async (ctx) => {
|
|
@@ -176,77 +54,19 @@ async function bootstrap() {
|
|
|
176
54
|
await (0, koa_send_1.default)(ctx, 'index.html', { root: distDir });
|
|
177
55
|
}
|
|
178
56
|
});
|
|
179
|
-
//
|
|
57
|
+
// Start server
|
|
180
58
|
server = app.listen(config_1.config.port, '0.0.0.0');
|
|
181
|
-
// Terminal WebSocket (must be after server is created)
|
|
182
59
|
(0, hermes_1.setupTerminalWebSocket)(server);
|
|
183
60
|
server.on('listening', () => {
|
|
184
|
-
|
|
61
|
+
const interfaces = os_1.default.networkInterfaces();
|
|
62
|
+
const localIp = Object.values(interfaces).flat().find(i => i?.family === 'IPv4' && !i?.internal)?.address || 'localhost';
|
|
63
|
+
console.log(`➜ Server: http://localhost:${config_1.config.port} (LAN: http://${localIp}:${config_1.config.port})`);
|
|
185
64
|
console.log(`➜ Upstream: ${config_1.config.upstream}`);
|
|
186
65
|
});
|
|
187
66
|
server.on('error', (err) => {
|
|
188
67
|
console.error('Server error:', err.message);
|
|
189
68
|
});
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
// Check for updates every 4 hours
|
|
193
|
-
checkLatestVersion();
|
|
194
|
-
setInterval(checkLatestVersion, 60 * 60 * 1000);
|
|
195
|
-
}
|
|
196
|
-
// ============================
|
|
197
|
-
// ✅ 统一关闭逻辑(核心)
|
|
198
|
-
// ============================
|
|
199
|
-
function bindShutdown() {
|
|
200
|
-
const shutdown = async (signal) => {
|
|
201
|
-
if (isShuttingDown)
|
|
202
|
-
return;
|
|
203
|
-
isShuttingDown = true;
|
|
204
|
-
console.log(`\n[${signal}] shutting down...`);
|
|
205
|
-
try {
|
|
206
|
-
// ✅ 1. 关闭 HTTP server
|
|
207
|
-
if (server) {
|
|
208
|
-
await new Promise((resolve) => {
|
|
209
|
-
server.close(() => {
|
|
210
|
-
console.log('✓ http server closed');
|
|
211
|
-
resolve();
|
|
212
|
-
});
|
|
213
|
-
});
|
|
214
|
-
}
|
|
215
|
-
// gateway 是系统服务,不随 dev server 退出而停止
|
|
216
|
-
}
|
|
217
|
-
catch (err) {
|
|
218
|
-
console.error('shutdown error:', err);
|
|
219
|
-
}
|
|
220
|
-
process.exit(0);
|
|
221
|
-
};
|
|
222
|
-
// 👉 nodemon 专用(必须 once)
|
|
223
|
-
process.once('SIGUSR2', shutdown);
|
|
224
|
-
// 👉 正常退出
|
|
225
|
-
process.on('SIGINT', shutdown);
|
|
226
|
-
process.on('SIGTERM', shutdown);
|
|
227
|
-
// 👉 防止异常退出没处理
|
|
228
|
-
process.on('uncaughtException', (err) => {
|
|
229
|
-
console.error('uncaughtException:', err);
|
|
230
|
-
shutdown('uncaughtException');
|
|
231
|
-
});
|
|
232
|
-
process.on('unhandledRejection', (err) => {
|
|
233
|
-
console.error('unhandledRejection:', err);
|
|
234
|
-
shutdown('unhandledRejection');
|
|
235
|
-
});
|
|
236
|
-
}
|
|
237
|
-
// ============================
|
|
238
|
-
// Gateway Manager
|
|
239
|
-
// ============================
|
|
240
|
-
async function initGatewayManager() {
|
|
241
|
-
const { GatewayManager } = await Promise.resolve().then(() => __importStar(require('./services/hermes/gateway-manager')));
|
|
242
|
-
const { getActiveProfileName } = await Promise.resolve().then(() => __importStar(require('./services/hermes/hermes-profile')));
|
|
243
|
-
const { setGatewayManager } = await Promise.resolve().then(() => __importStar(require('./routes/hermes/gateways')));
|
|
244
|
-
const activeProfile = getActiveProfileName();
|
|
245
|
-
gatewayManager = new GatewayManager(activeProfile);
|
|
246
|
-
setGatewayManager(gatewayManager);
|
|
247
|
-
// Detect all running gateways
|
|
248
|
-
await gatewayManager.detectAllOnStartup();
|
|
249
|
-
// Start all gateways that aren't running
|
|
250
|
-
await gatewayManager.startAll();
|
|
69
|
+
(0, shutdown_1.bindShutdown)(server);
|
|
70
|
+
(0, health_1.startVersionCheck)();
|
|
251
71
|
}
|
|
252
72
|
bootstrap();
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.healthRoutes = void 0;
|
|
40
|
+
exports.checkLatestVersion = checkLatestVersion;
|
|
41
|
+
exports.startVersionCheck = startVersionCheck;
|
|
42
|
+
const router_1 = __importDefault(require("@koa/router"));
|
|
43
|
+
const path_1 = require("path");
|
|
44
|
+
const fs_1 = require("fs");
|
|
45
|
+
const gateways_1 = require("./hermes/gateways");
|
|
46
|
+
const hermesCli = __importStar(require("../services/hermes/hermes-cli"));
|
|
47
|
+
const config_1 = require("../config");
|
|
48
|
+
function getLocalVersion() {
|
|
49
|
+
const candidates = [
|
|
50
|
+
(0, path_1.resolve)(__dirname, '../../../package.json'),
|
|
51
|
+
(0, path_1.resolve)(__dirname, '../../../../package.json'),
|
|
52
|
+
];
|
|
53
|
+
for (const p of candidates) {
|
|
54
|
+
try {
|
|
55
|
+
return JSON.parse((0, fs_1.readFileSync)(p, 'utf-8')).version;
|
|
56
|
+
}
|
|
57
|
+
catch { }
|
|
58
|
+
}
|
|
59
|
+
return '0.0.0';
|
|
60
|
+
}
|
|
61
|
+
const LOCAL_VERSION = getLocalVersion();
|
|
62
|
+
let cachedLatestVersion = '';
|
|
63
|
+
async function checkLatestVersion() {
|
|
64
|
+
try {
|
|
65
|
+
const res = await fetch('https://registry.npmjs.org/hermes-web-ui/latest', {
|
|
66
|
+
signal: AbortSignal.timeout(5000),
|
|
67
|
+
headers: { 'Cache-Control': 'no-cache' },
|
|
68
|
+
});
|
|
69
|
+
if (res.ok) {
|
|
70
|
+
const data = await res.json();
|
|
71
|
+
const latest = data.version || '';
|
|
72
|
+
if (latest && latest !== cachedLatestVersion) {
|
|
73
|
+
cachedLatestVersion = latest;
|
|
74
|
+
if (latest !== LOCAL_VERSION) {
|
|
75
|
+
console.log(`⬆ New version available: v${LOCAL_VERSION} → v${latest}`);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
catch { }
|
|
81
|
+
}
|
|
82
|
+
function startVersionCheck() {
|
|
83
|
+
checkLatestVersion();
|
|
84
|
+
setInterval(checkLatestVersion, 60 * 60 * 1000);
|
|
85
|
+
}
|
|
86
|
+
exports.healthRoutes = new router_1.default();
|
|
87
|
+
exports.healthRoutes.get('/health', async (ctx) => {
|
|
88
|
+
const raw = await hermesCli.getVersion();
|
|
89
|
+
const hermesVersion = raw.split('\n')[0].replace('Hermes Agent ', '') || '';
|
|
90
|
+
let gatewayOk = false;
|
|
91
|
+
try {
|
|
92
|
+
const mgr = (0, gateways_1.getGatewayManager)();
|
|
93
|
+
const upstream = mgr?.getUpstream() || config_1.config.upstream;
|
|
94
|
+
const res = await fetch(`${upstream.replace(/\/$/, '')}/health`, {
|
|
95
|
+
signal: AbortSignal.timeout(5000),
|
|
96
|
+
});
|
|
97
|
+
gatewayOk = res.ok;
|
|
98
|
+
}
|
|
99
|
+
catch { }
|
|
100
|
+
ctx.body = {
|
|
101
|
+
status: gatewayOk ? 'ok' : 'error',
|
|
102
|
+
platform: 'hermes-agent',
|
|
103
|
+
version: hermesVersion,
|
|
104
|
+
gateway: gatewayOk ? 'running' : 'stopped',
|
|
105
|
+
webui_version: LOCAL_VERSION,
|
|
106
|
+
webui_latest: cachedLatestVersion,
|
|
107
|
+
webui_update_available: cachedLatestVersion && cachedLatestVersion !== LOCAL_VERSION,
|
|
108
|
+
};
|
|
109
|
+
});
|
|
@@ -1,2 +1,4 @@
|
|
|
1
1
|
import Router from '@koa/router';
|
|
2
|
+
import type { GroupChatServer } from '../../services/hermes/group-chat';
|
|
2
3
|
export declare const groupChatRoutes: Router<import("koa").DefaultState, import("koa").DefaultContext>;
|
|
4
|
+
export declare function setGroupChatServer(server: GroupChatServer): void;
|