@evandu/super-pi 0.1.66 → 0.1.68

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-11WhrIBA.js"></script>
12
- <link rel="stylesheet" crossorigin href="/assets/index-D0NWc2Zw.css">
11
+ <script type="module" crossorigin src="/assets/index-CMOs6pUT.js"></script>
12
+ <link rel="stylesheet" crossorigin href="/assets/index-DKLKopji.css">
13
13
  </head>
14
14
  <body>
15
15
  <div id="root"></div>
@@ -15,6 +15,8 @@ export declare class CommandHandler {
15
15
  private readonly runService;
16
16
  private readonly extensionUiService;
17
17
  private readonly catalogService;
18
+ /** Path to the Super Pi repository root, used to spawn the restart script. */
19
+ private readonly rootDir?;
18
20
  /**
19
21
  * The terminal, or undefined when `SUPER_PI_TERMINAL` is off.
20
22
  *
@@ -23,7 +25,9 @@ export declare class CommandHandler {
23
25
  * is undefined, which is a refusal that names the command rather than one that pretends it exists.
24
26
  */
25
27
  private readonly terminalService?;
26
- constructor(workspaceService: WorkspaceService, conversationService: ConversationService, runService: RunService, extensionUiService: ExtensionUiService, catalogService: CatalogService, terminalService?: TerminalService);
28
+ constructor(workspaceService: WorkspaceService, conversationService: ConversationService, runService: RunService, extensionUiService: ExtensionUiService, catalogService: CatalogService, terminalService?: TerminalService,
29
+ /** Path to the Super Pi repository root, used to spawn the restart script. */
30
+ rootDir?: string | undefined);
27
31
  /**
28
32
  * Processes a client command.
29
33
  *
@@ -1,4 +1,5 @@
1
1
  import { spawn } from "node:child_process";
2
+ import { join } from "node:path";
2
3
  /**
3
4
  * Routes client commands to appropriate application services and converts results or errors.
4
5
  */
@@ -8,6 +9,7 @@ export class CommandHandler {
8
9
  runService;
9
10
  extensionUiService;
10
11
  catalogService;
12
+ rootDir;
11
13
  /**
12
14
  * The terminal, or undefined when `SUPER_PI_TERMINAL` is off.
13
15
  *
@@ -16,12 +18,15 @@ export class CommandHandler {
16
18
  * is undefined, which is a refusal that names the command rather than one that pretends it exists.
17
19
  */
18
20
  terminalService;
19
- constructor(workspaceService, conversationService, runService, extensionUiService, catalogService, terminalService) {
21
+ constructor(workspaceService, conversationService, runService, extensionUiService, catalogService, terminalService,
22
+ /** Path to the Super Pi repository root, used to spawn the restart script. */
23
+ rootDir) {
20
24
  this.workspaceService = workspaceService;
21
25
  this.conversationService = conversationService;
22
26
  this.runService = runService;
23
27
  this.extensionUiService = extensionUiService;
24
28
  this.catalogService = catalogService;
29
+ this.rootDir = rootDir;
25
30
  this.terminalService = terminalService;
26
31
  }
27
32
  /**
@@ -250,11 +255,32 @@ export class CommandHandler {
250
255
  return;
251
256
  }
252
257
  if (command.type === "super_pi.update") {
253
- spawn("pi", ["update", "@evandu/super-pi"], { stdio: "inherit", shell: true }).on("error", () => {
254
- console.error("Super Pi: `pi update @evandu/super-pi` failed — is the `pi` command in your PATH?");
258
+ // npm install -g picks up the latest published version, then the same restart script the
259
+ // /api/update endpoint uses runs detached. The user sees npm's output stream in their
260
+ // terminal because stdio: inherit is what makes a CLI feel like a CLI.
261
+ const npmCmd = process.platform === "win32" ? "npm.cmd" : "npm";
262
+ const updater = spawn(npmCmd, ["install", "-g", "@evandu/super-pi"], { stdio: "inherit", shell: process.platform === "win32", env: process.env });
263
+ updater.on("error", (error) => { console.error(`Super Pi: npm install failed: ${error instanceof Error ? error.message : "unknown error"}`); });
264
+ updater.on("close", (code) => {
265
+ if (code !== 0) {
266
+ console.error(`Super Pi: npm install exited with code ${code}`);
267
+ return;
268
+ }
269
+ const cwd = this.rootDir ?? import.meta.dirname;
270
+ const restart = spawn(process.execPath, [join(cwd, "scripts", "restart-server.mjs")], { cwd, detached: true, stdio: "ignore", env: process.env });
271
+ restart.unref();
255
272
  });
256
273
  return;
257
274
  }
275
+ if (command.type === "super_pi.restart") {
276
+ // Reuse the same restart script the in-app button and the terminal command use, so the
277
+ // three paths to 「重新加载磁盘上的新代码」 agree on how.
278
+ const cwd = this.rootDir ?? import.meta.dirname;
279
+ const restart = spawn(process.execPath, [join(cwd, "scripts", "restart-server.mjs")], { cwd, detached: true, stdio: "ignore", env: process.env });
280
+ restart.on("error", (error) => { console.warn(`Super Pi: restart spawn failed: ${error instanceof Error ? error.message : "unknown error"}`); });
281
+ restart.unref();
282
+ return;
283
+ }
258
284
  throw new Error(`未知的命令类型:${JSON.stringify(command.type ?? null)}`);
259
285
  }
260
286
  }
@@ -158,7 +158,7 @@ const serverContext = {
158
158
  terminalEnabled: () => terminalService.enabled,
159
159
  terminalDisabledReason: () => terminalDisabledReason(),
160
160
  };
161
- const commandHandler = new CommandHandler(workspaceService, conversationService, runService, extensionUiService, catalogService, terminalService);
161
+ const commandHandler = new CommandHandler(workspaceService, conversationService, runService, extensionUiService, catalogService, terminalService, rootDir);
162
162
  // ------------------------------------------------------------- Lifecycle & shutdown
163
163
  let shutdownPromise;
164
164
  async function closeHttpServer() {
@@ -1041,6 +1041,10 @@ export type ClientCommandBody =
1041
1041
  /** Runs `pi self-update` to update Super Pi. */
1042
1042
  | {
1043
1043
  type: "super_pi.update";
1044
+ }
1045
+ /** Restarts the Super Pi server by spawning the same restart script used by the auto-updater. */
1046
+ | {
1047
+ type: "super_pi.restart";
1044
1048
  } | ({
1045
1049
  type: "extension.ui.answer";
1046
1050
  conversationId: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@evandu/super-pi",
3
- "version": "0.1.66",
3
+ "version": "0.1.68",
4
4
  "description": "Web control plane and companion for Pi",
5
5
  "license": "MIT",
6
6
  "type": "module",