pi-webapp 0.1.20 → 0.1.22

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 (28) hide show
  1. package/README.md +14 -1
  2. package/README.zh-CN.md +14 -1
  3. package/bin/open-web-page.mjs +3 -0
  4. package/bin/pi-webapp.mjs +8 -0
  5. package/dist/extension.js +31 -28
  6. package/docs/desktop.md +124 -10
  7. package/docs/sentry.md +1 -1
  8. package/package.json +5 -5
  9. package/web/dist/.vite/manifest.json +63 -41
  10. package/web/dist/assets/app-D54rSb9U.js +542 -0
  11. package/web/dist/assets/app.js +2 -2
  12. package/web/dist/assets/{elixir-DI-tUE_U.js → elixir-R3IvWmT5.js} +1 -1
  13. package/web/dist/assets/{graphql-Bz9lYT3E.js → graphql-DSgZM88T.js} +1 -1
  14. package/web/dist/assets/{html-DfmEJESS.js → html-COcRjUs1.js} +1 -1
  15. package/web/dist/assets/{html-derivative-BaRuZAr6.js → html-derivative-C2Epw9Yg.js} +1 -1
  16. package/web/dist/assets/{http-oJQxPuUz.js → http-BnatDCTa.js} +1 -1
  17. package/web/dist/assets/{julia-VEDmabGN.js → julia-yApUWuwQ.js} +1 -1
  18. package/web/dist/assets/{perl-g_tPwekP.js → perl-CpGQZpC_.js} +1 -1
  19. package/web/dist/assets/{php-C_eP8QT0.js → php-C7wdcWqa.js} +1 -1
  20. package/web/dist/assets/{WorkspaceTerminal-DF87HK0D.js → plugin-CDXXKG8W.js} +12 -12
  21. package/web/dist/assets/plugin-DuICpslz.js +1 -0
  22. package/web/dist/assets/plugin-U9RqGH7R.js +3 -0
  23. package/web/dist/assets/{rst-D71MTZLw.js → rst-DXm1XNUD.js} +1 -1
  24. package/web/dist/assets/{ruby-DVYYFOy_.js → ruby-BM86KL0M.js} +1 -1
  25. package/web/dist/assets/style.css +2 -2
  26. package/web/dist/assets/{svelte-uHeUtAW3.js → svelte-Dizghd7i.js} +1 -1
  27. package/web/dist/assets/{vue-C1Yqc5Ux.js → vue-DJuuwuj_.js} +1 -1
  28. package/web/dist/assets/app-4px1DWHV.js +0 -544
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.
@@ -47,6 +57,7 @@ In Pi, enter `/web` to open the interface in your default browser. Pi also print
47
57
  - In **Git changes → Changes**, use each file’s **+ / −** button to stage or unstage it, use the fixed bottom composer to commit only the staged index (Ctrl/Cmd+Enter is supported), and click the branch name to search/switch local branches or open **New branch**. The file list scrolls independently; full repository metadata is available on the short repository name’s tooltip. Drafts stay with each chat’s Git tab. Commits and branch switches require a root workspace; switching also requires a clean working tree, including untracked files. Writes require all known chats using the worktree to be idle, reject stale snapshots, and honor Git hooks/signing. Conflicts, active Git operations, locks and occupied worktree branches block incompatible writes. Failed or unconfirmed operations retain drafts and never retry automatically. Changes are shared by chats using the same worktree. No fetch/push, forced switch, stash or discard is performed.
48
58
  - In **Git changes → History**, browse commits alongside their branch/merge graph, with HEAD, local branch, remote-tracking branch and tag labels. Load history 50 commits at a time; a ref change resets pagination to prevent mixed histories. Open commit details for the full message, author/committer, timestamps, parents and changed files, then preview a read-only file diff alongside the same commit file list without opening another tab. Merge details let you select the parent to compare against; root commits compare against an empty tree. The graph shows repository-wide metadata while commit files and diffs stay within the session directory. Graph selection and loaded history remain with each chat’s Git tab until the page reloads. Remote labels use local refs without fetching.
49
59
  - Attach up to 20 files of 20 MB each by selecting, dropping, or pasting them. Images show previews and are also sent as Pi image content.
