pi-webapp 0.1.6 → 0.1.7
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 +13 -2
- package/README.zh-CN.md +11 -2
- package/THIRD_PARTY_LICENSE.txt +24 -0
- package/bin/pi-webapp.mjs +31 -4
- package/dist/extension.js +9 -6
- package/package.json +28 -5
- package/web/dist/assets/KaTeX_AMS-Regular.ttf +0 -0
- package/web/dist/assets/KaTeX_AMS-Regular.woff +0 -0
- package/web/dist/assets/KaTeX_AMS-Regular.woff2 +0 -0
- package/web/dist/assets/KaTeX_Caligraphic-Bold.ttf +0 -0
- package/web/dist/assets/KaTeX_Caligraphic-Bold.woff +0 -0
- package/web/dist/assets/KaTeX_Caligraphic-Bold.woff2 +0 -0
- package/web/dist/assets/KaTeX_Caligraphic-Regular.ttf +0 -0
- package/web/dist/assets/KaTeX_Caligraphic-Regular.woff +0 -0
- package/web/dist/assets/KaTeX_Caligraphic-Regular.woff2 +0 -0
- package/web/dist/assets/KaTeX_Fraktur-Bold.ttf +0 -0
- package/web/dist/assets/KaTeX_Fraktur-Bold.woff +0 -0
- package/web/dist/assets/KaTeX_Fraktur-Bold.woff2 +0 -0
- package/web/dist/assets/KaTeX_Fraktur-Regular.ttf +0 -0
- package/web/dist/assets/KaTeX_Fraktur-Regular.woff +0 -0
- package/web/dist/assets/KaTeX_Fraktur-Regular.woff2 +0 -0
- package/web/dist/assets/KaTeX_Main-Bold.ttf +0 -0
- package/web/dist/assets/KaTeX_Main-Bold.woff +0 -0
- package/web/dist/assets/KaTeX_Main-Bold.woff2 +0 -0
- package/web/dist/assets/KaTeX_Main-BoldItalic.ttf +0 -0
- package/web/dist/assets/KaTeX_Main-BoldItalic.woff +0 -0
- package/web/dist/assets/KaTeX_Main-BoldItalic.woff2 +0 -0
- package/web/dist/assets/KaTeX_Main-Italic.ttf +0 -0
- package/web/dist/assets/KaTeX_Main-Italic.woff +0 -0
- package/web/dist/assets/KaTeX_Main-Italic.woff2 +0 -0
- package/web/dist/assets/KaTeX_Main-Regular.ttf +0 -0
- package/web/dist/assets/KaTeX_Main-Regular.woff +0 -0
- package/web/dist/assets/KaTeX_Main-Regular.woff2 +0 -0
- package/web/dist/assets/KaTeX_Math-BoldItalic.ttf +0 -0
- package/web/dist/assets/KaTeX_Math-BoldItalic.woff +0 -0
- package/web/dist/assets/KaTeX_Math-BoldItalic.woff2 +0 -0
- package/web/dist/assets/KaTeX_Math-Italic.ttf +0 -0
- package/web/dist/assets/KaTeX_Math-Italic.woff +0 -0
- package/web/dist/assets/KaTeX_Math-Italic.woff2 +0 -0
- package/web/dist/assets/KaTeX_SansSerif-Bold.ttf +0 -0
- package/web/dist/assets/KaTeX_SansSerif-Bold.woff +0 -0
- package/web/dist/assets/KaTeX_SansSerif-Bold.woff2 +0 -0
- package/web/dist/assets/KaTeX_SansSerif-Italic.ttf +0 -0
- package/web/dist/assets/KaTeX_SansSerif-Italic.woff +0 -0
- package/web/dist/assets/KaTeX_SansSerif-Italic.woff2 +0 -0
- package/web/dist/assets/KaTeX_SansSerif-Regular.ttf +0 -0
- package/web/dist/assets/KaTeX_SansSerif-Regular.woff +0 -0
- package/web/dist/assets/KaTeX_SansSerif-Regular.woff2 +0 -0
- package/web/dist/assets/KaTeX_Script-Regular.ttf +0 -0
- package/web/dist/assets/KaTeX_Script-Regular.woff +0 -0
- package/web/dist/assets/KaTeX_Script-Regular.woff2 +0 -0
- package/web/dist/assets/KaTeX_Size1-Regular.ttf +0 -0
- package/web/dist/assets/KaTeX_Size1-Regular.woff +0 -0
- package/web/dist/assets/KaTeX_Size1-Regular.woff2 +0 -0
- package/web/dist/assets/KaTeX_Size2-Regular.ttf +0 -0
- package/web/dist/assets/KaTeX_Size2-Regular.woff +0 -0
- package/web/dist/assets/KaTeX_Size2-Regular.woff2 +0 -0
- package/web/dist/assets/KaTeX_Size3-Regular.ttf +0 -0
- package/web/dist/assets/KaTeX_Size3-Regular.woff +0 -0
- package/web/dist/assets/KaTeX_Size4-Regular.ttf +0 -0
- package/web/dist/assets/KaTeX_Size4-Regular.woff +0 -0
- package/web/dist/assets/KaTeX_Size4-Regular.woff2 +0 -0
- package/web/dist/assets/KaTeX_Typewriter-Regular.ttf +0 -0
- package/web/dist/assets/KaTeX_Typewriter-Regular.woff +0 -0
- package/web/dist/assets/KaTeX_Typewriter-Regular.woff2 +0 -0
- package/web/dist/assets/app.js +504 -55
- package/web/dist/assets/asciidoc.js +1 -0
- package/web/dist/assets/bat.js +1 -0
- package/web/dist/assets/bibtex.js +1 -0
- package/web/dist/assets/c.js +1 -0
- package/web/dist/assets/clojure.js +1 -0
- package/web/dist/assets/cmake.js +1 -0
- package/web/dist/assets/cpp.js +1 -0
- package/web/dist/assets/csharp.js +1 -0
- package/web/dist/assets/css.js +1 -0
- package/web/dist/assets/csv.js +1 -0
- package/web/dist/assets/dart.js +1 -0
- package/web/dist/assets/diff.js +1 -0
- package/web/dist/assets/dotenv.js +1 -0
- package/web/dist/assets/elixir.js +1 -0
- package/web/dist/assets/erlang.js +1 -0
- package/web/dist/assets/fish.js +1 -0
- package/web/dist/assets/fsharp.js +1 -0
- package/web/dist/assets/go.js +1 -0
- package/web/dist/assets/graphql.js +1 -0
- package/web/dist/assets/groovy.js +1 -0
- package/web/dist/assets/haskell.js +1 -0
- package/web/dist/assets/hcl.js +1 -0
- package/web/dist/assets/html-derivative.js +1 -0
- package/web/dist/assets/html.js +1 -0
- package/web/dist/assets/http.js +1 -0
- package/web/dist/assets/ini.js +1 -0
- package/web/dist/assets/java.js +1 -0
- package/web/dist/assets/javascript.js +1 -0
- package/web/dist/assets/julia.js +1 -0
- package/web/dist/assets/kotlin.js +1 -0
- package/web/dist/assets/latex.js +1 -0
- package/web/dist/assets/less.js +1 -0
- package/web/dist/assets/log.js +1 -0
- package/web/dist/assets/lua.js +1 -0
- package/web/dist/assets/make.js +1 -0
- package/web/dist/assets/markdown.js +1 -0
- package/web/dist/assets/mdx.js +1 -0
- package/web/dist/assets/nix.js +1 -0
- package/web/dist/assets/perl.js +1 -0
- package/web/dist/assets/php.js +1 -0
- package/web/dist/assets/powershell.js +1 -0
- package/web/dist/assets/proto.js +1 -0
- package/web/dist/assets/python.js +1 -0
- package/web/dist/assets/r.js +1 -0
- package/web/dist/assets/rst.js +1 -0
- package/web/dist/assets/ruby.js +1 -0
- package/web/dist/assets/rust.js +1 -0
- package/web/dist/assets/scala.js +1 -0
- package/web/dist/assets/scss.js +1 -0
- package/web/dist/assets/sql.js +1 -0
- package/web/dist/assets/style.css +1 -1
- package/web/dist/assets/svelte.js +1 -0
- package/web/dist/assets/swift.js +1 -0
- package/web/dist/assets/system-verilog.js +1 -0
- package/web/dist/assets/toml.js +1 -0
- package/web/dist/assets/vb.js +1 -0
- package/web/dist/assets/verilog.js +1 -0
- package/web/dist/assets/vue.js +1 -0
- package/web/dist/assets/xml.js +1 -0
- package/web/dist/assets/yaml.js +1 -0
package/README.md
CHANGED
|
@@ -39,12 +39,12 @@ In Pi, enter `/web` to open the interface in your default browser. Pi also print
|
|
|
39
39
|
## Features
|
|
40
40
|
|
|
41
41
|
- View the current conversation with Markdown, streaming output, expandable reasoning and tool calls, token usage, and a turn-by-turn trace.
|
|
42
|
-
- Send messages,
|
|
42
|
+
- Send messages, pause and continue a run, start a new Pi session, and change the current model or thinking level. The bottom-right control pauses an active run; an empty composer offers Continue after pausing, including after refreshing or reopening the session. Continue uses an internal control action without adding a user message; the model makes a new request based on existing progress, and plan mode still requires fresh approval.
|
|
43
43
|
- Browse workspaces and saved sessions. Add a workspace with the native directory picker when available, or use the built-in directory browser over SSH.
|
|
44
44
|
- 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.
|
|
45
45
|
- 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.
|
|
46
46
|
|
|
47
|
-
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
|
|
47
|
+
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.
|
|
48
48
|
|
|
49
49
|
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.
|
|
50
50
|
|
|
@@ -62,10 +62,21 @@ npm run stop
|
|
|
62
62
|
|
|
63
63
|
`npm run start` builds the project, starts Pi in the background, and opens the web interface. After editing the extension, run `npm run stop` followed by `npm run start`. If you develop with `pi -e .`, enter `/reload` and `/web` in Pi after rebuilding. Refreshing an old browser page alone does not replace the running bridge.
|
|
64
64
|
|
|
65
|
+
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.
|
|
66
|
+
|
|
65
67
|
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.
|
|
66
68
|
|
|
67
69
|
## Publish
|
|
68
70
|
|
|
71
|
+
CI resolves the published `@chengzhiyi/pi-web-protocol` version before `npm ci`.
|
|
72
|
+
Until the first protocol publication, verification builds a pinned `pi-extensions`
|
|
73
|
+
commit in an ignored `.ci/` checkout and uses that local package. Checks, tests,
|
|
74
|
+
and builds still run; the Actions summary explains why host publication is waiting.
|
|
75
|
+
Release builds always require the published npm dependency. Once it exists, the
|
|
76
|
+
next workflow uses its exact version and the release commit records the lockfile.
|
|
77
|
+
Use Actions' manual run after initializing npm; protocol releases do not trigger
|
|
78
|
+
this repository automatically.
|
|
79
|
+
|
|
69
80
|
`npm publish` runs the checks, tests, and production build. The `pi-package` keyword makes the published npm package eligible for the [Pi package catalog](https://pi.dev/packages); catalog updates may lag behind npm.
|
|
70
81
|
|
|
71
82
|
GitHub Actions runs `check`, `test`, and `build` on pull requests to `main`. A push to `main` repeats those checks, chooses the next patch version from the source version and npm `latest`, then commits the updated `package.json` and `package-lock.json` to `main` before publishing. The release commit uses the workflow's `GITHUB_TOKEN` and does not start another workflow run. To start a new minor or major series, raise the version in both package files in the pull request. Each release also updates the package's `pi.image` URL to its own version. The repository must allow the workflow to push to `main` for publishing to proceed.
|
package/README.zh-CN.md
CHANGED
|
@@ -39,12 +39,12 @@ pi
|
|
|
39
39
|
## 功能
|
|
40
40
|
|
|
41
41
|
- 查看当前对话,包括 Markdown 内容、流式输出、可展开的推理过程与工具调用、Token 用量,以及逐轮执行轨迹。
|
|
42
|
-
-
|
|
42
|
+
- 发送消息、暂停与继续运行、启动新的 Pi 会话,以及切换当前模型或思考级别。运行时右下角显示暂停;暂停后清空输入框即可继续,刷新或重新打开会话后仍可恢复。继续通过内部控制动作恢复原任务,不新增用户消息;模型会基于已有进度发起新请求,计划模式仍需重新审批。
|
|
43
43
|
- 浏览工作区和已保存的会话。环境支持时可通过系统目录选择器添加工作区;通过 SSH 使用时,也可使用内置目录浏览器。
|
|
44
44
|
- 通过选择、拖放或粘贴附加文件,最多 20 个,每个不超过 20 MB。图片会显示预览,并作为 Pi 图片内容发送。
|
|
45
45
|
- 在设置面板中管理外观、Pi 软件包、扩展、技能和模型。模型页可添加模型、编辑显示名称、上下文窗口、最大输出 token 数和输入类型,或恢复内置模型的默认参数;配置写入 Pi 的 `models.json`。网页登录会自动打开提供方授权页;当回调无法到达 Pi 时,仍可手动粘贴授权码。已保存的提供方认证可在这里移除。凭据保留在 Pi 本地的 `auth.json`,不会返回给浏览器。
|
|
46
46
|
|
|
47
|
-
如果通过 Pi 终端手动输入 `/web`,该终端会话会与浏览器保持同步。使用启动器时,Pi 在后台运行。在其他工作区打开的会话使用 Pi SDK
|
|
47
|
+
如果通过 Pi 终端手动输入 `/web`,该终端会话会与浏览器保持同步。使用启动器时,Pi 在后台运行。在其他工作区打开的会话使用 Pi SDK,并加载该工作区的技能和项目上下文;已启用的 Web 插件 Pi 入口会显式加载,其他普通 Pi 扩展仍与主会话隔离。
|
|
48
48
|
|
|
49
49
|
启动时会从 Pi 已保存的会话中发现工作区,因此先前在其他目录使用 Pi 的会话也会出现在侧边栏。工作区记录和附件继续存放在 Pi 现有的 `pi-web/` 数据目录下。从侧边栏移除工作区不会删除其文件或会话;移除后如需再次显示,可以手动添加。
|
|
50
50
|
|
|
@@ -62,10 +62,19 @@ npm run stop
|
|
|
62
62
|
|
|
63
63
|
`npm run start` 会构建项目、在后台启动 Pi 并打开 Web 界面。修改扩展后,运行 `npm run stop`,再运行 `npm run start`;如果使用 `pi -e .` 开发,则在 Pi 中依次输入 `/reload` 和 `/web`。仅刷新旧的浏览器页面不会替换正在运行的连接桥接代码。
|
|
64
64
|
|
|
65
|
+
与同级 `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`。
|
|
66
|
+
|
|
65
67
|
源代码位于 `extension/`、`shared/` 和 `web/src/`。npm 软件包仅包含打包并压缩后的 JavaScript 扩展、构建后的 Web 资源、封面图片,以及英文和中文 README;不会发布 TypeScript 源码或 source map。代码压缩会增加阅读发布版本代码的难度,但不会对 JavaScript 加密。
|
|
66
68
|
|
|
67
69
|
## 发布
|
|
68
70
|
|
|
71
|
+
CI 会先从 npm 解析 `@chengzhiyi/pi-web-protocol` 的已发布版本,再运行 `npm ci`。
|
|
72
|
+
首次发布协议前,校验任务会将固定提交的 `pi-extensions` 检出到被忽略的 `.ci/`
|
|
73
|
+
目录,构建协议并使用本地包,完整执行检查、测试与构建;Actions 摘要会说明
|
|
74
|
+
宿主发布仍在等待协议初始化。正式发布始终要求准确的 npm 依赖,并将清单和
|
|
75
|
+
锁文件变化同步回仓库。协议发布后可以在 Actions 手动运行工作流;协议发布
|
|
76
|
+
不会主动触发这个仓库。
|
|
77
|
+
|
|
69
78
|
`npm publish` 会运行检查、测试和生产构建。`pi-package` 关键词使发布到 npm 的软件包有资格进入 [Pi 软件包目录](https://pi.dev/packages);目录更新可能晚于 npm。
|
|
70
79
|
|
|
71
80
|
GitHub Actions 会在针对 `main` 的拉取请求中运行 `check`、`test` 和 `build`。代码推送到 `main` 后会再次运行这些检查,根据源码版本和 npm `latest` 版本确定下一个补丁版本,先将更新后的 `package.json` 和 `package-lock.json` 提交回 `main`,再发布到 npm。版本同步提交使用工作流的 `GITHUB_TOKEN`,不会再次触发工作流。如需开始新的次版本或主版本,请在拉取请求中同步提高两个包文件的版本。每次发布也会将包内 `pi.image` 的地址更新为该版本。仓库必须允许工作流推送到 `main`,发布才能继续。
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
DSH presentation components are derived from DeepSeek Harness, commit
|
|
2
|
+
477b4f420553e8a52c2fbccc464d7561b239c443.
|
|
3
|
+
|
|
4
|
+
MIT License
|
|
5
|
+
|
|
6
|
+
Copyright (c) 2026 DeepSeek
|
|
7
|
+
|
|
8
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
9
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
10
|
+
in the Software without restriction, including without limitation the rights
|
|
11
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
12
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
13
|
+
furnished to do so, subject to the following conditions:
|
|
14
|
+
|
|
15
|
+
The above copyright notice and this permission notice shall be included in all
|
|
16
|
+
copies or substantial portions of the Software.
|
|
17
|
+
|
|
18
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
19
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
20
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
21
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
22
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
23
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
24
|
+
SOFTWARE.
|
package/bin/pi-webapp.mjs
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { spawn as spawnNode } from "node:child_process";
|
|
3
3
|
import { randomUUID } from "node:crypto";
|
|
4
|
-
import { closeSync, existsSync, openSync } from "node:fs";
|
|
4
|
+
import { closeSync, existsSync, openSync, watch } from "node:fs";
|
|
5
5
|
import { mkdir, open, readFile, rename, stat, unlink, writeFile } from "node:fs/promises";
|
|
6
6
|
import { homedir } from "node:os";
|
|
7
|
-
import { dirname, join, resolve } from "node:path";
|
|
7
|
+
import { delimiter, dirname, join, resolve } from "node:path";
|
|
8
8
|
import { fileURLToPath } from "node:url";
|
|
9
9
|
import spawn from "cross-spawn";
|
|
10
10
|
import { openWebPage } from "./open-web-page.mjs";
|
|
@@ -113,7 +113,8 @@ async function serve(pi, args) {
|
|
|
113
113
|
return;
|
|
114
114
|
} finally { await lock?.close().catch(() => {}); }
|
|
115
115
|
|
|
116
|
-
const
|
|
116
|
+
const pluginRoots = (process.env.PI_WEBAPP_PLUGIN_DEV_ROOTS ?? "").split(delimiter).filter(Boolean).map((root) => resolve(root));
|
|
117
|
+
const child = spawn(pi, ["--mode", "rpc", "-e", extension, ...pluginRoots.flatMap((root) => ["-e", root]), ...args], {
|
|
117
118
|
cwd: process.cwd(), env: { ...process.env, PI_WEBAPP_AUTO_OPEN: "0", PI_WEBAPP_LAUNCHER_NONCE: nonce }, stdio: ["pipe", "pipe", "pipe"],
|
|
118
119
|
});
|
|
119
120
|
child.stderr?.pipe(process.stderr, { end: false });
|
|
@@ -127,6 +128,10 @@ async function serve(pi, args) {
|
|
|
127
128
|
let runningUrl = null;
|
|
128
129
|
let buffer = "";
|
|
129
130
|
let killTimer;
|
|
131
|
+
const devWatchers = [];
|
|
132
|
+
let devReloadTimer;
|
|
133
|
+
let devReloadCount = 0;
|
|
134
|
+
let devReloadCommand;
|
|
130
135
|
const shutdown = () => {
|
|
131
136
|
if (stopping) return;
|
|
132
137
|
stopping = true;
|
|
@@ -157,7 +162,7 @@ async function serve(pi, args) {
|
|
|
157
162
|
process.on("SIGTERM", shutdown);
|
|
158
163
|
process.on("SIGINT", shutdown);
|
|
159
164
|
child.stdout?.on("data", (chunk) => {
|
|
160
|
-
if (
|
|
165
|
+
if (failed) return;
|
|
161
166
|
buffer += chunk.toString("utf8");
|
|
162
167
|
if (buffer.length > 8 * 1024 * 1024) { fail("Pi RPC 输出超出预期大小"); return; }
|
|
163
168
|
for (let index; (index = buffer.indexOf("\n")) !== -1;) {
|
|
@@ -165,6 +170,11 @@ async function serve(pi, args) {
|
|
|
165
170
|
buffer = buffer.slice(index + 1);
|
|
166
171
|
let record;
|
|
167
172
|
try { record = JSON.parse(line); } catch { continue; }
|
|
173
|
+
if (record?.type === "response" && /^dev-reload-\d+$/.test(record.id ?? "")) {
|
|
174
|
+
console.error(`pi-webapp: ${record.id} /${devReloadCommand ?? "web-dev-reload"}: ${record.success === true ? "reloaded" : `failed: ${record.error ?? "Unknown RPC error"}`}`);
|
|
175
|
+
continue;
|
|
176
|
+
}
|
|
177
|
+
if (ready || opening) continue;
|
|
168
178
|
if (record?.type === "response" && record.id === "list-commands") {
|
|
169
179
|
if (record.success !== true || !Array.isArray(record.data?.commands)) {
|
|
170
180
|
fail("无法读取 Pi 扩展命令列表");
|
|
@@ -176,6 +186,8 @@ async function serve(pi, args) {
|
|
|
176
186
|
fail("Pi 没有加载当前项目的 Web 扩展");
|
|
177
187
|
return;
|
|
178
188
|
}
|
|
189
|
+
devReloadCommand = record.data.commands.find((item) => item?.source === "extension"
|
|
190
|
+
&& item.sourceInfo?.path === extension && /^web-dev-reload(?::\d+)?$/.test(item.name))?.name;
|
|
179
191
|
child.stdin?.write(JSON.stringify({ id: "open-web", type: "prompt", message: `/${command.name}` }) + "\n");
|
|
180
192
|
continue;
|
|
181
193
|
}
|
|
@@ -196,6 +208,19 @@ async function serve(pi, args) {
|
|
|
196
208
|
ready = true;
|
|
197
209
|
clearTimeout(startupTimer);
|
|
198
210
|
notifyParent({ type: "ready", pid: process.pid, url: url.href });
|
|
211
|
+
for (const root of pluginRoots) {
|
|
212
|
+
try {
|
|
213
|
+
devWatchers.push(watch(join(root, "dist"), (_event, file) => {
|
|
214
|
+
if (String(file ?? "") !== "extension.js") return;
|
|
215
|
+
clearTimeout(devReloadTimer);
|
|
216
|
+
devReloadTimer = setTimeout(() => {
|
|
217
|
+
if (closed || stopping) return;
|
|
218
|
+
if (!devReloadCommand) { console.error("pi-webapp: development reload unavailable: local extension command not found"); return; }
|
|
219
|
+
child.stdin?.write(JSON.stringify({ id: `dev-reload-${++devReloadCount}`, type: "prompt", message: `/${devReloadCommand}` }) + "\n");
|
|
220
|
+
}, 250);
|
|
221
|
+
}));
|
|
222
|
+
} catch (error) { console.error(`pi-webapp: cannot watch plugin ${root}: ${error}`); }
|
|
223
|
+
}
|
|
199
224
|
})
|
|
200
225
|
.catch((error) => fail(`无法保存启动状态:${error.message}`));
|
|
201
226
|
return;
|
|
@@ -213,6 +238,8 @@ async function serve(pi, args) {
|
|
|
213
238
|
});
|
|
214
239
|
await stateWrite;
|
|
215
240
|
clearTimeout(startupTimer);
|
|
241
|
+
clearTimeout(devReloadTimer);
|
|
242
|
+
for (const watcher of devWatchers) watcher.close();
|
|
216
243
|
clearInterval(stopTimer);
|
|
217
244
|
clearTimeout(killTimer);
|
|
218
245
|
try { if ((await readFile(stopPath, "utf8")).trim() === nonce) await unlink(stopPath); } catch { /* Already removed. */ }
|