@jmfederico/pi-web 1.202606.3 → 1.202606.4
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 +11 -6
- package/dist/client/assets/{CodeViewer-iYSv2-dg.js → CodeViewer-CIG4PxA9.js} +1 -1
- package/dist/client/assets/{TerminalPanel-BpFW6j27.js → TerminalPanel-CKtvS-3H.js} +1 -1
- package/dist/client/assets/{index-D4dbiKXF.js → index-DDid7ddU.js} +367 -199
- package/dist/client/index.html +1 -1
- package/dist/config.js +51 -3
- package/dist/config.js.map +1 -1
- package/dist/pi-web-plugins/updates/pi-web-plugin.js +52 -56
- package/dist/pi-web-plugins/updates/updatesLogic.js +65 -0
- package/dist/pi-web-plugins/workspace-tasks/tasksPanelElement.js +1 -5
- package/dist/server/app.js +1 -1
- package/dist/server/app.js.map +1 -1
- package/dist/server/configRoutes.js +7 -0
- package/dist/server/configRoutes.js.map +1 -1
- package/dist/server/index.js +2 -2
- package/dist/server/index.js.map +1 -1
- package/dist/server/piWebStatus.js +15 -6
- package/dist/server/piWebStatus.js.map +1 -1
- package/dist/server/sessiond.js +16 -2
- package/dist/server/sessiond.js.map +1 -1
- package/dist/server/sessions/attachmentService.js +61 -0
- package/dist/server/sessions/attachmentService.js.map +1 -0
- package/dist/server/sessions/piSessionService.js +105 -18
- package/dist/server/sessions/piSessionService.js.map +1 -1
- package/dist/server/sessions/sessionCommandService.js +5 -1
- package/dist/server/sessions/sessionCommandService.js.map +1 -1
- package/dist/server/sessions/sessionRoutes.js +28 -4
- package/dist/server/sessions/sessionRoutes.js.map +1 -1
- package/dist/server/sessions/spawnSessionTool.js +36 -0
- package/dist/server/sessions/spawnSessionTool.js.map +1 -0
- package/dist/server/sessions/spawnTargetResolver.js +36 -0
- package/dist/server/sessions/spawnTargetResolver.js.map +1 -0
- package/dist/shared/apiTypes.d.ts +41 -3
- package/dist/shared/apiTypes.js +2 -0
- package/dist/shared/apiTypes.js.map +1 -1
- package/dist/shared/capabilities.js +4 -2
- package/dist/shared/capabilities.js.map +1 -1
- package/dist/shared/federatedRoutes.js +1 -0
- package/dist/shared/federatedRoutes.js.map +1 -1
- package/dist/shared/piWebStatusParsing.js +0 -15
- package/dist/shared/piWebStatusParsing.js.map +1 -1
- package/dist/shared/promptAttachments.js +73 -0
- package/dist/shared/promptAttachments.js.map +1 -0
- package/dist/shared/thinkingLevels.d.ts +27 -0
- package/dist/shared/thinkingLevels.js +31 -0
- package/dist/shared/thinkingLevels.js.map +1 -0
- package/dist/shared/workspaceDeletion.js +1 -1
- package/dist/shared/workspaceDeletion.js.map +1 -1
- package/docs/plugins.md +3 -3
- package/package.json +25 -14
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# PI WEB
|
|
1
|
+
# PI WEB — web UI for Pi Coding Agent
|
|
2
2
|
|
|
3
3
|
[](https://github.com/jmfederico/pi-web/actions/workflows/ci.yml)
|
|
4
4
|
[](https://www.npmjs.com/package/@jmfederico/pi-web)
|
|
@@ -10,9 +10,9 @@ Website: <https://pi-web.dev/>
|
|
|
10
10
|
|
|
11
11
|

|
|
12
12
|
|
|
13
|
-
**Run
|
|
13
|
+
**Run Pi Coding Agent from a web UI, keep sessions alive in real workspaces, and supervise them from any device.**
|
|
14
14
|
|
|
15
|
-
PI WEB is a web
|
|
15
|
+
PI WEB is a web UI for [Pi Coding Agent](https://github.com/earendil-works/pi/tree/main/packages/coding-agent) that keeps agent sessions running on your own machine or server. Add your repositories once, open project workspaces and git worktrees, start sessions inside them, and come back later without losing the work. Your browser becomes the cockpit; your server becomes the persistent development environment. Start on your laptop, check in from your phone, and continue from an iPad or another machine whenever that is the device you have at hand.
|
|
16
16
|
|
|
17
17
|

|
|
18
18
|
|
|
@@ -32,6 +32,10 @@ Agentic development works best when agents are not trapped inside a single local
|
|
|
32
32
|
|
|
33
33
|
PI WEB connects those two worlds. The work stays in the server-side environment while you move between devices: laptop for deep focus, phone for a quick check-in, tablet for review, desktop when you are back at a desk. It is not trying to recreate the old desktop IDE in a browser; it is a control surface for persistent, parallel, human-in-the-loop agent work.
|
|
34
34
|
|
|
35
|
+
### Is PI WEB a Pi web UI?
|
|
36
|
+
|
|
37
|
+
Yes. PI WEB is a Pi web UI for running and supervising Pi Coding Agent sessions from a browser. Unlike simple session viewers, PI WEB is built around persistent server-side workspaces, long-running session daemons, git worktrees, remote machines, and multi-device supervision.
|
|
38
|
+
|
|
35
39
|
## Core model
|
|
36
40
|
|
|
37
41
|
PI WEB organizes work into four levels:
|
|
@@ -69,7 +73,7 @@ This maps naturally to real development work:
|
|
|
69
73
|
|
|
70
74
|
## Architecture
|
|
71
75
|
|
|
72
|
-
PI WEB uses a split-process architecture so agent runtimes are not owned by the browser-facing dev server.
|
|
76
|
+
PI WEB uses a split-process architecture so agent runtimes are not owned by the browser-facing dev server. Under the hood, it acts as a browser-based control plane for sessions, workspaces, files, terminals, and trusted remote machines.
|
|
73
77
|
|
|
74
78
|
```text
|
|
75
79
|
Browser UI
|
|
@@ -104,7 +108,7 @@ PI WEB keeps its own state intentionally small:
|
|
|
104
108
|
|
|
105
109
|
## Machine federation
|
|
106
110
|
|
|
107
|
-
The Machines section lets one PI WEB instance act as a gateway to other PI WEB runtimes. Register a remote machine from **Actions → Add Machine** with the remote PI WEB base URL, for example a URL reachable over NetBird, Tailscale, WireGuard, an SSH tunnel, or a trusted reverse proxy. The browser continues talking to the local PI WEB origin; project, workspace, file, git, session, activity, and terminal HTTP/WebSocket traffic is proxied server-to-server. See the [Fleet guide](https://pi-web.dev/machines
|
|
111
|
+
The Machines section lets one PI WEB instance act as a gateway to other PI WEB runtimes. Register a remote machine from **Actions → Add Machine** with the remote PI WEB base URL, for example a URL reachable over NetBird, Tailscale, WireGuard, an SSH tunnel, or a trusted reverse proxy. The browser continues talking to the local PI WEB origin; project, workspace, file, git, session, activity, and terminal HTTP/WebSocket traffic is proxied server-to-server. See the [Fleet guide](https://pi-web.dev/machines) for setup, trust model, and troubleshooting details.
|
|
108
112
|
|
|
109
113
|
Remote model-provider credentials and OAuth state stay on the target machine. API-key provider configuration can be proxied, but OAuth login should be completed by opening the remote PI WEB directly. Register remote machines only when you trust the endpoint and the network path: adding a machine gives this PI WEB server permission to contact that URL with the optional bearer token you configured.
|
|
110
114
|
|
|
@@ -118,7 +122,7 @@ A useful prompt for AI agents:
|
|
|
118
122
|
|
|
119
123
|
```text
|
|
120
124
|
Build a PI WEB plugin for this project. Goal: <describe the UI behavior>.
|
|
121
|
-
Before coding, read https://pi-web.dev/plugins
|
|
125
|
+
Before coding, read https://pi-web.dev/plugins and https://pi-web.dev/plugins.md.
|
|
122
126
|
Create it under ~/.pi-web/plugins/<plugin-id> using the documented PI WEB v1 plugin API.
|
|
123
127
|
Validate with /pi-web-plugins/manifest.json and explain reload/debug steps.
|
|
124
128
|
Do not modify PI WEB itself.
|
|
@@ -272,6 +276,7 @@ Environment variables:
|
|
|
272
276
|
- `PI_WEB_SESSIOND_URL` — daemon URL used by the web process when connecting over TCP, for example `http://127.0.0.1:3001`. If you set `PI_WEB_SESSIOND_PORT`, set this for the web process too.
|
|
273
277
|
- `PI_WEB_PROJECTS_FILE` — optional override for the projects storage JSON file. Defaults to `$PI_WEB_DATA_DIR/projects.json`.
|
|
274
278
|
- `PI_WEB_MACHINES_FILE` — optional override for the remote machine registry JSON file. Defaults to `$PI_WEB_DATA_DIR/machines.json`.
|
|
279
|
+
- `PI_WEB_MAX_UPLOAD_BYTES` — maximum accepted HTTP request body size in bytes (covers pasted/attached images). Defaults to 64 MB. Also configurable as `maxUploadBytes` in `config.json`.
|
|
275
280
|
- `PI_CODING_AGENT_SESSION_DIR` — Pi session storage directory. PI WEB follows the same session-location priority as Pi for web sessions: this environment variable, then `sessionDir` in Pi settings for the selected workspace, then Pi's default session directory.
|
|
276
281
|
- `PI_CODING_AGENT_DIR` — Pi agent config directory. PI WEB uses this for Pi auth, settings, resources, and default session storage, matching Pi's own configuration layout.
|
|
277
282
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{w as a,J as p,$ as h,A as m,X as g,U as f,_ as v,a0 as b}from"./vendor-editor-core-B4Sq6exx.js";import{g as y,r as w,p as C,h as x,c as j,m as _,j as k,a as u}from"./vendor-editor-languages-DznYbTkJ.js";import{d as E}from"./vendor-editor-legacy-B4QLsWF8.js";import{i as H,b as O,a as S,n as d,e as P,t as L}from"./index-
|
|
1
|
+
import{w as a,J as p,$ as h,A as m,X as g,U as f,_ as v,a0 as b}from"./vendor-editor-core-B4Sq6exx.js";import{g as y,r as w,p as C,h as x,c as j,m as _,j as k,a as u}from"./vendor-editor-languages-DznYbTkJ.js";import{d as E}from"./vendor-editor-legacy-B4QLsWF8.js";import{i as H,b as O,a as S,n as d,e as P,t as L}from"./index-DDid7ddU.js";var D=Object.defineProperty,F=Object.getOwnPropertyDescriptor,i=(e,o,n,s)=>{for(var t=s>1?void 0:s?F(o,n):o,c=e.length-1,l;c>=0;c--)(l=e[c])&&(t=(s?l(o,n,t):l(t))||t);return s&&t&&D(o,n,t),t};let r=class extends H{constructor(){super(...arguments),this.content=""}firstUpdated(){this.recreateEditor()}updated(e){(e.has("content")||e.has("language"))&&this.recreateEditor()}disconnectedCallback(){this.view?.destroy(),this.view=void 0,super.disconnectedCallback()}render(){return O`<div class="host"></div>`}recreateEditor(){this.editorHost&&(this.view?.destroy(),this.view=new a({parent:this.editorHost,state:p.create({doc:this.content,extensions:[h(),m.of(g),f(v,{fallback:!0}),p.readOnly.of(!0),a.editable.of(!1),a.lineWrapping,M,...R(this.language)]})}))}};r.styles=S`
|
|
2
2
|
:host { display: block; min-height: 0; height: 100%; }
|
|
3
3
|
.host { height: 100%; min-height: 0; overflow: auto; }
|
|
4
4
|
`;i([d()],r.prototype,"content",2);i([d()],r.prototype,"language",2);i([P(".host")],r.prototype,"editorHost",2);r=i([L("code-viewer")],r);const M=a.theme({"&":{height:"100%",color:"var(--pi-text)",backgroundColor:"var(--pi-bg)",fontSize:"12px"},".cm-scroller":{fontFamily:"ui-monospace, SFMono-Regular, Menlo, Consolas, monospace",lineHeight:"1.45"},".cm-gutters":{backgroundColor:"var(--pi-bg)",color:"var(--pi-dim)",borderRight:"1px solid var(--pi-border-muted)"},".cm-activeLineGutter":{backgroundColor:"transparent"},".cm-activeLine":{backgroundColor:"transparent"},".cm-content":{caretColor:"transparent"},"&.cm-focused":{outline:"none"}});function R(e){if(e===void 0)return[];switch(e){case"typescript":return[u({typescript:!0})];case"javascript":return[u()];case"json":return[k()];case"markdown":return[_()];case"css":return[j()];case"html":return[x()];case"python":return[C()];case"rust":return[w()];case"go":return[y()];case"diff":return[b.define(E)];default:return[]}}export{r as CodeViewer};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{a as E,n as m,i as K,b as l,t as R,c as h,s as A,d as w,f as _,e as F,r as c}from"./index-
|
|
1
|
+
import{a as E,n as m,i as K,b as l,t as R,c as h,s as A,d as w,f as _,e as F,r as c}from"./index-DDid7ddU.js";import{D as S,o as T}from"./vendor-terminal-DjQ08hXu.js";import"./vendor-editor-core-B4Sq6exx.js";import"./vendor-editor-languages-DznYbTkJ.js";const P="pi-web.terminal.softKeys",N="(pointer: coarse), (max-width: 760px)";function z(e,t){return e??t}function V(e){if(e==="true")return!0;if(e==="false")return!1}function $(){return typeof window<"u"&&"matchMedia"in window?window.matchMedia(N):void 0}function M(e){return e?.matches===!0}function B(e=$()){return z(O(),M(e))}function H(){return O()!==void 0}function O(e=D()){if(e!==void 0)try{return V(e.getItem(P))}catch{return}}function j(e,t=D()){if(t!==void 0)try{t.setItem(P,String(e))}catch{}}function D(){if(!(typeof window>"u"))try{return window.localStorage}catch{return}}const U=[{id:"escape",label:"Esc",ariaLabel:"Escape",title:"Send Escape"},{id:"tab",label:"Tab",ariaLabel:"Tab",title:"Send Tab"},{id:"ctrl-c",label:"Ctrl+C",ariaLabel:"Control C",title:"Interrupt the foreground process"},{id:"ctrl-d",label:"Ctrl+D",ariaLabel:"Control D",title:"Send EOF / close input"},{id:"ctrl-z",label:"Ctrl+Z",ariaLabel:"Control Z",title:"Suspend the foreground process"},{id:"ctrl-l",label:"Ctrl+L",ariaLabel:"Control L",title:"Clear / redraw the terminal"},{id:"ctrl-r",label:"Ctrl+R",ariaLabel:"Control R",title:"Reverse search history"},{id:"ctrl-u",label:"Ctrl+U",ariaLabel:"Control U",title:"Delete to the start of the line"},{id:"ctrl-w",label:"Ctrl+W",ariaLabel:"Control W",title:"Delete the previous word"},{id:"arrow-left",label:"←",ariaLabel:"Left arrow",title:"Move left"},{id:"arrow-up",label:"↑",ariaLabel:"Up arrow",title:"Move up / previous command"},{id:"arrow-down",label:"↓",ariaLabel:"Down arrow",title:"Move down / next command"},{id:"arrow-right",label:"→",ariaLabel:"Right arrow",title:"Move right"},{id:"home",label:"Home",ariaLabel:"Home",title:"Move to the start"},{id:"end",label:"End",ariaLabel:"End",title:"Move to the end"},{id:"page-up",label:"PgUp",ariaLabel:"Page up",title:"Page up"},{id:"page-down",label:"PgDn",ariaLabel:"Page down",title:"Page down"},{id:"delete",label:"Del",ariaLabel:"Delete",title:"Delete forward"},{id:"backspace",label:"⌫",ariaLabel:"Backspace",title:"Backspace"},{id:"meta-backward-word",label:"M-B",ariaLabel:"Meta B",title:"Move backward one word"},{id:"meta-forward-word",label:"M-F",ariaLabel:"Meta F",title:"Move forward one word"}],d="\x1B",q="";function Y(e,t){switch(e){case"escape":return d;case"tab":return" ";case"ctrl-c":return p("c");case"ctrl-d":return p("d");case"ctrl-z":return p("z");case"ctrl-l":return p("l");case"ctrl-r":return p("r");case"ctrl-u":return p("u");case"ctrl-w":return p("w");case"arrow-left":return b("D",t);case"arrow-up":return b("A",t);case"arrow-down":return b("B",t);case"arrow-right":return b("C",t);case"home":return x("H",t);case"end":return x("F",t);case"page-up":return`${d}[5~`;case"page-down":return`${d}[6~`;case"delete":return`${d}[3~`;case"backspace":return q;case"meta-backward-word":return`${d}b`;case"meta-forward-word":return`${d}f`}}function p(e){return String.fromCharCode(e.toUpperCase().charCodeAt(0)-64)}function b(e,t){return t?.applicationCursorKeysMode===!0?`${d}O${e}`:`${d}[${e}`}function x(e,t){return t?.applicationCursorKeysMode===!0?`${d}O${e}`:`${d}[${e}`}var W=Object.defineProperty,X=Object.getOwnPropertyDescriptor,y=(e,t,i,r)=>{for(var n=r>1?void 0:r?X(t,i):t,a=e.length-1,u;a>=0;a--)(u=e[a])&&(n=(r?u(t,i,n):u(n))||n);return r&&n&&W(t,i,n),n};const J=8,Z=500;let f=class extends K{constructor(){super(...arguments),this.refocusOnClick=!0,this.onInput=()=>{},this.lastPointerFinishedAt=0}sendSoftKey(e,t){this.onInput(Y(e.id,this.modes),t)}onSoftKeyPointerDown(e,t){e.pointerType==="mouse"&&e.button!==0||(e.preventDefault(),this.pointerStart={pointerId:e.pointerId,key:t,clientX:e.clientX,clientY:e.clientY})}onSoftKeyPointerMove(e){const t=this.pointerStart;t?.pointerId===e.pointerId&&I(t,e)&&this.finishSoftKeyPointer()}onSoftKeyPointerUp(e,t){const i=this.pointerStart;i?.pointerId===e.pointerId&&(e.preventDefault(),this.finishSoftKeyPointer(),!(i.key.id!==t.id||I(i,e))&&this.sendSoftKey(t,{refocus:e.pointerType==="mouse"}))}onSoftKeyPointerCancel(e){this.pointerStart?.pointerId===e.pointerId&&this.finishSoftKeyPointer()}finishSoftKeyPointer(){this.pointerStart=void 0,this.lastPointerFinishedAt=Date.now()}onSoftKeyClick(e,t){if(Date.now()-this.lastPointerFinishedAt<Z){e.preventDefault();return}this.sendSoftKey(t,{refocus:this.refocusOnClick})}render(){return l`
|
|
2
2
|
<div class="terminal-soft-keys" role="toolbar" aria-label="Terminal soft keys">
|
|
3
3
|
${U.map(e=>l`
|
|
4
4
|
<button
|