60
+ - Open Plugins from the sidebar or Settings to inspect and switch the bundled Git, Files and Terminal capabilities. Switches are global, persist locally, and require every chat to be idle. Disabling closes related tabs and blocks backend requests; Terminal asks for confirmation before ending all service-owned terminals. External Pi Web runtimes remain managed through Packages & extensions rather than a misleading UI-only switch.
50
61
  - Manage appearance, Pi packages, extensions, skills, and models from the settings panel. The Models page can add models, edit display names, context windows, output limits, and input types, and restore built-in defaults; changes are saved to Pi's `models.json`. Browser sign-in opens the provider's authorization page automatically; manual code entry remains available when a callback cannot reach Pi. Stored provider credentials can also be removed there. Credentials stay in Pi's local `auth.json` and are never returned to the browser.
51
62
 
52
63
  If you enter `/web` manually in a Pi terminal, that terminal session stays synchronized with the browser. With the launcher, Pi runs in the background. Sessions opened in other workspaces use the Pi SDK and load that workspace's skills and project context. They load enabled Web plugin Pi entries explicitly while keeping other Pi extensions isolated from the parent bridge.
@@ -57,6 +68,8 @@ On startup, the app discovers workspaces from Pi's saved sessions, so conversati
57
68
 
58
69
  ## Optional desktop application
59
70
 
