Add per-task terminals over WebSocket with an xterm.js Terminal tab

This commit is contained in:
Ian Gulliver
2026-10-15 12:06:50 -07:00
parent 37bf1b60a7
commit ff22f33025
33 changed files with 1600 additions and 167 deletions
+10 -1
View File
@@ -5,7 +5,7 @@ export class ApiError extends Error {
this.status = status;
}
}
export async function request(method, path, opts = {}) {
function target(path, opts) {
const pathParams = (opts.path ?? {});
let url = path.replace(/\{(\w+)\}/g, (_, key) => {
const value = pathParams[key];
@@ -23,6 +23,10 @@ export async function request(method, path, opts = {}) {
if (query.size > 0) {
url += `?${query}`;
}
return url;
}
export async function request(method, path, opts = {}) {
const url = target(path, opts);
const init = { method: method.toUpperCase(), keepalive: opts.keepalive ?? false };
if (opts.body instanceof Blob) {
init.headers = { "Content-Type": opts.body.type || "application/octet-stream" };
@@ -50,6 +54,11 @@ export const get = (path, opts) => request("get", path, opts);
export const post = (path, opts) => request("post", path, opts);
export const put = (path, opts) => request("put", path, opts);
export const del = (path, opts) => request("delete", path, opts);
export function socket(path, opts) {
const ws = new WebSocket(`${location.protocol === "https:" ? "wss:" : "ws:"}//${location.host}${target(path, opts)}`);
ws.binaryType = "arraybuffer";
return ws;
}
const staleAfterMs = 40_000;
const retryAfterMs = 2_000;
export function subscribe(after, filter, onEvent, onState) {