[Init] Initial commit - NetMesh terminal manager
Some checks failed
build-packages / resolve bundled mosh-client (push) Has been cancelled
build-packages / resolve bundled et-client (push) Has been cancelled
build-packages / build-macos (push) Has been cancelled
build-packages / build-windows (push) Has been cancelled
build-packages / build-linux-x64 (push) Has been cancelled
build-packages / build-linux-arm64 (push) Has been cancelled
build-packages / release (push) Has been cancelled
build-packages / update Nix release metadata (push) Has been cancelled
build-packages / bump homebrew tap (push) Has been cancelled
test / lint-and-test (push) Has been cancelled
AI automation / Route event (push) Has been cancelled
AI automation / Hand reopened issue to maintainers (push) Has been cancelled
AI automation / Clean source issue state (push) Has been cancelled
AI automation / Reconcile handoffs (push) Has been cancelled
AI automation / Classify issue (push) Has been cancelled
AI automation / Claude Code smoke (push) Has been cancelled
AI automation / Review issue follow-up (push) Has been cancelled
AI automation / Publish issue follow-up (push) Has been cancelled
AI automation / Implement with Claude Code (push) Has been cancelled
AI automation / Publish implement PR (push) Has been cancelled
AI automation / Continue queued issue comments (push) Has been cancelled
AI automation / Codex review loop (push) Has been cancelled
AI automation / Publish Codex fix (push) Has been cancelled
AI automation / Clear Codex dispatch marker (push) Has been cancelled
AI automation / Own PR re-request Codex (push) Has been cancelled
AI automation / External PR re-request Codex (push) Has been cancelled
AI automation / Poll Codex reaction / retry (push) Has been cancelled
build-et-binaries / build-linux-x64 (push) Has been cancelled
build-et-binaries / build-linux-arm64 (push) Has been cancelled
build-et-binaries / build-macos-universal (push) Has been cancelled
build-et-binaries / build-windows-x64 (push) Has been cancelled
build-et-binaries / release (push) Has been cancelled

This commit is contained in:
2026-09-13 18:24:01 +08:00
commit 3c72efcb7f
3255 changed files with 907009 additions and 0 deletions

View File

@@ -0,0 +1,127 @@
const test = require("node:test");
const assert = require("node:assert/strict");
const terminalBridge = require("./terminalBridge.cjs");
const {
createConnectionRef,
acquireConnectionRef,
discardTransport,
resetSshTransportRegistryForTests,
} = require("./sshConnectionPool.cjs");
// Verifies the terminalBridge close path respects connection multiplexing
// (issue #1204): closing one tab that shares an SSH connection must only close
// that tab's channel. Once the last tab is gone, the transport is parked briefly
// so a later same-host open can reuse it without another authentication round.
test.beforeEach(() => {
resetSshTransportRegistryForTests();
});
test.afterEach(() => {
resetSshTransportRegistryForTests();
});
function makeStream() {
return {
closed: 0,
close() { this.closed += 1; },
};
}
function makeConn() {
return {
ended: 0,
end() { this.ended += 1; },
};
}
function makeSession(conn, connRef) {
return {
stream: makeStream(),
conn,
chainConnections: [],
connRef,
zmodemSentry: { cancel() {} },
};
}
test("closing a reused SSH tab keeps the shared connection alive", () => {
const sessions = new Map();
terminalBridge.init({ sessions, electronModule: {} });
const conn = makeConn();
const owner = makeSession(conn, null);
const connRef = createConnectionRef(owner, conn, []);
const copy = makeSession(conn, null);
acquireConnectionRef(copy, connRef);
sessions.set("owner", owner);
sessions.set("copy", copy);
assert.equal(connRef.count, 2);
// Close the copy tab.
terminalBridge.closeSession({ sender: {} }, { sessionId: "copy" });
assert.equal(copy.stream.closed, 1, "copy channel closed");
assert.equal(conn.ended, 0, "shared connection must stay up for the owner");
assert.equal(connRef.count, 1);
assert.equal(sessions.has("copy"), false);
// Close the owner tab — now the last holder, so the connection is parked.
terminalBridge.closeSession({ sender: {} }, { sessionId: "owner" });
assert.equal(owner.stream.closed, 1, "owner channel closed");
assert.equal(conn.ended, 0, "connection remains parked for same-host reuse");
assert.equal(connRef.count, 0);
assert.equal(connRef.state, "idle");
assert.equal(discardTransport(connRef), true);
assert.equal(conn.ended, 1, "parked connection is still reclaimable");
});
test("closing the owner tab first does not strand the copy's connection", () => {
const sessions = new Map();
terminalBridge.init({ sessions, electronModule: {} });
const conn = makeConn();
const owner = makeSession(conn, null);
const connRef = createConnectionRef(owner, conn, []);
const copy = makeSession(conn, null);
acquireConnectionRef(copy, connRef);
sessions.set("owner", owner);
sessions.set("copy", copy);
// Close the owner first.
terminalBridge.closeSession({ sender: {} }, { sessionId: "owner" });
assert.equal(conn.ended, 0, "connection survives for the still-open copy");
assert.equal(connRef.count, 1);
// Closing the copy (now last) parks the connection for reuse.
terminalBridge.closeSession({ sender: {} }, { sessionId: "copy" });
assert.equal(conn.ended, 0);
assert.equal(connRef.state, "idle");
assert.equal(discardTransport(connRef), true);
assert.equal(conn.ended, 1);
});
test("legacy SSH session without connRef still ends its own connection + chain", () => {
const sessions = new Map();
terminalBridge.init({ sessions, electronModule: {} });
const conn = makeConn();
const chain = [makeConn(), makeConn()];
const session = {
stream: makeStream(),
conn,
chainConnections: chain,
connRef: null,
zmodemSentry: { cancel() {} },
};
sessions.set("legacy", session);
terminalBridge.closeSession({ sender: {} }, { sessionId: "legacy" });
assert.equal(session.stream.closed, 1);
assert.equal(conn.ended, 1, "non-multiplexed connection ends directly");
assert.equal(chain[0].ended, 1);
assert.equal(chain[1].ended, 1);
});