@jmfederico/pi-web 1.202607.3 → 1.202608.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.
Files changed (69) hide show
  1. package/README.md +1 -1
  2. package/dist/client/assets/{CodeViewer-CDVbMiN9.js → CodeViewer-D91Sp61M.js} +1 -1
  3. package/dist/client/assets/{TerminalPanel-CTS1CgqF.js → TerminalPanel-fYrKc3jh.js} +1 -1
  4. package/dist/client/assets/{UnifiedDiffViewer-Cqke12ZX.js → UnifiedDiffViewer-BafLWGtF.js} +1 -1
  5. package/dist/client/assets/{index-LME0LfPb.js → index-CA8q9_o7.js} +310 -353
  6. package/dist/client/index.html +1 -1
  7. package/dist/pi-web-plugins/relays/relayDiscovery.js +159 -27
  8. package/dist/pi-web-plugins/relays/relaysPanelElement.js +173 -16
  9. package/dist/server/app.js +0 -22
  10. package/dist/server/app.js.map +1 -1
  11. package/dist/server/browserMessageProjection.js +0 -2
  12. package/dist/server/browserMessageProjection.js.map +1 -1
  13. package/dist/server/configRoutes.js +4 -13
  14. package/dist/server/configRoutes.js.map +1 -1
  15. package/dist/server/machines/machineProxyRoutes.js +2 -13
  16. package/dist/server/machines/machineProxyRoutes.js.map +1 -1
  17. package/dist/server/piWebStatus.js +12 -38
  18. package/dist/server/piWebStatus.js.map +1 -1
  19. package/dist/server/sessiond/agentHttpDispatcher.js +108 -0
  20. package/dist/server/sessiond/agentHttpDispatcher.js.map +1 -0
  21. package/dist/server/sessiond/agentProcessEnvironment.js +62 -0
  22. package/dist/server/sessiond/agentProcessEnvironment.js.map +1 -0
  23. package/dist/server/sessiond/sessionServiceDependencies.js +1 -0
  24. package/dist/server/sessiond/sessionServiceDependencies.js.map +1 -1
  25. package/dist/server/sessiond.js +26 -5
  26. package/dist/server/sessiond.js.map +1 -1
  27. package/dist/server/sessions/askUserTool.js +0 -3
  28. package/dist/server/sessions/askUserTool.js.map +1 -1
  29. package/dist/server/sessions/authRoutes.js +0 -10
  30. package/dist/server/sessions/authRoutes.js.map +1 -1
  31. package/dist/server/sessions/authService.js +0 -24
  32. package/dist/server/sessions/authService.js.map +1 -1
  33. package/dist/server/sessions/messagePaging.js +2 -2
  34. package/dist/server/sessions/messagePaging.js.map +1 -1
  35. package/dist/server/sessions/oauthLoginFlowService.js +2 -5
  36. package/dist/server/sessions/oauthLoginFlowService.js.map +1 -1
  37. package/dist/server/sessions/pendingAskStore.js +0 -3
  38. package/dist/server/sessions/pendingAskStore.js.map +1 -1
  39. package/dist/server/sessions/piSessionManagerGateway.js +182 -2
  40. package/dist/server/sessions/piSessionManagerGateway.js.map +1 -1
  41. package/dist/server/sessions/piSessionService.js +244 -186
  42. package/dist/server/sessions/piSessionService.js.map +1 -1
  43. package/dist/server/sessions/sessionFileHeader.js +92 -20
  44. package/dist/server/sessions/sessionFileHeader.js.map +1 -1
  45. package/dist/server/sessions/sessionRoutes.js +74 -56
  46. package/dist/server/sessions/sessionRoutes.js.map +1 -1
  47. package/dist/server/sessions/sessionSummaryScanner.js +619 -0
  48. package/dist/server/sessions/sessionSummaryScanner.js.map +1 -0
  49. package/dist/server/sessions/spawnSessionTool.js +8 -1
  50. package/dist/server/sessions/spawnSessionTool.js.map +1 -1
  51. package/dist/server/sessions/spawnSubsessionTool.js +7 -1
  52. package/dist/server/sessions/spawnSubsessionTool.js.map +1 -1
  53. package/dist/server/workspaces/effectivePathAccess.js +0 -19
  54. package/dist/server/workspaces/effectivePathAccess.js.map +1 -1
  55. package/dist/server/workspaces/workspaceDeletionRoutes.js +30 -4
  56. package/dist/server/workspaces/workspaceDeletionRoutes.js.map +1 -1
  57. package/dist/server/workspaces/workspaceService.js.map +1 -1
  58. package/dist/sessiond/config.js +2 -2
  59. package/dist/sessiond/config.js.map +1 -1
  60. package/dist/shared/apiTypes.d.ts +12 -29
  61. package/dist/shared/apiTypes.js +7 -16
  62. package/dist/shared/apiTypes.js.map +1 -1
  63. package/dist/shared/capabilities.js +10 -44
  64. package/dist/shared/capabilities.js.map +1 -1
  65. package/dist/shared/federatedRoutes.js +0 -3
  66. package/dist/shared/federatedRoutes.js.map +1 -1
  67. package/docs/config.md +59 -4
  68. package/docs/plugins.md +5 -3
  69. package/package.json +10 -9
