chore: localize README to Chinese, improve npx compatibility, and bump version to 0.5.13

- Translate README.md from English to Chinese
- Add npx quick-start instructions to README
- Resolve next CLI entry directly to avoid .bin symlink issues when running via npx
- Spawn next with node directly instead of relying on shell or .bin wrappers
- Gracefully handle missing @mariozechner/pi-coding-agent package in next.config.ts
This commit is contained in:
Alex Yang committed 2026-04-19 20:57:47 +08:00
1 parent 67b18d87b6
commit a0bcba9077
5 files changed
+73 -47

No files matched your search

+47 -39
View File
@@ -1,67 +1,75 @@
# pi-web
A web interface for the [pi coding agent](https://github.com/badlogic/pi-mono). Browse sessions, chat with the agent, fork conversations, and navigate message branches — all in the browser.
[pi 编程智能体](https://github.com/badlogic/pi-mono) 的网页界面。在浏览器中浏览会话、与智能体对话、分叉对话、切换消息分支。
## Installation
## 快速开始
**无需安装,直接运行:**
```bash
npx @agegr/pi-web@latest
```
**或全局安装后使用:**
```bash
npm install -g @agegr/pi-web
pi-web
```
Open [http://localhost:30141](http://localhost:30141).
启动后打开 [http://localhost:30141](http://localhost:30141)。
Options:
**可选参数:**
```bash
pi-web --port 8080 # custom port
pi-web --hostname 127.0.0.1 # local-only access
pi-web -p 8080 -H 127.0.0.1 # combined
pi-web --port 8080 # 自定义端口
pi-web --hostname 127.0.0.1 # 仅本机访问
pi-web -p 8080 -H 127.0.0.1 # 组合使用
PORT=8080 pi-web # env var also works
PORT=8080 pi-web # 也支持环境变量
```
## Development Setup
## 功能介绍
- **会话浏览器** — 按工作目录分组展示所有 pi 会话
- **实时对话** — 通过 SSE 流式输出与智能体实时交互
- **会话分叉** — 从任意用户消息创建独立的新会话分支
- **会话内分支** — 回退到任意节点继续对话,在同一文件内创建分支
- **分支导航器** — 可视化切换同一会话内的各个分支
- **模型切换** — 对话中途随时切换模型
- **工具面板** — 控制智能体可使用的工具
- **压缩会话** — 对长会话进行摘要,节省上下文窗口
- **引导 / 追加** — 打断正在运行的智能体,或在其完成后追加消息
## 注意事项
- **数据目录** — 默认读取 `~/.pi/agent/sessions` 下的会话文件。可通过环境变量 `PI_CODING_AGENT_DIR` 指定其他目录。
- **模型配置** — 从智能体数据目录下的 `models.json` 读取可用模型,可在侧边栏的「Models」面板中编辑。
- **文件浏览** — 侧边栏内置文件浏览器,可在标签页中查看当前工作目录下的文件。
## 开发
```bash
npm install
npm run dev
npm run dev # 端口 30141
```
## Features
- **Session browser** — lists all pi sessions grouped by working directory
- **Live chat** — sends messages to the agent with real-time streaming via SSE
- **Fork** — branch a session from any user message into a new independent session
- **In-session branching** — navigate back to any point and continue from there, creating a branch in the same session file
- **Branch navigator** — visual switcher for branch points within a session
- **Model selector** — switch models mid-session
- **Tool panel** — toggle which tools the agent can use
- **Compact** — summarize long sessions to save context window
- **Steer / Follow-up** — interrupt the agent mid-run or queue a message for after it finishes
## Notes
- **Agent data directory** — reads sessions from `~/.pi/agent/sessions` by default. Set `PI_CODING_AGENT_DIR` to use another agent directory.
- **Models** — reads available models from `models.json` in the agent directory. You can edit them from the sidebar `Models` panel.
- **Files** — the sidebar includes a file explorer for the current working directory and can open files in tabs.
## Project structure
## 项目结构
```
app/
api/
sessions/ # read/write session files
agent/ # send commands, stream events via SSE
files/ # read file contents for the in-app viewer
models/ # list available models + default model
models-config/ # read and write models.json
components/ # UI components
sessions/ # 读写会话文件
agent/ # 发送命令、SSE 事件流
files/ # 文件内容读取
models/ # 可用模型列表与默认模型
models-config/ # 读写 models.json
components/ # UI 组件
lib/
session-reader.ts # parse .jsonl session files
rpc-manager.ts # manage AgentSession lifecycle
normalize.ts # normalize toolCall field names (file vs. stream format)
session-reader.ts # 解析 .jsonl 会话文件
rpc-manager.ts # 管理 AgentSession 生命周期
normalize.ts # 规范化 toolCall 字段名
types.ts
```
Sessions are stored as `.jsonl` files at `~/.pi/agent/sessions/<encoded-cwd>/<timestamp>_<uuid>.jsonl`.
会话文件存储路径:`~/.pi/agent/sessions/<编码后的工作目录>/<时间戳>_<uuid>.jsonl`
+18 -4
View File
@@ -11,10 +11,23 @@ const fs = require("fs");
const { parseArgs } = require("util");
const pkgDir = path.join(__dirname, "..");
const isWindows = process.platform === "win32";
const nextBin = path.join(pkgDir, "node_modules", ".bin", isWindows ? "next.cmd" : "next");
const nextDir = path.join(pkgDir, ".next");
// Resolve next's CLI entry directly to avoid relying on .bin symlinks (which
// may not exist when installed via npx).
let nextBin;
try {
nextBin = require.resolve("next/dist/bin/next", { paths: [pkgDir] });
} catch {
// Fallback: locate next package root and derive the bin path manually.
try {
const nextPkg = require.resolve("next/package.json", { paths: [pkgDir] });
nextBin = path.join(path.dirname(nextPkg), "dist", "bin", "next");
} catch {
nextBin = path.join(pkgDir, "node_modules", "next", "dist", "bin", "next");
}
}
const { values: cliArgs } = parseArgs({
options: {
port: { type: "string", short: "p" },
@@ -34,11 +47,12 @@ if (!fs.existsSync(nextDir)) {
const nextArgs = ["start", "-p", port];
if (hostname) nextArgs.push("-H", hostname);
const child = spawn(nextBin, nextArgs, {
// Always run next's JS entry with node directly — avoids .bin symlink issues
// and path-with-spaces problems on Windows when shell: true is used.
const child = spawn(process.execPath, [nextBin, ...nextArgs], {
cwd: pkgDir,
stdio: "inherit",
env: { ...process.env },
shell: isWindows,
});
child.on("exit", (code) => process.exit(code ?? 0));
+5 -1
View File
@@ -3,7 +3,11 @@ import { readFileSync } from "fs";
import { join } from "path";
const { version } = JSON.parse(readFileSync(join(__dirname, "package.json"), "utf8")) as { version: string };
const { version: piVersion } = JSON.parse(readFileSync(join(__dirname, "node_modules/@mariozechner/pi-coding-agent/package.json"), "utf8")) as { version: string };
let piVersion = "unknown";
try {
const piPkgPath = require.resolve("@mariozechner/pi-coding-agent/package.json", { paths: [__dirname] });
piVersion = (JSON.parse(readFileSync(piPkgPath, "utf8")) as { version: string }).version;
} catch { /* package not found, use default */ }
const nextConfig: NextConfig = {
serverExternalPackages: ["@mariozechner/pi-coding-agent", "@mariozechner/pi-ai"],
+2 -2
View File
@@ -1,12 +1,12 @@
{
"name": "@agegr/pi-web",
"version": "0.5.9",
"version": "0.5.13",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@agegr/pi-web",
"version": "0.5.9",
"version": "0.5.13",
"dependencies": {
"@mariozechner/pi-coding-agent": "^0.67.1",
"@types/react-syntax-highlighter": "^15.5.13",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@agegr/pi-web",
"version": "0.5.9",
"version": "0.5.13",
"description": "Web UI for the pi coding agent",
"bin": {
"pi-web": "bin/pi-web.js"