hermes-web-ui 0.2.2 → 0.2.3

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.
Files changed (89) hide show
  1. package/README.md +30 -6
  2. package/bin/hermes-web-ui.mjs +34 -4
  3. package/dist/assets/Button-CQLKwjHl.js +109 -0
  4. package/dist/assets/ChannelsView-Bdv3P2Rv.js +1 -0
  5. package/dist/assets/ChatView-BGSDL0hI.js +142 -0
  6. package/dist/assets/{ChatView-BVHQ6KhU.css → ChatView-CGsFaSiv.css} +1 -1
  7. package/dist/assets/Close-inn9RP7R.js +45 -0
  8. package/dist/assets/FormItem-BvJieJmq.js +110 -0
  9. package/dist/assets/Input-edKmVCeM.js +234 -0
  10. package/dist/assets/InputNumber-BpYEJnKY.js +13 -0
  11. package/dist/assets/JobsView-Dx4HmGC6.js +2 -0
  12. package/dist/assets/LoginView-BHThbj0n.css +1 -0
  13. package/dist/assets/LoginView-CIQSZ6bh.js +1 -0
  14. package/dist/assets/LogsView-nn7t6RGX.js +1 -0
  15. package/dist/assets/{MarkdownRenderer-C2pkccH2.js → MarkdownRenderer-Yw5JS7CE.js} +9 -9
  16. package/dist/assets/MemoryView-CE9P7mef.js +5 -0
  17. package/dist/assets/Modal-CDRYujZp.js +232 -0
  18. package/dist/assets/ModelsView-B72PAvvd.js +1 -0
  19. package/dist/assets/Popover-CRhyj79I.js +117 -0
  20. package/dist/assets/Select-CXQmv_5e.js +340 -0
  21. package/dist/assets/SettingRow-B3O4TYKh.js +1 -0
  22. package/dist/assets/SettingsView-BF2Uh-Eo.js +352 -0
  23. package/dist/assets/SkillsView-Abm6Dt2r.css +1 -0
  24. package/dist/assets/SkillsView-CeUPV9g8.js +1 -0
  25. package/dist/assets/Spin-COypV4Iq.js +43 -0
  26. package/dist/assets/Suffix-Bs0SC_yA.js +101 -0
  27. package/dist/assets/Switch-BcUqwhfi.js +102 -0
  28. package/dist/assets/Tag-CVO-_zgr.js +71 -0
  29. package/dist/assets/Tooltip-BljrRE17.js +1 -0
  30. package/dist/assets/UsageView-CFH6hwxE.js +1 -0
  31. package/dist/assets/_plugin-vue_export-helper-DJRCopG_.js +3 -0
  32. package/dist/assets/app-BcCNNvPk.js +1 -0
  33. package/dist/assets/app-CMJknO_z.js +1 -0
  34. package/dist/assets/browser-BuJOvks2.js +47 -0
  35. package/dist/assets/chat-DIeO-6BT.js +6 -0
  36. package/dist/assets/context-C8Jv60vX.js +1 -0
  37. package/dist/assets/index-BZ3NfTDJ.css +1 -0
  38. package/dist/assets/index-Bj9YOu02.js +306 -0
  39. package/dist/assets/jobs-CnB9OiiZ.js +1 -0
  40. package/dist/assets/logo-CiQBpLPw.js +1 -0
  41. package/dist/assets/pinia-YU9i-6Bb.js +1 -0
  42. package/dist/assets/router--r9mOZY5.js +4 -0
  43. package/dist/assets/{sessions-DYkP_X2v.js → sessions-COjIc6fz.js} +1 -1
  44. package/dist/assets/{skills-C6QBmS9j.js → skills-C4yD0aCK.js} +1 -1
  45. package/dist/assets/use-message-D8bO1GLN.js +1 -0
  46. package/dist/index.html +18 -18
  47. package/dist/server/index.js +104 -61
  48. package/dist/server/routes/filesystem.js +38 -0
  49. package/dist/server/services/auth.d.ts +9 -0
  50. package/dist/server/services/auth.js +65 -0
  51. package/dist/server/services/hermes-cli.js +13 -1
  52. package/package.json +2 -2
  53. package/dist/assets/Button-CpNld4Mc.js +0 -109
  54. package/dist/assets/ChannelsView-BGXB46ZU.js +0 -1
  55. package/dist/assets/ChatView-CaO-j1NR.js +0 -142
  56. package/dist/assets/Close-BAvirVyH.js +0 -45
  57. package/dist/assets/FormItem-DUC1YCrh.js +0 -110
  58. package/dist/assets/Input-CCmp4iGM.js +0 -234
  59. package/dist/assets/InputNumber-DpIdrMEW.js +0 -13
  60. package/dist/assets/JobsView-t5o1pB0r.js +0 -2
  61. package/dist/assets/LogsView-QqOV3ZEf.js +0 -1
  62. package/dist/assets/MemoryView-oeAn8ZfB.js +0 -5
  63. package/dist/assets/Modal-BljFqAJF.js +0 -232
  64. package/dist/assets/ModelsView-DvK44HBy.js +0 -1
  65. package/dist/assets/Popover-BQMR8Xxo.js +0 -117
  66. package/dist/assets/Select-D33SMWcz.js +0 -340
  67. package/dist/assets/SettingRow-BxCsRfGG.js +0 -102
  68. package/dist/assets/SettingsView-CK9ArFcg.js +0 -352
  69. package/dist/assets/SkillsView-BvNhRbMq.css +0 -1
  70. package/dist/assets/SkillsView-_z2SQ9kJ.js +0 -1
  71. package/dist/assets/Spin-CwbBDHwW.js +0 -43
  72. package/dist/assets/Suffix-CKUJBJSi.js +0 -101
  73. package/dist/assets/Tag-87KswiOb.js +0 -71
  74. package/dist/assets/Tooltip-CuLVJgy8.js +0 -1
  75. package/dist/assets/UsageView-COiUupLe.js +0 -1
  76. package/dist/assets/_plugin-vue_export-helper-C7dadZ10.js +0 -49
  77. package/dist/assets/app-DX-WvBe8.js +0 -1
  78. package/dist/assets/app-DwI_Lyfm.js +0 -1
  79. package/dist/assets/chat-De2jGIM6.js +0 -6
  80. package/dist/assets/client-D-w1KhaU.js +0 -1
  81. package/dist/assets/context-vjXbZCu8.js +0 -1
  82. package/dist/assets/index-D3MGnlpF.js +0 -307
  83. package/dist/assets/index-DCNlSGk-.css +0 -1
  84. package/dist/assets/jobs-B2WdYQNb.js +0 -1
  85. package/dist/assets/pinia-B4dETPKk.js +0 -1
  86. package/dist/assets/preload-helper-D4M6sveU.js +0 -1
  87. package/dist/assets/use-message-BeTKmVAO.js +0 -1
  88. package/dist/assets/vue.runtime.esm-bundler-BoqZ7fRe.js +0 -3
  89. /package/dist/{assets/logo-BAarh-tH.png → logo.png} +0 -0
@@ -54,13 +54,24 @@ const filesystem_1 = require("./routes/filesystem");
54
54
  const config_2 = require("./routes/config");
55
55
  const weixin_1 = require("./routes/weixin");
56
56
  const hermesCli = __importStar(require("./services/hermes-cli"));
