@jmfederico/pi-web 1.202608.0 → 1.202608.2
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 +4 -4
- package/dist/cli.js +287 -113
- package/dist/cli.js.map +1 -1
- package/dist/client/assets/CodeViewer-BMWwxG7q.js +4 -0
- package/dist/client/assets/{TerminalPanel-fYrKc3jh.js → TerminalPanel-CacQDIYn.js} +6 -6
- package/dist/client/assets/index-DUW2xnoV.js +4279 -0
- package/dist/client/assets/vendor-editor-core-CXO8gGab.js +12 -0
- package/dist/client/assets/vendor-editor-languages-CpW4sJsX.js +46 -0
- package/dist/client/index.html +3 -3
- package/dist/config.js +110 -73
- package/dist/config.js.map +1 -1
- package/dist/docker/piWebDockerCommandPlan.js +4 -3
- package/dist/docker/piWebDockerCommandPlan.js.map +1 -1
- package/dist/environment.js +4 -0
- package/dist/environment.js.map +1 -0
- package/dist/nativeServices/installedServiceDefinitions.js +602 -0
- package/dist/nativeServices/installedServiceDefinitions.js.map +1 -0
- package/dist/nativeServices/serviceAction.js +174 -0
- package/dist/nativeServices/serviceAction.js.map +1 -0
- package/dist/nativeServices/serviceDoctor.js +374 -71
- package/dist/nativeServices/serviceDoctor.js.map +1 -1
- package/dist/nativeServices/servicePlan.js +1 -1
- package/dist/nativeServices/servicePlan.js.map +1 -1
- package/dist/{pi-web-plugins → pi-packages}/relays/markdownDocument.js +1 -1
- package/dist/pi-packages/relays/package.json +11 -0
- package/dist/{pi-web-plugins → pi-packages}/relays/pi-web-plugin.js +4 -4
- package/dist/pi-packages/relays/prompts/relay-worktree.md +157 -0
- package/dist/pi-packages/relays/prompts/relay.md +152 -0
- package/dist/{pi-web-plugins → pi-packages}/relays/relayDiscovery.js +1 -1
- package/dist/{pi-web-plugins → pi-packages}/relays/relaysPanelElement.js +1 -1
- package/dist/pi-packages/relays/skills/relay/SKILL.md +123 -0
- package/dist/pi-web-plugins/git/browser/git-contract.js +108 -0
- package/dist/pi-web-plugins/git/browser/git-panel.js +609 -0
- package/dist/pi-web-plugins/git/browser/gitFileList.js +43 -0
- package/dist/pi-web-plugins/git/browser/gitFileShared.js +16 -0
- package/dist/pi-web-plugins/git/browser/gitFileTree.js +81 -0
- package/dist/pi-web-plugins/git/browser/gitFileViewPreference.js +35 -0
- package/dist/pi-web-plugins/git/browser/gitRoute.js +42 -0
- package/dist/pi-web-plugins/git/browser/pi-web-plugin.js +10 -0
- package/dist/pi-web-plugins/git/browser/unifiedDiff.js +301 -0
- package/dist/{server/git/gitService.js → pi-web-plugins/git/git-backend.js} +209 -60
- package/dist/pi-web-plugins/git/package.json +16 -0
- package/dist/pi-web-plugins/git/server-plugin.js +176 -0
- package/dist/pi-web-plugins/info/infoInternals.js +16 -2
- package/dist/pi-web-plugins/info/package.json +1 -1
- package/dist/pi-web-plugins/info/pi-web-plugin.js +2 -2
- package/dist/pi-web-plugins/updates/package.json +1 -1
- package/dist/pi-web-plugins/updates/pi-web-plugin.js +1 -1
- package/dist/pi-web-plugins/workspace-tasks/package.json +1 -1
- package/dist/pi-web-plugins/workspace-tasks/pi-web-plugin.js +3 -3
- package/dist/piWebVersionReport.js +63 -10
- package/dist/piWebVersionReport.js.map +1 -1
- package/dist/plugin-api.d.ts +33 -16
- package/dist/pluginRecoveryCli.js +172 -0
- package/dist/pluginRecoveryCli.js.map +1 -0
- package/dist/server/activity/workspaceActivityService.js +27 -19
- package/dist/server/activity/workspaceActivityService.js.map +1 -1
- package/dist/server/app.js +41 -15
- package/dist/server/app.js.map +1 -1
- package/dist/server/configRoutes.js +3 -21
- package/dist/server/configRoutes.js.map +1 -1
- package/dist/server/knownAutoInstallPiPackages.js +30 -0
- package/dist/server/knownAutoInstallPiPackages.js.map +1 -0
- package/dist/server/machines/machineClient.js +23 -4
- package/dist/server/machines/machineClient.js.map +1 -1
- package/dist/server/machines/machinePluginProxyRoutes.js +74 -17
- package/dist/server/machines/machinePluginProxyRoutes.js.map +1 -1
- package/dist/server/machines/machineProxyRoutes.js +165 -8
- package/dist/server/machines/machineProxyRoutes.js.map +1 -1
- package/dist/server/machines/machineService.js +23 -0
- package/dist/server/machines/machineService.js.map +1 -1
- package/dist/server/piPackageIdentity.js +25 -0
- package/dist/server/piPackageIdentity.js.map +1 -0
- package/dist/server/piPackageService.js +69 -8
- package/dist/server/piPackageService.js.map +1 -1
- package/dist/server/piWebPluginCatalog.js +584 -0
- package/dist/server/piWebPluginCatalog.js.map +1 -0
- package/dist/server/piWebPluginLifecycle.js +162 -0
- package/dist/server/piWebPluginLifecycle.js.map +1 -0
- package/dist/server/piWebPluginService.js +159 -261
- package/dist/server/piWebPluginService.js.map +1 -1
- package/dist/server/piWebStatus.js +41 -9
- package/dist/server/piWebStatus.js.map +1 -1
- package/dist/server/plugins/pluginBackendProxyRoutes.js +69 -0
- package/dist/server/plugins/pluginBackendProxyRoutes.js.map +1 -0
- package/dist/server/plugins/serverPluginExec.js +184 -0
- package/dist/server/plugins/serverPluginExec.js.map +1 -0
- package/dist/server/plugins/serverPluginRuntime.js +480 -0
- package/dist/server/plugins/serverPluginRuntime.js.map +1 -0
- package/dist/server/projectTrustRoutes.js +80 -0
- package/dist/server/projectTrustRoutes.js.map +1 -0
- package/dist/server/projects/projectService.js +3 -1
- package/dist/server/projects/projectService.js.map +1 -1
- package/dist/server/realtime/sessionEventHub.js +26 -11
- package/dist/server/realtime/sessionEventHub.js.map +1 -1
- package/dist/server/requestCancellation.js +32 -0
- package/dist/server/requestCancellation.js.map +1 -0
- package/dist/server/sessiond/agentProcessEnvironment.js +29 -30
- package/dist/server/sessiond/agentProcessEnvironment.js.map +1 -1
- package/dist/server/sessiond/autoInstallPiPackages.js +63 -0
- package/dist/server/sessiond/autoInstallPiPackages.js.map +1 -0
- package/dist/server/sessiond/pluginBackendRoutes.js +64 -0
- package/dist/server/sessiond/pluginBackendRoutes.js.map +1 -0
- package/dist/server/sessiond/sessionDaemonShutdown.js +24 -0
- package/dist/server/sessiond/sessionDaemonShutdown.js.map +1 -0
- package/dist/server/sessiond/sessionProxyRoutes.js +2 -2
- package/dist/server/sessiond/sessionProxyRoutes.js.map +1 -1
- package/dist/server/sessiond/sessionServiceDependencies.js +2 -1
- package/dist/server/sessiond/sessionServiceDependencies.js.map +1 -1
- package/dist/server/sessiond/sessiondStateOwnership.js +235 -0
- package/dist/server/sessiond/sessiondStateOwnership.js.map +1 -0
- package/dist/server/sessiond/workspaceCatalogRoutes.js +31 -0
- package/dist/server/sessiond/workspaceCatalogRoutes.js.map +1 -0
- package/dist/server/sessiond/workspaceRemovalRoutes.js +41 -0
- package/dist/server/sessiond/workspaceRemovalRoutes.js.map +1 -0
- package/dist/server/sessiond.js +284 -98
- package/dist/server/sessiond.js.map +1 -1
- package/dist/server/sessions/authService.js +15 -54
- package/dist/server/sessions/authService.js.map +1 -1
- package/dist/server/sessions/dockerEnvironmentFacts.js +254 -0
- package/dist/server/sessions/dockerEnvironmentFacts.js.map +1 -0
- package/dist/server/sessions/modelCatalogRefresher.js +4 -3
- package/dist/server/sessions/modelCatalogRefresher.js.map +1 -1
- package/dist/server/sessions/piSessionManagerGateway.js +18 -67
- package/dist/server/sessions/piSessionManagerGateway.js.map +1 -1
- package/dist/server/sessions/piSessionService.js +495 -142
- package/dist/server/sessions/piSessionService.js.map +1 -1
- package/dist/server/sessions/sessionCommandService.js +24 -1
- package/dist/server/sessions/sessionCommandService.js.map +1 -1
- package/dist/server/sessions/sessionEnvironmentFacts.js +48 -0
- package/dist/server/sessions/sessionEnvironmentFacts.js.map +1 -0
- package/dist/server/sessions/sessionFileFormat.js +27 -0
- package/dist/server/sessions/sessionFileFormat.js.map +1 -0
- package/dist/server/sessions/sessionFileHeader.js +1 -14
- package/dist/server/sessions/sessionFileHeader.js.map +1 -1
- package/dist/server/sessions/sessionModelScope.js +160 -0
- package/dist/server/sessions/sessionModelScope.js.map +1 -0
- package/dist/server/sessions/sessionNameGenerator.js +6 -6
- package/dist/server/sessions/sessionNameGenerator.js.map +1 -1
- package/dist/server/sessions/sessionRoutes.js +55 -0
- package/dist/server/sessions/sessionRoutes.js.map +1 -1
- package/dist/server/sessions/sessionSummaryScanner.js +96 -224
- package/dist/server/sessions/sessionSummaryScanner.js.map +1 -1
- package/dist/server/sessions/spawnSubsessionTool.js +5 -9
- package/dist/server/sessions/spawnSubsessionTool.js.map +1 -1
- package/dist/server/sessions/spawnTargetResolver.js +1 -1
- package/dist/server/status/machineStatusRoutes.js +8 -0
- package/dist/server/status/machineStatusRoutes.js.map +1 -0
- package/dist/server/status/machineStatusService.js +181 -0
- package/dist/server/status/machineStatusService.js.map +1 -0
- package/dist/server/status/workspaceAttribution.js +87 -0
- package/dist/server/status/workspaceAttribution.js.map +1 -0
- package/dist/server/storage/piPackageDismissalStore.js +78 -0
- package/dist/server/storage/piPackageDismissalStore.js.map +1 -0
- package/dist/server/terminalProxyRoutes.js +2 -1
- package/dist/server/terminalProxyRoutes.js.map +1 -1
- package/dist/server/workspaceExplorerRoutes.js +20 -13
- package/dist/server/workspaceExplorerRoutes.js.map +1 -1
- package/dist/server/workspaces/fileContentService.js +18 -9
- package/dist/server/workspaces/fileContentService.js.map +1 -1
- package/dist/server/workspaces/filePreviewResponseHeaders.js +18 -0
- package/dist/server/workspaces/filePreviewResponseHeaders.js.map +1 -0
- package/dist/server/workspaces/filePreviewResponsePolicy.js +55 -0
- package/dist/server/workspaces/filePreviewResponsePolicy.js.map +1 -0
- package/dist/server/workspaces/filePreviewService.js +81 -0
- package/dist/server/workspaces/filePreviewService.js.map +1 -0
- package/dist/server/workspaces/projectWorkspaceCwds.js +0 -5
- package/dist/server/workspaces/projectWorkspaceCwds.js.map +1 -1
- package/dist/server/workspaces/sessionDaemonWorkspaceCatalog.js +402 -0
- package/dist/server/workspaces/sessionDaemonWorkspaceCatalog.js.map +1 -0
- package/dist/server/workspaces/workspaceCatalog.js +47 -0
- package/dist/server/workspaces/workspaceCatalog.js.map +1 -0
- package/dist/server/workspaces/workspaceContext.js +1 -3
- package/dist/server/workspaces/workspaceContext.js.map +1 -1
- package/dist/server/workspaces/workspaceDeletionRoutes.js +35 -125
- package/dist/server/workspaces/workspaceDeletionRoutes.js.map +1 -1
- package/dist/server/workspaces/workspaceProviderRegistry.js +651 -0
- package/dist/server/workspaces/workspaceProviderRegistry.js.map +1 -0
- package/dist/server/workspaces/workspaceRemovalService.js +256 -0
- package/dist/server/workspaces/workspaceRemovalService.js.map +1 -0
- package/dist/server/workspaces/workspaceRouteErrors.js +7 -0
- package/dist/server/workspaces/workspaceRouteErrors.js.map +1 -0
- package/dist/server/workspaces/worktreePreRemoveHook.js +39 -0
- package/dist/server/workspaces/worktreePreRemoveHook.js.map +1 -0
- package/dist/server-plugin-api.d.ts +140 -0
- package/dist/server-plugin-api.js +2 -0
- package/dist/server-plugin-api.js.map +1 -0
- package/dist/serverPluginRecovery.js +138 -0
- package/dist/serverPluginRecovery.js.map +1 -0
- package/dist/sessiond/activeAgentProfile.js +3 -22
- package/dist/sessiond/activeAgentProfile.js.map +1 -1
- package/dist/sessiond/config.js +11 -0
- package/dist/sessiond/config.js.map +1 -1
- package/dist/sessiond/sessionDaemonClient.js +11 -9
- package/dist/sessiond/sessionDaemonClient.js.map +1 -1
- package/dist/shared/activeAgentProfile.js +2 -41
- package/dist/shared/activeAgentProfile.js.map +1 -1
- package/dist/shared/activity.js +0 -3
- package/dist/shared/activity.js.map +1 -1
- package/dist/shared/apiTypes.js +7 -5
- package/dist/shared/apiTypes.js.map +1 -1
- package/dist/shared/capabilities.js +8 -6
- package/dist/shared/capabilities.js.map +1 -1
- package/dist/shared/federatedRoutes.js +36 -5
- package/dist/shared/federatedRoutes.js.map +1 -1
- package/dist/shared/machinePluginIds.js +4 -2
- package/dist/shared/machinePluginIds.js.map +1 -1
- package/dist/shared/machineStatus.js +94 -0
- package/dist/shared/machineStatus.js.map +1 -0
- package/dist/shared/piWebStatusParsing.js +33 -0
- package/dist/shared/piWebStatusParsing.js.map +1 -1
- package/dist/shared/pluginApiTypes.d.ts +150 -0
- package/dist/shared/pluginApiTypes.js +3 -0
- package/dist/shared/pluginApiTypes.js.map +1 -0
- package/dist/shared/pluginBackendProtocol.js +110 -0
- package/dist/shared/pluginBackendProtocol.js.map +1 -0
- package/dist/shared/pluginIds.js +5 -0
- package/dist/shared/pluginIds.js.map +1 -1
- package/dist/shared/pluginRecoveryCommands.js +14 -0
- package/dist/shared/pluginRecoveryCommands.js.map +1 -0
- package/dist/shared/workspaceFiles.js +41 -2
- package/dist/shared/workspaceFiles.js.map +1 -1
- package/dist/shared/workspaceRemovalProtocol.js +24 -0
- package/dist/shared/workspaceRemovalProtocol.js.map +1 -0
- package/docs/config.md +105 -52
- package/docs/plugins.md +403 -146
- package/examples/workspace-provider-plugin/README.md +52 -0
- package/examples/workspace-provider-plugin/package.json +25 -0
- package/examples/workspace-provider-plugin/src/browser/index.ts +69 -0
- package/examples/workspace-provider-plugin/src/server.ts +64 -0
- package/examples/workspace-provider-plugin/tsconfig.json +21 -0
- package/package.json +30 -11
- package/server-plugin-api.d.ts +1 -0
- package/dist/client/assets/CodeViewer-D91Sp61M.js +0 -4
- package/dist/client/assets/UnifiedDiffViewer-BafLWGtF.js +0 -39
- package/dist/client/assets/index-CA8q9_o7.js +0 -4025
- package/dist/client/assets/vendor-editor-core-vUi74DnD.js +0 -12
- package/dist/client/assets/vendor-editor-languages-DoaXUodB.js +0 -46
- package/dist/pi-web-plugins/relays/package.json +0 -9
- package/dist/plugin-api/unstable.d.ts +0 -22
- package/dist/server/activity/workspaceActivityRoutes.js +0 -4
- package/dist/server/activity/workspaceActivityRoutes.js.map +0 -1
- package/dist/server/git/gitService.js.map +0 -1
- package/dist/server/gitRoutes.js +0 -23
- package/dist/server/gitRoutes.js.map +0 -1
- package/dist/server/sessions/parentSessionLocator.js +0 -75
- package/dist/server/sessions/parentSessionLocator.js.map +0 -1
- package/dist/server/workspaces/gitWorktreeDiscovery.js +0 -43
- package/dist/server/workspaces/gitWorktreeDiscovery.js.map +0 -1
- package/dist/server/workspaces/imagePreviewService.js +0 -40
- package/dist/server/workspaces/imagePreviewService.js.map +0 -1
- package/dist/server/workspaces/workspaceService.js +0 -52
- package/dist/server/workspaces/workspaceService.js.map +0 -1
- package/dist/shared/apiTypes.d.ts +0 -1217
- package/dist/shared/thinkingLevels.d.ts +0 -27
- package/plugin-api/unstable.d.ts +0 -1
- /package/dist/{pi-web-plugins → pi-packages}/relays/vendor/README.md +0 -0
- /package/dist/{pi-web-plugins → pi-packages}/relays/vendor/marked.esm.js +0 -0
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# PI WEB dual-entry workspace-provider example
|
|
2
|
+
|
|
3
|
+
This standalone package is a copyable starting point for a trusted PI WEB plugin with both browser API v2 and server API v1 entries. It claims only projects that opt in with a marker file, publishes non-secret metadata to the browser, and demonstrates a browser request routed to the server provider that owns the workspace.
|
|
4
|
+
|
|
5
|
+
The example imports only the supported package declarations:
|
|
6
|
+
|
|
7
|
+
- `@jmfederico/pi-web/plugin-api`
|
|
8
|
+
- `@jmfederico/pi-web/server-plugin-api`
|
|
9
|
+
|
|
10
|
+
It requires PI WEB `1.202608.1` or newer, the first release that provides those entrypoints and browser API v2.
|
|
11
|
+
|
|
12
|
+
## Build and install
|
|
13
|
+
|
|
14
|
+
Copy `examples/workspace-provider-plugin/` out of the PI WEB repository or installed `@jmfederico/pi-web` package, then run:
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm install
|
|
18
|
+
npm run build
|
|
19
|
+
mkdir -p ~/.pi-web/plugins
|
|
20
|
+
ln -s "$PWD" ~/.pi-web/plugins/example-workspaces
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
If `PI_WEB_DATA_DIR` is set, link into `$PI_WEB_DATA_DIR/plugins` instead. The link name must be a valid plugin id and must not collide with another package.
|
|
24
|
+
|
|
25
|
+
Opt one registered PI WEB project into this example provider:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
mkdir -p /absolute/path/to/project/.pi-web
|
|
29
|
+
touch /absolute/path/to/project/.pi-web/example-workspace-provider
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Then restart the target session daemon and reload the browser:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
systemctl --user restart pi-web-sessiond
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Restarting `pi-web-sessiond.service` may interrupt active sessions and runtime ownership. A browser or web/API restart alone does not activate a server entry.
|
|
39
|
+
|
|
40
|
+
Open the opted-in project. The **Example Provider** panel displays the public marker metadata and its button calls the owning server provider's `summary` operation. Remove the marker and restart sessiond (or trigger a later workspace resolution) to stop claiming that project.
|
|
41
|
+
|
|
42
|
+
## Boundary demonstrated by the package
|
|
43
|
+
|
|
44
|
+
`package.json` declares:
|
|
45
|
+
|
|
46
|
+
- browser module `dist/browser/index.js` with `browserRoot: "dist/browser"`;
|
|
47
|
+
- server module `dist/server.js`, outside the browser root;
|
|
48
|
+
- `machineSpecific: true`, required for a dual browser/server entry.
|
|
49
|
+
|
|
50
|
+
Only files under `dist/browser/` can be served through this plugin's browser asset route. Source, package metadata, the server module, and dependencies remain outside that route. Keep secrets out of `publicMetadata`: it is visible to every browser script and API consumer.
|
|
51
|
+
|
|
52
|
+
The server provider intentionally does not advertise workspace removal. See the canonical plugin guide for removal-plan shell and completion semantics, package limits, federation behavior, and the complete API contract: <https://pi-web.dev/plugins>.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "pi-web-example-workspace-provider",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"build": "tsc -p tsconfig.json"
|
|
8
|
+
},
|
|
9
|
+
"devDependencies": {
|
|
10
|
+
"@jmfederico/pi-web": "^1.202608.1",
|
|
11
|
+
"@types/node": "^24.13.3",
|
|
12
|
+
"typescript": "^6.0.3"
|
|
13
|
+
},
|
|
14
|
+
"piWeb": {
|
|
15
|
+
"plugins": [
|
|
16
|
+
{
|
|
17
|
+
"id": "example-workspaces",
|
|
18
|
+
"browserRoot": "dist/browser",
|
|
19
|
+
"module": "dist/browser/index.js",
|
|
20
|
+
"serverModule": "dist/server.js",
|
|
21
|
+
"machineSpecific": true
|
|
22
|
+
}
|
|
23
|
+
]
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import type { JsonObject, PiWebPlugin, WorkspacePanelContext } from "@jmfederico/pi-web/plugin-api";
|
|
2
|
+
|
|
3
|
+
const summaries = new Map<string, string>();
|
|
4
|
+
|
|
5
|
+
const plugin: PiWebPlugin = {
|
|
6
|
+
apiVersion: 2,
|
|
7
|
+
name: "Example Workspace Provider",
|
|
8
|
+
activate: ({ pluginId, runtimePluginId, html }) => ({
|
|
9
|
+
contributions: {
|
|
10
|
+
actions: [
|
|
11
|
+
{
|
|
12
|
+
id: "workspace.open",
|
|
13
|
+
title: "Open Example Workspace Provider",
|
|
14
|
+
enabled: ({ state }) => state.selectedWorkspace?.provider?.pluginId === pluginId,
|
|
15
|
+
run: ({ selectWorkspaceTool }) => {
|
|
16
|
+
selectWorkspaceTool(`${runtimePluginId}:workspace.example-provider`);
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
],
|
|
20
|
+
workspacePanels: [
|
|
21
|
+
{
|
|
22
|
+
id: "workspace.example-provider",
|
|
23
|
+
title: "Example Provider",
|
|
24
|
+
visible: ({ workspace }) => workspace.provider?.pluginId === pluginId,
|
|
25
|
+
render: (context) => {
|
|
26
|
+
const marker = stringMetadata(context.workspace.provider?.metadata, "marker") ?? "unknown";
|
|
27
|
+
const summary = summaries.get(workspaceKey(context)) ?? "Request a summary from the owning server plugin.";
|
|
28
|
+
return html`
|
|
29
|
+
<section class="toolbar"><strong>Example workspace provider</strong></section>
|
|
30
|
+
<section class="viewer">
|
|
31
|
+
<p>This workspace is owned by <code>${pluginId}</code>.</p>
|
|
32
|
+
<p class="muted">Claim marker: <code>${marker}</code></p>
|
|
33
|
+
<button
|
|
34
|
+
?disabled=${context.backend === undefined}
|
|
35
|
+
@click=${() => { void refreshSummary(context); }}
|
|
36
|
+
>Request backend summary</button>
|
|
37
|
+
<p aria-live="polite">${summary}</p>
|
|
38
|
+
</section>
|
|
39
|
+
`;
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
],
|
|
43
|
+
},
|
|
44
|
+
}),
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export default plugin;
|
|
48
|
+
|
|
49
|
+
async function refreshSummary(context: WorkspacePanelContext): Promise<void> {
|
|
50
|
+
const key = workspaceKey(context);
|
|
51
|
+
try {
|
|
52
|
+
if (context.backend === undefined) throw new Error("The paired workspace backend is unavailable");
|
|
53
|
+
const result = await context.backend.request("summary", null);
|
|
54
|
+
if (typeof result !== "string") throw new Error("The workspace backend returned an invalid summary");
|
|
55
|
+
summaries.set(key, result);
|
|
56
|
+
} catch (error) {
|
|
57
|
+
summaries.set(key, error instanceof Error ? error.message : String(error));
|
|
58
|
+
}
|
|
59
|
+
context.host.requestRender();
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function workspaceKey(context: WorkspacePanelContext): string {
|
|
63
|
+
return `${context.machine.id}:${context.workspace.id}`;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function stringMetadata(metadata: JsonObject | undefined, key: string): string | undefined {
|
|
67
|
+
const value = metadata?.[key];
|
|
68
|
+
return typeof value === "string" ? value : undefined;
|
|
69
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { access } from "node:fs/promises";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import type {
|
|
4
|
+
PiWebServerPlugin,
|
|
5
|
+
ProjectInput,
|
|
6
|
+
ProviderClaim,
|
|
7
|
+
ProviderRequestContext,
|
|
8
|
+
ProviderWorkspace,
|
|
9
|
+
WorkspaceProvider,
|
|
10
|
+
} from "@jmfederico/pi-web/server-plugin-api";
|
|
11
|
+
|
|
12
|
+
const markerPath = ".pi-web/example-workspace-provider";
|
|
13
|
+
|
|
14
|
+
const plugin: PiWebServerPlugin = {
|
|
15
|
+
apiVersion: 1,
|
|
16
|
+
name: "Example Workspace Provider",
|
|
17
|
+
activate({ pluginId, logger }) {
|
|
18
|
+
logger.info("Activating example workspace provider", { pluginId });
|
|
19
|
+
return { workspaceProvider: createWorkspaceProvider(pluginId) };
|
|
20
|
+
},
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export default plugin;
|
|
24
|
+
|
|
25
|
+
function createWorkspaceProvider(pluginId: string): WorkspaceProvider {
|
|
26
|
+
return {
|
|
27
|
+
async probe(project: ProjectInput, signal: AbortSignal): Promise<ProviderClaim> {
|
|
28
|
+
signal.throwIfAborted();
|
|
29
|
+
try {
|
|
30
|
+
await access(join(project.path, markerPath));
|
|
31
|
+
signal.throwIfAborted();
|
|
32
|
+
return "claim";
|
|
33
|
+
} catch (error) {
|
|
34
|
+
if (isMissingFile(error)) return "pass";
|
|
35
|
+
throw error;
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
async list(project: ProjectInput, signal: AbortSignal): Promise<ProviderWorkspace[]> {
|
|
39
|
+
signal.throwIfAborted();
|
|
40
|
+
return [{
|
|
41
|
+
key: "main",
|
|
42
|
+
path: project.path,
|
|
43
|
+
label: project.name,
|
|
44
|
+
isMain: true,
|
|
45
|
+
// This object is visible to every browser script and API consumer.
|
|
46
|
+
publicMetadata: { kind: "example", marker: markerPath },
|
|
47
|
+
}];
|
|
48
|
+
},
|
|
49
|
+
request(context: ProviderRequestContext) {
|
|
50
|
+
context.signal.throwIfAborted();
|
|
51
|
+
if (context.operation !== "summary") {
|
|
52
|
+
throw new Error(`Unsupported example workspace operation: ${context.operation}`);
|
|
53
|
+
}
|
|
54
|
+
return Promise.resolve(`${pluginId} owns ${context.workspace.label} at ${context.workspace.path}`);
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function isMissingFile(error: unknown): boolean {
|
|
60
|
+
return typeof error === "object"
|
|
61
|
+
&& error !== null
|
|
62
|
+
&& "code" in error
|
|
63
|
+
&& Reflect.get(error, "code") === "ENOENT";
|
|
64
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2022",
|
|
4
|
+
"module": "NodeNext",
|
|
5
|
+
"moduleResolution": "NodeNext",
|
|
6
|
+
"lib": ["ES2022", "DOM"],
|
|
7
|
+
"types": ["node"],
|
|
8
|
+
"rootDir": "src",
|
|
9
|
+
"outDir": "dist",
|
|
10
|
+
"strict": true,
|
|
11
|
+
"exactOptionalPropertyTypes": true,
|
|
12
|
+
"noUncheckedIndexedAccess": true,
|
|
13
|
+
"noImplicitReturns": true,
|
|
14
|
+
"noFallthroughCasesInSwitch": true,
|
|
15
|
+
"forceConsistentCasingInFileNames": true,
|
|
16
|
+
"verbatimModuleSyntax": true,
|
|
17
|
+
"skipLibCheck": false,
|
|
18
|
+
"noEmitOnError": true
|
|
19
|
+
},
|
|
20
|
+
"include": ["src/**/*.ts"]
|
|
21
|
+
}
|
package/package.json
CHANGED
|
@@ -1,10 +1,28 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jmfederico/pi-web",
|
|
3
|
-
"version": "1.202608.
|
|
3
|
+
"version": "1.202608.2",
|
|
4
4
|
"description": "Web UI for persistent Pi Coding Agent sessions in real workspaces.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Federico Jaramillo Martinez",
|
|
7
7
|
"type": "module",
|
|
8
|
+
"exports": {
|
|
9
|
+
"./plugin-api": {
|
|
10
|
+
"types": "./dist/plugin-api.d.ts"
|
|
11
|
+
},
|
|
12
|
+
"./server-plugin-api": {
|
|
13
|
+
"types": "./dist/server-plugin-api.d.ts"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"typesVersions": {
|
|
17
|
+
"*": {
|
|
18
|
+
"plugin-api": [
|
|
19
|
+
"dist/plugin-api.d.ts"
|
|
20
|
+
],
|
|
21
|
+
"server-plugin-api": [
|
|
22
|
+
"dist/server-plugin-api.d.ts"
|
|
23
|
+
]
|
|
24
|
+
}
|
|
25
|
+
},
|
|
8
26
|
"bin": {
|
|
9
27
|
"pi-web": "dist/cli.js",
|
|
10
28
|
"pi-web-server": "dist/server/index.js",
|
|
@@ -17,15 +35,16 @@
|
|
|
17
35
|
"README.md",
|
|
18
36
|
"LICENSE",
|
|
19
37
|
"extensions",
|
|
38
|
+
"examples/workspace-provider-plugin",
|
|
20
39
|
"docs/plugins.md",
|
|
21
40
|
"docs/config.md",
|
|
22
41
|
"docs/assets",
|
|
23
42
|
"plugin-api.d.ts",
|
|
24
|
-
"plugin-api
|
|
43
|
+
"server-plugin-api.d.ts"
|
|
25
44
|
],
|
|
26
45
|
"scripts": {
|
|
27
46
|
"dev": "bash -c 'trap \"kill 0\" EXIT; npm run dev:sessiond & npm run dev:web & npm run dev:client & wait'",
|
|
28
|
-
"dev:sessiond": "tsx watch src/server/sessiond.ts",
|
|
47
|
+
"dev:sessiond": "npm run build:plugins && tsx watch src/server/sessiond.ts",
|
|
29
48
|
"dev:web": "bash -c 'set -e; npm run build:plugins; trap \"kill 0\" EXIT; npm run dev:plugins & tsx watch src/server/index.ts & wait'",
|
|
30
49
|
"dev:server": "npm run dev:web",
|
|
31
50
|
"dev:client": "vite --host 0.0.0.0",
|
|
@@ -37,12 +56,12 @@
|
|
|
37
56
|
"typecheck": "tsc --noEmit",
|
|
38
57
|
"typecheck:cached": "tsc --noEmit --incremental --tsBuildInfoFile node_modules/.cache/pi-web/typecheck.tsbuildinfo",
|
|
39
58
|
"knip": "knip",
|
|
40
|
-
"lint": "eslint \"src/**/*.ts\" \"extensions/**/*.ts\" \"pi-web-plugins/**/*.ts\" vite.config.ts vitest.config.ts",
|
|
59
|
+
"lint": "eslint \"src/**/*.ts\" \"extensions/**/*.ts\" \"pi-web-plugins/**/*.ts\" \"pi-packages/**/*.ts\" vite.config.ts vitest.config.ts",
|
|
41
60
|
"test": "vitest run --config vitest.config.ts",
|
|
42
61
|
"verify": "npm run typecheck && npm run lint && npm run knip && npm test",
|
|
43
62
|
"verify:staged": "node scripts/verify-staged.mjs",
|
|
44
63
|
"start": "tsx src/server/index.ts",
|
|
45
|
-
"start:sessiond": "tsx src/server/sessiond.ts",
|
|
64
|
+
"start:sessiond": "npm run build:plugins && tsx src/server/sessiond.ts",
|
|
46
65
|
"clean": "node -e \"require('node:fs').rmSync('dist', { recursive: true, force: true })\"",
|
|
47
66
|
"prepack": "npm run build",
|
|
48
67
|
"pack:dry": "npm pack --dry-run",
|
|
@@ -84,9 +103,9 @@
|
|
|
84
103
|
},
|
|
85
104
|
"devDependencies": {
|
|
86
105
|
"@changesets/cli": "^2.31.0",
|
|
87
|
-
"@earendil-works/pi-agent-core": "^0.
|
|
88
|
-
"@earendil-works/pi-ai": "^0.
|
|
89
|
-
"@earendil-works/pi-coding-agent": "^0.
|
|
106
|
+
"@earendil-works/pi-agent-core": "^0.84.1",
|
|
107
|
+
"@earendil-works/pi-ai": "^0.84.1",
|
|
108
|
+
"@earendil-works/pi-coding-agent": "^0.84.1",
|
|
90
109
|
"@eslint/js": "^10.0.1",
|
|
91
110
|
"@types/node": "^24.13.3",
|
|
92
111
|
"@types/ws": "^8.18.1",
|
|
@@ -116,9 +135,9 @@
|
|
|
116
135
|
"homepage": "https://pi-web.dev/",
|
|
117
136
|
"packageManager": "npm@11.11.0",
|
|
118
137
|
"peerDependencies": {
|
|
119
|
-
"@earendil-works/pi-agent-core": ">=0.
|
|
120
|
-
"@earendil-works/pi-ai": ">=0.
|
|
121
|
-
"@earendil-works/pi-coding-agent": ">=0.
|
|
138
|
+
"@earendil-works/pi-agent-core": ">=0.84.0",
|
|
139
|
+
"@earendil-works/pi-ai": ">=0.84.0",
|
|
140
|
+
"@earendil-works/pi-coding-agent": ">=0.84.0"
|
|
122
141
|
},
|
|
123
142
|
"keywords": [
|
|
124
143
|
"pi-package",
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./dist/server-plugin-api.js";
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
import{$ as e,J as t,P as n,S as r,Y as i,l as a,q as o,y as s}from"./vendor-editor-core-vUi74DnD.js";import{c,i as l,l as u,n as d,r as f,s as p,t as m,u as h}from"./vendor-editor-languages-DoaXUodB.js";import{_ as g,a as _,f as v,g as y,m as b,p as x,u as S}from"./index-CA8q9_o7.js";import{t as C}from"./vendor-editor-legacy-CYBnW6ZU.js";var w=class extends b{constructor(...e){super(...e),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 y`<div class="host"></div>`}recreateEditor(){this.editorHost&&(this.view?.destroy(),this.view=new o({parent:this.editorHost,state:e.create({doc:this.content,extensions:[i(),t.of(a),n(r,{fallback:!0}),e.readOnly.of(!0),o.editable.of(!1),o.lineWrapping,T,...D(this.language),...O(this.language)]})}))}static{this.styles=g`
|
|
2
|
-
:host { display: block; min-height: 0; height: 100%; }
|
|
3
|
-
.host { height: 100%; min-height: 0; overflow: auto; }
|
|
4
|
-
`}};_([v()],w.prototype,`content`,void 0),_([v()],w.prototype,`language`,void 0),_([S(`.host`)],w.prototype,`editorHost`,void 0),w=_([x(`code-viewer`)],w);var T=o.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`}}),E=o.theme({".cm-content":{textAlign:`start`},".cm-line":{unicodeBidi:`plaintext`}});function D(e){return e===`markdown`?[o.contentAttributes.of({dir:`auto`}),E]:[]}function O(e){if(e===void 0)return[];switch(e){case`typescript`:return[u({typescript:!0})];case`javascript`:return[u()];case`json`:return[l()];case`markdown`:return[p()];case`css`:return[h()];case`html`:return[c()];case`python`:return[f()];case`rust`:return[d()];case`go`:return[m()];case`diff`:return[s.define(C)];default:return[]}}export{w as CodeViewer};
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import{_ as e,a as t,f as n,g as r,m as i,p as a}from"./index-CA8q9_o7.js";var o=class{diff(e,t,n={}){let r;typeof n==`function`?(r=n,n={}):`callback`in n&&(r=n.callback);let i=this.castInput(e,n),a=this.castInput(t,n),o=this.removeEmpty(this.tokenize(i,n)),s=this.removeEmpty(this.tokenize(a,n));return this.diffWithOptionsObj(o,s,n,r)}diffWithOptionsObj(e,t,n,r){let i=e=>{if(e=this.postProcess(e,n),r){setTimeout(function(){r(e)},0);return}else return e},a=t.length,o=e.length,s=1,c=a+o;n.maxEditLength!=null&&(c=Math.min(c,n.maxEditLength));let l=n.timeout??1/0,u=Date.now()+l,d=[{oldPos:-1,lastComponent:void 0}],f=this.extractCommon(d[0],t,e,0,n);if(d[0].oldPos+1>=o&&f+1>=a)return i(this.buildValues(d[0].lastComponent,t,e));let p=-1/0,m=1/0,h=()=>{for(let r=Math.max(p,-s);r<=Math.min(m,s);r+=2){let s,c=d[r-1],l=d[r+1];c&&(d[r-1]=void 0);let u=!1;if(l){let e=l.oldPos-r;u=l&&0<=e&&e<a}let h=c&&c.oldPos+1<o;if(!u&&!h){d[r]=void 0;continue}if(s=!h||u&&c.oldPos<l.oldPos?this.addToPath(l,!0,!1,0,n):this.addToPath(c,!1,!0,1,n),f=this.extractCommon(s,t,e,r,n),s.oldPos+1>=o&&f+1>=a)return i(this.buildValues(s.lastComponent,t,e))||!0;d[r]=s,s.oldPos+1>=o&&(m=Math.min(m,r-1)),f+1>=a&&(p=Math.max(p,r+1))}s++};if(r)(function e(){setTimeout(function(){if(s>c||Date.now()>u)return r(void 0);h()||e()},0)})();else for(;s<=c&&Date.now()<=u;){let e=h();if(e)return e}}addToPath(e,t,n,r,i){let a=e.lastComponent;return a&&!i.oneChangePerToken&&a.added===t&&a.removed===n?{oldPos:e.oldPos+r,lastComponent:{count:a.count+1,added:t,removed:n,previousComponent:a.previousComponent}}:{oldPos:e.oldPos+r,lastComponent:{count:1,added:t,removed:n,previousComponent:a}}}extractCommon(e,t,n,r,i){let a=t.length,o=n.length,s=e.oldPos,c=s-r,l=0;for(;c+1<a&&s+1<o&&this.equals(n[s+1],t[c+1],i);)c++,s++,l++,i.oneChangePerToken&&(e.lastComponent={count:1,previousComponent:e.lastComponent,added:!1,removed:!1});return l&&!i.oneChangePerToken&&(e.lastComponent={count:l,previousComponent:e.lastComponent,added:!1,removed:!1}),e.oldPos=s,c}equals(e,t,n){return n.comparator?n.comparator(e,t):e===t||!!n.ignoreCase&&e.toLowerCase()===t.toLowerCase()}removeEmpty(e){let t=[];for(let n=0;n<e.length;n++)e[n]&&t.push(e[n]);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,n){let r=[],i;for(;e;)r.push(e),i=e.previousComponent,delete e.previousComponent,e=i;r.reverse();let a=r.length,o=0,s=0,c=0;for(;o<a;o++){let e=r[o];if(e.removed)e.value=this.join(n.slice(c,c+e.count)),c+=e.count;else{if(!e.added&&this.useLongestToken){let r=t.slice(s,s+e.count);r=r.map(function(e,t){let r=n[c+t];return r.length>e.length?r:e}),e.value=this.join(r)}else e.value=this.join(t.slice(s,s+e.count));s+=e.count,e.added||(c+=e.count)}}return r}},s=new class extends o{};function c(e,t,n){return s.diff(e,t,n)}function l(e,t){let n;for(n=0;n<e.length&&n<t.length;n++)if(e[n]!=t[n])return e.slice(0,n);return e.slice(0,n)}function u(e,t){let n;if(!e||!t||e[e.length-1]!=t[t.length-1])return``;for(n=0;n<e.length&&n<t.length;n++)if(e[e.length-(n+1)]!=t[t.length-(n+1)])return e.slice(-n);return e.slice(-n)}function d(e,t,n){if(e.slice(0,t.length)!=t)throw Error(`string ${JSON.stringify(e)} doesn't start with prefix ${JSON.stringify(t)}; this is a bug`);return n+e.slice(t.length)}function f(e,t,n){if(!t)return e+n;if(e.slice(-t.length)!=t)throw Error(`string ${JSON.stringify(e)} doesn't end with suffix ${JSON.stringify(t)}; this is a bug`);return e.slice(0,-t.length)+n}function p(e,t){return d(e,t,``)}function m(e,t){return f(e,t,``)}function h(e,t){return t.slice(0,g(e,t))}function g(e,t){let n=0;e.length>t.length&&(n=e.length-t.length);let r=t.length;e.length<t.length&&(r=e.length);let i=Array(r),a=0;i[0]=0;for(let e=1;e<r;e++){for(t[e]==t[a]?i[e]=i[a]:i[e]=a;a>0&&t[e]!=t[a];)a=i[a];t[e]==t[a]&&a++}a=0;for(let r=n;r<e.length;r++){for(;a>0&&e[r]!=t[a];)a=i[a];e[r]==t[a]&&a++}return a}function _(e,t){let n=[];for(let r of Array.from(t.segment(e))){let e=r.segment;n.length&&/\s/.test(n[n.length-1])&&/\s/.test(e)?n[n.length-1]+=e:n.push(e)}return n}function v(e,t){if(t)return b(e,t)[1];let n;for(n=e.length-1;n>=0&&e[n].match(/\s/);n--);return e.substring(n+1)}function y(e,t){if(t)return b(e,t)[0];let n=e.match(/^\s*/);return n?n[0]:``}function b(e,t){if(!t)return[y(e),v(e)];if(t.resolvedOptions().granularity!=`word`)throw Error(`The segmenter passed must have a granularity of "word"`);let n=_(e,t),r=n[0],i=n[n.length-1];return[/\s/.test(r)?r:``,/\s/.test(i)?i:``]}var x=`a-zA-Z0-9_\\u{AD}\\u{C0}-\\u{D6}\\u{D8}-\\u{F6}\\u{F8}-\\u{2C6}\\u{2C8}-\\u{2D7}\\u{2DE}-\\u{2FF}\\u{1E00}-\\u{1EFF}`,S=RegExp(`[${x}]+|\\s+|[^${x}]`,`ug`);new class extends o{equals(e,t,n){return n.ignoreCase&&(e=e.toLowerCase(),t=t.toLowerCase()),e.trim()===t.trim()}tokenize(e,t={}){let n;if(t.intlSegmenter){let r=t.intlSegmenter;if(r.resolvedOptions().granularity!=`word`)throw Error(`The segmenter passed must have a granularity of "word"`);n=_(e,r)}else n=e.match(S)||[];let r=[],i=null;return n.forEach(e=>{/\s/.test(e)?i==null?r.push(e):r.push(r.pop()+e):i!=null&&/\s/.test(i)?r[r.length-1]==i?r.push(r.pop()+e):r.push(i+e):r.push(e),i=e}),r}join(e){return e.map((e,t)=>t==0?e:e.replace(/^\s+/,``)).join(``)}postProcess(e,t){if(!e||t.oneChangePerToken)return e;let n=null,r=null,i=null;return e.forEach(e=>{e.added?r=e:e.removed?i=e:((r||i)&&C(n,i,r,e,t.intlSegmenter),n=e,r=null,i=null)}),(r||i)&&C(n,i,r,null,t.intlSegmenter),e}};function C(e,t,n,r,i){if(t&&n){let[a,o]=b(t.value,i),[s,c]=b(n.value,i);if(e){let r=l(a,s);e.value=f(e.value,s,r),t.value=p(t.value,r),n.value=p(n.value,r)}if(r){let e=u(o,c);r.value=d(r.value,c,e),t.value=m(t.value,e),n.value=m(n.value,e)}}else if(n){if(e){let e=y(n.value,i);n.value=n.value.substring(e.length)}if(r){let e=y(r.value,i);r.value=r.value.substring(e.length)}}else if(e&&r){let n=y(r.value,i),[a,o]=b(t.value,i),s=l(n,a);t.value=p(t.value,s);let c=u(p(n,s),o);t.value=m(t.value,c),r.value=d(r.value,n,c),e.value=f(e.value,n,n.slice(0,n.length-c.length))}else if(r){let e=y(r.value,i),n=h(v(t.value,i),e);t.value=m(t.value,n)}else if(e){let n=h(v(e.value,i),y(t.value,i));t.value=p(t.value,n)}}new class extends o{tokenize(e){let t=RegExp(`(\\r?\\n)|[${x}]+|[^\\S\\n\\r]+|[^${x}]`,`ug`);return e.match(t)||[]}},new class extends o{constructor(){super(...arguments),this.tokenize=w}equals(e,t,n){return n.ignoreWhitespace?((!n.newlineIsToken||!e.includes(`
|
|
2
|
-
`))&&(e=e.trim()),(!n.newlineIsToken||!t.includes(`
|
|
3
|
-
`))&&(t=t.trim())):n.ignoreNewlineAtEof&&!n.newlineIsToken&&(e.endsWith(`
|
|
4
|
-
`)&&(e=e.slice(0,-1)),t.endsWith(`
|
|
5
|
-
`)&&(t=t.slice(0,-1))),super.equals(e,t,n)}};function w(e,t){t.stripTrailingCr&&(e=e.replace(/\r\n/g,`
|
|
6
|
-
`));let n=[],r=e.split(/(\n|\r\n)/);r[r.length-1]||r.pop();for(let e=0;e<r.length;e++){let i=r[e];e%2&&!t.newlineIsToken?n[n.length-1]+=i:n.push(i)}return n}function T(e){return e==`.`||e==`!`||e==`?`}new class extends o{tokenize(e){let t=[],n=0;for(let r=0;r<e.length;r++){if(r==e.length-1){t.push(e.slice(n));break}if(T(e[r])&&e[r+1].match(/\s/)){for(t.push(e.slice(n,r+1)),r=n=r+1;e[r+1]?.match(/\s/);)r++;t.push(e.slice(n,r+1)),n=r+1}}return t}},new class extends o{tokenize(e){return e.split(/([{}:;,]|\s+)/)}},new class extends o{constructor(){super(...arguments),this.tokenize=w}get useLongestToken(){return!0}castInput(e,t){let{undefinedReplacement:n,stringifyReplacer:r=(e,t)=>t===void 0?n:t}=t;return typeof e==`string`?e:JSON.stringify(E(e,null,null,r),null,` `)}equals(e,t,n){return super.equals(e.replace(/,([\r\n])/g,`$1`),t.replace(/,([\r\n])/g,`$1`),n)}};function E(e,t,n,r,i){t||=[],n||=[],r&&(e=r(i===void 0?``:i,e));let a;for(a=0;a<t.length;a+=1)if(t[a]===e)return n[a];let o;if(Object.prototype.toString.call(e)===`[object Array]`){for(t.push(e),o=Array(e.length),n.push(o),a=0;a<e.length;a+=1)o[a]=E(e[a],t,n,r,String(a));return t.pop(),n.pop(),o}if(e&&e.toJSON&&(e=e.toJSON()),typeof e==`object`&&e){t.push(e),o={},n.push(o);let i=[],s;for(s in e)Object.prototype.hasOwnProperty.call(e,s)&&i.push(s);for(i.sort(),a=0;a<i.length;a+=1)s=i[a],o[s]=E(e[s],t,n,r,s);t.pop(),n.pop()}else o=e;return o}new class extends o{tokenize(e){return e.slice()}join(e){return e}removeEmpty(e){return e}};var D=/^@@ -(\d+)(?:,\d+)? \+(\d+)(?:,\d+)? @@/,O=5e3,k=20,A=.2,j=.25;function M(e){let t=N(e);return I(t),t}function N(e){let t=P(e),n=[],r,i;for(let e of t){let t=D.exec(e);if(t!==null){r=Number(t[1]),i=Number(t[2]),n.push(F(`hunk`,``,e));continue}if(r!==void 0&&i!==void 0){if(e.startsWith(`+`)){n.push(F(`add`,`+`,e.slice(1),{newLineNumber:i})),i++;continue}if(e.startsWith(`-`)){n.push(F(`remove`,`-`,e.slice(1),{oldLineNumber:r})),r++;continue}if(e.startsWith(` `)){n.push(F(`context`,` `,e.slice(1),{oldLineNumber:r,newLineNumber:i})),r++,i++;continue}if(e.startsWith(`\\`)){n.push(F(`marker`,``,e));continue}}r=void 0,i=void 0,n.push(F(`meta`,``,e))}return n}function P(e){if(e===``)return[];let t=e.replace(/\r\n/g,`
|
|
7
|
-
`).replace(/\r/g,`
|
|
8
|
-
`).split(`
|
|
9
|
-
`);return t.at(-1)===``&&t.pop(),t}function F(e,t,n,r={}){return{kind:e,prefix:t,text:n,spans:n===``?[]:[{text:n,changed:!1}],...r}}function I(e){let t=0;for(;t<e.length;){if(e[t]?.kind!==`remove`){t++;continue}let n=t;for(;e[t]?.kind===`remove`;)t++;let r=t;for(;e[t]?.kind===`add`;)t++;r!==t&&L(e.slice(n,r),e.slice(r,t))}}function L(e,t){if(!(e.length+t.length>k))for(let n of R(e,t)){let e=U(n.removed.text,n.added.text);e!==void 0&&(n.removed.spans=e.removed,n.added.spans=e.added)}}function R(e,t){if(e.length===t.length)return e.map((e,n)=>({removed:e,added:t[n]})).filter(z);if(e.length===1)return B(e[0],t);if(t.length===1)return V(e,t[0]);let n=[],r=Math.min(e.length,t.length);for(let i=0;i<r;i++){let r=e[i],a=t[i];r===void 0||a===void 0||W(r.text,a.text)>=j&&n.push({removed:r,added:a})}return n}function z(e){return e.added!==void 0}function B(e,t){if(e===void 0)return[];let n=H(e.text,t);return n===void 0?[]:[{removed:e,added:n}]}function V(e,t){if(t===void 0)return[];let n=H(t.text,e);return n===void 0?[]:[{removed:n,added:t}]}function H(e,t){let n,r=j;for(let i of t){let t=W(e,i.text);t<=r||(n=i,r=t)}return n}function U(e,t){if(e===t||e.length>O||t.length>O)return;let n=c(e,t),r=G(n,e,t);if(Math.max(e.length,t.length)>=20&&r<A)return;let i=[],a=[];for(let e of n)e.value!==``&&(e.added?a.push({text:e.value,changed:!0}):e.removed?i.push({text:e.value,changed:!0}):(i.push({text:e.value,changed:!1}),a.push({text:e.value,changed:!1})));if(!(!i.some(e=>e.changed)&&!a.some(e=>e.changed)))return{removed:K(i),added:K(a)}}function W(e,t){return e===t?1:e.length>O||t.length>O?0:G(c(e,t),e,t)}function G(e,t,n){let r=Math.max(t.length,n.length);return r===0?1:e.reduce((e,t)=>t.added||t.removed?e:e+t.value.length,0)/r}function K(e){let t=[];for(let n of e){let e=t[t.length-1];e?.changed===n.changed?e.text+=n.text:t.push({...n})}return t}var q=class extends i{constructor(...e){super(...e),this.diff=``}render(){let e=M(this.diff);return e.length===0?r`<p class="empty">No diff.</p>`:r`
|
|
10
|
-
<div class="scroller">
|
|
11
|
-
<div class="diff-grid" role="table" aria-label="Unified diff">
|
|
12
|
-
${e.map(e=>this.renderLine(e))}
|
|
13
|
-
</div>
|
|
14
|
-
</div>
|
|
15
|
-
`}renderLine(e){let t=e.kind;return r`
|
|
16
|
-
<div class="line" role="row">
|
|
17
|
-
<span class=${`cell line-number old ${t}`} role="cell">${Y(e.oldLineNumber)}</span>
|
|
18
|
-
<span class=${`cell line-number new ${t}`} role="cell">${Y(e.newLineNumber)}</span>
|
|
19
|
-
<span class=${`cell prefix ${t}`} role="cell">${e.prefix}</span>
|
|
20
|
-
<span class=${`cell content ${t}`} role="cell">${J(e.spans)}</span>
|
|
21
|
-
</div>
|
|
22
|
-
`}static{this.styles=e`
|
|
23
|
-
:host { display: block; min-height: 0; height: 100%; color: var(--pi-text); background: var(--pi-bg); }
|
|
24
|
-
.empty { box-sizing: border-box; margin: 0; padding: 10px; color: var(--pi-muted); }
|
|
25
|
-
.scroller { height: 100%; min-height: 0; overflow: auto; background: var(--pi-bg); }
|
|
26
|
-
.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; }
|
|
27
|
-
.line { display: contents; }
|
|
28
|
-
.cell { min-height: 1.45em; white-space: pre; }
|
|
29
|
-
.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; }
|
|
30
|
-
.prefix { padding: 0 4px; color: var(--pi-dim); text-align: center; user-select: none; }
|
|
31
|
-
.content { padding: 0 12px 0 4px; }
|
|
32
|
-
.meta { color: var(--pi-dim); }
|
|
33
|
-
.hunk { background: color-mix(in srgb, var(--pi-accent) 9%, transparent); color: var(--pi-accent); }
|
|
34
|
-
.add { background: color-mix(in srgb, var(--pi-success) 12%, transparent); }
|
|
35
|
-
.remove { background: color-mix(in srgb, var(--pi-danger) 12%, transparent); }
|
|
36
|
-
.marker { color: var(--pi-dim); }
|
|
37
|
-
.content.add .inline-change { border-radius: 2px; background: color-mix(in srgb, var(--pi-success) 36%, transparent); color: var(--pi-text); }
|
|
38
|
-
.content.remove .inline-change { border-radius: 2px; background: color-mix(in srgb, var(--pi-danger) 36%, transparent); color: var(--pi-text); }
|
|
39
|
-
`}};t([n()],q.prototype,`diff`,void 0),q=t([a(`unified-diff-viewer`)],q);function J(e){return e.map(e=>r`<span class=${e.changed?`inline-change`:``}>${e.text}</span>`)}function Y(e){return e===void 0?``:String(e)}export{q as UnifiedDiffViewer};
|