pi-web-console

把 Pi CLI(pi.dev)的全部能力通过 Web UI 暴露出来 —— 后端为每个会话孵化 pi --mode rpc 子进程做 JSONL 双向桥接,Web 前端经 WebSocket 与之对话,原生复用 Pi 全部能力。

Packages

Package details

extension

Install pi-web-console from npm and Pi will load the resources declared by the package manifest.

$ pi install npm:pi-web-console
Package
pi-web-console
Version
1.0.0
Published
Aug 18, 2026
Downloads
150/mo · 150/wk
Author
applesun
License
MIT
Types
extension
Size
316.2 KB
Dependencies
3 dependencies · 1 peer
Pi manifest JSON
{
  "extensions": [
    "./extensions"
  ]
}

Security note

Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.

README

Pi Web Console

Pi(一个极简、可扩展的终端编码 Agent)的全部能力通过 Web UI 暴露出来。架构与 Pi 官方集成规范一致:后端为每个会话孵化一个 pi --mode rpc 子进程,在 stdin/stdout 上做 JSONL 双向桥接,Web 前端经 WebSocket 与后端对话,从而原生复用 Pi 的全部能力,而不是重造一个 Agent。

Pi 官方明确 RPC 模式(--mode rpc,stdin/stdout JSONL)是"把 Pi 嵌入 IDE / 外部 UI"的首选机制。本项目即是该机制在 Web 端的完整实现。


特性

  • 原生复用 Pi 全部能力prompt / steer / follow_up / abort / bash / set_model / set_thinking_level / compact / fork / clone / switch_session / export_html / get_tree / get_session_stats … 全部 RPC 命令均可用。
  • 流式渲染:文本增量(text_delta)、思考过程(thinking_delta)、工具调用(tool_execution_*)实时呈现,支持 Markdown。
  • 扩展 UI 子协议:正确处理 select / confirm / input / editor(弹窗回填 extension_ui_response)以及 notify / setStatus / setWidget / setTitle
  • 会话管理:新建 / 销毁 / 切换到磁盘上的历史会话(与 CLI 共享 ~/.pi/agent/sessions),树形分支、分叉、克隆、导出 HTML。
  • 模型与思考等级get_available_models / get_available_thinking_levels 驱动下拉框,set_model / set_thinking_level 即时切换。
  • 用量统计:Token 用量、成本、上下文占用(get_session_stats)。
  • 一次性模式pi --mode json(print/JSON 事件流)做快速提问,不占用会话。
  • 无密钥演示:内置 test/mock-pi.js 模拟 pi 子进程,可端到端跑通整个链路。

架构

┌────────────┐   WebSocket (JSON)   ┌──────────────────────────────┐
│  浏览器前端  │ ◄────────────────────► │  Node 后端 (express + ws)   │
│  index.html │                      │  ┌────────────────────────┐ │
│  app.js     │                      │  │  SessionManager        │ │
└────────────┘                      │  │   ┌──────────────────┐ │ │
                                     │  │   │ PiRpcSession #1  │ │ │
        REST (健康检查 / 会话列表)      │  │   │  spawn pi        │ │ │
