termbridge 0.3.10 → 0.3.12
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/dist/bin.js +127 -102
- package/dist/bin.js.map +1 -1
- package/package.json +1 -1
- package/ui/dist/assets/{index-CgajTDZC.js → index-Re4cTx4o.js} +37 -37
- package/ui/dist/index.html +1 -1
package/dist/bin.js
CHANGED
|
@@ -2480,8 +2480,8 @@ var createAuth = ({
|
|
|
2480
2480
|
if (!record) {
|
|
2481
2481
|
return null;
|
|
2482
2482
|
}
|
|
2483
|
+
wsTokens.delete(token);
|
|
2483
2484
|
if (record.expiresAt <= clock()) {
|
|
2484
|
-
wsTokens.delete(token);
|
|
2485
2485
|
return null;
|
|
2486
2486
|
}
|
|
2487
2487
|
return getSession(record.sessionId);
|
|
@@ -2599,22 +2599,10 @@ var createTerminalRegistry = () => {
|
|
|
2599
2599
|
};
|
|
2600
2600
|
|
|
2601
2601
|
// src/server/server.ts
|
|
2602
|
-
import { createServer as createHttpServer
|
|
2603
|
-
import { request as httpsRequest } from "https";
|
|
2602
|
+
import { createServer as createHttpServer } from "http";
|
|
2604
2603
|
import { randomBytes as randomBytes3 } from "crypto";
|
|
2605
2604
|
import { WebSocketServer, WebSocket as WsWebSocket } from "ws";
|
|
2606
2605
|
|
|
2607
|
-
// ../packages/shared/src/index.ts
|
|
2608
|
-
var TERMINAL_CONTROL_KEYS = [
|
|
2609
|
-
"ctrl_c",
|
|
2610
|
-
"esc",
|
|
2611
|
-
"tab",
|
|
2612
|
-
"up",
|
|
2613
|
-
"down",
|
|
2614
|
-
"left",
|
|
2615
|
-
"right"
|
|
2616
|
-
];
|
|
2617
|
-
|
|
2618
2606
|
// src/server/static.ts
|
|
2619
2607
|
import { readFile } from "fs/promises";
|
|
2620
2608
|
import { extname, resolve as resolve3 } from "path";
|
|
@@ -2666,10 +2654,8 @@ var createStaticHandler = (uiDistPath, basePath) => {
|
|
|
2666
2654
|
};
|
|
2667
2655
|
};
|
|
2668
2656
|
|
|
2669
|
-
// src/server/
|
|
2657
|
+
// src/server/http-utils.ts
|
|
2670
2658
|
var MAX_HTTP_BODY_SIZE = 64 * 1024;
|
|
2671
|
-
var MAX_WS_MESSAGE_SIZE = 1024 * 1024;
|
|
2672
|
-
var MAX_INPUT_LENGTH = 64 * 1024;
|
|
2673
2659
|
var jsonResponse = (response, status, payload) => {
|
|
2674
2660
|
const body = JSON.stringify(payload);
|
|
2675
2661
|
response.statusCode = status;
|
|
@@ -2716,6 +2702,21 @@ var isAllowedOrigin = (origin, host, forwardedHost) => {
|
|
|
2716
2702
|
}
|
|
2717
2703
|
};
|
|
2718
2704
|
var resolveForwardedHost = (header) => Array.isArray(header) ? header[0] : header;
|
|
2705
|
+
|
|
2706
|
+
// ../packages/shared/src/index.ts
|
|
2707
|
+
var TERMINAL_CONTROL_KEYS = [
|
|
2708
|
+
"ctrl_c",
|
|
2709
|
+
"esc",
|
|
2710
|
+
"tab",
|
|
2711
|
+
"up",
|
|
2712
|
+
"down",
|
|
2713
|
+
"left",
|
|
2714
|
+
"right"
|
|
2715
|
+
];
|
|
2716
|
+
|
|
2717
|
+
// src/server/ws-utils.ts
|
|
2718
|
+
var MAX_WS_MESSAGE_SIZE = 1024 * 1024;
|
|
2719
|
+
var MAX_INPUT_LENGTH = 64 * 1024;
|
|
2719
2720
|
var allowedControlKeys = new Set(TERMINAL_CONTROL_KEYS);
|
|
2720
2721
|
var parseClientMessage = (payload) => {
|
|
2721
2722
|
const size = typeof payload === "string" ? payload.length : Array.isArray(payload) ? payload.reduce((sum, buf) => sum + buf.length, 0) : payload.byteLength;
|
|
@@ -2748,50 +2749,74 @@ var parseClientMessage = (payload) => {
|
|
|
2748
2749
|
var sendWsMessage = (socket, message) => {
|
|
2749
2750
|
socket.send(JSON.stringify(message));
|
|
2750
2751
|
};
|
|
2752
|
+
|
|
2753
|
+
// src/server/proxy.ts
|
|
2754
|
+
import { request as httpRequest } from "http";
|
|
2755
|
+
import { request as httpsRequest } from "https";
|
|
2756
|
+
var resolveProxyUrl = (config, targetPath, search) => {
|
|
2757
|
+
if (typeof config.proxyPort === "number") {
|
|
2758
|
+
return new URL(`http://localhost:${config.proxyPort}${targetPath}${search}`);
|
|
2759
|
+
}
|
|
2760
|
+
if (config.devProxyUrl) {
|
|
2761
|
+
try {
|
|
2762
|
+
return new URL(`${targetPath}${search}`, config.devProxyUrl);
|
|
2763
|
+
} catch {
|
|
2764
|
+
return null;
|
|
2765
|
+
}
|
|
2766
|
+
}
|
|
2767
|
+
return null;
|
|
2768
|
+
};
|
|
2769
|
+
var proxyRequest = (config, request, response, targetPath, search) => {
|
|
2770
|
+
const targetUrl = resolveProxyUrl(config, targetPath, search);
|
|
2771
|
+
if (!targetUrl) {
|
|
2772
|
+
response.statusCode = 502;
|
|
2773
|
+
response.end("proxy error");
|
|
2774
|
+
return;
|
|
2775
|
+
}
|
|
2776
|
+
const proxyHeaders = { ...request.headers, ...config.devProxyHeaders ?? {} };
|
|
2777
|
+
delete proxyHeaders.cookie;
|
|
2778
|
+
delete proxyHeaders.host;
|
|
2779
|
+
proxyHeaders.host = targetUrl.host;
|
|
2780
|
+
const requestImpl = targetUrl.protocol === "https:" ? httpsRequest : httpRequest;
|
|
2781
|
+
const proxyReq = requestImpl(
|
|
2782
|
+
targetUrl,
|
|
2783
|
+
{ method: request.method, headers: proxyHeaders },
|
|
2784
|
+
(proxyRes) => {
|
|
2785
|
+
response.writeHead(proxyRes.statusCode, proxyRes.headers);
|
|
2786
|
+
proxyRes.pipe(response);
|
|
2787
|
+
}
|
|
2788
|
+
);
|
|
2789
|
+
proxyReq.on("error", () => {
|
|
2790
|
+
response.statusCode = 502;
|
|
2791
|
+
response.end("proxy error");
|
|
2792
|
+
});
|
|
2793
|
+
request.pipe(proxyReq);
|
|
2794
|
+
};
|
|
2795
|
+
var getProxyWebSocketUrl = (config) => {
|
|
2796
|
+
try {
|
|
2797
|
+
if (typeof config.proxyPort === "number") {
|
|
2798
|
+
return new URL(`http://localhost:${config.proxyPort}`);
|
|
2799
|
+
}
|
|
2800
|
+
if (config.devProxyUrl) {
|
|
2801
|
+
return new URL(config.devProxyUrl);
|
|
2802
|
+
}
|
|
2803
|
+
} catch {
|
|
2804
|
+
return null;
|
|
2805
|
+
}
|
|
2806
|
+
return null;
|
|
2807
|
+
};
|
|
2808
|
+
|
|
2809
|
+
// src/server/server.ts
|
|
2751
2810
|
var createSessionName = () => `termbridge-${randomBytes3(4).toString("hex")}`;
|
|
2752
2811
|
var createAppServer = (deps) => {
|
|
2753
2812
|
const staticHandler = createStaticHandler(deps.uiDistPath, "/__tb/app");
|
|
2754
2813
|
const wss = new WebSocketServer({ noServer: true });
|
|
2755
2814
|
const connectionInfo = /* @__PURE__ */ new WeakMap();
|
|
2756
2815
|
const hasProxy = typeof deps.proxyPort === "number" || deps.devProxyUrl !== void 0;
|
|
2757
|
-
const
|
|
2758
|
-
|
|
2759
|
-
|
|
2760
|
-
|
|
2761
|
-
if (deps.devProxyUrl) {
|
|
2762
|
-
try {
|
|
2763
|
-
return new URL(`${targetPath}${search}`, deps.devProxyUrl);
|
|
2764
|
-
} catch {
|
|
2765
|
-
return null;
|
|
2766
|
-
}
|
|
2767
|
-
}
|
|
2768
|
-
return null;
|
|
2769
|
-
};
|
|
2770
|
-
const proxyRequest = (request, response, targetPath, search) => {
|
|
2771
|
-
const targetUrl = resolveProxyUrl(targetPath, search);
|
|
2772
|
-
if (!targetUrl) {
|
|
2773
|
-
response.statusCode = 502;
|
|
2774
|
-
response.end("proxy error");
|
|
2775
|
-
return;
|
|
2776
|
-
}
|
|
2777
|
-
const proxyHeaders = { ...request.headers, ...deps.devProxyHeaders ?? {} };
|
|
2778
|
-
delete proxyHeaders.cookie;
|
|
2779
|
-
delete proxyHeaders.host;
|
|
2780
|
-
proxyHeaders.host = targetUrl.host;
|
|
2781
|
-
const requestImpl = targetUrl.protocol === "https:" ? httpsRequest : httpRequest;
|
|
2782
|
-
const proxyReq = requestImpl(
|
|
2783
|
-
targetUrl,
|
|
2784
|
-
{ method: request.method, headers: proxyHeaders },
|
|
2785
|
-
(proxyRes) => {
|
|
2786
|
-
response.writeHead(proxyRes.statusCode, proxyRes.headers);
|
|
2787
|
-
proxyRes.pipe(response);
|
|
2788
|
-
}
|
|
2789
|
-
);
|
|
2790
|
-
proxyReq.on("error", () => {
|
|
2791
|
-
response.statusCode = 502;
|
|
2792
|
-
response.end("proxy error");
|
|
2793
|
-
});
|
|
2794
|
-
request.pipe(proxyReq);
|
|
2816
|
+
const proxyConfig = {
|
|
2817
|
+
proxyPort: deps.proxyPort,
|
|
2818
|
+
devProxyUrl: deps.devProxyUrl,
|
|
2819
|
+
devProxyHeaders: deps.devProxyHeaders
|
|
2795
2820
|
};
|
|
2796
2821
|
const server = createHttpServer(async (request, response) => {
|
|
2797
2822
|
const url = new URL(request.url, `http://${request.headers.host}`);
|
|
@@ -2890,7 +2915,7 @@ var createAppServer = (deps) => {
|
|
|
2890
2915
|
const handled = await staticHandler(request, response);
|
|
2891
2916
|
if (!handled) {
|
|
2892
2917
|
if (hasProxy && deps.auth.getSessionFromRequest(request)) {
|
|
2893
|
-
proxyRequest(request, response, url.pathname, url.search);
|
|
2918
|
+
proxyRequest(proxyConfig, request, response, url.pathname, url.search);
|
|
2894
2919
|
return;
|
|
2895
2920
|
}
|
|
2896
2921
|
response.statusCode = 404;
|
|
@@ -2901,17 +2926,15 @@ var createAppServer = (deps) => {
|
|
|
2901
2926
|
const url = new URL(request.url, `http://${request.headers.host}`);
|
|
2902
2927
|
if (!url.pathname.startsWith("/__tb/ws/terminal/")) {
|
|
2903
2928
|
if (hasProxy && deps.auth.getSessionFromRequest(request)) {
|
|
2904
|
-
|
|
2905
|
-
|
|
2906
|
-
baseUrl = typeof deps.proxyPort === "number" ? new URL(`http://localhost:${deps.proxyPort}`) : new URL(deps.devProxyUrl);
|
|
2907
|
-
} catch {
|
|
2929
|
+
const baseUrl = getProxyWebSocketUrl(proxyConfig);
|
|
2930
|
+
if (!baseUrl) {
|
|
2908
2931
|
socket.destroy();
|
|
2909
2932
|
return;
|
|
2910
2933
|
}
|
|
2911
2934
|
const wsProtocol = baseUrl.protocol === "https:" ? "wss:" : "ws:";
|
|
2912
2935
|
const targetUrl = new URL(`${url.pathname}${url.search}`, baseUrl);
|
|
2913
2936
|
targetUrl.protocol = wsProtocol;
|
|
2914
|
-
const proxyHeaders = { ...request.headers, ...
|
|
2937
|
+
const proxyHeaders = { ...request.headers, ...proxyConfig.devProxyHeaders ?? {} };
|
|
2915
2938
|
delete proxyHeaders.cookie;
|
|
2916
2939
|
delete proxyHeaders.host;
|
|
2917
2940
|
proxyHeaders.host = targetUrl.host;
|
|
@@ -3844,47 +3867,7 @@ var createSandboxDaytonaServerProvider = (options = {}) => {
|
|
|
3844
3867
|
};
|
|
3845
3868
|
};
|
|
3846
3869
|
|
|
3847
|
-
// src/cli/
|
|
3848
|
-
var resolveUiDistPath = () => {
|
|
3849
|
-
const currentDir = dirname3(fileURLToPath(import.meta.url));
|
|
3850
|
-
const candidates = [
|
|
3851
|
-
resolve5(currentDir, "../../ui/dist"),
|
|
3852
|
-
resolve5(currentDir, "../ui/dist"),
|
|
3853
|
-
resolve5(process.cwd(), "ui/dist"),
|
|
3854
|
-
resolve5(process.cwd(), "cli/ui/dist")
|
|
3855
|
-
];
|
|
3856
|
-
for (const candidate of candidates) {
|
|
3857
|
-
if (existsSync(candidate)) {
|
|
3858
|
-
return candidate;
|
|
3859
|
-
}
|
|
3860
|
-
}
|
|
3861
|
-
return candidates[0];
|
|
3862
|
-
};
|
|
3863
|
-
var packLocalCli = (logger) => {
|
|
3864
|
-
const cliDir = resolve5(dirname3(fileURLToPath(import.meta.url)), "..");
|
|
3865
|
-
const packageJson = resolve5(cliDir, "package.json");
|
|
3866
|
-
if (!existsSync(packageJson)) {
|
|
3867
|
-
return void 0;
|
|
3868
|
-
}
|
|
3869
|
-
const result = spawnSync("npm", ["pack"], { cwd: cliDir, encoding: "utf8" });
|
|
3870
|
-
if (result.status !== 0) {
|
|
3871
|
-
const stderr = result.stderr?.toString().trim();
|
|
3872
|
-
logger.warn(`Local CLI pack failed${stderr ? ` (${stderr})` : ""}`);
|
|
3873
|
-
return void 0;
|
|
3874
|
-
}
|
|
3875
|
-
const lines = result.stdout?.toString().trim().split(/\r?\n/).filter(Boolean) ?? [];
|
|
3876
|
-
const filename = lines[lines.length - 1];
|
|
3877
|
-
if (!filename) {
|
|
3878
|
-
logger.warn("Local CLI pack failed (no output)");
|
|
3879
|
-
return void 0;
|
|
3880
|
-
}
|
|
3881
|
-
return resolve5(cliDir, filename);
|
|
3882
|
-
};
|
|
3883
|
-
var createDefaultLogger = () => ({
|
|
3884
|
-
info: (message) => console.log(message),
|
|
3885
|
-
warn: (message) => console.warn(message),
|
|
3886
|
-
error: (message) => console.error(message)
|
|
3887
|
-
});
|
|
3870
|
+
// src/cli/agent-config.ts
|
|
3888
3871
|
var defaultAgentEnvKeys = [
|
|
3889
3872
|
"OPENAI_API_KEY",
|
|
3890
3873
|
"OPENAI_BASE_URL",
|
|
@@ -3955,6 +3938,48 @@ var resolveAutoAgentNames = (env) => {
|
|
|
3955
3938
|
const auto = parseBoolean(env.TERMBRIDGE_SANDBOX_AGENT_AUTO);
|
|
3956
3939
|
return auto ? ["all"] : [];
|
|
3957
3940
|
};
|
|
3941
|
+
|
|
3942
|
+
// src/cli/start.ts
|
|
3943
|
+
var resolveUiDistPath = () => {
|
|
3944
|
+
const currentDir = dirname3(fileURLToPath(import.meta.url));
|
|
3945
|
+
const candidates = [
|
|
3946
|
+
resolve5(currentDir, "../../ui/dist"),
|
|
3947
|
+
resolve5(currentDir, "../ui/dist"),
|
|
3948
|
+
resolve5(process.cwd(), "ui/dist"),
|
|
3949
|
+
resolve5(process.cwd(), "cli/ui/dist")
|
|
3950
|
+
];
|
|
3951
|
+
for (const candidate of candidates) {
|
|
3952
|
+
if (existsSync(candidate)) {
|
|
3953
|
+
return candidate;
|
|
3954
|
+
}
|
|
3955
|
+
}
|
|
3956
|
+
return candidates[0];
|
|
3957
|
+
};
|
|
3958
|
+
var packLocalCli = (logger) => {
|
|
3959
|
+
const cliDir = resolve5(dirname3(fileURLToPath(import.meta.url)), "..");
|
|
3960
|
+
const packageJson = resolve5(cliDir, "package.json");
|
|
3961
|
+
if (!existsSync(packageJson)) {
|
|
3962
|
+
return void 0;
|
|
3963
|
+
}
|
|
3964
|
+
const result = spawnSync("npm", ["pack"], { cwd: cliDir, encoding: "utf8" });
|
|
3965
|
+
if (result.status !== 0) {
|
|
3966
|
+
const stderr = result.stderr?.toString().trim();
|
|
3967
|
+
logger.warn(`Local CLI pack failed${stderr ? ` (${stderr})` : ""}`);
|
|
3968
|
+
return void 0;
|
|
3969
|
+
}
|
|
3970
|
+
const lines = result.stdout?.toString().trim().split(/\r?\n/).filter(Boolean) ?? [];
|
|
3971
|
+
const filename = lines[lines.length - 1];
|
|
3972
|
+
if (!filename) {
|
|
3973
|
+
logger.warn("Local CLI pack failed (no output)");
|
|
3974
|
+
return void 0;
|
|
3975
|
+
}
|
|
3976
|
+
return resolve5(cliDir, filename);
|
|
3977
|
+
};
|
|
3978
|
+
var createDefaultLogger = () => ({
|
|
3979
|
+
info: (message) => console.log(message),
|
|
3980
|
+
warn: (message) => console.warn(message),
|
|
3981
|
+
error: (message) => console.error(message)
|
|
3982
|
+
});
|
|
3958
3983
|
var resolveBackendMode = (value) => {
|
|
3959
3984
|
if (!value) {
|
|
3960
3985
|
return "tmux";
|