File size: 2,517 Bytes
c59a319
739d016
 
 
 
ea0bac9
739d016
 
 
 
 
 
 
 
ea0bac9
739d016
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
<!doctype html>
<html><head><meta charset="utf-8"><title>opencode web</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@xterm/xterm@5.5.0/css/xterm.css">
<style>html,body{margin:0;height:100%;background:#000}#console{height:100%}</style>
</head><body><div id="console"></div>
<script>
// Cross-origin isolation (needed by CheerpX) via service worker, since static hosting cannot set headers.
if ("serviceWorker" in navigator && !crossOriginIsolated) {
  navigator.serviceWorker.register("sw.js").then(reg => {
    if (reg.active && navigator.serviceWorker.controller) return;
    navigator.serviceWorker.addEventListener("controllerchange", () => location.reload());
    if (reg.active) location.reload();
  });
}
</script>
<script src="https://cdn.jsdelivr.net/npm/@xterm/xterm@5.5.0/lib/xterm.js"></script>
<script type="module">
const CX_URL = "https://cxrtnc.leaningtech.com/1.4.0/cx.esm.js";
const term = new Terminal({ cursorBlink: true, convertEol: true, fontFamily: "monospace" });
term.open(document.getElementById("console"));
term.focus();
term.write("opencode web: loading CheerpX + Alpine...\r\n");
try {
  if (!crossOriginIsolated) throw new Error("page is not cross-origin isolated yet (service worker reload pending)");
  const CheerpX = await import(CX_URL);
  const blockDevice = await CheerpX.HttpBytesDevice.create("rootfs.ext2");
  const cache = await CheerpX.IDBDevice.create("opencode-web-v1");
  const overlay = await CheerpX.OverlayDevice.create(blockDevice, cache);
  const webDevice = await CheerpX.WebDevice.create("");
  const dataDevice = await CheerpX.DataDevice.create();
  const cx = await CheerpX.Linux.create({ mounts: [
    { type: "ext2", dev: overlay, path: "/" },
    { type: "dir", dev: webDevice, path: "/web" },
    { type: "dir", dev: dataDevice, path: "/data" },
    { type: "devs", path: "/dev" },
    { type: "devpts", path: "/dev/pts" },
    { type: "proc", path: "/proc" },
    { type: "sys", path: "/sys" },
  ] });
  const readFn = cx.setCustomConsole((buf, vt) => { if (vt === 1) term.write(new Uint8Array(buf)); }, term.cols, term.rows);
  term.onData(s => { for (let i = 0; i < s.length; i++) readFn(s.charCodeAt(i)); });
  await cx.run("/bin/sh", ["-c", "opencode; exec /bin/sh -l"], {
    env: ["HOME=/root", "TERM=xterm-256color", "PATH=/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin", "LANG=C.UTF-8"],
    cwd: "/root", uid: 0, gid: 0,
  });
} catch (e) {
  term.write("\r\nERROR: " + e + "\r\n");
  console.error(e);
}
</script>
</body></html>