claude-relay 2.0.0 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/cli.js +4 -0
- package/lib/daemon.js +15 -0
- package/lib/server.js +62 -0
- package/package.json +1 -1
package/bin/cli.js
CHANGED
|
@@ -1266,6 +1266,10 @@ function showSetupGuide(config, ip, goBack) {
|
|
|
1266
1266
|
} else {
|
|
1267
1267
|
log(sym.bar + " " + a.dim + "Can't connect? Your phone must be on the same Wi-Fi network." + a.reset);
|
|
1268
1268
|
}
|
|
1269
|
+
if (config.tls) {
|
|
1270
|
+
var httpOnboardUrl = "http://" + (tsIP || ip) + ":" + (config.port + 1) + "/setup";
|
|
1271
|
+
log(sym.bar + " " + a.dim + "Certificate warning? Open " + a.reset + httpOnboardUrl);
|
|
1272
|
+
}
|
|
1269
1273
|
log(sym.bar);
|
|
1270
1274
|
log(sym.done + " " + a.dim + "Setup complete." + a.reset);
|
|
1271
1275
|
log(sym.end);
|
package/lib/daemon.js
CHANGED
|
@@ -187,6 +187,17 @@ relay.server.listen(config.port, function () {
|
|
|
187
187
|
saveConfig(config);
|
|
188
188
|
});
|
|
189
189
|
|
|
190
|
+
// --- HTTP onboarding server (only when TLS is active) ---
|
|
191
|
+
if (relay.onboardingServer) {
|
|
192
|
+
var onboardingPort = config.port + 1;
|
|
193
|
+
relay.onboardingServer.on("error", function (err) {
|
|
194
|
+
console.error("[daemon] Onboarding HTTP server error:", err.message);
|
|
195
|
+
});
|
|
196
|
+
relay.onboardingServer.listen(onboardingPort, function () {
|
|
197
|
+
console.log("[daemon] Onboarding HTTP on http://0.0.0.0:" + onboardingPort);
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
|
|
190
201
|
// --- Caffeinate (macOS) ---
|
|
191
202
|
var caffeinateProc = null;
|
|
192
203
|
if (config.keepAwake && process.platform === "darwin") {
|
|
@@ -216,6 +227,10 @@ function gracefulShutdown() {
|
|
|
216
227
|
}
|
|
217
228
|
} catch (e) {}
|
|
218
229
|
|
|
230
|
+
if (relay.onboardingServer) {
|
|
231
|
+
relay.onboardingServer.close();
|
|
232
|
+
}
|
|
233
|
+
|
|
219
234
|
relay.server.close(function () {
|
|
220
235
|
console.log("[daemon] Server closed");
|
|
221
236
|
process.exit(0);
|
package/lib/server.js
CHANGED
|
@@ -261,6 +261,67 @@ function createServer(opts) {
|
|
|
261
261
|
server = http.createServer(appHandler);
|
|
262
262
|
}
|
|
263
263
|
|
|
264
|
+
// --- HTTP onboarding server (only when TLS is active) ---
|
|
265
|
+
var onboardingServer = null;
|
|
266
|
+
if (tlsOptions) {
|
|
267
|
+
onboardingServer = http.createServer(function (req, res) {
|
|
268
|
+
var url = req.url.split("?")[0];
|
|
269
|
+
|
|
270
|
+
// CA certificate download
|
|
271
|
+
if (url === "/ca/download" && req.method === "GET" && caContent) {
|
|
272
|
+
res.writeHead(200, {
|
|
273
|
+
"Content-Type": "application/x-pem-file",
|
|
274
|
+
"Content-Disposition": 'attachment; filename="claude-relay-ca.pem"',
|
|
275
|
+
});
|
|
276
|
+
res.end(caContent);
|
|
277
|
+
return;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
// Setup page
|
|
281
|
+
if (url === "/setup" && req.method === "GET") {
|
|
282
|
+
var host = req.headers.host || "localhost";
|
|
283
|
+
var hostname = host.split(":")[0];
|
|
284
|
+
var httpsSetupUrl = "https://" + hostname + ":" + portNum;
|
|
285
|
+
var httpSetupUrl = "http://" + hostname + ":" + (portNum + 1);
|
|
286
|
+
res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
|
|
287
|
+
res.end(setupPageHtml(httpsSetupUrl, httpSetupUrl, !!caContent));
|
|
288
|
+
return;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
// /https-info — the setup page already fetches this to discover the HTTPS URL
|
|
292
|
+
if (url === "/https-info" && req.method === "GET") {
|
|
293
|
+
var hostname = (req.headers.host || "localhost").split(":")[0];
|
|
294
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
295
|
+
res.end(JSON.stringify({ httpsUrl: "https://" + hostname + ":" + portNum }));
|
|
296
|
+
return;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
// /info — CORS-enabled, used by setup page to verify HTTPS
|
|
300
|
+
if (url === "/info" && req.method === "GET") {
|
|
301
|
+
res.writeHead(200, {
|
|
302
|
+
"Content-Type": "application/json",
|
|
303
|
+
"Access-Control-Allow-Origin": "*",
|
|
304
|
+
});
|
|
305
|
+
var projectList = [];
|
|
306
|
+
projects.forEach(function (ctx, slug) {
|
|
307
|
+
projectList.push({ slug: slug, project: ctx.project, path: ctx.cwd });
|
|
308
|
+
});
|
|
309
|
+
res.end(JSON.stringify({ projects: projectList, version: currentVersion }));
|
|
310
|
+
return;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
// Favicon
|
|
314
|
+
if (url === "/favicon.svg" || url === "/favicon.ico") {
|
|
315
|
+
if (serveStatic(url, res)) return;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
// Everything else → redirect to HTTPS setup
|
|
319
|
+
var hostname = (req.headers.host || "localhost").split(":")[0];
|
|
320
|
+
res.writeHead(302, { "Location": "https://" + hostname + ":" + portNum + "/setup" });
|
|
321
|
+
res.end();
|
|
322
|
+
});
|
|
323
|
+
}
|
|
324
|
+
|
|
264
325
|
// --- WebSocket ---
|
|
265
326
|
var wss = new WebSocketServer({ noServer: true });
|
|
266
327
|
|
|
@@ -334,6 +395,7 @@ function createServer(opts) {
|
|
|
334
395
|
|
|
335
396
|
return {
|
|
336
397
|
server: server,
|
|
398
|
+
onboardingServer: onboardingServer,
|
|
337
399
|
isTLS: !!tlsOptions,
|
|
338
400
|
addProject: addProject,
|
|
339
401
|
removeProject: removeProject,
|