@jmfederico/pi-web 1.202606.7 → 1.202607.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.
- package/README.md +9 -3
- package/dist/client/assets/CodeViewer-tXF3UTsY.js +4 -0
- package/dist/client/assets/TerminalPanel-D_ihiWAt.js +187 -0
- package/dist/client/assets/UnifiedDiffViewer-BziirXBJ.js +39 -0
- package/dist/client/assets/index-Brfk1lwl.js +2950 -0
- package/dist/client/assets/vendor-editor-core-vUi74DnD.js +12 -0
- package/dist/client/assets/vendor-editor-languages-DoaXUodB.js +46 -0
- package/dist/client/assets/vendor-editor-legacy-CYBnW6ZU.js +1 -0
- package/dist/client/assets/vendor-terminal-BrP-ENHg.css +1 -0
- package/dist/client/assets/vendor-terminal-D8k4UKM2.js +35 -0
- package/dist/client/index.html +6 -3
- package/dist/docker/piWebDockerCommandPlan.js +211 -0
- package/dist/docker/piWebDockerCommandPlan.js.map +1 -0
- package/dist/pi-web-plugins/updates/pi-web-plugin.js +15 -5
- package/dist/pi-web-plugins/updates/updatesLogic.js +37 -5
- package/dist/piWebVersionReport.js +4 -0
- package/dist/piWebVersionReport.js.map +1 -1
- package/dist/plugin-api.d.ts +1 -1
- package/dist/server/app.js +16 -1
- package/dist/server/app.js.map +1 -1
- package/dist/server/browserMessageProjection.js +56 -0
- package/dist/server/browserMessageProjection.js.map +1 -0
- package/dist/server/configRoutes.js +108 -1
- package/dist/server/configRoutes.js.map +1 -1
- package/dist/server/machines/machineClient.js +19 -9
- package/dist/server/machines/machineClient.js.map +1 -1
- package/dist/server/machines/machineProxyRoutes.js +64 -11
- package/dist/server/machines/machineProxyRoutes.js.map +1 -1
- package/dist/server/machines/machineService.js +4 -26
- package/dist/server/machines/machineService.js.map +1 -1
- package/dist/server/piPackageRoutes.js +87 -0
- package/dist/server/piPackageRoutes.js.map +1 -0
- package/dist/server/piPackageService.js +69 -0
- package/dist/server/piPackageService.js.map +1 -0
- package/dist/server/piWebPluginService.js +43 -8
- package/dist/server/piWebPluginService.js.map +1 -1
- package/dist/server/piWebStatus.js +57 -0
- package/dist/server/piWebStatus.js.map +1 -1
- package/dist/server/realtime/sessionEventHub.js +2 -1
- package/dist/server/realtime/sessionEventHub.js.map +1 -1
- package/dist/server/sessions/builtinCommands.js +1 -1
- package/dist/server/sessions/builtinCommands.js.map +1 -1
- package/dist/server/sessions/piSessionService.js +503 -104
- package/dist/server/sessions/piSessionService.js.map +1 -1
- package/dist/server/sessions/sessionArchiveStore.js +51 -22
- package/dist/server/sessions/sessionArchiveStore.js.map +1 -1
- package/dist/server/sessions/sessionCommandService.js +16 -0
- package/dist/server/sessions/sessionCommandService.js.map +1 -1
- package/dist/server/sessions/sessionNameGenerator.js +27 -44
- package/dist/server/sessions/sessionNameGenerator.js.map +1 -1
- package/dist/server/sessions/sessionRoutes.js +38 -1
- package/dist/server/sessions/sessionRoutes.js.map +1 -1
- package/dist/server/sessions/spawnSessionTool.js +9 -4
- package/dist/server/sessions/spawnSessionTool.js.map +1 -1
- package/dist/server/sessions/spawnSubsessionTool.js +22 -15
- package/dist/server/sessions/spawnSubsessionTool.js.map +1 -1
- package/dist/server/workspaces/fileSuggestions.js +7 -3
- package/dist/server/workspaces/fileSuggestions.js.map +1 -1
- package/dist/shared/activity.js +0 -15
- package/dist/shared/activity.js.map +1 -1
- package/dist/shared/apiTypes.d.ts +63 -1
- package/dist/shared/apiTypes.js +4 -0
- package/dist/shared/apiTypes.js.map +1 -1
- package/dist/shared/capabilities.js +28 -2
- package/dist/shared/capabilities.js.map +1 -1
- package/dist/shared/federatedRoutes.js +10 -0
- package/dist/shared/federatedRoutes.js.map +1 -1
- package/dist/shared/piWebStatusParsing.js +20 -8
- package/dist/shared/piWebStatusParsing.js.map +1 -1
- package/dist/shared/thinkingLevels.d.ts +1 -1
- package/dist/shared/thinkingLevels.js +1 -1
- package/dist/shared/thinkingLevels.js.map +1 -1
- package/docs/config.md +24 -13
- package/docs/plugins.md +28 -14
- package/package.json +35 -31
- package/dist/client/assets/CodeViewer-CQU9mJ74.js +0 -4
- package/dist/client/assets/TerminalPanel-DtfVBsqI.js +0 -126
- package/dist/client/assets/UnifiedDiffViewer-BZQQK99S.js +0 -34
- package/dist/client/assets/index-CbE7df66.js +0 -2742
- package/dist/client/assets/vendor-editor-core-C7aWiQy0.js +0 -12
- package/dist/client/assets/vendor-editor-languages-EW34FfVy.js +0 -26
- package/dist/client/assets/vendor-editor-legacy-B4QLsWF8.js +0 -1
- package/dist/client/assets/vendor-terminal-DDGTF8rc.css +0 -1
- package/dist/client/assets/vendor-terminal-DjQ08hXu.js +0 -16
package/docs/plugins.md
CHANGED
|
@@ -13,6 +13,18 @@ Plugins can currently:
|
|
|
13
13
|
|
|
14
14
|
They do **not** run in the session daemon, do not get a server-side hook API, and are not sandboxed.
|
|
15
15
|
|
|
16
|
+
## Pi packages vs PI WEB plugins
|
|
17
|
+
|
|
18
|
+
**Pi packages** are packages managed by Pi (`pi install`, `pi remove`, `pi update`). A Pi package can provide extensions, skills, prompt templates, themes, context/system prompt files, and/or PI WEB browser plugins. Many Pi packages do not include a PI WEB plugin.
|
|
19
|
+
|
|
20
|
+
**PI WEB plugins** are browser-side PI WEB UI modules discovered from bundled, local, dev, and installed Pi-package sources. Enabling or disabling a PI WEB plugin is a PI WEB config task; installing, removing, or updating a Pi package is a Pi package-manager task.
|
|
21
|
+
|
|
22
|
+
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.
|
|
23
|
+
|
|
24
|
+
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.
|
|
25
|
+
|
|
26
|
+
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. After installing, removing, or updating a Pi package, type `/reload` in each idle PI WEB session on the target machine to refresh Pi runtime resources such as extensions, skills, prompt templates, themes, and context/system prompt files as supported by Pi. Reload the browser page separately for newly discovered or changed PI WEB browser plugins. A routine session daemon restart is not required.
|
|
27
|
+
|
|
16
28
|
## Trust model
|
|
17
29
|
|
|
18
30
|
Plugins run as JavaScript in the browser app. Treat them as trusted code:
|
|
@@ -140,7 +152,7 @@ When [machine federation](https://pi-web.dev/machines) is enabled, PI WEB also l
|
|
|
140
152
|
- remote theme contributions are ignored for now because themes are app-wide;
|
|
141
153
|
- mixed PI WEB versions across federated machines are best-effort and not guaranteed compatible.
|
|
142
154
|
|
|
143
|
-
Remote plugin enablement is controlled by the remote machine's PI WEB plugin config. To edit or disable a remote machine plugin,
|
|
155
|
+
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.
|
|
144
156
|
|
|
145
157
|
Plugin package metadata may set `machineSpecific: true` when the plugin's meaning is tied to the selected PI WEB machine:
|
|
146
158
|
|
|
@@ -155,9 +167,11 @@ const url = new URL("./asset.json", import.meta.url);
|
|
|
155
167
|
|
|
156
168
|
If a remote plugin constructs absolute asset URLs, it should use the `pluginId` from `activate()` because PI WEB gives remote plugins a gateway-scoped runtime id. Hard-coded `/pi-web-plugins/<original-id>/...` URLs may point at the gateway instead of the remote machine.
|
|
157
169
|
|
|
158
|
-
## Manage plugins
|
|
170
|
+
## Manage PI WEB plugins
|
|
171
|
+
|
|
172
|
+
Open **Settings → PI WEB plugins** to review discovered bundled, local, dev, and Pi package plugins for the selected PI WEB machine. When the local machine is selected, this is the gateway plugin list; when a remote machine is selected, the list comes from that remote PI WEB server and includes disabled discovered plugins it exposes. PI WEB can disable any discovered selected-machine plugin before the browser imports it. Core app contributions such as the built-in command palette, base workspace tools, and themes are not managed through this plugin list.
|
|
159
173
|
|
|
160
|
-
|
|
174
|
+
This surface is only for PI WEB plugin enablement. To install, remove, or update Pi packages that may provide plugins or other Pi resources, use **Settings → Pi packages**. In a federated setup, both the Pi packages panel and the PI WEB plugins panel target the selected machine; plugin enablement still writes the PI WEB `plugins` config key rather than changing Pi package-manager settings.
|
|
161
175
|
|
|
162
176
|
Plugin preferences are stored under the top-level `plugins` config key in the PI WEB config file:
|
|
163
177
|
|
|
@@ -183,14 +197,14 @@ After changing plugin enablement, reload the PI WEB browser tab. Already-loaded
|
|
|
183
197
|
|
|
184
198
|
PI WEB ships core, discoverable plugins in the main `@jmfederico/pi-web` npm package. No separate `pi install` step is required: update PI WEB, reload the browser tab, and the bundled plugins appear in `/pi-web-plugins/manifest.json`.
|
|
185
199
|
|
|
186
|
-
Built-in plugins can be managed from **Settings →
|
|
200
|
+
Built-in plugins can be managed from **Settings → PI WEB plugins** or with the top-level `plugins` config key.
|
|
187
201
|
|
|
188
202
|
### Updates
|
|
189
203
|
|
|
190
204
|
**Plugin id:** `updates`
|
|
191
205
|
**What it does:** adds a conditional **Updates** workspace tab with PI WEB update, restart, and installed-service guidance.
|
|
192
206
|
|
|
193
|
-
Updates is enabled by default. It declares `machineSpecific: true` so the gateway Updates tab only appears for the local machine; while a remote machine is selected, that remote machine's Updates plugin is used if available. To hide it, disable `updates` in **Settings →
|
|
207
|
+
Updates is enabled by default. It declares `machineSpecific: true` so the gateway Updates tab only appears for the local machine; while a remote machine is selected, that remote machine's Updates plugin is used if available. To hide it, disable `updates` in **Settings → PI WEB plugins** or set:
|
|
194
208
|
|
|
195
209
|
```json
|
|
196
210
|
{
|
|
@@ -206,7 +220,7 @@ Updates is enabled by default. It declares `machineSpecific: true` so the gatewa
|
|
|
206
220
|
**Config file:** `.pi-web/tasks.json`
|
|
207
221
|
**What it does:** adds a **Tasks** workspace tab for running configured shell commands in dedicated PI WEB terminals.
|
|
208
222
|
|
|
209
|
-
Workspace Tasks is enabled by default. To hide it, disable `workspace-tasks` in **Settings →
|
|
223
|
+
Workspace Tasks is enabled by default. To hide it, disable `workspace-tasks` in **Settings → PI WEB plugins** or set:
|
|
210
224
|
|
|
211
225
|
```json
|
|
212
226
|
{
|
|
@@ -223,11 +237,11 @@ Configure workspace tasks in `.pi-web/tasks.json`:
|
|
|
223
237
|
"version": 1,
|
|
224
238
|
"tasks": [
|
|
225
239
|
{
|
|
226
|
-
"id": "
|
|
227
|
-
"title": "Start
|
|
228
|
-
"group": "
|
|
229
|
-
"description": "Start the local
|
|
230
|
-
"command": "
|
|
240
|
+
"id": "app.start",
|
|
241
|
+
"title": "Start app",
|
|
242
|
+
"group": "Development",
|
|
243
|
+
"description": "Start the local development server.",
|
|
244
|
+
"command": "npm run dev"
|
|
231
245
|
},
|
|
232
246
|
{
|
|
233
247
|
"id": "db.reset",
|
|
@@ -273,7 +287,7 @@ PI WEB builds the gateway `/pi-web-plugins/manifest.json` from these sources:
|
|
|
273
287
|
|
|
274
288
|
Entries may be real directories or symlinks. This is the recommended development workflow.
|
|
275
289
|
|
|
276
|
-
3. Installed Pi packages that expose PI WEB plugin metadata. Pi packages may be user or project scoped.
|
|
290
|
+
3. Installed Pi packages that expose PI WEB plugin metadata. Pi packages may be user or project scoped. Installing/removing/updating Pi packages is done from **Settings → Pi packages** (or Pi's package manager), not from the PI WEB plugin enable/disable list.
|
|
277
291
|
|
|
278
292
|
Remote machines expose their own manifests through the gateway at `/api/machines/<machine-id>/pi-web-plugins/manifest.json`. Those plugin modules are rewritten to gateway-scoped asset URLs and registered under machine-scoped runtime ids so duplicate plugin ids on different machines do not collide.
|
|
279
293
|
|
|
@@ -746,7 +760,7 @@ Labels should use the same helper through a plugin-owned cache because `items()`
|
|
|
746
760
|
const envCache = new Map();
|
|
747
761
|
|
|
748
762
|
function envKey(machine, workspace) {
|
|
749
|
-
return `${machine.id}:${workspace.id}
|
|
763
|
+
return `${machine.id}:${workspace.id}:.env.local`;
|
|
750
764
|
}
|
|
751
765
|
|
|
752
766
|
function loadEnvLabel(context) {
|
|
@@ -756,7 +770,7 @@ function loadEnvLabel(context) {
|
|
|
756
770
|
|
|
757
771
|
const pending = { status: "loading", label: undefined };
|
|
758
772
|
envCache.set(key, pending);
|
|
759
|
-
context.files.readFile("
|
|
773
|
+
context.files.readFile(".env.local")
|
|
760
774
|
.then((file) => {
|
|
761
775
|
pending.status = "ready";
|
|
762
776
|
pending.label = file.content.match(/^DEV_URL=(.+)$/m)?.[1];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jmfederico/pi-web",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.202607.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",
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
},
|
|
13
13
|
"files": [
|
|
14
14
|
"dist",
|
|
15
|
+
"!dist/**/*.testSupport.*",
|
|
15
16
|
"install.sh",
|
|
16
17
|
"README.md",
|
|
17
18
|
"LICENSE",
|
|
@@ -29,18 +30,20 @@
|
|
|
29
30
|
"dev:server": "npm run dev:web",
|
|
30
31
|
"dev:client": "vite --host 0.0.0.0",
|
|
31
32
|
"dev:plugins": "node scripts/build-plugins.mjs --watch",
|
|
32
|
-
"build": "tsc -p tsconfig.build.json && npm run build:plugin-api && npm run build:plugins && vite build",
|
|
33
|
+
"build": "npm run clean && tsc -p tsconfig.build.json && npm run build:plugin-api && npm run build:plugins && vite build",
|
|
33
34
|
"build:plugin-api": "tsc -p tsconfig.plugin-api.json",
|
|
34
35
|
"build:plugins": "tsc -p tsconfig.plugins.json && node scripts/build-plugins.mjs",
|
|
35
36
|
"capture:screenshots": "node scripts/capture-screenshots.mjs",
|
|
36
37
|
"typecheck": "tsc --noEmit",
|
|
38
|
+
"typecheck:cached": "tsc --noEmit --incremental --tsBuildInfoFile node_modules/.cache/pi-web/typecheck.tsbuildinfo",
|
|
37
39
|
"knip": "knip",
|
|
38
40
|
"lint": "eslint \"src/**/*.ts\" \"extensions/**/*.ts\" \"pi-web-plugins/**/*.ts\" vite.config.ts vitest.config.ts",
|
|
39
41
|
"test": "vitest run --config vitest.config.ts",
|
|
40
42
|
"verify": "npm run typecheck && npm run lint && npm run knip && npm test",
|
|
43
|
+
"verify:staged": "node scripts/verify-staged.mjs",
|
|
41
44
|
"start": "tsx src/server/index.ts",
|
|
42
45
|
"start:sessiond": "tsx src/server/sessiond.ts",
|
|
43
|
-
"clean": "
|
|
46
|
+
"clean": "node -e \"require('node:fs').rmSync('dist', { recursive: true, force: true })\"",
|
|
44
47
|
"prepack": "npm run build",
|
|
45
48
|
"pack:dry": "npm pack --dry-run",
|
|
46
49
|
"prepublishOnly": "npm run verify",
|
|
@@ -51,7 +54,7 @@
|
|
|
51
54
|
"changelog:status": "changeset status"
|
|
52
55
|
},
|
|
53
56
|
"dependencies": {
|
|
54
|
-
"@codemirror/commands": "^6.10.
|
|
57
|
+
"@codemirror/commands": "^6.10.4",
|
|
55
58
|
"@codemirror/lang-css": "^6.3.1",
|
|
56
59
|
"@codemirror/lang-go": "^6.0.1",
|
|
57
60
|
"@codemirror/lang-html": "^6.4.11",
|
|
@@ -60,38 +63,39 @@
|
|
|
60
63
|
"@codemirror/lang-markdown": "^6.5.0",
|
|
61
64
|
"@codemirror/lang-python": "^6.2.1",
|
|
62
65
|
"@codemirror/lang-rust": "^6.0.2",
|
|
63
|
-
"@codemirror/language": "^6.12.
|
|
64
|
-
"@codemirror/legacy-modes": "^6.5.
|
|
65
|
-
"@codemirror/state": "^6.
|
|
66
|
-
"@codemirror/view": "^6.
|
|
67
|
-
"@fastify/
|
|
68
|
-
"@fastify/
|
|
66
|
+
"@codemirror/language": "^6.12.4",
|
|
67
|
+
"@codemirror/legacy-modes": "^6.5.3",
|
|
68
|
+
"@codemirror/state": "^6.7.1",
|
|
69
|
+
"@codemirror/view": "^6.43.6",
|
|
70
|
+
"@fastify/compress": "^9.0.0",
|
|
71
|
+
"@fastify/static": "^9.3.0",
|
|
72
|
+
"@fastify/websocket": "^11.3.0",
|
|
69
73
|
"@xterm/addon-fit": "^0.11.0",
|
|
70
74
|
"@xterm/xterm": "^6.0.0",
|
|
71
|
-
"diff": "^
|
|
72
|
-
"fastify": "^5.
|
|
73
|
-
"lit": "^3.3.
|
|
74
|
-
"marked": "^18.0.
|
|
75
|
+
"diff": "^9.0.0",
|
|
76
|
+
"fastify": "^5.10.0",
|
|
77
|
+
"lit": "^3.3.3",
|
|
78
|
+
"marked": "^18.0.6",
|
|
75
79
|
"node-pty": "^1.1.0",
|
|
76
|
-
"typebox": "1.
|
|
77
|
-
"ws": "^8.
|
|
80
|
+
"typebox": "1.3.6",
|
|
81
|
+
"ws": "^8.21.0"
|
|
78
82
|
},
|
|
79
83
|
"devDependencies": {
|
|
80
84
|
"@changesets/cli": "^2.31.0",
|
|
81
|
-
"@earendil-works/pi-agent-core": "^0.
|
|
82
|
-
"@earendil-works/pi-ai": "^0.
|
|
83
|
-
"@earendil-works/pi-coding-agent": "^0.
|
|
85
|
+
"@earendil-works/pi-agent-core": "^0.80.6",
|
|
86
|
+
"@earendil-works/pi-ai": "^0.80.6",
|
|
87
|
+
"@earendil-works/pi-coding-agent": "^0.80.6",
|
|
84
88
|
"@eslint/js": "^10.0.1",
|
|
85
|
-
"@types/node": "^24.
|
|
89
|
+
"@types/node": "^24.13.3",
|
|
86
90
|
"@types/ws": "^8.18.1",
|
|
87
|
-
"eslint": "^10.
|
|
88
|
-
"globals": "^17.
|
|
89
|
-
"knip": "^6.
|
|
90
|
-
"tsx": "^4.
|
|
91
|
-
"typescript": "^
|
|
92
|
-
"typescript-eslint": "^8.
|
|
93
|
-
"vite": "^
|
|
94
|
-
"vitest": "^4.1.
|
|
91
|
+
"eslint": "^10.6.0",
|
|
92
|
+
"globals": "^17.7.0",
|
|
93
|
+
"knip": "^6.25.0",
|
|
94
|
+
"tsx": "^4.23.0",
|
|
95
|
+
"typescript": "^6.0.3",
|
|
96
|
+
"typescript-eslint": "^8.63.0",
|
|
97
|
+
"vite": "^8.1.4",
|
|
98
|
+
"vitest": "^4.1.10"
|
|
95
99
|
},
|
|
96
100
|
"publishConfig": {
|
|
97
101
|
"access": "public"
|
|
@@ -109,9 +113,9 @@
|
|
|
109
113
|
"homepage": "https://pi-web.dev/",
|
|
110
114
|
"packageManager": "npm@11.11.0",
|
|
111
115
|
"peerDependencies": {
|
|
112
|
-
"@earendil-works/pi-agent-core": ">=0.
|
|
113
|
-
"@earendil-works/pi-ai": ">=0.
|
|
114
|
-
"@earendil-works/pi-coding-agent": ">=0.
|
|
116
|
+
"@earendil-works/pi-agent-core": ">=0.80.0 <1",
|
|
117
|
+
"@earendil-works/pi-ai": ">=0.80.0 <1",
|
|
118
|
+
"@earendil-works/pi-coding-agent": ">=0.80.0 <1"
|
|
115
119
|
},
|
|
116
120
|
"keywords": [
|
|
117
121
|
"pi-package",
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
import{v as r,J as d,$ as h,A as m,Y as g,U as f,a0 as v,V as b}from"./vendor-editor-core-C7aWiQy0.js";import{g as y,r as w,p as x,h as C,c as j,m as k,j as E,a as l}from"./vendor-editor-languages-EW34FfVy.js";import{d as H}from"./vendor-editor-legacy-B4QLsWF8.js";import{i as _,b as O,a as S,n as p,f as P,t as T}from"./index-CbE7df66.js";var A=Object.defineProperty,L=Object.getOwnPropertyDescriptor,i=(e,s,n,a)=>{for(var t=a>1?void 0:a?L(s,n):s,c=e.length-1,u;c>=0;c--)(u=e[c])&&(t=(a?u(s,n,t):u(t))||t);return a&&t&&A(s,n,t),t};let o=class extends _{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 r({parent:this.editorHost,state:d.create({doc:this.content,extensions:[h(),m.of(g),f(b,{fallback:!0}),d.readOnly.of(!0),r.editable.of(!1),r.lineWrapping,V,...F(this.language),...M(this.language)]})}))}};o.styles=S`
|
|
2
|
-
:host { display: block; min-height: 0; height: 100%; }
|
|
3
|
-
.host { height: 100%; min-height: 0; overflow: auto; }
|
|
4
|
-
`;i([p()],o.prototype,"content",2);i([p()],o.prototype,"language",2);i([P(".host")],o.prototype,"editorHost",2);o=i([T("code-viewer")],o);const V=r.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"}}),D=r.theme({".cm-content":{textAlign:"start"},".cm-line":{unicodeBidi:"plaintext"}});function F(e){return e==="markdown"?[r.contentAttributes.of({dir:"auto"}),D]:[]}function M(e){if(e===void 0)return[];switch(e){case"typescript":return[l({typescript:!0})];case"javascript":return[l()];case"json":return[E()];case"markdown":return[k()];case"css":return[j()];case"html":return[C()];case"python":return[x()];case"rust":return[w()];case"go":return[y()];case"diff":return[v.define(H)];default:return[]}}export{o as CodeViewer};
|
|
@@ -1,126 +0,0 @@
|
|
|
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,e as _,f as F,r as c}from"./index-CbE7df66.js";import{D as S,o as T}from"./vendor-terminal-DjQ08hXu.js";import"./vendor-editor-core-C7aWiQy0.js";import"./vendor-editor-languages-EW34FfVy.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 H(e=$()){return z(O(),M(e))}function B(){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,n)=>{for(var r=n>1?void 0:n?X(t,i):t,a=e.length-1,u;a>=0;a--)(u=e[a])&&(r=(n?u(t,i,r):u(r))||r);return n&&r&&W(t,i,r),r};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
|
-
<div class="terminal-soft-keys" role="toolbar" aria-label="Terminal soft keys">
|
|
3
|
-
${U.map(e=>l`
|
|
4
|
-
<button
|
|
5
|
-
type="button"
|
|
6
|
-
class="soft-key"
|
|
7
|
-
title=${e.title}
|
|
8
|
-
aria-label=${e.ariaLabel}
|
|
9
|
-
@pointerdown=${t=>{this.onSoftKeyPointerDown(t,e)}}
|
|
10
|
-
@pointermove=${t=>{this.onSoftKeyPointerMove(t)}}
|
|
11
|
-
@pointerup=${t=>{this.onSoftKeyPointerUp(t,e)}}
|
|
12
|
-
@pointercancel=${t=>{this.onSoftKeyPointerCancel(t)}}
|
|
13
|
-
@click=${t=>{this.onSoftKeyClick(t,e)}}
|
|
14
|
-
>${e.label}</button>
|
|
15
|
-
`)}
|
|
16
|
-
</div>
|
|
17
|
-
`}};f.styles=E`
|
|
18
|
-
:host { flex: 0 0 auto; display: block; }
|
|
19
|
-
.terminal-soft-keys { display: flex; gap: 6px; align-items: center; padding: 6px; border-bottom: 1px solid var(--pi-border-muted); background: var(--pi-bg); overflow-x: auto; overscroll-behavior-x: contain; scrollbar-width: none; touch-action: pan-x; }
|
|
20
|
-
.terminal-soft-keys::-webkit-scrollbar { display: none; }
|
|
21
|
-
button { display: inline-flex; align-items: center; gap: 6px; flex: 0 0 auto; max-width: none; min-height: 34px; border: 1px solid var(--pi-border); border-radius: 7px; background: var(--pi-surface); color: var(--pi-text); padding: 6px 9px; font: 12px ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; cursor: pointer; touch-action: pan-x; -webkit-touch-callout: none; user-select: none; }
|
|
22
|
-
button:disabled { opacity: .5; cursor: not-allowed; }
|
|
23
|
-
`;y([m({attribute:!1})],f.prototype,"modes",2);y([m({type:Boolean})],f.prototype,"refocusOnClick",2);y([m({attribute:!1})],f.prototype,"onInput",2);f=y([R("terminal-soft-keys")],f);function I(e,t){return Math.hypot(t.clientX-e.clientX,t.clientY-e.clientY)>J}var G=Object.defineProperty,Q=Object.getOwnPropertyDescriptor,s=(e,t,i,n)=>{for(var r=n>1?void 0:n?Q(t,i):t,a=e.length-1,u;a>=0;a--)(u=e[a])&&(r=(n?u(t,i,r):u(r))||r);return n&&r&&G(t,i,r),r};const ee={cursorBlink:!0,convertEol:!0,fontFamily:"ui-monospace, SFMono-Regular, Menlo, Consolas, monospace",fontSize:13},te={cols:100,rows:30},ie=1e3;let o=class extends K{constructor(){super(...arguments),this.machineId="local",this.autoStart=!1,this.onSelectTerminal=()=>{},this.terminals=[],this.commandRuns=[],this.loading=!1,this.visible=!1,this.cancellingRunIds=[],this.continuingTerminalIds=[],this.defaultSoftKeysEnvironment=!1,this.softKeysEnabled=H(),this.suppressTerminalInput=!1,this.softKeysDefaultEnvironmentMedia=$(),this.softKeysPreferenceStored=B(),this.onSoftKeysDefaultEnvironmentChange=()=>{this.syncDefaultSoftKeysEnvironment()}}connectedCallback(){super.connectedCallback(),this.syncDefaultSoftKeysEnvironment(),this.softKeysDefaultEnvironmentMedia?.addEventListener("change",this.onSoftKeysDefaultEnvironmentChange),this.themeObserver=new MutationObserver(()=>{this.applyTerminalTheme()}),this.themeObserver.observe(document.documentElement,{attributes:!0,attributeFilter:["class","style","data-theme"]})}firstUpdated(){this.intersectionObserver=new IntersectionObserver(e=>{this.visible=e[0]?.isIntersecting===!0}),this.intersectionObserver.observe(this)}disconnectedCallback(){this.intersectionObserver?.disconnect(),this.intersectionObserver=void 0,this.themeObserver?.disconnect(),this.themeObserver=void 0,this.softKeysDefaultEnvironmentMedia?.removeEventListener("change",this.onSoftKeysDefaultEnvironmentChange),this.updateCommandRunPolling(!1),this.disposeTerminalView(),super.disconnectedCallback()}syncDefaultSoftKeysEnvironment(){const e=M(this.softKeysDefaultEnvironmentMedia),t=this.softKeysEnabled;this.defaultSoftKeysEnvironment=e,this.softKeysPreferenceStored||(this.softKeysEnabled=e),this.softKeysEnabled!==t&&this.scheduleFitAndNotify()}scheduleFitAndNotify(){this.updateComplete.then(()=>{this.fitAndNotify()})}willUpdate(e){const t=this.workspace===void 0?void 0:JSON.stringify([this.machineId,this.workspace.path]);if(t!==this.observedWorkspaceScope){this.observedWorkspaceScope=t,this.loadedCwd=void 0,this.autoStartConsumedCwd=void 0,this.terminals=[],this.commandRuns=[],this.selectedId=void 0,this.cancellingRunIds=[],this.continuingTerminalIds=[],this.updateCommandRunPolling(!1),this.disposeTerminalView();return}if(e.has("selectedTerminalId")){if(e.get("selectedTerminalId")!==void 0&&this.selectedTerminalId===void 0){this.loadedCwd=void 0,this.selectTerminalIdInView(void 0);return}this.applyRequestedTerminalSelection()}}updated(e){this.visible?this.hasPendingCommandRuns()&&this.updateCommandRunPolling(!0):this.updateCommandRunPolling(!1),this.loadVisibleWorkspaceTerminals(),e.has("selectedTerminalId")&&this.shouldReloadForRequestedTerminal()&&this.loadTerminals(),this.ensureTerminalView()}loadVisibleWorkspaceTerminals(){const e=this.workspace?.path;!this.visible||e===void 0||e===this.loadedCwd||(this.loadedCwd=e,this.loadTerminals())}async loadTerminals(){this.loading=!0,this.error=void 0;try{const e=this.workspace;if(e===void 0)return;const t=this.consumeAutoStart(),[i,n]=await Promise.all([h.terminals(e.projectId,e.id,this.machineId),h.listCommandRuns({projectId:e.projectId,workspaceId:e.id},this.machineId)]);this.terminals=i,this.commandRuns=n,this.selectPreferredLoadedTerminal({replaceUrl:!0}),this.updateCommandRunPolling(this.hasPendingCommandRuns(n)),i.length===0&&t&&await this.startTerminal()}catch(e){this.error=e instanceof Error?e.message:String(e)}finally{this.loading=!1}}applyRequestedTerminalSelection(){this.selectedTerminalId!==void 0&&!this.terminals.some(e=>e.id===this.selectedTerminalId)||this.selectPreferredLoadedTerminal({replaceUrl:!0})}consumeAutoStart(){const e=this.workspace?.path;return!this.autoStart||e===void 0||this.autoStartConsumedCwd===e?!1:(this.autoStartConsumedCwd=e,!0)}shouldReloadForRequestedTerminal(){const e=this.workspace?.path;return this.visible&&e!==void 0&&e===this.loadedCwd&&this.selectedTerminalId!==void 0&&!this.loading&&!this.terminals.some(t=>t.id===this.selectedTerminalId)}selectPreferredLoadedTerminal(e){let t=A(this.terminals,{targetTerminalId:this.selectedTerminalId});t===void 0&&this.selectedTerminalId!==void 0&&(t=w(this.terminals)),this.selectTerminalIdInView(t?.id),(t?.id!==this.selectedTerminalId||t===void 0&&this.selectedTerminalId!==void 0)&&this.onSelectTerminal(t?.id,{replace:e?.replaceUrl===!0})}selectTerminalIdInView(e){this.selectedId!==e&&(this.selectedId=e,this.disposeTerminalView())}async startTerminal(){if(this.workspace!==void 0){this.error=void 0;try{const e=this.measureTerminalSize()??te,t=await h.startTerminal(this.workspace.projectId,this.workspace.id,e,this.machineId);this.terminals=[...this.terminals,t],this.selectTerminal(t.id)}catch(e){this.error=e instanceof Error?e.message:String(e)}}}async closeTerminal(e,t){t.stopPropagation();try{if(this.workspace===void 0)return;await h.closeTerminal(this.workspace.projectId,this.workspace.id,e,this.machineId);const i=this.terminals.filter(n=>n.id!==e);if(this.terminals=i,this.selectedId===e||this.selectedTerminalId===e){const n=w(i)?.id;this.selectTerminalIdInView(n),this.onSelectTerminal(n,{replace:!0})}}catch(i){this.error=i instanceof Error?i.message:String(i)}}selectTerminal(e){this.selectedId!==e&&this.selectTerminalIdInView(e),this.onSelectTerminal(e)}selectedTerminalInfo(){return this.terminals.find(e=>e.id===this.selectedId)}selectedCommandRun(){const e=this.selectedTerminalInfo()?.commandRunId;if(e!==void 0)return this.commandRuns.find(t=>t.id===e)}async loadCommandRuns(){const e=this.workspace;if(e!==void 0)try{const t=await h.listCommandRuns({projectId:e.projectId,workspaceId:e.id},this.machineId);this.commandRuns=t,this.cancellingRunIds=this.cancellingRunIds.filter(i=>t.some(n=>n.id===i&&v(n))),this.updateCommandRunPolling(this.hasPendingCommandRuns(t))}catch(t){this.error=t instanceof Error?t.message:String(t)}}updateCommandRunPolling(e){if(e&&this.commandRunPollTimer===void 0){this.commandRunPollTimer=window.setInterval(()=>{this.loadCommandRuns()},ie);return}!e&&this.commandRunPollTimer!==void 0&&(window.clearInterval(this.commandRunPollTimer),this.commandRunPollTimer=void 0)}hasPendingCommandRuns(e=this.commandRuns){return e.some(v)}async cancelCommandRun(e){if(!(!v(e)||this.cancellingRunIds.includes(e.id))){this.error=void 0,this.cancellingRunIds=[...this.cancellingRunIds,e.id];try{await h.cancelCommandRun(e.id,this.machineId),await this.loadCommandRuns()}catch(t){this.error=t instanceof Error?t.message:String(t)}finally{this.cancellingRunIds=this.cancellingRunIds.filter(t=>t!==e.id)}}}async continueTerminal(e){if(!(this.workspace===void 0||this.continuingTerminalIds.includes(e))){this.error=void 0,this.continuingTerminalIds=[...this.continuingTerminalIds,e];try{const t=await h.continueTerminal(this.workspace.projectId,this.workspace.id,e,this.machineId);this.terminals=this.terminals.map(i=>i.id===e?t:i),this.socket===void 0&&this.disposeTerminalView(),this.fitAndNotify(),this.terminal?.focus()}catch(t){this.error=t instanceof Error?t.message:String(t)}finally{this.continuingTerminalIds=this.continuingTerminalIds.filter(t=>t!==e)}}}ensureTerminalView(){const e=this.workspace,t=this.terminalHostElement();if(!this.visible||this.terminal!==void 0||this.selectedId===void 0||t===void 0||e===void 0)return;const i=new S(C(this)),n=new T;i.loadAddon(n),i.open(t),this.terminal=i,this.fitAddon=n,this.resizeObserver=new ResizeObserver(()=>{this.fitAndNotify()}),this.resizeObserver.observe(t),i.onData(a=>{this.suppressTerminalInput||this.sendTerminalInput(a)});const r=this.fitTerminal();this.connectSocket(e.projectId,e.id,this.selectedId,i,r),requestAnimationFrame(()=>{this.fitAndNotify()}),i.focus()}connectSocket(e,t,i,n,r){const a=_(e,t,i,r,this.machineId);a.binaryType="arraybuffer",this.socket=a,a.addEventListener("open",()=>{this.fitAndNotify()}),a.addEventListener("message",u=>{this.handleSocketMessage(u.data,i,n)}),a.addEventListener("close",()=>{this.socket===a&&(this.socket=void 0)})}async handleSocketMessage(e,t,i){try{const n=re(await se(e));n.type==="output"&&this.writeTerminalOutput(i,n.data,n.replay===!0),n.type==="exit"&&(i.writeln(`\r
|
|
24
|
-
[process exited${n.exitCode===void 0?"":` with code ${String(n.exitCode)}`}]`),this.terminals=this.terminals.map(r=>r.id===t?{...r,exited:!0,...n.exitCode===void 0?{}:{exitCode:n.exitCode}}:r),this.loadCommandRuns()),n.type==="error"&&i.writeln(`\r
|
|
25
|
-
[terminal error: ${n.message}]`)}catch(n){i.writeln(`\r
|
|
26
|
-
[terminal error: ${n instanceof Error?n.message:String(n)}]`)}}writeTerminalOutput(e,t,i){if(!i){e.write(t);return}this.suppressTerminalInput=!0,e.write(t,()=>{this.suppressTerminalInput=!1})}fitAndNotify(){const e=this.fitTerminal();e!==void 0&&this.send({type:"resize",...e})}fitTerminal(){if(this.fitAddon===void 0||this.terminal===void 0)return;const e=this.fitAddon.proposeDimensions(),t=k(e);if(t!==void 0)return this.fitAddon.fit(),t}measureTerminalSize(){const e=this.fitTerminal();if(e!==void 0)return e;const t=this.terminalHostElement();if(this.terminal!==void 0||t===void 0)return;const i=new S(C(this)),n=new T;i.loadAddon(n),i.open(t);const r=k(n.proposeDimensions());return i.dispose(),r}terminalHostElement(){const e=this.terminalHost;return e instanceof HTMLDivElement?e:void 0}applyTerminalTheme(){this.terminal!==void 0&&(this.terminal.options.theme=L(this))}sendTerminalInput(e){const t=oe(e);t!==""&&this.send({type:"input",data:t})}sendSoftKeyInput(e,t){this.sendTerminalInput(e),t.refocus&&this.focusTerminal()}focusTerminal(){const e=this.terminal;e!==void 0&&(e.focus(),requestAnimationFrame(()=>{e.focus()}))}send(e){this.socket?.readyState===WebSocket.OPEN&&this.socket.send(JSON.stringify(e))}disposeTerminalView(){this.resizeObserver?.disconnect(),this.resizeObserver=void 0,this.socket?.close(),this.socket=void 0,this.terminal?.dispose(),this.terminal=void 0,this.fitAddon=void 0}renderCommandRunNotice(){const e=this.selectedCommandRun();if(e===void 0)return null;const t=this.selectedTerminalInfo();if(v(e)){const i=this.cancellingRunIds.includes(e.id);return l`
|
|
27
|
-
<section class="command-run-notice running">
|
|
28
|
-
<div>
|
|
29
|
-
<strong>${e.title}</strong>
|
|
30
|
-
<p>Command is running. Press <kbd>Ctrl</kbd>+<kbd>C</kbd> or use the button to cancel.</p>
|
|
31
|
-
<code>${e.command}</code>
|
|
32
|
-
</div>
|
|
33
|
-
<button class="danger" ?disabled=${i} @click=${()=>{this.cancelCommandRun(e)}}>${i?"Cancel sent…":"Cancel command"}</button>
|
|
34
|
-
</section>
|
|
35
|
-
`}if(t?.exited===!0){const i=this.continuingTerminalIds.includes(t.id);return l`
|
|
36
|
-
<section class=${`command-run-notice ${e.status}`}>
|
|
37
|
-
<div>
|
|
38
|
-
<strong>${ne(e)}</strong>
|
|
39
|
-
<p>Output is preserved. Continue in a shell to inspect or run follow-up commands.</p>
|
|
40
|
-
<code>${e.command}</code>
|
|
41
|
-
</div>
|
|
42
|
-
<button ?disabled=${i} @click=${()=>{this.continueTerminal(t.id)}}>${i?"Starting shell…":"Continue in shell"}</button>
|
|
43
|
-
</section>
|
|
44
|
-
`}return null}selectedTerminalAcceptsInput(){const e=this.selectedTerminalInfo();return e!==void 0&&!e.exited}shouldShowSoftKeys(){return this.selectedTerminalAcceptsInput()&&this.softKeysEnabled}shouldShowSoftKeysToggle(){return this.selectedTerminalAcceptsInput()}toggleSoftKeys(){this.softKeysEnabled=!this.softKeysEnabled,this.softKeysPreferenceStored=!0,j(this.softKeysEnabled),this.scheduleFitAndNotify()}renderSoftKeysToggle(){return this.shouldShowSoftKeysToggle()?l`
|
|
45
|
-
<button
|
|
46
|
-
type="button"
|
|
47
|
-
class=${this.softKeysEnabled?"soft-keys-toggle selected":"soft-keys-toggle"}
|
|
48
|
-
title=${this.softKeysEnabled?"Hide terminal soft keys":"Show terminal soft keys"}
|
|
49
|
-
aria-label=${this.softKeysEnabled?"Hide terminal soft keys":"Show terminal soft keys"}
|
|
50
|
-
aria-pressed=${String(this.softKeysEnabled)}
|
|
51
|
-
@click=${()=>{this.toggleSoftKeys()}}
|
|
52
|
-
>
|
|
53
|
-
<svg class="keyboard-icon" viewBox="0 0 24 24" aria-hidden="true" focusable="false">
|
|
54
|
-
<rect x="3" y="5" width="18" height="14" rx="2"></rect>
|
|
55
|
-
<path d="M7 9h.01M10 9h.01M13 9h.01M16 9h.01M7 12h.01M10 12h.01M13 12h.01M16 12h.01M8 16h8"></path>
|
|
56
|
-
</svg>
|
|
57
|
-
<span>Keys</span>
|
|
58
|
-
</button>
|
|
59
|
-
`:null}renderSoftKeys(){return l`
|
|
60
|
-
<terminal-soft-keys
|
|
61
|
-
.modes=${this.terminal?.modes}
|
|
62
|
-
.refocusOnClick=${!this.defaultSoftKeysEnvironment}
|
|
63
|
-
.onInput=${(e,t)=>{this.sendSoftKeyInput(e,t)}}
|
|
64
|
-
></terminal-soft-keys>
|
|
65
|
-
`}render(){return l`
|
|
66
|
-
<section class="terminal-shell">
|
|
67
|
-
<div class="terminal-tabs">
|
|
68
|
-
${this.renderSoftKeysToggle()}
|
|
69
|
-
${this.terminals.map(e=>l`
|
|
70
|
-
<button class=${this.selectedId===e.id?"selected":""} @click=${()=>{this.selectTerminal(e.id)}}>
|
|
71
|
-
<span>${e.name}${e.exited?" · exited":""}</span>
|
|
72
|
-
<small @click=${t=>{this.closeTerminal(e.id,t)}}>×</small>
|
|
73
|
-
</button>
|
|
74
|
-
`)}
|
|
75
|
-
<button class="new" ?disabled=${this.workspace===void 0} @click=${()=>{this.startTerminal()}}>+ Shell</button>
|
|
76
|
-
</div>
|
|
77
|
-
${this.error===void 0?null:l`<p class="error">${this.error}</p>`}
|
|
78
|
-
${this.renderCommandRunNotice()}
|
|
79
|
-
${this.shouldShowSoftKeys()?this.renderSoftKeys():null}
|
|
80
|
-
${this.loading?l`<p class="muted">Loading terminals…</p>`:null}
|
|
81
|
-
<div class="terminal-host"></div>
|
|
82
|
-
</section>
|
|
83
|
-
`}};o.styles=E`
|
|
84
|
-
:host { flex: 1 1 auto; min-height: 0; display: flex; }
|
|
85
|
-
.terminal-shell { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; overflow: hidden; background: var(--pi-terminal-bg); }
|
|
86
|
-
.terminal-tabs { flex: 0 0 auto; display: flex; gap: 6px; align-items: center; padding: 6px; border-bottom: 1px solid var(--pi-border-muted); background: var(--pi-bg); overflow: auto; }
|
|
87
|
-
button { display: inline-flex; align-items: center; gap: 6px; min-width: 0; max-width: 180px; border: 1px solid var(--pi-border); border-radius: 7px; background: var(--pi-surface); color: var(--pi-text); padding: 5px 7px; cursor: pointer; }
|
|
88
|
-
button.selected { border-color: var(--pi-accent); background: var(--pi-selection-bg); }
|
|
89
|
-
button.new { flex: 0 0 auto; color: var(--pi-muted); }
|
|
90
|
-
.soft-keys-toggle { flex: 0 0 auto; }
|
|
91
|
-
.soft-keys-toggle .keyboard-icon { flex: 0 0 auto; width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; pointer-events: none; }
|
|
92
|
-
button span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
93
|
-
button small { color: var(--pi-muted); font-size: 14px; line-height: 1; }
|
|
94
|
-
button small:hover { color: var(--pi-danger); }
|
|
95
|
-
button.danger { color: var(--pi-danger); }
|
|
96
|
-
button:disabled { opacity: .5; cursor: not-allowed; }
|
|
97
|
-
.command-run-notice { flex: 0 0 auto; display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 10px; align-items: center; padding: 8px 10px; border-bottom: 1px solid var(--pi-border-muted); background: var(--pi-surface); color: var(--pi-text); }
|
|
98
|
-
.command-run-notice.running { border-color: var(--pi-warning-border); }
|
|
99
|
-
.command-run-notice.succeeded { border-color: var(--pi-success-border); }
|
|
100
|
-
.command-run-notice.failed { border-color: var(--pi-danger); }
|
|
101
|
-
.command-run-notice p { margin: 3px 0; color: var(--pi-muted); }
|
|
102
|
-
.command-run-notice code { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--pi-text-secondary); font: 12px ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; }
|
|
103
|
-
.command-run-notice kbd { border: 1px solid var(--pi-border); border-radius: 4px; background: var(--pi-bg); padding: 0 4px; font: 11px ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; }
|
|
104
|
-
.command-run-notice button { justify-self: end; max-width: none; }
|
|
105
|
-
.terminal-host { flex: 1 1 auto; min-height: 0; padding: 6px; box-sizing: border-box; overflow: hidden; }
|
|
106
|
-
.terminal-host .xterm { height: 100%; cursor: text; position: relative; user-select: none; }
|
|
107
|
-
.terminal-host .xterm.focus, .terminal-host .xterm:focus { outline: none; }
|
|
108
|
-
.terminal-host .xterm-helpers { position: absolute; top: 0; z-index: 5; }
|
|
109
|
-
/* Hide the helper textarea without using !important on the positional properties (left/top/width/height/z-index). xterm sets those inline during IME/dead-key composition (e.g. "~" on a Swedish layout) so the composition is positioned at the cursor and committed correctly; forcing them here would pin the textarea off-screen with zero size and break composition. */
|
|
110
|
-
.terminal-host .xterm-helper-textarea { position: absolute; left: -9999em; top: 0; width: 0; height: 0; padding: 0 !important; border: 0 !important; margin: 0 !important; opacity: 0 !important; z-index: -5; white-space: nowrap !important; overflow: hidden !important; resize: none !important; outline: 0 !important; appearance: none !important; }
|
|
111
|
-
/* The composition view shows pending dead-key/IME input. Without these rules it renders as a static block in the top-left corner instead of overlaying the cursor. */
|
|
112
|
-
.terminal-host .composition-view { position: absolute; display: none; white-space: nowrap; z-index: 1; background: var(--pi-terminal-bg, #000); color: var(--pi-terminal-text, #fff); }
|
|
113
|
-
.terminal-host .composition-view.active { display: block; }
|
|
114
|
-
.terminal-host .xterm-viewport { position: absolute; inset: 0; overflow-y: scroll; cursor: default; background-color: var(--pi-terminal-bg); }
|
|
115
|
-
.terminal-host .xterm-screen { position: relative; }
|
|
116
|
-
.terminal-host .xterm-screen canvas { position: absolute; left: 0; top: 0; }
|
|
117
|
-
.terminal-host .xterm-char-measure-element { display: inline-block; visibility: hidden; position: absolute; top: 0; left: -9999em; line-height: normal; }
|
|
118
|
-
.terminal-host .xterm-accessibility:not(.debug), .terminal-host .xterm-message { position: absolute; inset: 0; z-index: 10; color: transparent; pointer-events: none; }
|
|
119
|
-
.terminal-host .xterm-accessibility-tree:not(.debug) *::selection { color: transparent; }
|
|
120
|
-
.terminal-host .xterm-accessibility-tree { font-family: monospace; user-select: text; white-space: pre; }
|
|
121
|
-
.terminal-host .xterm-accessibility-tree > div { transform-origin: left; width: fit-content; }
|
|
122
|
-
.terminal-host .live-region { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }
|
|
123
|
-
.error { flex: 0 0 auto; margin: 0; padding: 8px; color: var(--pi-danger); border-bottom: 1px solid var(--pi-border); background: var(--pi-surface); }
|
|
124
|
-
.muted { margin: 10px; color: var(--pi-muted); }
|
|
125
|
-
.xterm { height: 100%; }
|
|
126
|
-
`;s([m({attribute:!1})],o.prototype,"workspace",2);s([m()],o.prototype,"machineId",2);s([m({attribute:!1})],o.prototype,"selectedTerminalId",2);s([m({type:Boolean})],o.prototype,"autoStart",2);s([m({attribute:!1})],o.prototype,"onSelectTerminal",2);s([F(".terminal-host")],o.prototype,"terminalHost",2);s([c()],o.prototype,"terminals",2);s([c()],o.prototype,"commandRuns",2);s([c()],o.prototype,"selectedId",2);s([c()],o.prototype,"loading",2);s([c()],o.prototype,"error",2);s([c()],o.prototype,"visible",2);s([c()],o.prototype,"cancellingRunIds",2);s([c()],o.prototype,"continuingTerminalIds",2);s([c()],o.prototype,"defaultSoftKeysEnvironment",2);s([c()],o.prototype,"softKeysEnabled",2);o=s([R("terminal-panel")],o);function v(e){return e.status==="queued"||e.status==="running"}function ne(e){return e.status==="succeeded"?`Command succeeded${e.exitCode===void 0?"":` with exit code ${String(e.exitCode)}`}`:`Command failed${e.exitCode===void 0?"":` with exit code ${String(e.exitCode)}`}`}function re(e){const t=JSON.parse(e);if(!le(t))return{type:"error",message:"Invalid terminal message"};const i=t;return i.type==="output"&&typeof i.data=="string"?{type:"output",data:i.data,...typeof i.replay=="boolean"?{replay:i.replay}:{}}:i.type==="exit"?{type:"exit",...typeof i.exitCode=="number"?{exitCode:i.exitCode}:{}}:i.type==="error"&&typeof i.message=="string"?{type:"error",message:i.message}:{type:"error",message:"Invalid terminal message"}}function oe(e){return e.replaceAll("\x1B[I","").replaceAll("\x1B[O","")}async function se(e){return typeof e=="string"?e:e instanceof ArrayBuffer?new TextDecoder().decode(e):e instanceof Blob?await e.text():String(e)}function C(e){return{...ee,theme:L(e)}}function L(e){return{background:g(e,"--pi-terminal-bg","#05070a"),foreground:g(e,"--pi-terminal-text","#e6edf3"),cursor:g(e,"--pi-accent","#58a6ff"),selectionBackground:g(e,"--pi-terminal-selection","#264f78")}}function g(e,t,i){const n=getComputedStyle(e).getPropertyValue(t).trim();return n===""?i:n}function k(e){if(!(e===void 0||!ae(e.cols,e.rows)))return{cols:Math.floor(e.cols),rows:Math.floor(e.rows)}}function ae(e,t){return Number.isFinite(e)&&Number.isFinite(t)&&e>0&&t>0}function le(e){return typeof e=="object"&&e!==null}export{o as TerminalPanel,oe as filterTerminalInput};
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import{i as A,b as P,a as V,n as z,t as F}from"./index-CbE7df66.js";import"./vendor-editor-core-C7aWiQy0.js";import"./vendor-editor-languages-EW34FfVy.js";class U{diff(e,t,i={}){let o;typeof i=="function"?(o=i,i={}):"callback"in i&&(o=i.callback);const r=this.castInput(e,i),s=this.castInput(t,i),u=this.removeEmpty(this.tokenize(r,i)),l=this.removeEmpty(this.tokenize(s,i));return this.diffWithOptionsObj(u,l,i,o)}diffWithOptionsObj(e,t,i,o){var r;const s=c=>{if(c=this.postProcess(c,i),o){setTimeout(function(){o(c)},0);return}else return c},u=t.length,l=e.length;let d=1,a=u+l;i.maxEditLength!=null&&(a=Math.min(a,i.maxEditLength));const g=(r=i.timeout)!==null&&r!==void 0?r:1/0,v=Date.now()+g,f=[{oldPos:-1,lastComponent:void 0}];let h=this.extractCommon(f[0],t,e,0,i);if(f[0].oldPos+1>=l&&h+1>=u)return s(this.buildValues(f[0].lastComponent,t,e));let w=-1/0,y=1/0;const $=()=>{for(let c=Math.max(w,-d);c<=Math.min(y,d);c+=2){let p;const x=f[c-1],b=f[c+1];x&&(f[c-1]=void 0);let D=!1;if(b){const S=b.oldPos-c;D=b&&0<=S&&S<u}const k=x&&x.oldPos+1<l;if(!D&&!k){f[c]=void 0;continue}if(!k||D&&x.oldPos<b.oldPos?p=this.addToPath(b,!0,!1,0,i):p=this.addToPath(x,!1,!0,1,i),h=this.extractCommon(p,t,e,c,i),p.oldPos+1>=l&&h+1>=u)return s(this.buildValues(p.lastComponent,t,e))||!0;f[c]=p,p.oldPos+1>=l&&(y=Math.min(y,c-1)),h+1>=u&&(w=Math.max(w,c+1))}d++};if(o)(function c(){setTimeout(function(){if(d>a||Date.now()>v)return o(void 0);$()||c()},0)})();else for(;d<=a&&Date.now()<=v;){const c=$();if(c)return c}}addToPath(e,t,i,o,r){const s=e.lastComponent;return s&&!r.oneChangePerToken&&s.added===t&&s.removed===i?{oldPos:e.oldPos+o,lastComponent:{count:s.count+1,added:t,removed:i,previousComponent:s.previousComponent}}:{oldPos:e.oldPos+o,lastComponent:{count:1,added:t,removed:i,previousComponent:s}}}extractCommon(e,t,i,o,r){const s=t.length,u=i.length;let l=e.oldPos,d=l-o,a=0;for(;d+1<s&&l+1<u&&this.equals(i[l+1],t[d+1],r);)d++,l++,a++,r.oneChangePerToken&&(e.lastComponent={count:1,previousComponent:e.lastComponent,added:!1,removed:!1});return a&&!r.oneChangePerToken&&(e.lastComponent={count:a,previousComponent:e.lastComponent,added:!1,removed:!1}),e.oldPos=l,d}equals(e,t,i){return i.comparator?i.comparator(e,t):e===t||!!i.ignoreCase&&e.toLowerCase()===t.toLowerCase()}removeEmpty(e){const t=[];for(let i=0;i<e.length;i++)e[i]&&t.push(e[i]);return t}castInput(e,t){return e}tokenize(e,t){return Array.from(e)}join(e){return e.join("")}postProcess(e,t){return e}get useLongestToken(){return!1}buildValues(e,t,i){const o=[];let r;for(;e;)o.push(e),r=e.previousComponent,delete e.previousComponent,e=r;o.reverse();const s=o.length;let u=0,l=0,d=0;for(;u<s;u++){const a=o[u];if(a.removed)a.value=this.join(i.slice(d,d+a.count)),d+=a.count;else{if(!a.added&&this.useLongestToken){let g=t.slice(l,l+a.count);g=g.map(function(v,f){const h=i[d+f];return h.length>v.length?h:v}),a.value=this.join(g)}else a.value=this.join(t.slice(l,l+a.count));l+=a.count,a.added||(d+=a.count)}}return o}}class R extends U{}const q=new R;function j(n,e,t){return q.diff(n,e,t)}const B=/^@@ -(\d+)(?:,\d+)? \+(\d+)(?:,\d+)? @@/,C=5e3,H=20,G=.2,E=.25;function J(n){const e=K(n);return X(e),e}function K(n){const e=Q(n),t=[];let i,o;for(const r of e){const s=B.exec(r);if(s!==null){i=Number(s[1]),o=Number(s[2]),t.push(m("hunk","",r));continue}if(i!==void 0&&o!==void 0){if(r.startsWith("+")){t.push(m("add","+",r.slice(1),{newLineNumber:o})),o++;continue}if(r.startsWith("-")){t.push(m("remove","-",r.slice(1),{oldLineNumber:i})),i++;continue}if(r.startsWith(" ")){t.push(m("context"," ",r.slice(1),{oldLineNumber:i,newLineNumber:o})),i++,o++;continue}if(r.startsWith("\\")){t.push(m("marker","",r));continue}}i=void 0,o=void 0,t.push(m("meta","",r))}return t}function Q(n){if(n==="")return[];const e=n.replace(/\r\n/g,`
|
|
2
|
-
`).replace(/\r/g,`
|
|
3
|
-
`).split(`
|
|
4
|
-
`);return e.at(-1)===""&&e.pop(),e}function m(n,e,t,i={}){return{kind:n,prefix:e,text:t,spans:t===""?[]:[{text:t,changed:!1}],...i}}function X(n){let e=0;for(;e<n.length;){if(n[e]?.kind!=="remove"){e++;continue}const i=e;for(;n[e]?.kind==="remove";)e++;const o=e;for(;n[e]?.kind==="add";)e++;if(o===e)continue;const r=n.slice(i,o),s=n.slice(o,e);Y(r,s)}}function Y(n,e){if(!(n.length+e.length>H))for(const t of Z(n,e)){const i=te(t.removed.text,t.added.text);i!==void 0&&(t.removed.spans=i.removed,t.added.spans=i.added)}}function Z(n,e){if(n.length===e.length)return n.map((o,r)=>({removed:o,added:e[r]})).filter(T);if(n.length===1)return ee(n[0],e);if(e.length===1)return ne(n,e[0]);const t=[],i=Math.min(n.length,e.length);for(let o=0;o<i;o++){const r=n[o],s=e[o];r===void 0||s===void 0||O(r.text,s.text)>=E&&t.push({removed:r,added:s})}return t}function T(n){return n.added!==void 0}function ee(n,e){if(n===void 0)return[];const t=N(n.text,e);return t===void 0?[]:[{removed:n,added:t}]}function ne(n,e){if(e===void 0)return[];const t=N(e.text,n);return t===void 0?[]:[{removed:t,added:e}]}function N(n,e){let t,i=E;for(const o of e){const r=O(n,o.text);r<=i||(t=o,i=r)}return t}function te(n,e){if(n===e||n.length>C||e.length>C)return;const t=j(n,e),i=_(t,n,e);if(Math.max(n.length,e.length)>=20&&i<G)return;const o=[],r=[];for(const s of t)s.value!==""&&(s.added?r.push({text:s.value,changed:!0}):s.removed?o.push({text:s.value,changed:!0}):(o.push({text:s.value,changed:!1}),r.push({text:s.value,changed:!1})));if(!(!o.some(s=>s.changed)&&!r.some(s=>s.changed)))return{removed:M(o),added:M(r)}}function O(n,e){return n===e?1:n.length>C||e.length>C?0:_(j(n,e),n,e)}function _(n,e,t){const i=Math.max(e.length,t.length);return i===0?1:n.reduce((r,s)=>s.added||s.removed?r:r+s.value.length,0)/i}function M(n){const e=[];for(const t of n){const i=e[e.length-1];i?.changed===t.changed?i.text+=t.text:e.push({...t})}return e}var ie=Object.defineProperty,oe=Object.getOwnPropertyDescriptor,W=(n,e,t,i)=>{for(var o=i>1?void 0:i?oe(e,t):e,r=n.length-1,s;r>=0;r--)(s=n[r])&&(o=(i?s(e,t,o):s(o))||o);return i&&o&&ie(e,t,o),o};let L=class extends A{constructor(){super(...arguments),this.diff=""}render(){const n=J(this.diff);return n.length===0?P`<p class="empty">No diff.</p>`:P`
|
|
5
|
-
<div class="scroller">
|
|
6
|
-
<div class="diff-grid" role="table" aria-label="Unified diff">
|
|
7
|
-
${n.map(e=>this.renderLine(e))}
|
|
8
|
-
</div>
|
|
9
|
-
</div>
|
|
10
|
-
`}renderLine(n){const e=n.kind;return P`
|
|
11
|
-
<div class="line" role="row">
|
|
12
|
-
<span class=${`cell line-number old ${e}`} role="cell">${I(n.oldLineNumber)}</span>
|
|
13
|
-
<span class=${`cell line-number new ${e}`} role="cell">${I(n.newLineNumber)}</span>
|
|
14
|
-
<span class=${`cell prefix ${e}`} role="cell">${n.prefix}</span>
|
|
15
|
-
<span class=${`cell content ${e}`} role="cell">${re(n.spans)}</span>
|
|
16
|
-
</div>
|
|
17
|
-
`}};L.styles=V`
|
|
18
|
-
:host { display: block; min-height: 0; height: 100%; color: var(--pi-text); background: var(--pi-bg); }
|
|
19
|
-
.empty { box-sizing: border-box; margin: 0; padding: 10px; color: var(--pi-muted); }
|
|
20
|
-
.scroller { height: 100%; min-height: 0; overflow: auto; background: var(--pi-bg); }
|
|
21
|
-
.diff-grid { display: grid; grid-template-columns: max-content max-content 2ch max-content; width: max-content; min-width: 100%; padding: 6px 0; font: 12px ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; line-height: 1.45; }
|
|
22
|
-
.line { display: contents; }
|
|
23
|
-
.cell { min-height: 1.45em; white-space: pre; }
|
|
24
|
-
.line-number { min-width: 4ch; padding: 0 8px; border-right: 1px solid var(--pi-border-muted); color: var(--pi-dim); text-align: right; user-select: none; }
|
|
25
|
-
.prefix { padding: 0 4px; color: var(--pi-dim); text-align: center; user-select: none; }
|
|
26
|
-
.content { padding: 0 12px 0 4px; }
|
|
27
|
-
.meta { color: var(--pi-dim); }
|
|
28
|
-
.hunk { background: color-mix(in srgb, var(--pi-accent) 9%, transparent); color: var(--pi-accent); }
|
|
29
|
-
.add { background: color-mix(in srgb, var(--pi-success) 12%, transparent); }
|
|
30
|
-
.remove { background: color-mix(in srgb, var(--pi-danger) 12%, transparent); }
|
|
31
|
-
.marker { color: var(--pi-dim); }
|
|
32
|
-
.content.add .inline-change { border-radius: 2px; background: color-mix(in srgb, var(--pi-success) 36%, transparent); color: var(--pi-text); }
|
|
33
|
-
.content.remove .inline-change { border-radius: 2px; background: color-mix(in srgb, var(--pi-danger) 36%, transparent); color: var(--pi-text); }
|
|
34
|
-
`;W([z()],L.prototype,"diff",2);L=W([F("unified-diff-viewer")],L);function re(n){return n.map(e=>P`<span class=${e.changed?"inline-change":""}>${e.text}</span>`)}function I(n){return n===void 0?"":String(n)}export{L as UnifiedDiffViewer};
|