hvip-mcp-server 0.2.42 → 0.2.43
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 +101 -101
- package/dist/index.js +520 -42
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,101 +1,101 @@
|
|
|
1
|
-
# hvip MCP Server
|
|
2
|
-
|
|
3
|
-
> OKX API 全景图 —— 让任何 AI Agent 都能使用 OKX 的全部能力。
|
|
4
|
-
|
|
5
|
-
[](https://www.npmjs.com/package/hvip-mcp-server)
|
|
6
|
-
[](https://github.com/okx-wallet-H/hvip-mcp/blob/master/LICENSE)
|
|
7
|
-
[](https://github.com/okx-wallet-H/hvip-mcp)
|
|
8
|
-
|
|
9
|
-
📦 **仓库**: [github.com/okx-wallet-H/hvip-mcp](https://github.com/okx-wallet-H/hvip-mcp)
|
|
10
|
-
🐛 **Issue**: [提交反馈](https://github.com/okx-wallet-H/hvip-mcp/issues/new)
|
|
11
|
-
📖 **贡献**: [CONTRIBUTING.md](./CONTRIBUTING.md)
|
|
12
|
-
|
|
13
|
-
---
|
|
14
|
-
|
|
15
|
-
## 快速开始
|
|
16
|
-
|
|
17
|
-
### 1. Claude Desktop 接入
|
|
18
|
-
|
|
19
|
-
在 Claude Desktop 配置中添加:
|
|
20
|
-
|
|
21
|
-
```json
|
|
22
|
-
{
|
|
23
|
-
"mcpServers": {
|
|
24
|
-
"hvip-mcp": {
|
|
25
|
-
"command": "npx",
|
|
26
|
-
"args": ["-y", "hvip-mcp-server"],
|
|
27
|
-
"env": {
|
|
28
|
-
"OKX_API_KEY": "<你的API Key>",
|
|
29
|
-
"OKX_SECRET_KEY": "<你的Secret Key>",
|
|
30
|
-
"OKX_PASSPHRASE": "<你的Passphrase>"
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
### 2. 直接运行
|
|
38
|
-
|
|
39
|
-
```bash
|
|
40
|
-
npx hvip-mcp-server
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
### 3. 本地开发
|
|
44
|
-
|
|
45
|
-
```bash
|
|
46
|
-
git clone https://github.com/okx-wallet-H/hvip-mcp.git
|
|
47
|
-
cd hvip-mcp
|
|
48
|
-
npm install
|
|
49
|
-
npm run build
|
|
50
|
-
npm start
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
---
|
|
54
|
-
|
|
55
|
-
## 工具覆盖
|
|
56
|
-
|
|
57
|
-
| 模块 | 工具数 | 说明 |
|
|
58
|
-
|------|--------|------|
|
|
59
|
-
| 🔹 **交易类** | 40+ | 下单/撤单/改单/批量/策略委托 |
|
|
60
|
-
| 🔹 **行情类** | 30+ | Ticker/K线/深度/资金费率/标记价 |
|
|
61
|
-
| 🔹 **数据类** | 50+ | 产品信息/多空比/买卖量/PCR/统计数据 |
|
|
62
|
-
| 🔹 **资金类** | 40+ | 划转/提现/充值/余额/持仓/杠杆 |
|
|
63
|
-
| 🔹 **策略类** | 20+ | 网格/信号/跟单/价差/RFQ |
|
|
64
|
-
| 🔹 **金融类** | 15+ | 赚币/质押/借贷/法币 |
|
|
65
|
-
| 🔹 **预测市场** | 9+ | 事件/市场/深度/套利检测 |
|
|
66
|
-
| 🔹 **Skill 组合** | 4 | 账户全景/市场速览/下单预检/反馈 |
|
|
67
|
-
|
|
68
|
-
**304 个 MCP 工具 · 覆盖 97.7% OKX REST API · P0 P1 全部清零**
|
|
69
|
-
|
|
70
|
-
---
|
|
71
|
-
|
|
72
|
-
## 架构
|
|
73
|
-
|
|
74
|
-
```
|
|
75
|
-
原子层 (300+ 工具) → AI Agent 直接调用
|
|
76
|
-
↓
|
|
77
|
-
Skill 组合层 (4 个) → 串联多工具,一次完成复杂任务
|
|
78
|
-
↓
|
|
79
|
-
反馈通道 → GitHub Issues → 新 Skill 需求 → AI Agent 自行实现并提 PR
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
---
|
|
83
|
-
|
|
84
|
-
## 贡献
|
|
85
|
-
|
|
86
|
-
AI Agent 或开发者都可以贡献 Skill:
|
|
87
|
-
|
|
88
|
-
1. 阅读 [`CLAUDE.md`](./CLAUDE.md) 了解项目规范
|
|
89
|
-
2. 阅读 [`CONTRIBUTING.md`](./CONTRIBUTING.md) 了解提交流程
|
|
90
|
-
3. Fork → 创建 Skill → 提 PR → Review → 合并
|
|
91
|
-
|
|
92
|
-
每个 Skill 串联多个原子工具,解决一个具体的使用场景。
|
|
93
|
-
|
|
94
|
-
---
|
|
95
|
-
|
|
96
|
-
## 文档
|
|
97
|
-
|
|
98
|
-
- [`CLAUDE.md`](./CLAUDE.md) — AI Agent 项目指南
|
|
99
|
-
- [`CONTRIBUTING.md`](./CONTRIBUTING.md) — Skill 贡献流程
|
|
100
|
-
- [`docs/OKX-MCP-API对接标准-v0.1.8.md`](./docs/OKX-MCP-API对接标准-v0.1.8.md) — API 对接规范
|
|
101
|
-
- [`docs/OKX-MCP-防幻觉对接SOP-v1.0.md`](./docs/OKX-MCP-防幻觉对接SOP-v1.0.md) — 防幻觉 SOP
|
|
1
|
+
# hvip MCP Server
|
|
2
|
+
|
|
3
|
+
> OKX API 全景图 —— 让任何 AI Agent 都能使用 OKX 的全部能力。
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/hvip-mcp-server)
|
|
6
|
+
[](https://github.com/okx-wallet-H/hvip-mcp/blob/master/LICENSE)
|
|
7
|
+
[](https://github.com/okx-wallet-H/hvip-mcp)
|
|
8
|
+
|
|
9
|
+
📦 **仓库**: [github.com/okx-wallet-H/hvip-mcp](https://github.com/okx-wallet-H/hvip-mcp)
|
|
10
|
+
🐛 **Issue**: [提交反馈](https://github.com/okx-wallet-H/hvip-mcp/issues/new)
|
|
11
|
+
📖 **贡献**: [CONTRIBUTING.md](./CONTRIBUTING.md)
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## 快速开始
|
|
16
|
+
|
|
17
|
+
### 1. Claude Desktop 接入
|
|
18
|
+
|
|
19
|
+
在 Claude Desktop 配置中添加:
|
|
20
|
+
|
|
21
|
+
```json
|
|
22
|
+
{
|
|
23
|
+
"mcpServers": {
|
|
24
|
+
"hvip-mcp": {
|
|
25
|
+
"command": "npx",
|
|
26
|
+
"args": ["-y", "hvip-mcp-server"],
|
|
27
|
+
"env": {
|
|
28
|
+
"OKX_API_KEY": "<你的API Key>",
|
|
29
|
+
"OKX_SECRET_KEY": "<你的Secret Key>",
|
|
30
|
+
"OKX_PASSPHRASE": "<你的Passphrase>"
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### 2. 直接运行
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
npx hvip-mcp-server
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### 3. 本地开发
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
git clone https://github.com/okx-wallet-H/hvip-mcp.git
|
|
47
|
+
cd hvip-mcp
|
|
48
|
+
npm install
|
|
49
|
+
npm run build
|
|
50
|
+
npm start
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## 工具覆盖
|
|
56
|
+
|
|
57
|
+
| 模块 | 工具数 | 说明 |
|
|
58
|
+
|------|--------|------|
|
|
59
|
+
| 🔹 **交易类** | 40+ | 下单/撤单/改单/批量/策略委托 |
|
|
60
|
+
| 🔹 **行情类** | 30+ | Ticker/K线/深度/资金费率/标记价 |
|
|
61
|
+
| 🔹 **数据类** | 50+ | 产品信息/多空比/买卖量/PCR/统计数据 |
|
|
62
|
+
| 🔹 **资金类** | 40+ | 划转/提现/充值/余额/持仓/杠杆 |
|
|
63
|
+
| 🔹 **策略类** | 20+ | 网格/信号/跟单/价差/RFQ |
|
|
64
|
+
| 🔹 **金融类** | 15+ | 赚币/质押/借贷/法币 |
|
|
65
|
+
| 🔹 **预测市场** | 9+ | 事件/市场/深度/套利检测 |
|
|
66
|
+
| 🔹 **Skill 组合** | 4 | 账户全景/市场速览/下单预检/反馈 |
|
|
67
|
+
|
|
68
|
+
**304 个 MCP 工具 · 覆盖 97.7% OKX REST API · P0 P1 全部清零**
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## 架构
|
|
73
|
+
|
|
74
|
+
```
|
|
75
|
+
原子层 (300+ 工具) → AI Agent 直接调用
|
|
76
|
+
↓
|
|
77
|
+
Skill 组合层 (4 个) → 串联多工具,一次完成复杂任务
|
|
78
|
+
↓
|
|
79
|
+
反馈通道 → GitHub Issues → 新 Skill 需求 → AI Agent 自行实现并提 PR
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## 贡献
|
|
85
|
+
|
|
86
|
+
AI Agent 或开发者都可以贡献 Skill:
|
|
87
|
+
|
|
88
|
+
1. 阅读 [`CLAUDE.md`](./CLAUDE.md) 了解项目规范
|
|
89
|
+
2. 阅读 [`CONTRIBUTING.md`](./CONTRIBUTING.md) 了解提交流程
|
|
90
|
+
3. Fork → 创建 Skill → 提 PR → Review → 合并
|
|
91
|
+
|
|
92
|
+
每个 Skill 串联多个原子工具,解决一个具体的使用场景。
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## 文档
|
|
97
|
+
|
|
98
|
+
- [`CLAUDE.md`](./CLAUDE.md) — AI Agent 项目指南
|
|
99
|
+
- [`CONTRIBUTING.md`](./CONTRIBUTING.md) — Skill 贡献流程
|
|
100
|
+
- [`docs/OKX-MCP-API对接标准-v0.1.8.md`](./docs/OKX-MCP-API对接标准-v0.1.8.md) — API 对接规范
|
|
101
|
+
- [`docs/OKX-MCP-防幻觉对接SOP-v1.0.md`](./docs/OKX-MCP-防幻觉对接SOP-v1.0.md) — 防幻觉 SOP
|
package/dist/index.js
CHANGED
|
@@ -6,6 +6,9 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
|
6
6
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
7
|
var __getProtoOf = Object.getPrototypeOf;
|
|
8
8
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
+
var __esm = (fn, res) => function __init() {
|
|
10
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
11
|
+
};
|
|
9
12
|
var __commonJS = (cb, mod) => function __require() {
|
|
10
13
|
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
11
14
|
};
|
|
@@ -10565,6 +10568,34 @@ var require_websocket_server = __commonJS({
|
|
|
10565
10568
|
}
|
|
10566
10569
|
});
|
|
10567
10570
|
|
|
10571
|
+
// node_modules/ws/wrapper.mjs
|
|
10572
|
+
var wrapper_exports = {};
|
|
10573
|
+
__export(wrapper_exports, {
|
|
10574
|
+
PerMessageDeflate: () => import_permessage_deflate.default,
|
|
10575
|
+
Receiver: () => import_receiver.default,
|
|
10576
|
+
Sender: () => import_sender.default,
|
|
10577
|
+
WebSocket: () => import_websocket.default,
|
|
10578
|
+
WebSocketServer: () => import_websocket_server.default,
|
|
10579
|
+
createWebSocketStream: () => import_stream.default,
|
|
10580
|
+
default: () => wrapper_default,
|
|
10581
|
+
extension: () => import_extension.default,
|
|
10582
|
+
subprotocol: () => import_subprotocol.default
|
|
10583
|
+
});
|
|
10584
|
+
var import_stream, import_extension, import_permessage_deflate, import_receiver, import_sender, import_subprotocol, import_websocket, import_websocket_server, wrapper_default;
|
|
10585
|
+
var init_wrapper = __esm({
|
|
10586
|
+
"node_modules/ws/wrapper.mjs"() {
|
|
10587
|
+
import_stream = __toESM(require_stream(), 1);
|
|
10588
|
+
import_extension = __toESM(require_extension(), 1);
|
|
10589
|
+
import_permessage_deflate = __toESM(require_permessage_deflate(), 1);
|
|
10590
|
+
import_receiver = __toESM(require_receiver(), 1);
|
|
10591
|
+
import_sender = __toESM(require_sender(), 1);
|
|
10592
|
+
import_subprotocol = __toESM(require_subprotocol(), 1);
|
|
10593
|
+
import_websocket = __toESM(require_websocket(), 1);
|
|
10594
|
+
import_websocket_server = __toESM(require_websocket_server(), 1);
|
|
10595
|
+
wrapper_default = import_websocket.default;
|
|
10596
|
+
}
|
|
10597
|
+
});
|
|
10598
|
+
|
|
10568
10599
|
// node_modules/zod/v3/external.js
|
|
10569
10600
|
var external_exports = {};
|
|
10570
10601
|
__export(external_exports, {
|
|
@@ -29728,7 +29759,7 @@ function registerOutcomesTools(server) {
|
|
|
29728
29759
|
);
|
|
29729
29760
|
server.tool(
|
|
29730
29761
|
"okx_predictions_split",
|
|
29731
|
-
"## \u529F\u80FD\uFF1A\u5C06 xp \u62C6\u5206\u4E3A YES \u548C NO \u4EE3\u5E01\n## \u573A\u666F\uFF1A\u62C6\u5206\u8D44\u91D1\u5230 YES/NO \u53CC\u65B9\u5411\uFF0C\u53C2\u4E0E\u9884\u6D4B\u5E02\u573A\n## \u5173\u952E\u8BCD\uFF1A\u62C6\u5206, split, xp
|
|
29762
|
+
"## \u529F\u80FD\uFF1A\u5C06 xp \u62C6\u5206\u4E3A YES \u548C NO \u4EE3\u5E01\n## \u573A\u666F\uFF1A\u62C6\u5206\u8D44\u91D1\u5230 YES/NO \u53CC\u65B9\u5411\uFF0C\u53C2\u4E0E\u9884\u6D4B\u5E02\u573A\n## \u5173\u952E\u8BCD\uFF1A\u62C6\u5206, split, xp\n## \u53C2\u6570\uFF1A\n## - amount: \u62C6\u5206\u6570\u91CF\uFF08\u5FC5\u586B\uFF09\n## \u9274\u6743\uFF1A\u9700\u8981 API Key\uFF08EIP-712\uFF09\n## \u98CE\u9669\uFF1AWRITE \u2014 \u8D44\u91D1\u64CD\u4F5C\n## \u8FD4\u56DE\u91CF\uFF1A\u5FAE\u5C0F ~500B\n## \u5173\u8054\uFF1Aokx_predictions_balance \u2192 \u672C\u5DE5\u5177",
|
|
29732
29763
|
{ amount: external_exports.string().describe("\u62C6\u5206\u6570\u91CF\uFF08\u5FC5\u586B\uFF09") },
|
|
29733
29764
|
async ({ amount }) => {
|
|
29734
29765
|
const auth = getAuth();
|
|
@@ -29743,7 +29774,7 @@ function registerOutcomesTools(server) {
|
|
|
29743
29774
|
);
|
|
29744
29775
|
server.tool(
|
|
29745
29776
|
"okx_predictions_merge",
|
|
29746
|
-
"## \u529F\u80FD\uFF1A\u5C06 YES+NO \u5408\u5E76\u4E3A xp\n## \u573A\u666F\uFF1A\u9000\u51FA\u9884\u6D4B\u5E02\u573A\u4ED3\u4F4D\uFF0C\u56DE\u6536\u8D44\u91D1\n## \u5173\u952E\u8BCD\uFF1A\u5408\u5E76, merge,
|
|
29777
|
+
"## \u529F\u80FD\uFF1A\u5C06 YES+NO \u5408\u5E76\u4E3A xp\n## \u573A\u666F\uFF1A\u9000\u51FA\u9884\u6D4B\u5E02\u573A\u4ED3\u4F4D\uFF0C\u56DE\u6536\u8D44\u91D1\n## \u5173\u952E\u8BCD\uFF1A\u5408\u5E76, merge, xp\n## \u53C2\u6570\uFF1A\n## - amount: \u5408\u5E76\u6570\u91CF\uFF08\u5FC5\u586B\uFF09\n## \u9274\u6743\uFF1A\u9700\u8981 API Key\uFF08EIP-712\uFF09\n## \u98CE\u9669\uFF1AWRITE \u2014 \u8D44\u91D1\u64CD\u4F5C\n## \u8FD4\u56DE\u91CF\uFF1A\u5FAE\u5C0F ~500B\n## \u5173\u8054\uFF1Aokx_predictions_split \u2192 \u672C\u5DE5\u5177",
|
|
29747
29778
|
{ amount: external_exports.string().describe("\u5408\u5E76\u6570\u91CF\uFF08\u5FC5\u586B\uFF09") },
|
|
29748
29779
|
async ({ amount }) => {
|
|
29749
29780
|
const auth = getAuth();
|
|
@@ -29758,7 +29789,7 @@ function registerOutcomesTools(server) {
|
|
|
29758
29789
|
);
|
|
29759
29790
|
server.tool(
|
|
29760
29791
|
"okx_predictions_redeem",
|
|
29761
|
-
"## \u529F\u80FD\uFF1A\u7ED3\u7B97\u540E\u8D4E\u56DE\u83B7\u80DC\u4EE3\u5E01\u4E3A xp\n## \u573A\u666F\uFF1A\u4E8B\u4EF6\u7ED3\u7B97\u540E\
|
|
29792
|
+
"## \u529F\u80FD\uFF1A\u7ED3\u7B97\u540E\u8D4E\u56DE\u83B7\u80DC\u4EE3\u5E01\u4E3A xp\n## \u573A\u666F\uFF1A\u4E8B\u4EF6\u7ED3\u7B97\u540E\u5151\u56DE\n## \u5173\u952E\u8BCD\uFF1A\u8D4E\u56DE, redeem, \u7ED3\u7B97\n## \u53C2\u6570\uFF1A\n## - assetId: \u8D44\u4EA7ID\uFF08\u53EF\u9009\uFF09\n## \u9274\u6743\uFF1A\u9700\u8981 API Key\uFF08EIP-712\uFF09\n## \u98CE\u9669\uFF1AWRITE \u2014 \u8D44\u91D1\u64CD\u4F5C\n## \u8FD4\u56DE\u91CF\uFF1A\u5FAE\u5C0F ~500B\n## \u5173\u8054\uFF1A\u4E8B\u4EF6\u7ED3\u7B97 \u2192 \u672C\u5DE5\u5177 \u2192 okx_predictions_balance",
|
|
29762
29793
|
{ assetId: external_exports.string().optional().describe("\u8D44\u4EA7ID") },
|
|
29763
29794
|
async ({ assetId }) => {
|
|
29764
29795
|
const auth = getAuth();
|
|
@@ -29775,7 +29806,7 @@ function registerOutcomesTools(server) {
|
|
|
29775
29806
|
);
|
|
29776
29807
|
server.tool(
|
|
29777
29808
|
"okx_predictions_balance",
|
|
29778
|
-
"## \u529F\u80FD\uFF1A\u67E5\u8BE2 Outcomes \u8D26\u6237 xp \u4F59\u989D\n## \u573A\u666F\uFF1A\u67E5\u770B\u9884\u6D4B\u5E02\u573A\u53EF\u7528\u8D44\u91D1\n## \u5173\u952E\u8BCD\uFF1A\u4F59\u989D, balance, xp\n## \u53C2\u6570\uFF1A\u65E0\n## \u9274\u6743\uFF1A\u9700\u8981 API Key\uFF08\u53EA\u8BFB\uFF09\n## \u98CE\u9669\uFF1AREAD
|
|
29809
|
+
"## \u529F\u80FD\uFF1A\u67E5\u8BE2 Outcomes \u8D26\u6237 xp \u4F59\u989D\n## \u573A\u666F\uFF1A\u67E5\u770B\u9884\u6D4B\u5E02\u573A\u53EF\u7528\u8D44\u91D1\n## \u5173\u952E\u8BCD\uFF1A\u4F59\u989D, balance, xp\n## \u53C2\u6570\uFF1A\u65E0\n## \u9274\u6743\uFF1A\u9700\u8981 API Key\uFF08\u53EA\u8BFB\uFF09\n## \u98CE\u9669\uFF1AREAD\n## \u8FD4\u56DE\u91CF\uFF1A\u5FAE\u5C0F ~500B\n## \u5173\u8054\uFF1A\u672C\u5DE5\u5177 \u2192 okx_predictions_positions",
|
|
29779
29810
|
{},
|
|
29780
29811
|
async () => {
|
|
29781
29812
|
const auth = getAuth();
|
|
@@ -29790,7 +29821,7 @@ function registerOutcomesTools(server) {
|
|
|
29790
29821
|
);
|
|
29791
29822
|
server.tool(
|
|
29792
29823
|
"okx_predictions_trades",
|
|
29793
|
-
"## \u529F\u80FD\uFF1A\u67E5\u8BE2 Outcomes \u6210\u4EA4\u8BB0\u5F55\n## \u573A\u666F\uFF1A\u67E5\u770B\u5386\u53F2\u6210\u4EA4\u660E\u7EC6\n## \u5173\u952E\u8BCD\uFF1A\u6210\u4EA4\u8BB0\u5F55, trades, \u5386\u53F2\u6210\u4EA4\n## \u53C2\u6570\uFF1A\n## - marketId: \u5E02\u573AID\uFF08\u53EF\u9009\uFF09\n## - limit: \u8FD4\u56DE\u6761\u6570\uFF08\u53EF\u9009\uFF09\n## \u9274\u6743\uFF1A\u9700\u8981 API Key\uFF08\u53EA\u8BFB\uFF09\n## \u98CE\u9669\uFF1AREAD
|
|
29824
|
+
"## \u529F\u80FD\uFF1A\u67E5\u8BE2 Outcomes \u6210\u4EA4\u8BB0\u5F55\n## \u573A\u666F\uFF1A\u67E5\u770B\u5386\u53F2\u6210\u4EA4\u660E\u7EC6\n## \u5173\u952E\u8BCD\uFF1A\u6210\u4EA4\u8BB0\u5F55, trades, \u5386\u53F2\u6210\u4EA4\n## \u53C2\u6570\uFF1A\n## - marketId: \u5E02\u573AID\uFF08\u53EF\u9009\uFF09\n## - limit: \u8FD4\u56DE\u6761\u6570\uFF08\u53EF\u9009\uFF09\n## \u9274\u6743\uFF1A\u9700\u8981 API Key\uFF08\u53EA\u8BFB\uFF09\n## \u98CE\u9669\uFF1AREAD\n## \u8FD4\u56DE\u91CF\uFF1A\u4E2D\u7B49 ~5KB\n## \u5173\u8054\uFF1Aokx_predictions_positions \u2192 \u672C\u5DE5\u5177",
|
|
29794
29825
|
{
|
|
29795
29826
|
marketId: external_exports.string().optional().describe("\u5E02\u573AID"),
|
|
29796
29827
|
limit: external_exports.number().int().min(1).max(100).optional().describe("\u8FD4\u56DE\u6761\u6570")
|
|
@@ -31555,18 +31586,8 @@ function registerAgentUtils(server, auth) {
|
|
|
31555
31586
|
);
|
|
31556
31587
|
}
|
|
31557
31588
|
|
|
31558
|
-
// node_modules/ws/wrapper.mjs
|
|
31559
|
-
var import_stream = __toESM(require_stream(), 1);
|
|
31560
|
-
var import_extension = __toESM(require_extension(), 1);
|
|
31561
|
-
var import_permessage_deflate = __toESM(require_permessage_deflate(), 1);
|
|
31562
|
-
var import_receiver = __toESM(require_receiver(), 1);
|
|
31563
|
-
var import_sender = __toESM(require_sender(), 1);
|
|
31564
|
-
var import_subprotocol = __toESM(require_subprotocol(), 1);
|
|
31565
|
-
var import_websocket = __toESM(require_websocket(), 1);
|
|
31566
|
-
var import_websocket_server = __toESM(require_websocket_server(), 1);
|
|
31567
|
-
var wrapper_default = import_websocket.default;
|
|
31568
|
-
|
|
31569
31589
|
// src/adapters/xlayer-ws.ts
|
|
31590
|
+
init_wrapper();
|
|
31570
31591
|
var WS_URL = process.env.XLAYER_WS_URL || "wss://xlayerws.okx.com";
|
|
31571
31592
|
var MAX_EVENTS = 500;
|
|
31572
31593
|
var XLayerWSManager = class {
|
|
@@ -31828,16 +31849,286 @@ function registerXLayerWSTools(server) {
|
|
|
31828
31849
|
);
|
|
31829
31850
|
}
|
|
31830
31851
|
|
|
31852
|
+
// src/adapters/ws.ts
|
|
31853
|
+
var import_node_crypto2 = __toESM(require("node:crypto"));
|
|
31854
|
+
var WS_PUBLIC = "wss://ws.okx.com:8443/ws/v5/public";
|
|
31855
|
+
var WS_PRIVATE = "wss://ws.okx.com:8443/ws/v5/private";
|
|
31856
|
+
var subCounter = 0;
|
|
31857
|
+
var WsManager = class {
|
|
31858
|
+
subscriptions = /* @__PURE__ */ new Map();
|
|
31859
|
+
events = [];
|
|
31860
|
+
ws = null;
|
|
31861
|
+
pingTimer = null;
|
|
31862
|
+
channelArgs = /* @__PURE__ */ new Map();
|
|
31863
|
+
// channel -> instIds
|
|
31864
|
+
async subscribe(opts) {
|
|
31865
|
+
const wsModule = await Promise.resolve().then(() => (init_wrapper(), wrapper_exports));
|
|
31866
|
+
const id = `sub_${++subCounter}`;
|
|
31867
|
+
this.subscriptions.set(id, { id, channel: opts.channel, instId: opts.instId });
|
|
31868
|
+
const arg = { channel: opts.channel, instId: opts.instId };
|
|
31869
|
+
if (!this.ws || this.ws.readyState !== wsModule.WebSocket.OPEN) {
|
|
31870
|
+
const url = opts.type === "private" ? WS_PRIVATE : WS_PUBLIC;
|
|
31871
|
+
await this.connect(wsModule, url, opts.auth);
|
|
31872
|
+
}
|
|
31873
|
+
if (this.ws?.readyState === wsModule.WebSocket.OPEN) {
|
|
31874
|
+
this.ws.send(JSON.stringify({ op: "subscribe", args: [arg] }));
|
|
31875
|
+
}
|
|
31876
|
+
const ck = opts.channel;
|
|
31877
|
+
if (!this.channelArgs.has(ck)) this.channelArgs.set(ck, /* @__PURE__ */ new Set());
|
|
31878
|
+
this.channelArgs.get(ck).add(opts.instId);
|
|
31879
|
+
return id;
|
|
31880
|
+
}
|
|
31881
|
+
drain(subId, limit = 20) {
|
|
31882
|
+
let batch;
|
|
31883
|
+
if (subId) {
|
|
31884
|
+
batch = this.events.filter((e) => e.subId === subId);
|
|
31885
|
+
this.events = this.events.filter((e) => e.subId !== subId);
|
|
31886
|
+
} else {
|
|
31887
|
+
batch = this.events.splice(0, limit);
|
|
31888
|
+
}
|
|
31889
|
+
return batch.slice(0, limit);
|
|
31890
|
+
}
|
|
31891
|
+
countBuffered(subId) {
|
|
31892
|
+
if (subId) return this.events.filter((e) => e.subId === subId).length;
|
|
31893
|
+
return this.events.length;
|
|
31894
|
+
}
|
|
31895
|
+
countAllBuffered() {
|
|
31896
|
+
return this.events.length;
|
|
31897
|
+
}
|
|
31898
|
+
getStatus() {
|
|
31899
|
+
return [...this.subscriptions.values()].map((s) => ({
|
|
31900
|
+
id: s.id,
|
|
31901
|
+
active: true,
|
|
31902
|
+
channel: s.channel,
|
|
31903
|
+
instId: s.instId,
|
|
31904
|
+
buffered: this.countBuffered(s.id)
|
|
31905
|
+
}));
|
|
31906
|
+
}
|
|
31907
|
+
close(subId) {
|
|
31908
|
+
if (subId) {
|
|
31909
|
+
this.subscriptions.delete(subId);
|
|
31910
|
+
this.events = this.events.filter((e) => e.subId !== subId);
|
|
31911
|
+
return 1;
|
|
31912
|
+
}
|
|
31913
|
+
const count = this.subscriptions.size;
|
|
31914
|
+
this.subscriptions.clear();
|
|
31915
|
+
this.events = [];
|
|
31916
|
+
if (this.ws) {
|
|
31917
|
+
try {
|
|
31918
|
+
this.ws.close();
|
|
31919
|
+
} catch {
|
|
31920
|
+
}
|
|
31921
|
+
;
|
|
31922
|
+
this.ws = null;
|
|
31923
|
+
}
|
|
31924
|
+
if (this.pingTimer) {
|
|
31925
|
+
clearInterval(this.pingTimer);
|
|
31926
|
+
this.pingTimer = null;
|
|
31927
|
+
}
|
|
31928
|
+
return count;
|
|
31929
|
+
}
|
|
31930
|
+
connect(wsModule, url, auth) {
|
|
31931
|
+
return new Promise((resolve, reject) => {
|
|
31932
|
+
const ws = new wsModule.WebSocket(url);
|
|
31933
|
+
const timeout = setTimeout(() => {
|
|
31934
|
+
ws.close();
|
|
31935
|
+
reject(new Error("WS \u8FDE\u63A5\u8D85\u65F6(10s)"));
|
|
31936
|
+
}, 1e4);
|
|
31937
|
+
ws.on("open", () => {
|
|
31938
|
+
clearTimeout(timeout);
|
|
31939
|
+
if (auth && url.includes("private")) {
|
|
31940
|
+
const ts = Math.floor(Date.now() / 1e3).toString();
|
|
31941
|
+
const sign2 = import_node_crypto2.default.createHmac("sha256", auth.secret).update(ts + "GET/users/self/verify").digest("base64");
|
|
31942
|
+
ws.send(JSON.stringify({
|
|
31943
|
+
op: "login",
|
|
31944
|
+
args: [{ apiKey: auth.apiKey, passphrase: auth.passphrase, timestamp: ts, sign: sign2 }]
|
|
31945
|
+
}));
|
|
31946
|
+
}
|
|
31947
|
+
for (const [channel, instIds] of this.channelArgs) {
|
|
31948
|
+
for (const instId of instIds) {
|
|
31949
|
+
ws.send(JSON.stringify({ op: "subscribe", args: [{ channel, instId }] }));
|
|
31950
|
+
}
|
|
31951
|
+
}
|
|
31952
|
+
this.pingTimer = setInterval(() => {
|
|
31953
|
+
if (ws.readyState === wsModule.WebSocket.OPEN) ws.send("ping");
|
|
31954
|
+
}, 25e3);
|
|
31955
|
+
this.ws = ws;
|
|
31956
|
+
resolve();
|
|
31957
|
+
});
|
|
31958
|
+
ws.on("message", (raw) => {
|
|
31959
|
+
try {
|
|
31960
|
+
const msg = raw.toString();
|
|
31961
|
+
if (msg === "pong") return;
|
|
31962
|
+
const parsed = JSON.parse(msg);
|
|
31963
|
+
if (parsed.arg && parsed.data) {
|
|
31964
|
+
for (const [id, sub] of this.subscriptions) {
|
|
31965
|
+
if (sub.channel === parsed.arg.channel && sub.instId === parsed.arg.instId) {
|
|
31966
|
+
this.events.push({
|
|
31967
|
+
subId: id,
|
|
31968
|
+
channel: parsed.arg.channel || sub.channel,
|
|
31969
|
+
instId: parsed.arg.instId || sub.instId,
|
|
31970
|
+
ts: Date.now(),
|
|
31971
|
+
data: parsed.data
|
|
31972
|
+
});
|
|
31973
|
+
if (this.events.length > 1e4) this.events = this.events.slice(-5e3);
|
|
31974
|
+
break;
|
|
31975
|
+
}
|
|
31976
|
+
}
|
|
31977
|
+
}
|
|
31978
|
+
} catch {
|
|
31979
|
+
}
|
|
31980
|
+
});
|
|
31981
|
+
ws.on("error", (err) => {
|
|
31982
|
+
clearTimeout(timeout);
|
|
31983
|
+
reject(err);
|
|
31984
|
+
});
|
|
31985
|
+
ws.on("close", () => {
|
|
31986
|
+
if (this.pingTimer) {
|
|
31987
|
+
clearInterval(this.pingTimer);
|
|
31988
|
+
this.pingTimer = null;
|
|
31989
|
+
}
|
|
31990
|
+
this.ws = null;
|
|
31991
|
+
});
|
|
31992
|
+
});
|
|
31993
|
+
}
|
|
31994
|
+
};
|
|
31995
|
+
|
|
31996
|
+
// src/tools/ws.ts
|
|
31997
|
+
var wsManager = null;
|
|
31998
|
+
function getOrCreateWs() {
|
|
31999
|
+
if (!wsManager) wsManager = new WsManager();
|
|
32000
|
+
return wsManager;
|
|
32001
|
+
}
|
|
32002
|
+
var PUBLIC_CHANNELS = [
|
|
32003
|
+
"tickers",
|
|
32004
|
+
"trades",
|
|
32005
|
+
"candle1m",
|
|
32006
|
+
"candle5m",
|
|
32007
|
+
"candle15m",
|
|
32008
|
+
"candle1H",
|
|
32009
|
+
"candle4H",
|
|
32010
|
+
"candle1D",
|
|
32011
|
+
"books5",
|
|
32012
|
+
"books",
|
|
32013
|
+
"mark-price",
|
|
32014
|
+
"funding-rate",
|
|
32015
|
+
"open-interest",
|
|
32016
|
+
"price-limit",
|
|
32017
|
+
"index-tickers"
|
|
32018
|
+
];
|
|
32019
|
+
function registerWsTools(server) {
|
|
32020
|
+
server.tool(
|
|
32021
|
+
"okx_ws_subscribe",
|
|
32022
|
+
"## \u529F\u80FD\uFF1A\u8BA2\u9605OKX WebSocket\u5B9E\u65F6\u6570\u636E\uFF0C\u4E8B\u4EF6\u81EA\u52A8\u7F13\u51B2\u5728\u5185\u5B58\u4E2D\n## \u573A\u666F\uFF1AAgent \u9700\u8981\u5B9E\u65F6\u76D1\u63A7\u884C\u60C5\u53D8\u5316\u800C\u975E\u8F6E\u8BE2\u65F6\u8C03\u7528\n## \u5173\u952E\u8BCD\uFF1AWebSocket, ws, \u5B9E\u65F6\u63A8\u9001, \u5B9E\u65F6\u884C\u60C5, \u8BA2\u9605, subscribe, \u6D41\u5F0F\n## \u53C2\u6570\uFF1A\n## - instId: \u4EA7\u54C1ID\uFF0C\u5982 BTC-USDT\u3001ETH-USDT-SWAP\n## - channel: \u9891\u9053\u540D\u3002(tickers/trades/candle1m~1D/books5/books\u7B49)\n## - instType: SPOT/SWAP/FUTURES/OPTION\uFF08tickers/trades \u9891\u9053\u9700\u8981\uFF09\n## \u9274\u6743\uFF1APUBLIC \u2014 \u516C\u5F00\u9891\u9053\n## \u98CE\u9669\uFF1AREAD \u2014 \u53EA\u8BFB\u8BA2\u9605\n## \u8FD4\u56DE\u91CF\uFF1A\u5FAE\u5C0F ~500B\n## \u5173\u8054\uFF1A\u672C\u5DE5\u5177\u8BA2\u9605 \u2192 okx_ws_events \u62C9\u53D6 \u2192 \u51B3\u7B56 \u2192 okx_ws_close \u5173\u95ED",
|
|
32023
|
+
{
|
|
32024
|
+
instId: external_exports.string().describe("\u4EA7\u54C1ID\uFF0C\u5982 BTC-USDT"),
|
|
32025
|
+
channel: external_exports.string().describe("\u9891\u9053\u540D"),
|
|
32026
|
+
instType: external_exports.enum(["SPOT", "SWAP", "FUTURES", "OPTION"]).optional().describe("tickers/trades \u9700\u8981")
|
|
32027
|
+
},
|
|
32028
|
+
async ({ instId, channel }) => {
|
|
32029
|
+
try {
|
|
32030
|
+
if (!PUBLIC_CHANNELS.includes(channel)) {
|
|
32031
|
+
return toError(new Error(`\u9891\u9053 "${channel}" \u4E0D\u652F\u6301\u3002\u652F\u6301: ${PUBLIC_CHANNELS.join(" ")}`));
|
|
32032
|
+
}
|
|
32033
|
+
const ws = getOrCreateWs();
|
|
32034
|
+
const subId = await ws.subscribe({ channel, instId: instId.toUpperCase(), type: "public" });
|
|
32035
|
+
return toResult({
|
|
32036
|
+
subscribed: true,
|
|
32037
|
+
subscriptionId: subId,
|
|
32038
|
+
channel,
|
|
32039
|
+
instId: instId.toUpperCase(),
|
|
32040
|
+
buffered: ws.countBuffered(subId),
|
|
32041
|
+
hint: `\u5DF2\u8BA2\u9605 ${instId.toUpperCase()} ${channel}\u3002\u8C03\u7528 okx_ws_events \u62C9\u53D6\u4E8B\u4EF6\u3002`,
|
|
32042
|
+
tsIso: (/* @__PURE__ */ new Date()).toISOString()
|
|
32043
|
+
});
|
|
32044
|
+
} catch (e) {
|
|
32045
|
+
return toError(e);
|
|
32046
|
+
}
|
|
32047
|
+
}
|
|
32048
|
+
);
|
|
32049
|
+
server.tool(
|
|
32050
|
+
"okx_ws_events",
|
|
32051
|
+
"## \u529F\u80FD\uFF1A\u62C9\u53D6 okx_ws_subscribe \u7F13\u51B2\u7684\u5B9E\u65F6\u4E8B\u4EF6\uFF0C\u6BCF\u6B21\u62C9\u53D6\u540E\u6E05\u7A7A\n## \u573A\u666F\uFF1AAgent \u5B9A\u671F\u68C0\u67E5\u6700\u65B0\u884C\u60C5\u3001\u4EE3\u66FF\u8F6E\u8BE2 REST API\n## \u5173\u952E\u8BCD\uFF1A\u62C9\u53D6, poll, \u4E8B\u4EF6, events, \u7F13\u51B2\u533A, \u6700\u65B0\u6D88\u606F\n## \u53C2\u6570\uFF1A\n## - subscriptionId: \u8BA2\u9605ID\uFF08\u9009\u586B\uFF0C\u4E0D\u586B\u8FD4\u56DE\u5168\u90E8\uFF09\n## - limit: \u6700\u5927\u8FD4\u56DE\u6761\u6570\uFF0C\u9ED8\u8BA420\n## - filter: \u8FC7\u6EE4\u5173\u952E\u8BCD\n## \u9274\u6743\uFF1APUBLIC \u2014 \u8BFB\u5185\u5B58\u7F13\u51B2\u533A\n## \u98CE\u9669\uFF1AREAD \u2014 \u53EA\u8BFB\n## \u8FD4\u56DE\u91CF\uFF1A\u53D7 limit \u63A7\u5236\uFF0C\u9ED8\u8BA4 ~2KB\n## \u5173\u8054\uFF1Aokx_ws_subscribe \u8BA2\u9605 \u2192 \u672C\u5DE5\u5177\u62C9\u53D6 \u2192 \u51B3\u7B56",
|
|
32052
|
+
{
|
|
32053
|
+
subscriptionId: external_exports.string().optional().describe("\u8BA2\u9605ID"),
|
|
32054
|
+
limit: external_exports.number().int().min(1).max(50).default(20).describe("\u6700\u5927\u8FD4\u56DE\u6761\u6570"),
|
|
32055
|
+
filter: external_exports.string().optional().describe("\u8FC7\u6EE4\u5173\u952E\u8BCD")
|
|
32056
|
+
},
|
|
32057
|
+
async ({ subscriptionId, limit, filter }) => {
|
|
32058
|
+
try {
|
|
32059
|
+
const ws = getOrCreateWs();
|
|
32060
|
+
let events = ws.drain(subscriptionId, limit);
|
|
32061
|
+
if (filter) {
|
|
32062
|
+
const kw = filter.toLowerCase();
|
|
32063
|
+
events = events.filter((e) => JSON.stringify(e).toLowerCase().includes(kw));
|
|
32064
|
+
}
|
|
32065
|
+
events = events.slice(0, limit);
|
|
32066
|
+
return toResult({
|
|
32067
|
+
events,
|
|
32068
|
+
count: events.length,
|
|
32069
|
+
active: ws.getStatus().filter((s) => s.active),
|
|
32070
|
+
tsIso: (/* @__PURE__ */ new Date()).toISOString()
|
|
32071
|
+
});
|
|
32072
|
+
} catch (e) {
|
|
32073
|
+
return toError(e);
|
|
32074
|
+
}
|
|
32075
|
+
}
|
|
32076
|
+
);
|
|
32077
|
+
server.tool(
|
|
32078
|
+
"okx_ws_status",
|
|
32079
|
+
"## \u529F\u80FD\uFF1A\u67E5\u770B\u5F53\u524D\u6240\u6709 WebSocket \u8BA2\u9605\u72B6\u6001\u53CA\u7F13\u51B2\u533A\u4E8B\u4EF6\u6570\u91CF\n## \u573A\u666F\uFF1AAgent \u67E5\u770B\u8BA2\u9605\u5217\u8868\u3001\u7F13\u51B2\u533A\u79EF\u538B\u60C5\u51B5\n## \u5173\u952E\u8BCD\uFF1A\u72B6\u6001, status, \u8BA2\u9605\u5217\u8868, \u7F13\u51B2\u533A, \u8FDE\u63A5\n## \u53C2\u6570\uFF1A\u65E0\n## \u9274\u6743\uFF1APUBLIC\n## \u98CE\u9669\uFF1AREAD \u2014 \u53EA\u8BFB\n## \u8FD4\u56DE\u91CF\uFF1A\u5FAE\u5C0F ~500B\n## \u5173\u8054\uFF1Aokx_ws_subscribe \u2192 \u672C\u5DE5\u5177 \u2192 okx_ws_close \u5173\u95ED",
|
|
32080
|
+
{},
|
|
32081
|
+
async () => {
|
|
32082
|
+
try {
|
|
32083
|
+
const ws = getOrCreateWs();
|
|
32084
|
+
return toResult({
|
|
32085
|
+
subscriptions: ws.getStatus(),
|
|
32086
|
+
totalBuffered: ws.countAllBuffered(),
|
|
32087
|
+
tsIso: (/* @__PURE__ */ new Date()).toISOString()
|
|
32088
|
+
});
|
|
32089
|
+
} catch (e) {
|
|
32090
|
+
return toError(e);
|
|
32091
|
+
}
|
|
32092
|
+
}
|
|
32093
|
+
);
|
|
32094
|
+
server.tool(
|
|
32095
|
+
"okx_ws_close",
|
|
32096
|
+
"## \u529F\u80FD\uFF1A\u5173\u95ED\u6307\u5B9A\u6216\u6240\u6709 WebSocket \u8BA2\u9605\uFF0C\u91CA\u653E\u8FDE\u63A5\u8D44\u6E90\n## \u573A\u666F\uFF1AAgent \u5B8C\u6210\u76D1\u63A7\u540E\u6E05\u7406\n## \u5173\u952E\u8BCD\uFF1A\u5173\u95ED, close, \u53D6\u6D88\u8BA2\u9605, \u65AD\u5F00, \u505C\u6B62\n## \u53C2\u6570\uFF1A\n## - subscriptionId: \u8981\u5173\u95ED\u7684\u8BA2\u9605ID\uFF08\u4E0D\u4F20\u5173\u95ED\u6240\u6709\uFF09\n## \u9274\u6743\uFF1APUBLIC\n## \u98CE\u9669\uFF1AWRITE \u2014 \u4F1A\u65AD\u5F00\u8FDE\u63A5\uFF0C\u4F46\u65E0\u8D44\u91D1\u98CE\u9669\n## \u8FD4\u56DE\u91CF\uFF1A\u5FAE\u5C0F ~200B\n## \u5173\u8054\uFF1Aokx_ws_status \u2192 \u672C\u5DE5\u5177\u5173\u95ED",
|
|
32097
|
+
{
|
|
32098
|
+
subscriptionId: external_exports.string().optional().describe("\u8BA2\u9605ID\uFF0C\u4E0D\u4F20\u5173\u95ED\u6240\u6709")
|
|
32099
|
+
},
|
|
32100
|
+
async ({ subscriptionId }) => {
|
|
32101
|
+
try {
|
|
32102
|
+
const ws = getOrCreateWs();
|
|
32103
|
+
const closed = ws.close(subscriptionId);
|
|
32104
|
+
return toResult({
|
|
32105
|
+
closed,
|
|
32106
|
+
tsIso: (/* @__PURE__ */ new Date()).toISOString()
|
|
32107
|
+
});
|
|
32108
|
+
} catch (e) {
|
|
32109
|
+
return toError(e);
|
|
32110
|
+
}
|
|
32111
|
+
}
|
|
32112
|
+
);
|
|
32113
|
+
}
|
|
32114
|
+
|
|
31831
32115
|
// src/adapters/agent-hub.ts
|
|
32116
|
+
init_wrapper();
|
|
32117
|
+
var MAX_ROOM_MESSAGES = 200;
|
|
31832
32118
|
var AgentHub = class {
|
|
31833
32119
|
wss = null;
|
|
31834
32120
|
agents = /* @__PURE__ */ new Map();
|
|
31835
32121
|
tasks = /* @__PURE__ */ new Map();
|
|
32122
|
+
rooms = /* @__PURE__ */ new Map();
|
|
31836
32123
|
heartbeatTimer = null;
|
|
32124
|
+
version = "0.0.0";
|
|
31837
32125
|
// ── 启动 ──
|
|
31838
|
-
start(port, host = "0.0.0.0") {
|
|
32126
|
+
start(port, host = "0.0.0.0", version2 = "0.0.0") {
|
|
32127
|
+
this.version = version2;
|
|
31839
32128
|
this.wss = new import_websocket_server.default({ port, host });
|
|
31840
|
-
console.log(`[AgentHub] WS Server started on ws://${host}:${port}`);
|
|
32129
|
+
console.log(`[AgentHub] WS Server v${version2} started on ws://${host}:${port}`);
|
|
32130
|
+
this.ensureRoom("#lobby");
|
|
32131
|
+
this.ensureRoom("#review");
|
|
31841
32132
|
this.wss.on("connection", (ws) => {
|
|
31842
32133
|
let agentId = null;
|
|
31843
32134
|
ws.on("message", (raw) => {
|
|
@@ -31849,19 +32140,7 @@ var AgentHub = class {
|
|
|
31849
32140
|
}
|
|
31850
32141
|
});
|
|
31851
32142
|
ws.on("close", () => {
|
|
31852
|
-
if (agentId)
|
|
31853
|
-
const info = this.agents.get(agentId);
|
|
31854
|
-
console.log(`[AgentHub] Agent \u79BB\u7EBF: ${agentId} (${info?.name || "?"})`);
|
|
31855
|
-
this.agents.delete(agentId);
|
|
31856
|
-
for (const [tid, t] of this.tasks) {
|
|
31857
|
-
if (t.assignedTo === agentId && t.status === "assigned") {
|
|
31858
|
-
t.status = "unassigned";
|
|
31859
|
-
t.assignedTo = void 0;
|
|
31860
|
-
t.claimedAt = void 0;
|
|
31861
|
-
this.broadcast({ type: "task:released", taskId: tid, reason: "Agent \u79BB\u7EBF" });
|
|
31862
|
-
}
|
|
31863
|
-
}
|
|
31864
|
-
}
|
|
32143
|
+
if (agentId) this.handleDisconnect(agentId);
|
|
31865
32144
|
});
|
|
31866
32145
|
ws.on("error", () => {
|
|
31867
32146
|
});
|
|
@@ -31892,6 +32171,19 @@ var AgentHub = class {
|
|
|
31892
32171
|
case "task:done":
|
|
31893
32172
|
this.handleDone(msg);
|
|
31894
32173
|
break;
|
|
32174
|
+
// ── Room ──
|
|
32175
|
+
case "room:join":
|
|
32176
|
+
this.handleRoomJoin(authAgentId, msg);
|
|
32177
|
+
break;
|
|
32178
|
+
case "room:leave":
|
|
32179
|
+
this.handleRoomLeave(authAgentId, msg);
|
|
32180
|
+
break;
|
|
32181
|
+
case "room:message":
|
|
32182
|
+
this.handleRoomMessage(authAgentId, msg);
|
|
32183
|
+
break;
|
|
32184
|
+
case "room:history":
|
|
32185
|
+
this.handleRoomHistory(ws, msg);
|
|
32186
|
+
break;
|
|
31895
32187
|
default:
|
|
31896
32188
|
this.send(ws, { type: "error", message: `\u672A\u77E5\u6D88\u606F\u7C7B\u578B: ${msg.type}` });
|
|
31897
32189
|
}
|
|
@@ -31915,13 +32207,25 @@ var AgentHub = class {
|
|
|
31915
32207
|
status: "idle",
|
|
31916
32208
|
lastSeen: Date.now()
|
|
31917
32209
|
});
|
|
32210
|
+
this.joinRoom(agentId, "#lobby");
|
|
31918
32211
|
console.log(`[AgentHub] Agent \u6CE8\u518C: ${agentId} (${name}) skills: [${capabilities.join(", ")}]`);
|
|
31919
32212
|
this.send(ws, {
|
|
31920
32213
|
type: "agent:registered",
|
|
31921
32214
|
agentId,
|
|
32215
|
+
currentVersion: this.version,
|
|
31922
32216
|
message: `\u5DF2\u6CE8\u518C\u3002\u53EF\u7528\u4EFB\u52A1: ${this.getUnassignedTasks().join(", ") || "\u65E0"}`,
|
|
31923
32217
|
pendingTasks: this.getUnassignedTasks()
|
|
31924
32218
|
});
|
|
32219
|
+
const agentVersion = String(msg.version || "");
|
|
32220
|
+
if (agentVersion && agentVersion !== this.version) {
|
|
32221
|
+
this.send(ws, {
|
|
32222
|
+
type: "agent:upgrade",
|
|
32223
|
+
current: this.version,
|
|
32224
|
+
yourVersion: agentVersion,
|
|
32225
|
+
message: `hvip MCP \u5DF2\u5347\u7EA7\u5230 v${this.version}\uFF0C\u4F60\u5F53\u524D v${agentVersion}\u3002\u8BF7 git pull && npm run build \u540E\u91CD\u8FDE\u3002`
|
|
32226
|
+
});
|
|
32227
|
+
this.sendToRoom("#lobby", "system", `${agentId} \u7248\u672C\u8FC7\u65E7 (v${agentVersion})\uFF0C\u5DF2\u63D0\u9192\u5347\u7EA7\u5230 v${this.version}`);
|
|
32228
|
+
}
|
|
31925
32229
|
if (capabilities.length > 0) {
|
|
31926
32230
|
for (const tid of this.getUnassignedTasks()) {
|
|
31927
32231
|
if (capabilities.includes(tid)) {
|
|
@@ -31930,6 +32234,30 @@ var AgentHub = class {
|
|
|
31930
32234
|
}
|
|
31931
32235
|
}
|
|
31932
32236
|
}
|
|
32237
|
+
handleDisconnect(agentId) {
|
|
32238
|
+
const info = this.agents.get(agentId);
|
|
32239
|
+
console.log(`[AgentHub] Agent \u79BB\u7EBF: ${agentId} (${info?.name || "?"})`);
|
|
32240
|
+
for (const [, room] of this.rooms) {
|
|
32241
|
+
if (room.members.has(agentId)) {
|
|
32242
|
+
room.members.delete(agentId);
|
|
32243
|
+
this.sendToRoomMembers(room, {
|
|
32244
|
+
type: "room:member_left",
|
|
32245
|
+
roomId: agentId,
|
|
32246
|
+
// fixed below
|
|
32247
|
+
agentId
|
|
32248
|
+
});
|
|
32249
|
+
}
|
|
32250
|
+
}
|
|
32251
|
+
this.agents.delete(agentId);
|
|
32252
|
+
for (const [tid, t] of this.tasks) {
|
|
32253
|
+
if (t.assignedTo === agentId && t.status === "assigned") {
|
|
32254
|
+
t.status = "unassigned";
|
|
32255
|
+
t.assignedTo = void 0;
|
|
32256
|
+
t.claimedAt = void 0;
|
|
32257
|
+
this.broadcast({ type: "task:released", taskId: tid, reason: "Agent \u79BB\u7EBF" });
|
|
32258
|
+
}
|
|
32259
|
+
}
|
|
32260
|
+
}
|
|
31933
32261
|
// ── Agent 心跳 ──
|
|
31934
32262
|
handleAgentStatus(agentId) {
|
|
31935
32263
|
const a = this.agents.get(agentId);
|
|
@@ -31956,6 +32284,7 @@ var AgentHub = class {
|
|
|
31956
32284
|
task.claimedAt = Date.now();
|
|
31957
32285
|
const a = this.agents.get(agentId);
|
|
31958
32286
|
if (a) a.status = "working";
|
|
32287
|
+
this.joinRoom(agentId, `#task-${taskId}`);
|
|
31959
32288
|
console.log(`[AgentHub] ${agentId} \u8BA4\u9886 ${taskId}`);
|
|
31960
32289
|
this.sendTo(agentId, {
|
|
31961
32290
|
type: "task:assigned",
|
|
@@ -31982,6 +32311,8 @@ var AgentHub = class {
|
|
|
31982
32311
|
const a = this.agents.get(agentId);
|
|
31983
32312
|
if (a) a.status = "idle";
|
|
31984
32313
|
console.log(`[AgentHub] ${agentId} \u5B8C\u6210 ${taskId}: ${result}`);
|
|
32314
|
+
this.sendToRoom(`#task-${taskId}`, agentId, `\u5DF2\u5B8C\u6210 ${taskId}: ${result} (branch: ${branch})\uFF0C\u7B49\u5F85\u5BA1\u6838\u3002`);
|
|
32315
|
+
this.sendToRoom("#review", agentId, `${taskId} \u63D0\u4EA4\u5B8C\u6210\uFF0Cbranch: ${branch}`);
|
|
31985
32316
|
this.broadcast({
|
|
31986
32317
|
type: "task:completed",
|
|
31987
32318
|
taskId,
|
|
@@ -31991,7 +32322,7 @@ var AgentHub = class {
|
|
|
31991
32322
|
message: `${agentId} \u5DF2\u5B8C\u6210 ${taskId}\uFF0C\u7B49\u5F85\u5BA1\u6838`
|
|
31992
32323
|
});
|
|
31993
32324
|
}
|
|
31994
|
-
// ──
|
|
32325
|
+
// ── 派发任务 ──
|
|
31995
32326
|
dispatchTaskTo(taskId, agentId) {
|
|
31996
32327
|
if (!this.tasks.has(taskId)) {
|
|
31997
32328
|
this.tasks.set(taskId, { status: "unassigned" });
|
|
@@ -32005,7 +32336,7 @@ var AgentHub = class {
|
|
|
32005
32336
|
url: `https://github.com/okx-wallet-H/hvip-mcp/blob/master/tasks/${taskId}.md`
|
|
32006
32337
|
});
|
|
32007
32338
|
}
|
|
32008
|
-
// ── 审核 ──
|
|
32339
|
+
// ── 审核 + 自动通知房间 ──
|
|
32009
32340
|
reviewTask(taskId, verdict, feedback) {
|
|
32010
32341
|
const task = this.tasks.get(taskId);
|
|
32011
32342
|
if (!task) return;
|
|
@@ -32016,10 +32347,101 @@ var AgentHub = class {
|
|
|
32016
32347
|
task.assignedTo = void 0;
|
|
32017
32348
|
task.claimedAt = void 0;
|
|
32018
32349
|
}
|
|
32350
|
+
const roomId = `#task-${taskId}`;
|
|
32351
|
+
const msg = verdict === "approved" ? `\u2705 ${taskId} \u5BA1\u6838\u901A\u8FC7\u3002\u5DF2\u5408\u5E76\u5230 master \u5E76\u5220\u9664\u8FDC\u7A0B\u5206\u652F\u3002` : `\u274C ${taskId} \u5BA1\u6838\u4E0D\u901A\u8FC7\u3002${feedback || "\u8BF7\u4FEE\u6539\u540E\u91CD\u65B0 push\u3002"}`;
|
|
32352
|
+
this.sendToRoom(roomId, "reviewer", msg);
|
|
32353
|
+
this.sendToRoom("#review", "reviewer", `${taskId}: ${verdict}`);
|
|
32019
32354
|
if (task.assignedTo) {
|
|
32020
32355
|
this.sendTo(task.assignedTo, { type: "task:review", taskId, verdict, feedback });
|
|
32021
32356
|
}
|
|
32022
32357
|
}
|
|
32358
|
+
// ══════════════════════════════════════════════════════════════════════
|
|
32359
|
+
// Room 操作
|
|
32360
|
+
// ══════════════════════════════════════════════════════════════════════
|
|
32361
|
+
ensureRoom(roomId) {
|
|
32362
|
+
let room = this.rooms.get(roomId);
|
|
32363
|
+
if (!room) {
|
|
32364
|
+
room = { messages: [], members: /* @__PURE__ */ new Set() };
|
|
32365
|
+
this.rooms.set(roomId, room);
|
|
32366
|
+
}
|
|
32367
|
+
return room;
|
|
32368
|
+
}
|
|
32369
|
+
joinRoom(agentId, roomId) {
|
|
32370
|
+
const room = this.ensureRoom(roomId);
|
|
32371
|
+
if (room.members.has(agentId)) return;
|
|
32372
|
+
room.members.add(agentId);
|
|
32373
|
+
const a = this.agents.get(agentId);
|
|
32374
|
+
if (a) {
|
|
32375
|
+
this.send(a.ws, {
|
|
32376
|
+
type: "room:joined",
|
|
32377
|
+
roomId,
|
|
32378
|
+
members: [...room.members],
|
|
32379
|
+
recentMessages: room.messages.slice(-5)
|
|
32380
|
+
});
|
|
32381
|
+
}
|
|
32382
|
+
this.sendToRoomMembers(room, { type: "room:member_joined", roomId, agentId });
|
|
32383
|
+
console.log(`[AgentHub] ${agentId} \u2192 ${roomId}`);
|
|
32384
|
+
}
|
|
32385
|
+
leaveRoom(agentId, roomId) {
|
|
32386
|
+
const room = this.rooms.get(roomId);
|
|
32387
|
+
if (!room) return;
|
|
32388
|
+
room.members.delete(agentId);
|
|
32389
|
+
this.sendToRoomMembers(room, { type: "room:member_left", roomId, agentId });
|
|
32390
|
+
if (roomId !== "#lobby" && roomId !== "#review" && room.members.size === 0) {
|
|
32391
|
+
this.rooms.delete(roomId);
|
|
32392
|
+
}
|
|
32393
|
+
}
|
|
32394
|
+
sendToRoom(roomId, from, text) {
|
|
32395
|
+
const room = this.ensureRoom(roomId);
|
|
32396
|
+
const msg = { roomId, from, text, ts: (/* @__PURE__ */ new Date()).toISOString() };
|
|
32397
|
+
room.messages.push(msg);
|
|
32398
|
+
if (room.messages.length > MAX_ROOM_MESSAGES) room.messages.shift();
|
|
32399
|
+
const raw = JSON.stringify({ type: "room:message", ...msg });
|
|
32400
|
+
for (const agentId of room.members) {
|
|
32401
|
+
const a = this.agents.get(agentId);
|
|
32402
|
+
if (a && a.ws.readyState === import_websocket.default.OPEN) a.ws.send(raw);
|
|
32403
|
+
}
|
|
32404
|
+
}
|
|
32405
|
+
getRoomHistory(roomId, limit = 50) {
|
|
32406
|
+
const room = this.rooms.get(roomId);
|
|
32407
|
+
if (!room) return [];
|
|
32408
|
+
return room.messages.slice(-limit);
|
|
32409
|
+
}
|
|
32410
|
+
getRooms() {
|
|
32411
|
+
return [...this.rooms.entries()].map(([id, r]) => ({
|
|
32412
|
+
roomId: id,
|
|
32413
|
+
members: [...r.members],
|
|
32414
|
+
messageCount: r.messages.length
|
|
32415
|
+
}));
|
|
32416
|
+
}
|
|
32417
|
+
// ── Room message handlers ────────────────────────────────────────────
|
|
32418
|
+
handleRoomJoin(agentId, msg) {
|
|
32419
|
+
if (!agentId) return;
|
|
32420
|
+
this.joinRoom(agentId, String(msg.roomId || ""));
|
|
32421
|
+
}
|
|
32422
|
+
handleRoomLeave(agentId, msg) {
|
|
32423
|
+
if (!agentId) return;
|
|
32424
|
+
this.leaveRoom(agentId, String(msg.roomId || ""));
|
|
32425
|
+
}
|
|
32426
|
+
handleRoomMessage(agentId, msg) {
|
|
32427
|
+
if (!agentId) return;
|
|
32428
|
+
const roomId = String(msg.roomId || "");
|
|
32429
|
+
const text = String(msg.text || "");
|
|
32430
|
+
if (!roomId || !text) return;
|
|
32431
|
+
this.sendToRoom(roomId, agentId, text);
|
|
32432
|
+
}
|
|
32433
|
+
handleRoomHistory(ws, msg) {
|
|
32434
|
+
const roomId = String(msg.roomId || "");
|
|
32435
|
+
const limit = Number(msg.limit) || 50;
|
|
32436
|
+
this.send(ws, { type: "room:history", roomId, messages: this.getRoomHistory(roomId, limit) });
|
|
32437
|
+
}
|
|
32438
|
+
sendToRoomMembers(room, msg) {
|
|
32439
|
+
const raw = JSON.stringify(msg);
|
|
32440
|
+
for (const agentId of room.members) {
|
|
32441
|
+
const a = this.agents.get(agentId);
|
|
32442
|
+
if (a && a.ws.readyState === import_websocket.default.OPEN) a.ws.send(raw);
|
|
32443
|
+
}
|
|
32444
|
+
}
|
|
32023
32445
|
// ── 链上事件桥接 ──
|
|
32024
32446
|
bridgeChainEvent(event) {
|
|
32025
32447
|
this.broadcast({ type: "chain:event", data: event, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
|
|
@@ -32070,7 +32492,8 @@ var AgentHub = class {
|
|
|
32070
32492
|
result: t.result,
|
|
32071
32493
|
branch: t.branch
|
|
32072
32494
|
}));
|
|
32073
|
-
|
|
32495
|
+
const rooms = this.getRooms();
|
|
32496
|
+
return { agents, tasks, rooms, agentCount: agents.length, taskCount: tasks.length };
|
|
32074
32497
|
}
|
|
32075
32498
|
// ── 关闭 ──
|
|
32076
32499
|
close() {
|
|
@@ -32081,18 +32504,19 @@ var AgentHub = class {
|
|
|
32081
32504
|
this.wss?.close();
|
|
32082
32505
|
this.agents.clear();
|
|
32083
32506
|
this.tasks.clear();
|
|
32507
|
+
this.rooms.clear();
|
|
32084
32508
|
}
|
|
32085
32509
|
};
|
|
32086
32510
|
var agentHub = new AgentHub();
|
|
32087
|
-
function startAgentHub(port, host = "0.0.0.0") {
|
|
32088
|
-
agentHub.start(port, host);
|
|
32511
|
+
function startAgentHub(port, host = "0.0.0.0", version2 = "0.0.0") {
|
|
32512
|
+
agentHub.start(port, host, version2);
|
|
32089
32513
|
}
|
|
32090
32514
|
|
|
32091
32515
|
// src/tools/agent-hub.ts
|
|
32092
32516
|
function registerAgentHubTools(server) {
|
|
32093
32517
|
server.tool(
|
|
32094
32518
|
"agent_hub_status",
|
|
32095
|
-
"## \u529F\u80FD\uFF1A\u67E5\u770B Agent Hub \u5168\u666F\uFF1A\u6240\u6709\u5728\u7EBF Agent\u3001\u4EFB\u52A1\u5206\u914D\
|
|
32519
|
+
"## \u529F\u80FD\uFF1A\u67E5\u770B Agent Hub \u5168\u666F\uFF1A\u6240\u6709\u5728\u7EBF Agent\u3001\u4EFB\u52A1\u5206\u914D\u3001\u623F\u95F4\u6D88\u606F\n## \u573A\u666F\uFF1A\u7528\u4E8E\u5DE1\u68C0 Agent \u96C6\u7FA4\u5065\u5EB7\u72B6\u51B5\u3001\u4E86\u89E3\u54EA\u4E9B\u4EFB\u52A1\u5728\u63A8\u8FDB\u3001\u54EA\u4E2A Agent \u7A7A\u95F2\u53EF\u6D3E\u6D3B\n## \u5173\u952E\u8BCD\uFF1AAgent Hub, \u96C6\u7FA4\u72B6\u6001, \u4EFB\u52A1\u8FDB\u5EA6, \u5728\u7EBFAgent, \u8C03\u5EA6\u9762\u677F, \u623F\u95F4\n## \u53C2\u6570\uFF1A\u65E0\n## \u9274\u6743\uFF1APUBLIC \u2014 Agent Hub \u5185\u90E8\u63A5\u53E3\n## \u98CE\u9669\uFF1AREAD \u2014 \u53EA\u8BFB\u72B6\u6001\u67E5\u8BE2\n## \u8FD4\u56DE\u91CF\uFF1A\u5FAE\u5C0F ~2KB\n## \u5173\u8054\uFF1A\u672C\u5DE5\u5177\u67E5\u770B\u5168\u5C40 \u2192 agent_hub_dispatch \u6D3E\u53D1\u4EFB\u52A1 \u2192 agent_room_send \u53D1\u6D88\u606F",
|
|
32096
32520
|
{},
|
|
32097
32521
|
async () => {
|
|
32098
32522
|
try {
|
|
@@ -32104,7 +32528,7 @@ function registerAgentHubTools(server) {
|
|
|
32104
32528
|
);
|
|
32105
32529
|
server.tool(
|
|
32106
32530
|
"agent_hub_dispatch",
|
|
32107
|
-
"## \u529F\u80FD\uFF1A\u5411\u6307\u5B9A Agent \u6216\u5168\u4F53\u5728\u7EBF Agent \u6D3E\u53D1\u4EFB\u52A1\n## \u573A\u666F\uFF1A\u7528\u4E8E\u624B\u52A8\u5C06\u4EFB\u52A1\u6C60\u4E2D\u7684\u5DE5\u5355\u5206\u53D1\u7ED9\u7A7A\u95F2 Agent\u3001\u8865\u5145\u81EA\u52A8\u6D3E\u53D1\u672A\u8986\u76D6\u7684\u4EFB\u52A1\n## \u5173\u952E\u8BCD\uFF1A\u6D3E\u53D1, dispatch, \u4EFB\u52A1\u5206\u914D, \u8C03\u5EA6, assign\n## \u53C2\u6570\uFF1A\n## - taskId: \u4EFB\u52A1\u7F16\u53F7\
|
|
32531
|
+
"## \u529F\u80FD\uFF1A\u5411\u6307\u5B9A Agent \u6216\u5168\u4F53\u5728\u7EBF Agent \u6D3E\u53D1\u4EFB\u52A1\n## \u573A\u666F\uFF1A\u7528\u4E8E\u624B\u52A8\u5C06\u4EFB\u52A1\u6C60\u4E2D\u7684\u5DE5\u5355\u5206\u53D1\u7ED9\u7A7A\u95F2 Agent\u3001\u8865\u5145\u81EA\u52A8\u6D3E\u53D1\u672A\u8986\u76D6\u7684\u4EFB\u52A1\n## \u5173\u952E\u8BCD\uFF1A\u6D3E\u53D1, dispatch, \u4EFB\u52A1\u5206\u914D, \u8C03\u5EA6, assign\n## \u53C2\u6570\uFF1A\n## - taskId: \u4EFB\u52A1\u7F16\u53F7\n## - agentId: \u76EE\u6807 Agent ID\uFF08\u9009\u586B\uFF0C\u4E0D\u586B\u5219\u627E\u7B2C\u4E00\u4E2A\u5339\u914D\u7684\uFF09\n## \u9274\u6743\uFF1APUBLIC \u2014 \u8C03\u5EA6\u63A7\u5236\u63A5\u53E3\n## \u98CE\u9669\uFF1AREAD \u2014 \u53EA\u6D3E\u53D1\u6D88\u606F\uFF0C\u4E0D\u4FEE\u6539\u4EE3\u7801\n## \u8FD4\u56DE\u91CF\uFF1A\u5FAE\u5C0F ~200B\n## \u5173\u8054\uFF1Aagent_hub_status \u67E5\u770B Agent \u72B6\u6001 \u2192 \u672C\u5DE5\u5177\u6D3E\u53D1 \u2192 Agent \u6536\u5230 task:dispatch",
|
|
32108
32532
|
{
|
|
32109
32533
|
taskId: external_exports.enum(["T-001", "T-002", "T-003", "T-004", "T-005", "T-006"]).describe("\u4EFB\u52A1\u7F16\u53F7"),
|
|
32110
32534
|
agentId: external_exports.string().optional().describe("\u76EE\u6807 Agent ID\u3002\u4E0D\u586B\u5219\u81EA\u52A8\u5339\u914D\u6709\u5BF9\u5E94\u6280\u80FD\u7684 Agent")
|
|
@@ -32155,7 +32579,7 @@ function registerAgentHubTools(server) {
|
|
|
32155
32579
|
);
|
|
32156
32580
|
server.tool(
|
|
32157
32581
|
"agent_hub_review",
|
|
32158
|
-
"## \u529F\u80FD\uFF1A\u5BA1\u6838 Agent \u63D0\u4EA4\u7684\u4EFB\u52A1\u7ED3\u679C\uFF0C\u901A\u8FC7/\u9A73\u56DE\n## \u573A\u666F\uFF1A\
|
|
32582
|
+
"## \u529F\u80FD\uFF1A\u5BA1\u6838 Agent \u63D0\u4EA4\u7684\u4EFB\u52A1\u7ED3\u679C\uFF0C\u901A\u8FC7/\u9A73\u56DE\uFF0C\u81EA\u52A8\u901A\u77E5\u5BF9\u5E94\u4EFB\u52A1\u623F\u95F4\n## \u573A\u666F\uFF1A\u5BA1\u6838\u5458\u5BA1\u5B8C\u4EE3\u7801\u540E\u53D1\u7ED3\u679C\uFF0CAgent \u5728\u623F\u95F4\u5B9E\u65F6\u6536\u5230\u53CD\u9988\n## \u5173\u952E\u8BCD\uFF1A\u5BA1\u6838, review, \u6279\u51C6, \u9A73\u56DE, approve, reject, \u623F\u95F4\u901A\u77E5\n## \u53C2\u6570\uFF1A\n## - taskId: \u4EFB\u52A1\u7F16\u53F7\n## - verdict: \u5BA1\u6838\u7ED3\u679C\u3002approved=\u901A\u8FC7, rejected=\u9A73\u56DE\n## - feedback: \u5BA1\u6838\u610F\u89C1\uFF08\u9A73\u56DE\u65F6\u5FC5\u586B\uFF09\n## \u9274\u6743\uFF1APUBLIC \u2014 \u5BA1\u6838\u63A7\u5236\u63A5\u53E3\n## \u98CE\u9669\uFF1AREAD \u2014 \u53D1\u6D88\u606F\u901A\u77E5\uFF0C\u4EE3\u7801\u7684\u5408\u5E76\u7531\u5B9A\u65F6\u4EFB\u52A1\u6267\u884C\n## \u8FD4\u56DE\u91CF\uFF1A\u5FAE\u5C0F ~200B\n## \u5173\u8054\uFF1A\u5BA1\u6838\u4E0D\u901A\u8FC7 \u2192 agent_room_send \u53D1\u623F\u95F4\u6D88\u606F \u2192 Agent \u6539\u4EE3\u7801",
|
|
32159
32583
|
{
|
|
32160
32584
|
taskId: external_exports.enum(["T-001", "T-002", "T-003", "T-004", "T-005", "T-006"]).describe("\u4EFB\u52A1\u7F16\u53F7"),
|
|
32161
32585
|
verdict: external_exports.enum(["approved", "rejected"]).describe("\u5BA1\u6838\u7ED3\u679C"),
|
|
@@ -32177,7 +32601,59 @@ function registerAgentHubTools(server) {
|
|
|
32177
32601
|
taskId,
|
|
32178
32602
|
verdict,
|
|
32179
32603
|
feedback: feedback || (verdict === "approved" ? "\u2705 \u901A\u8FC7" : "\u274C \u9A73\u56DE"),
|
|
32180
|
-
|
|
32604
|
+
roomNotice: `\u5BA1\u6838\u7ED3\u679C\u5DF2\u63A8\u9001\u5230 #task-${taskId} \u623F\u95F4`,
|
|
32605
|
+
next: verdict === "approved" ? `\u4EFB\u52A1\u5B8C\u6210\u3002` : `\u4EFB\u52A1\u9000\u56DE\u3002Agent \u5728 #task-${taskId} \u623F\u95F4\u67E5\u770B\u53CD\u9988\u3002`
|
|
32606
|
+
});
|
|
32607
|
+
} catch (e) {
|
|
32608
|
+
return toError(e);
|
|
32609
|
+
}
|
|
32610
|
+
}
|
|
32611
|
+
);
|
|
32612
|
+
server.tool(
|
|
32613
|
+
"agent_room_send",
|
|
32614
|
+
"## \u529F\u80FD\uFF1A\u5411\u6307\u5B9A\u623F\u95F4\u53D1\u9001\u6D88\u606F\uFF0C\u6240\u6709\u623F\u95F4\u6210\u5458\u5B9E\u65F6\u6536\u5230\n## \u573A\u666F\uFF1A\u5BA1\u6838\u5458\u7ED9 Agent \u53D1\u53CD\u9988\u3001\u5728\u4EFB\u52A1\u623F\u95F4\u534F\u8C03\u3001\u5411\u6240\u6709\u4EBA\u5E7F\u64AD\n## \u5173\u952E\u8BCD\uFF1A\u623F\u95F4\u6D88\u606F, room, \u53D1\u9001, \u901A\u77E5, \u5E7F\u64AD\n## \u53C2\u6570\uFF1A\n## - roomId: \u623F\u95F4ID\u3002#lobby / #review / #task-T-XXX\n## - text: \u6D88\u606F\u5185\u5BB9\n## \u9274\u6743\uFF1APUBLIC\n## \u98CE\u9669\uFF1AREAD \u2014 \u53EA\u53D1\u6D88\u606F\n## \u8FD4\u56DE\u91CF\uFF1A\u5FAE\u5C0F ~200B\n## \u5173\u8054\uFF1A\u5BA1\u6838\u4E0D\u901A\u8FC7 \u2192 \u672C\u5DE5\u5177\u53D1 #task-T-XXX \u2192 Agent \u6536\u5230",
|
|
32615
|
+
{
|
|
32616
|
+
roomId: external_exports.string().describe("\u623F\u95F4ID\u3002#lobby / #review / #task-T-003"),
|
|
32617
|
+
text: external_exports.string().describe("\u6D88\u606F\u5185\u5BB9")
|
|
32618
|
+
},
|
|
32619
|
+
async ({ roomId, text }) => {
|
|
32620
|
+
try {
|
|
32621
|
+
agentHub.sendToRoom(roomId, "reviewer", text);
|
|
32622
|
+
return toResult({
|
|
32623
|
+
sent: true,
|
|
32624
|
+
roomId,
|
|
32625
|
+
text,
|
|
32626
|
+
tsIso: (/* @__PURE__ */ new Date()).toISOString()
|
|
32627
|
+
});
|
|
32628
|
+
} catch (e) {
|
|
32629
|
+
return toError(e);
|
|
32630
|
+
}
|
|
32631
|
+
}
|
|
32632
|
+
);
|
|
32633
|
+
server.tool(
|
|
32634
|
+
"agent_room_view",
|
|
32635
|
+
"## \u529F\u80FD\uFF1A\u67E5\u770B\u623F\u95F4\u5217\u8868\u6216\u6307\u5B9A\u623F\u95F4\u7684\u6D88\u606F\u5386\u53F2\n## \u573A\u666F\uFF1A\u68C0\u67E5\u54EA\u4E9B\u623F\u95F4\u6D3B\u8DC3\u3001\u8BFB\u53D6\u5386\u53F2\u6D88\u606F\u3001\u770B\u8C01\u5728\u623F\u95F4\u91CC\n## \u5173\u952E\u8BCD\uFF1A\u623F\u95F4, room, \u6D88\u606F\u5386\u53F2, \u5728\u7EBF\u6210\u5458\n## \u53C2\u6570\uFF1A\n## - roomId: \u623F\u95F4ID\uFF08\u9009\u586B\uFF0C\u4E0D\u586B\u5217\u51FA\u6240\u6709\u623F\u95F4\uFF09\n## - limit: \u6D88\u606F\u6761\u6570\uFF0C\u9ED8\u8BA4 30\n## \u9274\u6743\uFF1APUBLIC\n## \u98CE\u9669\uFF1AREAD \u2014 \u53EA\u8BFB\n## \u8FD4\u56DE\u91CF\uFF1A\u5FAE\u5C0F ~3KB\n## \u5173\u8054\uFF1Aagent_room_send \u53D1\u6D88\u606F \u2192 \u672C\u5DE5\u5177\u67E5\u770B\u5386\u53F2",
|
|
32636
|
+
{
|
|
32637
|
+
roomId: external_exports.string().optional().describe("\u623F\u95F4ID\uFF0C\u4E0D\u586B\u5217\u51FA\u6240\u6709"),
|
|
32638
|
+
limit: external_exports.number().int().min(1).max(200).optional().describe("\u6D88\u606F\u6761\u6570\uFF0C\u9ED8\u8BA430")
|
|
32639
|
+
},
|
|
32640
|
+
async ({ roomId, limit }) => {
|
|
32641
|
+
try {
|
|
32642
|
+
if (roomId) {
|
|
32643
|
+
const msgs = agentHub.getRoomHistory(roomId, limit || 30);
|
|
32644
|
+
return toResult({
|
|
32645
|
+
roomId,
|
|
32646
|
+
messageCount: msgs.length,
|
|
32647
|
+
messages: msgs,
|
|
32648
|
+
tsIso: (/* @__PURE__ */ new Date()).toISOString()
|
|
32649
|
+
});
|
|
32650
|
+
}
|
|
32651
|
+
const rooms = agentHub.getRooms();
|
|
32652
|
+
return toResult({
|
|
32653
|
+
rooms,
|
|
32654
|
+
count: rooms.length,
|
|
32655
|
+
hint: "\u4F20 roomId \u67E5\u770B\u5177\u4F53\u623F\u95F4\u6D88\u606F\u3002frequent: #lobby #review #task-T-003",
|
|
32656
|
+
tsIso: (/* @__PURE__ */ new Date()).toISOString()
|
|
32181
32657
|
});
|
|
32182
32658
|
} catch (e) {
|
|
32183
32659
|
return toError(e);
|
|
@@ -32188,9 +32664,10 @@ function registerAgentHubTools(server) {
|
|
|
32188
32664
|
|
|
32189
32665
|
// src/index.ts
|
|
32190
32666
|
async function main() {
|
|
32667
|
+
const VERSION = "0.2.43";
|
|
32191
32668
|
const server = new McpServer({
|
|
32192
32669
|
name: "hvip-mcp",
|
|
32193
|
-
version: "0.2.
|
|
32670
|
+
version: "0.2.43",
|
|
32194
32671
|
description: "hvip MCP Server \u2014 304 \u5DE5\u5177\u8986\u76D6 97.7% OKX REST API\uFF0C\u542B\u4EA4\u6613/\u884C\u60C5/\u8D44\u91D1/\u7B56\u7565/\u9884\u6D4B\u5E02\u573A\uFF08\u975E OKX \u5B98\u65B9\u4EA7\u54C1\uFF09\u3002\u4ED3\u5E93: https://github.com/okx-wallet-H/hvip-mcp"
|
|
32195
32672
|
});
|
|
32196
32673
|
const auth = getAuth();
|
|
@@ -32213,8 +32690,9 @@ async function main() {
|
|
|
32213
32690
|
registerRfqTools(server, auth);
|
|
32214
32691
|
registerAgentUtils(server, auth);
|
|
32215
32692
|
registerXLayerWSTools(server);
|
|
32693
|
+
registerWsTools(server);
|
|
32216
32694
|
registerAgentHubTools(server);
|
|
32217
|
-
startAgentHub(parseInt(process.env.WS_AGENT_PORT || "9321"));
|
|
32695
|
+
startAgentHub(parseInt(process.env.WS_AGENT_PORT || "9321"), "0.0.0.0", VERSION);
|
|
32218
32696
|
const transport = new StdioServerTransport();
|
|
32219
32697
|
await server.connect(transport);
|
|
32220
32698
|
}
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hvip-mcp-server",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.43",
|
|
4
4
|
"description": "hvip MCP Server — 304 工具覆盖 97.7% OKX REST API,含交易/行情/资金/策略/预测市场(非 OKX 官方产品)",
|
|
5
|
-
"homepage": "https://hvip
|
|
5
|
+
"homepage": "https://github.com/okx-wallet-H/hvip-mcp",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
8
8
|
"url": "https://github.com/okx-wallet-H/hvip-mcp"
|