@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 +1 -1
- package/dist/gateway.cjs +52 -24
- package/package.json +1 -1
package/dist/cli.cjs
CHANGED
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 (
|
|
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
|
|
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
|
|
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
|
|
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
|
|
14568
|
+
settleLatch(key, entry, "failed");
|
|
14534
14569
|
return;
|
|
14535
14570
|
}
|
|
14536
14571
|
} else {
|
|
14537
|
-
entry
|
|
14572
|
+
settleLatch(key, entry, "failed");
|
|
14538
14573
|
return;
|
|
14539
14574
|
}
|
|
14540
|
-
|
|
14541
|
-
void pollInBackground(key, session, entry);
|
|
14542
|
-
});
|
|
14575
|
+
void pollInBackground(key, session, entry);
|
|
14543
14576
|
} catch {
|
|
14544
|
-
entry
|
|
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.
|
|
14553
|
-
return { status: existing.status };
|
|
14585
|
+
return { status: await existing.settled };
|
|
14554
14586
|
}
|
|
14555
|
-
let
|
|
14556
|
-
const
|
|
14557
|
-
|
|
14587
|
+
let settle;
|
|
14588
|
+
const settled = new Promise((resolve47) => {
|
|
14589
|
+
settle = resolve47;
|
|
14558
14590
|
});
|
|
14559
|
-
const entry = { status: "pending",
|
|
14591
|
+
const entry = { status: "pending", settled, settle };
|
|
14560
14592
|
latches.set(key, entry);
|
|
14561
|
-
|
|
14562
|
-
|
|
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
|
}
|