refactor: node tools and canvas host url
This commit is contained in:
@@ -76,6 +76,7 @@ import { isVerbose } from "../globals.js";
|
||||
import { onAgentEvent } from "../infra/agent-events.js";
|
||||
import { startGatewayBonjourAdvertiser } from "../infra/bonjour.js";
|
||||
import { startNodeBridgeServer } from "../infra/bridge/server.js";
|
||||
import { resolveCanvasHostUrl } from "../infra/canvas-host-url.js";
|
||||
import { GatewayLockError } from "../infra/gateway-lock.js";
|
||||
import {
|
||||
getLastHeartbeatEvent,
|
||||
@@ -90,6 +91,7 @@ import { getMachineDisplayName } from "../infra/machine-name.js";
|
||||
import {
|
||||
approveNodePairing,
|
||||
listNodePairing,
|
||||
renamePairedNode,
|
||||
rejectNodePairing,
|
||||
requestNodePairing,
|
||||
verifyNodeToken,
|
||||
@@ -379,6 +381,7 @@ import {
|
||||
validateNodePairRejectParams,
|
||||
validateNodePairRequestParams,
|
||||
validateNodePairVerifyParams,
|
||||
validateNodeRenameParams,
|
||||
validateProvidersStatusParams,
|
||||
validateRequestFrame,
|
||||
validateSendParams,
|
||||
@@ -485,6 +488,7 @@ const METHODS = [
|
||||
"node.pair.approve",
|
||||
"node.pair.reject",
|
||||
"node.pair.verify",
|
||||
"node.rename",
|
||||
"node.list",
|
||||
"node.describe",
|
||||
"node.invoke",
|
||||
@@ -609,39 +613,6 @@ function buildSnapshot(): Snapshot {
|
||||
const MAX_PAYLOAD_BYTES = 512 * 1024; // cap incoming frame size
|
||||
const MAX_BUFFERED_BYTES = 1.5 * 1024 * 1024; // per-connection send buffer limit
|
||||
|
||||
function deriveCanvasHostUrl(
|
||||
req: IncomingMessage | undefined,
|
||||
canvasPort: number | undefined,
|
||||
hostOverride?: string,
|
||||
) {
|
||||
if (!req || !canvasPort) return undefined;
|
||||
const hostHeader = req.headers.host?.trim();
|
||||
const forwardedProto =
|
||||
typeof req.headers["x-forwarded-proto"] === "string"
|
||||
? req.headers["x-forwarded-proto"]
|
||||
: Array.isArray(req.headers["x-forwarded-proto"])
|
||||
? req.headers["x-forwarded-proto"][0]
|
||||
: undefined;
|
||||
const scheme = forwardedProto === "https" ? "https" : "http";
|
||||
|
||||
let host = (hostOverride ?? "").trim();
|
||||
if (host === "0.0.0.0" || host === "::") host = "";
|
||||
if (!host && hostHeader) {
|
||||
try {
|
||||
const parsed = new URL(`http://${hostHeader}`);
|
||||
host = parsed.hostname;
|
||||
} catch {
|
||||
host = "";
|
||||
}
|
||||
}
|
||||
if (!host) {
|
||||
host = req.socket?.localAddress?.trim() ?? "";
|
||||
}
|
||||
if (!host) return undefined;
|
||||
|
||||
const formattedHost = host.includes(":") ? `[${host}]` : host;
|
||||
return `${scheme}://${formattedHost}:${canvasPort}`;
|
||||
}
|
||||
const MAX_CHAT_HISTORY_MESSAGES_BYTES = 6 * 1024 * 1024; // keep history responses comfortably under client WS limits
|
||||
const HANDSHAKE_TIMEOUT_MS = 10_000;
|
||||
const TICK_INTERVAL_MS = 30_000;
|
||||
@@ -3519,11 +3490,13 @@ export async function startGatewayServer(
|
||||
bridgeHost && bridgeHost !== "0.0.0.0" && bridgeHost !== "::"
|
||||
? bridgeHost
|
||||
: undefined;
|
||||
const canvasHostUrl = deriveCanvasHostUrl(
|
||||
upgradeReq,
|
||||
canvasHostPortForWs,
|
||||
canvasHostServer ? canvasHostOverride : undefined,
|
||||
);
|
||||
const canvasHostUrl = resolveCanvasHostUrl({
|
||||
canvasPort: canvasHostPortForWs,
|
||||
hostOverride: canvasHostServer ? canvasHostOverride : undefined,
|
||||
requestHost: upgradeReq.headers.host,
|
||||
forwardedProto: upgradeReq.headers["x-forwarded-proto"],
|
||||
localAddress: upgradeReq.socket?.localAddress,
|
||||
});
|
||||
logWs("in", "open", { connId, remoteAddr });
|
||||
const isWebchatConnect = (params: ConnectParams | null | undefined) =>
|
||||
params?.client?.mode === "webchat" ||
|
||||
@@ -5438,6 +5411,59 @@ export async function startGatewayServer(
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "node.rename": {
|
||||
const params = (req.params ?? {}) as Record<string, unknown>;
|
||||
if (!validateNodeRenameParams(params)) {
|
||||
respond(
|
||||
false,
|
||||
undefined,
|
||||
errorShape(
|
||||
ErrorCodes.INVALID_REQUEST,
|
||||
`invalid node.rename params: ${formatValidationErrors(validateNodeRenameParams.errors)}`,
|
||||
),
|
||||
);
|
||||
break;
|
||||
}
|
||||
const { nodeId, displayName } = params as {
|
||||
nodeId: string;
|
||||
displayName: string;
|
||||
};
|
||||
try {
|
||||
const trimmed = displayName.trim();
|
||||
if (!trimmed) {
|
||||
respond(
|
||||
false,
|
||||
undefined,
|
||||
errorShape(
|
||||
ErrorCodes.INVALID_REQUEST,
|
||||
"displayName required",
|
||||
),
|
||||
);
|
||||
break;
|
||||
}
|
||||
const updated = await renamePairedNode(nodeId, trimmed);
|
||||
if (!updated) {
|
||||
respond(
|
||||
false,
|
||||
undefined,
|
||||
errorShape(ErrorCodes.INVALID_REQUEST, "unknown nodeId"),
|
||||
);
|
||||
break;
|
||||
}
|
||||
respond(
|
||||
true,
|
||||
{ nodeId: updated.nodeId, displayName: updated.displayName },
|
||||
undefined,
|
||||
);
|
||||
} catch (err) {
|
||||
respond(
|
||||
false,
|
||||
undefined,
|
||||
errorShape(ErrorCodes.UNAVAILABLE, formatForLog(err)),
|
||||
);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "node.list": {
|
||||
const params = (req.params ?? {}) as Record<string, unknown>;
|
||||
if (!validateNodeListParams(params)) {
|
||||
|
||||
Reference in New Issue
Block a user