-
Notifications
You must be signed in to change notification settings - Fork 8
Expand file tree
/
Copy pathserver.ts
More file actions
70 lines (63 loc) · 2.84 KB
/
Copy pathserver.ts
File metadata and controls
70 lines (63 loc) · 2.84 KB
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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
// sideshow-term server. It reuses sideshow's runtime-agnostic core
// (createApp + JsonFileStore) from the sideshow package — snippets are opaque
// strings to the store, so the same REST API, SSE feed and long-poll serve STML
// just as well as HTML.
// What differs is the agent-facing contract: /guide and /setup teach the
// opentui markup, not browser HTML, and the viewer is the TUI (`watch`), not
// a browser, so we hand createApp a placeholder landing page.
//
// Runs on Node (hono). The opentui pieces run on Bun; the two never share a
// process.
import { serve } from "@hono/node-server";
import { readFile } from "node:fs/promises";
import { homedir } from "node:os";
import { basename, dirname, join } from "node:path";
import { fileURLToPath } from "node:url";
const { createApp, JsonFileStore } = await loadSideshowServerCore();
async function loadSideshowServerCore() {
try {
return await import("sideshow/server");
} catch {
// Compatibility for sideshow 0.4.0, which did not expose the stable
// `sideshow/server` entrypoint yet. New installs should resolve above.
const [{ createApp }, { JsonFileStore }] = await Promise.all([
import("sideshow/dist/server/app.js"),
import("sideshow/dist/server/storage.js"),
]);
return { createApp, JsonFileStore };
}
}
const here = dirname(fileURLToPath(import.meta.url));
const root = basename(here) === "dist" ? dirname(here) : here;
const [guideMarkdown, setupText, pkgJson] = await Promise.all([
readFile(join(root, "guide", "DESIGN_GUIDE.md"), "utf8"),
readFile(join(root, "guide", "AGENT_SETUP.md"), "utf8"),
readFile(join(root, "package.json"), "utf8"),
]);
const landing = `<!doctype html><meta charset="utf-8"><title>sideshow-term</title>
<body style="font:16px/1.6 system-ui;max-width:40rem;margin:4rem auto;padding:0 1rem">
<h1>sideshow-term</h1>
<p>This is a terminal visual surface. There is no browser viewer — open the
live viewer in a terminal:</p>
<pre style="background:#f4f4f5;padding:1rem;border-radius:8px">sideshow-term watch</pre>
<p>Agents publish opentui markup; see <a href="/guide">/guide</a> and
<a href="/setup">/setup</a>.</p>
</body>`;
const app = createApp({
store: new JsonFileStore(
process.env.SIDESHOW_DATA ?? join(homedir(), ".sideshow-term", "sideshow-term.json"),
),
viewerHtml: landing,
guideMarkdown,
setupText,
authToken: process.env.SIDESHOW_TOKEN,
version: (JSON.parse(pkgJson) as { version: string }).version,
upgradeCommand: "npm install -g sideshow-term",
// sideshow-term isn't on npm under sideshow's name; skip the update probe.
fetchLatestRelease: async () => null,
});
const port = Number(process.env.PORT ?? 4243);
serve({ fetch: app.fetch, port }, (info) => {
console.log(`sideshow-term listening on http://localhost:${info.port}`);
console.log(`open the live viewer in a terminal: sideshow-term watch`);
});