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.
@@ -3717,6 +3717,56 @@ var import_websocket_server = __toESM(require_websocket_server(), 1);
3717
3717
 
3718
3718
  // src/hub-worker.ts
3719
3719
  var import_node_child_process = require("node:child_process");
3720
+
3721
+ // src/utils/logger.ts
3722
+ var LEVEL_EMOJI = {
3723
+ [0 /* DEBUG */]: "\u{1F50D}",
3724
+ [1 /* INFO */]: "\u2139\uFE0F",
3725
+ [2 /* WARN */]: "\u26A0\uFE0F",
3726
+ [3 /* ERROR */]: "\u274C",
3727
+ [4 /* SILENT */]: ""
3728
+ };
3729
+ function resolveLevel() {
3730
+ const raw = (process.env.LOG_LEVEL || "").toUpperCase();
3731
+ if (raw === "DEBUG") return 0 /* DEBUG */;
3732
+ if (raw === "WARN" || raw === "WARNING") return 2 /* WARN */;
3733
+ if (raw === "ERROR") return 3 /* ERROR */;
3734
+ if (raw === "SILENT" || raw === "OFF") return 4 /* SILENT */;
3735
+ return 1 /* INFO */;
3736
+ }
3737
+ var currentLevel = resolveLevel();
3738
+ var LoggerImpl = class {
3739
+ constructor(tag) {
3740
+ this.tag = tag;
3741
+ }
3742
+ tag;
3743
+ debug(msg) {
3744
+ this.write(0 /* DEBUG */, msg);
3745
+ }
3746
+ info(msg) {
3747
+ this.write(1 /* INFO */, msg);
3748
+ }
3749
+ warn(msg) {
3750
+ this.write(2 /* WARN */, msg);
3751
+ }
3752
+ error(msg) {
3753
+ this.write(3 /* ERROR */, msg);
3754
+ }
3755
+ write(level, msg) {
3756
+ if (level < currentLevel) return;
3757
+ const ts = (/* @__PURE__ */ new Date()).toISOString().slice(11, 23);
3758
+ const emoji = LEVEL_EMOJI[level];
3759
+ const tag = this.tag ? `[${this.tag}]` : "";
3760
+ const prefix = emoji ? `${emoji} ${tag}` : tag;
3761
+ process.stderr.write(`${ts} ${prefix} ${msg}
3762
+ `);
3763
+ }
3764
+ };
3765
+ function logger(tag) {
3766
+ return new LoggerImpl(tag);
3767
+ }
3768
+
3769
+ // src/hub-worker.ts
3720
3770
  var argv = process.argv.slice(2);
3721
3771
  function flag(name) {
3722
3772
  const i = argv.indexOf("--" + name);
@@ -3732,8 +3782,12 @@ var AGENT_ID = `worker-${TASK_ID}-${Date.now()}`;
3732
3782
  var AGENT_NAME = `Worker\xB7${TASK_ID}`;
3733
3783
  var CLAUDE_CLI = process.env.CLAUDE_CLI || "claude";
3734
3784
  var WORKER_TIMEOUT_MS = parseInt(process.env.HUB_WORKER_TIMEOUT || "600000", 10);
3785
+ var log = logger(`Worker-${TASK_ID}`);
3735
3786
  var ws;
3736
3787
  var taskReceived = false;
3788
+ var heartbeatTimer;
3789
+ var taskDoneSent = false;
3790
+ var taskTitle = "";
3737
3791
  function connect() {
3738
3792
  ws = new import_websocket.default(HUB_URL);
3739
3793
  ws.on("open", () => {
@@ -3746,6 +3800,11 @@ function connect() {
3746
3800
  version: "0.3.0",
3747
3801
  capabilities: [TASK_ID]
3748
3802
  }));
3803
+ heartbeatTimer = setInterval(() => {
3804
+ if (ws.readyState === import_websocket.default.OPEN) {
3805
+ ws.send(JSON.stringify({ type: "agent:status" }));
3806
+ }
3807
+ }, 3e4);
3749
3808
  });
