@evandu/super-pi 0.1.51 → 0.1.53

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.
@@ -8,8 +8,8 @@
8
8
  <link rel="alternate icon" href="/favicon.ico" />
9
9
  <link rel="apple-touch-icon" href="/favicon.svg" />
10
10
  <title>Super Pi</title>
11
- <script type="module" crossorigin src="/assets/index-Bx1HHVVh.js"></script>
12
- <link rel="stylesheet" crossorigin href="/assets/index-DJD8mXiK.css">
11
+ <script type="module" crossorigin src="/assets/index-QrAie6Ph.js"></script>
12
+ <link rel="stylesheet" crossorigin href="/assets/index-C93dgl8m.css">
13
13
  </head>
14
14
  <body>
15
15
  <div id="root"></div>
@@ -1,3 +1,4 @@
1
+ import { spawn } from "node:child_process";
1
2
  /**
2
3
  * Routes client commands to appropriate application services and converts results or errors.
3
4
  */
@@ -232,6 +233,24 @@ export class CommandHandler {
232
233
  await this.catalogService.rescan();
233
234
  return;
234
235
  }
236
+ if (command.type === "super_pi.start") {
237
+ const port = Number(process.env.SUPER_PI_PORT ?? 3080);
238
+ const url = `http://127.0.0.1:${port}`;
239
+ const platform = process.platform;
240
+ if (platform === "darwin")
241
+ spawn("open", [url], { detached: true, stdio: "ignore" }).unref();
242
+ else if (platform === "win32")
243
+ spawn("cmd.exe", ["/c", "start", "", url], { detached: true, stdio: "ignore" }).unref();
244
+ else
245
+ spawn("xdg-open", [url], { detached: true, stdio: "ignore" }).unref();
246
+ return;
247
+ }
248
+ if (command.type === "super_pi.update") {
249
+ spawn("pi", ["update", "@evandu/super-pi"], { stdio: "inherit", shell: true }).on("error", () => {
250
+ console.error("Super Pi: `pi update @evandu/super-pi` failed — is the `pi` command in your PATH?");
251
+ });
252
+ return;
253
+ }
235
254
  throw new Error(`未知的命令类型:${JSON.stringify(command.type ?? null)}`);
236
255
  }
237
256
  }
@@ -1234,14 +1234,15 @@ export class PiRpcRuntime {
1234
1234
  catch (error) {
1235
1235
  if (child.exitCode === null && child.pid !== undefined)
1236
1236
  await killTree(child.pid);
1237
- await new Promise((resolve) => { child.once("exit", resolve); setTimeout(resolve, 5000); });
1237
+ // taskkill has already terminated the process tree; do not add a five-second UI stall waiting for
1238
+ // Node's exit event bookkeeping on Windows.
1238
1239
  throw error instanceof Error ? error : new Error(`无法向 Pi 询问会话文件:${String(error)}`);
1239
1240
  }
1240
1241
  // The lookup Pi is holding open is finished; it is killed BEFORE the file is touched, for the same
1241
1242
  // reason `answer()` kills before returning: a process still tearing down can still be appending.
1242
1243
  if (child.exitCode === null && child.pid !== undefined)
1243
1244
  await killTree(child.pid);
1244
- await new Promise((resolve) => { child.once("exit", resolve); setTimeout(resolve, 5000); });
1245
+ // The process tree is dead after killTree; copying can proceed without waiting for a delayed exit event.
1245
1246
  if (!sessionFile)
1246
1247
  throw new Error("Pi 没有报告这个会话的记录文件,已放弃,没有改动任何文件。");
1247
1248
  const exists = await stat(sessionFile).catch(() => undefined);
@@ -1325,12 +1326,12 @@ export class PiRpcRuntime {
1325
1326
  catch (error) {
1326
1327
  if (child.exitCode === null && child.pid !== undefined)
1327
1328
  await killTree(child.pid);
1328
- await new Promise((resolve) => { child.once("exit", resolve); setTimeout(resolve, 5000); });
1329
+ // killTree waits for taskkill; waiting again for Node's exit event can miss the event and add 5s.
1329
1330
  throw error instanceof Error ? error : new Error(`无法向 Pi 询问会话文件:${String(error)}`);
1330
1331
  }
1331
1332
  if (child.exitCode === null && child.pid !== undefined)
1332
1333
  await killTree(child.pid);
1333
- await new Promise((resolve) => { child.once("exit", resolve); setTimeout(resolve, 5000); });
1334
+ // killTree waits for taskkill; do not wait for a possibly already-delivered exit event.
1334
1335
  if (!sessionFile)
1335
1336
  throw new Error("Pi 没有报告这个会话的记录文件,已放弃,没有复制任何文件。");
1336
1337
  const exists = await stat(sessionFile).catch(() => undefined);
@@ -1008,6 +1008,14 @@ export type ClientCommandBody =
1008
1008
  dirs: string[];
1009
1009
  } | {
1010
1010
  type: "agents.rescan";
1011
+ }
1012
+ /** Opens the browser at the Super Pi web UI, starting the server if it is not running. */
1013
+ | {
1014
+ type: "super_pi.start";
1015
+ }
1016
+ /** Runs `pi self-update` to update Super Pi. */
1017
+ | {
1018
+ type: "super_pi.update";
1011
1019
  } | ({
1012
1020
  type: "extension.ui.answer";
1013
1021
  conversationId: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@evandu/super-pi",
3
- "version": "0.1.51",
3
+ "version": "0.1.53",
4
4
  "description": "Web control plane and companion for Pi",
5
5
  "license": "MIT",
6
6
  "type": "module",