57
+ const auth_1 = require("./services/auth");
58
+ const app = new koa_1.default();
57
59
  const { restartGateway, startGateway, startGatewayBackground, getVersion } = hermesCli;
60
+ let server = null;
61
+ let isShuttingDown = false;
62
+ // 👉 如果你有子进程,一定要存
63
+ let gatewayPid = null;
58
64
  async function bootstrap() {
59
65
  await (0, promises_1.mkdir)(config_1.config.uploadDir, { recursive: true });
60
66
  await (0, promises_1.mkdir)(config_1.config.dataDir, { recursive: true });
67
+ // Auth (after mkdir so data dir exists)
68
+ const authToken = await (0, auth_1.getToken)();
69
+ if (authToken) {
70
+ app.use(await (0, auth_1.authMiddleware)(authToken));
71
+ console.log(`🔐 Auth enabled — token: ${authToken}`);
72
+ }
61
73
  await ensureApiServerConfig();
62
74
  await ensureGatewayRunning();
63
- const app = new koa_1.default();
64
75
  app.use((0, cors_1.default)({ origin: config_1.config.corsOrigins }));
65
76
  app.use((0, bodyparser_1.default)());
66
77
  app.use(webhook_1.webhookRoutes.routes());
@@ -70,7 +81,7 @@ async function bootstrap() {
70
81
  app.use(filesystem_1.fsRoutes.routes());
71
82
  app.use(config_2.configRoutes.routes());
72
83
  app.use(weixin_1.weixinRoutes.routes());
73
- // Health endpoint: check CLI version + gateway connectivity
84
+ // health
74
85
  app.use(async (ctx, next) => {
75
86
  if (ctx.path === '/health') {
76
87
  const raw = await getVersion();
@@ -82,7 +93,7 @@ async function bootstrap() {
82
93
  });
83
94
  gatewayOk = res.ok;
84
95
  }
85
- catch { /* not reachable */ }
96
+ catch { }
86
97
  ctx.body = {
87
98
  status: gatewayOk ? 'ok' : 'error',
88
99
  platform: 'hermes-agent',
@@ -94,25 +105,87 @@ async function bootstrap() {
94
105
  await next();
95
106
  });
96
107
  app.use(proxy_1.proxyRoutes.routes());
97
- // SPA fallback
108
+ // SPA
98
109
  const distDir = (0, path_1.resolve)(__dirname, '..');
99
110
  app.use((0, koa_static_1.default)(distDir));
100
111
  app.use(async (ctx) => {
101
- if (!ctx.path.startsWith('/api') && !ctx.path.startsWith('/v1') && ctx.path !== '/health' && ctx.path !== '/upload' && ctx.path !== '/webhook') {
112
+ if (!ctx.path.startsWith('/api') &&
113
+ !ctx.path.startsWith('/v1') &&
114
+ ctx.path !== '/health' &&
115
+ ctx.path !== '/upload' &&
116
+ ctx.path !== '/webhook') {
102
117
  await (0, koa_send_1.default)(ctx, 'index.html', { root: distDir });
103
118
  }
104
119
  });
105
- app.listen(config_1.config.port, '0.0.0.0', () => {
106
- console.log(` ➜ Hermes BFF Server: http://localhost:${config_1.config.port}`);
107
- console.log(` ➜ Upstream: ${config_1.config.upstream}`);
120
+ // 🚀 启动服务
121
+ server = app.listen(config_1.config.port, '0.0.0.0');
122
+ server.on('listening', () => {
123
+ console.log(`➜ Server: http://localhost:${config_1.config.port}`);
124
+ console.log(`➜ Upstream: ${config_1.config.upstream}`);
125
+ });
126
+ server.on('error', (err) => {
127
+ console.error('Server error:', err.message);
108
128
  });
129
+ // 👇 绑定退出信号
130
+ bindShutdown();
109
131
  }
132
+ // ============================
133
+ // ✅ 统一关闭逻辑(核心)
134
+ // ============================
135
+ function bindShutdown() {
136
+ const shutdown = async (signal) => {
137
+ if (isShuttingDown)
138
+ return;
139
+ isShuttingDown = true;
140
+ console.log(`\n[${signal}] shutting down...`);
141
+ try {
142
+ // ✅ 1. 关闭 HTTP server
143
+ if (server) {
144
+ await new Promise((resolve) => {
145
+ server.close(() => {
146
+ console.log('✓ http server closed');
147
+ resolve();
148
+ });
149
+ });
150
+ }
151
+ // ✅ 2. 关闭子进程(如果有)
152
+ if (gatewayPid) {
153
+ try {
154
+ process.kill(gatewayPid);
155
+ console.log(`✓ gateway process killed: ${gatewayPid}`);
156
+ }
157
+ catch { }
158
+ }
159
+ }
160
+ catch (err) {
161
+ console.error('shutdown error:', err);
162
+ }
163
+ process.exit(0);
164
+ };
165
+ // 👉 nodemon 专用(必须 once)
166
+ process.once('SIGUSR2', shutdown);
167
+ // 👉 正常退出
168
+ process.on('SIGINT', shutdown);
169
+ process.on('SIGTERM', shutdown);
170
+ // 👉 防止异常退出没处理
171
+ process.on('uncaughtException', (err) => {
172
+ console.error('uncaughtException:', err);
173
+ shutdown('uncaughtException');
174
+ });
175
+ process.on('unhandledRejection', (err) => {
176
+ console.error('unhandledRejection:', err);
177
+ shutdown('unhandledRejection');
178
+ });
179
+ }
180
+ // ============================
181
+ // 你的原逻辑(基本不动)
182
+ // ============================
110
183
  async function ensureApiServerConfig() {
111
184
  const { homedir } = await Promise.resolve().then(() => __importStar(require('os')));
112
185
  const { readFileSync, writeFileSync, existsSync, copyFileSync } = await Promise.resolve().then(() => __importStar(require('fs')));
113
186
  const yaml = (await Promise.resolve().then(() => __importStar(require('js-yaml')))).default;
114
187
  const configPath = (0, path_1.resolve)(homedir(), '.hermes/config.yaml');
115
- const apiServerDefaults = {
188
+ const defaults = {
116
189
  enabled: true,
117
190
  host: '127.0.0.1',
118
191
  port: 8642,
@@ -121,83 +194,53 @@ async function ensureApiServerConfig() {
121
194
  };
122
195
  try {
123
196
  if (!existsSync(configPath)) {
124
- console.log(' ✗ config.yaml not found, run "hermes setup" first');
197
+ console.log('✗ config.yaml not found');
125
198
  return;
126
199
  }
127
200
  const content = readFileSync(configPath, 'utf-8');
128
- const config = yaml.load(content) || {};
129
- if (!config.platforms)
130
- config.platforms = {};
131
- if (!config.platforms.api_server)
132
- config.platforms.api_server = {};
133
- const api = config.platforms.api_server;
134
- let needsUpdate = false;
135
- for (const [key, value] of Object.entries(apiServerDefaults)) {
136
- if (api[key] === undefined || api[key] === null) {
137
- api[key] = value;
138
- needsUpdate = true;
201
+ const cfg = yaml.load(content) || {};
202
+ if (!cfg.platforms)
203
+ cfg.platforms = {};
204
+ if (!cfg.platforms.api_server)
205
+ cfg.platforms.api_server = {};
206
+ const api = cfg.platforms.api_server;
207
+ let changed = false;
208
+ for (const [k, v] of Object.entries(defaults)) {
209
+ if (api[k] != null && api[k] !== v) {
210
+ api[k] = v;
211
+ changed = true;
139
212
  }
140
213
  }
141
- if (!needsUpdate) {
142
- console.log(' ✓ api_server config is correct');
214
+ if (!changed)
143
215
  return;
144
- }
145
- // Backup before modifying
146
216
  copyFileSync(configPath, configPath + '.bak');
147
- const updated = yaml.dump(config, { lineWidth: -1, noRefs: true, quotingType: '"' });
148
- writeFileSync(configPath, updated, 'utf-8');
149
- console.log(' ✓ api_server config ensured (backup saved to config.yaml.bak)');
217
+ writeFileSync(configPath, yaml.dump(cfg), 'utf-8');
150
218
  await restartGateway();
151
219
  }
152
220
  catch (err) {
153
- console.error(' Failed to update config:', err.message);
221
+ console.error('config error:', err.message);
154
222
  }
155
223
  }
156
224
  async function ensureGatewayRunning() {
157
225
  const upstream = config_1.config.upstream.replace(/\/$/, '');
158
226
  try {
159
227
  const res = await fetch(`${upstream}/health`, { signal: AbortSignal.timeout(5000) });
160
- if (res.ok) {
161
- console.log(' ✓ Gateway is running');
228
+ if (res.ok)
162
229
  return;
163
- }
164
- }
165
- catch {
166
- // Gateway not reachable
167
- }
168
- // Detect WSL — no launchd/systemd, hermes gateway start won't work
169
- const { existsSync, readFileSync } = await Promise.resolve().then(() => __importStar(require('fs')));
170
- const isWSL = existsSync('/proc/version') && readFileSync('/proc/version', 'utf-8').toLowerCase().includes('microsoft');
171
- if (isWSL) {
172
- console.log(' ⚠ WSL detected — Gateway not reachable, starting in background...');
173
- try {
174
- const pid = await startGatewayBackground();
175
- await new Promise(r => setTimeout(r, 3000));
176
- const res = await fetch(`${upstream}/health`, { signal: AbortSignal.timeout(5000) });
177
- if (res.ok) {
178
- console.log(` ✓ Gateway started in background (PID: ${pid})`);
179
- return;
180
- }
181
- console.log(' ✗ Gateway start attempted but still not reachable');
182
- }
183
- catch (err) {
184
- console.error(' ✗ Failed to start gateway:', err.message);
185
- }
186
- return;
187
230
  }
188
- console.log(' ⚠ Gateway not reachable, starting...');
231
+ catch { }
232
+ console.log('⚠ Gateway not running, starting...');
189
233
  try {
190
- await startGateway();
234
+ // 👉 关键:保存 PID
235
+ gatewayPid = await startGatewayBackground();
191
236
  await new Promise(r => setTimeout(r, 3000));
192
237
  const res = await fetch(`${upstream}/health`, { signal: AbortSignal.timeout(5000) });
193
238
  if (res.ok) {
194
- console.log(' ✓ Gateway started successfully');
195
- return;
239
+ console.log(`✓ Gateway started (PID: ${gatewayPid})`);
196
240
  }
197
- console.log(' ✗ Gateway start attempted but still not reachable');
198
241
  }
199
242
  catch (err) {
200
- console.error(' Failed to start gateway:', err.message);
243
+ console.error('gateway start failed:', err.message);
201
244
  }
202
245
  }
203
246
  bootstrap();
@@ -116,6 +116,9 @@ async function writeConfigYaml(config) {
116
116
  exports.fsRoutes.get('/api/skills', async (ctx) => {
117
117
  const skillsDir = (0, path_1.join)(hermesDir, 'skills');
118
118
  try {
119
+ // Read disabled skills list from config.yaml
120
+ const config = await readConfigYaml();
121
+ const disabledList = config.skills?.disabled || [];
119
122
  const entries = await (0, promises_1.readdir)(skillsDir, { withFileTypes: true });
120
123
  const categories = [];
121
124
  for (const entry of entries) {
@@ -134,6 +137,7 @@ exports.fsRoutes.get('/api/skills', async (ctx) => {
134
137
  skills.push({
135
138
  name: se.name,
136
139
  description: extractDescription(skillMd),
140
+ enabled: !disabledList.includes(se.name),
137
141
  });
138
142
  }
139
143
  }
@@ -152,6 +156,40 @@ exports.fsRoutes.get('/api/skills', async (ctx) => {
152
156
  ctx.body = { error: `Failed to read skills directory: ${err.message}` };
153
157
  }
154
158
  });
159
+ // Toggle skill enabled/disabled via config.yaml skills.disabled
160
+ exports.fsRoutes.put('/api/skills/toggle', async (ctx) => {
161
+ const { name, enabled } = ctx.request.body;
162
+ if (!name || typeof enabled !== 'boolean') {
163
+ ctx.status = 400;
164
+ ctx.body = { error: 'Missing name or enabled flag' };
165
+ return;
166
+ }
167
+ try {
168
+ const config = await readConfigYaml();
169
+ if (!config.skills)
170
+ config.skills = {};
171
+ if (!Array.isArray(config.skills.disabled))
172
+ config.skills.disabled = [];
173
+ const disabled = config.skills.disabled;
174
+ const idx = disabled.indexOf(name);
175
+ if (enabled) {
176
+ // Enable: remove from disabled list
177
+ if (idx !== -1)
178
+ disabled.splice(idx, 1);
179
+ }
180
+ else {
181
+ // Disable: add to disabled list
182
+ if (idx === -1)
183
+ disabled.push(name);
184
+ }
185
+ await writeConfigYaml(config);
186
+ ctx.body = { success: true };
187
+ }
188
+ catch (err) {
189
+ ctx.status = 500;
190
+ ctx.body = { error: err.message };
191
+ }
192
+ });
155
193
  // List files in a skill directory
156
194
  async function listFilesRecursive(dir, prefix) {
157
195
  const result = [];
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Get or create the auth token. Returns null if auth is disabled.
3
+ */
4
+ export declare function getToken(): Promise<string | null>;
5
+ /**
6
+ * Koa middleware: check Authorization header for API routes.
7
+ * Skips /health, /webhook, and static file requests.
8
+ */
9
+ export declare function authMiddleware(token: string | null): Promise<(ctx: any, next: () => Promise<void>) => Promise<void>>;
@@ -0,0 +1,65 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getToken = getToken;
4
+ exports.authMiddleware = authMiddleware;
5
+ const promises_1 = require("fs/promises");
6
+ const path_1 = require("path");
7
+ const crypto_1 = require("crypto");
8
+ const config_1 = require("../config");
9
+ // Token stored in project data directory
10
+ const TOKEN_FILE = (0, path_1.join)(config_1.config.dataDir, '.token');
11
+ function generateToken() {
12
+ return (0, crypto_1.randomBytes)(32).toString('hex');
13
+ }
14
+ /**
15
+ * Get or create the auth token. Returns null if auth is disabled.
16
+ */
17
+ async function getToken() {
18
+ // Auth can be disabled via env var
19
+ if (process.env.AUTH_DISABLED === '1' || process.env.AUTH_DISABLED === 'true') {
20
+ return null;
21
+ }
22
+ // Custom token via env var
23
+ if (process.env.AUTH_TOKEN) {
24
+ return process.env.AUTH_TOKEN;
25
+ }
26
+ try {
27
+ const token = await (0, promises_1.readFile)(TOKEN_FILE, 'utf-8');
28
+ return token.trim();
29
+ }
30
+ catch {
31
+ // Generate a new token
32
+ const token = generateToken();
33
+ await (0, promises_1.writeFile)(TOKEN_FILE, token + '\n', { mode: 0o600 });
34
+ return token;
35
+ }
36
+ }
37
+ /**
38
+ * Koa middleware: check Authorization header for API routes.
39
+ * Skips /health, /webhook, and static file requests.
40
+ */
41
+ async function authMiddleware(token) {
42
+ return async (ctx, next) => {
43
+ // If auth is disabled, skip
44
+ if (!token) {
45
+ await next();
46
+ return;
47
+ }
48
+ // Skip non-API paths (static files, health check, SPA)
49
+ const path = ctx.path;
50
+ if (path === '/health' ||
51
+ (!path.startsWith('/api') && !path.startsWith('/v1') && path !== '/upload' && path !== '/webhook')) {
52
+ await next();
53
+ return;
54
+ }
55
+ const auth = ctx.headers.authorization || '';
56
+ const provided = auth.startsWith('Bearer ') ? auth.slice(7) : '';
57
+ if (!provided || provided !== token) {
58
+ ctx.status = 401;
59
+ ctx.set('Content-Type', 'application/json');
60
+ ctx.body = { error: 'Unauthorized' };
61
+ return;
62
+ }
63
+ await next();
64
+ };
65
+ }
@@ -13,6 +13,7 @@ exports.readLogs = readLogs;
13
13
  const child_process_1 = require("child_process");
14
14
  const util_1 = require("util");
15
15
  const execFileAsync = (0, util_1.promisify)(child_process_1.execFile);
16
+ const execOpts = { windowsHide: true };
16
17
  /**
17
18
  * List sessions from Hermes CLI (without messages)
18
19
  */
@@ -24,6 +25,7 @@ async function listSessions(source, limit) {
24
25
  const { stdout } = await execFileAsync('hermes', args, {
25
26
  maxBuffer: 50 * 1024 * 1024, // 50MB
26
27
  timeout: 30000,
28
+ ...execOpts,
27
29
  });
28
30
  const lines = stdout.trim().split('\n').filter(Boolean);
29
31
  const sessions = [];
@@ -83,10 +85,13 @@ async function getSession(id) {
83
85
  const { stdout } = await execFileAsync('hermes', args, {
84
86
  maxBuffer: 50 * 1024 * 1024,
85
87
  timeout: 30000,
88
+ ...execOpts,
86
89
  });
87
90
  const lines = stdout.trim().split('\n').filter(Boolean);
88
91
  if (lines.length === 0)
89
92
  return null;
93
+ if (!lines[0].startsWith('{'))
94
+ return null;
90
95
  const raw = JSON.parse(lines[0]);
91
96
  return {
92
97
  id: raw.id,
@@ -125,6 +130,7 @@ async function deleteSession(id) {
125
130
  try {
126
131
  await execFileAsync('hermes', ['sessions', 'delete', id, '--yes'], {
127
132
  timeout: 10000,
133
+ ...execOpts,
128
134
  });
129
135
  return true;
130
136
  }
@@ -140,6 +146,7 @@ async function renameSession(id, title) {
140
146
  try {
141
147
  await execFileAsync('hermes', ['sessions', 'rename', id, title], {
142
148
  timeout: 10000,
149
+ ...execOpts,
143
150
  });
144
151
  return true;
145
152
  }
@@ -153,7 +160,7 @@ async function renameSession(id, title) {
153
160
  */
154
161
  async function getVersion() {
155
162
  try {
156
- const { stdout } = await execFileAsync('hermes', ['--version'], { timeout: 5000 });
163
+ const { stdout } = await execFileAsync('hermes', ['--version'], { timeout: 5000, ...execOpts });
157
164
  return stdout.trim();
158
165
  }
159
166
  catch {
@@ -166,6 +173,7 @@ async function getVersion() {
166
173
  async function startGateway() {
167
174
  const { stdout, stderr } = await execFileAsync('hermes', ['gateway', 'start'], {
168
175
  timeout: 30000,
176
+ ...execOpts,
169
177
  });
170
178
  return stdout || stderr;
171
179
  }
@@ -178,6 +186,7 @@ async function startGatewayBackground() {
178
186
  const child = spawn('hermes', ['gateway', 'run'], {
179
187
  detached: true,
180
188
  stdio: 'ignore',
189
+ windowsHide: true,
181
190
  });
182
191
  child.unref();
183
192
  return child.pid ?? null;
@@ -188,6 +197,7 @@ async function startGatewayBackground() {
188
197
  async function restartGateway() {
189
198
  const { stdout, stderr } = await execFileAsync('hermes', ['gateway', 'restart'], {
190
199
  timeout: 30000,
200
+ ...execOpts,
191
201
  });
192
202
  return stdout || stderr;
193
203
  }
@@ -198,6 +208,7 @@ async function listLogFiles() {
198
208
  try {
199
209
  const { stdout } = await execFileAsync('hermes', ['logs', 'list'], {
200
210
  timeout: 10000,
211
+ ...execOpts,
201
212
  });
202
213
  const files = [];
203
214
  const lines = stdout.trim().split('\n').filter(l => l.includes('.log'));
@@ -233,6 +244,7 @@ async function readLogs(logName = 'agent', lines = 100, level, session, since) {
233
244
  const { stdout } = await execFileAsync('hermes', args, {
234
245
  maxBuffer: 10 * 1024 * 1024,
235
246
  timeout: 15000,
247
+ ...execOpts,
236
248
  });
237
249
  return stdout;
238
250
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hermes-web-ui",
3
- "version": "0.2.2",
3
+ "version": "0.2.3",
4
4
  "description": "Hermes Agent Web UI - Chat and Job Management Dashboard",
5
5
  "repository": {
6
6
  "type": "git",
@@ -15,7 +15,7 @@
15
15
  "start": "vite --host --port 8648",
16
16
  "dev": "concurrently \"npm run dev:server\" \"npm run dev:client\"",
17
17
  "dev:client": "vite --host",
18
- "dev:server": "nodemon --watch server/src --ext ts --exec node -r ts-node/register server/src/index.ts",
18
+ "dev:server": "nodemon --signal SIGTERM --watch server/src -e ts,tsx --exec node -r ts-node/register server/src/index.ts",
19
19
  "build": "vue-tsc -b && vite build && tsc -p server/tsconfig.json",
20
20
  "preview": "vite preview"
21
21
  },
@@ -1,109 +0,0 @@
1
- import{$ as e,E as t,M as n,S as r,k as i,m as a,n as o,r as s,rt as c,w as l}from"./vue.runtime.esm-bundler-BoqZ7fRe.js";import{$ as u,B as d,J as f,Q as p,V as m,W as h,d as g,dt as _,f as v,ft as y,i as b,l as x,lt as S,n as C,nt as w,o as T,ot as E,q as D,r as O,rt as k,s as A,st as j,tt as M,u as N,ut as P,z as F}from"./_plugin-vue_export-helper-C7dadZ10.js";function I(e){return e.replace(/#|\(|\)|,|\s|\./g,`_`)}var L=r({name:`FadeInExpandTransition`,props:{appear:Boolean,group:Boolean,mode:String,onLeave:Function,onAfterLeave:Function,onAfterEnter:Function,width:Boolean,reverse:Boolean},setup(e,{slots:t}){function n(t){e.width?t.style.maxWidth=`${t.offsetWidth}px`:t.style.maxHeight=`${t.offsetHeight}px`,t.offsetWidth}function r(t){e.width?t.style.maxWidth=`0`:t.style.maxHeight=`0`,t.offsetWidth;let{onLeave:n}=e;n&&n()}function i(t){e.width?t.style.maxWidth=``:t.style.maxHeight=``;let{onAfterLeave:n}=e;n&&n()}function a(t){if(t.style.transition=`none`,e.width){let e=t.offsetWidth;t.style.maxWidth=`0`,t.offsetWidth,t.style.transition=``,t.style.maxWidth=`${e}px`}else if(e.reverse)t.style.maxHeight=`${t.offsetHeight}px`,t.offsetHeight,t.style.transition=``,t.style.maxHeight=`0`;else{let e=t.offsetHeight;t.style.maxHeight=`0`,t.offsetWidth,t.style.transition=``,t.style.maxHeight=`${e}px`}t.offsetWidth}function c(t){var n;e.width?t.style.maxWidth=``:e.reverse||(t.style.maxHeight=``),(n=e.onAfterEnter)==null||n.call(e)}return()=>{let{group:u,width:d,appear:f,mode:p}=e,m=u?s:o,h={name:d?`fade-in-width-expand-transition`:`fade-in-height-expand-transition`,appear:f,onEnter:a,onAfterEnter:c,onBeforeLeave:n,onLeave:r,onAfterLeave:i};return u||(h.mode=p),l(m,h,t)}}}),{cubicBezierEaseInOut:R}=g;function z({duration:e=`.2s`,delay:t=`.1s`}={}){return[E(`&.fade-in-width-expand-transition-leave-from, &.fade-in-width-expand-transition-enter-to`,{opacity:1}),E(`&.fade-in-width-expand-transition-leave-to, &.fade-in-width-expand-transition-enter-from`,`
2
- opacity: 0!important;
3
- margin-left: 0!important;
4
- margin-right: 0!important;
5
- `),E(`&.fade-in-width-expand-transition-leave-active`,`
6
- overflow: hidden;
7
- transition:
8
- opacity ${e} ${R},
9
- max-width ${e} ${R} ${t},
10
- margin-left ${e} ${R} ${t},
11
- margin-right ${e} ${R} ${t};
12
- `),E(`&.fade-in-width-expand-transition-enter-active`,`
13
- overflow: hidden;
14
- transition:
15
- opacity ${e} ${R} ${t},
16
- max-width ${e} ${R},
17
- margin-left ${e} ${R},
18
- margin-right ${e} ${R};
19
- `)]}var B=j(`base-wave`,`
20
- position: absolute;
21
- left: 0;
22
- right: 0;
23
- top: 0;
24
- bottom: 0;
25
- border-radius: inherit;
26
- `),V=r({name:`BaseWave`,props:{clsPrefix:{type:String,required:!0}},setup(t){N(`-base-wave`,B,c(t,`clsPrefix`));let r=e(null),a=e(!1),o=null;return n(()=>{o!==null&&window.clearTimeout(o)}),{active:a,selfRef:r,play(){o!==null&&(window.clearTimeout(o),a.value=!1,o=null),i(()=>{var e;(e=r.value)==null||e.offsetHeight,a.value=!0,o=window.setTimeout(()=>{a.value=!1,o=null},1e3)})}}},render(){let{clsPrefix:e}=this;return l(`div`,{ref:`selfRef`,"aria-hidden":!0,class:[`${e}-base-wave`,this.active&&`${e}-base-wave--active`]})}});function H(e){return k(e,[255,255,255,.16])}function U(e){return k(e,[0,0,0,.12])}var W=u(`n-button-group`),G={paddingTiny:`0 6px`,paddingSmall:`0 10px`,paddingMedium:`0 14px`,paddingLarge:`0 18px`,paddingRoundTiny:`0 10px`,paddingRoundSmall:`0 14px`,paddingRoundMedium:`0 18px`,paddingRoundLarge:`0 22px`,iconMarginTiny:`6px`,iconMarginSmall:`6px`,iconMarginMedium:`6px`,iconMarginLarge:`6px`,iconSizeTiny:`14px`,iconSizeSmall:`18px`,iconSizeMedium:`18px`,iconSizeLarge:`20px`,rippleDuration:`.6s`};function K(e){let{heightTiny:t,heightSmall:n,heightMedium:r,heightLarge:i,borderRadius:a,fontSizeTiny:o,fontSizeSmall:s,fontSizeMedium:c,fontSizeLarge:l,opacityDisabled:u,textColor2:d,textColor3:f,primaryColorHover:p,primaryColorPressed:m,borderColor:h,primaryColor:g,baseColor:_,infoColor:v,infoColorHover:y,infoColorPressed:b,successColor:x,successColorHover:S,successColorPressed:C,warningColor:w,warningColorHover:T,warningColorPressed:E,errorColor:D,errorColorHover:O,errorColorPressed:k,fontWeight:A,buttonColor2:j,buttonColor2Hover:M,buttonColor2Pressed:N,fontWeightStrong:P}=e;return Object.assign(Object.assign({},G),{heightTiny:t,heightSmall:n,heightMedium:r,heightLarge:i,borderRadiusTiny:a,borderRadiusSmall:a,borderRadiusMedium:a,borderRadiusLarge:a,fontSizeTiny:o,fontSizeSmall:s,fontSizeMedium:c,fontSizeLarge:l,opacityDisabled:u,colorOpacitySecondary:`0.16`,colorOpacitySecondaryHover:`0.22`,colorOpacitySecondaryPressed:`0.28`,colorSecondary:j,colorSecondaryHover:M,colorSecondaryPressed:N,colorTertiary:j,colorTertiaryHover:M,colorTertiaryPressed:N,colorQuaternary:`#0000`,colorQuaternaryHover:M,colorQuaternaryPressed:N,color:`#0000`,colorHover:`#0000`,colorPressed:`#0000`,colorFocus:`#0000`,colorDisabled:`#0000`,textColor:d,textColorTertiary:f,textColorHover:p,textColorPressed:m,textColorFocus:p,textColorDisabled:d,textColorText:d,textColorTextHover:p,textColorTextPressed:m,textColorTextFocus:p,textColorTextDisabled:d,textColorGhost:d,textColorGhostHover:p,textColorGhostPressed:m,textColorGhostFocus:p,textColorGhostDisabled:d,border:`1px solid ${h}`,borderHover:`1px solid ${p}`,borderPressed:`1px solid ${m}`,borderFocus:`1px solid ${p}`,borderDisabled:`1px solid ${h}`,rippleColor:g,colorPrimary:g,colorHoverPrimary:p,colorPressedPrimary:m,colorFocusPrimary:p,colorDisabledPrimary:g,textColorPrimary:_,textColorHoverPrimary:_,textColorPressedPrimary:_,textColorFocusPrimary:_,textColorDisabledPrimary:_,textColorTextPrimary:g,textColorTextHoverPrimary:p,textColorTextPressedPrimary:m,textColorTextFocusPrimary:p,textColorTextDisabledPrimary:d,textColorGhostPrimary:g,textColorGhostHoverPrimary:p,textColorGhostPressedPrimary:m,textColorGhostFocusPrimary:p,textColorGhostDisabledPrimary:g,borderPrimary:`1px solid ${g}`,borderHoverPrimary:`1px solid ${p}`,borderPressedPrimary:`1px solid ${m}`,borderFocusPrimary:`1px solid ${p}`,borderDisabledPrimary:`1px solid ${g}`,rippleColorPrimary:g,colorInfo:v,colorHoverInfo:y,colorPressedInfo:b,colorFocusInfo:y,colorDisabledInfo:v,textColorInfo:_,textColorHoverInfo:_,textColorPressedInfo:_,textColorFocusInfo:_,textColorDisabledInfo:_,textColorTextInfo:v,textColorTextHoverInfo:y,textColorTextPressedInfo:b,textColorTextFocusInfo:y,textColorTextDisabledInfo:d,textColorGhostInfo:v,textColorGhostHoverInfo:y,textColorGhostPressedInfo:b,textColorGhostFocusInfo:y,textColorGhostDisabledInfo:v,borderInfo:`1px solid ${v}`,borderHoverInfo:`1px solid ${y}`,borderPressedInfo:`1px solid ${b}`,borderFocusInfo:`1px solid ${y}`,borderDisabledInfo:`1px solid ${v}`,rippleColorInfo:v,colorSuccess:x,colorHoverSuccess:S,colorPressedSuccess:C,colorFocusSuccess:S,colorDisabledSuccess:x,textColorSuccess:_,textColorHoverSuccess:_,textColorPressedSuccess:_,textColorFocusSuccess:_,textColorDisabledSuccess:_,textColorTextSuccess:x,textColorTextHoverSuccess:S,textColorTextPressedSuccess:C,textColorTextFocusSuccess:S,textColorTextDisabledSuccess:d,textColorGhostSuccess:x,textColorGhostHoverSuccess:S,textColorGhostPressedSuccess:C,textColorGhostFocusSuccess:S,textColorGhostDisabledSuccess:x,borderSuccess:`1px solid ${x}`,borderHoverSuccess:`1px solid ${S}`,borderPressedSuccess:`1px solid ${C}`,borderFocusSuccess:`1px solid ${S}`,borderDisabledSuccess:`1px solid ${x}`,rippleColorSuccess:x,colorWarning:w,colorHoverWarning:T,colorPressedWarning:E,colorFocusWarning:T,colorDisabledWarning:w,textColorWarning:_,textColorHoverWarning:_,textColorPressedWarning:_,textColorFocusWarning:_,textColorDisabledWarning:_,textColorTextWarning:w,textColorTextHoverWarning:T,textColorTextPressedWarning:E,textColorTextFocusWarning:T,textColorTextDisabledWarning:d,textColorGhostWarning:w,textColorGhostHoverWarning:T,textColorGhostPressedWarning:E,textColorGhostFocusWarning:T,textColorGhostDisabledWarning:w,borderWarning:`1px solid ${w}`,borderHoverWarning:`1px solid ${T}`,borderPressedWarning:`1px solid ${E}`,borderFocusWarning:`1px solid ${T}`,borderDisabledWarning:`1px solid ${w}`,rippleColorWarning:w,colorError:D,colorHoverError:O,colorPressedError:k,colorFocusError:O,colorDisabledError:D,textColorError:_,textColorHoverError:_,textColorPressedError:_,textColorFocusError:_,textColorDisabledError:_,textColorTextError:D,textColorTextHoverError:O,textColorTextPressedError:k,textColorTextFocusError:O,textColorTextDisabledError:d,textColorGhostError:D,textColorGhostHoverError:O,textColorGhostPressedError:k,textColorGhostFocusError:O,textColorGhostDisabledError:D,borderError:`1px solid ${D}`,borderHoverError:`1px solid ${O}`,borderPressedError:`1px solid ${k}`,borderFocusError:`1px solid ${O}`,borderDisabledError:`1px solid ${D}`,rippleColorError:D,waveOpacity:`0.6`,fontWeight:A,fontWeightStrong:P})}var q={name:`Button`,common:O,self:K},J=E([j(`button`,`
27
- margin: 0;
28
- font-weight: var(--n-font-weight);
29
- line-height: 1;
30
- font-family: inherit;
31
- padding: var(--n-padding);
32
- height: var(--n-height);
33
- font-size: var(--n-font-size);
34
- border-radius: var(--n-border-radius);
35
- color: var(--n-text-color);
36
- background-color: var(--n-color);
37
- width: var(--n-width);
38
- white-space: nowrap;
39
- outline: none;
40
- position: relative;
41
- z-index: auto;
42
- border: none;
43
- display: inline-flex;
44
- flex-wrap: nowrap;
45
- flex-shrink: 0;
46
- align-items: center;
47
- justify-content: center;
48
- user-select: none;
49
- -webkit-user-select: none;
50
- text-align: center;
51
- cursor: pointer;
52
- text-decoration: none;
53
- transition:
54
- color .3s var(--n-bezier),
55
- background-color .3s var(--n-bezier),
56
- opacity .3s var(--n-bezier),
57
- border-color .3s var(--n-bezier);
58
- `,[P(`color`,[S(`border`,{borderColor:`var(--n-border-color)`}),P(`disabled`,[S(`border`,{borderColor:`var(--n-border-color-disabled)`})]),_(`disabled`,[E(`&:focus`,[S(`state-border`,{borderColor:`var(--n-border-color-focus)`})]),E(`&:hover`,[S(`state-border`,{borderColor:`var(--n-border-color-hover)`})]),E(`&:active`,[S(`state-border`,{borderColor:`var(--n-border-color-pressed)`})]),P(`pressed`,[S(`state-border`,{borderColor:`var(--n-border-color-pressed)`})])])]),P(`disabled`,{backgroundColor:`var(--n-color-disabled)`,color:`var(--n-text-color-disabled)`},[S(`border`,{border:`var(--n-border-disabled)`})]),_(`disabled`,[E(`&:focus`,{backgroundColor:`var(--n-color-focus)`,color:`var(--n-text-color-focus)`},[S(`state-border`,{border:`var(--n-border-focus)`})]),E(`&:hover`,{backgroundColor:`var(--n-color-hover)`,color:`var(--n-text-color-hover)`},[S(`state-border`,{border:`var(--n-border-hover)`})]),E(`&:active`,{backgroundColor:`var(--n-color-pressed)`,color:`var(--n-text-color-pressed)`},[S(`state-border`,{border:`var(--n-border-pressed)`})]),P(`pressed`,{backgroundColor:`var(--n-color-pressed)`,color:`var(--n-text-color-pressed)`},[S(`state-border`,{border:`var(--n-border-pressed)`})])]),P(`loading`,`cursor: wait;`),j(`base-wave`,`
59
- pointer-events: none;
60
- top: 0;
61
- right: 0;
62
- bottom: 0;
63
- left: 0;
64
- animation-iteration-count: 1;
65
- animation-duration: var(--n-ripple-duration);
66
- animation-timing-function: var(--n-bezier-ease-out), var(--n-bezier-ease-out);
67
- `,[P(`active`,{zIndex:1,animationName:`button-wave-spread, button-wave-opacity`})]),p&&`MozBoxSizing`in document.createElement(`div`).style?E(`&::moz-focus-inner`,{border:0}):null,S(`border, state-border`,`
68
- position: absolute;
69
- left: 0;
70
- top: 0;
71
- right: 0;
72
- bottom: 0;
73
- border-radius: inherit;
74
- transition: border-color .3s var(--n-bezier);
75
- pointer-events: none;
76
- `),S(`border`,`
77
- border: var(--n-border);
78
- `),S(`state-border`,`
79
- border: var(--n-border);
80
- border-color: #0000;
81
- z-index: 1;
82
- `),S(`icon`,`
83
- margin: var(--n-icon-margin);
84
- margin-left: 0;
85
- height: var(--n-icon-size);
86
- width: var(--n-icon-size);
87
- max-width: var(--n-icon-size);
88
- font-size: var(--n-icon-size);
89
- position: relative;
90
- flex-shrink: 0;
91
- `,[j(`icon-slot`,`
92
- height: var(--n-icon-size);
93
- width: var(--n-icon-size);
94
- position: absolute;
95
- left: 0;
96
- top: 50%;
97
- transform: translateY(-50%);
98
- display: flex;
99
- align-items: center;
100
- justify-content: center;
101
- `,[T({top:`50%`,originalTransform:`translateY(-50%)`})]),z()]),S(`content`,`
102
- display: flex;
103
- align-items: center;
104
- flex-wrap: nowrap;
105
- min-width: 0;
106
- `,[E(`~`,[S(`icon`,{margin:`var(--n-icon-margin)`,marginRight:0})])]),P(`block`,`
107
- display: flex;
108
- width: 100%;
109
- `),P(`dashed`,[S(`border, state-border`,{borderStyle:`dashed !important`})]),P(`disabled`,{cursor:`not-allowed`,opacity:`var(--n-opacity-disabled)`})]),E(`@keyframes button-wave-spread`,{from:{boxShadow:`0 0 0.5px 0 var(--n-ripple-color)`},to:{boxShadow:`0 0 0.5px 4.5px var(--n-ripple-color)`}}),E(`@keyframes button-wave-opacity`,{from:{opacity:`var(--n-wave-opacity)`},to:{opacity:0}})]),Y=r({name:`Button`,props:Object.assign(Object.assign({},x.props),{color:String,textColor:String,text:Boolean,block:Boolean,loading:Boolean,disabled:Boolean,circle:Boolean,size:String,ghost:Boolean,round:Boolean,secondary:Boolean,tertiary:Boolean,quaternary:Boolean,strong:Boolean,focusable:{type:Boolean,default:!0},keyboard:{type:Boolean,default:!0},tag:{type:String,default:`button`},type:{type:String,default:`default`},dashed:Boolean,renderIcon:Function,iconPlacement:{type:String,default:`left`},attrType:{type:String,default:`button`},bordered:{type:Boolean,default:!0},onClick:[Function,Array],nativeFocusBehavior:{type:Boolean,default:!C},spinProps:Object}),slots:Object,setup(n){let r=e(null),i=e(null),o=e(!1),s=M(()=>!n.quaternary&&!n.tertiary&&!n.secondary&&!n.text&&(!n.color||n.ghost||n.dashed)&&n.bordered),c=t(W,{}),{inlineThemeDisabled:l,mergedClsPrefixRef:u,mergedRtlRef:p,mergedComponentPropsRef:h}=m(n),{mergedSizeRef:g}=F({},{defaultSize:`medium`,mergedSize:e=>{let{size:t}=n;if(t)return t;let{size:r}=c;if(r)return r;let{mergedSize:i}=e||{};return i?i.value:h?.value?.Button?.size||`medium`}}),_=a(()=>n.focusable&&!n.disabled),b=e=>{var t;_.value||e.preventDefault(),!n.nativeFocusBehavior&&(e.preventDefault(),!n.disabled&&_.value&&((t=r.value)==null||t.focus({preventScroll:!0})))},S=e=>{var t;if(!n.disabled&&!n.loading){let{onClick:r}=n;r&&f(r,e),n.text||(t=i.value)==null||t.play()}},C=e=>{switch(e.key){case`Enter`:if(!n.keyboard)return;o.value=!1}},T=e=>{switch(e.key){case`Enter`:if(!n.keyboard||n.loading){e.preventDefault();return}o.value=!0}},E=()=>{o.value=!1},D=x(`Button`,`-button`,J,q,n,u),O=v(`Button`,p,u),k=a(()=>{let{common:{cubicBezierEaseInOut:e,cubicBezierEaseOut:t},self:r}=D.value,{rippleDuration:i,opacityDisabled:a,fontWeight:o,fontWeightStrong:s}=r,c=g.value,{dashed:l,type:u,ghost:d,text:f,color:p,round:m,circle:h,textColor:_,secondary:v,tertiary:b,quaternary:x,strong:S}=n,C={"--n-font-weight":S?s:o},T={"--n-color":`initial`,"--n-color-hover":`initial`,"--n-color-pressed":`initial`,"--n-color-focus":`initial`,"--n-color-disabled":`initial`,"--n-ripple-color":`initial`,"--n-text-color":`initial`,"--n-text-color-hover":`initial`,"--n-text-color-pressed":`initial`,"--n-text-color-focus":`initial`,"--n-text-color-disabled":`initial`},E=u===`tertiary`,O=u===`default`,k=E?`default`:u;if(f){let e=_||p;T={"--n-color":`#0000`,"--n-color-hover":`#0000`,"--n-color-pressed":`#0000`,"--n-color-focus":`#0000`,"--n-color-disabled":`#0000`,"--n-ripple-color":`#0000`,"--n-text-color":e||r[y(`textColorText`,k)],"--n-text-color-hover":e?H(e):r[y(`textColorTextHover`,k)],"--n-text-color-pressed":e?U(e):r[y(`textColorTextPressed`,k)],"--n-text-color-focus":e?H(e):r[y(`textColorTextHover`,k)],"--n-text-color-disabled":e||r[y(`textColorTextDisabled`,k)]}}else if(d||l){let e=_||p;T={"--n-color":`#0000`,"--n-color-hover":`#0000`,"--n-color-pressed":`#0000`,"--n-color-focus":`#0000`,"--n-color-disabled":`#0000`,"--n-ripple-color":p||r[y(`rippleColor`,k)],"--n-text-color":e||r[y(`textColorGhost`,k)],"--n-text-color-hover":e?H(e):r[y(`textColorGhostHover`,k)],"--n-text-color-pressed":e?U(e):r[y(`textColorGhostPressed`,k)],"--n-text-color-focus":e?H(e):r[y(`textColorGhostHover`,k)],"--n-text-color-disabled":e||r[y(`textColorGhostDisabled`,k)]}}else if(v){let e=O?r.textColor:E?r.textColorTertiary:r[y(`color`,k)],t=p||e,n=u!==`default`&&u!==`tertiary`;T={"--n-color":n?w(t,{alpha:Number(r.colorOpacitySecondary)}):r.colorSecondary,"--n-color-hover":n?w(t,{alpha:Number(r.colorOpacitySecondaryHover)}):r.colorSecondaryHover,"--n-color-pressed":n?w(t,{alpha:Number(r.colorOpacitySecondaryPressed)}):r.colorSecondaryPressed,"--n-color-focus":n?w(t,{alpha:Number(r.colorOpacitySecondaryHover)}):r.colorSecondaryHover,"--n-color-disabled":r.colorSecondary,"--n-ripple-color":`#0000`,"--n-text-color":t,"--n-text-color-hover":t,"--n-text-color-pressed":t,"--n-text-color-focus":t,"--n-text-color-disabled":t}}else if(b||x){let e=O?r.textColor:E?r.textColorTertiary:r[y(`color`,k)],t=p||e;b?(T[`--n-color`]=r.colorTertiary,T[`--n-color-hover`]=r.colorTertiaryHover,T[`--n-color-pressed`]=r.colorTertiaryPressed,T[`--n-color-focus`]=r.colorSecondaryHover,T[`--n-color-disabled`]=r.colorTertiary):(T[`--n-color`]=r.colorQuaternary,T[`--n-color-hover`]=r.colorQuaternaryHover,T[`--n-color-pressed`]=r.colorQuaternaryPressed,T[`--n-color-focus`]=r.colorQuaternaryHover,T[`--n-color-disabled`]=r.colorQuaternary),T[`--n-ripple-color`]=`#0000`,T[`--n-text-color`]=t,T[`--n-text-color-hover`]=t,T[`--n-text-color-pressed`]=t,T[`--n-text-color-focus`]=t,T[`--n-text-color-disabled`]=t}else T={"--n-color":p||r[y(`color`,k)],"--n-color-hover":p?H(p):r[y(`colorHover`,k)],"--n-color-pressed":p?U(p):r[y(`colorPressed`,k)],"--n-color-focus":p?H(p):r[y(`colorFocus`,k)],"--n-color-disabled":p||r[y(`colorDisabled`,k)],"--n-ripple-color":p||r[y(`rippleColor`,k)],"--n-text-color":_||(p?r.textColorPrimary:E?r.textColorTertiary:r[y(`textColor`,k)]),"--n-text-color-hover":_||(p?r.textColorHoverPrimary:r[y(`textColorHover`,k)]),"--n-text-color-pressed":_||(p?r.textColorPressedPrimary:r[y(`textColorPressed`,k)]),"--n-text-color-focus":_||(p?r.textColorFocusPrimary:r[y(`textColorFocus`,k)]),"--n-text-color-disabled":_||(p?r.textColorDisabledPrimary:r[y(`textColorDisabled`,k)])};let A={"--n-border":`initial`,"--n-border-hover":`initial`,"--n-border-pressed":`initial`,"--n-border-focus":`initial`,"--n-border-disabled":`initial`};A=f?{"--n-border":`none`,"--n-border-hover":`none`,"--n-border-pressed":`none`,"--n-border-focus":`none`,"--n-border-disabled":`none`}:{"--n-border":r[y(`border`,k)],"--n-border-hover":r[y(`borderHover`,k)],"--n-border-pressed":r[y(`borderPressed`,k)],"--n-border-focus":r[y(`borderFocus`,k)],"--n-border-disabled":r[y(`borderDisabled`,k)]};let{[y(`height`,c)]:j,[y(`fontSize`,c)]:M,[y(`padding`,c)]:N,[y(`paddingRound`,c)]:P,[y(`iconSize`,c)]:F,[y(`borderRadius`,c)]:I,[y(`iconMargin`,c)]:L,waveOpacity:R}=r,z={"--n-width":h&&!f?j:`initial`,"--n-height":f?`initial`:j,"--n-font-size":M,"--n-padding":h||f?`initial`:m?P:N,"--n-icon-size":F,"--n-icon-margin":L,"--n-border-radius":f?`initial`:h||m?j:I};return Object.assign(Object.assign(Object.assign(Object.assign({"--n-bezier":e,"--n-bezier-ease-out":t,"--n-ripple-duration":i,"--n-opacity-disabled":a,"--n-wave-opacity":R},C),T),A),z)}),A=l?d(`button`,a(()=>{let e=``,{dashed:t,type:r,ghost:i,text:a,color:o,round:s,circle:c,textColor:l,secondary:u,tertiary:d,quaternary:f,strong:p}=n;t&&(e+=`a`),i&&(e+=`b`),a&&(e+=`c`),s&&(e+=`d`),c&&(e+=`e`),u&&(e+=`f`),d&&(e+=`g`),f&&(e+=`h`),p&&(e+=`i`),o&&(e+=`j${I(o)}`),l&&(e+=`k${I(l)}`);let{value:m}=g;return e+=`l${m[0]}`,e+=`m${r[0]}`,e}),k,n):void 0;return{selfElRef:r,waveElRef:i,mergedClsPrefix:u,mergedFocusable:_,mergedSize:g,showBorder:s,enterPressed:o,rtlEnabled:O,handleMousedown:b,handleKeydown:T,handleBlur:E,handleKeyup:C,handleClick:S,customColorCssVars:a(()=>{let{color:e}=n;if(!e)return null;let t=H(e);return{"--n-border-color":e,"--n-border-color-hover":t,"--n-border-color-pressed":U(e),"--n-border-color-focus":t,"--n-border-color-disabled":e}}),cssVars:l?void 0:k,themeClass:A?.themeClass,onRender:A?.onRender}},render(){let{mergedClsPrefix:e,tag:t,onRender:n}=this;n?.();let r=D(this.$slots.default,t=>t&&l(`span`,{class:`${e}-button__content`},t));return l(t,{ref:`selfElRef`,class:[this.themeClass,`${e}-button`,`${e}-button--${this.type}-type`,`${e}-button--${this.mergedSize}-type`,this.rtlEnabled&&`${e}-button--rtl`,this.disabled&&`${e}-button--disabled`,this.block&&`${e}-button--block`,this.enterPressed&&`${e}-button--pressed`,!this.text&&this.dashed&&`${e}-button--dashed`,this.color&&`${e}-button--color`,this.secondary&&`${e}-button--secondary`,this.loading&&`${e}-button--loading`,this.ghost&&`${e}-button--ghost`],tabindex:this.mergedFocusable?0:-1,type:this.attrType,style:this.cssVars,disabled:this.disabled,onClick:this.handleClick,onBlur:this.handleBlur,onMousedown:this.handleMousedown,onKeyup:this.handleKeyup,onKeydown:this.handleKeydown},this.iconPlacement===`right`&&r,l(L,{width:!0},{default:()=>D(this.$slots.icon,t=>(this.loading||this.renderIcon||t)&&l(`span`,{class:`${e}-button__icon`,style:{margin:h(this.$slots.default)?`0`:``}},l(A,null,{default:()=>this.loading?l(b,Object.assign({clsPrefix:e,key:`loading`,class:`${e}-icon-slot`,strokeWidth:20},this.spinProps)):l(`div`,{key:`icon`,class:`${e}-icon-slot`,role:`none`},this.renderIcon?this.renderIcon():t)})))}),this.iconPlacement===`left`&&r,this.text?null:l(V,{ref:`waveElRef`,clsPrefix:e}),this.showBorder?l(`div`,{"aria-hidden":!0,class:`${e}-button__border`,style:this.customColorCssVars}):null,this.showBorder?l(`div`,{"aria-hidden":!0,class:`${e}-button__state-border`,style:this.customColorCssVars}):null)}}),X=Y;export{I as a,L as i,X as n,q as r,Y as t};