hvip-mcp-server 0.4.3 → 0.6.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/README.md +165 -165
- package/dist/hub-server.js +1433 -115
- package/dist/hub-worker.js +97 -22
- package/dist/index.js +495 -62
- package/package.json +76 -68
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, log4 = "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[log4](`${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;
|
|
@@ -10980,10 +10980,94 @@ var require_websocket_server = __commonJS({
|
|
|
10980
10980
|
);
|
|
10981
10981
|
})();
|
|
10982
10982
|
|
|
10983
|
+
// src/dns-fix.ts
|
|
10984
|
+
var import_node_dns = __toESM(require("node:dns"));
|
|
10985
|
+
|
|
10986
|
+
// src/utils/logger.ts
|
|
10987
|
+
var LEVEL_EMOJI = {
|
|
10988
|
+
[0 /* DEBUG */]: "\u{1F50D}",
|
|
10989
|
+
[1 /* INFO */]: "\u2139\uFE0F",
|
|
10990
|
+
[2 /* WARN */]: "\u26A0\uFE0F",
|
|
10991
|
+
[3 /* ERROR */]: "\u274C",
|
|
10992
|
+
[4 /* SILENT */]: ""
|
|
10993
|
+
};
|
|
10994
|
+
function resolveLevel() {
|
|
10995
|
+
const raw = (process.env.LOG_LEVEL || "").toUpperCase();
|
|
10996
|
+
if (raw === "DEBUG") return 0 /* DEBUG */;
|
|
10997
|
+
if (raw === "WARN" || raw === "WARNING") return 2 /* WARN */;
|
|
10998
|
+
if (raw === "ERROR") return 3 /* ERROR */;
|
|
10999
|
+
if (raw === "SILENT" || raw === "OFF") return 4 /* SILENT */;
|
|
11000
|
+
return 1 /* INFO */;
|
|
11001
|
+
}
|
|
11002
|
+
var currentLevel = resolveLevel();
|
|
11003
|
+
var LoggerImpl = class {
|
|
11004
|
+
constructor(tag) {
|
|
11005
|
+
this.tag = tag;
|
|
11006
|
+
}
|
|
11007
|
+
tag;
|
|
11008
|
+
debug(msg) {
|
|
11009
|
+
this.write(0 /* DEBUG */, msg);
|
|
11010
|
+
}
|
|
11011
|
+
info(msg) {
|
|
11012
|
+
this.write(1 /* INFO */, msg);
|
|
11013
|
+
}
|
|
11014
|
+
warn(msg) {
|
|
11015
|
+
this.write(2 /* WARN */, msg);
|
|
11016
|
+
}
|
|
11017
|
+
error(msg) {
|
|
11018
|
+
this.write(3 /* ERROR */, msg);
|
|
11019
|
+
}
|
|
11020
|
+
write(level, msg) {
|
|
11021
|
+
if (level < currentLevel) return;
|
|
11022
|
+
const ts = (/* @__PURE__ */ new Date()).toISOString().slice(11, 23);
|
|
11023
|
+
const emoji2 = LEVEL_EMOJI[level];
|
|
11024
|
+
const tag = this.tag ? `[${this.tag}]` : "";
|
|
11025
|
+
const prefix = emoji2 ? `${emoji2} ${tag}` : tag;
|
|
11026
|
+
process.stderr.write(`${ts} ${prefix} ${msg}
|
|
11027
|
+
`);
|
|
11028
|
+
}
|
|
11029
|
+
};
|
|
11030
|
+
function logger(tag) {
|
|
11031
|
+
return new LoggerImpl(tag);
|
|
11032
|
+
}
|
|
11033
|
+
|
|
11034
|
+
// src/dns-fix.ts
|
|
11035
|
+
var log = logger("dns-fix");
|
|
11036
|
+
var FALLBACK_DNS = ["8.8.8.8", "1.1.1.1", "8.8.4.4"];
|
|
11037
|
+
function checkAndFixDns() {
|
|
11038
|
+
try {
|
|
11039
|
+
const servers = import_node_dns.default.getServers();
|
|
11040
|
+
if (servers.some((s) => FALLBACK_DNS.includes(s))) {
|
|
11041
|
+
return;
|
|
11042
|
+
}
|
|
11043
|
+
const hasLocalhost = servers.some((s) => s.startsWith("127."));
|
|
11044
|
+
if (!hasLocalhost) {
|
|
11045
|
+
return;
|
|
11046
|
+
}
|
|
11047
|
+
const testDomain = "one.one.one.one";
|
|
11048
|
+
import_node_dns.default.resolve4(testDomain, (err) => {
|
|
11049
|
+
if (err && (err.code === "ECONNREFUSED" || err.code === "ENOTFOUND" || err.code === "ETIMEOUT")) {
|
|
11050
|
+
log.warn(`\u7CFB\u7EDF DNS (${servers.join(", ")}) \u4E0D\u53EF\u8FBE (${err.code})\uFF0C\u5207\u6362\u81F3\u516C\u5171 DNS: ${FALLBACK_DNS.join(", ")}`);
|
|
11051
|
+
import_node_dns.default.setServers(FALLBACK_DNS);
|
|
11052
|
+
import_node_dns.default.resolve4("www.okx.com", (verifyErr) => {
|
|
11053
|
+
if (verifyErr) {
|
|
11054
|
+
log.warn(`\u516C\u5171 DNS \u4E5F\u65E0\u6CD5\u89E3\u6790: ${verifyErr.code}`);
|
|
11055
|
+
} else {
|
|
11056
|
+
log.info(`DNS \u4FEE\u590D\u6210\u529F\uFF0C\u5F53\u524D\u670D\u52A1\u5668: ${import_node_dns.default.getServers().join(", ")}`);
|
|
11057
|
+
}
|
|
11058
|
+
});
|
|
11059
|
+
}
|
|
11060
|
+
});
|
|
11061
|
+
} catch (e) {
|
|
11062
|
+
log.warn(`DNS \u68C0\u6D4B\u5931\u8D25: ${e instanceof Error ? e.message : String(e)}`);
|
|
11063
|
+
}
|
|
11064
|
+
}
|
|
11065
|
+
checkAndFixDns();
|
|
11066
|
+
|
|
10983
11067
|
// src/index.ts
|
|
10984
11068
|
var import_node_http = require("node:http");
|
|
10985
|
-
var
|
|
10986
|
-
var
|
|
11069
|
+
var import_node_fs2 = require("node:fs");
|
|
11070
|
+
var import_node_path2 = require("node:path");
|
|
10987
11071
|
|
|
10988
11072
|
// node_modules/zod/v3/external.js
|
|
10989
11073
|
var external_exports = {};
|
|
@@ -23859,8 +23943,8 @@ var Server = class extends Protocol {
|
|
|
23859
23943
|
this._loggingLevels = /* @__PURE__ */ new Map();
|
|
23860
23944
|
this.LOG_LEVEL_SEVERITY = new Map(LoggingLevelSchema.options.map((level, index) => [level, index]));
|
|
23861
23945
|
this.isMessageIgnored = (level, sessionId) => {
|
|
23862
|
-
const
|
|
23863
|
-
return
|
|
23946
|
+
const currentLevel2 = this._loggingLevels.get(sessionId);
|
|
23947
|
+
return currentLevel2 ? this.LOG_LEVEL_SEVERITY.get(level) < this.LOG_LEVEL_SEVERITY.get(currentLevel2) : false;
|
|
23864
23948
|
};
|
|
23865
23949
|
this._capabilities = options?.capabilities ?? {};
|
|
23866
23950
|
this._instructions = options?.instructions;
|
|
@@ -37557,6 +37641,7 @@ function registerWsTools(server, auth) {
|
|
|
37557
37641
|
|
|
37558
37642
|
// src/adapters/agent-hub.ts
|
|
37559
37643
|
var MAX_ROOM_MESSAGES = 200;
|
|
37644
|
+
var log2 = logger("AgentHub");
|
|
37560
37645
|
var AgentHub = class {
|
|
37561
37646
|
wss = null;
|
|
37562
37647
|
agents = /* @__PURE__ */ new Map();
|
|
@@ -37564,30 +37649,53 @@ var AgentHub = class {
|
|
|
37564
37649
|
rooms = /* @__PURE__ */ new Map();
|
|
37565
37650
|
heartbeatTimer = null;
|
|
37566
37651
|
version = "0.0.0";
|
|
37652
|
+
startTime = 0;
|
|
37567
37653
|
port = 0;
|
|
37654
|
+
// public: updated after WS negotiate, read by hub for dashboard URL
|
|
37655
|
+
registryCount = 0;
|
|
37656
|
+
// set by hub-server after HubRegistry loads
|
|
37568
37657
|
db = null;
|
|
37569
37658
|
token = "";
|
|
37570
37659
|
// PSK 鉴权令牌
|
|
37660
|
+
costTracker = null;
|
|
37661
|
+
// HubCosts 实例
|
|
37571
37662
|
// ── 持久化绑定 ──
|
|
37663
|
+
setCostTracker(ct) {
|
|
37664
|
+
this.costTracker = ct;
|
|
37665
|
+
}
|
|
37572
37666
|
setDB(db) {
|
|
37573
37667
|
this.db = db;
|
|
37574
37668
|
const rows = db.loadTasks();
|
|
37669
|
+
let orphanCount = 0;
|
|
37575
37670
|
for (const r of rows) {
|
|
37576
|
-
this.
|
|
37577
|
-
|
|
37578
|
-
|
|
37579
|
-
|
|
37580
|
-
|
|
37581
|
-
|
|
37582
|
-
|
|
37671
|
+
if (r.status === "assigned" && r.assignedTo && !this.agents.has(r.assignedTo)) {
|
|
37672
|
+
this.tasks.set(r.taskId, {
|
|
37673
|
+
status: "unassigned",
|
|
37674
|
+
assignedTo: void 0,
|
|
37675
|
+
claimedAt: void 0,
|
|
37676
|
+
result: r.result || void 0,
|
|
37677
|
+
branch: r.branch || void 0
|
|
37678
|
+
});
|
|
37679
|
+
db.saveTask({ taskId: r.taskId, status: "unassigned" });
|
|
37680
|
+
orphanCount++;
|
|
37681
|
+
} else {
|
|
37682
|
+
this.tasks.set(r.taskId, {
|
|
37683
|
+
status: r.status,
|
|
37684
|
+
assignedTo: r.assignedTo || void 0,
|
|
37685
|
+
claimedAt: r.claimedAt || void 0,
|
|
37686
|
+
result: r.result || void 0,
|
|
37687
|
+
branch: r.branch || void 0
|
|
37688
|
+
});
|
|
37689
|
+
}
|
|
37583
37690
|
}
|
|
37584
37691
|
if (rows.length > 0) {
|
|
37585
|
-
|
|
37692
|
+
log2.info(`\u4ECE DB \u6062\u590D ${rows.length} \u4E2A\u4EFB\u52A1` + (orphanCount > 0 ? `\uFF0C\u91CA\u653E ${orphanCount} \u4E2A\u5B64\u513F\u4EFB\u52A1` : ""));
|
|
37586
37693
|
}
|
|
37587
37694
|
}
|
|
37588
37695
|
// ── 启动 ──
|
|
37589
37696
|
start(port, host = "0.0.0.0", version2 = "0.0.0", token = "") {
|
|
37590
37697
|
this.version = version2;
|
|
37698
|
+
this.startTime = Date.now();
|
|
37591
37699
|
this.token = token;
|
|
37592
37700
|
const startWss = (p) => {
|
|
37593
37701
|
return new Promise((resolve2) => {
|
|
@@ -37623,12 +37731,10 @@ var AgentHub = class {
|
|
|
37623
37731
|
return ok === true ? true : false;
|
|
37624
37732
|
}).then((ok) => {
|
|
37625
37733
|
if (!ok) {
|
|
37626
|
-
|
|
37627
|
-
`);
|
|
37734
|
+
log2.warn(`WS Hub \u8DF3\u8FC7\uFF08\u7AEF\u53E3 ${ports.join("/")} \u4E0D\u53EF\u7528\uFF09`);
|
|
37628
37735
|
return;
|
|
37629
37736
|
}
|
|
37630
|
-
|
|
37631
|
-
`);
|
|
37737
|
+
log2.info(`WS Hub v${version2} ws://${host}:${this.port}`);
|
|
37632
37738
|
this.setupHub();
|
|
37633
37739
|
});
|
|
37634
37740
|
}
|
|
@@ -37660,17 +37766,17 @@ var AgentHub = class {
|
|
|
37660
37766
|
if (agentId) this.handleDisconnect(agentId);
|
|
37661
37767
|
});
|
|
37662
37768
|
ws.on("error", (e) => {
|
|
37663
|
-
|
|
37664
|
-
`);
|
|
37769
|
+
log2.error(`WS \u9519\u8BEF: ${e.message}`);
|
|
37665
37770
|
});
|
|
37666
37771
|
});
|
|
37667
37772
|
this.heartbeatTimer = setInterval(() => {
|
|
37668
37773
|
const now = Date.now();
|
|
37669
37774
|
for (const [id, a] of this.agents) {
|
|
37775
|
+
if (id.startsWith("term-") || id.startsWith("dashboard")) continue;
|
|
37670
37776
|
if (now - a.lastSeen > 12e4) {
|
|
37671
37777
|
a.ws.close();
|
|
37672
37778
|
this.agents.delete(id);
|
|
37673
|
-
|
|
37779
|
+
log2.warn("Agent \u5FC3\u8DF3\u8D85\u65F6: " + id);
|
|
37674
37780
|
}
|
|
37675
37781
|
}
|
|
37676
37782
|
}, 3e4);
|
|
@@ -37686,9 +37792,29 @@ var AgentHub = class {
|
|
|
37686
37792
|
case "task:claim":
|
|
37687
37793
|
this.handleClaim(msg);
|
|
37688
37794
|
break;
|
|
37795
|
+
case "task:progress":
|
|
37796
|
+
this.broadcast(msg);
|
|
37797
|
+
break;
|
|
37798
|
+
// 流式文本转发
|
|
37799
|
+
case "task:tool":
|
|
37800
|
+
this.broadcast(msg);
|
|
37801
|
+
break;
|
|
37802
|
+
// 工具调用转发
|
|
37689
37803
|
case "task:done":
|
|
37690
37804
|
this.handleDone(msg);
|
|
37691
37805
|
break;
|
|
37806
|
+
case "task:assign":
|
|
37807
|
+
this.handleAssign(msg);
|
|
37808
|
+
break;
|
|
37809
|
+
// Chronos AI 调度指令
|
|
37810
|
+
case "task:unassign":
|
|
37811
|
+
this.handleUnassign(msg);
|
|
37812
|
+
break;
|
|
37813
|
+
// Chronos 释放卡住任务
|
|
37814
|
+
case "task:reject":
|
|
37815
|
+
this.handleReject(msg);
|
|
37816
|
+
break;
|
|
37817
|
+
// Worker 忙时拒绝任务
|
|
37692
37818
|
// ── Room ──
|
|
37693
37819
|
case "room:join":
|
|
37694
37820
|
this.handleRoomJoin(authAgentId, msg);
|
|
@@ -37727,7 +37853,7 @@ var AgentHub = class {
|
|
|
37727
37853
|
lastSeen: Date.now()
|
|
37728
37854
|
});
|
|
37729
37855
|
this.joinRoom(agentId, "#lobby");
|
|
37730
|
-
|
|
37856
|
+
log2.info(`Agent \u6CE8\u518C: ${agentId} (${name}) skills: [${capabilities.join(", ")}]`);
|
|
37731
37857
|
this.send(ws, {
|
|
37732
37858
|
type: "agent:registered",
|
|
37733
37859
|
agentId,
|
|
@@ -37735,6 +37861,13 @@ var AgentHub = class {
|
|
|
37735
37861
|
message: `\u5DF2\u6CE8\u518C\u3002\u53EF\u7528\u4EFB\u52A1: ${this.getUnassignedTasks().join(", ") || "\u65E0"}`,
|
|
37736
37862
|
pendingTasks: this.getUnassignedTasks()
|
|
37737
37863
|
});
|
|
37864
|
+
this.broadcast({
|
|
37865
|
+
type: "agent:update",
|
|
37866
|
+
agentId,
|
|
37867
|
+
name,
|
|
37868
|
+
capabilities,
|
|
37869
|
+
status: "idle"
|
|
37870
|
+
});
|
|
37738
37871
|
const agentVersion = String(msg.version || "");
|
|
37739
37872
|
if (agentVersion && agentVersion !== this.version) {
|
|
37740
37873
|
this.send(ws, {
|
|
@@ -37756,7 +37889,8 @@ var AgentHub = class {
|
|
|
37756
37889
|
}
|
|
37757
37890
|
handleDisconnect(agentId) {
|
|
37758
37891
|
const info = this.agents.get(agentId);
|
|
37759
|
-
|
|
37892
|
+
log2.info(`Agent \u79BB\u7EBF: ${agentId} (${info?.name || "?"})`);
|
|
37893
|
+
this.broadcast({ type: "agent:offline", agentId });
|
|
37760
37894
|
for (const [roomId, room] of this.rooms) {
|
|
37761
37895
|
if (room.members.has(agentId)) {
|
|
37762
37896
|
room.members.delete(agentId);
|
|
@@ -37796,8 +37930,12 @@ var AgentHub = class {
|
|
|
37796
37930
|
return;
|
|
37797
37931
|
}
|
|
37798
37932
|
if (task.status === "assigned" && task.assignedTo !== agentId) {
|
|
37799
|
-
|
|
37800
|
-
|
|
37933
|
+
const assignedWorker = task.assignedTo ? this.agents.get(task.assignedTo) : null;
|
|
37934
|
+
if (assignedWorker) {
|
|
37935
|
+
this.sendTo(agentId, { type: "error", message: `\u4EFB\u52A1 ${taskId} \u5DF2\u88AB ${task.assignedTo} \u8BA4\u9886` });
|
|
37936
|
+
return;
|
|
37937
|
+
}
|
|
37938
|
+
log2.info(`${agentId} \u63A5\u7BA1\u5B64\u513F\u4EFB\u52A1 ${taskId}\uFF08\u539F ${task.assignedTo} \u5DF2\u79BB\u7EBF\uFF09`);
|
|
37801
37939
|
}
|
|
37802
37940
|
task.status = "assigned";
|
|
37803
37941
|
task.assignedTo = agentId;
|
|
@@ -37805,7 +37943,7 @@ var AgentHub = class {
|
|
|
37805
37943
|
const a = this.agents.get(agentId);
|
|
37806
37944
|
if (a) a.status = "working";
|
|
37807
37945
|
this.joinRoom(agentId, `#task-${taskId}`);
|
|
37808
|
-
|
|
37946
|
+
log2.info(`${agentId} \u8BA4\u9886 ${taskId}`);
|
|
37809
37947
|
this.db?.saveTask({ taskId, status: "assigned", title: this.getTaskTitle(taskId), assignedTo: agentId, claimedAt: task.claimedAt });
|
|
37810
37948
|
this.sendTo(agentId, {
|
|
37811
37949
|
type: "task:assigned",
|
|
@@ -37821,18 +37959,44 @@ var AgentHub = class {
|
|
|
37821
37959
|
const agentId = String(msg.agentId || "");
|
|
37822
37960
|
const result = String(msg.result || "");
|
|
37823
37961
|
const branch = String(msg.branch || "");
|
|
37962
|
+
const error2 = msg.error ? String(msg.error) : "";
|
|
37963
|
+
const usage = msg.usage;
|
|
37964
|
+
const steps = Number(msg.steps || 0);
|
|
37965
|
+
if (this.costTracker && usage?.inputTokens) {
|
|
37966
|
+
this.costTracker.record({
|
|
37967
|
+
agentId,
|
|
37968
|
+
taskId,
|
|
37969
|
+
model: usage.model || "claude-sonnet-4-6",
|
|
37970
|
+
inputTokens: usage.inputTokens || 0,
|
|
37971
|
+
outputTokens: usage.outputTokens || 0,
|
|
37972
|
+
purpose: "task"
|
|
37973
|
+
});
|
|
37974
|
+
}
|
|
37824
37975
|
const task = this.tasks.get(taskId);
|
|
37825
37976
|
if (!task) {
|
|
37826
37977
|
this.sendTo(agentId, { type: "error", message: `\u4EFB\u52A1 ${taskId} \u4E0D\u5B58\u5728` });
|
|
37827
37978
|
return;
|
|
37828
37979
|
}
|
|
37980
|
+
if (error2 || /^❌|^执行失败/i.test(result)) {
|
|
37981
|
+
task.status = "unassigned";
|
|
37982
|
+
task.assignedTo = void 0;
|
|
37983
|
+
task.claimedAt = void 0;
|
|
37984
|
+
const a2 = this.agents.get(agentId);
|
|
37985
|
+
if (a2) a2.status = "idle";
|
|
37986
|
+
this.db?.saveTask({ taskId, status: "unassigned" });
|
|
37987
|
+
log2.info(`\u4EFB\u52A1\u6267\u884C\u5931\u8D25\uFF0C\u91CA\u653E\u91CD\u8BD5: ${taskId} \u2014 ${error2 || result.slice(0, 80)}`);
|
|
37988
|
+
this.broadcast({ type: "agent:update", agentId, status: "idle" });
|
|
37989
|
+
this.broadcast({ type: "task:released", taskId, reason: `\u6267\u884C\u5931\u8D25: ${error2 || result.slice(0, 60)}` });
|
|
37990
|
+
return;
|
|
37991
|
+
}
|
|
37829
37992
|
task.status = "done";
|
|
37830
37993
|
task.result = result;
|
|
37831
37994
|
task.branch = branch;
|
|
37832
37995
|
const a = this.agents.get(agentId);
|
|
37833
37996
|
if (a) a.status = "idle";
|
|
37834
|
-
|
|
37997
|
+
log2.info(`${agentId} \u5B8C\u6210 ${taskId}: ${result}`);
|
|
37835
37998
|
this.db?.saveTask({ taskId, status: "done", title: this.getTaskTitle(taskId), assignedTo: agentId, result, branch });
|
|
37999
|
+
this.broadcast({ type: "agent:update", agentId, status: "idle" });
|
|
37836
38000
|
this.sendToRoom(`#task-${taskId}`, agentId, `\u5DF2\u5B8C\u6210 ${taskId}: ${result} (branch: ${branch})\uFF0C\u7B49\u5F85\u5BA1\u6838\u3002`);
|
|
37837
38001
|
this.sendToRoom("#review", agentId, `${taskId} \u63D0\u4EA4\u5B8C\u6210\uFF0Cbranch: ${branch}`);
|
|
37838
38002
|
this.broadcast({
|
|
@@ -37844,41 +38008,125 @@ var AgentHub = class {
|
|
|
37844
38008
|
message: `${agentId} \u5DF2\u5B8C\u6210 ${taskId}\uFF0C\u7B49\u5F85\u5BA1\u6838`
|
|
37845
38009
|
});
|
|
37846
38010
|
}
|
|
38011
|
+
// ── Chronos 释放卡住任务 ──
|
|
38012
|
+
handleUnassign(msg) {
|
|
38013
|
+
const taskId = String(msg.taskId || "");
|
|
38014
|
+
const reason = String(msg.reason || "Chronos \u5DE1\u68C0\u91CA\u653E");
|
|
38015
|
+
const task = this.tasks.get(taskId);
|
|
38016
|
+
if (!task) {
|
|
38017
|
+
log2.warn(`Chronos \u91CA\u653E\u5931\u8D25: \u4EFB\u52A1 ${taskId} \u4E0D\u5B58\u5728`);
|
|
38018
|
+
return;
|
|
38019
|
+
}
|
|
38020
|
+
if (task.status !== "assigned") {
|
|
38021
|
+
return;
|
|
38022
|
+
}
|
|
38023
|
+
const oldAgentId = task.assignedTo;
|
|
38024
|
+
task.status = "unassigned";
|
|
38025
|
+
task.assignedTo = void 0;
|
|
38026
|
+
task.claimedAt = void 0;
|
|
38027
|
+
if (oldAgentId) {
|
|
38028
|
+
const oldWorker = this.agents.get(oldAgentId);
|
|
38029
|
+
if (oldWorker && oldWorker.status === "working") {
|
|
38030
|
+
oldWorker.status = "idle";
|
|
38031
|
+
}
|
|
38032
|
+
}
|
|
38033
|
+
this.db?.saveTask({ taskId, status: "unassigned" });
|
|
38034
|
+
log2.warn(`Chronos \u91CA\u653E\u5361\u4F4F\u4EFB\u52A1: ${taskId} (\u539F ${oldAgentId || "?"}) \u2014 ${reason}`);
|
|
38035
|
+
this.broadcast({
|
|
38036
|
+
type: "task:released",
|
|
38037
|
+
taskId,
|
|
38038
|
+
reason: `Chronos \u91CA\u653E: ${reason}`
|
|
38039
|
+
});
|
|
38040
|
+
}
|
|
38041
|
+
// ── Worker 拒绝任务(忙碌)──
|
|
38042
|
+
handleReject(msg) {
|
|
38043
|
+
const taskId = String(msg.taskId || "");
|
|
38044
|
+
const agentId = String(msg.agentId || "");
|
|
38045
|
+
const reason = String(msg.reason || "Worker busy");
|
|
38046
|
+
const task = this.tasks.get(taskId);
|
|
38047
|
+
if (!task) return;
|
|
38048
|
+
if (task.status !== "assigned") return;
|
|
38049
|
+
task.status = "unassigned";
|
|
38050
|
+
task.assignedTo = void 0;
|
|
38051
|
+
task.claimedAt = void 0;
|
|
38052
|
+
const a = this.agents.get(agentId);
|
|
38053
|
+
if (a && a.status === "working") a.status = "idle";
|
|
38054
|
+
this.db?.saveTask({ taskId, status: "unassigned" });
|
|
38055
|
+
log2.info(`\u4EFB\u52A1\u88AB\u62D2\u7EDD: ${taskId} by ${agentId} \u2014 ${reason}`);
|
|
38056
|
+
this.broadcast({ type: "task:released", taskId, reason: `Worker \u62D2\u7EDD: ${reason}` });
|
|
38057
|
+
}
|
|
37847
38058
|
// ── 注册任务(自动派发给空闲 Agent) ──
|
|
37848
|
-
|
|
38059
|
+
/** 检查是否有空闲的 WS Worker(非 dashboard、非 CLI spawn) */
|
|
38060
|
+
hasIdleWorker() {
|
|
38061
|
+
for (const [id, a] of this.agents) {
|
|
38062
|
+
if (a.status === "idle" && !id.startsWith("dashboard") && !id.startsWith("term-")) {
|
|
38063
|
+
return true;
|
|
38064
|
+
}
|
|
38065
|
+
}
|
|
38066
|
+
return false;
|
|
38067
|
+
}
|
|
38068
|
+
registerTask(taskId, title, promptB64) {
|
|
37849
38069
|
if (!this.tasks.has(taskId)) {
|
|
37850
38070
|
this.tasks.set(taskId, { status: "unassigned" });
|
|
37851
38071
|
}
|
|
37852
|
-
|
|
37853
|
-
|
|
37854
|
-
|
|
37855
|
-
}
|
|
37856
|
-
console.log(`[AgentHub] \u4EFB\u52A1\u6CE8\u518C: ${taskId} "${title || taskId}"`);
|
|
38072
|
+
const task = this.tasks.get(taskId);
|
|
38073
|
+
if (title) task.title = title;
|
|
38074
|
+
if (promptB64) task.promptB64 = promptB64;
|
|
38075
|
+
log2.info(`\u4EFB\u52A1\u6CE8\u518C: ${taskId} "${title || taskId}"`);
|
|
37857
38076
|
this.broadcast({ type: "task:announced", taskId, title: title || taskId });
|
|
37858
|
-
const
|
|
38077
|
+
const hasChronos = [...this.agents.values()].some(
|
|
38078
|
+
(a) => a.agentId === "chronos-dispatcher" && a.status !== "offline"
|
|
38079
|
+
);
|
|
38080
|
+
if (hasChronos) {
|
|
38081
|
+
log2.info(`Chronos \u5728\u7EBF\uFF0C\u4EFB\u52A1 ${taskId} \u7B49\u5F85 AI \u8C03\u5EA6`);
|
|
38082
|
+
return;
|
|
38083
|
+
}
|
|
38084
|
+
const idleAgents = [...this.agents.entries()].filter(([, a]) => a.status === "idle" && !a.agentId.startsWith("dashboard") && !a.agentId.startsWith("term-"));
|
|
37859
38085
|
if (idleAgents.length === 0) {
|
|
37860
|
-
|
|
38086
|
+
log2.warn(`\u6CA1\u6709\u7A7A\u95F2 Agent\uFF0C\u4EFB\u52A1 ${taskId} \u7B49\u5F85\u624B\u52A8 spawn`);
|
|
37861
38087
|
return;
|
|
37862
38088
|
}
|
|
37863
38089
|
const match = idleAgents.find(([, a]) => a.capabilities.includes(taskId)) || idleAgents[0];
|
|
37864
38090
|
if (match) {
|
|
37865
|
-
|
|
37866
|
-
this.dispatchTaskTo(taskId, match[0]);
|
|
38091
|
+
log2.info(`\u81EA\u52A8\u6D3E\u53D1 ${taskId} \u2192 ${match[1].name} (${match[0]})`);
|
|
38092
|
+
this.dispatchTaskTo(taskId, match[0], promptB64);
|
|
37867
38093
|
}
|
|
37868
38094
|
}
|
|
37869
38095
|
// ── 派发任务 ──
|
|
37870
|
-
dispatchTaskTo(taskId, agentId) {
|
|
38096
|
+
dispatchTaskTo(taskId, agentId, promptB64) {
|
|
37871
38097
|
if (!this.tasks.has(taskId)) {
|
|
37872
38098
|
this.tasks.set(taskId, { status: "unassigned" });
|
|
37873
38099
|
}
|
|
37874
38100
|
const task = this.tasks.get(taskId);
|
|
37875
38101
|
if (task.status === "assigned") return;
|
|
37876
|
-
|
|
38102
|
+
const msg = {
|
|
37877
38103
|
type: "task:dispatch",
|
|
37878
38104
|
taskId,
|
|
37879
|
-
title: this.getTaskTitle(taskId)
|
|
37880
|
-
|
|
37881
|
-
|
|
38105
|
+
title: this.getTaskTitle(taskId)
|
|
38106
|
+
};
|
|
38107
|
+
if (promptB64) msg.promptB64 = promptB64;
|
|
38108
|
+
else if (task.promptB64) msg.promptB64 = task.promptB64;
|
|
38109
|
+
this.sendTo(agentId, msg);
|
|
38110
|
+
}
|
|
38111
|
+
// ── Chronos 调度指令 ──
|
|
38112
|
+
handleAssign(msg) {
|
|
38113
|
+
const taskId = String(msg.taskId || "");
|
|
38114
|
+
const targetAgentId = String(msg.agentId || "");
|
|
38115
|
+
const assignedBy = String(msg.assignedBy || "chronos");
|
|
38116
|
+
if (!taskId || !targetAgentId) return;
|
|
38117
|
+
const targetWorker = this.agents.get(targetAgentId);
|
|
38118
|
+
if (!targetWorker) {
|
|
38119
|
+
log2.warn(`Chronos \u6307\u6D3E\u5931\u8D25: Worker ${targetAgentId} \u4E0D\u5728\u7EBF`);
|
|
38120
|
+
return;
|
|
38121
|
+
}
|
|
38122
|
+
if (targetWorker.status !== "idle") {
|
|
38123
|
+
log2.warn(`Chronos \u6307\u6D3E\u5931\u8D25: Worker ${targetAgentId} \u5FD9\u788C\u4E2D`);
|
|
38124
|
+
return;
|
|
38125
|
+
}
|
|
38126
|
+
log2.info(`Chronos \u8C03\u5EA6: ${taskId} \u2192 ${targetWorker.name}`);
|
|
38127
|
+
const task = this.tasks.get(taskId);
|
|
38128
|
+
const promptB64 = task?.promptB64;
|
|
38129
|
+
this.dispatchTaskTo(taskId, targetAgentId, promptB64);
|
|
37882
38130
|
}
|
|
37883
38131
|
// ── 审核 + 自动通知房间 ──
|
|
37884
38132
|
reviewTask(taskId, verdict, feedback) {
|
|
@@ -37926,7 +38174,7 @@ var AgentHub = class {
|
|
|
37926
38174
|
});
|
|
37927
38175
|
}
|
|
37928
38176
|
this.sendToRoomMembers(room, { type: "room:member_joined", roomId, agentId });
|
|
37929
|
-
|
|
38177
|
+
log2.info(`${agentId} \u2192 ${roomId}`);
|
|
37930
38178
|
}
|
|
37931
38179
|
leaveRoom(agentId, roomId) {
|
|
37932
38180
|
const room = this.rooms.get(roomId);
|
|
@@ -38043,7 +38291,7 @@ var AgentHub = class {
|
|
|
38043
38291
|
branch: t.branch
|
|
38044
38292
|
}));
|
|
38045
38293
|
const rooms = this.getRooms();
|
|
38046
|
-
return { agents, tasks, rooms, agentCount: agents.length, taskCount: tasks.length };
|
|
38294
|
+
return { agents, tasks, rooms, agentCount: agents.length, taskCount: tasks.length, version: this.version, uptime: this.startTime ? Math.floor((Date.now() - this.startTime) / 1e3) : 0, registry: `${this.registryCount || 24} plugins` };
|
|
38047
38295
|
}
|
|
38048
38296
|
// ── 关闭 ──
|
|
38049
38297
|
close() {
|
|
@@ -38628,6 +38876,146 @@ function registerCodeGraphTools(server) {
|
|
|
38628
38876
|
);
|
|
38629
38877
|
}
|
|
38630
38878
|
|
|
38879
|
+
// src/adapters/api-credits.ts
|
|
38880
|
+
var import_node_sqlite = require("node:sqlite");
|
|
38881
|
+
var import_node_fs = require("node:fs");
|
|
38882
|
+
var import_node_path = require("node:path");
|
|
38883
|
+
var log3 = logger("Credits");
|
|
38884
|
+
var CREDIT_COST = {
|
|
38885
|
+
READ: 1,
|
|
38886
|
+
WRITE: 5,
|
|
38887
|
+
FUND_TRANSFER: 10,
|
|
38888
|
+
ADMIN: 20
|
|
38889
|
+
};
|
|
38890
|
+
var ApiCredits = class {
|
|
38891
|
+
db;
|
|
38892
|
+
cache = /* @__PURE__ */ new Map();
|
|
38893
|
+
cacheLoaded = false;
|
|
38894
|
+
constructor(dbPath = ".hub/api-credits.db") {
|
|
38895
|
+
const dir = (0, import_node_path.dirname)(dbPath);
|
|
38896
|
+
if (!(0, import_node_fs.existsSync)(dir)) (0, import_node_fs.mkdirSync)(dir, { recursive: true });
|
|
38897
|
+
this.db = new import_node_sqlite.DatabaseSync(dbPath);
|
|
38898
|
+
this.db.exec("PRAGMA journal_mode=WAL");
|
|
38899
|
+
this.init();
|
|
38900
|
+
}
|
|
38901
|
+
init() {
|
|
38902
|
+
this.db.exec(`
|
|
38903
|
+
CREATE TABLE IF NOT EXISTS api_keys (
|
|
38904
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
38905
|
+
key TEXT UNIQUE NOT NULL,
|
|
38906
|
+
client_name TEXT NOT NULL,
|
|
38907
|
+
credits REAL NOT NULL DEFAULT 0,
|
|
38908
|
+
total_used INTEGER NOT NULL DEFAULT 0,
|
|
38909
|
+
enabled INTEGER NOT NULL DEFAULT 1,
|
|
38910
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
38911
|
+
last_used_at TEXT
|
|
38912
|
+
);
|
|
38913
|
+
CREATE INDEX IF NOT EXISTS idx_api_keys_key ON api_keys(key);
|
|
38914
|
+
`);
|
|
38915
|
+
this.loadCache();
|
|
38916
|
+
}
|
|
38917
|
+
loadCache() {
|
|
38918
|
+
const rows = this.db.prepare("SELECT * FROM api_keys").all();
|
|
38919
|
+
for (const r of rows) this.cache.set(r.key, r);
|
|
38920
|
+
this.cacheLoaded = true;
|
|
38921
|
+
log3.info(`\u5DF2\u52A0\u8F7D ${rows.length} \u4E2A API Key`);
|
|
38922
|
+
}
|
|
38923
|
+
/** 查找 Key — 缓存命中或直接查 DB */
|
|
38924
|
+
lookup(key) {
|
|
38925
|
+
if (!this.cacheLoaded) this.loadCache();
|
|
38926
|
+
const cached2 = this.cache.get(key);
|
|
38927
|
+
if (cached2) return cached2;
|
|
38928
|
+
const row = this.db.prepare("SELECT * FROM api_keys WHERE key = ?").get(key);
|
|
38929
|
+
if (row) {
|
|
38930
|
+
this.cache.set(key, row);
|
|
38931
|
+
return row;
|
|
38932
|
+
}
|
|
38933
|
+
return null;
|
|
38934
|
+
}
|
|
38935
|
+
/** 校验并扣费 */
|
|
38936
|
+
deduct(key, riskLevel) {
|
|
38937
|
+
const record2 = this.lookup(key);
|
|
38938
|
+
if (!record2) return { ok: false, error: "\u65E0\u6548\u7684 API Key" };
|
|
38939
|
+
if (!record2.enabled) return { ok: false, error: "API Key \u5DF2\u7981\u7528" };
|
|
38940
|
+
const cost = CREDIT_COST[riskLevel] || 1;
|
|
38941
|
+
if (record2.credits < cost) return { ok: false, error: `\u79EF\u5206\u4E0D\u8DB3 (\u9700\u8981 ${cost}\uFF0C\u5269\u4F59 ${record2.credits})` };
|
|
38942
|
+
record2.credits -= cost;
|
|
38943
|
+
record2.totalUsed++;
|
|
38944
|
+
record2.lastUsedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
38945
|
+
this.db.prepare("UPDATE api_keys SET credits = ?, total_used = ?, last_used_at = ? WHERE id = ?").run(record2.credits, record2.totalUsed, record2.lastUsedAt, record2.id);
|
|
38946
|
+
return { ok: true, remaining: record2.credits };
|
|
38947
|
+
}
|
|
38948
|
+
/** 管理:创建 Key */
|
|
38949
|
+
createKey(clientName, initialCredits = 1e3) {
|
|
38950
|
+
const key = "hvip-" + Array.from(
|
|
38951
|
+
{ length: 32 },
|
|
38952
|
+
() => "abcdefghijklmnopqrstuvwxyz0123456789"[Math.floor(Math.random() * 36)]
|
|
38953
|
+
).join("");
|
|
38954
|
+
const result = this.db.prepare(
|
|
38955
|
+
"INSERT INTO api_keys (key, client_name, credits) VALUES (?, ?, ?)"
|
|
38956
|
+
).run(key, clientName, initialCredits);
|
|
38957
|
+
const record2 = {
|
|
38958
|
+
id: result.lastInsertRowid,
|
|
38959
|
+
key,
|
|
38960
|
+
clientName,
|
|
38961
|
+
credits: initialCredits,
|
|
38962
|
+
totalUsed: 0,
|
|
38963
|
+
enabled: true,
|
|
38964
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
38965
|
+
lastUsedAt: null
|
|
38966
|
+
};
|
|
38967
|
+
this.cache.set(key, record2);
|
|
38968
|
+
return record2;
|
|
38969
|
+
}
|
|
38970
|
+
/** 管理:充值 */
|
|
38971
|
+
topUp(key, amount) {
|
|
38972
|
+
const record2 = this.lookup(key);
|
|
38973
|
+
if (!record2) return { ok: false, error: "Key \u4E0D\u5B58\u5728" };
|
|
38974
|
+
if (amount <= 0) return { ok: false, error: "\u5145\u503C\u91D1\u989D\u5FC5\u987B > 0" };
|
|
38975
|
+
record2.credits += amount;
|
|
38976
|
+
this.db.prepare("UPDATE api_keys SET credits = ? WHERE id = ?").run(record2.credits, record2.id);
|
|
38977
|
+
return { ok: true, newBalance: record2.credits };
|
|
38978
|
+
}
|
|
38979
|
+
/** 管理:启用/禁用 Key */
|
|
38980
|
+
setEnabled(key, enabled) {
|
|
38981
|
+
const record2 = this.lookup(key);
|
|
38982
|
+
if (!record2) return false;
|
|
38983
|
+
record2.enabled = enabled;
|
|
38984
|
+
this.db.prepare("UPDATE api_keys SET enabled = ? WHERE id = ?").run(enabled ? 1 : 0, record2.id);
|
|
38985
|
+
return true;
|
|
38986
|
+
}
|
|
38987
|
+
/** 管理:列出所有 Key (含 Key 前缀,完整 Key 仅创建时返回) */
|
|
38988
|
+
listAll() {
|
|
38989
|
+
return [...this.cache.values()].map((r) => ({
|
|
38990
|
+
id: r.id,
|
|
38991
|
+
clientName: r.clientName,
|
|
38992
|
+
credits: r.credits,
|
|
38993
|
+
totalUsed: r.totalUsed,
|
|
38994
|
+
enabled: r.enabled,
|
|
38995
|
+
createdAt: r.createdAt,
|
|
38996
|
+
lastUsedAt: r.lastUsedAt,
|
|
38997
|
+
keyPrefix: r.key.slice(0, 12) + "..." + r.key.slice(-8)
|
|
38998
|
+
}));
|
|
38999
|
+
}
|
|
39000
|
+
/** 客户端:查询余额 */
|
|
39001
|
+
getBalance(key) {
|
|
39002
|
+
const record2 = this.lookup(key);
|
|
39003
|
+
if (!record2) return null;
|
|
39004
|
+
return { clientName: record2.clientName, credits: record2.credits, totalUsed: record2.totalUsed };
|
|
39005
|
+
}
|
|
39006
|
+
close() {
|
|
39007
|
+
try {
|
|
39008
|
+
this.db.close();
|
|
39009
|
+
} catch {
|
|
39010
|
+
}
|
|
39011
|
+
}
|
|
39012
|
+
};
|
|
39013
|
+
var instance = null;
|
|
39014
|
+
function getApiCredits(dbPath) {
|
|
39015
|
+
if (!instance) instance = new ApiCredits(dbPath);
|
|
39016
|
+
return instance;
|
|
39017
|
+
}
|
|
39018
|
+
|
|
38631
39019
|
// src/index.ts
|
|
38632
39020
|
function resolveExecutionMode() {
|
|
38633
39021
|
if (process.env.MCP_EXECUTION_ENABLED === "false") {
|
|
@@ -38700,7 +39088,7 @@ function registerAllTools(server, auth, readOnly) {
|
|
|
38700
39088
|
if (risk !== "READ") {
|
|
38701
39089
|
skipped++;
|
|
38702
39090
|
skipLog.push(`${name} (${risk})`);
|
|
38703
|
-
return;
|
|
39091
|
+
return server;
|
|
38704
39092
|
}
|
|
38705
39093
|
return orig(name, ...args);
|
|
38706
39094
|
};
|
|
@@ -38732,22 +39120,46 @@ function registerAllTools(server, auth, readOnly) {
|
|
|
38732
39120
|
return { skipped, skipLog };
|
|
38733
39121
|
}
|
|
38734
39122
|
async function startHttp(server, version2, auth, readOnly, skipped) {
|
|
38735
|
-
|
|
39123
|
+
let port = parseInt(process.env.PORT || "3000", 10);
|
|
38736
39124
|
if (!Number.isInteger(port) || port < 1 || port > 65535) {
|
|
38737
39125
|
process.stderr.write(`[hvip] \u274C \u65E0\u6548\u7AEF\u53E3: ${process.env.PORT}\uFF0C\u4F7F\u7528\u9ED8\u8BA4 3000
|
|
38738
39126
|
`);
|
|
39127
|
+
port = 3e3;
|
|
38739
39128
|
}
|
|
38740
39129
|
const host = process.env.HOST || "127.0.0.1";
|
|
38741
|
-
const
|
|
39130
|
+
const adminToken = process.env.MCP_AUTH_TOKEN || "";
|
|
39131
|
+
const creditsEnabled = process.env.MCP_CREDITS !== "false" && process.env.MCP_CREDITS !== "0";
|
|
39132
|
+
const credits = creditsEnabled ? getApiCredits() : null;
|
|
38742
39133
|
const transport = new StreamableHTTPServerTransport({
|
|
38743
39134
|
sessionIdGenerator: void 0
|
|
38744
39135
|
// stateless
|
|
38745
39136
|
});
|
|
38746
39137
|
await server.connect(transport);
|
|
38747
39138
|
const httpServer = (0, import_node_http.createServer)(async (req, res) => {
|
|
38748
|
-
|
|
38749
|
-
|
|
38750
|
-
if (provided
|
|
39139
|
+
const provided = req.headers["authorization"]?.replace(/^Bearer\s+/i, "") || "";
|
|
39140
|
+
if (req.url !== "/health" && req.url !== "/") {
|
|
39141
|
+
if (adminToken && provided === adminToken) {
|
|
39142
|
+
} else if (credits && provided) {
|
|
39143
|
+
const record2 = credits.lookup(provided);
|
|
39144
|
+
if (!record2) {
|
|
39145
|
+
res.writeHead(401, { "Content-Type": "application/json" });
|
|
39146
|
+
res.end(JSON.stringify({ error: "Unauthorized \u2014 \u65E0\u6548\u7684 API Key" }));
|
|
39147
|
+
return;
|
|
39148
|
+
}
|
|
39149
|
+
if (!record2.enabled) {
|
|
39150
|
+
res.writeHead(403, { "Content-Type": "application/json" });
|
|
39151
|
+
res.end(JSON.stringify({ error: "Forbidden \u2014 API Key \u5DF2\u7981\u7528" }));
|
|
39152
|
+
return;
|
|
39153
|
+
}
|
|
39154
|
+
if (req.method === "POST" && req.url === "/mcp") {
|
|
39155
|
+
const result = credits.deduct(provided, "READ");
|
|
39156
|
+
if (!result.ok) {
|
|
39157
|
+
res.writeHead(402, { "Content-Type": "application/json" });
|
|
39158
|
+
res.end(JSON.stringify({ error: result.error, remaining: credits.lookup(provided)?.credits || 0 }));
|
|
39159
|
+
return;
|
|
39160
|
+
}
|
|
39161
|
+
}
|
|
39162
|
+
} else if (adminToken) {
|
|
38751
39163
|
res.writeHead(401, { "Content-Type": "application/json" });
|
|
38752
39164
|
res.end(JSON.stringify({ error: "Unauthorized \u2014 \u8BF7\u5728 Authorization \u5934\u643A\u5E26\u6709\u6548 token" }));
|
|
38753
39165
|
return;
|
|
@@ -38764,15 +39176,15 @@ async function startHttp(server, version2, auth, readOnly, skipped) {
|
|
|
38764
39176
|
if (req.method === "GET" && (req.url === "/" || req.url === "/index.html")) {
|
|
38765
39177
|
try {
|
|
38766
39178
|
const paths = [
|
|
38767
|
-
(0,
|
|
39179
|
+
(0, import_node_path2.join)(__dirname, "web", "index.html"),
|
|
38768
39180
|
// published npm (dist/index.js → dist/web/)
|
|
38769
|
-
(0,
|
|
39181
|
+
(0, import_node_path2.join)(__dirname, "..", "src", "web", "index.html")
|
|
38770
39182
|
// dev (dist/index.js → ../src/web/)
|
|
38771
39183
|
];
|
|
38772
39184
|
let html = "";
|
|
38773
39185
|
for (const p of paths) {
|
|
38774
|
-
if ((0,
|
|
38775
|
-
html = (0,
|
|
39186
|
+
if ((0, import_node_fs2.existsSync)(p)) {
|
|
39187
|
+
html = (0, import_node_fs2.readFileSync)(p, "utf-8");
|
|
38776
39188
|
break;
|
|
38777
39189
|
}
|
|
38778
39190
|
}
|
|
@@ -38832,7 +39244,7 @@ async function startHttp(server, version2, auth, readOnly, skipped) {
|
|
|
38832
39244
|
const platform = process.platform;
|
|
38833
39245
|
const cmd = platform === "win32" ? `start ${openUrl}` : platform === "darwin" ? `open ${openUrl}` : `xdg-open ${openUrl}`;
|
|
38834
39246
|
import("node:child_process").then((cp) => {
|
|
38835
|
-
cp.exec(cmd, () => {
|
|
39247
|
+
cp.exec(cmd, { windowsHide: true }, () => {
|
|
38836
39248
|
});
|
|
38837
39249
|
});
|
|
38838
39250
|
});
|
|
@@ -38863,12 +39275,33 @@ async function startStdio(server, version2, auth, readOnly, skipped, skipLog) {
|
|
|
38863
39275
|
}
|
|
38864
39276
|
const wsHost = process.env.WS_BIND_HOST || "127.0.0.1";
|
|
38865
39277
|
const wsToken = process.env.HUB_AUTH_TOKEN || "";
|
|
38866
|
-
startAgentHub(parseInt(process.env.WS_AGENT_PORT || "9321"), wsHost, version2, wsToken);
|
|
39278
|
+
startAgentHub(parseInt(process.env.WS_AGENT_PORT || "9321", 10), wsHost, version2, wsToken);
|
|
38867
39279
|
const transport = new StdioServerTransport();
|
|
38868
39280
|
await server.connect(transport);
|
|
38869
39281
|
}
|
|
39282
|
+
var _cachedVersion = null;
|
|
39283
|
+
function loadVersion() {
|
|
39284
|
+
if (_cachedVersion) return _cachedVersion;
|
|
39285
|
+
try {
|
|
39286
|
+
const paths = [
|
|
39287
|
+
(0, import_node_path2.join)(__dirname, "..", "package.json"),
|
|
39288
|
+
(0, import_node_path2.join)(__dirname, "..", "..", "..", "package.json")
|
|
39289
|
+
];
|
|
39290
|
+
for (const p of paths) {
|
|
39291
|
+
if ((0, import_node_fs2.existsSync)(p)) {
|
|
39292
|
+
const pkg = JSON.parse((0, import_node_fs2.readFileSync)(p, "utf-8"));
|
|
39293
|
+
if (pkg.version) {
|
|
39294
|
+
_cachedVersion = String(pkg.version);
|
|
39295
|
+
return _cachedVersion;
|
|
39296
|
+
}
|
|
39297
|
+
}
|
|
39298
|
+
}
|
|
39299
|
+
} catch {
|
|
39300
|
+
}
|
|
39301
|
+
return "0.0.0";
|
|
39302
|
+
}
|
|
38870
39303
|
async function main() {
|
|
38871
|
-
const VERSION =
|
|
39304
|
+
const VERSION = loadVersion();
|
|
38872
39305
|
const argv = process.argv.slice(2);
|
|
38873
39306
|
if (argv.includes("--help") || argv.includes("-h")) printHelpAndExit(VERSION);
|
|
38874
39307
|
if (argv.includes("--version") || argv.includes("-v")) {
|