@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,162 @@
|
|
|
1
|
+
import { PI_WEB_PLUGIN_LIFECYCLE_VERSION, } from "../shared/apiTypes.js";
|
|
2
|
+
import { PI_WEB_PLUGIN_RECOVERY_COMMANDS, pluginDisableRecoveryCommand } from "../shared/pluginRecoveryCommands.js";
|
|
3
|
+
/** Pure desired/active reconciliation shared by the manifest and diagnostics API. */
|
|
4
|
+
export function reconcilePiWebPluginLifecycle(desired, runtime, browserModuleUrl, desiredSafeStart) {
|
|
5
|
+
const activeSnapshot = runtime.status === "available" ? runtime.snapshot : undefined;
|
|
6
|
+
const desiredById = new Map(desired.plugins.map((plugin) => [plugin.id, plugin]));
|
|
7
|
+
const recordsById = new Map(activeSnapshot?.records.map((record) => [record.pluginId, record]) ?? []);
|
|
8
|
+
const healthById = new Map(activeSnapshot?.health.map((inspection) => [inspection.pluginId, inspection]) ?? []);
|
|
9
|
+
const diagnostics = publicDiagnostics(desired.diagnostics, activeSnapshot?.diagnostics ?? []);
|
|
10
|
+
const conflictIds = new Set(diagnostics.flatMap((diagnostic) => diagnostic.kind === "conflict" && diagnostic.pluginId !== undefined ? [diagnostic.pluginId] : []));
|
|
11
|
+
const pluginIds = new Set([...desiredById.keys(), ...recordsById.keys()]);
|
|
12
|
+
const browserPlugins = [];
|
|
13
|
+
const activeSafeStart = activeSnapshot?.safeStart ?? "off";
|
|
14
|
+
const effectiveDesiredSafeStart = desiredSafeStart ?? activeSafeStart;
|
|
15
|
+
const plugins = [...pluginIds]
|
|
16
|
+
.sort((left, right) => left.localeCompare(right))
|
|
17
|
+
.map((pluginId) => {
|
|
18
|
+
const plugin = desiredById.get(pluginId);
|
|
19
|
+
const record = recordsById.get(pluginId);
|
|
20
|
+
const server = plugin?.serverModule !== undefined || record !== undefined
|
|
21
|
+
? serverInfo(pluginId, plugin, record, healthById.get(pluginId), runtime.status, activeSafeStart, effectiveDesiredSafeStart)
|
|
22
|
+
: undefined;
|
|
23
|
+
if (plugin?.browserModule !== undefined && shouldPublishBrowserPlugin(plugin, server)) {
|
|
24
|
+
browserPlugins.push({
|
|
25
|
+
plugin,
|
|
26
|
+
...(server?.activeRevision === undefined ? {} : { backendRevision: server.activeRevision }),
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
if (plugin !== undefined) {
|
|
30
|
+
return {
|
|
31
|
+
id: plugin.id,
|
|
32
|
+
...(plugin.browserModule === undefined ? {} : { module: browserModuleUrl(plugin) }),
|
|
33
|
+
source: plugin.source,
|
|
34
|
+
scope: plugin.scope,
|
|
35
|
+
machineSpecific: plugin.machineSpecific,
|
|
36
|
+
enabled: plugin.enabled,
|
|
37
|
+
discovered: true,
|
|
38
|
+
conflict: conflictIds.has(plugin.id),
|
|
39
|
+
...(server === undefined ? {} : { server }),
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
if (record === undefined || server === undefined)
|
|
43
|
+
throw new Error(`Missing active server plugin record: ${pluginId}`);
|
|
44
|
+
return {
|
|
45
|
+
id: record.pluginId,
|
|
46
|
+
source: record.source,
|
|
47
|
+
scope: record.scope,
|
|
48
|
+
machineSpecific: record.machineSpecific,
|
|
49
|
+
enabled: false,
|
|
50
|
+
discovered: false,
|
|
51
|
+
conflict: conflictIds.has(record.pluginId),
|
|
52
|
+
server,
|
|
53
|
+
};
|
|
54
|
+
});
|
|
55
|
+
const safeStartRestartRequired = desiredSafeStart === undefined
|
|
56
|
+
? false
|
|
57
|
+
: runtime.status === "available"
|
|
58
|
+
? desiredSafeStart !== (activeSnapshot?.safeStart ?? "off")
|
|
59
|
+
: desiredSafeStart !== "off";
|
|
60
|
+
const restartRequired = safeStartRestartRequired || plugins.some((plugin) => plugin.server?.restartRequired === true);
|
|
61
|
+
return {
|
|
62
|
+
response: {
|
|
63
|
+
lifecycleVersion: PI_WEB_PLUGIN_LIFECYCLE_VERSION,
|
|
64
|
+
plugins,
|
|
65
|
+
diagnostics,
|
|
66
|
+
serverRuntime: {
|
|
67
|
+
status: runtime.status,
|
|
68
|
+
...(activeSnapshot?.safeStart === undefined ? {} : { safeStart: activeSnapshot.safeStart }),
|
|
69
|
+
...(desiredSafeStart === undefined ? {} : { desiredSafeStart }),
|
|
70
|
+
restartRequired,
|
|
71
|
+
...(runtime.status === "available" ? {} : { message: runtime.message }),
|
|
72
|
+
recovery: PI_WEB_PLUGIN_RECOVERY_COMMANDS,
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
browserPlugins: Object.freeze(browserPlugins),
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
function serverInfo(pluginId, desired, active, health, runtimeStatus, activeSafeStart, desiredSafeStart) {
|
|
79
|
+
const staleRevision = revisionsAreStale(desired, active);
|
|
80
|
+
const state = runtimeStatus !== "available"
|
|
81
|
+
? "unknown"
|
|
82
|
+
: active?.state ?? (desired !== undefined && !serverEnabledForSafeStart(desired, activeSafeStart) ? "disabled" : "missing");
|
|
83
|
+
const restartRequired = runtimeStatus === "available" && serverRestartRequired(desired, active, staleRevision, desiredSafeStart);
|
|
84
|
+
const phase = active?.phase ?? health?.phase;
|
|
85
|
+
const message = active?.message ?? health?.error;
|
|
86
|
+
return {
|
|
87
|
+
state,
|
|
88
|
+
...(desired?.serverModule === undefined ? {} : { desiredRevision: desired.serverModule.revision }),
|
|
89
|
+
...(active === undefined ? {} : { activeRevision: active.moduleRevision }),
|
|
90
|
+
...(phase === undefined ? {} : { phase }),
|
|
91
|
+
...(message === undefined ? {} : { message }),
|
|
92
|
+
...(health === undefined ? {} : {
|
|
93
|
+
health: {
|
|
94
|
+
status: health.health.status,
|
|
95
|
+
...(health.health.message === undefined ? {} : { message: health.health.message }),
|
|
96
|
+
},
|
|
97
|
+
}),
|
|
98
|
+
staleRevision,
|
|
99
|
+
restartRequired,
|
|
100
|
+
disableCommand: pluginDisableRecoveryCommand(pluginId),
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
function serverRestartRequired(desired, active, staleRevision, desiredSafeStart) {
|
|
104
|
+
if (desired === undefined) {
|
|
105
|
+
if (active === undefined)
|
|
106
|
+
return false;
|
|
107
|
+
return active.state !== "disabled";
|
|
108
|
+
}
|
|
109
|
+
const shouldBeActive = serverEnabledForSafeStart(desired, desiredSafeStart);
|
|
110
|
+
if (active === undefined)
|
|
111
|
+
return shouldBeActive;
|
|
112
|
+
if (!shouldBeActive)
|
|
113
|
+
return active.state !== "disabled";
|
|
114
|
+
if (staleRevision)
|
|
115
|
+
return true;
|
|
116
|
+
return active.state !== "active";
|
|
117
|
+
}
|
|
118
|
+
function serverEnabledForSafeStart(plugin, safeStart) {
|
|
119
|
+
return plugin.enabled
|
|
120
|
+
&& safeStart !== "none"
|
|
121
|
+
&& (safeStart !== "bundled-only" || plugin.scope === "bundled");
|
|
122
|
+
}
|
|
123
|
+
function shouldPublishBrowserPlugin(plugin, server) {
|
|
124
|
+
if (plugin.browserModule === undefined)
|
|
125
|
+
return false;
|
|
126
|
+
if (server === undefined)
|
|
127
|
+
return plugin.enabled;
|
|
128
|
+
if (plugin.serverModule === undefined)
|
|
129
|
+
return false;
|
|
130
|
+
return server.state === "active"
|
|
131
|
+
&& !server.staleRevision
|
|
132
|
+
&& server.health?.status !== "unhealthy";
|
|
133
|
+
}
|
|
134
|
+
function revisionsAreStale(desired, active) {
|
|
135
|
+
if (desired === undefined)
|
|
136
|
+
return false;
|
|
137
|
+
if (active === undefined)
|
|
138
|
+
return false;
|
|
139
|
+
const browserRevision = desired.browserModule?.revision;
|
|
140
|
+
return desired.serverModule?.revision !== active.moduleRevision
|
|
141
|
+
|| (browserRevision !== undefined && browserRevision !== active.browserRevision)
|
|
142
|
+
|| desired.settingsRevision !== active.settingsRevision
|
|
143
|
+
|| desired.source !== active.source
|
|
144
|
+
|| desired.scope !== active.scope
|
|
145
|
+
|| desired.machineSpecific !== active.machineSpecific;
|
|
146
|
+
}
|
|
147
|
+
function publicDiagnostics(desired, active) {
|
|
148
|
+
return [
|
|
149
|
+
...desired.map((diagnostic) => publicDiagnostic(diagnostic, "desired")),
|
|
150
|
+
...active.map((diagnostic) => publicDiagnostic(diagnostic, "active")),
|
|
151
|
+
];
|
|
152
|
+
}
|
|
153
|
+
function publicDiagnostic(diagnostic, snapshot) {
|
|
154
|
+
return {
|
|
155
|
+
kind: diagnostic.code === "duplicate-id" ? "conflict" : "discovery",
|
|
156
|
+
snapshot,
|
|
157
|
+
source: diagnostic.source,
|
|
158
|
+
message: diagnostic.message,
|
|
159
|
+
...(diagnostic.pluginId === undefined ? {} : { pluginId: diagnostic.pluginId }),
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
//# sourceMappingURL=piWebPluginLifecycle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"piWebPluginLifecycle.js","sourceRoot":"","sources":["../../src/server/piWebPluginLifecycle.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,156 +1,184 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { readdir, readFile, realpath, stat } from "node:fs/promises";
|
|
3
|
-
import { dirname, join, relative, resolve, sep } from "node:path";
|
|
4
|
-
import { fileURLToPath } from "node:url";
|
|
5
|
-
import { DefaultPackageManager, SettingsManager } from "@earendil-works/pi-coding-agent";
|
|
6
|
-
import { loadPiWebConfig, piWebDataDir } from "../config.js";
|
|
1
|
+
import { PI_WEB_PLUGIN_LIFECYCLE_VERSION } from "../shared/apiTypes.js";
|
|
7
2
|
import { isPiWebPluginId } from "../shared/pluginIds.js";
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
}
|
|
16
|
-
getInstalledPath(source, scope) {
|
|
17
|
-
return this.createPackageManager().getInstalledPath(source, scope);
|
|
18
|
-
}
|
|
19
|
-
createPackageManager() {
|
|
20
|
-
return new DefaultPackageManager({
|
|
21
|
-
cwd: this.cwd,
|
|
22
|
-
agentDir: this.agentDir,
|
|
23
|
-
settingsManager: SettingsManager.create(this.cwd, this.agentDir),
|
|
24
|
-
});
|
|
25
|
-
}
|
|
26
|
-
}
|
|
3
|
+
import { PiWebPluginCatalog, readPiWebPluginPackageArtifact, } from "./piWebPluginCatalog.js";
|
|
4
|
+
import { reconcilePiWebPluginLifecycle } from "./piWebPluginLifecycle.js";
|
|
5
|
+
import { WorkspaceCatalogProtocolError } from "./workspaces/workspaceCatalog.js";
|
|
6
|
+
export { DefaultPiPackageProvider, PiWebPluginCatalog, } from "./piWebPluginCatalog.js";
|
|
7
|
+
const BROWSER_ARTIFACT_CACHE_MAX_ENTRIES = 32;
|
|
8
|
+
const BROWSER_ARTIFACT_CACHE_MAX_BYTES = 64 * 1024 * 1024;
|
|
9
|
+
/** Browser manifest and asset adapter over the process-neutral package catalog. */
|
|
27
10
|
export class PiWebPluginService {
|
|
28
11
|
constructor(options = {}) {
|
|
29
|
-
|
|
30
|
-
this.
|
|
31
|
-
this.
|
|
32
|
-
this.
|
|
33
|
-
|
|
34
|
-
this.staticPackageProvider = packageProvider === false || packageProvider === undefined ? undefined : packageProvider;
|
|
35
|
-
this.packageProviderForAgentDir = packageProvider === false || packageProvider !== undefined
|
|
36
|
-
? undefined
|
|
37
|
-
: (agentDir) => new DefaultPiPackageProvider(cwd, agentDir);
|
|
38
|
-
this.configProvider = options.configProvider ?? (() => loadPiWebConfig({ cwd }).config);
|
|
12
|
+
this.browserArtifacts = new Map();
|
|
13
|
+
this.browserArtifactBytes = 0;
|
|
14
|
+
this.catalog = options.catalog ?? new PiWebPluginCatalog(options);
|
|
15
|
+
this.runtimeProvider = options.runtimeProvider;
|
|
16
|
+
this.recoveryProvider = options.recoveryProvider;
|
|
39
17
|
}
|
|
40
18
|
async manifest() {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
19
|
+
const lifecycle = await this.lifecycle();
|
|
20
|
+
const plugins = [];
|
|
21
|
+
for (const { plugin, backendRevision } of lifecycle.browserPlugins) {
|
|
22
|
+
const artifact = await this.captureBrowserArtifact(plugin, backendRevision);
|
|
23
|
+
if (artifact === undefined)
|
|
24
|
+
continue;
|
|
25
|
+
plugins.push({
|
|
26
|
+
id: plugin.id,
|
|
27
|
+
module: browserModuleUrl(plugin),
|
|
28
|
+
...(backendRevision === undefined ? {} : { backendRevision }),
|
|
29
|
+
source: plugin.source,
|
|
30
|
+
scope: plugin.scope,
|
|
31
|
+
machineSpecific: plugin.machineSpecific,
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
return { lifecycleVersion: PI_WEB_PLUGIN_LIFECYCLE_VERSION, plugins };
|
|
46
35
|
}
|
|
47
36
|
async plugins() {
|
|
48
|
-
|
|
49
|
-
const plugins = await this.discoverPlugins();
|
|
50
|
-
return { plugins: plugins.map((plugin) => this.pluginInfo(plugin, config)) };
|
|
37
|
+
return (await this.lifecycle()).response;
|
|
51
38
|
}
|
|
52
|
-
async readAsset(pluginId, assetPath) {
|
|
39
|
+
async readAsset(pluginId, assetPath, browserRevision) {
|
|
53
40
|
if (!isPiWebPluginId(pluginId))
|
|
54
41
|
return undefined;
|
|
55
|
-
|
|
56
|
-
if (
|
|
42
|
+
let artifact = this.browserArtifacts.get(pluginId);
|
|
43
|
+
if (artifact !== undefined && !await this.cachedArtifactIsActive(artifact))
|
|
44
|
+
artifact = undefined;
|
|
45
|
+
artifact ??= await this.loadBrowserArtifact(pluginId);
|
|
46
|
+
if (artifact === undefined)
|
|
57
47
|
return undefined;
|
|
58
|
-
|
|
59
|
-
const [realRoot, realAsset] = await Promise.all([
|
|
60
|
-
realpath(plugin.root),
|
|
61
|
-
realpath(resolved).catch(() => undefined),
|
|
62
|
-
]);
|
|
63
|
-
if (realAsset === undefined || !isWithin(realRoot, realAsset))
|
|
48
|
+
if (browserRevision !== undefined && assetPath === artifact.entryPath && artifact.revision !== browserRevision)
|
|
64
49
|
return undefined;
|
|
65
|
-
const
|
|
66
|
-
if (
|
|
50
|
+
const content = artifact.files.get(assetPath);
|
|
51
|
+
if (content === undefined)
|
|
67
52
|
return undefined;
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
pluginInfo(plugin, config) {
|
|
71
|
-
return {
|
|
72
|
-
id: plugin.id,
|
|
73
|
-
module: `/pi-web-plugins/${encodeURIComponent(plugin.id)}/${plugin.entryFile}?${pluginModuleQuery(plugin)}`,
|
|
74
|
-
source: plugin.source,
|
|
75
|
-
scope: plugin.scope,
|
|
76
|
-
machineSpecific: plugin.machineSpecific,
|
|
77
|
-
enabled: config.plugins?.[plugin.id]?.enabled !== false,
|
|
78
|
-
};
|
|
53
|
+
this.touchBrowserArtifact(artifact);
|
|
54
|
+
return { content, contentType: contentTypeFor(assetPath) };
|
|
79
55
|
}
|
|
80
|
-
async
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
56
|
+
async loadBrowserArtifact(pluginId) {
|
|
57
|
+
try {
|
|
58
|
+
const lifecycle = await this.lifecycle();
|
|
59
|
+
const browserPlugin = lifecycle.browserPlugins.find(({ plugin }) => plugin.id === pluginId);
|
|
60
|
+
if (browserPlugin === undefined)
|
|
61
|
+
return undefined;
|
|
62
|
+
return await this.captureBrowserArtifact(browserPlugin.plugin, browserPlugin.backendRevision);
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
const localPlugin = await this.catalog.browserPlugin(pluginId);
|
|
66
|
+
if (localPlugin?.serverModule !== undefined)
|
|
67
|
+
throw error;
|
|
68
|
+
return localPlugin === undefined ? undefined : await this.captureBrowserArtifact(localPlugin);
|
|
88
69
|
}
|
|
89
|
-
return [...records.values()].sort((left, right) => left.id.localeCompare(right.id));
|
|
90
70
|
}
|
|
91
|
-
async
|
|
92
|
-
const
|
|
93
|
-
if (
|
|
94
|
-
return localPlugin;
|
|
95
|
-
const packageProvider = await this.currentPackageProvider();
|
|
96
|
-
if (packageProvider === undefined)
|
|
71
|
+
async captureBrowserArtifact(plugin, backendRevision) {
|
|
72
|
+
const module = plugin.browserModule;
|
|
73
|
+
if (module === undefined)
|
|
97
74
|
return undefined;
|
|
98
|
-
const
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
75
|
+
const browserRoot = plugin.browserRoot;
|
|
76
|
+
if (browserRoot === undefined)
|
|
77
|
+
throw new Error(`PI WEB plugin has no browser root: ${plugin.id}`);
|
|
78
|
+
const cached = this.browserArtifacts.get(plugin.id);
|
|
79
|
+
if (cached !== undefined) {
|
|
80
|
+
const matches = cached.revision === module.revision
|
|
81
|
+
&& cached.entryPath === module.path
|
|
82
|
+
&& cached.entryFilePath === module.filePath
|
|
83
|
+
&& cached.browserRootPath === browserRoot.path
|
|
84
|
+
&& cached.browserRootDirectoryPath === browserRoot.directoryPath
|
|
85
|
+
&& cached.packageRoot === plugin.packageRoot
|
|
86
|
+
&& cached.backendRevision === backendRevision;
|
|
87
|
+
if (matches) {
|
|
88
|
+
this.touchBrowserArtifact(cached);
|
|
89
|
+
return cached;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
const packageArtifact = await readPiWebPluginPackageArtifact(plugin.packageRoot, browserRoot).catch(() => undefined);
|
|
93
|
+
if (packageArtifact?.revision !== module.revision || !packageArtifact.files.has(module.path))
|
|
107
94
|
return undefined;
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
return
|
|
95
|
+
const artifact = {
|
|
96
|
+
pluginId: plugin.id,
|
|
97
|
+
revision: module.revision,
|
|
98
|
+
entryPath: module.path,
|
|
99
|
+
entryFilePath: module.filePath,
|
|
100
|
+
browserRootPath: browserRoot.path,
|
|
101
|
+
browserRootDirectoryPath: browserRoot.directoryPath,
|
|
102
|
+
packageRoot: plugin.packageRoot,
|
|
103
|
+
...(backendRevision === undefined ? {} : { backendRevision }),
|
|
104
|
+
files: packageArtifact.files,
|
|
105
|
+
byteLength: packageArtifact.byteLength,
|
|
106
|
+
};
|
|
107
|
+
this.cacheBrowserArtifact(artifact);
|
|
108
|
+
return artifact;
|
|
109
|
+
}
|
|
110
|
+
async cachedArtifactIsActive(artifact) {
|
|
111
|
+
if (artifact.backendRevision === undefined)
|
|
112
|
+
return true;
|
|
113
|
+
const runtime = await this.loadRuntime();
|
|
114
|
+
if (runtime.status !== "available")
|
|
115
|
+
return false;
|
|
116
|
+
const record = runtime.snapshot.records.find(({ pluginId }) => pluginId === artifact.pluginId);
|
|
117
|
+
const health = runtime.snapshot.health.find(({ pluginId }) => pluginId === artifact.pluginId);
|
|
118
|
+
return record?.state === "active"
|
|
119
|
+
&& record.moduleRevision === artifact.backendRevision
|
|
120
|
+
&& record.browserRevision === artifact.revision
|
|
121
|
+
&& health?.health.status !== "unhealthy";
|
|
122
|
+
}
|
|
123
|
+
cacheBrowserArtifact(artifact) {
|
|
124
|
+
const current = this.browserArtifacts.get(artifact.pluginId);
|
|
125
|
+
if (current !== undefined) {
|
|
126
|
+
this.browserArtifacts.delete(artifact.pluginId);
|
|
127
|
+
this.browserArtifactBytes -= current.byteLength;
|
|
128
|
+
}
|
|
129
|
+
while (this.browserArtifacts.size >= BROWSER_ARTIFACT_CACHE_MAX_ENTRIES
|
|
130
|
+
|| this.browserArtifactBytes + artifact.byteLength > BROWSER_ARTIFACT_CACHE_MAX_BYTES) {
|
|
131
|
+
const oldest = this.browserArtifacts.values().next().value;
|
|
132
|
+
if (oldest === undefined)
|
|
133
|
+
break;
|
|
134
|
+
this.browserArtifacts.delete(oldest.pluginId);
|
|
135
|
+
this.browserArtifactBytes -= oldest.byteLength;
|
|
136
|
+
}
|
|
137
|
+
this.browserArtifacts.set(artifact.pluginId, artifact);
|
|
138
|
+
this.browserArtifactBytes += artifact.byteLength;
|
|
139
|
+
}
|
|
140
|
+
touchBrowserArtifact(artifact) {
|
|
141
|
+
if (this.browserArtifacts.get(artifact.pluginId) !== artifact)
|
|
142
|
+
return;
|
|
143
|
+
this.browserArtifacts.delete(artifact.pluginId);
|
|
144
|
+
this.browserArtifacts.set(artifact.pluginId, artifact);
|
|
145
|
+
}
|
|
146
|
+
async lifecycle() {
|
|
147
|
+
const desired = await this.catalog.snapshot();
|
|
148
|
+
const [runtime, desiredSafeStart] = await Promise.all([this.loadRuntime(), this.loadDesiredSafeStart()]);
|
|
149
|
+
return reconcilePiWebPluginLifecycle(desired, runtime, browserModuleUrl, desiredSafeStart);
|
|
150
|
+
}
|
|
151
|
+
async loadDesiredSafeStart() {
|
|
152
|
+
if (this.recoveryProvider === undefined)
|
|
153
|
+
return undefined;
|
|
154
|
+
return (await this.recoveryProvider()).safeStart ?? "off";
|
|
122
155
|
}
|
|
123
|
-
async
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
156
|
+
async loadRuntime() {
|
|
157
|
+
if (this.runtimeProvider === undefined) {
|
|
158
|
+
return { status: "unavailable", message: "Session daemon server-plugin runtime is unavailable" };
|
|
159
|
+
}
|
|
160
|
+
try {
|
|
161
|
+
return { status: "available", snapshot: await this.runtimeProvider.providerRuntime() };
|
|
162
|
+
}
|
|
163
|
+
catch (error) {
|
|
164
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
165
|
+
return {
|
|
166
|
+
status: error instanceof WorkspaceCatalogProtocolError ? "incompatible" : "unavailable",
|
|
167
|
+
message,
|
|
168
|
+
};
|
|
135
169
|
}
|
|
136
|
-
return plugins;
|
|
137
170
|
}
|
|
138
171
|
}
|
|
139
|
-
function
|
|
140
|
-
const
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
{ path: join(piWebDataDir(), "plugins"), source: "local", scope: "local" },
|
|
146
|
-
];
|
|
172
|
+
function browserModuleUrl(plugin) {
|
|
173
|
+
const browserModule = plugin.browserModule;
|
|
174
|
+
if (browserModule === undefined)
|
|
175
|
+
throw new Error(`PI WEB plugin has no browser module: ${plugin.id}`);
|
|
176
|
+
const path = browserModule.path.split("/").map((segment) => encodeURIComponent(segment)).join("/");
|
|
177
|
+
return `/pi-web-plugins/${encodeURIComponent(plugin.id)}/${path}?${pluginModuleQuery(plugin.id, browserModule.revision)}`;
|
|
147
178
|
}
|
|
148
|
-
function
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
function pluginModuleQuery(plugin) {
|
|
152
|
-
const params = new URLSearchParams({ v: plugin.version });
|
|
153
|
-
const dockerMode = plugin.id === "updates" ? dockerModeFromEnv() : undefined;
|
|
179
|
+
function pluginModuleQuery(pluginId, revision) {
|
|
180
|
+
const params = new URLSearchParams({ v: revision });
|
|
181
|
+
const dockerMode = pluginId === "updates" ? dockerModeFromEnv() : undefined;
|
|
154
182
|
if (dockerMode !== undefined)
|
|
155
183
|
params.set("piWebDockerMode", dockerMode);
|
|
156
184
|
return params.toString();
|
|
@@ -179,136 +207,9 @@ function isTruthyEnv(key) {
|
|
|
179
207
|
const value = process.env[key];
|
|
180
208
|
return value !== undefined && value !== "" && value !== "0" && value.toLowerCase() !== "false";
|
|
181
209
|
}
|
|
182
|
-
function sourceCheckoutPluginRoots(cwd) {
|
|
183
|
-
const pluginsRoot = join(cwd, "plugins");
|
|
184
|
-
if (!existsSync(join(cwd, "src", "server", "index.ts")) || !existsSync(pluginsRoot))
|
|
185
|
-
return [];
|
|
186
|
-
return [{ path: pluginsRoot, source: "dev", scope: "local" }];
|
|
187
|
-
}
|
|
188
|
-
async function discoverLocalRoot(root) {
|
|
189
|
-
if (!existsSync(root.path))
|
|
190
|
-
return [];
|
|
191
|
-
const entries = await readdir(root.path, { withFileTypes: true }).catch(() => []);
|
|
192
|
-
const plugins = [];
|
|
193
|
-
for (const entry of entries) {
|
|
194
|
-
if (!isPiWebPluginId(entry.name))
|
|
195
|
-
continue;
|
|
196
|
-
const pluginRoot = join(root.path, entry.name);
|
|
197
|
-
const pluginStat = entry.isDirectory() ? undefined : entry.isSymbolicLink() ? await stat(pluginRoot).catch(() => undefined) : undefined;
|
|
198
|
-
if (!entry.isDirectory() && pluginStat?.isDirectory() !== true)
|
|
199
|
-
continue;
|
|
200
|
-
try {
|
|
201
|
-
plugins.push(...await discoverLocalPlugin(pluginRoot, root));
|
|
202
|
-
}
|
|
203
|
-
catch (error) {
|
|
204
|
-
warnInvalidPlugin(pluginRoot, error);
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
return plugins;
|
|
208
|
-
}
|
|
209
|
-
async function discoverLocalPlugin(root, localRoot) {
|
|
210
|
-
const config = await readPiWebPackageConfig(root);
|
|
211
|
-
if (config === undefined)
|
|
212
|
-
return [];
|
|
213
|
-
const plugins = await discoverPluginEntries(root, config);
|
|
214
|
-
return plugins.map((plugin) => ({ ...plugin, source: localRoot.source, scope: localRoot.scope }));
|
|
215
|
-
}
|
|
216
|
-
async function discoverPackageRoot(root, configuredPackage) {
|
|
217
|
-
const config = await readPiWebPackageConfig(root);
|
|
218
|
-
if (config === undefined)
|
|
219
|
-
return [];
|
|
220
|
-
const plugins = await discoverPluginEntries(root, config);
|
|
221
|
-
return plugins.map((plugin) => ({ ...plugin, source: configuredPackage.source, scope: configuredPackage.scope }));
|
|
222
|
-
}
|
|
223
|
-
async function discoverPluginEntries(root, config) {
|
|
224
|
-
const plugins = [];
|
|
225
|
-
for (const entry of config.plugins) {
|
|
226
|
-
if (!isSafeRelativePath(entry.module))
|
|
227
|
-
throw new Error(`Unsafe PI WEB plugin module path for ${entry.id}: ${entry.module}`);
|
|
228
|
-
const entryPath = join(root, entry.module);
|
|
229
|
-
const entryStat = await stat(entryPath).catch(() => undefined);
|
|
230
|
-
if (entryStat?.isFile() !== true)
|
|
231
|
-
throw new Error(`PI WEB plugin module not found for ${entry.id}: ${entry.module}`);
|
|
232
|
-
plugins.push({ id: entry.id, root, entryFile: entry.module, version: String(Math.floor(entryStat.mtimeMs)), machineSpecific: entry.machineSpecific });
|
|
233
|
-
}
|
|
234
|
-
return plugins;
|
|
235
|
-
}
|
|
236
|
-
async function readPiWebPackageConfig(root) {
|
|
237
|
-
const packagePath = join(root, "package.json");
|
|
238
|
-
const content = await readFile(packagePath, "utf8").catch(() => undefined);
|
|
239
|
-
if (content === undefined)
|
|
240
|
-
return undefined;
|
|
241
|
-
const parsed = JSON.parse(content);
|
|
242
|
-
if (!isRecord(parsed))
|
|
243
|
-
return undefined;
|
|
244
|
-
const piWeb = parsed["piWeb"];
|
|
245
|
-
if (!isRecord(piWeb))
|
|
246
|
-
return undefined;
|
|
247
|
-
const plugins = parsePluginEntries(piWeb, packagePath);
|
|
248
|
-
if (plugins.length === 0)
|
|
249
|
-
return undefined;
|
|
250
|
-
return { plugins };
|
|
251
|
-
}
|
|
252
|
-
function parsePluginEntries(piWeb, packagePath) {
|
|
253
|
-
if (piWeb["plugin"] !== undefined)
|
|
254
|
-
throw new Error(`Unsupported PI WEB plugin metadata in ${packagePath}: use piWeb.plugins with { id, module, machineSpecific? } entries`);
|
|
255
|
-
const plugins = piWeb["plugins"];
|
|
256
|
-
if (plugins === undefined)
|
|
257
|
-
return [];
|
|
258
|
-
if (!Array.isArray(plugins))
|
|
259
|
-
throw new Error(`PI WEB plugins must be an array in ${packagePath}`);
|
|
260
|
-
return plugins.map((entry, index) => {
|
|
261
|
-
if (!isRecord(entry))
|
|
262
|
-
throw new Error(`PI WEB plugin entry ${String(index + 1)} must be an object in ${packagePath}`);
|
|
263
|
-
const id = entry["id"];
|
|
264
|
-
const module = entry["module"];
|
|
265
|
-
if (typeof id !== "string" || !isPiWebPluginId(id))
|
|
266
|
-
throw new Error(`Invalid PI WEB plugin id in ${packagePath}: ${String(id)}`);
|
|
267
|
-
if (typeof module !== "string" || module === "")
|
|
268
|
-
throw new Error(`Invalid PI WEB plugin module for ${id} in ${packagePath}`);
|
|
269
|
-
return { id, module, machineSpecific: parseMachineSpecific(entry["machineSpecific"], packagePath, id) };
|
|
270
|
-
});
|
|
271
|
-
}
|
|
272
|
-
function parseMachineSpecific(value, packagePath, pluginId) {
|
|
273
|
-
if (value === undefined)
|
|
274
|
-
return false;
|
|
275
|
-
if (typeof value !== "boolean")
|
|
276
|
-
throw new Error(`Invalid PI WEB plugin machineSpecific value for ${pluginId} in ${packagePath}: ${formatUnknownValue(value)}`);
|
|
277
|
-
return value;
|
|
278
|
-
}
|
|
279
|
-
function formatUnknownValue(value) {
|
|
280
|
-
if (typeof value === "string")
|
|
281
|
-
return value;
|
|
282
|
-
if (typeof value === "number" || typeof value === "boolean" || typeof value === "bigint" || typeof value === "symbol" || typeof value === "function" || value === null || value === undefined)
|
|
283
|
-
return String(value);
|
|
284
|
-
try {
|
|
285
|
-
return JSON.stringify(value);
|
|
286
|
-
}
|
|
287
|
-
catch {
|
|
288
|
-
return Object.prototype.toString.call(value);
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
function addUnique(records, plugin) {
|
|
292
|
-
if (records.has(plugin.id)) {
|
|
293
|
-
warnInvalidPlugin(plugin.source, `Duplicate PI WEB plugin id: ${plugin.id}`);
|
|
294
|
-
return;
|
|
295
|
-
}
|
|
296
|
-
records.set(plugin.id, plugin);
|
|
297
|
-
}
|
|
298
|
-
function warnInvalidPlugin(source, error) {
|
|
299
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
300
|
-
console.warn(`Skipping PI WEB plugin from ${source}: ${message}`);
|
|
301
|
-
}
|
|
302
|
-
function isSafeRelativePath(path) {
|
|
303
|
-
return path !== "" && !path.includes("..") && !path.startsWith("/");
|
|
304
|
-
}
|
|
305
|
-
function isWithin(root, candidate) {
|
|
306
|
-
const rel = relative(root, candidate);
|
|
307
|
-
return rel === "" || (!rel.startsWith("..") && !rel.startsWith(sep));
|
|
308
|
-
}
|
|
309
210
|
function contentTypeFor(path) {
|
|
310
211
|
const lowerPath = path.toLowerCase();
|
|
311
|
-
if (lowerPath.endsWith(".js"))
|
|
212
|
+
if (lowerPath.endsWith(".js") || lowerPath.endsWith(".mjs"))
|
|
312
213
|
return "application/javascript; charset=utf-8";
|
|
313
214
|
if (lowerPath.endsWith(".json"))
|
|
314
215
|
return "application/json; charset=utf-8";
|
|
@@ -320,7 +221,4 @@ function contentTypeFor(path) {
|
|
|
320
221
|
return "image/svg+xml";
|
|
321
222
|
return "application/octet-stream";
|
|
322
223
|
}
|
|
323
|
-
function isRecord(value) {
|
|
324
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
325
|
-
}
|
|
326
224
|
//# sourceMappingURL=piWebPluginService.js.map
|