hermes-web-ui 0.2.5 → 0.2.6
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 +138 -205
- package/bin/hermes-web-ui.mjs +14 -2
- package/dist/assets/{Button-DBOPt_s1.js → Button-BHvh9zmj.js} +1 -1
- package/dist/assets/{ChannelsView-BU9QAub-.css → ChannelsView-C7Wor1FB.css} +1 -1
- package/dist/assets/ChannelsView-DZMniRoi.js +1 -0
- package/dist/assets/ChatView-Dt1eqp6-.js +127 -0
- package/dist/assets/{ChatView-D1SaZAvQ.css → ChatView-gR62J-Xr.css} +1 -1
- package/dist/assets/Close-DYPlamoH.js +45 -0
- package/dist/assets/{FormItem-De01hN-G.js → FormItem-C75Y2lpf.js} +1 -1
- package/dist/assets/Input-CS0p63GR.js +234 -0
- package/dist/assets/InputNumber-lHTE1DBf.js +13 -0
- package/dist/assets/JobsView-DoUtVQm_.css +1 -0
- package/dist/assets/JobsView-kGXDpDGq.js +2 -0
- package/dist/assets/LoginView-BXByybMK.css +1 -0
- package/dist/assets/LoginView-HQwDR5A7.js +1 -0
- package/dist/assets/{LogsView-BgmSycD4.js → LogsView-KPcTBGzh.js} +1 -1
- package/dist/assets/{MarkdownRenderer-z5xC7cOw.js → MarkdownRenderer-Bp-uAEtp.js} +1 -1
- package/dist/assets/{MemoryView-BUZGXC60.js → MemoryView-CWEya0jB.js} +1 -1
- package/dist/assets/{Modal-BLLYorfc.js → Modal-mFCAbKPD.js} +5 -5
- package/dist/assets/{ModelsView-ByryHyh7.js → ModelsView-BdPt2Mo_.js} +1 -1
- package/dist/assets/{ModelsView-DCR-0I10.css → ModelsView-DbBXgw4g.css} +1 -1
- package/dist/assets/Popconfirm-C2OzcGTX.js +16 -0
- package/dist/assets/Popover-CRZpNb8Q.js +117 -0
- package/dist/assets/Scrollbar-CA0Mq0os.js +77 -0
- package/dist/assets/Select-DLECSo9D.js +340 -0
- package/dist/assets/SettingRow-CsKwX-jv.js +1 -0
- package/dist/assets/{SettingsView-Y2Et1YHr.css → SettingsView-Citzr3ci.css} +1 -1
- package/dist/assets/SettingsView-DWXjfdpD.js +352 -0
- package/dist/assets/{SkillsView-CREfL6dQ.css → SkillsView-BNEWlriU.css} +1 -1
- package/dist/assets/{SkillsView-Blcv_g2_.js → SkillsView-Gb4tyJjH.js} +1 -1
- package/dist/assets/{Spin-DiwsqMEC.js → Spin-BbbA3R-G.js} +1 -1
- package/dist/assets/Suffix-BMwB7UJK.js +25 -0
- package/dist/assets/{Switch-Ce0Tgpcj.js → Switch-Xa0U6jwA.js} +2 -2
- package/dist/assets/{Tag-BUJuCRNX.js → Tag-NMAaTGW7.js} +2 -2
- package/dist/assets/TerminalView-B7iMIrM8.css +1 -0
- package/dist/assets/TerminalView-CvTXTM3W.js +36 -0
- package/dist/assets/{Tooltip-C65FWX0W.js → Tooltip-C9RmASqV.js} +1 -1
- package/dist/assets/{UsageView-CKMaJ5W0.css → UsageView-DKigFrVY.css} +1 -1
- package/dist/assets/UsageView-DiCHVrs8.js +1 -0
- package/dist/assets/Warning-CmJYhk3M.js +1 -0
- package/dist/assets/{_plugin-vue_export-helper-DkLSTLBi.js → _plugin-vue_export-helper-NLzeiXdV.js} +1 -1
- package/dist/assets/{app-DtII96CF.js → app-CQZfHgyy.js} +1 -1
- package/dist/assets/app-DeeNNd_a.js +1 -0
- package/dist/assets/{browser-oMT2KRlV.js → browser-DNwI2j4X.js} +1 -1
- package/dist/assets/{chat-nPd2Ount.js → chat-DnFbBAAK.js} +2 -2
- package/dist/assets/context-DLFTSrww.js +1 -0
- package/dist/assets/fade-in-scale-up.cssr-BMJXPg-3.js +1 -0
- package/dist/assets/index-DlNQjiQP.js +306 -0
- package/dist/assets/{index-8v0lZOmS.css → index-TVVcuwR0.css} +1 -1
- package/dist/assets/{jobs-fIgcRW5v.js → jobs-B7U8gZia.js} +1 -1
- package/dist/assets/{pinia-D41F8A9y.js → pinia-DKSOddVw.js} +1 -1
- package/dist/assets/{router-B0PaAFys.js → router-CpYvE976.js} +2 -2
- package/dist/assets/{sessions-Dsqr5aLA.js → sessions-DTV2WuAE.js} +1 -1
- package/dist/assets/{skills-COmQAkb0.js → skills-DwX9oZGG.js} +1 -1
- package/dist/assets/use-compitable-D2-fMbL2.js +1 -0
- package/dist/assets/{use-message-CG8KB3t0.js → use-message-17mZlZe3.js} +1 -1
- package/dist/index.html +22 -18
- package/dist/server/index.js +3 -0
- package/dist/server/routes/terminal.d.ts +2 -0
- package/dist/server/routes/terminal.js +288 -0
- package/package.json +28 -4
- package/dist/assets/ChannelsView-CIZXL3vY.js +0 -1
- package/dist/assets/ChatView-DvAYfM24.js +0 -142
- package/dist/assets/Close-Ck11Jegf.js +0 -45
- package/dist/assets/Input-CyvPny5v.js +0 -234
- package/dist/assets/InputNumber-v7Tkrv97.js +0 -13
- package/dist/assets/JobsView-Cch6Sv2Y.js +0 -2
- package/dist/assets/JobsView-DARa8llR.css +0 -1
- package/dist/assets/LoginView-Cp-xfwtv.css +0 -1
- package/dist/assets/LoginView-DsClZpVT.js +0 -1
- package/dist/assets/Popover-ZzeCeChJ.js +0 -117
- package/dist/assets/Select-CPQQRbMt.js +0 -340
- package/dist/assets/SettingRow-BvAmImkg.js +0 -1
- package/dist/assets/SettingsView-B_5pGI0B.js +0 -352
- package/dist/assets/Suffix-La8FFPWu.js +0 -101
- package/dist/assets/UsageView-MZGY4EKW.js +0 -1
- package/dist/assets/app-DVSCPXta.js +0 -1
- package/dist/assets/context-DRBiUHq_.js +0 -1
- package/dist/assets/index-DNNVWa6r.js +0 -306
- /package/dist/assets/{omit-C6t0n7Zy.js → omit-C4dR5R2G.js} +0 -0
package/README.md
CHANGED
|
@@ -1,76 +1,165 @@
|
|
|
1
|
-
|
|
1
|
+
<p align="center">
|
|
2
|
+
<strong>Hermes Web UI</strong>
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
<p align="center">
|
|
6
|
+
A full-featured web dashboard for <a href="https://github.com/NousResearch/hermes-agent">Hermes Agent</a>.<br/>
|
|
7
|
+
Manage AI chat sessions, monitor usage & costs, configure platform channels,<br/>
|
|
8
|
+
schedule cron jobs, browse skills — all from a clean, responsive web interface.
|
|
9
|
+
</p>
|
|
10
|
+
|
|
11
|
+
<p align="center">
|
|
12
|
+
<code>npm install -g hermes-web-ui && hermes-web-ui start</code>
|
|
13
|
+
</p>
|
|
14
|
+
|
|
15
|
+
<p align="center">
|
|
16
|
+
<img src="https://github.com/EKKOLearnAI/hermes-web-ui/blob/main/src/assets/output.gif" alt="Hermes Web UI Demo" width="680"/>
|
|
17
|
+
</p>
|
|
18
|
+
|
|
19
|
+
<p align="center">
|
|
20
|
+
<strong>Mobile</strong>
|
|
21
|
+
</p>
|
|
22
|
+
<p align="center">
|
|
23
|
+
<video src="https://github.com/EKKOLearnAI/hermes-web-ui/blob/main/src/assets/video.mp4?raw=true" width="360" controls></video>
|
|
24
|
+
</p>
|
|
25
|
+
|
|
26
|
+
<p align="center">
|
|
27
|
+
<a href="https://www.npmjs.com/package/hermes-web-ui"><img src="https://img.shields.io/npm/v/hermes-web-ui?style=flat-square&color=blue" alt="npm version"/></a>
|
|
28
|
+
<a href="https://github.com/EKKOLearnAI/hermes-web-ui/blob/main/LICENSE"><img src="https://img.shields.io/npm/l/hermes-web-ui?style=flat-square" alt="license"/></a>
|
|
29
|
+
<a href="https://github.com/EKKOLearnAI/hermes-web-ui/stargazers"><img src="https://img.shields.io/github/stars/EKKOLearnAI/hermes-web-ui?style=flat-square" alt="stars"/></a>
|
|
30
|
+
</p>
|
|
2
31
|
|
|
3
|
-
|
|
32
|
+
---
|
|
4
33
|
|
|
5
|
-
|
|
34
|
+
## Features
|
|
6
35
|
|
|
7
|
-
|
|
36
|
+
### AI Chat
|
|
37
|
+
|
|
38
|
+
- Real-time streaming via SSE with async run support
|
|
39
|
+
- Multi-session management — create, rename, delete, switch between sessions
|
|
40
|
+
- Session grouping by source (Telegram, Discord, Slack, etc.) with collapsible accordion
|
|
41
|
+
- Markdown rendering with syntax highlighting and code copy
|
|
42
|
+
- Tool call detail expansion (arguments / result)
|
|
43
|
+
- File upload support
|
|
44
|
+
- Global model selector — discovers models from `~/.hermes/auth.json` credential pool
|
|
45
|
+
- Per-session model display badge and context token usage
|
|
46
|
+
|
|
47
|
+
### Platform Channels
|
|
48
|
+
|
|
49
|
+
Unified configuration for **8 platforms** in one page:
|
|
50
|
+
|
|
51
|
+
| Platform | Features |
|
|
52
|
+
|---|---|
|
|
53
|
+
| Telegram | Bot token, mention control, reactions, free-response chats |
|
|
54
|
+
| Discord | Bot token, mention, auto-thread, reactions, channel allow/ignore lists |
|
|
55
|
+
| Slack | Bot token, mention control, bot message handling |
|
|
56
|
+
| WhatsApp | Enable/disable, mention control, mention patterns |
|
|
57
|
+
| Matrix | Access token, homeserver, auto-thread, DM mention threads |
|
|
58
|
+
| Feishu (Lark) | App ID / Secret, mention control |
|
|
59
|
+
| WeChat | QR code login (scan in browser, auto-save credentials) |
|
|
60
|
+
| WeCom | Bot ID / Secret |
|
|
61
|
+
|
|
62
|
+
- Credential management writes to `~/.hermes/.env`
|
|
63
|
+
- Channel behavior settings write to `~/.hermes/config.yaml`
|
|
64
|
+
- Auto gateway restart on config change
|
|
65
|
+
- Per-platform configured/unconfigured status detection
|
|
66
|
+
|
|
67
|
+
### Usage Analytics
|
|
68
|
+
|
|
69
|
+
- Total token usage breakdown (input / output)
|
|
70
|
+
- Session count with daily average
|
|
71
|
+
- Estimated cost tracking & cache hit rate
|
|
72
|
+
- Model usage distribution chart
|
|
73
|
+
- 30-day daily trend (bar chart + data table)
|
|
74
|
+
|
|
75
|
+
### Scheduled Jobs
|
|
76
|
+
|
|
77
|
+
- Create, edit, pause, resume, delete cron jobs
|
|
78
|
+
- Trigger immediate execution
|
|
79
|
+
- Cron expression quick presets
|
|
80
|
+
|
|
81
|
+
### Model Management
|
|
82
|
+
|
|
83
|
+
- Auto-discover models from credential pool (`~/.hermes/auth.json`)
|
|
84
|
+
- Fetch available models from each provider endpoint (`/v1/models`)
|
|
85
|
+
- Add custom OpenAI-compatible providers
|
|
86
|
+
- Provider-level model grouping
|
|
8
87
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
-
|
|
18
|
-
-
|
|
88
|
+
### Skills & Memory
|
|
89
|
+
|
|
90
|
+
- Browse and search installed skills
|
|
91
|
+
- View skill details and attached files
|
|
92
|
+
- User notes and profile management
|
|
93
|
+
|
|
94
|
+
### Logs
|
|
95
|
+
|
|
96
|
+
- View agent / gateway / error logs
|
|
97
|
+
- Filter by log level, log file, and keyword
|
|
98
|
+
- Structured log parsing with HTTP access log highlighting
|
|
99
|
+
|
|
100
|
+
### Settings
|
|
101
|
+
|
|
102
|
+
- Display (streaming, compact mode, reasoning, cost display)
|
|
103
|
+
- Agent (max turns, timeout, tool enforcement)
|
|
104
|
+
- Memory (enable/disable, char limits)
|
|
105
|
+
- Session reset (idle timeout, scheduled reset)
|
|
106
|
+
- Privacy (PII redaction)
|
|
107
|
+
- API server configuration
|
|
19
108
|
|
|
20
|
-
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
## Quick Start
|
|
21
112
|
|
|
22
|
-
###
|
|
113
|
+
### npm (Recommended)
|
|
23
114
|
|
|
24
115
|
```bash
|
|
25
116
|
npm install -g hermes-web-ui
|
|
26
117
|
hermes-web-ui start
|
|
27
118
|
```
|
|
28
119
|
|
|
29
|
-
Open http://localhost:8648
|
|
120
|
+
Open **http://localhost:8648**
|
|
121
|
+
|
|
122
|
+
### One-line Setup (Auto-detect OS)
|
|
30
123
|
|
|
31
|
-
|
|
124
|
+
Automatically installs Node.js (if missing) and hermes-web-ui on Debian/Ubuntu/macOS:
|
|
32
125
|
|
|
33
126
|
```bash
|
|
34
|
-
# 1. Auto-setup: install Node.js + hermes-web-ui
|
|
35
127
|
bash <(curl -fsSL https://cdn.jsdelivr.net/gh/EKKOLearnAI/hermes-web-ui@main/scripts/setup.sh)
|
|
36
|
-
|
|
37
|
-
# 2. Start
|
|
38
|
-
hermes-web-ui start
|
|
39
128
|
```
|
|
40
129
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
### One-line Setup (Auto-detect OS)
|
|
130
|
+
### WSL
|
|
44
131
|
|
|
45
132
|
```bash
|
|
46
133
|
bash <(curl -fsSL https://cdn.jsdelivr.net/gh/EKKOLearnAI/hermes-web-ui@main/scripts/setup.sh)
|
|
134
|
+
hermes-web-ui start
|
|
47
135
|
```
|
|
48
136
|
|
|
49
|
-
|
|
137
|
+
> WSL auto-detects and uses `hermes gateway run` for background startup (no launchd/systemd).
|
|
50
138
|
|
|
51
139
|
### CLI Commands
|
|
52
140
|
|
|
53
|
-
| Command
|
|
54
|
-
|
|
55
|
-
| `hermes-web-ui start`
|
|
56
|
-
| `hermes-web-ui start --port 9000` | Start on custom port
|
|
57
|
-
| `hermes-web-ui stop`
|
|
58
|
-
| `hermes-web-ui restart`
|
|
59
|
-
| `hermes-web-ui status`
|
|
60
|
-
| `hermes-web-ui update`
|
|
61
|
-
| `hermes-web-ui -v`
|
|
62
|
-
| `hermes-web-ui -h`
|
|
63
|
-
| `hermes-web-ui` | Run in foreground (for debugging) |
|
|
141
|
+
| Command | Description |
|
|
142
|
+
|---|---|
|
|
143
|
+
| `hermes-web-ui start` | Start in background (daemon mode) |
|
|
144
|
+
| `hermes-web-ui start --port 9000` | Start on custom port |
|
|
145
|
+
| `hermes-web-ui stop` | Stop background process |
|
|
146
|
+
| `hermes-web-ui restart` | Restart background process |
|
|
147
|
+
| `hermes-web-ui status` | Check if running |
|
|
148
|
+
| `hermes-web-ui update` | Update to latest version & restart |
|
|
149
|
+
| `hermes-web-ui -v` | Show version number |
|
|
150
|
+
| `hermes-web-ui -h` | Show help message |
|
|
64
151
|
|
|
65
152
|
### Auto Configuration
|
|
66
153
|
|
|
67
|
-
On startup
|
|
154
|
+
On startup the BFF server automatically:
|
|
68
155
|
|
|
69
|
-
-
|
|
70
|
-
-
|
|
71
|
-
- Detects
|
|
72
|
-
-
|
|
73
|
-
- Opens
|
|
156
|
+
- Validates `~/.hermes/config.yaml` and fills missing `api_server` fields
|
|
157
|
+
- Backs up original config to `config.yaml.bak` if modified
|
|
158
|
+
- Detects and starts the gateway if needed
|
|
159
|
+
- Resolves port conflicts (kills stale processes)
|
|
160
|
+
- Opens browser on successful startup
|
|
161
|
+
|
|
162
|
+
---
|
|
74
163
|
|
|
75
164
|
## Development
|
|
76
165
|
|
|
@@ -81,161 +170,13 @@ npm install
|
|
|
81
170
|
npm run dev
|
|
82
171
|
```
|
|
83
172
|
|
|
84
|
-
This starts:
|
|
85
|
-
|
|
86
173
|
- Frontend: http://localhost:5173
|
|
87
174
|
- BFF Server: http://localhost:8648 (proxies to Hermes on 8642)
|
|
88
175
|
|
|
89
|
-
### Build
|
|
90
|
-
|
|
91
176
|
```bash
|
|
92
|
-
npm run build
|
|
93
|
-
```
|
|
94
|
-
|
|
95
|
-
Outputs to `dist/` (frontend + compiled BFF server).
|
|
96
|
-
|
|
97
|
-
## Project Structure
|
|
98
|
-
|
|
99
|
-
```
|
|
100
|
-
hermes-web-ui/
|
|
101
|
-
├── bin/
|
|
102
|
-
│ └── hermes-web-ui.mjs # CLI entry (start/stop/restart/status/update/version/help)
|
|
103
|
-
├── server/src/
|
|
104
|
-
│ ├── index.ts # BFF entry (Koa app bootstrap)
|
|
105
|
-
│ ├── config.ts # Configuration (port, upstream, etc.)
|
|
106
|
-
│ ├── routes/
|
|
107
|
-
│ │ ├── proxy.ts # API proxy to Hermes (/api/*, /v1/*)
|
|
108
|
-
│ │ ├── config.ts # Config & credentials management
|
|
109
|
-
│ │ ├── weixin.ts # WeChat QR code login proxy
|
|
110
|
-
│ │ ├── upload.ts # File upload (POST /upload)
|
|
111
|
-
│ │ ├── sessions.ts # Session management via Hermes CLI
|
|
112
|
-
│ │ ├── filesystem.ts # Skills, memory, config model management
|
|
113
|
-
│ │ ├── webhook.ts # Webhook receiver
|
|
114
|
-
│ │ └── logs.ts # Log file listing and reading
|
|
115
|
-
│ └── services/
|
|
116
|
-
│ └── hermes-cli.ts # Hermes CLI wrapper (sessions, logs, version)
|
|
117
|
-
├── src/
|
|
118
|
-
│ ├── i18n/ # Internationalization (en / zh)
|
|
119
|
-
│ │ ├── index.ts # i18n instance setup
|
|
120
|
-
│ │ └── locales/
|
|
121
|
-
│ │ ├── en.ts # English translations
|
|
122
|
-
│ │ └── zh.ts # Chinese translations
|
|
123
|
-
│ ├── api/ # Frontend API layer
|
|
124
|
-
│ ├── stores/ # Pinia state management
|
|
125
|
-
│ ├── components/
|
|
126
|
-
│ │ ├── layout/
|
|
127
|
-
│ │ │ ├── AppSidebar.vue # Sidebar navigation
|
|
128
|
-
│ │ │ ├── LanguageSwitch.vue # Language toggle (EN / 中文)
|
|
129
|
-
│ │ │ └── ModelSelector.vue # Global model selector
|
|
130
|
-
│ │ ├── chat/ # Chat components
|
|
131
|
-
│ │ ├── jobs/ # Job components
|
|
132
|
-
│ │ ├── models/ # Model/provider components
|
|
133
|
-
│ │ ├── settings/ # Settings components
|
|
134
|
-
│ │ │ ├── PlatformCard.vue # Platform card with config status
|
|
135
|
-
│ │ │ └── PlatformSettings.vue # Platform channel configuration
|
|
136
|
-
│ │ ├── usage/ # Usage statistics components
|
|
137
|
-
│ │ └── skills/ # Skill components
|
|
138
|
-
│ ├── views/
|
|
139
|
-
│ │ ├── ChatView.vue # Chat page
|
|
140
|
-
│ │ ├── JobsView.vue # Jobs page
|
|
141
|
-
│ │ ├── LogsView.vue # Logs page
|
|
142
|
-
│ │ ├── ModelsView.vue # Model management page
|
|
143
|
-
│ │ ├── ChannelsView.vue # Platform channels page
|
|
144
|
-
│ │ ├── SkillsView.vue # Skills page
|
|
145
|
-
│ │ ├── MemoryView.vue # Memory page
|
|
146
|
-
│ │ ├── UsageView.vue # Usage statistics page
|
|
147
|
-
│ │ └── SettingsView.vue # Settings page
|
|
148
|
-
│ └── router/index.ts # Router configuration
|
|
149
|
-
└── dist/ # Build output (published to npm)
|
|
150
|
-
├── server/index.js # Compiled BFF
|
|
151
|
-
├── index.html # Frontend entry
|
|
152
|
-
└── assets/ # Frontend static assets
|
|
177
|
+
npm run build # outputs to dist/
|
|
153
178
|
```
|
|
154
179
|
|
|
155
|
-
## Features
|
|
156
|
-
|
|
157
|
-
### Chat
|
|
158
|
-
|
|
159
|
-
- Async Run + SSE event streaming via BFF proxy
|
|
160
|
-
- Session management via Hermes CLI
|
|
161
|
-
- Multi-session switching with message history
|
|
162
|
-
- Session grouping by source (Telegram, Discord, Slack, etc.) with collapsible accordion
|
|
163
|
-
- Session rename and deletion
|
|
164
|
-
- Markdown rendering with syntax highlighting and code copy
|
|
165
|
-
- Tool call detail expansion (arguments / result)
|
|
166
|
-
- File upload support (saved to temp, path passed to API)
|
|
167
|
-
- Model selector — automatically discovers available models from `~/.hermes/auth.json` credential pool
|
|
168
|
-
- Global model switching (updates `~/.hermes/config.yaml`)
|
|
169
|
-
- Per-session model display (badge in chat header and session list)
|
|
170
|
-
- Context token usage display (used / total)
|
|
171
|
-
|
|
172
|
-
### Usage Statistics
|
|
173
|
-
|
|
174
|
-
- Total token usage breakdown (input / output)
|
|
175
|
-
- Session count with daily average
|
|
176
|
-
- Estimated cost tracking
|
|
177
|
-
- Cache hit rate
|
|
178
|
-
- Model usage distribution (horizontal bar chart)
|
|
179
|
-
- 30-day daily trend (bar chart + data table)
|
|
180
|
-
- Hover tooltips on chart bars
|
|
181
|
-
|
|
182
|
-
### Platform Channels
|
|
183
|
-
|
|
184
|
-
- Unified channel configuration page (Telegram, Discord, Slack, WhatsApp, Matrix, Feishu, WeChat, WeCom)
|
|
185
|
-
- Credential management — writes to `~/.hermes/.env` (matching `hermes gateway setup` behavior)
|
|
186
|
-
- Channel behavior settings — writes to `~/.hermes/config.yaml`
|
|
187
|
-
- WeChat QR code login — opens QR in browser, polls scan status, auto-saves credentials
|
|
188
|
-
- Auto gateway restart after any channel config change
|
|
189
|
-
- Per-platform configured/unconfigured status detection
|
|
190
|
-
|
|
191
|
-
### Model Management
|
|
192
|
-
|
|
193
|
-
- Automatically reads credential pool from `~/.hermes/auth.json`
|
|
194
|
-
- Fetches available models from each provider endpoint (`/v1/models`)
|
|
195
|
-
- Groups models by provider (e.g. zai, subrouter.ai)
|
|
196
|
-
- Add custom OpenAI-compatible providers
|
|
197
|
-
- Switching model updates `model.provider` in config.yaml to bypass env auto-detection
|
|
198
|
-
- Error handling: parallel fetching, per-provider timeout, fallback to config.yaml parsing
|
|
199
|
-
|
|
200
|
-
### Settings
|
|
201
|
-
|
|
202
|
-
- Display settings (streaming, compact mode, reasoning, cost, etc.)
|
|
203
|
-
- Agent settings (max turns, timeout, tool enforcement)
|
|
204
|
-
- Memory settings (enable/disable, char limits)
|
|
205
|
-
- Session reset settings (idle timeout, scheduled reset)
|
|
206
|
-
- Privacy settings (PII redaction)
|
|
207
|
-
- API server settings
|
|
208
|
-
|
|
209
|
-
### Scheduled Jobs
|
|
210
|
-
|
|
211
|
-
- Job list view (including paused/disabled jobs)
|
|
212
|
-
- Create, edit, pause, resume, and delete jobs
|
|
213
|
-
- Trigger immediate job execution
|
|
214
|
-
- Cron expression quick presets
|
|
215
|
-
|
|
216
|
-
### Skills & Memory
|
|
217
|
-
|
|
218
|
-
- Browse and search installed skills
|
|
219
|
-
- View skill details and attached files
|
|
220
|
-
- User notes and profile management
|
|
221
|
-
|
|
222
|
-
### Logs
|
|
223
|
-
|
|
224
|
-
- View Hermes agent/gateway/error logs
|
|
225
|
-
- Filter by log level, log file, and search keyword
|
|
226
|
-
- Structured log parsing with HTTP access log highlighting
|
|
227
|
-
|
|
228
|
-
### Other
|
|
229
|
-
|
|
230
|
-
- Internationalization — auto-detect browser language, manual toggle between Chinese and English
|
|
231
|
-
- Real-time connection status monitoring
|
|
232
|
-
- Hermes version display in sidebar
|
|
233
|
-
- Auto config check on startup with field-level validation
|
|
234
|
-
- Port conflict auto-resolution (kills stale processes)
|
|
235
|
-
- Auto browser open on startup
|
|
236
|
-
- Minimalist "Pure Ink" theme
|
|
237
|
-
- Session group collapse state persisted across navigation
|
|
238
|
-
|
|
239
180
|
## Architecture
|
|
240
181
|
|
|
241
182
|
```
|
|
@@ -248,21 +189,13 @@ Browser → BFF (Koa, :8648) → Hermes API (:8642)
|
|
|
248
189
|
Tencent iLink API (WeChat QR login)
|
|
249
190
|
```
|
|
250
191
|
|
|
251
|
-
The BFF layer handles
|
|
192
|
+
The BFF layer handles API proxy, SSE streaming, file upload, session CRUD via CLI, config/credential management, WeChat QR login, model discovery, skills/memory management, log reading, and static file serving.
|
|
252
193
|
|
|
253
|
-
|
|
254
|
-
- SSE streaming passthrough
|
|
255
|
-
- File upload to temp directory
|
|
256
|
-
- Session CRUD via Hermes CLI (with cache/cost token passthrough)
|
|
257
|
-
- Config & credential management (config.yaml + .env)
|
|
258
|
-
- WeChat QR code login flow (fetch QR, poll status, save credentials)
|
|
259
|
-
- Auto gateway restart on platform config changes
|
|
260
|
-
- Model discovery from `~/.hermes/auth.json` credential pool
|
|
261
|
-
- Skills, memory, and custom provider management
|
|
262
|
-
- Log file reading and parsing
|
|
263
|
-
- Static file serving (SPA fallback)
|
|
194
|
+
## Tech Stack
|
|
264
195
|
|
|
265
|
-
|
|
196
|
+
**Frontend:** Vue 3 + TypeScript + Vite + Naive UI + Pinia + Vue Router + vue-i18n + SCSS + markdown-it + highlight.js
|
|
197
|
+
|
|
198
|
+
**Backend:** Koa 2 (BFF server) + node-pty (web terminal)
|
|
266
199
|
|
|
267
200
|
## License
|
|
268
201
|
|
package/bin/hermes-web-ui.mjs
CHANGED
|
@@ -2,13 +2,14 @@
|
|
|
2
2
|
import { spawn, execSync } from 'child_process'
|
|
3
3
|
import { resolve, dirname, join } from 'path'
|
|
4
4
|
import { fileURLToPath } from 'url'
|
|
5
|
-
import { readFileSync, writeFileSync, unlinkSync, mkdirSync, openSync } from 'fs'
|
|
5
|
+
import { readFileSync, writeFileSync, unlinkSync, mkdirSync, openSync, chmodSync } from 'fs'
|
|
6
6
|
import { randomBytes } from 'crypto'
|
|
7
7
|
import { homedir } from 'os'
|
|
8
8
|
|
|
9
9
|
const __dirname = dirname(fileURLToPath(import.meta.url))
|
|
10
10
|
const serverEntry = resolve(__dirname, '..', 'dist', 'server', 'index.js')
|
|
11
|
-
const
|
|
11
|
+
const pkgDir = resolve(__dirname, '..')
|
|
12
|
+
const pkg = JSON.parse(readFileSync(resolve(pkgDir, 'package.json'), 'utf-8'))
|
|
12
13
|
const VERSION = pkg.version
|
|
13
14
|
const PID_DIR = resolve(homedir(), '.hermes-web-ui')
|
|
14
15
|
const PID_FILE = join(PID_DIR, 'server.pid')
|
|
@@ -16,6 +17,15 @@ const LOG_FILE = join(PID_DIR, 'server.log')
|
|
|
16
17
|
const TOKEN_FILE = resolve(__dirname, '..', 'dist', 'server', 'data', '.token')
|
|
17
18
|
const DEFAULT_PORT = 8648
|
|
18
19
|
|
|
20
|
+
// ─── Auto-fix node-pty native module ──────────────────────────
|
|
21
|
+
function ensureNativeModules() {
|
|
22
|
+
const prebuildDir = join(pkgDir, 'node_modules', 'node-pty', 'prebuilds', `${process.platform}-${process.arch}`)
|
|
23
|
+
const helper = join(prebuildDir, 'spawn-helper')
|
|
24
|
+
try {
|
|
25
|
+
chmodSync(helper, 0o755)
|
|
26
|
+
} catch {}
|
|
27
|
+
}
|
|
28
|
+
|
|
19
29
|
function getToken() {
|
|
20
30
|
try {
|
|
21
31
|
return readFileSync(TOKEN_FILE, 'utf-8').trim()
|
|
@@ -105,6 +115,7 @@ function startDaemon(port) {
|
|
|
105
115
|
|
|
106
116
|
mkdirSync(PID_DIR, { recursive: true })
|
|
107
117
|
|
|
118
|
+
ensureNativeModules()
|
|
108
119
|
const token = ensureToken()
|
|
109
120
|
|
|
110
121
|
const logStream = openSync(LOG_FILE, 'a')
|
|
@@ -260,6 +271,7 @@ switch (command) {
|
|
|
260
271
|
doUpdate()
|
|
261
272
|
break
|
|
262
273
|
default:
|
|
274
|
+
ensureNativeModules()
|
|
263
275
|
const port = !isNaN(command) ? parseInt(command) : DEFAULT_PORT
|
|
264
276
|
const child = spawn(process.execPath, [serverEntry], {
|
|
265
277
|
stdio: 'inherit',
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{C as e,F as t,N as n,R as r,V as i,ct as a,d as o,dt as s,f as c,j as l}from"./router-
|
|
1
|
+
import{C as e,F as t,N as n,R as r,V as i,ct as a,d as o,dt as s,f as c,j as l}from"./router-CpYvE976.js";import{B as u,K as d,Q as f,R as p,U as m,Z as h,a as g,at as _,c as v,ct as y,d as b,dt as x,et as S,l as C,lt as w,n as T,nt as E,o as D,ot as O,q as k,r as A,t as j,tt as M,u as N,ut as P,z as F}from"./browser-DNwI2j4X.js";function I(e){return e.replace(/#|\(|\)|,|\s|\./g,`_`)}var L=l({name:`FadeInExpandTransition`,props:{appear:Boolean,group:Boolean,mode:String,onLeave:Function,onAfterLeave:Function,onAfterEnter:Function,width:Boolean,reverse:Boolean},setup(e,{slots:t}){function r(t){e.width?t.style.maxWidth=`${t.offsetWidth}px`:t.style.maxHeight=`${t.offsetHeight}px`,t.offsetWidth}function i(t){e.width?t.style.maxWidth=`0`:t.style.maxHeight=`0`,t.offsetWidth;let{onLeave:n}=e;n&&n()}function a(t){e.width?t.style.maxWidth=``:t.style.maxHeight=``;let{onAfterLeave:n}=e;n&&n()}function s(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 l(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?c:o,h={name:d?`fade-in-width-expand-transition`:`fade-in-height-expand-transition`,appear:f,onEnter:s,onAfterEnter:l,onBeforeLeave:r,onLeave:i,onAfterLeave:a};return u||(h.mode=p),n(m,h,t)}}}),{cubicBezierEaseInOut:R}=N;function z({duration:e=`.2s`,delay:t=`.1s`}={}){return[_(`&.fade-in-width-expand-transition-leave-from, &.fade-in-width-expand-transition-enter-to`,{opacity:1}),_(`&.fade-in-width-expand-transition-leave-to, &.fade-in-width-expand-transition-enter-from`,`
|
|
2
2
|
opacity: 0!important;
|
|
3
3
|
margin-left: 0!important;
|
|
4
4
|
margin-right: 0!important;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
.platform-card[data-v-ee5f4168]{background-color:#fff;border:1px solid #e0e0e0;border-radius:10px;margin-bottom:12px;overflow:hidden}.platform-card.configured[data-v-ee5f4168]{border-color:#2e7d3233}.platform-card-header[data-v-ee5f4168]{cursor:pointer;-webkit-user-select:none;user-select:none;justify-content:space-between;align-items:center;padding:12px 16px;display:flex}.platform-card-header[data-v-ee5f4168]:hover{background-color:#1a1a1a08}.platform-info[data-v-ee5f4168]{align-items:center;gap:10px;display:flex}.platform-icon[data-v-ee5f4168]{color:#666;flex-shrink:0;width:18px;height:18px}.platform-name[data-v-ee5f4168]{color:#1a1a1a;font-size:14px;font-weight:500}.expand-icon[data-v-ee5f4168]{color:#999;font-size:12px;transition:transform .2s}.expand-icon.expanded[data-v-ee5f4168]{transform:rotate(0)}.expand-icon[data-v-ee5f4168]:not(.expanded){transform:rotate(-90deg)}.platform-card-body[data-v-ee5f4168]{border-top:1px solid #ebebeb;padding:0 16px 12px}.settings-section[data-v-
|
|
1
|
+
.platform-card[data-v-ee5f4168]{background-color:#fff;border:1px solid #e0e0e0;border-radius:10px;margin-bottom:12px;overflow:hidden}.platform-card.configured[data-v-ee5f4168]{border-color:#2e7d3233}.platform-card-header[data-v-ee5f4168]{cursor:pointer;-webkit-user-select:none;user-select:none;justify-content:space-between;align-items:center;padding:12px 16px;display:flex}.platform-card-header[data-v-ee5f4168]:hover{background-color:#1a1a1a08}.platform-info[data-v-ee5f4168]{align-items:center;gap:10px;display:flex}.platform-icon[data-v-ee5f4168]{color:#666;flex-shrink:0;width:18px;height:18px}.platform-name[data-v-ee5f4168]{color:#1a1a1a;font-size:14px;font-weight:500}.expand-icon[data-v-ee5f4168]{color:#999;font-size:12px;transition:transform .2s}.expand-icon.expanded[data-v-ee5f4168]{transform:rotate(0)}.expand-icon[data-v-ee5f4168]:not(.expanded){transform:rotate(-90deg)}.platform-card-body[data-v-ee5f4168]{border-top:1px solid #ebebeb;padding:0 16px 12px}.settings-section[data-v-9f4c95ee]{margin-top:16px}.weixin-qr-section[data-v-9f4c95ee]{margin-top:12px;margin-bottom:12px}.weixin-qr-loading[data-v-9f4c95ee]{color:#999;align-items:center;gap:8px;font-size:13px;display:flex}.weixin-qr-hint[data-v-9f4c95ee]{color:#666;font-size:13px}.channels-view[data-v-099b0c1b]{height:calc(100 * var(--vh));flex-direction:column;display:flex}.channels-content[data-v-099b0c1b]{flex:1;padding:20px;position:relative;overflow-y:auto}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{A as e,C as t,D as n,E as r,G as i,J as a,Q as o,T as s,U as c,W as l,Y as u,ct as d,gt as f,j as p,k as m,mt as h,pt as g,q as _,w as v,y}from"./router-CpYvE976.js";import{r as b,t as x}from"./_plugin-vue_export-helper-NLzeiXdV.js";import{t as S}from"./Button-BHvh9zmj.js";import{t as C}from"./Input-CS0p63GR.js";import{t as w}from"./Tag-NMAaTGW7.js";import{t as T}from"./use-message-17mZlZe3.js";import{t as E}from"./Spin-BbbA3R-G.js";import{t as D}from"./Switch-Xa0U6jwA.js";import{a as O,i as k,n as A,o as j,r as M,t as N}from"./SettingRow-CsKwX-jv.js";var P={class:`platform-info`},F=[`innerHTML`],I={class:`platform-name`},L={key:0,class:`platform-card-body`},R=x(p({__name:`PlatformCard`,props:{name:{},icon:{},config:{},credentials:{}},setup(s){let c=s,l=d(!0),{t:u}=b(),p=t(()=>{let e=c.credentials;if(!e)return!1;let t=[`token`,`api_key`,`app_id`,`client_id`,`secret`,`app_secret`,`client_secret`,`access_token`,`bot_id`,`account_id`,`enabled`];return[e,e.extra].filter(Boolean).some(e=>t.some(t=>{let n=e[t];return n!=null&&n!==``&&n!==!1}))});return(t,c)=>(i(),n(`div`,{class:h([`platform-card`,{configured:p.value}])},[v(`div`,{class:`platform-card-header`,onClick:c[0]||=e=>l.value=!l.value},[v(`div`,P,[v(`span`,{class:`platform-icon`,innerHTML:s.icon},null,8,F),v(`span`,I,f(s.name),1),e(g(w),{type:p.value?`success`:`default`,size:`small`,round:``},{default:o(()=>[m(f(p.value?g(u)(`common.configured`):g(u)(`common.notConfigured`)),1)]),_:1},8,[`type`])]),v(`span`,{class:h([`expand-icon`,{expanded:l.value}])},`▾`,2)]),l.value?(i(),n(`div`,L,[a(t.$slots,`default`,{},void 0,!0)])):r(``,!0)],2))}}),[[`__scopeId`,`data-v-ee5f4168`]]),z={class:`settings-section`},B={class:`weixin-qr-section`},V={key:1,class:`weixin-qr-loading`},H={key:2,class:`weixin-qr-hint`},U=x(p({__name:`PlatformSettings`,setup(t){let a=A(),c=T(),{t:p}=b();async function h(e,t){try{await a.saveSection(e,t),c.success(p(`settings.saved`))}catch{c.error(p(`settings.saveFailed`))}}let x=d(!1);async function w(e,t){x.value=!0;try{await O(e,t),await a.fetchSettings(),c.success(p(`settings.saved`))}catch{c.error(p(`settings.saveFailed`))}finally{x.value=!1}}function E(e){return a.platforms[e]||{}}let P=d(``),F=d(``),I=d(`idle`),L=null;async function U(){I.value=`loading`,P.value=``,F.value=``,G();try{let e=await M();F.value=e.qrcode,P.value=e.qrcode_url,window.open(e.qrcode_url,`_blank`),I.value=`waiting`,W()}catch(e){I.value=`error`,c.error(e.message||p(`platform.qrFetching`))}}function W(){F.value&&(L=setTimeout(async()=>{try{let e=await k(F.value);e.status===`wait`?W():e.status===`scaned`?(I.value=`scaned`,W()):e.status===`expired`?I.value=`expired`:e.status===`confirmed`&&(I.value=`confirmed`,await j({account_id:e.account_id,token:e.token,base_url:e.base_url}),await a.fetchSettings(),c.success(p(`settings.saved`)))}catch{W()}},3e3))}function G(){L&&=(clearTimeout(L),null)}l(()=>{G()});let K=[{key:`telegram`,name:`Telegram`,icon:`<svg viewBox="0 0 24 24" fill="currentColor"><path d="M11.944 0A12 12 0 0 0 0 12a12 12 0 0 0 12 12 12 12 0 0 0 12-12A12 12 0 0 0 12 0a12 12 0 0 0-.056 0zm4.962 7.224c.1-.002.321.023.465.14a.506.506 0 0 1 .171.325c.016.093.036.306.02.472-.18 1.898-.962 6.502-1.36 8.627-.168.9-.499 1.201-.82 1.23-.696.065-1.225-.46-1.9-.902-1.056-.693-1.653-1.124-2.678-1.8-1.185-.78-.417-1.21.258-1.91.177-.184 3.247-2.977 3.307-3.23.007-.032.014-.15-.056-.212s-.174-.041-.249-.024c-.106.024-1.793 1.14-5.061 3.345-.479.33-.913.49-1.302.48-.428-.008-1.252-.241-1.865-.44-.752-.245-1.349-.374-1.297-.789.027-.216.325-.437.893-.663 3.498-1.524 5.83-2.529 6.998-3.014 3.332-1.386 4.025-1.627 4.476-1.635z"/></svg>`},{key:`discord`,name:`Discord`,icon:`<svg viewBox="0 0 24 24" fill="currentColor"><path d="M20.317 4.3698a19.7913 19.7913 0 00-4.8851-1.5152.0741.0741 0 00-.0785.0371c-.211.3753-.4447.8648-.6083 1.2495-1.8447-.2762-3.68-.2762-5.4868 0-.1636-.3933-.4058-.8742-.6177-1.2495a.077.077 0 00-.0785-.037 19.7363 19.7363 0 00-4.8852 1.515.0699.0699 0 00-.0321.0277C.5334 9.0458-.319 13.5799.0992 18.0578a.0824.0824 0 00.0312.0561c2.0528 1.5076 4.0413 2.4228 5.9929 3.0294a.0777.0777 0 00.0842-.0276c.4616-.6304.8731-1.2952 1.226-1.9942a.076.076 0 00-.0416-.1057c-.6528-.2476-1.2743-.5495-1.8722-.8923a.077.077 0 01-.0076-.1277c.1258-.0943.2517-.1923.3718-.2914a.0743.0743 0 01.0776-.0105c3.9278 1.7933 8.18 1.7933 12.0614 0a.0739.0739 0 01.0785.0095c.1202.099.246.1981.3728.2924a.077.077 0 01-.0066.1276 12.2986 12.2986 0 01-1.873.8914.0766.0766 0 00-.0407.1067c.3604.698.7719 1.3628 1.225 1.9932a.076.076 0 00.0842.0286c1.961-.6067 3.9495-1.5219 6.0023-3.0294a.077.077 0 00.0313-.0552c.5004-5.177-.8382-9.6739-3.5485-13.6604a.061.061 0 00-.0312-.0286zM8.02 15.3312c-1.1825 0-2.1569-1.0857-2.1569-2.419 0-1.3332.9555-2.4189 2.157-2.4189 1.2108 0 2.1757 1.0952 2.1568 2.419 0 1.3332-.9555 2.4189-2.1569 2.4189zm7.9748 0c-1.1825 0-2.1569-1.0857-2.1569-2.419 0-1.3332.9554-2.4189 2.1569-2.4189 1.2108 0 2.1757 1.0952 2.1568 2.419 0 1.3332-.946 2.4189-2.1568 2.4189z"/></svg>`},{key:`slack`,name:`Slack`,icon:`<svg viewBox="0 0 24 24" fill="currentColor"><path d="M5.042 15.165a2.528 2.528 0 0 1-2.52 2.523A2.528 2.528 0 0 1 0 15.165a2.527 2.527 0 0 1 2.522-2.52h2.52v2.52zm1.271 0a2.527 2.527 0 0 1 2.521-2.52 2.527 2.527 0 0 1 2.521 2.52v6.313A2.528 2.528 0 0 1 8.834 24a2.528 2.528 0 0 1-2.521-2.522v-6.313zM8.834 5.042a2.528 2.528 0 0 1-2.521-2.52A2.528 2.528 0 0 1 8.834 0a2.528 2.528 0 0 1 2.521 2.522v2.52H8.834zm0 1.271a2.528 2.528 0 0 1 2.521 2.521 2.528 2.528 0 0 1-2.521 2.521H2.522A2.528 2.528 0 0 1 0 8.834a2.528 2.528 0 0 1 2.522-2.521h6.312zm10.122 0a2.528 2.528 0 0 1 2.522-2.521A2.528 2.528 0 0 1 24 8.834a2.528 2.528 0 0 1-2.522 2.521h-2.522V5.042zm-1.27 0a2.528 2.528 0 0 1-2.523 2.521 2.527 2.527 0 0 1-2.52-2.521V2.522A2.527 2.527 0 0 1 15.165 0a2.528 2.528 0 0 1 2.523 2.522v6.312zM15.165 18.956a2.528 2.528 0 0 1 2.523 2.522A2.528 2.528 0 0 1 15.165 24a2.527 2.527 0 0 1-2.52-2.522v-2.522h2.52zm0-1.27a2.527 2.527 0 0 1 2.523-2.52h6.313A2.528 2.528 0 0 1 24 18.956a2.528 2.528 0 0 1-2.522 2.523h-6.313z"/></svg>`},{key:`whatsapp`,name:`WhatsApp`,icon:`<svg viewBox="0 0 24 24" fill="currentColor"><path d="M17.472 14.382c-.297-.149-1.758-.867-2.03-.967-.273-.099-.471-.148-.67.15-.197.297-.767.966-.94 1.164-.173.199-.347.223-.644.075-.297-.15-1.255-.463-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.298-.347.446-.52.149-.174.198-.298.298-.497.099-.198.05-.371-.025-.52-.075-.149-.669-1.612-.916-2.207-.242-.579-.487-.5-.669-.51-.173-.008-.371-.01-.57-.01-.198 0-.52.074-.792.372-.272.297-1.04 1.016-1.04 2.479 0 1.462 1.065 2.875 1.213 3.074.149.198 2.096 3.2 5.077 4.487.709.306 1.262.489 1.694.625.712.227 1.36.195 1.871.118.571-.085 1.758-.719 2.006-1.413.248-.694.248-1.289.173-1.413-.074-.124-.272-.198-.57-.347m-5.421 7.403h-.004a9.87 9.87 0 01-5.031-1.378l-.361-.214-3.741.982.998-3.648-.235-.374a9.86 9.86 0 01-1.51-5.26c.001-5.45 4.436-9.884 9.888-9.884 2.64 0 5.122 1.03 6.988 2.898a9.825 9.825 0 012.893 6.994c-.003 5.45-4.437 9.884-9.885 9.884m8.413-18.297A11.815 11.815 0 0012.05 0C5.495 0 .16 5.335.157 11.892c0 2.096.547 4.142 1.588 5.945L.057 24l6.305-1.654a11.882 11.882 0 005.683 1.448h.005c6.554 0 11.89-5.335 11.893-11.893a11.821 11.821 0 00-3.48-8.413z"/></svg>`},{key:`matrix`,name:`Matrix`,icon:`<svg viewBox="0 0 24 24" fill="currentColor"><path d="M.632.55v22.9H2.28V24H0V0h2.28v.55zm7.043 7.26v1.157h.033c.309-.443.683-.784 1.117-1.024.433-.245.936-.365 1.5-.365.54 0 1.033.107 1.48.324.448.217.786.619 1.017 1.205.24-.376.558-.702.956-.98.398-.277.872-.414 1.424-.414.41 0 .784.065 1.122.194.34.13.629.325.87.588.241.263.428.59.56.984.132.393.198.85.198 1.368v5.89h-2.49v-4.893c0-.268-.016-.525-.048-.77a1.627 1.627 0 00-.2-.63 1.028 1.028 0 00-.392-.426 1.294 1.294 0 00-.616-.134c-.277 0-.508.05-.693.15a1.043 1.043 0 00-.43.41 1.768 1.768 0 00-.214.616 4.15 4.15 0 00-.06.74v4.937H9.29v-4.937c0-.25-.01-.498-.032-.742a1.84 1.84 0 00-.166-.638.998.998 0 00-.363-.448 1.206 1.206 0 00-.624-.154c-.26 0-.483.048-.67.144a1.055 1.055 0 00-.436.402 1.744 1.744 0 00-.227.616 4.108 4.108 0 00-.063.74v4.937H5.21V7.81zm15.693 15.64V.55H21.72V0H24v24h-2.28v-.55z"/></svg>`},{key:`feishu`,name:`Feishu`,icon:`<svg viewBox="0 0 24 24" fill="currentColor"><path d="M6.59 3.41a2.25 2.25 0 0 1 3.182 0L13.5 7.14l-3.182 3.182L6.59 7.59a2.25 2.25 0 0 1 0-3.182zm5.303 5.303L15.075 5.53a2.25 2.25 0 0 1 3.182 3.182L15.075 11.894 11.893 8.713zM3.41 6.59a2.25 2.25 0 0 1 3.182 0l3.182 3.182-3.182 3.182a2.25 2.25 0 0 1-3.182-3.182L3.41 6.59zm5.303 5.303L11.894 15.075a2.25 2.25 0 0 1-3.182 3.182L5.53 15.075 8.713 11.893zm5.303-5.303L17.478 9.778a2.25 2.25 0 0 1-3.182 3.182L10.53 10.075l3.182-3.182 0 .023z"/></svg>`},{key:`weixin`,name:`Weixin`,icon:`<svg viewBox="0 0 24 24" fill="currentColor"><path d="M8.691 2.188C3.891 2.188 0 5.476 0 9.53c0 2.212 1.17 4.203 3.002 5.55a.59.59 0 01.213.665l-.39 1.48c-.019.07-.048.141-.048.213 0 .163.13.295.29.295a.326.326 0 00.167-.054l1.903-1.114a.864.864 0 01.717-.098 10.16 10.16 0 002.837.403c.276 0 .543-.027.811-.05-.857-2.578.157-4.972 1.932-6.446 1.703-1.415 3.882-1.98 5.853-1.838-.576-3.583-4.196-6.348-8.596-6.348zM5.785 5.991c.642 0 1.162.529 1.162 1.18a1.17 1.17 0 01-1.162 1.178A1.17 1.17 0 014.623 7.17c0-.651.52-1.18 1.162-1.18zm5.813 0c.642 0 1.162.529 1.162 1.18a1.17 1.17 0 01-1.162 1.178 1.17 1.17 0 01-1.162-1.178c0-.651.52-1.18 1.162-1.18zm3.68 4.025c-3.694 0-6.69 2.462-6.69 5.496 0 3.034 2.996 5.496 6.69 5.496.753 0 1.477-.1 2.158-.28a.66.66 0 01.548.074l1.46.854a.25.25 0 00.127.041.224.224 0 00.221-.225c0-.055-.022-.109-.037-.162l-.298-1.131a.453.453 0 01.163-.509C21.81 18.613 22.77 16.973 22.77 15.512c0-3.034-2.996-5.496-6.69-5.496h.198zm-2.454 3.347c.491 0 .889.404.889.902a.896.896 0 01-.889.903.896.896 0 01-.889-.903c0-.498.398-.902.889-.902zm4.912 0c.491 0 .889.404.889.902a.896.896 0 01-.889.903.896.896 0 01-.889-.903c0-.498.398-.902.889-.902z"/></svg>`},{key:`wecom`,name:`WeCom`,icon:`<svg viewBox="0 0 24 24" fill="currentColor"><path d="M8.691 2.188C3.891 2.188 0 5.476 0 9.53c0 2.212 1.17 4.203 3.002 5.55a.59.59 0 01.213.665l-.39 1.48c-.019.07-.048.141-.048.213 0 .163.13.295.29.295a.326.326 0 00.167-.054l1.903-1.114a.864.864 0 01.717-.098 10.16 10.16 0 002.837.403c.276 0 .543-.027.811-.05-.857-2.578.157-4.972 1.932-6.446 1.703-1.415 3.882-1.98 5.853-1.838-.576-3.583-4.196-6.348-8.596-6.348zM5.785 5.991c.642 0 1.162.529 1.162 1.18a1.17 1.17 0 01-1.162 1.178A1.17 1.17 0 014.623 7.17c0-.651.52-1.18 1.162-1.18zm5.813 0c.642 0 1.162.529 1.162 1.18a1.17 1.17 0 01-1.162 1.178 1.17 1.17 0 01-1.162-1.178c0-.651.52-1.18 1.162-1.18zm3.68 4.025c-3.694 0-6.69 2.462-6.69 5.496 0 3.034 2.996 5.496 6.69 5.496.753 0 1.477-.1 2.158-.28a.66.66 0 01.548.074l1.46.854a.25.25 0 00.127.041.224.224 0 00.221-.225c0-.055-.022-.109-.037-.162l-.298-1.131a.453.453 0 01.163-.509C21.81 18.613 22.77 16.973 22.77 15.512c0-3.034-2.996-5.496-6.69-5.496h.198zm-2.454 3.347c.491 0 .889.404.889.902a.896.896 0 01-.889.903.896.896 0 01-.889-.903c0-.498.398-.902.889-.902zm4.912 0c.491 0 .889.404.889.902a.896.896 0 01-.889.903.896.896 0 01-.889-.903c0-.498.398-.902.889-.902z"/></svg>`}];return(t,c)=>{let l=u(`NSpin`);return i(),n(`section`,z,[(i(),n(y,null,_(K,t=>e(R,{key:t.key,name:t.name,icon:t.icon,config:g(a)[t.key],credentials:E(t.key)},{default:o(()=>[t.key===`telegram`?(i(),n(y,{key:0},[e(N,{label:g(p)(`platform.botToken`),hint:g(p)(`platform.botTokenHint`)},{default:o(()=>[e(g(C),{value:E(`telegram`).token||``,clearable:``,size:`small`,class:`input-lg`,placeholder:`123456:ABC-DEF...`,"onUpdate:value":c[0]||=e=>w(`telegram`,{token:e})},null,8,[`value`])]),_:1},8,[`label`,`hint`]),e(N,{label:g(p)(`platform.requireMention`),hint:g(p)(`platform.requireMentionGroup`)},{default:o(()=>[e(g(D),{value:g(a).telegram.require_mention,"onUpdate:value":c[1]||=e=>h(`telegram`,{require_mention:e})},null,8,[`value`])]),_:1},8,[`label`,`hint`]),e(N,{label:g(p)(`platform.reactions`),hint:g(p)(`platform.reactionsHint`)},{default:o(()=>[e(g(D),{value:g(a).telegram.reactions,"onUpdate:value":c[2]||=e=>h(`telegram`,{reactions:e})},null,8,[`value`])]),_:1},8,[`label`,`hint`]),e(N,{label:g(p)(`platform.freeResponseChats`),hint:g(p)(`platform.freeResponseChatsHint`)},{default:o(()=>[e(g(C),{value:g(a).telegram.free_response_chats||``,size:`small`,placeholder:`chat_id1,chat_id2`,"onUpdate:value":c[3]||=e=>h(`telegram`,{free_response_chats:e})},null,8,[`value`])]),_:1},8,[`label`,`hint`]),e(N,{label:g(p)(`platform.mentionPatterns`),hint:g(p)(`platform.mentionPatternsHint`)},{default:o(()=>[e(g(C),{value:(g(a).telegram.mention_patterns||[]).join(`, `),size:`small`,placeholder:`pattern1, pattern2`,"onUpdate:value":c[4]||=e=>h(`telegram`,{mention_patterns:e?e.split(`,`).map(e=>e.trim()):[]})},null,8,[`value`])]),_:1},8,[`label`,`hint`])],64)):r(``,!0),t.key===`discord`?(i(),n(y,{key:1},[e(N,{label:g(p)(`platform.botToken`),hint:g(p)(`platform.botTokenHint`)},{default:o(()=>[e(g(C),{value:E(`discord`).token||``,clearable:``,size:`small`,class:`input-lg`,placeholder:`Bot token...`,"onUpdate:value":c[5]||=e=>w(`discord`,{token:e})},null,8,[`value`])]),_:1},8,[`label`,`hint`]),e(N,{label:g(p)(`platform.requireMention`),hint:g(p)(`platform.requireMentionChannel`)},{default:o(()=>[e(g(D),{value:g(a).discord.require_mention,"onUpdate:value":c[6]||=e=>h(`discord`,{require_mention:e})},null,8,[`value`])]),_:1},8,[`label`,`hint`]),e(N,{label:g(p)(`platform.autoThread`),hint:g(p)(`platform.autoThreadHint`)},{default:o(()=>[e(g(D),{value:g(a).discord.auto_thread,"onUpdate:value":c[7]||=e=>h(`discord`,{auto_thread:e})},null,8,[`value`])]),_:1},8,[`label`,`hint`]),e(N,{label:g(p)(`platform.reactions`),hint:g(p)(`platform.reactionsHint`)},{default:o(()=>[e(g(D),{value:g(a).discord.reactions,"onUpdate:value":c[8]||=e=>h(`discord`,{reactions:e})},null,8,[`value`])]),_:1},8,[`label`,`hint`]),e(N,{label:g(p)(`platform.freeResponseChannels`),hint:g(p)(`platform.freeResponseChannelsHint`)},{default:o(()=>[e(g(C),{value:g(a).discord.free_response_channels||``,size:`small`,placeholder:`channel_id1,channel_id2`,"onUpdate:value":c[9]||=e=>h(`discord`,{free_response_channels:e})},null,8,[`value`])]),_:1},8,[`label`,`hint`]),e(N,{label:g(p)(`platform.allowedChannels`),hint:g(p)(`platform.allowedChannelsHint`)},{default:o(()=>[e(g(C),{value:g(a).discord.allowed_channels||``,size:`small`,placeholder:`channel_id1,channel_id2`,"onUpdate:value":c[10]||=e=>h(`discord`,{allowed_channels:e})},null,8,[`value`])]),_:1},8,[`label`,`hint`]),e(N,{label:g(p)(`platform.ignoredChannels`),hint:g(p)(`platform.ignoredChannelsHint`)},{default:o(()=>[e(g(C),{value:g(a).discord.ignored_channels||``,size:`small`,placeholder:`channel_id1,channel_id2`,"onUpdate:value":c[11]||=e=>h(`discord`,{ignored_channels:e})},null,8,[`value`])]),_:1},8,[`label`,`hint`]),e(N,{label:g(p)(`platform.noThreadChannels`),hint:g(p)(`platform.noThreadChannelsHint`)},{default:o(()=>[e(g(C),{value:g(a).discord.no_thread_channels||``,size:`small`,placeholder:`channel_id1,channel_id2`,"onUpdate:value":c[12]||=e=>h(`discord`,{no_thread_channels:e})},null,8,[`value`])]),_:1},8,[`label`,`hint`])],64)):r(``,!0),t.key===`slack`?(i(),n(y,{key:2},[e(N,{label:g(p)(`platform.botToken`),hint:g(p)(`platform.botTokenHint`)},{default:o(()=>[e(g(C),{value:E(`slack`).token||``,clearable:``,size:`small`,class:`input-lg`,placeholder:`xoxb-...`,"onUpdate:value":c[13]||=e=>w(`slack`,{token:e})},null,8,[`value`])]),_:1},8,[`label`,`hint`]),e(N,{label:g(p)(`platform.requireMention`),hint:g(p)(`platform.requireMentionChannel`)},{default:o(()=>[e(g(D),{value:g(a).slack.require_mention,"onUpdate:value":c[14]||=e=>h(`slack`,{require_mention:e})},null,8,[`value`])]),_:1},8,[`label`,`hint`]),e(N,{label:g(p)(`platform.allowBots`),hint:g(p)(`platform.allowBotsHint`)},{default:o(()=>[e(g(D),{value:g(a).slack.allow_bots,"onUpdate:value":c[15]||=e=>h(`slack`,{allow_bots:e})},null,8,[`value`])]),_:1},8,[`label`,`hint`]),e(N,{label:g(p)(`platform.freeResponseChannels`),hint:g(p)(`platform.freeResponseChannelsHint`)},{default:o(()=>[e(g(C),{value:g(a).slack.free_response_channels||``,size:`small`,placeholder:`channel_id1,channel_id2`,"onUpdate:value":c[16]||=e=>h(`slack`,{free_response_channels:e})},null,8,[`value`])]),_:1},8,[`label`,`hint`])],64)):r(``,!0),t.key===`whatsapp`?(i(),n(y,{key:3},[e(N,{label:g(p)(`platform.waEnabled`),hint:g(p)(`platform.waEnabledHint`)},{default:o(()=>[e(g(D),{value:E(`whatsapp`).enabled,"onUpdate:value":c[17]||=e=>w(`whatsapp`,{enabled:e})},null,8,[`value`])]),_:1},8,[`label`,`hint`]),e(N,{label:g(p)(`platform.requireMention`),hint:g(p)(`platform.requireMentionGroup`)},{default:o(()=>[e(g(D),{value:g(a).whatsapp.require_mention,"onUpdate:value":c[18]||=e=>h(`whatsapp`,{require_mention:e})},null,8,[`value`])]),_:1},8,[`label`,`hint`]),e(N,{label:g(p)(`platform.freeResponseChats`),hint:g(p)(`platform.freeResponseChatsHint`)},{default:o(()=>[e(g(C),{value:g(a).whatsapp.free_response_chats||``,size:`small`,placeholder:`chat_id1,chat_id2`,"onUpdate:value":c[19]||=e=>h(`whatsapp`,{free_response_chats:e})},null,8,[`value`])]),_:1},8,[`label`,`hint`]),e(N,{label:g(p)(`platform.mentionPatterns`),hint:g(p)(`platform.mentionPatternsHint`)},{default:o(()=>[e(g(C),{value:(g(a).whatsapp.mention_patterns||[]).join(`, `),size:`small`,placeholder:`pattern1, pattern2`,"onUpdate:value":c[20]||=e=>h(`whatsapp`,{mention_patterns:e?e.split(`,`).map(e=>e.trim()):[]})},null,8,[`value`])]),_:1},8,[`label`,`hint`])],64)):r(``,!0),t.key===`matrix`?(i(),n(y,{key:4},[e(N,{label:g(p)(`platform.accessToken`),hint:g(p)(`platform.accessTokenHint`)},{default:o(()=>[e(g(C),{value:E(`matrix`).token||``,clearable:``,size:`small`,class:`input-lg`,placeholder:`syt_...`,"onUpdate:value":c[21]||=e=>w(`matrix`,{token:e})},null,8,[`value`])]),_:1},8,[`label`,`hint`]),e(N,{label:g(p)(`platform.homeserver`),hint:g(p)(`platform.homeserverHint`)},{default:o(()=>[e(g(C),{value:E(`matrix`).extra?.homeserver||``,clearable:``,size:`small`,class:`input-lg`,placeholder:`https://matrix.org`,"onUpdate:value":c[22]||=e=>w(`matrix`,{extra:{...E(`matrix`).extra,homeserver:e}})},null,8,[`value`])]),_:1},8,[`label`,`hint`]),e(N,{label:g(p)(`platform.requireMention`),hint:g(p)(`platform.requireMentionRoom`)},{default:o(()=>[e(g(D),{value:g(a).matrix.require_mention,"onUpdate:value":c[23]||=e=>h(`matrix`,{require_mention:e})},null,8,[`value`])]),_:1},8,[`label`,`hint`]),e(N,{label:g(p)(`platform.autoThread`),hint:g(p)(`platform.autoThreadHintRoom`)},{default:o(()=>[e(g(D),{value:g(a).matrix.auto_thread,"onUpdate:value":c[24]||=e=>h(`matrix`,{auto_thread:e})},null,8,[`value`])]),_:1},8,[`label`,`hint`]),e(N,{label:g(p)(`platform.dmMentionThreads`),hint:g(p)(`platform.dmMentionThreadsHint`)},{default:o(()=>[e(g(D),{value:g(a).matrix.dm_mention_threads,"onUpdate:value":c[25]||=e=>h(`matrix`,{dm_mention_threads:e})},null,8,[`value`])]),_:1},8,[`label`,`hint`]),e(N,{label:g(p)(`platform.freeResponseRooms`),hint:g(p)(`platform.freeResponseRoomsHint`)},{default:o(()=>[e(g(C),{value:g(a).matrix.free_response_rooms||``,size:`small`,placeholder:`room_id1,room_id2`,"onUpdate:value":c[26]||=e=>h(`matrix`,{free_response_rooms:e})},null,8,[`value`])]),_:1},8,[`label`,`hint`])],64)):r(``,!0),t.key===`feishu`?(i(),n(y,{key:5},[e(N,{label:g(p)(`platform.appId`),hint:g(p)(`platform.appIdHint`)},{default:o(()=>[e(g(C),{value:E(`feishu`).extra?.app_id||``,clearable:``,size:`small`,class:`input-lg`,placeholder:`cli_...`,"onUpdate:value":c[27]||=e=>w(`feishu`,{extra:{...E(`feishu`).extra,app_id:e}})},null,8,[`value`])]),_:1},8,[`label`,`hint`]),e(N,{label:g(p)(`platform.appSecret`),hint:g(p)(`platform.appSecretHint`)},{default:o(()=>[e(g(C),{value:E(`feishu`).extra?.app_secret||``,clearable:``,size:`small`,class:`input-lg`,placeholder:`App Secret`,"onUpdate:value":c[28]||=e=>w(`feishu`,{extra:{...E(`feishu`).extra,app_secret:e}})},null,8,[`value`])]),_:1},8,[`label`,`hint`]),e(N,{label:g(p)(`platform.requireMention`),hint:g(p)(`platform.requireMentionGroup`)},{default:o(()=>[e(g(D),{value:g(a).feishu.require_mention,"onUpdate:value":c[29]||=e=>h(`feishu`,{require_mention:e})},null,8,[`value`])]),_:1},8,[`label`,`hint`]),e(N,{label:g(p)(`platform.freeResponseChats`),hint:g(p)(`platform.freeResponseChatsHint`)},{default:o(()=>[e(g(C),{value:g(a).feishu.free_response_chats||``,size:`small`,placeholder:`chat_id1,chat_id2`,"onUpdate:value":c[30]||=e=>h(`feishu`,{free_response_chats:e})},null,8,[`value`])]),_:1},8,[`label`,`hint`])],64)):r(``,!0),t.key===`dingtalk`?(i(),n(y,{key:6},[e(N,{label:g(p)(`platform.clientId`),hint:g(p)(`platform.clientIdHint`)},{default:o(()=>[e(g(C),{value:E(`dingtalk`).extra?.client_id||``,clearable:``,size:`small`,class:`input-lg`,placeholder:`Client ID`,"onUpdate:value":c[31]||=e=>w(`dingtalk`,{extra:{...E(`dingtalk`).extra,client_id:e}})},null,8,[`value`])]),_:1},8,[`label`,`hint`]),e(N,{label:g(p)(`platform.clientSecret`),hint:g(p)(`platform.clientSecretHint`)},{default:o(()=>[e(g(C),{value:E(`dingtalk`).extra?.client_secret||``,clearable:``,size:`small`,class:`input-lg`,placeholder:`Client Secret`,"onUpdate:value":c[32]||=e=>w(`dingtalk`,{extra:{...E(`dingtalk`).extra,client_secret:e}})},null,8,[`value`])]),_:1},8,[`label`,`hint`]),e(N,{label:g(p)(`platform.requireMention`),hint:g(p)(`platform.requireMentionGroup`)},{default:o(()=>[e(g(D),{value:g(a).dingtalk.require_mention,"onUpdate:value":c[33]||=e=>h(`dingtalk`,{require_mention:e})},null,8,[`value`])]),_:1},8,[`label`,`hint`]),e(N,{label:g(p)(`platform.freeResponseChats`),hint:g(p)(`platform.freeResponseChatsHint`)},{default:o(()=>[e(g(C),{value:g(a).dingtalk.free_response_chats||``,size:`small`,placeholder:`chat_id1,chat_id2`,"onUpdate:value":c[34]||=e=>h(`dingtalk`,{free_response_chats:e})},null,8,[`value`])]),_:1},8,[`label`,`hint`])],64)):r(``,!0),t.key===`weixin`?(i(),n(y,{key:7},[v(`div`,B,[I.value===`idle`||I.value===`error`||I.value===`expired`||I.value===`confirmed`?(i(),s(g(S),{key:0,type:`primary`,size:`small`,onClick:U},{default:o(()=>[m(f(I.value===`confirmed`?g(p)(`platform.qrRelogin`):g(p)(`platform.qrLogin`)),1)]),_:1})):r(``,!0),I.value===`loading`?(i(),n(`div`,V,[e(l,{size:`small`}),v(`span`,null,f(g(p)(`platform.qrFetching`)),1)])):r(``,!0),I.value===`waiting`||I.value===`scaned`?(i(),n(`div`,H,f(I.value===`scaned`?g(p)(`platform.qrScanedHint`):g(p)(`platform.qrScanHint`)),1)):r(``,!0)]),e(N,{label:g(p)(`platform.weixinToken`),hint:g(p)(`platform.weixinTokenHint`)},{default:o(()=>[e(g(C),{value:E(`weixin`).token||``,clearable:``,size:`small`,class:`input-lg`,placeholder:`Token`,"onUpdate:value":c[35]||=e=>w(`weixin`,{token:e})},null,8,[`value`])]),_:1},8,[`label`,`hint`]),e(N,{label:g(p)(`platform.accountId`),hint:g(p)(`platform.accountIdHint`)},{default:o(()=>[e(g(C),{value:E(`weixin`).extra?.account_id||``,clearable:``,size:`small`,class:`input-lg`,placeholder:`Account ID`,"onUpdate:value":c[36]||=e=>w(`weixin`,{extra:{...E(`weixin`).extra,account_id:e}})},null,8,[`value`])]),_:1},8,[`label`,`hint`])],64)):r(``,!0),t.key===`wecom`?(i(),n(y,{key:8},[e(N,{label:g(p)(`platform.botId`),hint:g(p)(`platform.botIdHint`)},{default:o(()=>[e(g(C),{value:E(`wecom`).extra?.bot_id||``,clearable:``,size:`small`,class:`input-lg`,placeholder:`Bot ID`,"onUpdate:value":c[37]||=e=>w(`wecom`,{extra:{...E(`wecom`).extra,bot_id:e}})},null,8,[`value`])]),_:1},8,[`label`,`hint`]),e(N,{label:g(p)(`platform.appSecret`),hint:g(p)(`platform.wecomSecretHint`)},{default:o(()=>[e(g(C),{value:E(`wecom`).extra?.secret||``,clearable:``,size:`small`,class:`input-lg`,placeholder:`Secret`,"onUpdate:value":c[38]||=e=>w(`wecom`,{extra:{...E(`wecom`).extra,secret:e}})},null,8,[`value`])]),_:1},8,[`label`,`hint`])],64)):r(``,!0)]),_:2},1032,[`name`,`icon`,`config`,`credentials`])),64))])}}}),[[`__scopeId`,`data-v-9f4c95ee`]]),W={class:`channels-view`},G={class:`page-header`},K={class:`header-title`},q={class:`channels-content`},J=x(p({__name:`ChannelsView`,setup(t){let r=A(),{t:a}=b();return c(()=>{r.fetchSettings()}),(t,s)=>(i(),n(`div`,W,[v(`header`,G,[v(`h2`,K,f(g(a)(`sidebar.channels`)),1)]),v(`div`,q,[e(g(E),{show:g(r).loading||g(r).saving,size:`large`,description:g(a)(`common.loading`)},{default:o(()=>[e(U)]),_:1},8,[`show`,`description`])])]))}}),[[`__scopeId`,`data-v-099b0c1b`]]);export{J as default};
|