@bulolo/hermes-link 0.3.0 → 0.3.2
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.en.md +630 -0
- package/README.md +153 -22
- package/dist/{chunk-AA2LZ6QZ.js → chunk-YNBTALOX.js} +417 -51
- package/dist/cli/index.js +1 -1
- package/dist/http/app.js +1 -1
- package/package.json +4 -3
package/README.md
CHANGED
|
@@ -1,6 +1,31 @@
|
|
|
1
|
-
|
|
1
|
+
<div align="center">
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
# hermes-link
|
|
4
|
+
|
|
5
|
+
**Hermes Agent 本地接入层**
|
|
6
|
+
|
|
7
|
+
为 [Hermes Agent](https://github.com/nousresearch/hermes-agent) 提供完整的客户端 API、多设备鉴权与对话管理,支持局域网 / 公网直连。
|
|
8
|
+
|
|
9
|
+
[](https://www.npmjs.com/package/@bulolo/hermes-link)
|
|
10
|
+
[](https://nodejs.org/)
|
|
11
|
+
[](#)
|
|
12
|
+
[](#)
|
|
13
|
+
|
|
14
|
+
简体中文 | [English](./README.en.md)
|
|
15
|
+
|
|
16
|
+
[npm 包](https://www.npmjs.com/package/@bulolo/hermes-link)
|
|
17
|
+
|
|
18
|
+
<p>
|
|
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 项目"/>
|
|
21
|
+
</a>
|
|
22
|
+
</p>
|
|
23
|
+
|
|
24
|
+
**如果这个项目对你有帮助,请点击右上角 ⭐ Star 支持一下,这是对开发者最大的鼓励!**
|
|
25
|
+
|
|
26
|
+
</div>
|
|
27
|
+
|
|
28
|
+
---
|
|
4
29
|
|
|
5
30
|
## 概述
|
|
6
31
|
|
|
@@ -9,7 +34,7 @@ Hermes Link 是一个运行在本机的后台 HTTP 服务,默认监听 `http:/
|
|
|
9
34
|
所有 API 请求分为两类:
|
|
10
35
|
|
|
11
36
|
- **无需鉴权**:`/pair`、`/api/v1/bootstrap`
|
|
12
|
-
- **需要 Bearer Token**:其余接口均需 `Authorization: Bearer
|
|
37
|
+
- **需要 Bearer Token**:其余接口均需 `Authorization: Bearer hlat_xxx`,通过配对流程获取
|
|
13
38
|
|
|
14
39
|
## 为什么需要 HermesLink?
|
|
15
40
|
|
|
@@ -190,7 +215,7 @@ curl -s -X POST http://localhost:18642/api/v1/auth/device-session \
|
|
|
190
215
|
|
|
191
216
|
---
|
|
192
217
|
|
|
193
|
-
> **Token 有效期**:access_token
|
|
218
|
+
> **Token 有效期**:access_token 2 小时,refresh_token 90 天。access_token 过期后用 refresh_token 换新,无需重新配对。
|
|
194
219
|
|
|
195
220
|
## 命令一览
|
|
196
221
|
|
|
@@ -223,15 +248,15 @@ hermeslink config set log-level debug # 日志级别:debug / info / wa
|
|
|
223
248
|
|
|
224
249
|
## API 参考
|
|
225
250
|
|
|
226
|
-
服务默认监听 `http://0.0.0.0:18642`。所有需要鉴权的接口均使用 Bearer Token(`
|
|
251
|
+
服务默认监听 `http://0.0.0.0:18642`。所有需要鉴权的接口均使用 Bearer Token(`hlat_` 前缀)。
|
|
227
252
|
|
|
228
253
|
### Token 说明
|
|
229
254
|
|
|
230
255
|
| Token | 前缀 | 有效期 | 用途 |
|
|
231
256
|
|-------|------|--------|------|
|
|
232
257
|
| Connect Token | 无前缀(base64url)| 5 分钟,一次性 | 兑换 access_token |
|
|
233
|
-
| Access Token | `
|
|
234
|
-
| Refresh Token | `
|
|
258
|
+
| Access Token | `hlat_` | 2 小时 | 所有 API 请求 |
|
|
259
|
+
| Refresh Token | `hlrt_` | 90 天 | 刷新 access_token |
|
|
235
260
|
|
|
236
261
|
### 无需鉴权
|
|
237
262
|
|
|
@@ -242,7 +267,7 @@ hermeslink config set log-level debug # 日志级别:debug / info / wa
|
|
|
242
267
|
|
|
243
268
|
### 认证 / 设备
|
|
244
269
|
|
|
245
|
-
所有以下接口需要 Header:`Authorization: Bearer
|
|
270
|
+
所有以下接口需要 Header:`Authorization: Bearer hlat_xxx`
|
|
246
271
|
|
|
247
272
|
| 方法 | 路径 | 说明 |
|
|
248
273
|
|------|------|------|
|
|
@@ -251,7 +276,7 @@ hermeslink config set log-level debug # 日志级别:debug / info / wa
|
|
|
251
276
|
| POST | `/api/v1/auth/refresh` | 用 refresh_token 换新 access_token |
|
|
252
277
|
| POST | `/api/v1/auth/logout` | 撤销 refresh_token |
|
|
253
278
|
|
|
254
|
-
**POST `/api/v1/auth/device-session`** 的 Authorization 头需放 **connect_token**(不是
|
|
279
|
+
**POST `/api/v1/auth/device-session`** 的 Authorization 头需放 **connect_token**(不是 hlat_),Body:
|
|
255
280
|
|
|
256
281
|
```json
|
|
257
282
|
{
|
|
@@ -267,15 +292,15 @@ hermeslink config set log-level debug # 日志级别:debug / info / wa
|
|
|
267
292
|
{
|
|
268
293
|
"ok": true,
|
|
269
294
|
"device": { "device_id": "dev_xxx", "label": "我的设备", "platform": "ios" },
|
|
270
|
-
"access_token": { "token": "
|
|
271
|
-
"refresh_token": { "token": "
|
|
295
|
+
"access_token": { "token": "hlat_xxx", "expires_at": "2026-05-08T13:00:00Z" },
|
|
296
|
+
"refresh_token": { "token": "hlrt_xxx", "expires_at": "2026-08-06T12:00:00Z" }
|
|
272
297
|
}
|
|
273
298
|
```
|
|
274
299
|
|
|
275
300
|
**POST `/api/v1/auth/refresh`** Body:
|
|
276
301
|
|
|
277
302
|
```json
|
|
278
|
-
{ "refresh_token": "
|
|
303
|
+
{ "refresh_token": "hlrt_xxx" }
|
|
279
304
|
```
|
|
280
305
|
|
|
281
306
|
### 配对
|
|
@@ -316,38 +341,144 @@ hermeslink config set log-level debug # 日志级别:debug / info / wa
|
|
|
316
341
|
|
|
317
342
|
### 对话(Conversations)
|
|
318
343
|
|
|
344
|
+
#### 活跃对话
|
|
345
|
+
|
|
319
346
|
| 方法 | 路径 | 说明 |
|
|
320
347
|
|------|------|------|
|
|
321
|
-
| GET | `/api/v1/conversations` |
|
|
322
|
-
| GET | `/api/v1/conversations/search` |
|
|
348
|
+
| GET | `/api/v1/conversations` | 列出活跃对话(`?limit=20&cursor=xxx`) |
|
|
349
|
+
| GET | `/api/v1/conversations/search` | 搜索活跃对话(`?q=关键词`) |
|
|
323
350
|
| POST | `/api/v1/conversations` | 新建对话 |
|
|
324
|
-
| DELETE | `/api/v1/conversations` |
|
|
351
|
+
| DELETE | `/api/v1/conversations` | 批量删除对话(`{"conversation_ids":["conv_xxx"]}`) |
|
|
325
352
|
| DELETE | `/api/v1/conversations/:id` | 删除单个对话 |
|
|
326
|
-
| GET | `/api/v1/conversations/:id/messages` |
|
|
353
|
+
| GET | `/api/v1/conversations/:id/messages` | 获取对话消息列表(含 `runtime` 上下文信息) |
|
|
327
354
|
| POST | `/api/v1/conversations/:id/messages` | 发送消息 |
|
|
328
355
|
| GET | `/api/v1/conversations/:id/events` | SSE 实时事件流 |
|
|
329
356
|
| GET | `/api/v1/conversations/events` | 所有对话事件流(SSE) |
|
|
330
357
|
| PATCH | `/api/v1/conversations/:id/title` | 重命名对话(`{"title":"新标题"}`) |
|
|
331
|
-
| PATCH | `/api/v1/conversations/:id/model` |
|
|
358
|
+
| PATCH | `/api/v1/conversations/:id/model` | 切换模型(`{"model_id":"xxx"}`) |
|
|
332
359
|
| PATCH | `/api/v1/conversations/:id/profile` | 切换 profile |
|
|
333
360
|
| POST | `/api/v1/conversations/:id/ack` | 确认已读 |
|
|
334
|
-
| POST | `/api/v1/conversations/clear-plans` | 创建批量清理计划 |
|
|
335
|
-
| GET | `/api/v1/conversations/clear-plans/:planId` | 查询清理计划状态 |
|
|
336
|
-
| POST | `/api/v1/conversations/clear-plans/:planId/execute` | 执行清理计划 |
|
|
337
361
|
| POST | `/api/v1/conversations/:id/runs/:runId/cancel` | 取消对话内的某次执行 |
|
|
338
|
-
| POST | `/api/v1/conversations/:id/approvals/:approvalId/approve` |
|
|
362
|
+
| POST | `/api/v1/conversations/:id/approvals/:approvalId/approve` | 审批工具调用(允许,`{"scope":"once\|session\|always"}`) |
|
|
339
363
|
| POST | `/api/v1/conversations/:id/approvals/:approvalId/deny` | 审批工具调用(拒绝) |
|
|
340
364
|
| POST | `/api/v1/conversations/:id/blobs` | 上传附件 |
|
|
341
365
|
| GET | `/api/v1/conversations/:id/blobs/:blobId` | 下载附件 |
|
|
342
366
|
| DELETE | `/api/v1/conversations/:id/blobs/:blobId` | 删除附件 |
|
|
343
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
|
+
|
|
344
457
|
### 统计
|
|
345
458
|
|
|
346
459
|
| 方法 | 路径 | 说明 |
|
|
347
460
|
|------|------|------|
|
|
348
|
-
| GET | `/api/v1/statistics` |
|
|
461
|
+
| GET | `/api/v1/statistics` | 全局使用统计(`?profile=xxx&profile_uid=xxx`) |
|
|
349
462
|
| GET | `/api/v1/statistics/usage` | Token 用量统计(`?days=7&from=2026-05-01&to=2026-05-08&model=xxx&profile=xxx`) |
|
|
350
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
|
+
|
|
351
482
|
### 模型(Models)
|
|
352
483
|
|
|
353
484
|
| 方法 | 路径 | 说明 |
|