hvip-mcp-server 0.4.3 → 0.5.0
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/dist/hub-server.js +1097 -109
- package/dist/hub-worker.js +96 -21
- package/dist/index.js +257 -49
- package/package.json +7 -2
package/dist/index.js
CHANGED
|
@@ -4805,11 +4805,11 @@ var require_core = __commonJS({
|
|
|
4805
4805
|
Ajv2.ValidationError = validation_error_1.default;
|
|
4806
4806
|
Ajv2.MissingRefError = ref_error_1.default;
|
|
4807
4807
|
exports2.default = Ajv2;
|
|
4808
|
-
function checkOptions(checkOpts, options, msg,
|
|
4808
|
+
function checkOptions(checkOpts, options, msg, log2 = "error") {
|
|
4809
4809
|
for (const key in checkOpts) {
|
|
4810
4810
|
const opt = key;
|
|
4811
4811
|
if (opt in options)
|
|
4812
|
-
this.logger[
|
|
4812
|
+
this.logger[log2](`${msg}: option ${key}. ${checkOpts[opt]}`);
|
|
4813
4813
|
}
|
|
4814
4814
|
}
|
|
4815
4815
|
function getSchEnv(keyRef) {
|
|
@@ -4856,13 +4856,13 @@ var require_core = __commonJS({
|
|
|
4856
4856
|
}, warn() {
|
|
4857
4857
|
}, error() {
|
|
4858
4858
|
} };
|
|
4859
|
-
function getLogger(
|
|
4860
|
-
if (
|
|
4859
|
+
function getLogger(logger2) {
|
|
4860
|
+
if (logger2 === false)
|
|
4861
4861
|
return noLogs;
|
|
4862
|
-
if (
|
|
4862
|
+
if (logger2 === void 0)
|
|
4863
4863
|
return console;
|
|
4864
|
-
if (
|
|
4865
|
-
return
|
|
4864
|
+
if (logger2.log && logger2.warn && logger2.error)
|
|
4865
|
+
return logger2;
|
|
4866
4866
|
throw new Error("logger must implement log, warn and error methods");
|
|
4867
4867
|
}
|
|
4868
4868
|
var KEYWORD_NAME = /^[a-z_$][a-z0-9_$:-]*$/i;
|
|
@@ -23859,8 +23859,8 @@ var Server = class extends Protocol {
|
|
|
23859
23859
|
this._loggingLevels = /* @__PURE__ */ new Map();
|
|
23860
23860
|
this.LOG_LEVEL_SEVERITY = new Map(LoggingLevelSchema.options.map((level, index) => [level, index]));
|
|
23861
23861
|
this.isMessageIgnored = (level, sessionId) => {
|
|
23862
|
-
const
|
|
23863
|
-
return
|
|
23862
|
+
const currentLevel2 = this._loggingLevels.get(sessionId);
|
|
23863
|
+
return currentLevel2 ? this.LOG_LEVEL_SEVERITY.get(level) < this.LOG_LEVEL_SEVERITY.get(currentLevel2) : false;
|
|
23864
23864
|
};
|
|
23865
23865
|
this._capabilities = options?.capabilities ?? {};
|
|
23866
23866
|
this._instructions = options?.instructions;
|
|
@@ -37555,8 +37555,57 @@ function registerWsTools(server, auth) {
|
|
|
37555
37555
|
);
|
|
37556
37556
|
}
|
|
37557
37557
|
|
|
37558
|
+
// src/utils/logger.ts
|
|
37559
|
+
var LEVEL_EMOJI = {
|
|
37560
|
+
[0 /* DEBUG */]: "\u{1F50D}",
|
|
37561
|
+
[1 /* INFO */]: "",
|
|
37562
|
+
[2 /* WARN */]: "\u26A0\uFE0F",
|
|
37563
|
+
[3 /* ERROR */]: "\u274C",
|
|
37564
|
+
[4 /* SILENT */]: ""
|
|
37565
|
+
};
|
|
37566
|
+
function resolveLevel() {
|
|
37567
|
+
const raw = (process.env.LOG_LEVEL || "").toUpperCase();
|
|
37568
|
+
if (raw === "DEBUG") return 0 /* DEBUG */;
|
|
37569
|
+
if (raw === "WARN" || raw === "WARNING") return 2 /* WARN */;
|
|
37570
|
+
if (raw === "ERROR") return 3 /* ERROR */;
|
|
37571
|
+
if (raw === "SILENT" || raw === "OFF") return 4 /* SILENT */;
|
|
37572
|
+
return 1 /* INFO */;
|
|
37573
|
+
}
|
|
37574
|
+
var currentLevel = resolveLevel();
|
|
37575
|
+
var LoggerImpl = class {
|
|
37576
|
+
constructor(tag) {
|
|
37577
|
+
this.tag = tag;
|
|
37578
|
+
}
|
|
37579
|
+
tag;
|
|
37580
|
+
debug(msg) {
|
|
37581
|
+
this.write(0 /* DEBUG */, msg);
|
|
37582
|
+
}
|
|
37583
|
+
info(msg) {
|
|
37584
|
+
this.write(1 /* INFO */, msg);
|
|
37585
|
+
}
|
|
37586
|
+
warn(msg) {
|
|
37587
|
+
this.write(2 /* WARN */, msg);
|
|
37588
|
+
}
|
|
37589
|
+
error(msg) {
|
|
37590
|
+
this.write(3 /* ERROR */, msg);
|
|
37591
|
+
}
|
|
37592
|
+
write(level, msg) {
|
|
37593
|
+
if (level < currentLevel) return;
|
|
37594
|
+
const ts = (/* @__PURE__ */ new Date()).toISOString().slice(11, 23);
|
|
37595
|
+
const emoji2 = LEVEL_EMOJI[level];
|
|
37596
|
+
const tag = this.tag ? `[${this.tag}]` : "";
|
|
37597
|
+
const prefix = emoji2 ? `${emoji2} ${tag}` : tag;
|
|
37598
|
+
process.stderr.write(`${ts} ${prefix} ${msg}
|
|
37599
|
+
`);
|
|
37600
|
+
}
|
|
37601
|
+
};
|
|
37602
|
+
function logger(tag) {
|
|
37603
|
+
return new LoggerImpl(tag);
|
|
37604
|
+
}
|
|
37605
|
+
|
|
37558
37606
|
// src/adapters/agent-hub.ts
|
|
37559
37607
|
var MAX_ROOM_MESSAGES = 200;
|
|
37608
|
+
var log = logger("AgentHub");
|
|
37560
37609
|
var AgentHub = class {
|
|
37561
37610
|
wss = null;
|
|
37562
37611
|
agents = /* @__PURE__ */ new Map();
|
|
@@ -37568,21 +37617,39 @@ var AgentHub = class {
|
|
|
37568
37617
|
db = null;
|
|
37569
37618
|
token = "";
|
|
37570
37619
|
// PSK 鉴权令牌
|
|
37620
|
+
costTracker = null;
|
|
37621
|
+
// HubCosts 实例
|
|
37571
37622
|
// ── 持久化绑定 ──
|
|
37623
|
+
setCostTracker(ct) {
|
|
37624
|
+
this.costTracker = ct;
|
|
37625
|
+
}
|
|
37572
37626
|
setDB(db) {
|
|
37573
37627
|
this.db = db;
|
|
37574
37628
|
const rows = db.loadTasks();
|
|
37629
|
+
let orphanCount = 0;
|
|
37575
37630
|
for (const r of rows) {
|
|
37576
|
-
this.
|
|
37577
|
-
|
|
37578
|
-
|
|
37579
|
-
|
|
37580
|
-
|
|
37581
|
-
|
|
37582
|
-
|
|
37631
|
+
if (r.status === "assigned" && r.assignedTo && !this.agents.has(r.assignedTo)) {
|
|
37632
|
+
this.tasks.set(r.taskId, {
|
|
37633
|
+
status: "unassigned",
|
|
37634
|
+
assignedTo: void 0,
|
|
37635
|
+
claimedAt: void 0,
|
|
37636
|
+
result: r.result || void 0,
|
|
37637
|
+
branch: r.branch || void 0
|
|
37638
|
+
});
|
|
37639
|
+
db.saveTask({ taskId: r.taskId, status: "unassigned" });
|
|
37640
|
+
orphanCount++;
|
|
37641
|
+
} else {
|
|
37642
|
+
this.tasks.set(r.taskId, {
|
|
37643
|
+
status: r.status,
|
|
37644
|
+
assignedTo: r.assignedTo || void 0,
|
|
37645
|
+
claimedAt: r.claimedAt || void 0,
|
|
37646
|
+
result: r.result || void 0,
|
|
37647
|
+
branch: r.branch || void 0
|
|
37648
|
+
});
|
|
37649
|
+
}
|
|
37583
37650
|
}
|
|
37584
37651
|
if (rows.length > 0) {
|
|
37585
|
-
|
|
37652
|
+
log.info(`\u4ECE DB \u6062\u590D ${rows.length} \u4E2A\u4EFB\u52A1` + (orphanCount > 0 ? `\uFF0C\u91CA\u653E ${orphanCount} \u4E2A\u5B64\u513F\u4EFB\u52A1` : ""));
|
|
37586
37653
|
}
|
|
37587
37654
|
}
|
|
37588
37655
|
// ── 启动 ──
|
|
@@ -37623,12 +37690,10 @@ var AgentHub = class {
|
|
|
37623
37690
|
return ok === true ? true : false;
|
|
37624
37691
|
}).then((ok) => {
|
|
37625
37692
|
if (!ok) {
|
|
37626
|
-
|
|
37627
|
-
`);
|
|
37693
|
+
log.warn(`WS Hub \u8DF3\u8FC7\uFF08\u7AEF\u53E3 ${ports.join("/")} \u4E0D\u53EF\u7528\uFF09`);
|
|
37628
37694
|
return;
|
|
37629
37695
|
}
|
|
37630
|
-
|
|
37631
|
-
`);
|
|
37696
|
+
log.info(`WS Hub v${version2} ws://${host}:${this.port}`);
|
|
37632
37697
|
this.setupHub();
|
|
37633
37698
|
});
|
|
37634
37699
|
}
|
|
@@ -37660,17 +37725,17 @@ var AgentHub = class {
|
|
|
37660
37725
|
if (agentId) this.handleDisconnect(agentId);
|
|
37661
37726
|
});
|
|
37662
37727
|
ws.on("error", (e) => {
|
|
37663
|
-
|
|
37664
|
-
`);
|
|
37728
|
+
log.error(`WS \u9519\u8BEF: ${e.message}`);
|
|
37665
37729
|
});
|
|
37666
37730
|
});
|
|
37667
37731
|
this.heartbeatTimer = setInterval(() => {
|
|
37668
37732
|
const now = Date.now();
|
|
37669
37733
|
for (const [id, a] of this.agents) {
|
|
37734
|
+
if (id.startsWith("term-") || id.startsWith("dashboard")) continue;
|
|
37670
37735
|
if (now - a.lastSeen > 12e4) {
|
|
37671
37736
|
a.ws.close();
|
|
37672
37737
|
this.agents.delete(id);
|
|
37673
|
-
|
|
37738
|
+
log.warn("Agent \u5FC3\u8DF3\u8D85\u65F6: " + id);
|
|
37674
37739
|
}
|
|
37675
37740
|
}
|
|
37676
37741
|
}, 3e4);
|
|
@@ -37686,9 +37751,29 @@ var AgentHub = class {
|
|
|
37686
37751
|
case "task:claim":
|
|
37687
37752
|
this.handleClaim(msg);
|
|
37688
37753
|
break;
|
|
37754
|
+
case "task:progress":
|
|
37755
|
+
this.broadcast(msg);
|
|
37756
|
+
break;
|
|
37757
|
+
// 流式文本转发
|
|
37758
|
+
case "task:tool":
|
|
37759
|
+
this.broadcast(msg);
|
|
37760
|
+
break;
|
|
37761
|
+
// 工具调用转发
|
|
37689
37762
|
case "task:done":
|
|
37690
37763
|
this.handleDone(msg);
|
|
37691
37764
|
break;
|
|
37765
|
+
case "task:assign":
|
|
37766
|
+
this.handleAssign(msg);
|
|
37767
|
+
break;
|
|
37768
|
+
// Chronos AI 调度指令
|
|
37769
|
+
case "task:unassign":
|
|
37770
|
+
this.handleUnassign(msg);
|
|
37771
|
+
break;
|
|
37772
|
+
// Chronos 释放卡住任务
|
|
37773
|
+
case "task:reject":
|
|
37774
|
+
this.handleReject(msg);
|
|
37775
|
+
break;
|
|
37776
|
+
// Worker 忙时拒绝任务
|
|
37692
37777
|
// ── Room ──
|
|
37693
37778
|
case "room:join":
|
|
37694
37779
|
this.handleRoomJoin(authAgentId, msg);
|
|
@@ -37727,7 +37812,7 @@ var AgentHub = class {
|
|
|
37727
37812
|
lastSeen: Date.now()
|
|
37728
37813
|
});
|
|
37729
37814
|
this.joinRoom(agentId, "#lobby");
|
|
37730
|
-
|
|
37815
|
+
log.info(`Agent \u6CE8\u518C: ${agentId} (${name}) skills: [${capabilities.join(", ")}]`);
|
|
37731
37816
|
this.send(ws, {
|
|
37732
37817
|
type: "agent:registered",
|
|
37733
37818
|
agentId,
|
|
@@ -37735,6 +37820,13 @@ var AgentHub = class {
|
|
|
37735
37820
|
message: `\u5DF2\u6CE8\u518C\u3002\u53EF\u7528\u4EFB\u52A1: ${this.getUnassignedTasks().join(", ") || "\u65E0"}`,
|
|
37736
37821
|
pendingTasks: this.getUnassignedTasks()
|
|
37737
37822
|
});
|
|
37823
|
+
this.broadcast({
|
|
37824
|
+
type: "agent:update",
|
|
37825
|
+
agentId,
|
|
37826
|
+
name,
|
|
37827
|
+
capabilities,
|
|
37828
|
+
status: "idle"
|
|
37829
|
+
});
|
|
37738
37830
|
const agentVersion = String(msg.version || "");
|
|
37739
37831
|
if (agentVersion && agentVersion !== this.version) {
|
|
37740
37832
|
this.send(ws, {
|
|
@@ -37756,7 +37848,8 @@ var AgentHub = class {
|
|
|
37756
37848
|
}
|
|
37757
37849
|
handleDisconnect(agentId) {
|
|
37758
37850
|
const info = this.agents.get(agentId);
|
|
37759
|
-
|
|
37851
|
+
log.info(`Agent \u79BB\u7EBF: ${agentId} (${info?.name || "?"})`);
|
|
37852
|
+
this.broadcast({ type: "agent:offline", agentId });
|
|
37760
37853
|
for (const [roomId, room] of this.rooms) {
|
|
37761
37854
|
if (room.members.has(agentId)) {
|
|
37762
37855
|
room.members.delete(agentId);
|
|
@@ -37796,8 +37889,12 @@ var AgentHub = class {
|
|
|
37796
37889
|
return;
|
|
37797
37890
|
}
|
|
37798
37891
|
if (task.status === "assigned" && task.assignedTo !== agentId) {
|
|
37799
|
-
|
|
37800
|
-
|
|
37892
|
+
const assignedWorker = task.assignedTo ? this.agents.get(task.assignedTo) : null;
|
|
37893
|
+
if (assignedWorker) {
|
|
37894
|
+
this.sendTo(agentId, { type: "error", message: `\u4EFB\u52A1 ${taskId} \u5DF2\u88AB ${task.assignedTo} \u8BA4\u9886` });
|
|
37895
|
+
return;
|
|
37896
|
+
}
|
|
37897
|
+
log.info(`${agentId} \u63A5\u7BA1\u5B64\u513F\u4EFB\u52A1 ${taskId}\uFF08\u539F ${task.assignedTo} \u5DF2\u79BB\u7EBF\uFF09`);
|
|
37801
37898
|
}
|
|
37802
37899
|
task.status = "assigned";
|
|
37803
37900
|
task.assignedTo = agentId;
|
|
@@ -37805,7 +37902,7 @@ var AgentHub = class {
|
|
|
37805
37902
|
const a = this.agents.get(agentId);
|
|
37806
37903
|
if (a) a.status = "working";
|
|
37807
37904
|
this.joinRoom(agentId, `#task-${taskId}`);
|
|
37808
|
-
|
|
37905
|
+
log.info(`${agentId} \u8BA4\u9886 ${taskId}`);
|
|
37809
37906
|
this.db?.saveTask({ taskId, status: "assigned", title: this.getTaskTitle(taskId), assignedTo: agentId, claimedAt: task.claimedAt });
|
|
37810
37907
|
this.sendTo(agentId, {
|
|
37811
37908
|
type: "task:assigned",
|
|
@@ -37821,18 +37918,44 @@ var AgentHub = class {
|
|
|
37821
37918
|
const agentId = String(msg.agentId || "");
|
|
37822
37919
|
const result = String(msg.result || "");
|
|
37823
37920
|
const branch = String(msg.branch || "");
|
|
37921
|
+
const error2 = msg.error ? String(msg.error) : "";
|
|
37922
|
+
const usage = msg.usage;
|
|
37923
|
+
const steps = Number(msg.steps || 0);
|
|
37924
|
+
if (this.costTracker && usage?.inputTokens) {
|
|
37925
|
+
this.costTracker.record({
|
|
37926
|
+
agentId,
|
|
37927
|
+
taskId,
|
|
37928
|
+
model: usage.model || "claude-sonnet-4-6",
|
|
37929
|
+
inputTokens: usage.inputTokens || 0,
|
|
37930
|
+
outputTokens: usage.outputTokens || 0,
|
|
37931
|
+
purpose: "task"
|
|
37932
|
+
});
|
|
37933
|
+
}
|
|
37824
37934
|
const task = this.tasks.get(taskId);
|
|
37825
37935
|
if (!task) {
|
|
37826
37936
|
this.sendTo(agentId, { type: "error", message: `\u4EFB\u52A1 ${taskId} \u4E0D\u5B58\u5728` });
|
|
37827
37937
|
return;
|
|
37828
37938
|
}
|
|
37939
|
+
if (error2 || /^❌|^执行失败/i.test(result)) {
|
|
37940
|
+
task.status = "unassigned";
|
|
37941
|
+
task.assignedTo = void 0;
|
|
37942
|
+
task.claimedAt = void 0;
|
|
37943
|
+
const a2 = this.agents.get(agentId);
|
|
37944
|
+
if (a2) a2.status = "idle";
|
|
37945
|
+
this.db?.saveTask({ taskId, status: "unassigned" });
|
|
37946
|
+
log.info(`\u4EFB\u52A1\u6267\u884C\u5931\u8D25\uFF0C\u91CA\u653E\u91CD\u8BD5: ${taskId} \u2014 ${error2 || result.slice(0, 80)}`);
|
|
37947
|
+
this.broadcast({ type: "agent:update", agentId, status: "idle" });
|
|
37948
|
+
this.broadcast({ type: "task:released", taskId, reason: `\u6267\u884C\u5931\u8D25: ${error2 || result.slice(0, 60)}` });
|
|
37949
|
+
return;
|
|
37950
|
+
}
|
|
37829
37951
|
task.status = "done";
|
|
37830
37952
|
task.result = result;
|
|
37831
37953
|
task.branch = branch;
|
|
37832
37954
|
const a = this.agents.get(agentId);
|
|
37833
37955
|
if (a) a.status = "idle";
|
|
37834
|
-
|
|
37956
|
+
log.info(`${agentId} \u5B8C\u6210 ${taskId}: ${result}`);
|
|
37835
37957
|
this.db?.saveTask({ taskId, status: "done", title: this.getTaskTitle(taskId), assignedTo: agentId, result, branch });
|
|
37958
|
+
this.broadcast({ type: "agent:update", agentId, status: "idle" });
|
|
37836
37959
|
this.sendToRoom(`#task-${taskId}`, agentId, `\u5DF2\u5B8C\u6210 ${taskId}: ${result} (branch: ${branch})\uFF0C\u7B49\u5F85\u5BA1\u6838\u3002`);
|
|
37837
37960
|
this.sendToRoom("#review", agentId, `${taskId} \u63D0\u4EA4\u5B8C\u6210\uFF0Cbranch: ${branch}`);
|
|
37838
37961
|
this.broadcast({
|
|
@@ -37844,41 +37967,125 @@ var AgentHub = class {
|
|
|
37844
37967
|
message: `${agentId} \u5DF2\u5B8C\u6210 ${taskId}\uFF0C\u7B49\u5F85\u5BA1\u6838`
|
|
37845
37968
|
});
|
|
37846
37969
|
}
|
|
37970
|
+
// ── Chronos 释放卡住任务 ──
|
|
37971
|
+
handleUnassign(msg) {
|
|
37972
|
+
const taskId = String(msg.taskId || "");
|
|
37973
|
+
const reason = String(msg.reason || "Chronos \u5DE1\u68C0\u91CA\u653E");
|
|
37974
|
+
const task = this.tasks.get(taskId);
|
|
37975
|
+
if (!task) {
|
|
37976
|
+
log.warn(`Chronos \u91CA\u653E\u5931\u8D25: \u4EFB\u52A1 ${taskId} \u4E0D\u5B58\u5728`);
|
|
37977
|
+
return;
|
|
37978
|
+
}
|
|
37979
|
+
if (task.status !== "assigned") {
|
|
37980
|
+
return;
|
|
37981
|
+
}
|
|
37982
|
+
const oldAgentId = task.assignedTo;
|
|
37983
|
+
task.status = "unassigned";
|
|
37984
|
+
task.assignedTo = void 0;
|
|
37985
|
+
task.claimedAt = void 0;
|
|
37986
|
+
if (oldAgentId) {
|
|
37987
|
+
const oldWorker = this.agents.get(oldAgentId);
|
|
37988
|
+
if (oldWorker && oldWorker.status === "working") {
|
|
37989
|
+
oldWorker.status = "idle";
|
|
37990
|
+
}
|
|
37991
|
+
}
|
|
37992
|
+
this.db?.saveTask({ taskId, status: "unassigned" });
|
|
37993
|
+
log.warn(`Chronos \u91CA\u653E\u5361\u4F4F\u4EFB\u52A1: ${taskId} (\u539F ${oldAgentId || "?"}) \u2014 ${reason}`);
|
|
37994
|
+
this.broadcast({
|
|
37995
|
+
type: "task:released",
|
|
37996
|
+
taskId,
|
|
37997
|
+
reason: `Chronos \u91CA\u653E: ${reason}`
|
|
37998
|
+
});
|
|
37999
|
+
}
|
|
38000
|
+
// ── Worker 拒绝任务(忙碌)──
|
|
38001
|
+
handleReject(msg) {
|
|
38002
|
+
const taskId = String(msg.taskId || "");
|
|
38003
|
+
const agentId = String(msg.agentId || "");
|
|
38004
|
+
const reason = String(msg.reason || "Worker busy");
|
|
38005
|
+
const task = this.tasks.get(taskId);
|
|
38006
|
+
if (!task) return;
|
|
38007
|
+
if (task.status !== "assigned") return;
|
|
38008
|
+
task.status = "unassigned";
|
|
38009
|
+
task.assignedTo = void 0;
|
|
38010
|
+
task.claimedAt = void 0;
|
|
38011
|
+
const a = this.agents.get(agentId);
|
|
38012
|
+
if (a && a.status === "working") a.status = "idle";
|
|
38013
|
+
this.db?.saveTask({ taskId, status: "unassigned" });
|
|
38014
|
+
log.info(`\u4EFB\u52A1\u88AB\u62D2\u7EDD: ${taskId} by ${agentId} \u2014 ${reason}`);
|
|
38015
|
+
this.broadcast({ type: "task:released", taskId, reason: `Worker \u62D2\u7EDD: ${reason}` });
|
|
38016
|
+
}
|
|
37847
38017
|
// ── 注册任务(自动派发给空闲 Agent) ──
|
|
37848
|
-
|
|
38018
|
+
/** 检查是否有空闲的 WS Worker(非 dashboard、非 CLI spawn) */
|
|
38019
|
+
hasIdleWorker() {
|
|
38020
|
+
for (const [id, a] of this.agents) {
|
|
38021
|
+
if (a.status === "idle" && !id.startsWith("dashboard") && !id.startsWith("term-")) {
|
|
38022
|
+
return true;
|
|
38023
|
+
}
|
|
38024
|
+
}
|
|
38025
|
+
return false;
|
|
38026
|
+
}
|
|
38027
|
+
registerTask(taskId, title, promptB64) {
|
|
37849
38028
|
if (!this.tasks.has(taskId)) {
|
|
37850
38029
|
this.tasks.set(taskId, { status: "unassigned" });
|
|
37851
38030
|
}
|
|
37852
|
-
|
|
37853
|
-
|
|
37854
|
-
|
|
37855
|
-
}
|
|
37856
|
-
console.log(`[AgentHub] \u4EFB\u52A1\u6CE8\u518C: ${taskId} "${title || taskId}"`);
|
|
38031
|
+
const task = this.tasks.get(taskId);
|
|
38032
|
+
if (title) task.title = title;
|
|
38033
|
+
if (promptB64) task.promptB64 = promptB64;
|
|
38034
|
+
log.info(`\u4EFB\u52A1\u6CE8\u518C: ${taskId} "${title || taskId}"`);
|
|
37857
38035
|
this.broadcast({ type: "task:announced", taskId, title: title || taskId });
|
|
37858
|
-
const
|
|
38036
|
+
const hasChronos = [...this.agents.values()].some(
|
|
38037
|
+
(a) => a.agentId === "chronos-dispatcher" && a.status !== "offline"
|
|
38038
|
+
);
|
|
38039
|
+
if (hasChronos) {
|
|
38040
|
+
log.info(`Chronos \u5728\u7EBF\uFF0C\u4EFB\u52A1 ${taskId} \u7B49\u5F85 AI \u8C03\u5EA6`);
|
|
38041
|
+
return;
|
|
38042
|
+
}
|
|
38043
|
+
const idleAgents = [...this.agents.entries()].filter(([, a]) => a.status === "idle" && !a.agentId.startsWith("dashboard") && !a.agentId.startsWith("term-"));
|
|
37859
38044
|
if (idleAgents.length === 0) {
|
|
37860
|
-
|
|
38045
|
+
log.warn(`\u6CA1\u6709\u7A7A\u95F2 Agent\uFF0C\u4EFB\u52A1 ${taskId} \u7B49\u5F85\u624B\u52A8 spawn`);
|
|
37861
38046
|
return;
|
|
37862
38047
|
}
|
|
37863
38048
|
const match = idleAgents.find(([, a]) => a.capabilities.includes(taskId)) || idleAgents[0];
|
|
37864
38049
|
if (match) {
|
|
37865
|
-
|
|
37866
|
-
this.dispatchTaskTo(taskId, match[0]);
|
|
38050
|
+
log.info(`\u81EA\u52A8\u6D3E\u53D1 ${taskId} \u2192 ${match[1].name} (${match[0]})`);
|
|
38051
|
+
this.dispatchTaskTo(taskId, match[0], promptB64);
|
|
37867
38052
|
}
|
|
37868
38053
|
}
|
|
37869
38054
|
// ── 派发任务 ──
|
|
37870
|
-
dispatchTaskTo(taskId, agentId) {
|
|
38055
|
+
dispatchTaskTo(taskId, agentId, promptB64) {
|
|
37871
38056
|
if (!this.tasks.has(taskId)) {
|
|
37872
38057
|
this.tasks.set(taskId, { status: "unassigned" });
|
|
37873
38058
|
}
|
|
37874
38059
|
const task = this.tasks.get(taskId);
|
|
37875
38060
|
if (task.status === "assigned") return;
|
|
37876
|
-
|
|
38061
|
+
const msg = {
|
|
37877
38062
|
type: "task:dispatch",
|
|
37878
38063
|
taskId,
|
|
37879
|
-
title: this.getTaskTitle(taskId)
|
|
37880
|
-
|
|
37881
|
-
|
|
38064
|
+
title: this.getTaskTitle(taskId)
|
|
38065
|
+
};
|
|
38066
|
+
if (promptB64) msg.promptB64 = promptB64;
|
|
38067
|
+
else if (task.promptB64) msg.promptB64 = task.promptB64;
|
|
38068
|
+
this.sendTo(agentId, msg);
|
|
38069
|
+
}
|
|
38070
|
+
// ── Chronos 调度指令 ──
|
|
38071
|
+
handleAssign(msg) {
|
|
38072
|
+
const taskId = String(msg.taskId || "");
|
|
38073
|
+
const targetAgentId = String(msg.agentId || "");
|
|
38074
|
+
const assignedBy = String(msg.assignedBy || "chronos");
|
|
38075
|
+
if (!taskId || !targetAgentId) return;
|
|
38076
|
+
const targetWorker = this.agents.get(targetAgentId);
|
|
38077
|
+
if (!targetWorker) {
|
|
38078
|
+
log.warn(`Chronos \u6307\u6D3E\u5931\u8D25: Worker ${targetAgentId} \u4E0D\u5728\u7EBF`);
|
|
38079
|
+
return;
|
|
38080
|
+
}
|
|
38081
|
+
if (targetWorker.status !== "idle") {
|
|
38082
|
+
log.warn(`Chronos \u6307\u6D3E\u5931\u8D25: Worker ${targetAgentId} \u5FD9\u788C\u4E2D`);
|
|
38083
|
+
return;
|
|
38084
|
+
}
|
|
38085
|
+
log.info(`Chronos \u8C03\u5EA6: ${taskId} \u2192 ${targetWorker.name}`);
|
|
38086
|
+
const task = this.tasks.get(taskId);
|
|
38087
|
+
const promptB64 = task?.promptB64;
|
|
38088
|
+
this.dispatchTaskTo(taskId, targetAgentId, promptB64);
|
|
37882
38089
|
}
|
|
37883
38090
|
// ── 审核 + 自动通知房间 ──
|
|
37884
38091
|
reviewTask(taskId, verdict, feedback) {
|
|
@@ -37926,7 +38133,7 @@ var AgentHub = class {
|
|
|
37926
38133
|
});
|
|
37927
38134
|
}
|
|
37928
38135
|
this.sendToRoomMembers(room, { type: "room:member_joined", roomId, agentId });
|
|
37929
|
-
|
|
38136
|
+
log.info(`${agentId} \u2192 ${roomId}`);
|
|
37930
38137
|
}
|
|
37931
38138
|
leaveRoom(agentId, roomId) {
|
|
37932
38139
|
const room = this.rooms.get(roomId);
|
|
@@ -38732,10 +38939,11 @@ function registerAllTools(server, auth, readOnly) {
|
|
|
38732
38939
|
return { skipped, skipLog };
|
|
38733
38940
|
}
|
|
38734
38941
|
async function startHttp(server, version2, auth, readOnly, skipped) {
|
|
38735
|
-
|
|
38942
|
+
let port = parseInt(process.env.PORT || "3000", 10);
|
|
38736
38943
|
if (!Number.isInteger(port) || port < 1 || port > 65535) {
|
|
38737
38944
|
process.stderr.write(`[hvip] \u274C \u65E0\u6548\u7AEF\u53E3: ${process.env.PORT}\uFF0C\u4F7F\u7528\u9ED8\u8BA4 3000
|
|
38738
38945
|
`);
|
|
38946
|
+
port = 3e3;
|
|
38739
38947
|
}
|
|
38740
38948
|
const host = process.env.HOST || "127.0.0.1";
|
|
38741
38949
|
const token = process.env.MCP_AUTH_TOKEN || "";
|
|
@@ -38863,12 +39071,12 @@ async function startStdio(server, version2, auth, readOnly, skipped, skipLog) {
|
|
|
38863
39071
|
}
|
|
38864
39072
|
const wsHost = process.env.WS_BIND_HOST || "127.0.0.1";
|
|
38865
39073
|
const wsToken = process.env.HUB_AUTH_TOKEN || "";
|
|
38866
|
-
startAgentHub(parseInt(process.env.WS_AGENT_PORT || "9321"), wsHost, version2, wsToken);
|
|
39074
|
+
startAgentHub(parseInt(process.env.WS_AGENT_PORT || "9321", 10), wsHost, version2, wsToken);
|
|
38867
39075
|
const transport = new StdioServerTransport();
|
|
38868
39076
|
await server.connect(transport);
|
|
38869
39077
|
}
|
|
38870
39078
|
async function main() {
|
|
38871
|
-
const VERSION = "0.3
|
|
39079
|
+
const VERSION = "0.4.3";
|
|
38872
39080
|
const argv = process.argv.slice(2);
|
|
38873
39081
|
if (argv.includes("--help") || argv.includes("-h")) printHelpAndExit(VERSION);
|
|
38874
39082
|
if (argv.includes("--version") || argv.includes("-v")) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hvip-mcp-server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "hvip MCP Server — 365 工具覆盖 97.7% OKX REST API,含交易/行情/资金/策略/预测市场/技术指标/Smart Money(非 OKX 官方产品)",
|
|
5
5
|
"homepage": "https://github.com/okx-wallet-H/hvip-mcp",
|
|
6
6
|
"repository": {
|
|
@@ -45,10 +45,15 @@
|
|
|
45
45
|
"typecheck": "tsc --noEmit"
|
|
46
46
|
},
|
|
47
47
|
"dependencies": {
|
|
48
|
+
"@ai-sdk/anthropic": "^3.0.85",
|
|
49
|
+
"@ai-sdk/deepseek": "^2.0.39",
|
|
50
|
+
"@ai-sdk/openai": "^3.0.73",
|
|
51
|
+
"@anthropic-ai/sdk": "^0.105.0",
|
|
48
52
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
53
|
+
"ai": "^6.0.208",
|
|
49
54
|
"dotenv": "^16.4.0",
|
|
50
55
|
"ws": "^8.21.0",
|
|
51
|
-
"zod": "^3.
|
|
56
|
+
"zod": "^3.25.76"
|
|
52
57
|
},
|
|
53
58
|
"devDependencies": {
|
|
54
59
|
"@types/node": "^22.0.0",
|