[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,226 @@
"use strict";
const fs = require("node:fs");
const os = require("node:os");
const path = require("node:path");
const { createHash } = require("node:crypto");
const { execFile } = require("node:child_process");
const { promisify } = require("node:util");
const { utils } = require("ssh2");
const { BaseAgent, createAgent } = require("ssh2/lib/agent.js");
const execFileAsync = promisify(execFile);
function publicKeyBlob(key) {
try {
const parsed = typeof key?.getPublicSSH === "function" ? key : utils.parseKey(key);
if (parsed instanceof Error || typeof parsed?.getPublicSSH !== "function") return null;
return parsed.getPublicSSH().toString("base64");
} catch {
return null;
}
}
function resolveIdentityPath(rawPath, context = {}) {
if (typeof rawPath !== "string") return "";
const env = context.env ?? process.env;
const localHostname = context.localHostname || os.hostname();
const hostname = context.hostname || "";
const port = String(context.port || 22);
const username = context.username || "";
const proxyJump = context.proxyJump || "";
const tokenValues = {
"%": "%",
d: os.homedir(),
h: hostname,
i: String(context.uid ?? (typeof process.getuid === "function" ? process.getuid() : "")),
j: proxyJump,
k: context.hostKeyAlias || hostname,
L: context.shortLocalHostname || localHostname.split(".")[0],
l: localHostname,
n: context.originalHostname || hostname,
p: port,
r: username,
u: context.localUsername || os.userInfo().username,
};
tokenValues.C = createHash("sha1")
.update(`${localHostname}${hostname}${port}${username}${proxyJump}`)
.digest("hex");
let resolved = rawPath.trim()
.replace(/%([%CdhijkLlnpru])/g, (match, token) => tokenValues[token] ?? match)
.replace(/^~(?=$|[\\/])/, os.homedir())
.replace(/\$\{([A-Za-z_][A-Za-z0-9_]*)\}/g, (_match, name) => env[name] ?? "")
.replace(/\$([A-Za-z_][A-Za-z0-9_]*)/g, (_match, name) => env[name] ?? "");
if (!path.isAbsolute(resolved) && resolved) {
resolved = path.resolve(resolved);
}
return resolved;
}
async function loadPreferredPublicKeyBlobs(identityFilePaths, publicKeys, options, deps) {
const preferred = new Set();
const resolvedIdentityPaths = [];
const unavailablePublicKeyPaths = [];
let providedPreferredCount = 0;
for (const publicKey of publicKeys ?? []) {
const blob = publicKeyBlob(publicKey);
if (blob) {
preferred.add(blob);
providedPreferredCount += 1;
}
}
for (const rawPath of identityFilePaths ?? []) {
const identityPath = resolveIdentityPath(rawPath, options);
if (!identityPath) continue;
resolvedIdentityPaths.push(identityPath);
const publicKeyPath = identityPath.endsWith(".pub") ? identityPath : `${identityPath}.pub`;
try {
const contents = await deps.readFile(publicKeyPath, "utf8");
const blob = publicKeyBlob(contents);
if (blob) preferred.add(blob);
else unavailablePublicKeyPaths.push(publicKeyPath);
} catch (error) {
unavailablePublicKeyPaths.push(publicKeyPath);
deps.log?.("Configured SSH public key is unavailable", {
publicKeyPath,
error: error instanceof Error ? error.message : String(error),
});
}
}
return { preferred, providedPreferredCount, resolvedIdentityPaths, unavailablePublicKeyPaths };
}
function getIdentities(agent) {
return new Promise((resolve, reject) => {
agent.getIdentities((error, identities) => {
if (error) reject(error);
else resolve(Array.isArray(identities) ? identities : []);
});
});
}
class IdentityAwareAgent extends BaseAgent {
constructor(delegate, preferred, identitiesOnly) {
super();
this.delegate = delegate;
this.preferred = preferred;
this.identitiesOnly = identitiesOnly;
}
getIdentities(callback) {
this.delegate.getIdentities((error, identities) => {
if (error) return callback(error);
const keys = Array.isArray(identities) ? identities : [];
const matching = [];
const remaining = [];
for (const key of keys) {
if (this.preferred.has(publicKeyBlob(key))) matching.push(key);
else remaining.push(key);
}
callback(null, this.identitiesOnly ? matching : [...matching, ...remaining]);
});
}
sign(publicKey, data, options, callback) {
this.delegate.sign(publicKey, data, options, callback);
}
getStream(callback) {
if (typeof this.delegate.getStream !== "function") {
callback(new Error("SSH agent does not support forwarding streams"));
return;
}
this.delegate.getStream(callback);
}
}
function shouldLoadFromMacKeychain(options, platform) {
return platform === "darwin"
&& options.useKeychain === true
&& typeof options.addKeysToAgent === "string"
&& options.addKeysToAgent.toLowerCase() === "yes"
&& Array.isArray(options.identityFilePaths)
&& options.identityFilePaths.length > 0;
}
async function defaultRunSshAdd(args, { socketPath, env }) {
await execFileAsync("/usr/bin/ssh-add", args, {
timeout: 5000,
windowsHide: true,
env: {
...env,
SSH_AUTH_SOCK: socketPath,
SSH_ASKPASS_REQUIRE: "never",
},
});
}
async function prepareSystemSshAgent(options, injected = {}) {
if (!options?.socketPath) return null;
const deps = {
createAgent: injected.createAgent ?? createAgent,
readFile: injected.readFile ?? fs.promises.readFile,
runSshAdd: injected.runSshAdd,
platform: injected.platform ?? process.platform,
env: injected.env ?? process.env,
log: injected.log,
};
const agent = deps.createAgent(options.socketPath);
const { preferred, providedPreferredCount, resolvedIdentityPaths, unavailablePublicKeyPaths } = await loadPreferredPublicKeyBlobs(
options.identityFilePaths,
options.agentPublicKeys,
{ hostname: options.hostname, port: options.port, username: options.username, env: deps.env },
deps,
);
if (shouldLoadFromMacKeychain(options, deps.platform)) {
let loadedBlobs = new Set();
try {
loadedBlobs = new Set((await getIdentities(agent)).map(publicKeyBlob).filter(Boolean));
} catch (error) {
deps.log?.("Could not inspect SSH agent identities before Keychain load", {
error: error instanceof Error ? error.message : String(error),
});
}
// Without a readable .pub selector we cannot tell whether the configured
// identity is already loaded, so still ask Apple's ssh-add to load it.
// In non-strict mode the delegate can then safely advertise the full list.
const hasEveryPreferredIdentity = unavailablePublicKeyPaths.length === 0
&& preferred.size > 0
&& [...preferred].every((blob) => loadedBlobs.has(blob));
if (!hasEveryPreferredIdentity) {
try {
const args = ["--apple-load-keychain", ...resolvedIdentityPaths];
if (deps.runSshAdd) await deps.runSshAdd(args);
else await defaultRunSshAdd(args, { socketPath: options.socketPath, env: deps.env });
} catch (error) {
deps.log?.("macOS Keychain could not load the configured SSH identity", {
error: error instanceof Error ? error.message : String(error),
});
}
}
}
if (
options.identitiesOnly === true
&& (preferred.size === 0 || (unavailablePublicKeyPaths.length > 0 && providedPreferredCount === 0))
) {
const error = new Error(
unavailablePublicKeyPaths.length > 0
? `IdentitiesOnly requires a readable public key selector. Missing or invalid: ${unavailablePublicKeyPaths.join(", ")}`
: "IdentitiesOnly requires at least one IdentityFile with a readable public .pub key.",
);
error.code = "ERR_SSH_AGENT_IDENTITY_SELECTOR_UNAVAILABLE";
throw error;
}
return new IdentityAwareAgent(agent, preferred, options.identitiesOnly === true);
}
module.exports = {
IdentityAwareAgent,
prepareSystemSshAgent,
publicKeyBlob,
resolveIdentityPath,
shouldLoadFromMacKeychain,
};