71
+ **[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.
72
+
60
73
  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.
61
74
 
62
75
  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.
@@ -79,7 +92,7 @@ npm run stop
79
92
 
80
93
  For local Web plugin development with the sibling `pi-extensions` workspace, follow its `README.md`. Set `PI_WEBAPP_PLUGIN_DEV_ROOTS=../pi-extensions/packages/plan-mode` when starting this app; browser asset changes refresh automatically and Pi entry changes trigger a safe reload when the agent is idle.
81
94
 
82
- The source lives in `extension/`, `shared/`, and `web/src/`. The npm package contains only the bundled, minified JavaScript extension, built web assets, cover image, and the English and Chinese READMEs. No TypeScript source or source maps are published. Minification makes the shipped code harder to read; it does not encrypt JavaScript.
95
+ Source ownership is split across `src/adapters/pi/` (the thin Pi entry), `src/host/` (server and browser host), `src/plugins/builtin/` (Git, Files and Terminal, each with server/client/contracts), `src/contracts/`, and shared UI in `web/src/ui/`. See [architecture and plugin management](docs/architecture.md). The npm package contains only the bundled, minified JavaScript extension, built web assets, cover image, and the English and Chinese READMEs. No TypeScript source or source maps are published. Minification makes the shipped code harder to read; it does not encrypt JavaScript.
83
96
 
84
97
  ## Error collection
85
98
 
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 运行和管理;浏览器提供实时的对话与控制界面。
@@ -47,6 +57,7 @@ pi
47
57
  - 在「Git 改动 → 改动」中,用文件右侧的 **+ / −** 逐文件暂存或取消暂存;底部固定提交栏仅提交暂存区内容(支持 Ctrl/Cmd+Enter);点击顶部分支名称,可搜索和切换本地分支,选择「新建分支」才展开创建表单。文件列表独立滚动,仓库完整信息通过短名称的悬停提示查看。草稿随各聊天的 Git 标签保留。提交和切换分支要求仓库根目录工作区,切换还要求整个工作树干净(包括未跟踪文件)。写操作要求共用工作树的已知聊天均为空闲,并校验状态快照,遵守 Git hooks 与签名配置。冲突、未完成的 Git 操作、锁及其他工作树占用的分支会阻止相应操作。失败或结果不明时保留草稿,不自动重试。同一工作树的改动由多个聊天共享。不执行 fetch/push、强制切换、stash 或丢弃改动。
48
58
  - 在「Git 改动 → 历史」中浏览提交及其分支、合并关系图,显示 HEAD、本地分支、远端跟踪分支和标签。历史每次加载 50 条;引用变化时重新加载首页,避免分页混入不同版本的历史。点击提交查看完整说明、作者与提交者、时间、父提交及改动文件,再点击文件在当前提交详情内预览只读差异,保留文件列表,不再新建差异标签。合并提交可选择比较的父提交,根提交与空目录比较。关系图展示整个仓库的提交元数据,提交文件和差异仍限制在当前会话目录内。历史选中项与已加载页随各聊天的 Git 标签保留,网页刷新后重置。远端标签仅使用本地记录,不发起拉取。
49
59
  - 通过选择、拖放或粘贴附加文件,最多 20 个,每个不超过 20 MB。图片会显示预览,并作为 Pi 图片内容发送。
60
+ - 从侧栏「插件」或「设置 → 插件」管理内置 Git、文件和终端。支持列表/详情、搜索、真实启停和全局持久化;所有聊天空闲后才可切换。停用会关闭相关标签并阻止后端请求,停用终端需确认并结束此服务的全部终端。外部 Pi Web 插件展示运行时归属,仍通过「包与扩展」管理,不提供只隐藏 UI 的假开关。
50
61
  - 在设置面板中管理外观、Pi 软件包、扩展、技能和模型。模型页可添加模型、编辑显示名称、上下文窗口、最大输出 token 数和输入类型,或恢复内置模型的默认参数;配置写入 Pi 的 `models.json`。网页登录会自动打开提供方授权页;当回调无法到达 Pi 时,仍可手动粘贴授权码。已保存的提供方认证可在这里移除。凭据保留在 Pi 本地的 `auth.json`,不会返回给浏览器。
51
62
 
52
63
  如果通过 Pi 终端手动输入 `/web`,该终端会话会与浏览器保持同步。使用启动器时,Pi 在后台运行。在其他工作区打开的会话使用 Pi SDK,并加载该工作区的技能和项目上下文;已启用的 Web 插件 Pi 入口会显式加载,其他普通 Pi 扩展仍与主会话隔离。
@@ -57,6 +68,8 @@ pi
57
68
 
58
69
  ## 桌面端(可选)
59
70
 
71
+ **[下载 pi 桌面测试版](https://github.com/chengzhiyi/pi-webapp/releases)** — 目前仅发布已验收的 macOS Apple 芯片(arm64)版本。在 `desktop-v...` 预发布版本中下载 DMG,核对 `SHA256SUMS` 后安装 **pi.app**,在“pi → 关于 pi”查看构建号。测试版未签名、未公证,请勿全局关闭系统安全保护;Windows/Linux 暂不提供已验收的发行包。
72
+
60
73
  同一套界面也可在名为 **pi** 的 Electron 桌面程序中使用,现有浏览器与 `/web` 方式保持不变。桌面包自带 Node/Pi,支持独立窗口、已有服务复用、在浏览器打开同一服务,以及退出时选择保留或停止后台任务。
61
74
 
62
75
  源码构建:`npm ci` → `npm run desktop:prepare` → `npm run desktop:start`。运行 `npm run desktop:package` 生成当前系统/架构的安装包,输出到 `desktop-release/`。当前本地验证目标为 macOS arm64;Windows/Linux 打包配置需在对应系统验证。首版安装包未签名,尚无桌面自动更新。安装包文件名包含桌面构建号;“pi → 关于 pi”显示实际运行的构建号和应用位置。替换前先退出旧桌面,外部兼容 Web 后台无需停止;若替换桌面自有运行时,请先结束任务并停止该自有后台。
@@ -79,7 +92,7 @@ npm run stop
79
92
 
80
93
  与同级 `pi-extensions` 联调时,先在该目录运行 `pnpm install && pnpm build`,再运行 `pnpm dev`;在本项目设置 `PI_WEBAPP_PLUGIN_DEV_ROOTS=../pi-extensions/packages/plan-mode` 后执行 `npm run start`。浏览器资源变化后页面会刷新,Pi 入口变化后会等待代理空闲并重载扩展。完整步骤见 `pi-extensions/README.md`。
81
94
 
82
- 源代码位于 `extension/`、`shared/` 和 `web/src/`。npm 软件包仅包含打包并压缩后的 JavaScript 扩展、构建后的 Web 资源、封面图片,以及英文和中文 README;不会发布 TypeScript 源码或 source map。代码压缩会增加阅读发布版本代码的难度,但不会对 JavaScript 加密。
95
+ 源码按职责组织:`src/adapters/pi/` 为薄 Pi 入口,`src/host/` 为前后端宿主,`src/plugins/builtin/` 分别集中 Git、文件和终端的 server/client/contract,`src/contracts/` 保存宿主跨端契约,`web/src/ui/` 保留共享 UI。详见[目录与插件管理说明](docs/architecture.md)。npm 软件包仅包含打包并压缩后的 JavaScript 扩展、构建后的 Web 资源、封面图片,以及英文和中文 README;不会发布 TypeScript 源码或 source map。代码压缩会增加阅读发布版本代码的难度,但不会对 JavaScript 加密。
83
96
 
84
97
  ## 错误采集
85
98
 
@@ -9,6 +9,9 @@ const runOpenCommand = (command, args) => new Promise((resolve, reject) => {
9
9
 
10
10
  /** Open on the host desktop only when this process has a local graphical session. */
11
11
  export async function openWebPage(url, platform = process.platform, env = process.env, run = runOpenCommand) {
12
+ // Embedded desktop owns its window. Awaiting xdg-open here can keep its RPC
13
+ // readiness notification blocked for the lifetime of an external browser.
14
+ if (env.PI_WEBAPP_AUTO_OPEN === "0" || env.PI_WEBAPP_RUNTIME === "desktop") return false;
12
15
  if (env.SSH_CONNECTION || env.SSH_TTY || env.SSH_CLIENT) return false;
13
16
  if (platform === "linux" && !env.DISPLAY && !env.WAYLAND_DISPLAY) return false;
14
17
  const command = platform === "darwin" ? "open" : platform === "linux" ? "xdg-open" : platform === "win32" ? "explorer.exe" : null;
package/bin/pi-webapp.mjs CHANGED
@@ -146,6 +146,9 @@ async function serve(pi, args) {
146
146
  instanceId, pid: process.pid, piPid: child.pid, uptimeMs: Math.round(performance.now() - startedAt), ...fields }));
147
147
  } catch { /* Diagnostics must not interrupt process supervision. */ }
148
148
  };
149
+ // Opt-in fixture diagnostics: fixed milestones only, never RPC content or URLs.
150
+ const startupStage = stage => { if (process.env.PI_WEBAPP_STARTUP_TRACE === "1") lifecycle("launcher_startup_stage", { stage }); };
151
+ let sawStdout = false;
149
152
  const devWatchers = [];
150
153
  let devReloadTimer;
151
154
  let devReloadCount = 0;
@@ -187,6 +190,7 @@ async function serve(pi, args) {
187
190
  process.on("SIGINT", () => shutdown("signal_sigint"));
188
191
  child.stdout?.on("data", (chunk) => {
189
192
  if (failed) return;
193
+ if (!sawStdout) { sawStdout = true; startupStage("first-rpc-output"); }
190
194
  buffer += chunk.toString("utf8");
191
195
  if (buffer.length > 8 * 1024 * 1024) { fail("Pi RPC 输出超出预期大小"); return; }
192
196
  for (let index; (index = buffer.indexOf("\n")) !== -1;) {
@@ -200,6 +204,7 @@ async function serve(pi, args) {
200
204
  }
201
205
  if (ready || opening) continue;
202
206
  if (record?.type === "response" && record.id === "list-commands") {
207
+ startupStage("command-list-response");
203
208
  if (record.success !== true || !Array.isArray(record.data?.commands)) {
204
209
  fail("无法读取 Pi 扩展命令列表");
205
210
  return;
@@ -212,6 +217,7 @@ async function serve(pi, args) {
212
217
  }
213
218
  devReloadCommand = record.data.commands.find((item) => item?.source === "extension"
214
219
  && item.sourceInfo?.path === extension && /^web-dev-reload(?::\d+)?$/.test(item.name))?.name;
220
+ startupStage("opening-web-command");
215
221
  child.stdin?.write(JSON.stringify({ id: "open-web", type: "prompt", message: `/${command.name}` }) + "\n");
216
222
  continue;
217
223
  }
@@ -220,6 +226,7 @@ async function serve(pi, args) {
220
226
  return;
221
227
  }
222
228
  if (record?.type !== "extension_ui_request" || record.method !== "notify" || typeof record.message !== "string" || !record.message.startsWith("pi-webapp: ")) continue;
229
+ startupStage("web-ready-notification");
223
230
  let url;
224
231
  try { url = new URL(record.message.slice("pi-webapp: ".length)); }
225
232
  catch { continue; }
@@ -252,6 +259,7 @@ async function serve(pi, args) {
252
259
  }
253
260
  });
254
261
  child.stdin?.on("error", (error) => fail(`无法向 Pi 发送启动命令:${error.message}`));
262
+ startupStage("waiting-command-list");
255
263
  child.stdin?.write(JSON.stringify({ id: "list-commands", type: "get_commands" }) + "\n");
256
264
  await new Promise((resolveExit) => {
257
265
  child.once("error", (error) => { fail(`无法启动 Pi:${error.message}`); resolveExit(); });