@memoraone/mcp 0.1.58 → 0.1.60

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/cli.cjs CHANGED
@@ -231,7 +231,7 @@ var require_package = __commonJS({
231
231
  "package.json"(exports2, module2) {
232
232
  module2.exports = {
233
233
  name: "@memoraone/mcp",
234
- version: "0.1.58",
234
+ version: "0.1.60",
235
235
  type: "module",
236
236
  main: "dist/index.cjs",
237
237
  exports: {
package/dist/gateway.cjs CHANGED
@@ -14130,6 +14130,19 @@ async function removeSession(sessionId) {
14130
14130
  } catch {
14131
14131
  }
14132
14132
  }
14133
+ function pauseHeartbeatWhenGetSseCloses(req, res, sessionId) {
14134
+ let paused = false;
14135
+ const pause = () => {
14136
+ if (paused) return;
14137
+ if (!res.headersSent || res.statusCode !== 200) return;
14138
+ paused = true;
14139
+ const session = sessionsById.get(sessionId);
14140
+ if (!session || session.closed) return;
14141
+ session.heartbeat?.stop();
14142
+ };
14143
+ res.once("close", pause);
14144
+ req.socket?.once("close", pause);
14145
+ }
14133
14146
  async function closeGatewayMcpSessionsForWorkspace(workspaceRoot) {
14134
14147
  const root = path50.resolve(workspaceRoot);
14135
14148
  const ids = [...sessionsById.values()].filter((s) => s.workspaceRoot === root).map((s) => s.sessionId);
@@ -14258,6 +14271,18 @@ async function handleAuthenticatedGatewayMcpRequest(req, res, auth, options = {}
14258
14271
  await existing.transport.handleRequest(req, res, parsed3.body);
14259
14272
  return;
14260
14273
  }
14274
+ if (method === "GET") {
14275
+ const heartbeat = existing.heartbeat;
14276
+ if (heartbeat && !heartbeat.isRunning()) {
14277
+ await heartbeat.start();
14278
+ }
14279
+ pauseHeartbeatWhenGetSseCloses(req, res, existing.sessionId);
14280
+ try {
14281
+ await existing.transport.handleRequest(req, res);
14282
+ } catch {
14283
+ }
14284
+ return;
14285
+ }
14261
14286
  await existing.transport.handleRequest(req, res);
14262
14287
  return;
14263
14288
  }
@@ -14322,6 +14347,9 @@ function sendPairingGate(res, body) {
14322
14347
  });
14323
14348
  res.end(body);
14324
14349
  }
14350
+ function canWriteGatewayResponse(res) {
14351
+ return !res.writableEnded && !res.destroyed;
14352
+ }
14325
14353
  async function handleGatewayMcpAuthRequest(req, res, url, options = {}) {
14326
14354
  if (url.pathname !== GATEWAY_MCP_PATH) return false;
14327
14355
  const env2 = options.env ?? process.env;
@@ -14393,8 +14421,7 @@ async function handleGatewayMcpAuthRequest(req, res, url, options = {}) {
14393
14421
  return true;
14394
14422
  }
14395
14423
  const pairing = await coordinator.ensure(parsed2.workspaceRoot);
14396
- if (pairing.status === "pending") {
14397
- sendPairingGate(res, "Pairing pending");
14424
+ if (!canWriteGatewayResponse(res)) {
14398
14425
  return true;
14399
14426
  }
14400
14427
  if (pairing.status === "failed") {
@@ -14434,6 +14461,9 @@ async function handleGatewayMcpAuthRequest(req, res, url, options = {}) {
14434
14461
  );
14435
14462
  return true;
14436
14463
  } catch {
14464
+ if (!canWriteGatewayResponse(res)) {
14465
+ return true;
14466
+ }
14437
14467
  sendUnauthorized(res, env2, parsed2.workspaceRoot);
14438
14468
  return true;
14439
14469
  }
@@ -14486,13 +14516,19 @@ function createGatewayUnboundPairingCoordinator(options = {}) {
14486
14516
  const openUrl = options.openUrl ?? ((url) => openUrlInBrowser(url));
14487
14517
  const pollIntervalMs = options.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS2;
14488
14518
  const apiUrl = (options.apiUrl ?? config2.apiUrl).replace(/\/+$/, "");
14519
+ function settleLatch(key, entry, status) {
14520
+ if (entry.status !== "pending") return;
14521
+ entry.status = status;
14522
+ entry.settle(status);
14523
+ latches.delete(key);
14524
+ }
14489
14525
  async function pollInBackground(key, session, entry) {
14490
14526
  for (; ; ) {
14491
14527
  let result;
14492
14528
  try {
14493
14529
  result = await session.poll();
14494
14530
  } catch {
14495
- entry.status = "failed";
14531
+ settleLatch(key, entry, "failed");
14496
14532
  return;
14497
14533
  }
14498
14534
  if (result.status === "pending") {
@@ -14500,15 +14536,14 @@ function createGatewayUnboundPairingCoordinator(options = {}) {
14500
14536
  continue;
14501
14537
  }
14502
14538
  if (result.status === "ready") {
14503
- entry.status = "ready";
14504
- latches.delete(key);
14539
+ settleLatch(key, entry, "ready");
14505
14540
  return;
14506
14541
  }
14507
14542
  if (result.status === "backend_failure" && result.operation === "poll") {
14508
14543
  await delay3(pollIntervalMs);
14509
14544
  continue;
14510
14545
  }
14511
- entry.status = "failed";
14546
+ settleLatch(key, entry, "failed");
14512
14547
  return;
14513
14548
  }
14514
14549
  }
@@ -14530,18 +14565,16 @@ function createGatewayUnboundPairingCoordinator(options = {}) {
14530
14565
  try {
14531
14566
  await openUrl(authorizationUrl);
14532
14567
  } catch {
14533
- entry.status = "failed";
14568
+ settleLatch(key, entry, "failed");
14534
14569
  return;
14535
14570
  }
14536
14571
  } else {
14537
- entry.status = "failed";
14572
+ settleLatch(key, entry, "failed");
14538
14573
  return;
14539
14574
  }
14540
- setImmediate(() => {
14541
- void pollInBackground(key, session, entry);
14542
- });
14575
+ void pollInBackground(key, session, entry);
14543
14576
  } catch {
14544
- entry.status = "failed";
14577
+ settleLatch(key, entry, "failed");
14545
14578
  }
14546
14579
  }
14547
14580
  return {
@@ -14549,21 +14582,16 @@ function createGatewayUnboundPairingCoordinator(options = {}) {
14549
14582
  const key = path51.resolve(workspaceRoot);
14550
14583
  const existing = latches.get(key);
14551
14584
  if (existing) {
14552
- await existing.startPromise;
14553
- return { status: existing.status };
14585
+ return { status: await existing.settled };
14554
14586
  }
14555
- let resolveStart;
14556
- const startPromise = new Promise((resolve47) => {
14557
- resolveStart = resolve47;
14587
+ let settle;
14588
+ const settled = new Promise((resolve47) => {
14589
+ settle = resolve47;
14558
14590
  });
14559
- const entry = { status: "pending", startPromise };
14591
+ const entry = { status: "pending", settled, settle };
14560
14592
  latches.set(key, entry);
14561
- try {
14562
- await startPairing(key, entry);
14563
- } finally {
14564
- resolveStart();
14565
- }
14566
- return { status: entry.status };
14593
+ void startPairing(key, entry);
14594
+ return { status: await entry.settled };
14567
14595
  }
14568
14596
  };
14569
14597
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@memoraone/mcp",
3
- "version": "0.1.58",
3
+ "version": "0.1.60",
4
4
  "type": "module",
5
5
  "main": "dist/index.cjs",
6
6
  "exports": {