┌────────────┐                      │  │   │  --mode rpc      │ │ │
│ GET /api/*  │ ◄────────────────────┤  │   └────────┬─────────┘ │ │
└────────────┘                      │  └────────────┼───────────┘ │
                                     └───────────────┼─────────────┘
                                        stdin 命令 / stdout 事件+响应
                                                     │
                                        ┌────────────▼─────────────┐
                                        │   pi --mode rpc          │
                                        │   (JSONL over stdio)     │
                                        └──────────────────────────┘
  • 一个会话 = 一个 pi --mode rpc 子进程。会话生命周期与子进程绑定,父进程退出即自然终止。
  • 后端只做透明转发 + 请求/响应 id 关联,不解析、不改造 Agent 语义——前端直接发 Pi RPC 命令对象。
  • 严格 JSONL 帧解析:仅以 \n 切分记录、剥离尾部 \r,不使用会把 U+2028/2029 当换行的通用行读取器(如 Node readline)。

WebSocket 协议(后端 ↔ 前端)

客户端 → 服务端

type 字段 说明
session.create payload: { cwd?, name?, env? } 创建会话(spawn pi)
session.destroy runtimeId 销毁会话(kill 子进程)
session.list 列出活跃 + 磁盘会话
session.deleteDisk sessionFile 删除磁盘上的历史会话文件(.jsonl,路径受限 + 活跃占用保护)
command runtimeId, command, clientId? 转发 Pi RPC 命令
ui.response runtimeId, response 回填 extension_ui_response
oneshot payload: { prompt, cwd?, model?, provider? } pi --mode json 一次性调用

服务端 → 客户端

type 字段 说明
hello pi pi 可用性 / 版本
session.created / session.destroyed / session.exited / session.list 会话生命周期与列表
session.diskDeleted sessionFile, removed 磁盘历史会话已删除(全端广播刷新)
command.ack id, clientId 命令已写出的实际 id
response runtimeId, response Pi 命令应答
event runtimeId, event Pi Agent 事件流(原始透传)
ui.request runtimeId, request 扩展 UI 请求
stderr runtimeId, text pi 子进程 stderr
oneshot.event / oneshot.done 一次性调用事件流

快速开始

前置:Node ≥ 18,且已安装 Pi(npm install -g --ignore-scripts @earendil-works/pi-coding-agentcurl -fsSL https://pi.dev/install.sh | sh)。

cd pi-web-console
npm install
npm start

打开 http://127.0.0.1:4120 即可。点「+ 新会话」,输入消息回车发送;运行中回车即 Steer,或用 Follow-up / 中止 按钮。

无 API 密钥演示(mock pi)

npm run demo

此时后端用 node test/mock-pi.js 模拟 pi 子进程,可完整体验聊天、工具卡、统计、树、分叉等交互,无需任何模型密钥。

作为 Pi 插件安装(pi install

本项目内置了一个真正的 Pi Extension(extensions/web-console.ts),通过标准的包管理方式分发,无需单独 git clone

pi install npm:pi-web-console        # 安装到 ~/.pi/agent/
# 或项目内安装(团队共享,随 pi 启动自动安装缺失包):
pi install -l npm:pi-web-console

安装后在任意 pi 会话中输入:

/web-console

即会以子进程方式拉起 server/index.js(默认 http://127.0.0.1:4120),并尝试自动打开浏览器;工作目录、会话自动继承当前 pi 会话的 cwd

  • /web-console 8080 — 指定端口启动
  • /web-console stop — 停止
  • 会话退出 / /reload 时会自动清理子进程

配置(.env

复制 .env.example.env,按需修改。关键项:

变量 默认 说明
HOST / PORT 127.0.0.1 / 4120 监听地址/端口。默认仅本机
PI_BIN pi pi 可执行文件,可带参数(如 node test/mock-pi.js
PI_SESSION_DIR ~/.pi/agent/sessions 会话目录(默认与 CLI 共享)
DEFAULT_CWD 启动目录 新会话默认工作目录
ALLOWED_CWDS 白名单工作目录(安全)
PI_APPROVE false 是否 --approve 信任项目本地文件
PI_EXTRA_ARGS 透传给 pi 的额外参数(逗号分隔)
AUTH_TOKEN 设置后 REST/WS 需携带 token
MAX_SESSIONS 20 最大同时会话数

安全须知(重要)

⚠️ 本应用让浏览器驱动 pi,而 pi 可在机器上执行 bash 等工具。默认只绑定 127.0.0.1不要在没有鉴权与可信网络的前提下暴露到公网。

  • 保持 HOST=127.0.0.1;确需远程访问时务必设置 AUTH_TOKEN 并走 HTTPS 反向代理。
  • ALLOWED_CWDS 把会话限制在指定项目目录。
  • 需要权限门禁/沙箱时,可结合 Pi 扩展(permission-gate、sandbox、protected-paths)或把 pi 跑进容器(见 Pi 官方 Containerization 文档)。

项目结构

pi-web-console/
├── server/
│   ├── index.js             # HTTP + WebSocket 服务入口、REST、鉴权
│   ├── config.js            # 环境配置
│   ├── jsonl.js             # 严格 JSONL 读取器(仅 \n 切分)
│   ├── pi-rpc-session.js    # PiRpcSession:spawn pi --mode rpc 并桥接
│   ├── session-manager.js   # 会话管理 + 磁盘会话枚举
│   ├── one-shot.js          # pi --mode json 一次性调用
│   └── check-pi.js          # pi 可用性探测
├── public/
│   ├── index.html
│   ├── css/style.css
│   └── js/ (app.js, ws.js, markdown.js)
└── test/
    ├── mock-pi.js           # 模拟 pi(无密钥演示/测试)
    └── smoke.mjs            # 后端桥接冒烟测试

测试

npm run smoke   # 用 mock pi 验证 JSONL 桥接(事件流 + 响应关联)

参考