Add custom headers to direct connections (#2922)

* Add custom headers to direct connections

* Address custom header review feedback

* Fix direct connection header integration

* Fix desktop relay E2E transport setup

---------

Co-authored-by: Claude <claude@Claudes-Mac-mini.local>
Co-authored-by: Mohamed Boudra <boudra.moha@gmail.com>
This commit is contained in:
Claude
2026-08-06 11:05:40 +02:00
committed by GitHub
co-authored by Claude Mohamed Boudra
parent 098122be8d
commit 73ba37a07a
38 changed files with 1190 additions and 125 deletions
+192 -15
View File
@@ -139,8 +139,123 @@ export async function installDesktopRuntime(
let daemonRunning = true;
let currentPid: number | null = cfg.daemonPid ?? null;
let startCount = 0;
let nextTransportSessionId = 0;
const transportSessions = new Map<string, WebSocket>();
const desktopEventHandlers = new Map<string, Set<(payload: unknown) => void>>();
window.__desktopDaemonStartRequested = false;
function emitDesktopEvent(event: string, payload: unknown) {
for (const handler of desktopEventHandlers.get(event) ?? []) {
handler(payload);
}
}
function bytesToBase64(bytes: Uint8Array): string {
let binary = "";
for (const byte of bytes) {
binary += String.fromCharCode(byte);
}
return btoa(binary);
}
function base64ToBytes(base64: string): Uint8Array {
const binary = atob(base64);
const bytes = new Uint8Array(binary.length);
for (let index = 0; index < binary.length; index += 1) {
bytes[index] = binary.charCodeAt(index);
}
return bytes;
}
function parseWebSocketTransportTarget(args?: Record<string, unknown>): {
url: string;
protocols: string[];
} {
const url = typeof args?.url === "string" ? args.url : "";
const protocols = Array.isArray(args?.protocols)
? args.protocols.filter((protocol): protocol is string => typeof protocol === "string")
: [];
const headers =
args?.headers && typeof args.headers === "object"
? Object.entries(args.headers as Record<string, unknown>)
: [];
const passwordProtocol = protocols.find((protocol) => protocol.startsWith("paseo.bearer."));
const supportsHeaders =
headers.length === 0 ||
(headers.length === 1 &&
headers[0][0].toLowerCase() === "authorization" &&
typeof headers[0][1] === "string" &&
passwordProtocol !== undefined &&
headers[0][1] === `Bearer ${passwordProtocol.slice("paseo.bearer.".length)}`);
if (!url || !supportsHeaders) {
throw new Error("The browser-backed desktop E2E transport cannot attach custom headers.");
}
return { url, protocols };
}
async function openWebSocketTransport(args?: Record<string, unknown>): Promise<string> {
const target = parseWebSocketTransportTarget(args);
const sessionId = `e2e-websocket-session-${++nextTransportSessionId}`;
const socket = new WebSocket(target.url, target.protocols);
socket.binaryType = "arraybuffer";
transportSessions.set(sessionId, socket);
return await new Promise<string>((resolve, reject) => {
let opened = false;
socket.addEventListener("open", () => {
opened = true;
resolve(sessionId);
emitDesktopEvent("local-daemon-transport-event", { sessionId, kind: "open" });
});
socket.addEventListener("message", async (event) => {
if (typeof event.data === "string") {
emitDesktopEvent("local-daemon-transport-event", {
sessionId,
kind: "message",
text: event.data,
});
return;
}
const buffer =
event.data instanceof ArrayBuffer
? event.data
: await (event.data as Blob).arrayBuffer();
emitDesktopEvent("local-daemon-transport-event", {
sessionId,
kind: "message",
binaryBase64: bytesToBase64(new Uint8Array(buffer)),
});
});
socket.addEventListener("close", (event) => {
transportSessions.delete(sessionId);
if (!opened) {
reject(new Error("Desktop E2E WebSocket closed before opening."));
return;
}
emitDesktopEvent("local-daemon-transport-event", {
sessionId,
kind: "close",
code: event.code,
reason: event.reason,
});
});
socket.addEventListener("error", () => {
if (!opened) {
transportSessions.delete(sessionId);
reject(new Error("Desktop E2E WebSocket failed to open."));
return;
}
emitDesktopEvent("local-daemon-transport-event", {
sessionId,
kind: "error",
error: "Desktop E2E WebSocket transport error.",
});
});
});
}
function buildDaemonStatus() {
return {
serverId: cfg.serverId,
@@ -175,6 +290,55 @@ export async function installDesktopRuntime(
}
}
function patchDesktopSettings(args?: Record<string, unknown>) {
const daemon = args?.daemon;
if (
daemon !== null &&
typeof daemon === "object" &&
"manageBuiltInDaemon" in daemon &&
typeof daemon.manageBuiltInDaemon === "boolean"
) {
manageDaemon = daemon.manageBuiltInDaemon;
}
return {
releaseChannel: "stable",
daemon: { manageBuiltInDaemon: manageDaemon, keepRunningAfterQuit: true },
};
}
function sendWebSocketTransportMessage(args?: Record<string, unknown>): null {
const sessionId = typeof args?.sessionId === "string" ? args.sessionId : "";
const socket = transportSessions.get(sessionId);
if (!socket || socket.readyState !== WebSocket.OPEN) {
throw new Error(`Desktop E2E WebSocket session is not open: ${sessionId}`);
}
if (typeof args?.text === "string") {
socket.send(args.text);
return null;
}
if (typeof args?.binaryBase64 === "string") {
socket.send(base64ToBytes(args.binaryBase64));
return null;
}
throw new Error("Desktop E2E WebSocket send requires a payload.");
}
function closeWebSocketTransport(args?: Record<string, unknown>): null {
const sessionId = typeof args?.sessionId === "string" ? args.sessionId : "";
transportSessions.get(sessionId)?.close();
transportSessions.delete(sessionId);
return null;
}
const webSocketTransportCommandHandlers: Record<
string,
(args?: Record<string, unknown>) => unknown
> = {
open_websocket_daemon_transport: openWebSocketTransport,
send_local_daemon_transport_message: sendWebSocketTransportMessage,
close_local_daemon_transport: closeWebSocketTransport,
};
const desktopBridge: {
platform: string;
invoke: (command: string, args?: Record<string, unknown>) => Promise<unknown>;
@@ -183,7 +347,10 @@ export async function installDesktopRuntime(
open: (options?: Record<string, unknown>) => Promise<string | string[] | null>;
};
getPendingOpenProject: () => Promise<string | null>;
events: { on: () => Promise<() => void> };
opener: { openUrl: (url: string) => Promise<void> };
events: {
on: (event: string, handler: (payload: unknown) => void) => Promise<() => void>;
};
editor?: {
listTargets: () => Promise<DesktopEditorTargetConfig[]>;
openTarget: (input: DesktopEditorOpenRecord) => Promise<void>;
@@ -239,19 +406,7 @@ export async function installDesktopRuntime(
}
if (command === "patch_desktop_settings") {
const daemon = args?.daemon;
if (
daemon !== null &&
typeof daemon === "object" &&
"manageBuiltInDaemon" in daemon &&
typeof daemon.manageBuiltInDaemon === "boolean"
) {
manageDaemon = daemon.manageBuiltInDaemon;
}
return {
releaseChannel: "stable",
daemon: { manageBuiltInDaemon: manageDaemon, keepRunningAfterQuit: true },
};
return patchDesktopSettings(args);
}
if (command === "stop_desktop_daemon") {
@@ -264,6 +419,11 @@ export async function installDesktopRuntime(
return startDesktopDaemon();
}
const transportCommandHandler = webSocketTransportCommandHandlers[command];
if (transportCommandHandler) {
return await transportCommandHandler(args);
}
return null;
},
dialog: {
@@ -280,7 +440,24 @@ export async function installDesktopRuntime(
},
},
getPendingOpenProject: async () => null,
events: { on: async () => () => undefined },
opener: {
openUrl: async (url) => {
localStorage.setItem("@paseo:e2e-opened-url", url);
},
},
events: {
on: async (event, handler) => {
const handlers = desktopEventHandlers.get(event) ?? new Set();
handlers.add(handler);
desktopEventHandlers.set(event, handlers);
return () => {
handlers.delete(handler);
if (handlers.size === 0) {
desktopEventHandlers.delete(event);
}
};
},
},
};
if (cfg.editorTargets) {