3750
3809
  ws.on("message", (raw) => {
3751
3810
  try {
@@ -3757,6 +3816,7 @@ function connect() {
3757
3816
  }
3758
3817
  });
3759
3818
  ws.on("close", () => {
3819
+ clearInterval(heartbeatTimer);
3760
3820
  if (!taskReceived) {
3761
3821
  process.stderr.write("[Worker] \u8FDE\u63A5\u65AD\u5F00\uFF0C5s \u540E\u91CD\u8FDE...\n");
3762
3822
  setTimeout(connect, 5e3);
@@ -3767,6 +3827,19 @@ function connect() {
3767
3827
  `);
3768
3828
  });
3769
3829
  }
3830
+ function sendTaskDone(taskId, result) {
3831
+ if (taskDoneSent) return;
3832
+ taskDoneSent = true;
3833
+ try {
3834
+ ws.send(JSON.stringify({
3835
+ type: "task:done",
3836
+ taskId,
3837
+ agentId: AGENT_ID,
3838
+ result
3839
+ }));
3840
+ } catch {
3841
+ }
3842
+ }
3770
3843
  function handleMessage(msg) {
3771
3844
  switch (msg.type) {
3772
3845
  case "agent:registered":
@@ -3804,8 +3877,8 @@ function detectTaskType(title) {
3804
3877
  return "code";
3805
3878
  }
3806
3879
  function doTask(taskId, title, url, promptB64) {
3807
- process.stderr.write(`[Worker] \u{1F680} \u5F00\u59CB\u6267\u884C ${taskId}: ${title}
3808
- `);
3880
+ taskTitle = title;
3881
+ log.info(`\u{1F680} \u5F00\u59CB\u6267\u884C: ${title}`);
3809
3882
  ws.send(JSON.stringify({ type: "task:claim", taskId, agentId: AGENT_ID }));
3810
3883
  let prompt;
3811
3884
  let mode = "code";
@@ -3822,7 +3895,7 @@ function doTask(taskId, title, url, promptB64) {
3822
3895
  }
3823
3896
  try {
3824
3897
  const memUrl = `http://127.0.0.1:${WEB_PORT}/api/memory/for-task?q=${encodeURIComponent(title)}`;
3825
- const kbRaw = (0, import_node_child_process.execSync)(`curl -s "${memUrl}"`, { timeout: 5e3, stdio: ["ignore", "pipe", "ignore"] });
3898
+ const kbRaw = (0, import_node_child_process.execSync)(`curl -s "${memUrl}"`, { timeout: 5e3, stdio: ["ignore", "pipe", "ignore"], windowsHide: true });
3826
3899
  if (kbRaw && kbRaw.length > 0) {
3827
3900
  const kb = JSON.parse(kbRaw.toString());
3828
3901
  if (kb.hit > 0) {
@@ -3845,7 +3918,8 @@ Worker \u5DF2\u542F\u52A8\uFF0CClaude Code \u6B63\u5728\u521D\u59CB\u5316...`
3845
3918
  const child = (0, import_node_child_process.spawn)(CLAUDE_CLI, ["-p", prompt], {
3846
3919
  cwd: REPO_PATH,
3847
3920
  stdio: ["pipe", "pipe", "pipe"],
3848
- env: { ...process.env, NO_COLOR: "1" }
3921
+ env: { ...process.env, NO_COLOR: "1" },
3922
+ windowsHide: true
3849
3923
  });
3850
3924
  child.stdin.end();
3851
3925
  let output = "";
@@ -3864,6 +3938,14 @@ ${text}`
3864
3938
  const timeoutTimer = setTimeout(() => {
3865
3939
  process.stderr.write(`[Worker] \u23F0 \u8D85\u65F6 (${WORKER_TIMEOUT_MS / 1e3}s)\uFF0C\u5F3A\u5236\u7EC8\u6B62
3866
3940
  `);
3941
+ sendTaskDone(taskId, `\u274C (\u8D85\u65F6 ${WORKER_TIMEOUT_MS / 1e3}s) ${title}
3942
+ ${output.slice(-3e3)}`);
3943
+ ws.send(JSON.stringify({
3944
+ type: "room:message",
3945
+ roomId: "#review",
3946
+ text: `\u274C ${taskId} \u8D85\u65F6 ${WORKER_TIMEOUT_MS / 1e3}s\uFF0C\u5DF2\u7EC8\u6B62\u3002\u8F93\u51FA:
3947
+ ${output.slice(-1e3)}`
3948
+ }));
3867
3949
  try {
3868
3950
  child.kill("SIGKILL");
3869
3951
  } catch {
@@ -3879,8 +3961,7 @@ ${text}`
3879
3961
  clearInterval(progressTimer);
3880
3962
  clearTimeout(timeoutTimer);
3881
3963
  if (code === 0) {
3882
- process.stderr.write(`[Worker] \u2705 Claude Code \u5B8C\u6210 (exit ${code})
3883
- `);
3964
+ log.info(`\u2705 Claude Code \u5B8C\u6210 (exit ${code})`);
3884
3965
  if (mode === "market" || mode === "research" || mode === "template") {
3885
3966
  ws.send(JSON.stringify({
3886
3967
  type: "room:message",
@@ -3889,12 +3970,7 @@ ${text}`
3889
3970
 
3890
3971
  ${output.slice(-3e3)}`
3891
3972
  }));
3892
- ws.send(JSON.stringify({
3893
- type: "task:done",
3894
- taskId,
3895
- agentId: AGENT_ID,
3896
- result: output.slice(-5e3) || `${title} \u2014 \u65E0\u8F93\u51FA`
3897
- }));
3973
+ sendTaskDone(taskId, output.slice(-5e3) || `${title} \u2014 \u65E0\u8F93\u51FA`);
3898
3974
  try {
3899
3975
  tagAndSave(title, output);
3900
3976
  } catch {
@@ -3902,27 +3978,23 @@ ${output.slice(-3e3)}`
3902
3978
  } else {
3903
3979
  const branchMatch = output.match(/push.*?(task\/\S+|feat\/\S+|fix\/\S+)/i);
3904
3980
  const branch = branchMatch ? branchMatch[1] : `worker/${AGENT_ID}`;
3905
- ws.send(JSON.stringify({
3906
- type: "task:done",
3907
- taskId,
3908
- agentId: AGENT_ID,
3909
- branch,
3910
- result: `${title} \u2014
3981
+ sendTaskDone(taskId, `${title} \u2014
3911
3982
 
3912
- ${output.slice(-5e3)}`
3913
- }));
3983
+ ${output.slice(-5e3)}`);
3914
3984
  }
3915
3985
  } else {
3916
- process.stderr.write(`[Worker] \u274C Claude Code \u5931\u8D25 (exit ${code})
3917
- `);
3986
+ log.error(`\u274C Claude Code \u5931\u8D25 (exit ${code})`);
3918
3987
  ws.send(JSON.stringify({
3919
3988
  type: "room:message",
3920
3989
  roomId: "#review",
3921
3990
  text: `\u274C ${taskId} \u6267\u884C\u5931\u8D25 (exit ${code})\u3002\u8F93\u51FA:
3922
3991
  ${output.slice(-1e3)}`
3923
3992
  }));
3993
+ sendTaskDone(taskId, `\u274C (\u5931\u8D25 exit ${code}) ${title}
3994
+ ${output.slice(-3e3)}`);
3924
3995
  }
3925
3996
  setTimeout(() => {
3997
+ clearInterval(heartbeatTimer);
3926
3998
  ws.close();
3927
3999
  process.exit(code === 0 ? 0 : 1);
3928
4000
  }, 3e4);
@@ -3930,8 +4002,10 @@ ${output.slice(-1e3)}`
3930
4002
  child.on("error", (err) => {
3931
4003
  clearInterval(progressTimer);
3932
4004
  clearTimeout(timeoutTimer);
4005
+ clearInterval(heartbeatTimer);
3933
4006
  process.stderr.write(`[Worker] Claude Code \u542F\u52A8\u5931\u8D25: ${err.message}
3934
4007
  `);
4008
+ sendTaskDone(taskId, `\u274C (\u542F\u52A8\u5931\u8D25) ${title}: ${err.message}`);
3935
4009
  ws.send(JSON.stringify({
3936
4010
  type: "room:message",
3937
4011
  roomId: "#review",
@@ -4033,6 +4107,7 @@ connect();
4033
4107
  setTimeout(() => {
4034
4108
  if (!taskReceived) {
4035
4109
  process.stderr.write("[Worker] \u8D85\u65F6\u672A\u6536\u5230\u4EFB\u52A1\uFF0C\u9000\u51FA\n");
4110
+ clearInterval(heartbeatTimer);
4036
4111
  ws.close();
4037
4112
  process.exit(1);
4038
4113
  }