pi-webapp 0.1.19 → 0.1.21

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.
package/README.md CHANGED
@@ -2,6 +2,16 @@
2
2
 
3
3
  [简体中文](README.zh-CN.md)
4
4
 
5
+ ## Download pi desktop
6
+
7
+ ### [⬇ Download for macOS Apple Silicon (.dmg)](https://github.com/chengzhiyi/pi-webapp/releases/download/desktop-v0.1.20-b5/pi-0.1.20-desktop.5-mac-arm64.dmg)
8
+
9
+ **Test release · v0.1.20 / desktop build 5 · Apple M-series only**
10
+
11
+ [Release notes and SHA-256 checksums](https://github.com/chengzhiyi/pi-webapp/releases/tag/desktop-v0.1.20-b5) · [All desktop releases](https://github.com/chengzhiyi/pi-webapp/releases) · [Use the Web/npm version instead](#install-and-open)
12
+
13
+ > Open the DMG and drag **pi.app** into Applications. This test build is unsigned/unnotarized; do not globally disable macOS security. Windows/Linux/Intel Mac installers are not yet validated. Node and a tested, pinned Pi runtime are bundled; you do not need to install them separately.
14
+
5
15
  ![pi-webapp cover](assets/cover-webapp.png)
6
16
 
7
17
  **pi-webapp** opens the active Pi coding agent session in a local browser. Pi continues to run the agent, tools, and session storage; the browser provides a live interface for conversation and control.
@@ -55,6 +65,16 @@ Chats run independently: switching workspaces or chats, or creating a new chat,
55
65
 
56
66
  On startup, the app discovers workspaces from Pi's saved sessions, so conversations from other directories appear in the sidebar. Workspace records and attachments stay under Pi's existing `pi-web/` data directory. Removing a workspace from the sidebar does not delete its files or sessions; you can add it again manually.
57
67
 
68
+ ## Optional desktop application
69
+
70
+ **[Download pi desktop test releases](https://github.com/chengzhiyi/pi-webapp/releases)** — macOS Apple Silicon (arm64) only for now. Download the DMG from a `desktop-v...` prerelease; compare `SHA256SUMS`, install **pi.app**, and check the build in **pi → 关于 pi**. These builds are unsigned/unnotarized; do not globally disable macOS security. Windows/Linux are not yet validated release downloads.
71
+
72
+ The same UI can run in the **pi** Electron desktop application while the browser and `/web` entry points remain available. Desktop packages include Node/Pi, reuse compatible running services, and let you open the same service in a browser or choose whether to keep background tasks running on exit.
73
+
74
+ From source: `npm ci` → `npm run desktop:prepare` → `npm run desktop:start`. Run `npm run desktop:package` to create a host-native installer under `desktop-release/`. Local QA targets macOS arm64; Windows/Linux configurations need verification on their respective systems. Initial packages are unsigned and do not auto-update. Installers include a desktop build number; check **pi → 关于 pi** for the running build and executable location. Quit the old desktop before replacing it; an external compatible Web backend need not be stopped. Finish tasks and stop an owned runtime before replacing that runtime.
75
+
76
+ See [desktop build, testing and release boundaries](docs/desktop.md).
77
+
58
78
  ## Develop locally
59
79
 
60
80
  ```bash
package/README.zh-CN.md CHANGED
@@ -2,6 +2,16 @@
2
2
 
3
3
  [English](README.md)
4
4
 
5
+ ## 下载 pi 桌面版
6
+
7
+ ### [⬇ 下载 macOS Apple 芯片版(DMG)](https://github.com/chengzhiyi/pi-webapp/releases/download/desktop-v0.1.20-b5/pi-0.1.20-desktop.5-mac-arm64.dmg)
8
+
9
+ **测试版 · v0.1.20 / 桌面构建 5 · 仅支持 Apple M 系列芯片**
10
+
11
+ [版本说明与 SHA-256 校验和](https://github.com/chengzhiyi/pi-webapp/releases/tag/desktop-v0.1.20-b5) · [所有桌面版本](https://github.com/chengzhiyi/pi-webapp/releases) · [改用 Web/npm 方式](#安装与打开)
12
+
13
+ > 打开 DMG,将 **pi.app** 拖入“应用程序”即可。此测试版未签名、未公证,请勿全局关闭 macOS 安全保护。Windows/Linux/Intel Mac 安装包尚未验收。安装包已内置 Node 与经过验证、锁定版本的 Pi,无需另行安装。
14
+
5
15
  ![pi-webapp 封面](assets/cover-webapp.png)
6
16
 
7
17
  **pi-webapp** 可以在本地浏览器中打开当前活跃的 Pi 编程 Agent 会话。Agent、工具和会话存储仍由 Pi 运行和管理;浏览器提供实时的对话与控制界面。
@@ -55,6 +65,16 @@ pi
55
65
 
56
66
  启动时会从 Pi 已保存的会话中发现工作区,因此先前在其他目录使用 Pi 的会话也会出现在侧边栏。工作区记录和附件继续存放在 Pi 现有的 `pi-web/` 数据目录下。从侧边栏移除工作区不会删除其文件或会话;移除后如需再次显示,可以手动添加。
57
67
 
68
+ ## 桌面端(可选)
69
+
70
+ **[下载 pi 桌面测试版](https://github.com/chengzhiyi/pi-webapp/releases)** — 目前仅发布已验收的 macOS Apple 芯片(arm64)版本。在 `desktop-v...` 预发布版本中下载 DMG,核对 `SHA256SUMS` 后安装 **pi.app**,在“pi → 关于 pi”查看构建号。测试版未签名、未公证,请勿全局关闭系统安全保护;Windows/Linux 暂不提供已验收的发行包。
71
+
72
+ 同一套界面也可在名为 **pi** 的 Electron 桌面程序中使用,现有浏览器与 `/web` 方式保持不变。桌面包自带 Node/Pi,支持独立窗口、已有服务复用、在浏览器打开同一服务,以及退出时选择保留或停止后台任务。
73
+
74
+ 源码构建:`npm ci` → `npm run desktop:prepare` → `npm run desktop:start`。运行 `npm run desktop:package` 生成当前系统/架构的安装包,输出到 `desktop-release/`。当前本地验证目标为 macOS arm64;Windows/Linux 打包配置需在对应系统验证。首版安装包未签名,尚无桌面自动更新。安装包文件名包含桌面构建号;“pi → 关于 pi”显示实际运行的构建号和应用位置。替换前先退出旧桌面,外部兼容 Web 后台无需停止;若替换桌面自有运行时,请先结束任务并停止该自有后台。
75
+
76
+ 详细说明见 [桌面端构建、测试与发布边界](docs/desktop.md)。
77
+
58
78
  ## 本地开发
59
79
 
60
80
  ```bash
package/bin/pi-webapp.mjs CHANGED
@@ -11,6 +11,9 @@ import { openWebPage } from "./open-web-page.mjs";
11
11
  import { npmCommand } from "./npm-command.mjs";
12
12
 
13
13
  const minimum = [0, 87, 1];
14
+ const packageVersion = JSON.parse(await readFile(new URL("../package.json", import.meta.url), "utf8")).version;
15
+ const runtimeKind = process.env.PI_WEBAPP_RUNTIME === "desktop" ? "desktop" : "npm";
16
+ const runtimeInfo = { version: packageVersion, bridgeVersion: 1, runtimeKind };
14
17
  const launcher = fileURLToPath(import.meta.url);
15
18
  const extension = fileURLToPath(new URL("../dist/extension.js", import.meta.url));
16
19
  const agentDir = resolve((process.env.PI_CODING_AGENT_DIR ?? join(homedir(), ".pi", "agent")).replace(/^~(?=$|[\\/])/, homedir()));
@@ -109,7 +112,7 @@ async function serve(pi, args) {
109
112
  try {
110
113
  lock = await open(statePath, "wx", 0o600);
111
114
  claimed = true;
112
- await lock.writeFile(JSON.stringify({ pid: process.pid, nonce, cwd: process.cwd(), starting: true }));
115
+ await lock.writeFile(JSON.stringify({ pid: process.pid, nonce, cwd: process.cwd(), starting: true, ...runtimeInfo }));
113
116
  } catch (error) {
114
117
  if (claimed) await unlink(statePath).catch(() => {});
115
118
  notifyParent({ type: "error", message: error?.code === "EEXIST" ? "pi-webapp 已在启动或运行" : String(error) });
@@ -117,7 +120,8 @@ async function serve(pi, args) {
117
120
  } finally { await lock?.close().catch(() => {}); }
118
121
 
119
122
  const pluginRoots = (process.env.PI_WEBAPP_PLUGIN_DEV_ROOTS ?? "").split(delimiter).filter(Boolean).map((root) => resolve(root));
120
- const child = spawn(pi, ["--mode", "rpc", "-e", extension, ...pluginRoots.flatMap((root) => ["-e", root]), ...args], {
123
+ const piPrefix = process.env.PI_WEBAPP_PI_CLI ? [resolve(process.env.PI_WEBAPP_PI_CLI)] : [];
124
+ const child = spawn(pi, [...piPrefix, "--mode", "rpc", "-e", extension, ...pluginRoots.flatMap((root) => ["-e", root]), ...args], {
121
125
  cwd: process.cwd(), env: { ...process.env, PI_WEBAPP_AUTO_OPEN: "0", PI_WEBAPP_LAUNCHER_NONCE: nonce }, stdio: ["pipe", "pipe", "pipe"],
122
126
  });
123
127
  child.stderr?.pipe(process.stderr, { end: false });
@@ -173,7 +177,7 @@ async function serve(pi, args) {
173
177
  try {
174
178
  const request = JSON.parse(await readFile(restartPath, "utf8"));
175
179
  const prepared = JSON.parse(await readFile(updatePath, "utf8"));
176
- if (request.nonce === nonce && request.launcher === prepared.launcher && existsSync(request.launcher)) {
180
+ if (runtimeKind !== "desktop" && request.nonce === nonce && request.launcher === prepared.launcher && existsSync(request.launcher)) {
177
181
  restartRequest = request;
178
182
  shutdown("restart_request");
179
183
  }
@@ -222,7 +226,7 @@ async function serve(pi, args) {
222
226
  if (url.hostname !== "127.0.0.1" || !url.hash) continue;
223
227
  runningUrl = url.href;
224
228
  opening = true;
225
- stateWrite = saveState({ pid: process.pid, piPid: child.pid, nonce, cwd: process.cwd(), url: url.href })
229
+ stateWrite = saveState({ pid: process.pid, piPid: child.pid, nonce, cwd: process.cwd(), url: url.href, ...runtimeInfo })
226
230
  .then(() => {
227
231
  if (closed || failed) return;
228
232
  ready = true;
@@ -331,7 +335,7 @@ async function start(args) {
331
335
  if (!nodeVersion || !compatible(nodeVersion, [22, 19, 0])) throw new Error("需要 Node.js 22.19 或更新版本。");
332
336
  if (!existsSync(extension)) throw new Error("找不到构建后的扩展。请先运行 npm run build。");
333
337
  if (args.some((arg) => ["--mode", "--print", "-p"].includes(arg))) throw new Error("后台启动不支持覆盖 Pi 的运行模式");
334
- const pi = probe("pi") ?? installPi();
338
+ const pi = process.env.PI_WEBAPP_PI_CLI ? process.execPath : probe("pi") ?? installPi();
335
339
  await mkdir(dirname(statePath), { recursive: true });
336
340
  const logFd = openSync(logPath, "a", 0o600);
337
341
  let worker;