@sleep2agi/commhub-server 0.9.0-preview.21 → 0.9.0-preview.22

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/src/tools.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
2
  import { z } from "zod/v4";
3
3
  import { db, uuidv4, logTaskEvent, chainReplyToParent, hashToken, generateId, generateNetworkToken } from "./db.js";
4
- import { pushEvent } from "./push.js";
4
+ import { pushEvent, pushNetworkObserverEvent } from "./push.js";
5
5
  import { assertNodeActive } from "./lifecycle-guard.js";
6
6
  import { getUserNetworkRole, createNetworkTokenForNode } from "./auth.js";
7
7
  import {
@@ -958,6 +958,9 @@ export function registerTools(server: McpServer, clientIP?: string, enforceNetwo
958
958
  if (target.state === "online") {
959
959
  pushEvent(targetAlias, { type: "new_task", inbox_count: pending?.cnt ?? 1, priority, from: from_session, ...(canonical.renamed ? { renamed_from: alias } : {}) }, effectiveNetId);
960
960
  }
961
+ // #461 network observer summary — unconditional (task row exists
962
+ // even when the target is offline/queued), metadata only.
963
+ pushNetworkObserverEvent(effectiveNetId, { type: "new_task", task_id: id, from: from_session, to: targetAlias, status: target.state === "online" ? "delivered" : "queued", priority });
961
964
 
962
965
  if (target.state === "offline") {
963
966
  return {
@@ -1185,6 +1188,8 @@ export function registerTools(server: McpServer, clientIP?: string, enforceNetwo
1185
1188
 
1186
1189
  const session = scopedSessionStatus(alias, effectiveNetId);
1187
1190
  pushEvent(alias, { type: "new_reply", from: from_session, message_id: id, in_reply_to, status: replyStatus }, effectiveNetId);
1191
+ // #461 network observer summary — ids + routing only, no reply text.
1192
+ pushNetworkObserverEvent(effectiveNetId, { type: "new_reply", task_id: in_reply_to ?? null, message_id: id, from: from_session, to: alias, status: replyStatus });
1188
1193
 
1189
1194
  return {
1190
1195
  content: [{
@@ -1267,6 +1272,7 @@ export function registerTools(server: McpServer, clientIP?: string, enforceNetwo
1267
1272
  logTaskEvent(task_id, task.status, "delivered", from_session, "retry");
1268
1273
  // SSE push (unconditional — channel is keyed by alias, not network)
1269
1274
  pushEvent(task.to_name, { type: "new_task", inbox_count: 1, priority: task.priority, from: from_session }, effectiveNetId ?? task.network_id ?? null);
1275
+ pushNetworkObserverEvent(effectiveNetId ?? task.network_id ?? null, { type: "new_task", task_id, from: from_session, to: task.to_name, status: "delivered", priority: task.priority });
1270
1276
  return {
1271
1277
  content: [{ type: "text" as const, text: JSON.stringify({ ok: true, task_id, retried_to: task.to_name }) }],
1272
1278
  };
@@ -1419,6 +1425,7 @@ export function registerTools(server: McpServer, clientIP?: string, enforceNetwo
1419
1425
  });
1420
1426
  logTaskEvent(task_id, task.status, "delivered", from_session, `reassign: ${oldAlias} → ${reassignedAlias}`);
1421
1427
  pushEvent(reassignedAlias, { type: "new_task", inbox_count: 1, priority: task.priority, from: from_session, ...(canonical.renamed ? { renamed_from: new_alias } : {}) }, effectiveNetId ?? task.network_id ?? null);
1428
+ pushNetworkObserverEvent(effectiveNetId ?? task.network_id ?? null, { type: "new_task", task_id, from: from_session, to: reassignedAlias, status: "delivered", priority: task.priority });
1422
1429
  return { content: [{ type: "text" as const, text: JSON.stringify({ ok: true, task_id, reassigned_from: oldAlias, reassigned_to: reassignedAlias, ...(canonical.renamed ? { renamed_from: new_alias, renamed_to: reassignedAlias } : {}) }) }] };
1423
1430
  }
1424
1431
  );
@@ -14,8 +14,11 @@ import { register, login } from "./auth.js";
14
14
 
15
15
  const SERVER_DB = mkdtempSync(join(tmpdir(), "anet-upload-http-db-")) + "/commhub.db";
16
16
  const UPLOADS_DIR = mkdtempSync(join(tmpdir(), "anet-upload-http-fs-"));
17
- const PORT = 19000 + Math.floor(Math.random() * 1000);
18
- const BASE = `http://127.0.0.1:${PORT}`;
17
+ // #438 corrective: private bootServer({ port: 0 }) instance — the OS
18
+ // assigns the port and BASE is derived from the ACTUAL bound port, so
19
+ // this suite is immune to both the parent-side random-port TOCTOU and
20
+ // the aggregate module-cache no-op (import no longer boots anything).
21
+ let BASE = "";
19
22
 
20
23
  let server: any;
21
24
  let userToken = "";
@@ -27,7 +30,6 @@ beforeAll(async () => {
27
30
  // we want to validate the production code path).
28
31
  process.env.COMMHUB_DB = SERVER_DB;
29
32
  process.env.COMMHUB_UPLOADS_DIR = UPLOADS_DIR;
30
- process.env.PORT = String(PORT);
31
33
  process.env.HOST = "127.0.0.1";
32
34
 
33
35
  // Use a unique username + strong password each run so we don't trip
@@ -50,16 +52,17 @@ beforeAll(async () => {
50
52
  }
51
53
  expect(userToken).toBeTruthy();
52
54
 
53
- // Import the server module — its top-level `Bun.serve` call binds
54
- // the port immediately. The import side effect IS the server start.
55
- await import("./index.js");
55
+ // Importing is side-effect-free now; boot a private instance and
56
+ // read the real port back.
57
+ const { bootServer } = await import("./server.js");
58
+ server = bootServer({ port: 0, hostname: "127.0.0.1" });
59
+ BASE = `http://127.0.0.1:${server.port}`;
56
60
  // Tiny settle so the listener is ready.
57
61
  await new Promise((r) => setTimeout(r, 100));
58
62
  });
59
63
 
60
64
  afterAll(() => {
61
- // Best-effort cleanup. The Bun.serve handle is created at import
62
- // time so we can't easily stop it — process exit handles that.
65
+ try { server?.stop?.(true); } catch {}
63
66
  try { rmSync(UPLOADS_DIR, { recursive: true, force: true }); } catch {}
64
67
  try { rmSync(SERVER_DB, { recursive: true, force: true }); } catch {}
65
68
  });