package/docs/config.md CHANGED
@@ -11,7 +11,7 @@ PI WEB uses two config files:
11
11
  - **Global PI WEB config:** `$PI_WEB_CONFIG`, or `$XDG_CONFIG_HOME/pi-web/config.json`, or `~/.config/pi-web/config.json`.
12
12
  - **Project-local PI WEB config:** `<project>/.pi-web/config.json` for commit-able project settings.
13
13
 
14
- Each PI WEB machine has its own config. When using Fleet/machine federation, Settings uses the selected machine for config that affects work running there: the Pi-compatible agent profile and companion CLI, session daemon tools, PI WEB plugin enablement, external path access, and upload defaults. Gateway/browser-only settings stay local to the gateway: keyboard shortcuts, remote machine registry/tokens, and gateway host/port/allowed-hosts. Remote servers that do not advertise selected-machine settings support report those settings as unavailable instead of silently falling back to the gateway.
14
+ Each PI WEB machine has its own config. When using Fleet/machine federation, Settings uses the selected machine for config that affects work running there: the Pi-compatible agent profile and companion CLI, session daemon tools, PI WEB plugin enablement, external path access, and upload defaults. Gateway/browser-only settings stay local to the gateway: keyboard shortcuts, remote machine registry/tokens, and gateway host/port/allowed-hosts.
15
15
 
16
16
  Pi package settings are separate from PI WEB config. They live in Pi's package-manager settings on the target machine and are managed by Pi (`pi install`, `pi remove`, `pi update`) or **Settings → Pi packages**. In a federated setup, **Settings → Pi packages** targets the currently selected machine. The PI WEB `plugins` config key only enables or disables discovered PI WEB browser plugins on the machine whose config you are editing; it does not install, remove, or update Pi packages.
17
17
 
@@ -97,10 +97,51 @@ Project-local config lives at `<project>/.pi-web/config.json`. Use it for settin
97
97
 
98
98
  Project-local `pathAccess.allowedPaths` entries are merged after the global list and deduplicated. Paths must still be host-absolute or `~`-prefixed; relative roots are not supported.
99
99
 
100
- Project-local `uploads.defaultFolder` overrides the global upload destination for workspaces in that project. Current PI WEB servers include this workspace-effective value on the existing workspace responses used locally and through machine federation. Older remote servers may omit the optional field; the browser falls back to the global/default upload folder.
100
+ Project-local `uploads.defaultFolder` overrides the global upload destination for workspaces in that project. PI WEB servers always include this workspace-effective value on the workspace responses used locally and through machine federation.
101
101
 
102
102
  Plugins may own separate project files, such as `.pi-web/tasks.json` for the built-in Workspace Tasks plugin.
103
103
 
