@bulolo/hermes-link 0.3.4 → 0.3.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 CHANGED
@@ -2,99 +2,99 @@
2
2
 
3
3
  # hermes-link
4
4
 
5
- **Hermes Agent 本地接入层**
5
+ **Local access layer for Hermes Agent**
6
6
 
7
- [Hermes Agent](https://github.com/nousresearch/hermes-agent) 提供完整的客户端 API、多设备鉴权与对话管理,支持局域网 / 公网直连。
7
+ Provides full client API, multi-device auth and conversation management for [Hermes Agent](https://github.com/nousresearch/hermes-agent), with LAN and internet connectivity.
8
8
 
9
9
  [![npm](https://img.shields.io/npm/v/@bulolo/hermes-link?color=cb3837&logo=npm)](https://www.npmjs.com/package/@bulolo/hermes-link)
10
10
  [![Node](https://img.shields.io/badge/Node.js-%3E%3D20-339933?logo=node.js&logoColor=white)](https://nodejs.org/)
11
11
  [![License](https://img.shields.io/badge/License-MIT-blue)](#)
12
12
  [![Platform](https://img.shields.io/badge/Platform-macOS%20%7C%20Linux%20%7C%20Windows-lightgrey)](#)
13
13
 
14
- 简体中文 | [English](./README.en.md)
14
+ [中文](./README.zh-CN.md) | **English**
15
15
 
16
- [npm ](https://www.npmjs.com/package/@bulolo/hermes-link)
16
+ [npm package](https://www.npmjs.com/package/@bulolo/hermes-link)
17
17
 
18
18
  <p>
19
19
  <a href="https://github.com/bulolo/HermesLink">
20
- <img src="https://img.shields.io/badge/⭐_Star-项目-yellow?style=for-the-badge&logo=github" alt="Star 项目"/>
20
+ <img src="https://img.shields.io/badge/⭐_Star-Project-yellow?style=for-the-badge&logo=github" alt="Star Project"/>
21
21
  </a>
22
22
  </p>
23
23
 
24
- **如果这个项目对你有帮助,请点击右上角 ⭐ Star 支持一下,这是对开发者最大的鼓励!**
24
+ **If this project helps you, please ⭐ Star it — it means a lot to the developer!**
25
25
 
26
26
  </div>
27
27
 
28
28
  ---
29
29
 
30
- ## 概述
30
+ ## Overview
31
31
 
32
- Hermes Link 是一个运行在本机的后台 HTTP 服务,默认监听 `http://0.0.0.0:18642`。客户端(App / 浏览器)通过公网或局域网直接访问,对话、文件、指令均在本地处理,数据不经过外部服务器。
32
+ Hermes Link is a background HTTP service running on your local machine, listening on `http://0.0.0.0:18642` by default. Clients (App / browser) connect directly over LAN or the internet — all conversations, files and commands are processed locally, with no data leaving your machine.
33
33
 
34
- 所有 API 请求分为两类:
34
+ All API requests fall into two categories:
35
35
 
36
- - **无需鉴权**:`/pair`、`/api/v1/bootstrap`
37
- - **需要 Bearer Token**:其余接口均需 `Authorization: Bearer hlat_xxx`,通过配对流程获取
36
+ - **No auth required**: `/pair`, `/api/v1/bootstrap`
37
+ - **Bearer Token required**: all other endpoints require `Authorization: Bearer hlat_xxx`, obtained through the pairing flow
38
38
 
39
- ## 为什么需要 HermesLink
39
+ ## Why HermesLink?
40
40
 
41
- Hermes Agent 内置了一个 API Server(端口 8642),但它只有 **12 个接口**:
41
+ Hermes Agent ships with a built-in API Server (port 8642), but it only exposes **12 endpoints**:
42
42
 
43
- | 功能 | Hermes API Server `:8642` | HermesLink `:18642` |
44
- |------|:---:|:---:|
45
- | 接口数量 | 12 | **97** |
46
- | Agent 执行 / 事件流 | ✓ | ✓(代理转发) |
47
- | 模型列表 / 定时任务 | ✓ | ✓(代理转发) |
48
- | 认证 | 单一共享 Key | 设备独立 Token,可单独吊销 |
49
- | 设备配对 | — | ✓ 二维码 / 多设备管理 |
50
- | 对话存储 | — | ✓ 本地历史 + 附件 |
51
- | Profile & Memory 管理 | — | ✓ Profile、记忆、权限、工具开关 |
52
- | 使用统计 | — | ✓ Token 用量按日期 / 模型 / Profile |
53
- | 工具调用审批 | — | ✓ Approve / deny 流程 |
54
- | 更新管理 / 开机自启 | — | ✓ |
43
+ | Feature | Hermes API Server `:8642` | HermesLink `:18642` |
44
+ |---------|:---:|:---:|
45
+ | Endpoint count | 12 | **97** |
46
+ | Agent execution / event stream | ✓ | (proxied) |
47
+ | Model list / Cron jobs | ✓ | (proxied) |
48
+ | Authentication | Single shared key | Per-device token, individually revocable |
49
+ | Device pairing | — | ✓ QR code / multi-device management |
50
+ | Conversation storage | — | ✓ Local history + attachments |
51
+ | Profile & Memory management | — | ✓ Multi-profile, memory, permissions, tool switches |
52
+ | Usage statistics | — | ✓ Token usage by date / model / profile |
53
+ | Tool call approval | — | ✓ Approve / deny flow |
54
+ | Update management / autostart | — | ✓ |
55
55
 
56
- ### 如何选择
56
+ ### When to use which
57
57
 
58
- - **只需本机脚本 / 受信任内部服务直连**直接用 Hermes API Server8642
59
- - **开发移动 App 或多设备接入**需要 HermesLink(18642
60
- - **需要对话历史 / Profile / 统计等完整功能**需要 HermesLink(18642
58
+ - **Local scripts / trusted internal services calling Hermes directly** use Hermes API Server (8642)
59
+ - **Building a mobile app or multi-device access** HermesLink (18642) required
60
+ - **Need conversation history / Profile management / statistics**HermesLink (18642) required
61
61
 
62
- ## 工作原理
62
+ ## How It Works
63
63
 
64
64
  ```
65
- 客户端(浏览器 / App
65
+ Client (browser / App)
66
66
 
67
- └──→ hermeslink (本机, 端口 18642)
67
+ └──→ hermeslink (local machine, port 18642)
68
68
 
69
- ├── 鉴权 / 设备管理 / 对话存储 / Profile & Memory ← HermesLink 自身处理(~87 个接口)
69
+ ├── auth / device management / conversation storage / Profile & Memory handled by HermesLink (~87 endpoints)
70
70
 
71
- └──→ Hermes Agent API Server (127.0.0.1:8642) runs / models / cron jobs(~10 个接口)
71
+ └──→ Hermes Agent API Server (127.0.0.1:8642) only runs / models / cron jobs (~10 endpoints)
72
72
  ```
73
73
 
74
- 绝大多数功能由 HermesLink 独立完成,不依赖 API ServerAPI Server 未运行时,认证、配对、对话查询、Profile 管理等接口仍可正常使用,仅 Agent 执行、模型列表、定时任务不可用。所有数据均存储在本机,不经过外部服务器。
74
+ The vast majority of functionality is handled by HermesLink independently, without relying on the API Server. If the API Server is not running, auth, pairing, conversation queries, and Profile management all continue to work — only Agent execution, model listing, and cron jobs become unavailable. All data is stored locally.
75
75
 
76
- ## 环境要求
76
+ ## Requirements
77
77
 
78
78
  ### 1. Node.js >= 20.0.0
79
79
 
80
80
  ```bash
81
- node --version # 需要 >= v20.0.0
81
+ node --version # must be >= v20.0.0
82
82
  ```
83
83
 
84
- 如未安装,推荐通过 [nvm](https://github.com/nvm-sh/nvm) 安装:
84
+ If not installed, use [nvm](https://github.com/nvm-sh/nvm):
85
85
 
86
86
  ```bash
87
87
  nvm install 20
88
88
  nvm use 20
89
89
  ```
90
90
 
91
- ### 2. 启动 Hermes Agent API Server
91
+ ### 2. Start the Hermes Agent API Server
92
92
 
93
- Hermes Link 通过 `127.0.0.1:8642` 与本机的 **Hermes Agent API Server** 通信。
93
+ HermesLink communicates with the **Hermes Agent API Server** at `127.0.0.1:8642`.
94
94
 
95
- > 如果 Hermes Agent API Server 未运行,对话、Profiles 等功能将无法使用,但认证、配对、设备管理、日志等基础接口仍可正常工作。
95
+ > If the API Server is not running, conversation and Profile features will be unavailable, but auth, pairing, device management, and logs still work fine.
96
96
 
97
- `~/.hermes/.env` 中添加以下配置以启用 API Server
97
+ Add the following to `~/.hermes/.env` to enable the API Server:
98
98
 
99
99
  ```bash
100
100
  API_SERVER_ENABLED=true
@@ -104,71 +104,68 @@ API_SERVER_CORS_ORIGINS=*
104
104
  GATEWAY_ALLOW_ALL_USERS=true
105
105
  ```
106
106
 
107
- | 配置项 | 说明 |
108
- |--------|------|
109
- | `API_SERVER_ENABLED` | 设为 `true` 开启 API Server |
110
- | `API_SERVER_KEY` | 认证密钥,替换为强随机字符串 `openssl rand -hex 32` |
111
- | `API_SERVER_HOST` | 监听地址,`0.0.0.0` 允许本机所有网卡 |
112
- | `API_SERVER_CORS_ORIGINS` | CORS 来源,本地调试可设为 `*` |
107
+ | Option | Description |
108
+ |--------|-------------|
109
+ | `API_SERVER_ENABLED` | Set to `true` to enable the API Server |
110
+ | `API_SERVER_KEY` | Auth key — replace with a strong random string: `openssl rand -hex 32` |
111
+ | `API_SERVER_HOST` | Listen address — `0.0.0.0` allows all network interfaces |
112
+ | `API_SERVER_CORS_ORIGINS` | CORS origins — can be `*` for local development |
113
113
 
114
- 配置完成后启动:
114
+ Then restart:
115
115
 
116
116
  ```bash
117
- hermes gateway stop
118
- hermes gateway start
119
- 或者
120
117
  hermes gateway restart
121
118
  ```
122
119
 
123
- 验证是否就绪:
120
+ Verify it's running:
124
121
 
125
122
  ```bash
126
123
  curl -s http://127.0.0.1:8642/v1/health
127
124
  ```
128
125
 
129
- 如缺失或版本过旧:
126
+ If missing or outdated:
130
127
 
131
128
  ```bash
132
129
  hermes update
133
130
  ```
134
131
 
135
- ## 安装
132
+ ## Installation
136
133
 
137
- npm 包地址:[https://www.npmjs.com/package/@bulolo/hermes-link](https://www.npmjs.com/package/@bulolo/hermes-link)
134
+ npm package: [https://www.npmjs.com/package/@bulolo/hermes-link](https://www.npmjs.com/package/@bulolo/hermes-link)
138
135
 
139
136
  ```bash
140
137
  npm install -g @bulolo/hermes-link
141
138
  ```
142
139
 
143
- > 安装后如果终端找不到 `hermeslink` 命令,说明 npm 全局 bin 目录不在 PATH 中,运行以下命令添加:
140
+ > If the `hermeslink` command is not found after installation, the npm global bin directory is not in your PATH. Fix it with:
144
141
  >
145
142
  > ```bash
146
143
  > export PATH="$(npm prefix -g)/bin:$PATH"
147
144
  > ```
148
145
  >
149
- > 也可以直接用完整路径调用:`$(npm prefix -g)/bin/hermeslink`
146
+ > Or call it directly: `$(npm prefix -g)/bin/hermeslink`
150
147
 
151
- ## 快速开始
148
+ ## Quick Start
152
149
 
153
150
  ```bash
154
- # 1. 启动后台服务
151
+ # 1. Start the background daemon
155
152
  hermeslink start
156
153
 
157
- # 2. 生成配对页面(浏览器打开完成配对)
154
+ # 2. Open the pairing page in a browser
158
155
  hermeslink pair
159
156
 
160
- # 3. 查看状态
157
+ # 3. Check status
161
158
  hermeslink status
162
159
 
163
- # 4. 查看日志
160
+ # 4. View logs
164
161
  hermeslink logs
165
162
  ```
166
163
 
167
- ## 配对流程
164
+ ## Pairing
168
165
 
169
- ### 方式一:App 扫码配对(标准流程)
166
+ ### Method 1: App QR code scan (standard flow)
170
167
 
171
- 二维码内容是一段 JSON,App 解析后获取连接所需的全部信息:
168
+ The QR code contains a JSON payload the app parses to get everything it needs:
172
169
 
173
170
  ```json
174
171
  {
@@ -182,31 +179,31 @@ hermeslink logs
182
179
  }
183
180
  ```
184
181
 
185
- App 拿到上述信息后:
182
+ Once the app has this:
186
183
 
187
184
  ```
188
- 1. preferred_urls[0] 作为服务地址(优先局域网 IP
185
+ 1. Use preferred_urls[0] as the base URL (LAN IP preferred)
189
186
  2. POST {baseUrl}/api/v1/pairing/claim
190
- Body: { "session_id": "...", "claim_token": "<code 字段的值>" }
191
- 3. 响应中获得 access_token refresh_token
192
- 4. 后续 API 请求携带 Authorization: Bearer <access_token>
187
+ Body: { "session_id": "...", "claim_token": "<value of the code field>" }
188
+ 3. Response contains access_token and refresh_token
189
+ 4. Include Authorization: Bearer <access_token> on all subsequent requests
193
190
  ```
194
191
 
195
- ### 方式二:浏览器配对
192
+ ### Method 2: Browser pairing
196
193
 
197
194
  ```bash
198
195
  hermeslink pair
199
- # 在浏览器打开终端输出的 Pairing page URL
200
- # 点击"在此设备上配对",页面直接显示 access_token refresh_token
196
+ # Open the Pairing page URL printed in the terminal
197
+ # Click "Pair on this device" — the page shows your access_token and refresh_token
201
198
  ```
202
199
 
203
- ### 方式三:命令行脚本(适合自动化)
200
+ ### Method 3: CLI / script (automation-friendly)
204
201
 
205
202
  ```bash
206
- # 1. 获取 connect_token
203
+ # 1. Get the connect_token
207
204
  CONNECT_TOKEN=$(hermeslink pair 2>&1 | grep "Connect token:" | awk '{print $NF}')
208
205
 
209
- # 2. connect_token access_token
206
+ # 2. Exchange it for an access_token
210
207
  curl -s -X POST http://localhost:18642/api/v1/auth/device-session \
211
208
  -H "Authorization: Bearer $CONNECT_TOKEN" \
212
209
  -H "Content-Type: application/json" \
@@ -215,348 +212,242 @@ curl -s -X POST http://localhost:18642/api/v1/auth/device-session \
215
212
 
216
213
  ---
217
214
 
218
- > **Token 有效期**:access_token 2 小时,refresh_token 90 天。access_token 过期后用 refresh_token 换新,无需重新配对。
215
+ > **Token expiry**: access_token lasts 2 hours, refresh_token lasts 90 days. When the access_token expires, use the refresh_token to get a new one — no need to re-pair.
219
216
 
220
- ## 命令一览
217
+ ## Commands
221
218
 
222
- | 命令 | 说明 |
223
- |------|------|
224
- | `hermeslink start` | 启动后台守护进程 |
225
- | `hermeslink stop` | 停止守护进程 |
226
- | `hermeslink restart` | 重启守护进程 |
227
- | `hermeslink status` | 查看运行状态 |
228
- | `hermeslink pair` | 生成配对 URL 和二维码 |
229
- | `hermeslink config get` | 查看当前配置 |
230
- | `hermeslink config set <key> <value>` | 修改配置 |
231
- | `hermeslink autostart on` | 开机自启(同 `enable`)|
232
- | `hermeslink autostart off` | 关闭自启(同 `disable`)|
233
- | `hermeslink logs` | 查看 Link 日志 |
234
- | `hermeslink logs --gateway` | 查看 Hermes 网关日志 |
235
- | `hermeslink logs -n 100` | 查看最近 100 条日志 |
236
- | `hermeslink version` | 查看版本号 |
219
+ | Command | Description |
220
+ |---------|-------------|
221
+ | `hermeslink start` | Start the background daemon |
222
+ | `hermeslink stop` | Stop the daemon |
223
+ | `hermeslink restart` | Restart the daemon |
224
+ | `hermeslink status` | Show running status |
225
+ | `hermeslink pair` | Generate pairing URL and QR code |
226
+ | `hermeslink config get` | Show current config |
227
+ | `hermeslink config set <key> <value>` | Update a config value |
228
+ | `hermeslink autostart on` | Enable autostart on login (alias: `enable`) |
229
+ | `hermeslink autostart off` | Disable autostart (alias: `disable`) |
230
+ | `hermeslink logs` | View Link logs |
231
+ | `hermeslink logs --gateway` | View Hermes gateway logs |
232
+ | `hermeslink logs -n 100` | View last 100 log lines |
233
+ | `hermeslink version` | Show version |
237
234
 
238
- ## 配置
235
+ ## Configuration
239
236
 
240
237
  ```bash
241
- hermeslink config set port 18642 # 修改监听端口(默认 18642
242
- hermeslink config set lan-host 192.168.1.10 # 手动指定局域网 IP(默认自动检测)
243
- hermeslink config set language zh-CN # 语言:auto / en / zh-CN
244
- hermeslink config set log-level debug # 日志级别:debug / info / warn / error
238
+ hermeslink config set port 18642 # Change listen port (default: 18642)
239
+ hermeslink config set lan-host 192.168.1.10 # Set LAN IP manually (default: auto-detect)
240
+ hermeslink config set language en # Language: auto / en / zh-CN
241
+ hermeslink config set log-level debug # Log level: debug / info / warn / error
245
242
  ```
246
243
 
247
- 配置文件位于 `~/.hermeslink/config.json`。
244
+ Config file is at `~/.hermeslink/config.json`.
248
245
 
249
- ## API 参考
246
+ ## API Reference
250
247
 
251
- 服务默认监听 `http://0.0.0.0:18642`。所有需要鉴权的接口均使用 Bearer Token(`hlat_` 前缀)。
248
+ Service listens on `http://0.0.0.0:18642` by default. All authenticated endpoints use a Bearer Token with the `hlat_` prefix.
252
249
 
253
- ### Token 说明
250
+ ### Token Types
254
251
 
255
- | Token | 前缀 | 有效期 | 用途 |
256
- |-------|------|--------|------|
257
- | Connect Token | 无前缀(base64url)| 5 分钟,一次性 | 兑换 access_token |
258
- | Access Token | `hlat_` | 2 小时 | 所有 API 请求 |
259
- | Refresh Token | `hlrt_` | 90 | 刷新 access_token |
252
+ | Token | Prefix | Expiry | Purpose |
253
+ |-------|--------|--------|---------|
254
+ | Connect Token | none (base64url) | 5 min, one-time | Exchange for access_token |
255
+ | Access Token | `hlat_` | 15 min | All API requests |
256
+ | Refresh Token | `hlrt_` | 90 days | Refresh access_token |
260
257
 
261
- ### 无需鉴权
258
+ ### No Auth Required
262
259
 
263
- | 方法 | 路径 | 说明 |
264
- |------|------|------|
265
- | GET | `/pair` | 配对网页(浏览器打开) |
266
- | GET | `/api/v1/bootstrap` | 服务基础信息,含 link_id、版本、能力 |
260
+ | Method | Path | Description |
261
+ |--------|------|-------------|
262
+ | GET | `/pair` | Pairing web page (open in browser) |
263
+ | GET | `/api/v1/bootstrap` | Service info: link_id, version, capabilities |
267
264
 
268
- ### 认证 / 设备
265
+ ### Auth / Devices
269
266
 
270
- 所有以下接口需要 Header:`Authorization: Bearer hlat_xxx`
267
+ All endpoints below require `Authorization: Bearer hlat_xxx`
271
268
 
272
- | 方法 | 路径 | 说明 |
273
- |------|------|------|
274
- | GET | `/api/v1/auth/me` | 当前 Token 信息及设备信息 |
275
- | POST | `/api/v1/auth/device-session` | connect_token 换取 access/refresh token |
276
- | POST | `/api/v1/auth/refresh` | refresh_token 换新 access_token |
277
- | POST | `/api/v1/auth/logout` | 撤销 refresh_token |
269
+ | Method | Path | Description |
270
+ |--------|------|-------------|
271
+ | GET | `/api/v1/auth/me` | Current token info and device details |
272
+ | POST | `/api/v1/auth/device-session` | Exchange connect_token for access/refresh tokens |
273
+ | POST | `/api/v1/auth/refresh` | Refresh access_token using refresh_token |
274
+ | POST | `/api/v1/auth/logout` | Revoke refresh_token |
278
275
 
279
- **POST `/api/v1/auth/device-session`** Authorization 头需放 **connect_token**(不是 hlat_),Body
276
+ **POST `/api/v1/auth/device-session`** Authorization header takes the **connect_token** (not hlat_). Body:
280
277
 
281
278
  ```json
282
279
  {
283
- "device_label": "我的设备",
280
+ "device_label": "My Device",
284
281
  "device_platform": "ios|android|web|cli",
285
- "device_model": "可选,设备型号"
282
+ "device_model": "optional device model"
286
283
  }
287
284
  ```
288
285
 
289
- 响应:
286
+ Response:
290
287
 
291
288
  ```json
292
289
  {
293
290
  "ok": true,
294
- "device": { "device_id": "dev_xxx", "label": "我的设备", "platform": "ios" },
291
+ "device": { "device_id": "dev_xxx", "label": "My Device", "platform": "ios" },
295
292
  "access_token": { "token": "hlat_xxx", "expires_at": "2026-05-08T13:00:00Z" },
296
293
  "refresh_token": { "token": "hlrt_xxx", "expires_at": "2026-08-06T12:00:00Z" }
297
294
  }
298
295
  ```
299
296
 
300
- **POST `/api/v1/auth/refresh`** Body
297
+ **POST `/api/v1/auth/refresh`** Body:
301
298
 
302
299
  ```json
303
300
  { "refresh_token": "hlrt_xxx" }
304
301
  ```
305
302
 
306
- ### 配对
303
+ ### Pairing
307
304
 
308
- | 方法 | 路径 | 说明 |
309
- |------|------|------|
310
- | GET | `/api/v1/pairing/session` | 查询配对会话状态(含 claimed 字段) |
311
- | POST | `/api/v1/pairing/claim` | App 端用来完成配对 |
305
+ | Method | Path | Description |
306
+ |--------|------|-------------|
307
+ | GET | `/api/v1/pairing/session` | Query pairing session status (includes `claimed` field) |
308
+ | POST | `/api/v1/pairing/claim` | Complete pairing from the app side |
312
309
 
313
- **GET `/api/v1/pairing/session`** 查询参数:`?session_id=ps_xxx`
310
+ **GET `/api/v1/pairing/session`** query: `?session_id=ps_xxx`
314
311
 
315
- **POST `/api/v1/pairing/claim`** Body
312
+ **POST `/api/v1/pairing/claim`** Body:
316
313
 
317
314
  ```json
318
315
  {
319
316
  "session_id": "ps_xxx",
320
- "claim_token": "connect_token",
317
+ "claim_token": "<connect_token value>",
321
318
  "device_label": "My App",
322
319
  "device_platform": "ios"
323
320
  }
324
321
  ```
325
322
 
326
- ### 系统状态
327
-
328
- | 方法 | 路径 | 说明 |
329
- |------|------|------|
330
- | GET | `/api/v1/status` | 服务整体状态(版本、设备数、profiles 数量等) |
331
- | GET | `/api/v1/logs` | 最近日志(`?source=link\|gateway&limit=50`) |
332
-
333
- ### 设备列表
334
-
335
- | 方法 | 路径 | 说明 |
336
- |------|------|------|
337
- | GET | `/api/v1/devices` | 列出所有已配对设备 |
338
- | PATCH | `/api/v1/devices/:deviceId` | 重命名设备(`{"label":"新名字"}`) |
339
- | DELETE | `/api/v1/devices/:deviceId` | 撤销设备(吊销 token) |
340
- | DELETE | `/api/v1/devices/:deviceId/app-listing` | 从列表中隐藏已撤销设备 |
341
-
342
- ### 对话(Conversations
343
-
344
- #### 活跃对话
345
-
346
- | 方法 | 路径 | 说明 |
347
- |------|------|------|
348
- | GET | `/api/v1/conversations` | 列出活跃对话(`?limit=20&cursor=xxx`) |
349
- | GET | `/api/v1/conversations/search` | 搜索活跃对话(`?q=关键词`) |
350
- | POST | `/api/v1/conversations` | 新建对话 |
351
- | DELETE | `/api/v1/conversations` | 批量删除对话(`{"conversation_ids":["conv_xxx"]}`) |
352
- | DELETE | `/api/v1/conversations/:id` | 删除单个对话 |
353
- | GET | `/api/v1/conversations/:id/messages` | 获取对话消息列表(含 `runtime` 上下文信息) |
354
- | POST | `/api/v1/conversations/:id/messages` | 发送消息 |
355
- | GET | `/api/v1/conversations/:id/events` | SSE 实时事件流 |
356
- | GET | `/api/v1/conversations/events` | 所有对话事件流(SSE) |
357
- | PATCH | `/api/v1/conversations/:id/title` | 重命名对话(`{"title":"新标题"}`) |
358
- | PATCH | `/api/v1/conversations/:id/model` | 切换模型(`{"model_id":"xxx"}`) |
359
- | PATCH | `/api/v1/conversations/:id/profile` | 切换 profile |
360
- | POST | `/api/v1/conversations/:id/ack` | 确认已读 |
361
- | POST | `/api/v1/conversations/:id/runs/:runId/cancel` | 取消对话内的某次执行 |
362
- | POST | `/api/v1/conversations/:id/approvals/:approvalId/approve` | 审批工具调用(允许,`{"scope":"once\|session\|always"}`) |
363
- | POST | `/api/v1/conversations/:id/approvals/:approvalId/deny` | 审批工具调用(拒绝) |
364
- | POST | `/api/v1/conversations/:id/blobs` | 上传附件 |
365
- | GET | `/api/v1/conversations/:id/blobs/:blobId` | 下载附件 |
366
- | DELETE | `/api/v1/conversations/:id/blobs/:blobId` | 删除附件 |
367
-
368
- #### 归档对话
369
-
370
- | 方法 | 路径 | 说明 |
371
- |------|------|------|
372
- | GET | `/api/v1/conversations/archived` | 列出已归档对话(`?limit=20&cursor=xxx`) |
373
- | GET | `/api/v1/conversations/archived/search` | 搜索已归档对话(`?q=关键词`) |
374
- | POST | `/api/v1/conversations/:id/archive` | 归档对话(发送新消息时自动恢复为活跃) |
375
- | POST | `/api/v1/conversations/:id/unarchive` | 取消归档 |
376
-
377
- #### 批量清理计划
378
-
379
- | 方法 | 路径 | 说明 |
380
- |------|------|------|
381
- | POST | `/api/v1/conversations/clear-plans` | 创建批量删除计划(`{"target_status":"active\|archived"}`) |
382
- | GET | `/api/v1/conversations/clear-plans/:planId` | 查询计划状态 |
383
- | POST | `/api/v1/conversations/clear-plans/:planId/execute` | 执行计划(批量删除) |
384
-
385
- #### 批量归档计划
386
-
387
- | 方法 | 路径 | 说明 |
388
- |------|------|------|
389
- | POST | `/api/v1/conversations/archive-plans` | 创建批量归档计划(`{"exclude_conversation_ids":[]}`) |
390
- | GET | `/api/v1/conversations/archive-plans/:planId` | 查询计划状态 |
391
- | POST | `/api/v1/conversations/archive-plans/:planId/execute` | 执行计划(批量归档) |
392
-
393
- #### 响应结构说明
394
-
395
- **ConversationSummary**(对话列表每项):
396
-
397
- ```json
398
- {
399
- "id": "conv_xxx",
400
- "title": "对话标题",
401
- "created_at": "2026-05-09T00:00:00.000Z",
402
- "updated_at": "2026-05-09T00:00:00.000Z",
403
- "last_event_seq": 12,
404
- "usage": { "input_tokens": 100, "output_tokens": 200, "total_tokens": 300, "updated_at": "..." },
405
- "profile": { "uid": "prof_xxx", "name": "default", "display_name": "default", "avatar_url": null },
406
- "last_message": { "id": "msg_xxx", "role": "assistant", "content_preview": "消息摘要..." }
407
- }
408
- ```
409
-
410
- **GET `/api/v1/conversations/:id/messages`** 响应新增 `runtime` 字段:
411
-
412
- ```json
413
- {
414
- "ok": true,
415
- "messages": [...],
416
- "last_event_seq": 12,
417
- "runtime": {
418
- "profile": { "name": "default", "display_name": "default", "avatar_url": null },
419
- "model": { "id": "claude-3-5-sonnet", "provider": "anthropic", "context_window": 200000 },
420
- "context": { "input_tokens": 100, "output_tokens": 200, "total_tokens": 300, "usage_percent": 0, "source": "estimated" }
421
- },
422
- "page": { "limit": 50, "has_more_before": false, "has_more_after": false, "oldest_message_id": "...", "newest_message_id": "..." }
423
- }
424
- ```
425
-
426
- **LinkMessage**(消息对象):
427
-
428
- ```json
429
- {
430
- "id": "msg_xxx",
431
- "schema_version": 1,
432
- "conversation_id": "conv_xxx",
433
- "role": "user|assistant|tool|system",
434
- "status": "queued|streaming|completed|failed|cancelled",
435
- "created_at": "...",
436
- "updated_at": "...",
437
- "sender": { "id": "app_user", "type": "human|agent|system|tool", "display_name": "Me" },
438
- "parts": [{ "type": "text", "text": "消息内容" }],
439
- "attachments": [],
440
- "blocks": [],
441
- "agent_events": [],
442
- "approvals": []
443
- }
444
- ```
445
-
446
- **DELETE `/api/v1/conversations/:id`** 响应新增字段:
447
-
448
- ```json
449
- {
450
- "ok": true,
451
- "conversation_id": "conv_xxx",
452
- "hermes_deleted": false,
453
- "deleted_at": "2026-05-09T00:00:00.000Z"
454
- }
455
- ```
456
-
457
- ### 统计
458
-
459
- | 方法 | 路径 | 说明 |
460
- |------|------|------|
461
- | GET | `/api/v1/statistics` | 全局使用统计(`?profile=xxx&profile_uid=xxx`) |
462
- | GET | `/api/v1/statistics/usage` | Token 用量统计(`?days=7&from=2026-05-01&to=2026-05-08&model=xxx&profile=xxx`) |
463
-
464
- **GET `/api/v1/statistics`** 响应:
465
-
466
- ```json
467
- {
468
- "ok": true,
469
- "statistics": {
470
- "conversations": { "total": 10, "active": 8, "archived": 1, "deleted": 1 },
471
- "tokens": { "input_tokens": 5000, "output_tokens": 8000, "total_tokens": 13000 },
472
- "messages": { "total": 120 },
473
- "runs": { "total": 50 },
474
- "models": { "total": 0 },
475
- "profiles": { "total": 0 },
476
- "skills": { "total": 0 },
477
- "tools": { "total": 0 }
478
- }
479
- }
480
- ```
481
-
482
- ### 模型(Models)
483
-
484
- | 方法 | 路径 | 说明 |
485
- |------|------|------|
486
- | GET | `/api/v1/models` | 列出可用模型(来自 Hermes API Server,OpenAI 兼容格式) |
487
- | GET | `/api/v1/model-configs` | 列出全局模型配置 |
488
- | POST | `/api/v1/model-configs` | 新增全局模型配置 |
489
- | PATCH | `/api/v1/model-configs/defaults` | 更新默认模型配置 |
490
- | DELETE | `/api/v1/model-configs` | 删除全局模型配置 |
323
+ ### System Status
324
+
325
+ | Method | Path | Description |
326
+ |--------|------|-------------|
327
+ | GET | `/api/v1/status` | Overall service status (version, device count, profile count, etc.) |
328
+ | GET | `/api/v1/logs` | Recent logs (`?source=link\|gateway&limit=50`) |
329
+
330
+ ### Devices
331
+
332
+ | Method | Path | Description |
333
+ |--------|------|-------------|
334
+ | GET | `/api/v1/devices` | List all paired devices |
335
+ | PATCH | `/api/v1/devices/:deviceId` | Rename device (`{"label":"New Name"}`) |
336
+ | DELETE | `/api/v1/devices/:deviceId` | Revoke device (invalidates its tokens) |
337
+ | DELETE | `/api/v1/devices/:deviceId/app-listing` | Hide a revoked device from the list |
338
+
339
+ ### Conversations
340
+
341
+ | Method | Path | Description |
342
+ |--------|------|-------------|
343
+ | GET | `/api/v1/conversations` | List conversations (`?limit=20&cursor=xxx`) |
344
+ | GET | `/api/v1/conversations/search` | Search conversations (`?q=keyword`) |
345
+ | POST | `/api/v1/conversations` | Create a new conversation |
346
+ | DELETE | `/api/v1/conversations` | Bulk delete conversations |
347
+ | DELETE | `/api/v1/conversations/:id` | Delete a single conversation |
348
+ | GET | `/api/v1/conversations/:id/messages` | Get messages in a conversation |
349
+ | POST | `/api/v1/conversations/:id/messages` | Send a message |
350
+ | GET | `/api/v1/conversations/:id/events` | SSE event stream for a conversation |
351
+ | GET | `/api/v1/conversations/events` | SSE stream for all conversations |
352
+ | PATCH | `/api/v1/conversations/:id/title` | Rename conversation (`{"title":"New Title"}`) |
353
+ | PATCH | `/api/v1/conversations/:id/model` | Switch model |
354
+ | PATCH | `/api/v1/conversations/:id/profile` | Switch profile |
355
+ | POST | `/api/v1/conversations/:id/ack` | Acknowledge events read |
356
+ | POST | `/api/v1/conversations/clear-plans` | Create a bulk-clear plan |
357
+ | GET | `/api/v1/conversations/clear-plans/:planId` | Query clear plan status |
358
+ | POST | `/api/v1/conversations/clear-plans/:planId/execute` | Execute clear plan |
359
+ | POST | `/api/v1/conversations/:id/runs/:runId/cancel` | Cancel an in-progress run |
360
+ | POST | `/api/v1/conversations/:id/approvals/:approvalId/approve` | Approve a tool call |
361
+ | POST | `/api/v1/conversations/:id/approvals/:approvalId/deny` | Deny a tool call |
362
+ | POST | `/api/v1/conversations/:id/blobs` | Upload attachment |
363
+ | GET | `/api/v1/conversations/:id/blobs/:blobId` | Download attachment |
364
+ | DELETE | `/api/v1/conversations/:id/blobs/:blobId` | Delete attachment |
365
+
366
+ ### Statistics
367
+
368
+ | Method | Path | Description |
369
+ |--------|------|-------------|
370
+ | GET | `/api/v1/statistics` | Global usage stats (conversation count, message count, etc.) |
371
+ | GET | `/api/v1/statistics/usage` | Token usage (`?days=7&from=2026-05-01&to=2026-05-08&model=xxx&profile=xxx`) |
372
+
373
+ ### Models
374
+
375
+ | Method | Path | Description |
376
+ |--------|------|-------------|
377
+ | GET | `/api/v1/models` | List available models (from Hermes API Server, OpenAI-compatible format) |
378
+ | GET | `/api/v1/model-configs` | List global model configs |
379
+ | POST | `/api/v1/model-configs` | Add global model config |
380
+ | PATCH | `/api/v1/model-configs/defaults` | Update default model config |
381
+ | DELETE | `/api/v1/model-configs` | Delete global model config |
491
382
 
492
383
  ### Profiles
493
384
 
494
- | 方法 | 路径 | 说明 |
495
- |------|------|------|
496
- | GET | `/api/v1/profiles` | 列出所有 Profile 名称 |
497
- | POST | `/api/v1/profiles` | 创建新 Profile(异步,返回 202 |
498
- | PATCH | `/api/v1/profiles/:name` | 重命名(`{"name":"new-name"}`)或更新元数据 |
499
- | DELETE | `/api/v1/profiles/:name` | 删除 Profile |
500
- | GET | `/api/v1/profiles/catalog` | 完整目录(包含各 Profile capabilities、permissionsmodelConfigs)|
501
- | GET | `/api/v1/profile-creation/status` | 查询创建进度 |
502
- | GET | `/api/v1/profile-creation/events` | 创建进度 SSE |
503
- | GET | `/api/v1/profiles/:name/status` | Profile 状态(存在性、API Key 配置等) |
504
- | GET | `/api/v1/profiles/:name/statistics` | Profile 的对话统计 |
505
- | GET | `/api/v1/profiles/:name/skills` | 列出 Profile Skills(`?include_disabled=true`)|
506
- | PATCH | `/api/v1/profiles/:name/skills/:skillName` | 启用/禁用 Skill(`{"enabled":true}`) |
507
- | GET | `/api/v1/profiles/:name/memory` | 查看记忆(USER.md + MEMORY.md |
508
- | POST | `/api/v1/profiles/:name/memory/entries` | 新增记忆条目(`{"target":"memory","content":"..."}`) |
509
- | PATCH | `/api/v1/profiles/:name/memory/entries` | 替换记忆条目(`{"target":"memory","match":"旧内容","content":"新内容"}`)|
510
- | DELETE | `/api/v1/profiles/:name/memory/entries` | 删除记忆条目(`{"target":"memory","match":"匹配内容"}`)|
511
- | DELETE | `/api/v1/profiles/:name/memory` | 重置记忆(`{"target":"memory\|user\|all"}`)|
512
- | PATCH | `/api/v1/profiles/:name/memory/settings` | 更新记忆 Provider 设置 |
513
- | PATCH | `/api/v1/profiles/:name/memory/provider` | 切换记忆 Provider(`{"provider":"built-in"}`)|
514
- | GET | `/api/v1/profiles/:name/permissions` | 查看权限配置 |
515
- | PATCH | `/api/v1/profiles/:name/permissions` | 更新权限配置 |
516
- | GET | `/api/v1/profiles/:name/tool-configs/:toolKey` | 查看工具配置(toolKey:`web` / `image_gen` / `stt` / `tts` / `messaging` / `homeassistant` / `rl`)|
517
- | PATCH | `/api/v1/profiles/:name/tool-configs/:toolKey` | 更新工具配置(同上 toolKey)|
518
- | GET | `/api/v1/profiles/:name/model-configs` | 列出 Profile 的模型配置 |
519
- | POST | `/api/v1/profiles/:name/model-configs` | 新增 Profile 的模型配置 |
520
- | PATCH | `/api/v1/profiles/:name/model-configs/defaults` | 更新 Profile 默认模型 |
521
- | DELETE | `/api/v1/profiles/:name/model-configs` | 删除 Profile 的模型配置 |
522
-
523
- 记忆 `target` 字段:`"memory"`(Agent 笔记,MEMORY.md)或 `"user"`(用户信息,USER.md)。
524
-
525
- ### Cron Jobs(定时任务)
526
-
527
- | 方法 | 路径 | 说明 |
528
- |------|------|------|
529
- | GET | `/api/v1/cron-jobs` | 汇总列出所有 Profile 的定时任务 |
530
- | GET | `/api/v1/profiles/:name/cron-jobs` | 列出指定 Profile 的定时任务 |
531
- | POST | `/api/v1/profiles/:name/cron-jobs` | 创建定时任务 |
532
- | GET | `/api/v1/profiles/:name/cron-jobs/:jobId` | 查看定时任务详情 |
533
- | PATCH | `/api/v1/profiles/:name/cron-jobs/:jobId` | 更新定时任务 |
534
- | DELETE | `/api/v1/profiles/:name/cron-jobs/:jobId` | 删除定时任务 |
535
- | POST | `/api/v1/profiles/:name/cron-jobs/:jobId/pause` | 暂停定时任务 |
536
- | POST | `/api/v1/profiles/:name/cron-jobs/:jobId/resume` | 恢复定时任务 |
537
- | POST | `/api/v1/profiles/:name/cron-jobs/:jobId/run` | 立即执行定时任务 |
538
-
539
- ### Runs(执行任务)
540
-
541
- | 方法 | 路径 | 说明 |
542
- |------|------|------|
543
- | POST | `/api/v1/runs` | Hermes Agent 提交执行任务(返回 202 |
544
- | GET | `/api/v1/runs/:runId/events` | 订阅执行事件流(SSE 代理) |
545
- | POST | `/api/v1/runs/:runId/cancel` | 取消执行任务 |
546
-
547
- **POST `/api/v1/runs`** Body
385
+ | Method | Path | Description |
386
+ |--------|------|-------------|
387
+ | GET | `/api/v1/profiles` | List all profile names |
388
+ | POST | `/api/v1/profiles` | Create new profile (async, returns 202) |
389
+ | PATCH | `/api/v1/profiles/:name` | Rename (`{"name":"new-name"}`) or update metadata |
390
+ | DELETE | `/api/v1/profiles/:name` | Delete profile |
391
+ | GET | `/api/v1/profiles/catalog` | Full catalog (capabilities, permissions, modelConfigs per profile) |
392
+ | GET | `/api/v1/profile-creation/status` | Query creation progress |
393
+ | GET | `/api/v1/profile-creation/events` | Creation progress SSE stream |
394
+ | GET | `/api/v1/profiles/:name/status` | Profile status (existence, API key configuration, etc.) |
395
+ | GET | `/api/v1/profiles/:name/statistics` | Profile conversation statistics |
396
+ | GET | `/api/v1/profiles/:name/skills` | List profile skills (`?include_disabled=true`) |
397
+ | PATCH | `/api/v1/profiles/:name/skills/:skillName` | Enable/disable skill (`{"enabled":true}`) |
398
+ | GET | `/api/v1/profiles/:name/memory` | View memory (USER.md + MEMORY.md) |
399
+ | POST | `/api/v1/profiles/:name/memory/entries` | Add memory entry (`{"target":"memory","content":"..."}`) |
400
+ | PATCH | `/api/v1/profiles/:name/memory/entries` | Replace memory entry (`{"target":"memory","match":"old","content":"new"}`) |
401
+ | DELETE | `/api/v1/profiles/:name/memory/entries` | Delete memory entry (`{"target":"memory","match":"text to match"}`) |
402
+ | DELETE | `/api/v1/profiles/:name/memory` | Reset memory (`{"target":"memory\|user\|all"}`) |
403
+ | PATCH | `/api/v1/profiles/:name/memory/settings` | Update memory provider settings |
404
+ | PATCH | `/api/v1/profiles/:name/memory/provider` | Switch memory provider (`{"provider":"built-in"}`) |
405
+ | GET | `/api/v1/profiles/:name/permissions` | View permissions config |
406
+ | PATCH | `/api/v1/profiles/:name/permissions` | Update permissions config |
407
+ | GET | `/api/v1/profiles/:name/tool-configs/:toolKey` | View tool config (toolKey: `web` / `image_gen` / `stt` / `tts` / `messaging` / `homeassistant` / `rl`) |
408
+ | PATCH | `/api/v1/profiles/:name/tool-configs/:toolKey` | Update tool config |
409
+ | GET | `/api/v1/profiles/:name/model-configs` | List profile model configs |
410
+ | POST | `/api/v1/profiles/:name/model-configs` | Add profile model config |
411
+ | PATCH | `/api/v1/profiles/:name/model-configs/defaults` | Update profile default model |
412
+ | DELETE | `/api/v1/profiles/:name/model-configs` | Delete profile model config |
413
+
414
+ Memory `target` values: `"memory"` (agent notes, MEMORY.md) or `"user"` (user info, USER.md).
415
+
416
+ ### Cron Jobs
417
+
418
+ | Method | Path | Description |
419
+ |--------|------|-------------|
420
+ | GET | `/api/v1/cron-jobs` | List all cron jobs across all profiles |
421
+ | GET | `/api/v1/profiles/:name/cron-jobs` | List cron jobs for a specific profile |
422
+ | POST | `/api/v1/profiles/:name/cron-jobs` | Create cron job |
423
+ | GET | `/api/v1/profiles/:name/cron-jobs/:jobId` | Get cron job details |
424
+ | PATCH | `/api/v1/profiles/:name/cron-jobs/:jobId` | Update cron job |
425
+ | DELETE | `/api/v1/profiles/:name/cron-jobs/:jobId` | Delete cron job |
426
+ | POST | `/api/v1/profiles/:name/cron-jobs/:jobId/pause` | Pause cron job |
427
+ | POST | `/api/v1/profiles/:name/cron-jobs/:jobId/resume` | Resume cron job |
428
+ | POST | `/api/v1/profiles/:name/cron-jobs/:jobId/run` | Run cron job immediately |
429
+
430
+ ### Runs
431
+
432
+ | Method | Path | Description |
433
+ |--------|------|-------------|
434
+ | POST | `/api/v1/runs` | Submit a run to Hermes Agent (returns 202) |
435
+ | GET | `/api/v1/runs/:runId/events` | Subscribe to run event stream (SSE proxy) |
436
+ | POST | `/api/v1/runs/:runId/cancel` | Cancel a run |
437
+
438
+ **POST `/api/v1/runs`** Body:
548
439
 
549
440
  ```json
550
441
  {
551
- "input": "请帮我整理 ~/Downloads 目录",
442
+ "input": "Please organise my ~/Downloads folder",
552
443
  "profile": "default",
553
- "instructions": "可选的系统指令",
554
- "session_id": "可选的会话 ID",
444
+ "instructions": "optional system instructions",
445
+ "session_id": "optional session ID",
555
446
  "conversation_history": []
556
447
  }
557
448
  ```
558
449
 
559
- 响应(202):
450
+ Response (202):
560
451
 
561
452
  ```json
562
453
  {
@@ -565,42 +456,42 @@ hermeslink config set log-level debug # 日志级别:debug / info / wa
565
456
  }
566
457
  ```
567
458
 
568
- ### 更新管理(Updates
459
+ ### Updates
569
460
 
570
- #### Hermes Agent 更新
461
+ #### Hermes Agent
571
462
 
572
- | 方法 | 路径 | 说明 |
573
- |------|------|------|
574
- | GET | `/api/v1/hermes/update-check` | 检查 Hermes Agent 是否有新版本 |
575
- | GET | `/api/v1/hermes/update/status` | 查询 Hermes 更新进度 |
576
- | POST | `/api/v1/hermes/update` | 触发 Hermes Agent 更新 |
577
- | GET | `/api/v1/hermes/update/events` | 更新进度 SSE |
463
+ | Method | Path | Description |
464
+ |--------|------|-------------|
465
+ | GET | `/api/v1/hermes/update-check` | Check for a new Hermes Agent version |
466
+ | GET | `/api/v1/hermes/update/status` | Query Hermes update progress |
467
+ | POST | `/api/v1/hermes/update` | Trigger Hermes Agent update |
468
+ | GET | `/api/v1/hermes/update/events` | Update progress SSE stream |
578
469
 
579
- #### Link 自身更新
470
+ #### Link itself
580
471
 
581
- | 方法 | 路径 | 说明 |
582
- |------|------|------|
583
- | GET | `/api/v1/link/update-check` | 检查 Link 是否有新版本 |
584
- | GET | `/api/v1/link/update/status` | 查询 Link 更新进度 |
585
- | POST | `/api/v1/link/update` | 触发 Link 自更新(`{"version":"0.3.0"}`)|
586
- | GET | `/api/v1/link/update/events` | 更新进度 SSE |
472
+ | Method | Path | Description |
473
+ |--------|------|-------------|
474
+ | GET | `/api/v1/link/update-check` | Check for a new Link version |
475
+ | GET | `/api/v1/link/update/status` | Query Link update progress |
476
+ | POST | `/api/v1/link/update` | Trigger Link self-update (`{"version":"0.3.0"}`) |
477
+ | GET | `/api/v1/link/update/events` | Update progress SSE stream |
587
478
 
588
- ### 系统(System
479
+ ### System
589
480
 
590
- | 方法 | 路径 | 说明 |
591
- |------|------|------|
592
- | GET | `/api/v1/system/status` | 系统详情(版本、自启状态、网络环境)|
593
- | GET | `/api/v1/system/version` | 仅返回 Link 版本号 |
594
- | POST | `/api/v1/system/autostart/enable` | 开启开机自启 |
595
- | POST | `/api/v1/system/autostart/disable` | 关闭开机自启 |
596
- | GET | `/api/v1/system/logs` | 最近 Link 日志 |
597
- | GET | `/api/v1/system/logs/gateway` | 最近 Gateway 日志 |
598
- | GET | `/api/v1/system/updates` | 查询可用更新(Hermes + Link 汇总)|
599
- | POST | `/api/v1/system/updates/dismiss` | 忽略当前可用更新提示 |
481
+ | Method | Path | Description |
482
+ |--------|------|-------------|
483
+ | GET | `/api/v1/system/status` | System details (version, autostart state, network info) |
484
+ | GET | `/api/v1/system/version` | Link version only |
485
+ | POST | `/api/v1/system/autostart/enable` | Enable autostart on login |
486
+ | POST | `/api/v1/system/autostart/disable` | Disable autostart |
487
+ | GET | `/api/v1/system/logs` | Recent Link logs |
488
+ | GET | `/api/v1/system/logs/gateway` | Recent gateway logs |
489
+ | GET | `/api/v1/system/updates` | Available updates (Hermes + Link combined) |
490
+ | POST | `/api/v1/system/updates/dismiss` | Dismiss current update notification |
600
491
 
601
- ### 错误响应格式
492
+ ### Error Response Format
602
493
 
603
- 所有错误均返回:
494
+ All errors return:
604
495
 
605
496
  ```json
606
497
  {
@@ -612,31 +503,31 @@ hermeslink config set log-level debug # 日志级别:debug / info / wa
612
503
  }
613
504
  ```
614
505
 
615
- 常见错误码:
506
+ Common error codes:
616
507
 
617
- | code | HTTP | 说明 |
618
- |------|------|------|
619
- | `auth_required` | 401 | 未提供 Authorization |
620
- | `device_access_token_invalid` | 401 | access_token 已过期或无效 |
621
- | `auth_invalid` | 401 | connect_token 无效或已用过 |
622
- | `pairing_session_not_found` | 404 | 配对会话不存在 |
623
- | `pairing_session_expired` | 404 | 配对会话已过期 |
624
- | `pairing_claim_mismatch` | 409 | 配对 token 不匹配 |
625
- | `link_not_paired` | 409 | 服务尚未分配 link_id |
508
+ | code | HTTP | Description |
509
+ |------|------|-------------|
510
+ | `auth_required` | 401 | No Authorization header |
511
+ | `device_access_token_invalid` | 401 | access_token expired or invalid |
512
+ | `auth_invalid` | 401 | connect_token invalid or already used |
513
+ | `pairing_session_not_found` | 404 | Pairing session not found |
514
+ | `pairing_session_expired` | 404 | Pairing session expired |
515
+ | `pairing_claim_mismatch` | 409 | Pairing token mismatch |
516
+ | `link_not_paired` | 409 | Service has not been assigned a link_id yet |
626
517
 
627
- ## 调用示例
518
+ ## Examples
628
519
 
629
- ### 全流程脚本
520
+ ### Full pairing and usage script
630
521
 
631
522
  ```bash
632
523
  #!/bin/bash
633
524
  BASE="http://localhost:18642"
634
525
 
635
- # Step 1: 生成配对 token
526
+ # Step 1: Generate a connect token
636
527
  CONNECT=$(hermeslink pair 2>&1 | grep "Connect token:" | awk '{print $NF}')
637
528
  echo "Connect token: $CONNECT"
638
529
 
639
- # Step 2: 兑换 access_token refresh_token
530
+ # Step 2: Exchange for access_token and refresh_token
640
531
  RESP=$(curl -s -X POST "$BASE/api/v1/auth/device-session" \
641
532
  -H "Authorization: Bearer $CONNECT" \
642
533
  -H "Content-Type: application/json" \
@@ -647,11 +538,11 @@ REFRESH=$(echo $RESP | python3 -c "import json,sys; print(json.load(sys.stdin)['
647
538
  echo "Access: $ACCESS"
648
539
  echo "Refresh: $REFRESH"
649
540
 
650
- # Step 3: 查询状态
541
+ # Step 3: Check status
651
542
  curl -s "$BASE/api/v1/status" -H "Authorization: Bearer $ACCESS" | python3 -m json.tool
652
543
  ```
653
544
 
654
- ### 刷新 Token
545
+ ### Refresh token
655
546
 
656
547
  ```bash
657
548
  curl -s -X POST http://localhost:18642/api/v1/auth/refresh \
@@ -659,80 +550,80 @@ curl -s -X POST http://localhost:18642/api/v1/auth/refresh \
659
550
  -d "{\"refresh_token\":\"$REFRESH\"}"
660
551
  ```
661
552
 
662
- ### 查询设备列表
553
+ ### List devices
663
554
 
664
555
  ```bash
665
556
  curl -s http://localhost:18642/api/v1/devices \
666
557
  -H "Authorization: Bearer $ACCESS"
667
558
  ```
668
559
 
669
- ### 查询对话列表
560
+ ### List conversations
670
561
 
671
562
  ```bash
672
563
  curl -s "http://localhost:18642/api/v1/conversations?limit=10" \
673
564
  -H "Authorization: Bearer $ACCESS"
674
565
  ```
675
566
 
676
- ## 开机自启
567
+ ## Autostart
677
568
 
678
- - **macOS**:通过 launchd(`~/Library/LaunchAgents/com.hermes.link.plist`)
679
- - **Linux**:通过 systemd 用户服务或 XDG autostart
680
- - **Windows**:通过 Startup 文件夹
569
+ - **macOS**: via launchd (`~/Library/LaunchAgents/com.hermes.link.plist`)
570
+ - **Linux**: via systemd user service or XDG autostart
571
+ - **Windows**: via the Startup folder
681
572
 
682
573
  ```bash
683
574
  hermeslink autostart on
684
575
  hermeslink autostart off
685
576
  ```
686
577
 
687
- ## 运行时文件
578
+ ## Runtime Files
688
579
 
689
- 所有文件存储于 `~/.hermeslink/`:
580
+ All files are stored under `~/.hermeslink/`:
690
581
 
691
- | 路径 | 说明 |
692
- |------|------|
693
- | `config.json` | 用户配置 |
694
- | `identity.json` | 设备身份(ed25519 密钥对 + link_id)|
695
- | `credentials.json` | 已配对设备的访问令牌 |
696
- | `app-connect-tokens.json` | 待使用的配对 token(5 分钟有效)|
697
- | `conversations/` | 对话数据 |
698
- | `blobs/` | 文件附件 |
699
- | `pairing/` | 配对会话 |
700
- | `link.db` | SQLite 数据库(统计信息)|
701
- | `logs/` | 日志文件 |
582
+ | Path | Description |
583
+ |------|-------------|
584
+ | `config.json` | User configuration |
585
+ | `identity.json` | Device identity (ed25519 key pair + link_id) |
586
+ | `credentials.json` | Access tokens for paired devices |
587
+ | `app-connect-tokens.json` | Pending pairing tokens (5-minute TTL) |
588
+ | `conversations/` | Conversation data |
589
+ | `blobs/` | File attachments |
590
+ | `pairing/` | Pairing sessions |
591
+ | `link.db` | SQLite database (usage statistics) |
592
+ | `logs/` | Log files |
702
593
 
703
- 卸载 npm 包不会删除此目录,重新安装后仍可复用同一 link_id
594
+ Uninstalling the npm package does not delete this directory — reinstalling reuses the same link_id.
704
595
 
705
- ## 环境变量
596
+ ## Environment Variables
706
597
 
707
- | 变量 | 说明 |
708
- |------|------|
709
- | `HERMESLINK_HOME` | 覆盖运行时目录(默认 `~/.hermeslink`)|
710
- | `HERMESLINK_LOG_LEVEL` | 覆盖日志级别 |
711
- | `HERMESLINK_LANG` | 覆盖语言(`en` / `zh-CN`)|
712
- | `HERMES_BIN` | `hermes` 二进制路径(默认 `hermes`)|
713
- | `HERMESLINK_LISTEN_HOST` | HTTP 监听地址(默认 `0.0.0.0`)|
598
+ | Variable | Description |
599
+ |----------|-------------|
600
+ | `HERMESLINK_HOME` | Override the runtime directory (default: `~/.hermeslink`) |
601
+ | `HERMESLINK_LOG_LEVEL` | Override log level |
602
+ | `HERMESLINK_LANG` | Override language (`en` / `zh-CN`) |
603
+ | `HERMES_BIN` | Path to the `hermes` binary (default: `hermes`) |
604
+ | `HERMESLINK_LISTEN_HOST` | HTTP listen address (default: `0.0.0.0`) |
714
605
 
715
- ## 开发调试
606
+ ## Development
716
607
 
717
608
  ```bash
718
- # 安装依赖并构建
609
+ # Install dependencies and build
719
610
  npm install
720
611
  npm run build
721
612
 
722
- # 前台运行(调试)
613
+ # Run in foreground (for debugging)
723
614
  npm run dev:run
724
- #
615
+ # or
725
616
  node dist/cli/index.js daemon --foreground
726
617
 
727
- # watch 模式(自动重编译,需手动重启服务)
728
- npm run dev:watch # 终端1:监听源码变化自动 build
729
- node dist/cli/index.js daemon --foreground # 终端2:运行服务
618
+ # Watch mode (auto-rebuild on source changes, restart manually)
619
+ npm run dev:watch # terminal 1: watch and rebuild
620
+ node dist/cli/index.js daemon --foreground # terminal 2: run the service
730
621
 
731
- # TypeScript 类型检查
622
+ # TypeScript type check
732
623
  npm run check
733
624
  ```
734
625
 
735
- 服务运行后可访问 `http://localhost:18642/api/v1/bootstrap` 验证是否正常。
626
+ After starting, visit `http://localhost:18642/api/v1/bootstrap` to verify the service is running.
736
627
 
737
628
  ## License
738
629