[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
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:
140
electron/bridges/terminalBridge.moshConpty.integration.cjs
Normal file
140
electron/bridges/terminalBridge.moshConpty.integration.cjs
Normal file
@@ -0,0 +1,140 @@
|
||||
"use strict";
|
||||
|
||||
const assert = require("node:assert/strict");
|
||||
const fs = require("node:fs");
|
||||
const Module = require("node:module");
|
||||
const os = require("node:os");
|
||||
const path = require("node:path");
|
||||
|
||||
function waitFor(predicate, description, timeoutMs = 15_000) {
|
||||
const startedAt = Date.now();
|
||||
return new Promise((resolve, reject) => {
|
||||
const poll = () => {
|
||||
if (predicate()) {
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
if (Date.now() - startedAt >= timeoutMs) {
|
||||
reject(new Error(`Timed out waiting for ${description}`));
|
||||
return;
|
||||
}
|
||||
setTimeout(poll, 25);
|
||||
};
|
||||
poll();
|
||||
});
|
||||
}
|
||||
|
||||
async function main() {
|
||||
assert.equal(process.platform, "win32", "Windows ConPTY only");
|
||||
const fakeSsh = process.env.NETCATTY_TEST_MOSH_SSH_EXE;
|
||||
const fakeClient = process.env.NETCATTY_TEST_MOSH_CLIENT_EXE;
|
||||
assert.ok(fakeSsh && fs.existsSync(fakeSsh), "compiled fake ssh executable is required");
|
||||
assert.ok(fakeClient && fs.existsSync(fakeClient), "compiled fake mosh-client executable is required");
|
||||
|
||||
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), "netcatty-mosh-conpty-"));
|
||||
const binDir = path.join(tmp, "bin");
|
||||
const resourcesPath = path.join(tmp, "resources");
|
||||
const clientDir = path.join(tmp, "project", "resources", "mosh", "win32-x64");
|
||||
fs.mkdirSync(binDir, { recursive: true });
|
||||
fs.mkdirSync(clientDir, { recursive: true });
|
||||
fs.copyFileSync(fakeSsh, path.join(binDir, "ssh.exe"));
|
||||
fs.copyFileSync(fakeClient, path.join(clientDir, "mosh-client.exe"));
|
||||
|
||||
const oldPath = process.env.PATH;
|
||||
process.env.PATH = `${binDir}${path.delimiter}${oldPath || ""}`;
|
||||
|
||||
const bridgePath = require.resolve("./terminalBridge.cjs");
|
||||
delete require.cache[bridgePath];
|
||||
const originalLoad = Module._load;
|
||||
Module._load = function loadWithoutElectronBinary(request, parent, isMain) {
|
||||
if (request === "electron") {
|
||||
return { dialog: {} };
|
||||
}
|
||||
return originalLoad.call(this, request, parent, isMain);
|
||||
};
|
||||
let bridge;
|
||||
try {
|
||||
bridge = require("./terminalBridge.cjs");
|
||||
} finally {
|
||||
Module._load = originalLoad;
|
||||
}
|
||||
const sessions = new Map();
|
||||
const sent = [];
|
||||
bridge.init({
|
||||
sessions,
|
||||
electronModule: {
|
||||
webContents: {
|
||||
fromId() {
|
||||
return { send: (channel, payload) => sent.push({ channel, payload }) };
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
try {
|
||||
const sessionId = "mosh-conpty-integration";
|
||||
await bridge.startMoshSession(
|
||||
{ sender: { id: 77 } },
|
||||
{
|
||||
sessionId,
|
||||
hostname: "example.com",
|
||||
username: "alice",
|
||||
authMethod: "password",
|
||||
password: "netcatty-test-password",
|
||||
cols: 80,
|
||||
rows: 24,
|
||||
env: { PATH: process.env.PATH },
|
||||
},
|
||||
{
|
||||
moshClientLookup: {
|
||||
platform: "win32",
|
||||
arch: "x64",
|
||||
projectRoot: path.join(tmp, "project"),
|
||||
resourcesPath,
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
await waitFor(
|
||||
() => sent.some((entry) => entry.channel === "netcatty:mosh:ready"),
|
||||
"mosh ready event",
|
||||
);
|
||||
await waitFor(
|
||||
() => sent.some((entry) => entry.channel === "netcatty:data"
|
||||
&& String(entry.payload?.data).includes("MOSHCATTY_TEST_READY")),
|
||||
"mosh-client output",
|
||||
);
|
||||
|
||||
const output = sent
|
||||
.filter((entry) => entry.channel === "netcatty:data")
|
||||
.map((entry) => String(entry.payload?.data || ""))
|
||||
.join("");
|
||||
assert.match(output, /key=ABCDEFGHIJKLMNOPQRSTUV==/);
|
||||
assert.match(output, /args=127\.0\.0\.1\|60002/);
|
||||
assert.match(output, /fallback=example\.com/);
|
||||
assert.equal(sessions.get(sessionId)?.moshHandshakePhase, "mosh-client");
|
||||
|
||||
bridge.writeToSession(null, { sessionId, data: "hello-from-conpty\r" });
|
||||
await waitFor(
|
||||
() => sent.some((entry) => entry.channel === "netcatty:data"
|
||||
&& String(entry.payload?.data).includes("MOSHCATTY_TEST_ECHO=hello-from-conpty")),
|
||||
"input routed to mosh-client",
|
||||
);
|
||||
|
||||
bridge.writeToSession(null, { sessionId, data: "quit\r" });
|
||||
await waitFor(() => !sessions.has(sessionId), "mosh-client exit");
|
||||
} finally {
|
||||
bridge.cleanupAllSessions();
|
||||
process.env.PATH = oldPath;
|
||||
delete require.cache[bridgePath];
|
||||
fs.rmSync(tmp, { recursive: true, force: true });
|
||||
}
|
||||
}
|
||||
|
||||
main().then(() => {
|
||||
console.log("Windows ConPTY Mosh handoff passed");
|
||||
process.exit(0);
|
||||
}).catch((err) => {
|
||||
console.error(err);
|
||||
process.exit(1);
|
||||
});
|
||||
Reference in New Issue
Block a user