104
+ PI WEB also honors one optional project hook; see [Worktree pre-remove hook](#worktree-pre-remove-hook).
105
+
106
+ ## Worktree pre-remove hook
107
+
108
+ Before PI WEB deletes a workspace (a secondary Git worktree), it gives the repository one chance to tear down project-owned infrastructure tied to that worktree. To use the hook, provide an executable script at:
109
+
110
+ ```text
111
+ .pi-web/hooks/worktree-pre-remove
112
+ ```
113
+
114
+ relative to the workspace where the deletion command runs. PI WEB runs the deletion command from the project's main workspace when it exists, so commit the hook there and it follows the repository.
115
+
116
+ When the hook is present and executable, PI WEB dispatches the hook and the removal as one composed terminal command:
117
+
118
+ ```sh
119
+ '<hook path>' '<worktree path>' && git worktree remove '<worktree path>'
120
+ ```
121
+
122
+ Contract:
123
+
124
+ - **Arguments:** exactly one — the absolute path of the worktree being deleted.
125
+ - **Working directory:** the workspace the deletion command runs in, not the worktree being deleted.
126
+ - **Exit codes:** `0` lets the removal proceed; any non-zero exit blocks it. The `&&` chain is the fail-closed guarantee — a failing hook keeps the worktree on disk.
127
+ - **Absent hook:** a missing file, or a file without the executable bit (for example after a checkout that lost it), is treated as no hook; PI WEB then runs a plain `git worktree remove`.
128
+
129
+ The composed command is dispatched like any other workspace deletion — same `Delete workspace: <branch>` terminal title — so hook output and failures are visible in the terminal run. If PI WEB cannot probe the hook path because of an unexpected filesystem error, the deletion request fails before any workspace terminals are closed.
130
+
131
+ Example: a hook that stops and removes local dev containers that bind-mount the worktree, so deletion does not leave stale containers behind. The hook is an opaque extension point — the contract does not assume any specific tooling, so use whatever the repository standardizes on:
132
+
133
+ ```sh
134
+ #!/bin/sh
135
+ # .pi-web/hooks/worktree-pre-remove
136
+ set -eu
137
+
138
+ worktree_path="$1"
139
+
140
+ # Stop/remove local dev containers bind-mounting "$worktree_path",
141
+ # release other per-worktree resources, etc.
142
+ # Exit non-zero to block the worktree removal.
143
+ ```
144
+
104
145
  ## Configuration matrix
105
146
 
106
147
  Rows with JSON key `—` are runtime-only environment variables, not config-file keys. `Global` means machine-global. In Settings, selected-machine-safe global keys (`pathAccess`, `uploads`, `maxUploadBytes`, `agent`, `spawnSessions`, `subsessions`, `askUser`, and `plugins`) are edited for the selected machine; gateway host/port/allowed-hosts, keyboard shortcuts, and machine registry/tokens stay local.
@@ -147,6 +188,10 @@ Each data directory is independent: after pointing PI WEB at a new root, it star
147
188
 
148
189
  This setting does not change the PI WEB config file selected by `PI_WEB_CONFIG` or Pi-owned state such as the active session files selected by `PI_CODING_AGENT_SESSION_DIR`.
149
190
 
191
+ ### Agent process environment
192
+
193
+ Agent shells, terminals, and spawned sessions do not inherit the session daemon's own configuration. When the daemon starts, it removes its `PI_WEB_*` configuration keys, `NODE_ENV`, `PORT`, and `PI_CODING_AGENT_SESSION_DIR` from the environment agent processes see, so development commands behave normally inside sessions — for example, `npm install` is not affected by a production `NODE_ENV` meant for the daemon, and a second PI WEB instance started from a session does not pick up the live daemon's data directory or socket. `PI_CODING_AGENT_DIR` and ordinary variables (`PATH`, `HOME`, proxy settings, and the like) remain visible. The daemon itself keeps using the values it captured at startup.
194
+
150
195
  ### External path access
151
196
 
152
197
  `pathAccess.allowedPaths` grants PI WEB's file explorer and absolute `@` path completions access to specific filesystem roots outside the current workspace.
@@ -186,7 +231,7 @@ The value must be a non-empty workspace-relative folder. PI WEB normalizes repea
186
231
 
187
232
  Manual uploads use the workspace file-write path: paths stay workspace-relative, parent folder creation is enabled by default, and overwrite is disabled by default. Direct drag/drop always keeps `overwrite` off; the review dialog lets you explicitly enable overwrite when needed. Browser-owned XHR progress is shown per batch/file, conflicts and errors stay visible in the upload progress UI, and the final file-write response is the source of truth.
188
233
 
189
- For machine federation, Settings saves the global upload default on the selected machine. Current remote PI WEB servers also return `workspace.effectiveConfig.uploads.defaultFolder` on the existing workspace-list response. Older remote servers can omit that optional field without breaking clients; the Files panel falls back to the global/default upload folder.
234
+ For machine federation, Settings saves the global upload default on the selected machine. Remote PI WEB servers always return `workspace.effectiveConfig.uploads.defaultFolder` on the workspace-list response, and the Files panel uses it as the default upload destination.
190
235
 
191
236
  The per-request size limit is still controlled by `maxUploadBytes` / `PI_WEB_MAX_UPLOAD_BYTES` on the machine serving the upload.
192
237
 
@@ -211,7 +256,7 @@ Environment variables take precedence over the config file. `PI_WEB_AGENT_COMMAN
211
256
 
212
257
  The session daemon resolves the persisted desired values plus its environment once at startup. That secret-free active profile stays fixed for the daemon lifetime. **Settings → Session daemon** saves command and directory together as desired configuration and shows whether the profile is active, needs a restart, or cannot be compared. Until the daemon restarts, sessions, Pi package operations, Pi-package-backed PI WEB plugin discovery, status/install detection, and update planning continue to use the daemon-owned active profile; a web/API restart recovers that same active profile instead of applying the newly saved values.
213
258
 
214
- If the session daemon cannot report a valid active profile, profile-dependent Pi package and PI WEB plugin operations report unavailable instead of falling back to independently resolved config. A package-managed update command is shown only when PI WEB can preserve the active profile with a recognized, safe Pi companion CLI; otherwise the command is omitted. Remote profile editing likewise requires advertised support, and the gateway rejects a remote save if the target does not return the requested profile. Restart the session daemon on the selected machine to establish the next active profile.
259
+ If the session daemon cannot report a valid active profile, profile-dependent Pi package and PI WEB plugin operations report unavailable instead of falling back to independently resolved config. A package-managed update command is shown only when PI WEB can preserve the active profile with a recognized, safe Pi companion CLI; otherwise the command is omitted. Restart the session daemon on the selected machine to establish the next active profile.
215
260
 
216
261
  ### Pi extension provider baseline
217
262
 
@@ -273,6 +318,8 @@ A completion notice wakes an idle parent or queues behind in-flight work. Each n
273
318
 
274
319
  `list_subsessions`, `check_subsession`, and `read_subsession` never yield or change control flow. They are for deliberate inspection or recovery, not completion polling. While a child works, agent-facing `check_subsession` and `read_subsession` withhold partial output and direct the parent to continue independent work or yield at the join point. Output becomes available when the child stops. Included output and transcripts follow a labeled marker and come last, after PI WEB guidance.
275
320
 
321
+ Both `spawn_session` and `spawn_subsession` accept an optional `model` parameter, given as an exact `provider/model-id` such as `anthropic/claude-sonnet-4-5`. When set, the new session starts on that model instead of inheriting the dispatching session's model. The match is strict: an unknown or malformed value is rejected with an error. A `#provider/model-id` reference in the prompt (see [Prompt completions](#prompt-completions)) is how users ask for a specific model; agents forward that reference as this parameter. The new session also inherits the dispatching session's thinking level, clamped to its model's capabilities.
322
+
276
323
  In **Settings → Session daemon**, these keys are saved on the selected machine. Restart the session daemon on that machine after changing them.
277
324
 
278
325
  #### `askUser` and `ask_user`
@@ -331,6 +378,14 @@ Shortcut values are keyed by action id. Values are shortcut strings such as `mod
331
378
 
332
379
  Prefer Settings → Keyboard for editing shortcuts interactively.
333
380
 
381
+ ## Prompt completions
382
+
383
+ The chat composer opens completion menus on three trigger characters:
384
+
385
+ - `/` at the very start of the draft completes session commands.
386
+ - `@` completes file paths: `@` for tracked files, `@ ` (at, then space) or `!@` for all files. Picking one inserts an `@path` reference into the draft, quoted automatically when the path contains spaces.
387
+ - `#` completes the models available to the session, filtered case-insensitively as you type (at most 12 entries). Picking one inserts a `#provider/model-id` reference into the draft, which tells agents the request should run on that model — for example as the `model` parameter of `spawn_session`.
388
+
334
389
  ## Optional completion tools
335
390
 
336
391
  File and path `@` completions work without extra tools. If `fzf` is available on the PI WEB server's `PATH`, PI WEB uses it to improve completion filtering/ranking; otherwise it falls back to built-in ranking.
package/docs/plugins.md CHANGED
@@ -23,9 +23,9 @@ They do **not** run in the session daemon, do not get a server-side hook API, an
23
23
 
24
24
  Use **Settings → Pi packages** to view configured Pi packages or install/remove/update a package. Enter only the package source, such as `npm:@scope/package`, a git/URL source, or a local path. PI WEB uses Pi's default package location, equivalent to `pi install <source>`, and does not ask for an install location.
25
25
 
26
- When machine federation is enabled, **Settings → Pi packages** targets the currently selected machine. The panel labels whether changes will run on the local/gateway machine or on a selected remote PI WEB machine. If an older or unavailable remote PI WEB server does not expose package-management routes, PI WEB reports the package management operation as unsupported or unavailable instead of silently falling back to the gateway.
26
+ When machine federation is enabled, **Settings → Pi packages** targets the currently selected machine. The panel labels whether changes will run on the local/gateway machine or on a selected remote PI WEB machine.
27
27
 
28
- Use **Settings → PI WEB plugins** to enable or disable discovered PI WEB browser plugins before the browser imports them. In a federated setup, this plugin enablement surface targets the currently selected machine and labels where changes are saved. If an older or unavailable remote PI WEB server does not advertise selected-machine settings support, PI WEB reports the plugin settings as unsupported or unavailable instead of silently falling back to the gateway.
28
+ Use **Settings → PI WEB plugins** to enable or disable discovered PI WEB browser plugins before the browser imports them. In a federated setup, this plugin enablement surface targets the currently selected machine and labels where changes are saved.
29
29
 
30
30
  After installing, removing, or updating a Pi package, type `/reload` in each idle PI WEB session on the target machine to refresh ordinary Pi resources such as extensions, skills, prompt templates, themes, and context/system prompt files. Reload the browser page separately for newly discovered or changed PI WEB browser plugins. A provider-registering Pi extension follows a separate daemon-start policy; see [Pi extension provider baseline](https://pi-web.dev/config#pi-extension-provider-baseline).
31
31
 
@@ -175,7 +175,7 @@ When [machine federation](https://pi-web.dev/machines) is enabled, PI WEB also l
175
175
  - remote theme contributions are ignored for now because themes are app-wide;
176
176
  - mixed PI WEB versions across federated machines are best-effort and not guaranteed compatible.
177
177
 
178
- Remote plugin enablement is controlled by the remote machine's PI WEB plugin config. To edit or disable a remote machine plugin, select that machine and use **Settings → PI WEB plugins** when the remote server exposes selected-machine settings, or open that machine directly/update its config file.
178
+ Remote plugin enablement is controlled by the remote machine's PI WEB plugin config. To edit or disable a remote machine plugin, select that machine and use **Settings → PI WEB plugins**, or open that machine directly/update its config file.
179
179
 
180
180
  Plugin package metadata may set `machineSpecific: true` when the plugin's meaning is tied to the selected PI WEB machine:
181
181
 
@@ -301,6 +301,8 @@ Review task configs before running them, especially in shared projects. Workspac
301
301
 
302
302
  A relay is a directory of markdown notes under `.pi-web/relays/<name>/` in the workspace root — the convention used by the Relay method for chaining agent sessions. The tab lists each relay's documents with `status.md`, `charter.md`, and `log.md` first (in that order), followed by any other files alphabetically, and opens `status.md` by default. Markdown documents render as sanitized HTML; other files render as preformatted text, and binary files have no preview. Truncated documents show a notice, and **Refresh** re-scans the workspace and reloads the open document.
303
303
 
304
+ Documents in subfolders are listed too. Folders appear as chips in the document strip, and expanding one inserts its files inline right after it — accordion-style, so expanding a folder collapses its siblings on the same level. An expanded folder wraps its chip and documents in a group bubble, so nested entries stay visually contained. Collapsing the folder that holds the open document keeps the selection and highlights the folder instead. Relay trees deeper than five levels, larger than 200 documents, or with more than 50 folders are listed partially, with a notice.
305
+
304
306
  With several relays, a picker pre-selects the most recently modified one; a single relay opens directly. A workspace without `.pi-web/relays/` shows an empty state explaining the convention. The tab never creates, edits, or deletes relay files.
305
307
 
306
308
  Relays is enabled by default. To hide it, disable `relays` in **Settings → PI WEB plugins** or set:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jmfederico/pi-web",
3
- "version": "1.202607.3",
3
+ "version": "1.202608.0",
4
4
  "description": "Web UI for persistent Pi Coding Agent sessions in real workspaces.",
5
5
  "license": "MIT",
6
6
  "author": "Federico Jaramillo Martinez",
@@ -69,7 +69,7 @@
69
69
  "@codemirror/state": "^6.7.1",
70
70
  "@codemirror/view": "^6.43.6",
71
71
  "@fastify/compress": "^9.0.0",
72
- "@fastify/static": "^9.3.0",
72
+ "@fastify/static": "^10.1.2",
73
73
  "@fastify/websocket": "^11.3.0",
74
74
  "@xterm/addon-fit": "^0.11.0",
75
75
  "@xterm/xterm": "^6.0.0",
@@ -78,14 +78,15 @@
78
78
  "lit": "^3.3.3",
79
79
  "marked": "^18.0.6",
80
80
  "node-pty": "^1.1.0",
81
- "typebox": "1.3.6",
81
+ "typebox": "1.3.7",
82
+ "undici": "^8.5.0",
82
83
  "ws": "^8.21.0"
83
84
  },
84
85
  "devDependencies": {
85
86
  "@changesets/cli": "^2.31.0",
86
- "@earendil-works/pi-agent-core": "^0.82.1",
87
- "@earendil-works/pi-ai": "^0.82.1",
88
- "@earendil-works/pi-coding-agent": "^0.82.1",
87
+ "@earendil-works/pi-agent-core": "^0.83.0",
88
+ "@earendil-works/pi-ai": "^0.83.0",
89
+ "@earendil-works/pi-coding-agent": "^0.83.0",
89
90
  "@eslint/js": "^10.0.1",
90
91
  "@types/node": "^24.13.3",
91
92
  "@types/ws": "^8.18.1",
@@ -115,9 +116,9 @@
115
116
  "homepage": "https://pi-web.dev/",
116
117
  "packageManager": "npm@11.11.0",
117
118
  "peerDependencies": {
118
- "@earendil-works/pi-agent-core": ">=0.82.1 <0.83",
119
- "@earendil-works/pi-ai": ">=0.82.1 <0.83",
120
- "@earendil-works/pi-coding-agent": ">=0.82.1 <0.83"
119
+ "@earendil-works/pi-agent-core": ">=0.83.0",
120
+ "@earendil-works/pi-ai": ">=0.83.0",
121
+ "@earendil-works/pi-coding-agent": ">=0.83.0"
121
122
  },
122
123
  "keywords": [
123
124
  "pi-package",