@rotriz/pi-web-ui 1.0.0 → 1.0.2

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.
Files changed (2) hide show
  1. package/extension.mjs +29 -9
  2. package/package.json +2 -2
package/extension.mjs CHANGED
@@ -10,9 +10,24 @@ import { dirname, join } from "node:path";
10
10
  import { exec, execFile } from "node:child_process";
11
11
  import { fileURLToPath } from "node:url";
12
12
  import { existsSync } from "node:fs";
13
+ import { request } from "node:http";
13
14
 
14
15
  const PORT = Number(process.env.PI_WEB_PORT || process.env.PORT || 3123);
15
16
 
17
+ // HTTP GET helper — works on Node 14+ without global fetch
18
+ function httpGet(url) {
19
+ return new Promise((resolve) => {
20
+ const req = request(url, (res) => {
21
+ let data = "";
22
+ res.on("data", (chunk) => (data += chunk));
23
+ res.on("end", () => resolve({ ok: res.statusCode >= 200 && res.statusCode < 300, status: res.statusCode, data }));
24
+ });
25
+ req.on("error", () => resolve({ ok: false, status: 0, data: "" }));
26
+ req.setTimeout(3000, () => { req.destroy(); resolve({ ok: false, status: 0, data: "" }); });
27
+ req.end();
28
+ });
29
+ }
30
+
16
31
  function openBrowser(url) {
17
32
  const cmd = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
18
33
  exec(`${cmd} ${JSON.stringify(url)}`, () => {});
@@ -36,6 +51,12 @@ export default function (pi) {
36
51
  }
37
52
 
38
53
  async function ensureServer() {
54
+ // Check if server is already running (from a previous session or manual start)
55
+ try {
56
+ const res = await httpGet(`${origin}/api/tabs`);
57
+ if (res.ok) return; // Already running, reuse it
58
+ } catch {}
59
+
39
60
  if (serverProcess && !serverProcess.killed) return;
40
61
  const serverPath = join(extDir, "server.mjs");
41
62
  if (!existsSync(serverPath)) {
@@ -48,11 +69,11 @@ export default function (pi) {
48
69
  });
49
70
  serverProcess.unref();
50
71
  serverProcess.on("exit", () => { serverProcess = null; });
51
- // Wait for the server to be ready
52
- for (let i = 0; i < 30; i++) {
53
- await new Promise((r) => setTimeout(r, 200));
72
+ // Wait for the server to be ready (up to 30 seconds for slow machines)
73
+ for (let i = 0; i < 60; i++) {
74
+ await new Promise((r) => setTimeout(r, 500));
54
75
  try {
55
- const res = await fetch(`${origin}/api/tabs`);
76
+ const res = await httpGet(`${origin}/api/tabs`);
56
77
  if (res.ok) return;
57
78
  } catch {}
58
79
  }
@@ -68,11 +89,10 @@ export default function (pi) {
68
89
 
69
90
  // ── Lifecycle ────────────────────────────────────────────────────────
70
91
  pi.on("session_start", async (_event, ctx) => {
71
- try {
72
- await ensureServer();
73
- } catch (err) {
74
- ctx.ui?.notify?.(`pi-web-ui could not start: ${err?.message ?? err}`, "error");
75
- }
92
+ // Start server in background — don't block Pi's session startup
93
+ ensureServer().catch((err) => {
94
+ ctx.ui?.notify?.(`pi-web-ui: ${err?.message ?? err}`, "warning");
95
+ });
76
96
  });
77
97
 
78
98
  pi.on("session_shutdown", async (event) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rotriz/pi-web-ui",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "Web UI extension for the Pi coding agent — browser-based session management, git integration, and task tracking",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -30,6 +30,6 @@
30
30
  "@earendil-works/pi-coding-agent": "*"
31
31
  },
32
32
  "engines": {
33
- "node": ">=20"
33
+ "node": ">=16"
34
34
  }
35
35
  }