gitterm 0.0.2 → 0.0.3
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/index.js +155 -119
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -10034,7 +10034,7 @@ async function runTunnel(args) {
|
|
|
10034
10034
|
`);
|
|
10035
10035
|
}
|
|
10036
10036
|
if (!args.port) {
|
|
10037
|
-
const portInput = await prompt("Enter the
|
|
10037
|
+
const portInput = await prompt("Enter the port your Opencode server is running on (e.g. 4096): ");
|
|
10038
10038
|
const parsedPort = Number.parseInt(portInput, 10);
|
|
10039
10039
|
if (!Number.isFinite(parsedPort) || parsedPort <= 0) {
|
|
10040
10040
|
throw new Error("Invalid port number");
|
|
@@ -10065,25 +10065,122 @@ async function runTunnel(args) {
|
|
|
10065
10065
|
primaryPort = args.port;
|
|
10066
10066
|
}
|
|
10067
10067
|
const exposedPorts = parseExposeArgs(args.expose);
|
|
10068
|
-
const
|
|
10069
|
-
const pendingRequestMeta = new Map;
|
|
10068
|
+
const pendingRequests = new Map;
|
|
10070
10069
|
const activeRequests = new Map;
|
|
10071
|
-
function
|
|
10072
|
-
|
|
10073
|
-
|
|
10074
|
-
|
|
10075
|
-
|
|
10076
|
-
|
|
10077
|
-
|
|
10078
|
-
|
|
10079
|
-
|
|
10080
|
-
|
|
10081
|
-
|
|
10082
|
-
|
|
10083
|
-
|
|
10070
|
+
function createBodyStream(pending) {
|
|
10071
|
+
return new ReadableStream({
|
|
10072
|
+
start: (controller) => {
|
|
10073
|
+
pending.bodyController = controller;
|
|
10074
|
+
if (pending.bufferedChunks.length > 0) {
|
|
10075
|
+
for (const chunk of pending.bufferedChunks) {
|
|
10076
|
+
controller.enqueue(chunk);
|
|
10077
|
+
}
|
|
10078
|
+
pending.bufferedChunks = [];
|
|
10079
|
+
}
|
|
10080
|
+
if (pending.bodyClosed)
|
|
10081
|
+
controller.close();
|
|
10082
|
+
},
|
|
10083
|
+
cancel: () => {
|
|
10084
|
+
pending.abortController.abort();
|
|
10085
|
+
}
|
|
10086
|
+
});
|
|
10084
10087
|
}
|
|
10085
10088
|
const effectiveWsUrl = args.wsUrl ?? connectCfg?.wsUrl ?? DEFAULT_WS_URL;
|
|
10086
10089
|
const ws = new WebSocket(effectiveWsUrl);
|
|
10090
|
+
async function startUpstreamRequest(id, pending) {
|
|
10091
|
+
if (pending.started)
|
|
10092
|
+
return;
|
|
10093
|
+
pending.started = true;
|
|
10094
|
+
const meta = pending.meta;
|
|
10095
|
+
const abortController = pending.abortController;
|
|
10096
|
+
activeRequests.set(id, abortController);
|
|
10097
|
+
try {
|
|
10098
|
+
const base = new URL(targetBase.replace(/\/$/, "") + "/");
|
|
10099
|
+
base.hostname = "localhost";
|
|
10100
|
+
base.port = String(meta.port ?? primaryPort);
|
|
10101
|
+
const url = new URL(meta.path.replace(/^\//, ""), base);
|
|
10102
|
+
const headers = new Headers(meta.headers);
|
|
10103
|
+
headers.delete("host");
|
|
10104
|
+
headers.delete("content-length");
|
|
10105
|
+
headers.delete("connection");
|
|
10106
|
+
headers.delete("keep-alive");
|
|
10107
|
+
headers.delete("proxy-authenticate");
|
|
10108
|
+
headers.delete("proxy-authorization");
|
|
10109
|
+
headers.delete("te");
|
|
10110
|
+
headers.delete("trailers");
|
|
10111
|
+
headers.delete("transfer-encoding");
|
|
10112
|
+
headers.delete("upgrade");
|
|
10113
|
+
const upstream = await fetch(url, {
|
|
10114
|
+
method: meta.method,
|
|
10115
|
+
headers,
|
|
10116
|
+
body: pending.ignoreBody ? undefined : pending.bodyStream ?? undefined,
|
|
10117
|
+
redirect: "manual",
|
|
10118
|
+
signal: abortController.signal
|
|
10119
|
+
});
|
|
10120
|
+
ws.send(JSON.stringify({
|
|
10121
|
+
type: "response",
|
|
10122
|
+
id,
|
|
10123
|
+
statusCode: upstream.status,
|
|
10124
|
+
headers: headersToRecord(upstream.headers),
|
|
10125
|
+
timestamp: Date.now()
|
|
10126
|
+
}));
|
|
10127
|
+
if (!upstream.body) {
|
|
10128
|
+
activeRequests.delete(id);
|
|
10129
|
+
ws.send(JSON.stringify({
|
|
10130
|
+
type: "data",
|
|
10131
|
+
id,
|
|
10132
|
+
final: true,
|
|
10133
|
+
timestamp: Date.now()
|
|
10134
|
+
}));
|
|
10135
|
+
return;
|
|
10136
|
+
}
|
|
10137
|
+
const reader = upstream.body.getReader();
|
|
10138
|
+
try {
|
|
10139
|
+
while (true) {
|
|
10140
|
+
const { done, value } = await reader.read();
|
|
10141
|
+
if (done)
|
|
10142
|
+
break;
|
|
10143
|
+
if (!value)
|
|
10144
|
+
continue;
|
|
10145
|
+
ws.send(JSON.stringify({
|
|
10146
|
+
type: "data",
|
|
10147
|
+
id,
|
|
10148
|
+
data: bytesToBase64(value),
|
|
10149
|
+
final: false,
|
|
10150
|
+
timestamp: Date.now()
|
|
10151
|
+
}));
|
|
10152
|
+
}
|
|
10153
|
+
} finally {
|
|
10154
|
+
reader.releaseLock();
|
|
10155
|
+
}
|
|
10156
|
+
activeRequests.delete(id);
|
|
10157
|
+
ws.send(JSON.stringify({
|
|
10158
|
+
type: "data",
|
|
10159
|
+
id,
|
|
10160
|
+
final: true,
|
|
10161
|
+
timestamp: Date.now()
|
|
10162
|
+
}));
|
|
10163
|
+
} catch (error) {
|
|
10164
|
+
activeRequests.delete(id);
|
|
10165
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
10166
|
+
return;
|
|
10167
|
+
}
|
|
10168
|
+
ws.send(JSON.stringify({
|
|
10169
|
+
type: "response",
|
|
10170
|
+
id,
|
|
10171
|
+
statusCode: 502,
|
|
10172
|
+
headers: { "content-type": "application/json" },
|
|
10173
|
+
timestamp: Date.now()
|
|
10174
|
+
}));
|
|
10175
|
+
ws.send(JSON.stringify({
|
|
10176
|
+
type: "data",
|
|
10177
|
+
id,
|
|
10178
|
+
data: bytesToBase64(new TextEncoder().encode(JSON.stringify({ error: "upstream_error" }))),
|
|
10179
|
+
final: true,
|
|
10180
|
+
timestamp: Date.now()
|
|
10181
|
+
}));
|
|
10182
|
+
}
|
|
10183
|
+
}
|
|
10087
10184
|
ws.addEventListener("open", () => {
|
|
10088
10185
|
console.log("Establishing secure tunnel for workspace...");
|
|
10089
10186
|
ws.send(JSON.stringify({
|
|
@@ -10146,123 +10243,63 @@ Press Ctrl+C to disconnect.
|
|
|
10146
10243
|
controller.abort();
|
|
10147
10244
|
activeRequests.delete(frame.id);
|
|
10148
10245
|
}
|
|
10149
|
-
|
|
10150
|
-
|
|
10246
|
+
const pending = pendingRequests.get(frame.id);
|
|
10247
|
+
if (pending?.bodyController) {
|
|
10248
|
+
try {
|
|
10249
|
+
pending.bodyController.close();
|
|
10250
|
+
} catch {}
|
|
10251
|
+
}
|
|
10252
|
+
pendingRequests.delete(frame.id);
|
|
10151
10253
|
return;
|
|
10152
10254
|
}
|
|
10153
10255
|
if (frame.type === "request") {
|
|
10154
|
-
|
|
10155
|
-
pendingRequestMeta.set(frame.id, {
|
|
10256
|
+
const meta = {
|
|
10156
10257
|
method: (frame.method ?? "GET").toUpperCase(),
|
|
10157
10258
|
path: frame.path ?? "/",
|
|
10158
10259
|
headers: frame.headers ?? {},
|
|
10159
10260
|
port: frame.port
|
|
10160
|
-
}
|
|
10261
|
+
};
|
|
10262
|
+
const ignoreBody = meta.method === "GET" || meta.method === "HEAD";
|
|
10263
|
+
const pending = {
|
|
10264
|
+
meta,
|
|
10265
|
+
bodyStream: null,
|
|
10266
|
+
bufferedChunks: [],
|
|
10267
|
+
bodyClosed: false,
|
|
10268
|
+
started: false,
|
|
10269
|
+
abortController: new AbortController,
|
|
10270
|
+
ignoreBody
|
|
10271
|
+
};
|
|
10272
|
+
pending.bodyStream = ignoreBody ? null : createBodyStream(pending);
|
|
10273
|
+
pendingRequests.set(frame.id, pending);
|
|
10274
|
+
startUpstreamRequest(frame.id, pending);
|
|
10161
10275
|
return;
|
|
10162
10276
|
}
|
|
10163
10277
|
if (frame.type === "data") {
|
|
10164
|
-
const
|
|
10165
|
-
if (!
|
|
10278
|
+
const pending = pendingRequests.get(frame.id);
|
|
10279
|
+
if (!pending)
|
|
10280
|
+
return;
|
|
10281
|
+
if (pending.ignoreBody) {
|
|
10282
|
+
if (frame.final)
|
|
10283
|
+
pendingRequests.delete(frame.id);
|
|
10166
10284
|
return;
|
|
10167
10285
|
}
|
|
10168
|
-
if (frame.data)
|
|
10169
|
-
|
|
10286
|
+
if (frame.data) {
|
|
10287
|
+
const chunk = base64ToBytes(frame.data);
|
|
10288
|
+
if (pending.bodyController) {
|
|
10289
|
+
pending.bodyController.enqueue(chunk);
|
|
10290
|
+
} else {
|
|
10291
|
+
pending.bufferedChunks.push(chunk);
|
|
10292
|
+
}
|
|
10293
|
+
}
|
|
10170
10294
|
if (!frame.final)
|
|
10171
10295
|
return;
|
|
10172
|
-
|
|
10173
|
-
|
|
10174
|
-
const meta = pendingRequestMeta.get(frame.id);
|
|
10175
|
-
if (!meta)
|
|
10176
|
-
return;
|
|
10177
|
-
pendingRequestMeta.delete(frame.id);
|
|
10178
|
-
try {
|
|
10179
|
-
const reqBody = mergeBody(frame.id);
|
|
10180
|
-
const base = new URL(targetBase.replace(/\/$/, "") + "/");
|
|
10181
|
-
base.hostname = "localhost";
|
|
10182
|
-
base.port = String(meta.port ?? primaryPort);
|
|
10183
|
-
const url = new URL(meta.path.replace(/^\//, ""), base);
|
|
10184
|
-
const headers = new Headers(meta.headers);
|
|
10185
|
-
headers.delete("host");
|
|
10186
|
-
headers.delete("content-length");
|
|
10187
|
-
headers.delete("connection");
|
|
10188
|
-
headers.delete("keep-alive");
|
|
10189
|
-
headers.delete("proxy-authenticate");
|
|
10190
|
-
headers.delete("proxy-authorization");
|
|
10191
|
-
headers.delete("te");
|
|
10192
|
-
headers.delete("trailers");
|
|
10193
|
-
headers.delete("transfer-encoding");
|
|
10194
|
-
headers.delete("upgrade");
|
|
10195
|
-
const upstream = await fetch(url, {
|
|
10196
|
-
method: meta.method,
|
|
10197
|
-
headers,
|
|
10198
|
-
body: reqBody.byteLength > 0 ? reqBody : undefined,
|
|
10199
|
-
redirect: "manual",
|
|
10200
|
-
signal: abortController.signal
|
|
10201
|
-
});
|
|
10202
|
-
ws.send(JSON.stringify({
|
|
10203
|
-
type: "response",
|
|
10204
|
-
id: frame.id,
|
|
10205
|
-
statusCode: upstream.status,
|
|
10206
|
-
headers: headersToRecord(upstream.headers),
|
|
10207
|
-
timestamp: Date.now()
|
|
10208
|
-
}));
|
|
10209
|
-
if (!upstream.body) {
|
|
10210
|
-
activeRequests.delete(frame.id);
|
|
10211
|
-
ws.send(JSON.stringify({
|
|
10212
|
-
type: "data",
|
|
10213
|
-
id: frame.id,
|
|
10214
|
-
final: true,
|
|
10215
|
-
timestamp: Date.now()
|
|
10216
|
-
}));
|
|
10217
|
-
return;
|
|
10218
|
-
}
|
|
10219
|
-
const reader = upstream.body.getReader();
|
|
10296
|
+
pending.bodyClosed = true;
|
|
10297
|
+
if (pending.bodyController) {
|
|
10220
10298
|
try {
|
|
10221
|
-
|
|
10222
|
-
|
|
10223
|
-
if (done)
|
|
10224
|
-
break;
|
|
10225
|
-
if (!value)
|
|
10226
|
-
continue;
|
|
10227
|
-
ws.send(JSON.stringify({
|
|
10228
|
-
type: "data",
|
|
10229
|
-
id: frame.id,
|
|
10230
|
-
data: bytesToBase64(value),
|
|
10231
|
-
final: false,
|
|
10232
|
-
timestamp: Date.now()
|
|
10233
|
-
}));
|
|
10234
|
-
}
|
|
10235
|
-
} finally {
|
|
10236
|
-
reader.releaseLock();
|
|
10237
|
-
}
|
|
10238
|
-
activeRequests.delete(frame.id);
|
|
10239
|
-
ws.send(JSON.stringify({
|
|
10240
|
-
type: "data",
|
|
10241
|
-
id: frame.id,
|
|
10242
|
-
final: true,
|
|
10243
|
-
timestamp: Date.now()
|
|
10244
|
-
}));
|
|
10245
|
-
} catch (error) {
|
|
10246
|
-
activeRequests.delete(frame.id);
|
|
10247
|
-
pendingRequestBodies.delete(frame.id);
|
|
10248
|
-
if (error instanceof Error && error.name === "AbortError") {
|
|
10249
|
-
return;
|
|
10250
|
-
}
|
|
10251
|
-
ws.send(JSON.stringify({
|
|
10252
|
-
type: "response",
|
|
10253
|
-
id: frame.id,
|
|
10254
|
-
statusCode: 502,
|
|
10255
|
-
headers: { "content-type": "application/json" },
|
|
10256
|
-
timestamp: Date.now()
|
|
10257
|
-
}));
|
|
10258
|
-
ws.send(JSON.stringify({
|
|
10259
|
-
type: "data",
|
|
10260
|
-
id: frame.id,
|
|
10261
|
-
data: bytesToBase64(new TextEncoder().encode(JSON.stringify({ error: "upstream_error" }))),
|
|
10262
|
-
final: true,
|
|
10263
|
-
timestamp: Date.now()
|
|
10264
|
-
}));
|
|
10299
|
+
pending.bodyController.close();
|
|
10300
|
+
} catch {}
|
|
10265
10301
|
}
|
|
10302
|
+
pendingRequests.delete(frame.id);
|
|
10266
10303
|
}
|
|
10267
10304
|
});
|
|
10268
10305
|
ws.addEventListener("close", () => {
|
|
@@ -10282,8 +10319,7 @@ Disconnecting...`);
|
|
|
10282
10319
|
controller.abort();
|
|
10283
10320
|
}
|
|
10284
10321
|
activeRequests.clear();
|
|
10285
|
-
|
|
10286
|
-
pendingRequestMeta.clear();
|
|
10322
|
+
pendingRequests.clear();
|
|
10287
10323
|
try {
|
|
10288
10324
|
ws.close();
|
|
10289
10325
|
} catch {}
|