pi-web-ui 0.1.1

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 xing-shuyin
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,163 @@
1
+ # pi-web-ui
2
+
3
+ A web chat interface for the [pi coding agent](https://pi.dev), built directly on
4
+ the **pi SDK** ([`@earendil-works/pi-coding-agent`](https://www.npmjs.com/package/@earendil-works/pi-coding-agent)) โ€”
5
+ no subprocess, no JSON-RPC shim. The agent runs in the server process and streams
6
+ events to the browser over WebSocket.
7
+
8
+ Inspired by [Pintra (pi-vsc)](https://github.com/bilalbentoumi/pi-vsc), which does
9
+ the same thing inside VS Code by spawning `pi --mode rpc`. This project instead
10
+ uses the SDK's `createAgentSessionRuntime` API in-process (the SDK docs recommend
11
+ this over RPC for Node.js apps), so you get type safety, direct state access, and
12
+ your existing pi auth/config/extensions โ€” nothing extra to install or configure.
13
+
14
+ ## Features
15
+
16
+ - ๐Ÿง  Full agent loop with **thinking** blocks (collapsible) and streaming text
17
+ - ๐Ÿ›  Tool execution cards with **live output streaming**, status (queued โ†’ running โ†’ done/error), and copyable arguments
18
+ - ๐Ÿ’ฌ Session **history persisted per browser** (localStorage clientId + per-client session dirs) โ€” refresh or restart and your chats come back. The conversation panel also lists the pi CLI/TUI sessions for the current folder (tagged `TUI`), so you can resume a terminal conversation from the web UI
19
+ - ๐Ÿ”„ Model & thinking-level cycling (same as pi's TUI), new chat, abort/stop
20
+ - ๐Ÿ“Ž Markdown rendering with GFM tables, syntax-highlighted code blocks and copy buttons
21
+ - ๐Ÿ“ Workspace-aware: the agent reads/edits/runs code in a configurable directory using **your** `~/.pi/agent` auth, models, skills and extensions
22
+ - ๐ŸŒ Multiple browser clients each get an isolated session (private session dir per clientId)
23
+ - ๐Ÿ–ฅ Built-in **terminal** (xterm.js + node-pty, no VS Code needed): three panes โ€” a
24
+ **command list** on the left (user-defined commands with `${pwd}` support, persisted in
25
+ the project's `.pi/commands.json`), the **terminal** in the middle, and a VSCode-style
26
+ **tab strip** on the right for multiple concurrent shells. Switch between chat and
27
+ terminal views with the toggle in the top bar.
28
+
29
+ ## Quick start
30
+
31
+ Requires Node.js โ‰ฅ 20.11 and a configured pi install (run `pi` once to log in).
32
+
33
+ ```bash
34
+ npm install
35
+ npm run dev # server on :8787, web UI on :5173 (auto-proxied)
36
+ # open http://localhost:5173
37
+ ```
38
+
39
+ Production:
40
+
41
+ ```bash
42
+ npm run build # compiles server (tsc) + frontend (vite)
43
+ npm start # serves everything on http://localhost:8787
44
+ ```
45
+
46
+ ## Configuration
47
+
48
+ | Env var | Default | Description |
49
+ | --- | --- | --- |
50
+ | `PORT` | `8787` | HTTP/WebSocket port |
51
+ | `PI_WEB_CWD` | server's cwd | The workspace directory the agent operates in (read/edit/bash/write) |
52
+ | `PI_WEB_DATA_DIR` | `<cwd>/.pi-web` | Where per-client session dirs are stored |
53
+ | `PI_WEB_INLINE_FILE_MAX` | `12288` (12KB) | Text attachments at or below this size are inlined into the model context; larger files are passed as path references and the model reads them on demand (saves tokens for small edits) |
54
+ | `PI_CODING_AGENT_DIR` | `~/.pi/agent` | pi config dir (auth.json, models.json, skills, extensions) |
55
+
56
+ Example โ€” point the agent at a project:
57
+
58
+ ```bash
59
+ PI_WEB_CWD=/path/to/your/project npm run dev
60
+ ```
61
+
62
+ ## Architecture
63
+
64
+ ```text
65
+ Browser (React + Vite)
66
+ โ”‚ WebSocket JSON โ€” snapshot-driven protocol (server/protocol.ts)
67
+ โ–ผ
68
+ server/index.ts express static + ws endpoint
69
+ โ”‚
70
+ server/agent-service.ts per-client ClientSession:
71
+ โ”‚ createAgentSessionRuntime({ sessionManager: SessionManager.continueRecent(cwd, sessionDir) })
72
+ โ”‚ session.subscribe(events) โ†’ throttled full-state snapshots + live tool deltas
73
+ โ–ผ
74
+ @earendil-works/pi-coding-agent (SDK, in-process)
75
+ โ”‚ ModelRuntime (auth from ~/.pi/agent) ยท tools ยท extensions ยท skills
76
+ โ–ผ
77
+ your LLM provider
78
+ ```
79
+
80
+ Key design points:
81
+
82
+ - **Snapshot-driven UI.** The server is the source of truth: after every SDK
83
+ event it schedules a throttled (60 ms) full-state snapshot, and the browser
84
+ renders purely from snapshots. Reconnects just re-request `get_state`. Large
85
+ payloads (tool output, text) are capped during serialization (`server/serialize.ts`).
86
+ - **Size-aware attachments.** Clicking + on a file queues it as an attachment
87
+ (shown as chips above the input). On send, the server attaches each file as an
88
+ independent custom message (SDK `sendCustomMessage` + `nextTurn` asides) โ€” the
89
+ user message stays clean, and each file renders as its own collapsible card:
90
+ small text files (โ‰ค `PI_WEB_INLINE_FILE_MAX`, default 12KB) are inlined so the
91
+ model sees them immediately; larger files are passed as a `<file path=...>`
92
+ reference and the model reads them on demand with its `read` tool, so attaching
93
+ a 5 MB file costs only a few tokens until the model actually looks at it.
94
+ Images are always attached as image content.
95
+ - **Live tool output.** `bash_execution_update` / `tool_execution_update` events
96
+ are forwarded as lightweight `tool_delta` messages so terminal output streams
97
+ in real time; the final output arrives in the toolResult message on the next
98
+ snapshot, which supersedes the delta buffer.
99
+ - **Isolated sessions.** Each browser client gets `sessions/<clientId>/` under
100
+ the data dir, resumed on reconnect via `SessionManager.continueRecent`.
101
+ - **Everything you already have.** No separate auth step โ€” the SDK reads
102
+ `~/.pi/agent/auth.json` and loads your global extensions/skills automatically.
103
+
104
+ ## Terminal
105
+
106
+ Toggle the terminal view from the top bar (ๅฏน่ฏ/็ปˆ็ซฏ). It replaces the chat layout
107
+ with three panes:
108
+
109
+ - **Left โ€” ๅ‘ฝไปค (commands)**: click a command to open a terminal tab in its directory and
110
+ run it. Add/edit/delete commands in the panel; they are saved to
111
+ `<project>/.pi/commands.json` (committed to the repo, shared with teammates):
112
+
113
+ ```json
114
+ {
115
+ "commands": [
116
+ { "name": "dev", "command": "npm run dev", "cwd": "${pwd}" },
117
+ { "name": "test", "command": "npm test", "cwd": "${pwd}/server" },
118
+ { "name": "build", "command": "npm run build", "cwd": "~/other-project" }
119
+ ]
120
+ }
121
+ ```
122
+
123
+ `${pwd}` resolves to the agent's current working directory (the one shown in the chat
124
+ view's file panel, changeable via set_cwd); `~` and relative paths also work. The `+`
125
+ button at the top of the command panel creates a new entry.
126
+
127
+ - **Middle โ€” the terminal**: each tab is a real PTY (your `$SHELL`); output streams live
128
+ and you can type, Ctrl+C, resize, etc. exactly like a desktop terminal.
129
+
130
+ - **Right โ€” ็ปˆ็ซฏ (tabs)**: VSCode-style vertical tab strip. `+` opens a plain shell in the
131
+ current directory. Closing a tab kills its process.
132
+
133
+ Notes:
134
+
135
+ - Running commands keep running while you switch back to the chat view.
136
+ - Terminals are killed when the last browser tab for a client disconnects (no orphaned
137
+ dev servers), so a dropped connection resets the terminal view.
138
+
139
+ ## Protocol
140
+
141
+ See `server/protocol.ts` for the full wire format. Client โ†’ server: `hello`,
142
+ `prompt`, `abort`, `new_chat`, `cycle_model`, `cycle_thinking`, `get_state`,
143
+ `list_sessions`, `switch_session`, `list_files`, `list_models`, `set_model`,
144
+ `set_thinking`, `set_cwd`, `complete_path`, `dialog_response`,
145
+ `terminal_create`, `terminal_input`, `terminal_resize`, `terminal_kill`,
146
+ `run_command`, `list_commands`, `save_commands`.
147
+ Server โ†’ client: `ready`, `snapshot` (full `UiState`), `tool_delta`, `notice`,
148
+ `terminal_output`, `terminal_exit`, `commands`.
149
+
150
+ ## Scripts
151
+
152
+ | Script | What it does |
153
+ | --- | --- |
154
+ | `npm run dev` | server (tsx watch) + Vite dev server with WS proxy |
155
+ | `npm run build` | type-check + build frontend and server |
156
+ | `npm start` | run the production server (serves `web/dist`) |
157
+ | `npm run typecheck` | `tsc --noEmit` for both server and web |
158
+ | `node terminal-smoke-test.mjs` | WS-level terminal/commands protocol test (build first) |
159
+ | `node terminal-browser-test.mjs` | headless-browser E2E of the terminal view (build first) |
160
+
161
+ ## License
162
+
163
+ MIT
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * pi-web-ui CLI entry.
4
+ *
5
+ * Starts the production server (serves the built frontend + WebSocket API).
6
+ * Env vars: PORT (default 8787), PI_WEB_CWD, PI_WEB_DATA_DIR, PI_CODING_AGENT_DIR.
7
+ * See README.md for details.
8
+ */
9
+ import "../dist/server/index.js";
@@ -0,0 +1,48 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+ <!--
4
+ pi-web-ui launchd agent โ€” macOS auto-start at login.
5
+
6
+ Install:
7
+ npm i -g pi-web-ui
8
+ cp deploy/com.xingshuyin.pi-web-ui.plist ~/Library/LaunchAgents/
9
+ # edit ProgramArguments / WorkingDirectory / PI_WEB_CWD for your setup
10
+ launchctl load ~/Library/LaunchAgents/com.xingshuyin.pi-web-ui.plist
11
+ # (or: launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.xingshuyin.pi-web-ui.plist)
12
+
13
+ Find the pi-web-ui binary path with: which pi-web-ui
14
+ -->
15
+ <plist version="1.0">
16
+ <dict>
17
+ <key>Label</key>
18
+ <string>com.xingshuyin.pi-web-ui</string>
19
+
20
+ <key>ProgramArguments</key>
21
+ <array>
22
+ <string>/usr/local/bin/pi-web-ui</string>
23
+ </array>
24
+
25
+ <key>RunAtLoad</key>
26
+ <true/>
27
+
28
+ <!-- Restart if it crashes -->
29
+ <key>KeepAlive</key>
30
+ <true/>
31
+
32
+ <key>WorkingDirectory</key>
33
+ <string>/Users/YOUR_USER</string>
34
+
35
+ <key>EnvironmentVariables</key>
36
+ <dict>
37
+ <key>PORT</key>
38
+ <string>8787</string>
39
+ <key>PI_WEB_CWD</key>
40
+ <string>/Users/YOUR_USER</string>
41
+ </dict>
42
+
43
+ <key>StandardOutPath</key>
44
+ <string>/tmp/pi-web-ui.log</string>
45
+ <key>StandardErrorPath</key>
46
+ <string>/tmp/pi-web-ui.err</string>
47
+ </dict>
48
+ </plist>
@@ -0,0 +1,31 @@
1
+ # pi-web-ui systemd unit โ€” Linux auto-start on boot.
2
+ #
3
+ # Install (adjust User/WorkingDirectory/Environment to taste):
4
+ # sudo npm i -g pi-web-ui
5
+ # sudo cp deploy/pi-web-ui.service /etc/systemd/system/
6
+ # sudo systemctl daemon-reload
7
+ # sudo systemctl enable --now pi-web-ui
8
+ # sudo systemctl status pi-web-ui
9
+ #
10
+ # Logs: journalctl -u pi-web-ui -f
11
+
12
+ [Unit]
13
+ Description=pi-web-ui โ€” web chat for the pi coding agent
14
+ After=network.target
15
+
16
+ [Service]
17
+ Type=simple
18
+ # Run as an unprivileged user (change to your user, e.g. yourname)
19
+ User=YOUR_USER
20
+ # The workspace the agent operates in (read/edit/bash/write)
21
+ WorkingDirectory=/home/YOUR_USER
22
+ Environment=PORT=8787
23
+ # Point at your pi config dir if it's not the default ~/.pi/agent
24
+ #Environment=PI_CODING_AGENT_DIR=/home/YOUR_USER/.pi/agent
25
+ ExecStart=/usr/bin/pi-web-ui
26
+ Restart=on-failure
27
+ RestartSec=5
28
+ # npm global bin may live elsewhere (nvm, etc.) โ€” find with: which pi-web-ui
29
+
30
+ [Install]
31
+ WantedBy=multi-user.target