pi2web 0.2.0

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.
@@ -0,0 +1,256 @@
1
+ # Remote Pi Android App 功能说明
2
+
3
+ > 本文描述当前仓库中 `android/` 原生客户端已经实现的功能、交互方式、数据安全设计、协议依赖和已知边界。
4
+
5
+ ## 1. 定位和架构
6
+
7
+ Android App 是 Remote Pi Server 的原生客户端,不在手机上运行 Agent,也不直接访问开发主机文件系统。Agent、模型调用、工具执行和 Pi session 都运行并保存在 Remote Pi Server 所在机器。
8
+
9
+ ```text
10
+ Android App
11
+ ├── HTTP/JSON:认证、Workspace、文件、Agent、Session 和设置
12
+ ├── WebSocket:流式事件、断线恢复和任务完成监听
13
+ └── Android Notification:Agent 完成提醒
14
+ │
15
+ ▼
16
+ Remote Pi Server → Pi SDK → LLM / 本地工具 / Session 文件
17
+ ```
18
+
19
+ 最低系统版本为 Android 8.0(API 26)。Debug 构建允许 HTTP,Release 构建只接受 HTTPS,WebSocket 由 OkHttp 自动升级为 WS/WSS。
20
+
21
+ ## 2. Server 管理和认证
22
+
23
+ - 可以保存多个 Remote Pi Server。
24
+ - Server 配置包括显示名称、Base URL 和 Access Token。
25
+ - 登录时调用认证接口并读取 `/api/v1/system/status`。
26
+ - App 只接受 protocol version 1,不兼容时显示明确错误。
27
+ - 支持编辑、删除和切换 Server。
28
+ - Android 13 及以上首次启动会请求通知权限。
29
+
30
+ Access Token 不保存在普通 Profile 中。App 使用 Android Keystore 中不可导出的 AES 密钥,以 AES-GCM 加密 Token 后保存到独立 SharedPreferences;该文件排除于 Android Backup。Token 不写入 URL 和应用日志。
31
+
32
+ ## 3. Workspace 和文件浏览
33
+
34
+ 主页可以:
35
+
36
+ - 添加 Workspace,填写 Remote 主机上的名称和绝对路径。
37
+ - 查看 Workspace 列表和根路径。
38
+ - 进入任意 Workspace 浏览目录。
39
+ - 返回上级目录。
40
+ - 分页读取文本文件,避免一次载入大文件。
41
+ - 对二进制文件显示不可预览提示。
42
+ - 从 Workspace 根目录或当前浏览目录创建 Agent。
43
+
44
+ 所有路径安全校验由 Server 执行,包括路径穿越和符号链接逃逸检查。
45
+
46
+ ## 4. Agent 管理
47
+
48
+ 主页显示当前 Server 上的 Agent:
49
+
50
+ - Session 有名称时优先显示名称,否则显示 Agent ID。
51
+ - 显示 Agent ID、运行状态和 cwd。
52
+ - 支持创建、打开和停止 Agent。
53
+ - 创建时可选择 Workspace、cwd、新 Session 或已有 Session。
54
+ - 多 Workspace 场景会先显示 Workspace 选择器。
55
+
56
+ Agent 状态包括 idle、streaming、error 和 stopped 等。
57
+
58
+ ## 5. Session 功能
59
+
60
+ 当前支持:
61
+
62
+ - 创建新 Session。
63
+ - 列出并恢复 cwd 对应的历史 Session。
64
+ - 给 Session 命名。
65
+ - 随时修改 Session 名称。
66
+ - Session 名称持久化到 Pi session,并显示在对话标题和 Agent 列表。
67
+ - 查看 Session tree 条目。
68
+ - Navigate 到指定 tree entry。
69
+ - Fork / Revert。
70
+ - Compact。
71
+
72
+ ### Revert 行为
73
+
74
+ 对话页工具栏的 Undo 按钮对应 Pi CLI 双击 Escape 在 `doubleEscapeAction=fork` 时打开的用户消息选择器:
75
+
76
+ 1. App 显示当前 Session 中的历史用户消息,最近消息在前。
77
+ 2. 选择一条消息后,Server 从该用户消息之前的父节点创建新 Session。
78
+ 3. 原 Session 不被修改。
79
+ 4. 新 Agent 打开 fork 后的 Session。
80
+ 5. 被选择的用户消息自动放回输入框,用户可以修改后重新发送。
81
+
82
+ 这与普通 tree navigation 不同:Revert 会创建新的 Session 分支,不覆盖原历史。
83
+
84
+ ## 6. 对话和实时事件
85
+
86
+ 进入 Agent 后,App 先通过 HTTP 加载历史消息和 Session 状态,再通过 WebSocket 订阅实时事件。
87
+
88
+ 支持显示:
89
+
90
+ - 用户消息。
91
+ - Assistant 文本增量。
92
+ - Thinking 增量。
93
+ - Tool execution start/end。
94
+ - Tool 参数和完成状态。
95
+ - Retry 和系统状态。
96
+ - Extension notify/status/widget/title。
97
+
98
+ 支持发送:
99
+
100
+ - prompt。
101
+ - steer。
102
+ - follow-up。
103
+ - abort。
104
+
105
+ 长时间 prompt 使用不设置 read timeout 的独立 OkHttp Client,避免 Agent 正常运行超过 30 秒时出现错误弹窗。普通 API 仍保留网络超时。
106
+
107
+ ### 折叠卡片
108
+
109
+ 对话中的每个消息或事件块默认折叠:
110
+
111
+ - Tool 折叠后显示工具/操作名称。
112
+ - Thinking 折叠后显示 `Thinking`。
113
+ - 系统事件显示标题或第一行。
114
+ - 用户和 Assistant 消息显示前 60 个字符。
115
+ - 点击卡片可展开完整内容,再次点击折叠。
116
+ - 展开状态通过 Compose saveable state 保留,屏幕旋转时不会立即丢失。
117
+
118
+ ## 7. `@` 文件和目录引用
119
+
120
+ 在输入框输入 `@` 会在输入框上方打开路径选择器:
121
+
122
+ - 初始位置是 Agent cwd。
123
+ - 显示当前目录中的文件和子目录。
124
+ - 点击目录进入目录。
125
+ - 可以引用当前目录或子目录。
126
+ - 点击文件直接插入引用。
127
+ - 可以返回上级目录,最高到 Workspace 根目录。
128
+ - 可以随时取消。
129
+ - cwd 内目标生成相对路径。
130
+ - cwd 外但 Workspace 内目标生成绝对路径。
131
+ - 含空格的路径自动加双引号。
132
+
133
+ 例如:
134
+
135
+ ```text
136
+ @src/Main.kt
137
+ @"docs/design notes.md"
138
+ @/repo/shared/config.json
139
+ ```
140
+
141
+ ## 8. WebSocket 恢复
142
+
143
+ 每个 Agent 事件包含 eventId、递增 sequence 和 Unix 秒级 timestamp。
144
+
145
+ 客户端会:
146
+
147
+ - 持久化每个 Agent 的最后 sequence。
148
+ - 丢弃重复 sequence。
149
+ - 检测 sequence gap。
150
+ - 按 1、2、4、8、15、30 秒指数退避重连。
151
+ - 缓存仍存在时请求增量 replay。
152
+ - 缓存不足时接收 `agent_snapshot`,恢复完整 state/messages。
153
+ - snapshot 不可用时重新请求 HTTP messages。
154
+
155
+ 切换 Agent 会关闭旧对话订阅,避免不同 Agent 的事件混入。
156
+
157
+ ## 9. 完成通知
158
+
159
+ App 为当前连接的 Server 维护一个独立、多 Agent WebSocket 连接。即使用户正在查看另一个 Agent,也会订阅该 Server 上所有已知 Agent 的完成事件。
160
+
161
+ 当 Agent 发出 `agent_end` 并转为空闲状态时:
162
+
163
+ - Android 创建“Agent 完成”系统通知。
164
+ - 通知标题使用 Session 标识。
165
+ - Server 事件携带 Unix 秒级时间戳。
166
+ - Android 使用设备当前时区转换成本地时间。
167
+ - 通知同时显示本地时间和原始 Unix 时间戳。
168
+ - 通知 `when` 使用事件真实发生时间,而不是手机收到通知的时间。
169
+ - 每个 Agent 保存独立通知 sequence,重连时补收事件并避免重复通知。
170
+ - 首次订阅使用 `fromNow`,不会把缓存中的旧完成事件全部重新通知。
171
+
172
+ 示例:
173
+
174
+ ```text
175
+ Session 已转为空闲状态
176
+ 本地时间:2026-07-18 22:20:00 CST
177
+ Unix 时间戳:1784370000
178
+ ```
179
+
180
+ 当前通知依赖 App 进程中的 WebSocket。App 退到后台后,系统通常仍可在一段时间内保持连接;如果进程被系统彻底终止,则无法保证实时通知。需要进程被杀后仍可靠送达时,应按计划增加 Server 设备注册接口和 FCM/UnifiedPush,而不是依赖永久后台 WebSocket。
181
+
182
+ ## 10. Extension UI
183
+
184
+ Pi Extension UI 请求可映射为 Compose 组件:
185
+
186
+ - select:选择对话框。
187
+ - confirm:确认对话框。
188
+ - input:单行输入。
189
+ - editor:多行输入。
190
+ - notify:对话系统事件。
191
+ - setStatus:页面状态。
192
+ - setWidget:对话顶部 Widget。
193
+ - setTitle:页面标题。
194
+ - extension response:把用户结果返回 Server。
195
+
196
+ 自定义 TUI Component 无法直接在 Android 渲染,Server 会返回不支持错误。
197
+
198
+ ## 11. Model 和 Thinking
199
+
200
+ Agent 控制对话框支持:
201
+
202
+ - 查询当前模型。
203
+ - 查看当前 Provider 可用模型。
204
+ - 切换模型。
205
+ - 查询当前 thinking level。
206
+ - 查看模型支持的 thinking levels。
207
+ - 修改 thinking level。
208
+
209
+ 模型凭据仍由 Server 复用 Pi CLI 配置,Android 不存储 Provider API Key。
210
+
211
+ ## 12. 本地数据
212
+
213
+ 当前本地持久化内容:
214
+
215
+ - Server Profile 非敏感信息。
216
+ - Keystore 加密后的 Token。
217
+ - 当前选择的 Server。
218
+ - 对话 WebSocket sequence cursor。
219
+ - 通知 WebSocket sequence cursor。
220
+
221
+ 完整消息和 Session 不复制到 Android 数据库;Server/Pi session 文件是唯一事实来源。
222
+
223
+ ## 13. 测试和构建
224
+
225
+ Server:
226
+
227
+ ```bash
228
+ npm run check
229
+ npm test
230
+ ```
231
+
232
+ Android:
233
+
234
+ ```bash
235
+ cd android
236
+ ./gradlew testDebugUnitTest assembleDebug assembleRelease
237
+ ```
238
+
239
+ 测试覆盖认证和协议解析、Workspace、安全路径、Agent 生命周期、Session 命名、fork/revert 管理、事件 sequence、snapshot、fromNow、Unix 时间转换、`@` 路径计算、折叠标题、长任务超时策略及 HTTP 错误映射。
240
+
241
+ 构建产物:
242
+
243
+ ```text
244
+ android/app/build/outputs/apk/debug/app-debug.apk
245
+ android/app/build/outputs/apk/release/app-release-unsigned.apk
246
+ ```
247
+
248
+ ## 14. 当前边界
249
+
250
+ - 单机、单用户和单 Access Token。
251
+ - Release 默认要求 HTTPS/WSS。
252
+ - 文件 API 只读;Agent 本身仍可通过 Pi 工具修改文件。
253
+ - 没有内置终端模拟器。
254
+ - 没有 FCM,因此进程被系统杀死后不保证通知。
255
+ - 没有多用户 RBAC。
256
+ - 没有把 Pi 自定义 TUI Component 自动转换成 Compose 的通用方案。
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 sxwxs
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,194 @@
1
+ # Remote Pi
2
+
3
+ Remote Pi 在开发机上运行 Pi Agent,并通过受 Bearer 配对码保护的 HTTP/WebSocket API 提供 Web UI 和 Android 原生客户端。默认只监听 `127.0.0.1`。
4
+
5
+ ## 作为 npm 全局命令安装
6
+
7
+ 要求 Node.js 20.10 或更高版本:
8
+
9
+ ```bash
10
+ npm install -g pi2web
11
+ pi2web
12
+ ```
13
+
14
+ npm 包名为 `pi2web`,全局命令同名(`pi2web`)。安装时会准备 `better-sqlite3` 和 `node-pty` 两个原生模块:多数平台直接使用预编译产物,没有预编译产物的平台需要本机具备 Python 3 与 C/C++ 工具链(Linux `build-essential`、macOS Xcode Command Line Tools、Windows Visual Studio Build Tools)。
15
+
16
+ 启动后访问终端显示的地址(默认 <http://127.0.0.1:11318>)。服务首次启动只在终端显示一次配对码;Web UI **必须由用户手动输入配对码**,不会从 URL 或服务端自动注入。连接成功后页面会询问是否保存到 localStorage;只有用户明确确认后才会保存,请仅在可信设备上使用。
17
+
18
+ 常用选项:
19
+
20
+ ```bash
21
+ pi2web --host 127.0.0.1 --port 11318
22
+ pi2web --data-dir ~/.pi/remote-pi
23
+ pi2web --rotate-access-token # 旧配对码立即失效,输出新配对码
24
+ pi2web --help
25
+ ```
26
+
27
+ 服务器会同时提供 API、WebSocket 和 Web UI,无需另起静态文件服务器。请勿直接暴露到公网;远程访问建议使用 SSH tunnel、Tailscale、devtunnel 或配置 HTTPS 的可信反向代理。
28
+
29
+ 配对失败有速率限制:同一来源地址在 60 秒窗口内累计 10 次失败后会被锁定,锁定时间从 60 秒起按次翻倍,最长 15 分钟,HTTP 返回 `429` 与 `Retry-After`,WebSocket 升级同样受限;一次成功配对立即清除该地址的计数。注意限流按 TCP 来源地址统计,通过 devtunnel、Cloudflare Tunnel 或反向代理访问时所有客户端共用同一个计数桶。Remote Pi 不校验 `Origin` / `Host`,因此可以直接配合内网穿透使用。
30
+
31
+ ## Agent 完成邮件通知(MailDispatch)
32
+
33
+ 如果启动时同时配置 MailDispatch 消息 API endpoint、API key 环境变量和通知邮箱,Pi 发出 `agent_settled`(不会再自动重试、自动 compact 或执行排队的 follow-up)后,Remote Pi 可以提交事务邮件。MailDispatch 返回 `202` 后邮件进入其持久队列;实际投递由 MailDispatch worker 完成。
34
+
35
+ ```bash
36
+ export REMOTE_PI_MAILDISPATCH_KEY='md_live_...'
37
+ pi2web \
38
+ --maildispatch-endpoint https://mail.example.com/api/v1/messages \
39
+ --maildispatch-api-key-env REMOTE_PI_MAILDISPATCH_KEY \
40
+ --maildispatch-notify-to owner@example.com \
41
+ --maildispatch-sender-id system
42
+ ```
43
+
44
+ 前三个选项必须同时提供,否则 Remote Pi 会拒绝启动。`--maildispatch-sender-id` 可选;省略时由 MailDispatch 按 API key 和服务配置选择 sender。API key 只从指定环境变量读取,避免出现在命令行参数和进程列表中,并且至少需要 MailDispatch 的 `mail:send` scope。邮件通知失败只写入 Remote Pi 标准错误,不会改变 Agent 任务状态。
45
+
46
+ 导航栏的“配置”窗口可以启用或关闭邮件通知,并设置:
47
+
48
+ - 聚合等待时间:首个任务完成后等待指定秒数,期间完成的其他任务合并到同一封邮件;`0` 表示立即发送。
49
+ - 是否包含 Agent 最终回复。
50
+ - 是否包含 Session 名称和工作路径。
51
+
52
+ 如果后两项都关闭,邮件正文只说明一个或多个 Agent 任务已经完成。邮件设置保存在 Remote Pi 的 SQLite 元数据数据库中,对所有浏览器客户端和 Agent 生效,服务重启后继续保留。
53
+
54
+ ## 本地语音摘要与语音输入(实验性)
55
+
56
+ Windows 下的 Speaches 中文语音服务器启动、模型下载和故障排查见 [`VOICE_SERVER_SETUP.md`](VOICE_SERVER_SETUP.md)。只需要在线 TTS 时,也可以使用 [`packages/edge-tts-server`](packages/edge-tts-server/README.md) 中的原生 Python 服务,不需要 Docker。
57
+
58
+ Remote Pi 可以连接两个 OpenAI-compatible 服务:一个 LLM endpoint 把 Agent 最终输出压缩成适合朗读的短摘要,一个语音 endpoint 负责 TTS,并可选提供 STT。语音默认关闭,只有配置 `--voice-base-url` 才会启用;`--voice-stt-model` 是可选项。
59
+
60
+ ```bash
61
+ # 示例模型 ID 需要替换为 Speaches 中实际下载的模型
62
+ export SUMMARY_API_KEY=...
63
+ pi2web \
64
+ --voice-base-url http://127.0.0.1:8000/v1 \
65
+ --voice-stt-model <stt-model-id> \
66
+ --voice-tts-model <tts-model-id> \
67
+ --voice-tts-voice <voice-id> \
68
+ --voice-summary-base-url https://llm.example.com/v1 \
69
+ --voice-summary-model <summary-model-id> \
70
+ --voice-summary-api-key-env SUMMARY_API_KEY \
71
+ --voice-language zh-CN
72
+ ```
73
+
74
+ 工作方式:
75
+
76
+ - Pi 发出 `agent_settled` 后,Remote Pi 取得最后一条 Assistant 文本,移除代码块、长链接和 Markdown,再限制摘要输入长度。
77
+ - 摘要 LLM 使用流式 Chat Completions;Remote Pi 在完整句子出现后立即调用流式 TTS,因此无需等待整段摘要完成。
78
+ - Web UI 中点击“启用语音”后,会播放服务端推送的 PCM16 或 MP3 音频;新的 Agent 运行会取消该 Agent 尚未完成的播报。
79
+ - 多个 Session 接近同时完成时,语音摘要会进入全局队列依次播放,不会重叠;有 Session 名称时以“会话{name}已完成:”开头。
80
+ - 只有配置 `--voice-stt-model` 时,Web UI 才显示麦克风按钮;识别文字只插入输入框,不会自动发送。
81
+ - API key 通过 `--voice-api-key-env` 和 `--voice-summary-api-key-env` 指定环境变量名,避免把密钥放入命令行参数。
82
+
83
+ 语音流目前通过已认证的 Agent WebSocket 发送,只会实时投递,不写入 Session 或事件 replay。浏览器麦克风通常要求 HTTPS 安全上下文(`localhost` 例外)。Android 客户端的流式 PCM 播放和录音 UI 尚未接入。
84
+
85
+ ### Edge TTS(仅语音合成)
86
+
87
+ 项目提供了一个基于 Python `edge-tts` 和 `aiohttp` 的轻量本地服务。它直接返回 MP3,不需要 Docker 或 FFmpeg:
88
+
89
+ ```bash
90
+ cd packages/edge-tts-server
91
+ python -m venv .venv
92
+ # Windows: .venv\\Scripts\\Activate.ps1
93
+ # Linux/macOS: source .venv/bin/activate
94
+ python -m pip install -e .
95
+ remote-pi-edge-tts
96
+
97
+ pi2web \
98
+ --voice-base-url http://127.0.0.1:5050/v1 \
99
+ --voice-tts-model edge-tts \
100
+ --voice-tts-voice zh-CN-XiaoxiaoNeural \
101
+ --voice-tts-format mp3 \
102
+ --voice-summary-base-url https://llm.example.com/v1 \
103
+ --voice-summary-model <summary-model-id> \
104
+ --voice-summary-api-key-env SUMMARY_API_KEY
105
+ ```
106
+
107
+ 语音摘要、语音合成和语音识别的每次请求都有超时保护,默认 120000 毫秒,可用 `--voice-request-timeout <ms>` 调整;超时后播报会降级为文本提示,不会阻塞后续 Agent 的播报队列。
108
+
109
+ 该模式不配置 `--voice-stt-model`,因此只启用 Agent 摘要播报,不启用语音识别。Edge TTS 使用非官方消费者服务,适合本地和实验性使用。
110
+
111
+ ## 本地开发
112
+
113
+ 项目 Review 中发现的问题、修复状态和暂缓的 Android 项目见 [`PROJECT_REVIEW_ISSUES.md`](https://github.com/sxwxs/pi2web/blob/main/PROJECT_REVIEW_ISSUES.md)。
114
+
115
+ ```bash
116
+ npm install
117
+ npm run check
118
+ npm test
119
+ npm run dev -- --port 11318
120
+ ```
121
+
122
+ ## 数据持久化
123
+
124
+ Remote Pi 的服务端元数据保存在 `~/.pi/remote-pi/remote-pi.db` SQLite 数据库中:
125
+
126
+ - `workspaces`:Workspace ID、名称、根目录和创建时间。
127
+ - `agents`:Agent 与 Workspace/Session 的映射、cwd、状态、创建/最后活动时间以及 Archive 状态。
128
+ - `sessions`:用于 Session 列表、排序和分页的轻量索引,包括名称、文件路径、消息数量、文件 mtime/size 和最后活动时间。
129
+ - `auth.json`:配对码的 SHA-256 hash、创建和轮换时间;认证数据仍单独保存,不保存配对码明文,文件权限为 `0600`。
130
+
131
+ 数据库使用 WAL、短事务、部分索引和批量延迟更新。Session 活动时间不会随每个 streaming token 写入,而是在完整消息、Agent 完成和 Session 信息变化时合并持久化。旧版 `workspaces.json`、`agents.json` 和 `agents_archive.json` 不会被读取、迁移或继续写入。
132
+
133
+ Terminal 只保存在服务进程内存中,不写入数据库。刷新浏览器可以重新连接仍在运行的 Terminal;Remote Pi 服务退出或重启时会终止全部 Terminal。
134
+
135
+ 完整对话由 Pi 的 `SessionManager` 以 JSONL 管理,默认位于 `~/.pi/agent/sessions/<编码后的-cwd>/`,其中包含会话消息、分支、模型及 thinking level 等 Session 条目。SQLite 只保存可重建的 Session 索引,不复制完整消息。模型配置、Provider 认证和 Pi 设置也继续复用 `~/.pi/agent`。浏览器选择的服务地址、Workspace/Agent 和事件游标另存在浏览器 `localStorage`;配对码仅在用户明确同意后才会存入其中。
136
+
137
+ Remote Pi 启动时从 SQLite 恢复 Agent 元数据,恢复后的 Agent 状态为 `unloaded`,不会创建 Pi `AgentSession` 或初始化扩展。读取该 Agent 的消息、Session、能力,或者向其发送命令时才按需启动;并发请求共享同一次启动。“停止 Agent”只释放运行中的 Session 并保留 Agent 元数据,再次使用时会按需启动。
138
+
139
+ Web UI 的 Agent 列表支持右键 `Archive`。Archive 只设置数据库记录的 `archived_at`,不会移动、重命名或删除 Pi 的任何 Session 文件;归档记录不会在当前 UI 中显示。
140
+
141
+ 发布包可本地检查:
142
+
143
+ ```bash
144
+ npm pack --dry-run
145
+ npm install -g ./pi2web-0.2.0.tgz
146
+ ```
147
+
148
+ ## Web UI
149
+
150
+ Web 端覆盖 Android 客户端的主要浏览器可实现能力:
151
+
152
+ - Workspace 添加、目录浏览、文本文件分页及二进制提示。
153
+ - Workspace 目录右键在交互式 Terminal 中打开;Terminal 与 Agent 显示在同一列表,支持刷新重连、清屏和关闭。
154
+ - 创建/恢复 Session、Agent 列表、停止与 abort;Agent 右键 Archive。
155
+ - Prompt、steer、follow-up 和流式对话。
156
+ - 折叠消息、Thinking、Tool、Retry 和 Extension UI 事件。
157
+ - Session 命名、Tree Navigate、Undo/Fork、Compact。
158
+ - 模型和 Thinking level 切换。
159
+ - 输入 `@` 浏览并引用 Workspace 文件或目录。
160
+ - WebSocket sequence 去重、断线指数退避、增量 replay/snapshot 恢复。
161
+ - 浏览器允许通知时,对所有已知 Agent 提供完成通知。
162
+
163
+ Terminal 是以 Remote Pi 进程用户身份运行的完整宿主机 Shell。Workspace 路径只决定初始 cwd,并不是安全沙箱;Shell 可以访问 Workspace 之外的文件及继承到的环境变量。获得配对码的人实际上也获得了该用户的 Shell 权限,请勿将服务直接暴露到不可信网络。每个服务进程最多同时运行 8 个 Terminal,每个 Terminal 只保留最近 512 KiB 输出用于浏览器重连。
164
+
165
+ 浏览器安全模型与 Android 不同:配对码默认仅保存在当前页面的 JS 内存中;连接成功后会询问是否保存,只有用户确认才写入 localStorage。服务地址、当前 Workspace/Agent 和事件 sequence cursor 会保存在 localStorage。浏览器通知要求 HTTPS 安全上下文(`localhost` 可使用 HTTP);通过局域网 IP 的 HTTP 地址访问时无法启用。自定义 Pi TUI Component 无法在浏览器通用渲染。
166
+
167
+ ## API
168
+
169
+ 除 Web 静态资源、`/health` 和 `/api/v1/auth/login` 外,请求均需 `Authorization: Bearer <token>`。响应为 `{ data }` 或 `{ error: { code, message, requestId } }`。
170
+
171
+ - `GET /health`
172
+ - `POST /api/v1/auth/login`
173
+ - `GET /api/v1/system/status`
174
+ - `GET/POST /api/v1/mail-notifications`
175
+ - `GET/POST /api/v1/workspaces`
176
+ - `GET /api/v1/workspaces/:id/tree|file|stat`
177
+ - `GET /api/v1/sessions`
178
+ - `GET/POST /api/v1/agents`
179
+ - `GET/DELETE /api/v1/agents/:id`
180
+ - `GET/POST /api/v1/terminals`
181
+ - `GET/DELETE /api/v1/terminals/:id`
182
+ - Terminal WebSocket `/api/v1/terminals/:id/ws` 支持输入、窗口 resize、输出快照和退出事件。
183
+ - Agent 的 `state`、`messages`、`capabilities`、`session`、`prompt`、`steer`、`follow-up`、`abort`、`compact`、`model`、`thinking`、`session-name`、`navigate`、`fork`、`archive` 和 `extension-response` 接口。
184
+ - WebSocket `/api/v1/ws` 支持 sequence、replay、snapshot、`fromNow` 和 Agent command。
185
+
186
+ ## Android App
187
+
188
+ `android/` 是 Kotlin + Jetpack Compose 原生客户端。构建和连接说明见 [`android/README.md`](https://github.com/sxwxs/pi2web/blob/main/android/README.md),完整功能见 [`ANDROID_APP_FEATURES.md`](ANDROID_APP_FEATURES.md)。
189
+
190
+ 运行时使用真实 `@earendil-works/pi-coding-agent` SDK,并复用 Pi CLI 的 `~/.pi/agent` 模型、认证和设置。`MockBackend` 只用于自动化测试。
191
+
192
+ ## License
193
+
194
+ MIT © sxwxs。完整条款见 [`LICENSE`](LICENSE)。