@vincenthanxiaodu/pi-web 1.202608.1
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/LICENSE +21 -0
- package/README.md +185 -0
- package/dist/cli.js +1149 -0
- package/dist/cli.js.map +1 -0
- package/dist/client/apple-touch-icon.png +0 -0
- package/dist/client/assets/CodeViewer-D_Q6ljLV.js +4 -0
- package/dist/client/assets/TerminalPanel-CTGixJIz.js +187 -0
- package/dist/client/assets/index-C2phil_t.js +5637 -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/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/favicon.svg +11 -0
- package/dist/client/index.html +124 -0
- package/dist/client/manifest.webmanifest +24 -0
- package/dist/client/pwa-icon-192.png +0 -0
- package/dist/client/pwa-icon-512.png +0 -0
- package/dist/config.js +505 -0
- package/dist/config.js.map +1 -0
- package/dist/docker/piWebDockerCommandPlan.js +212 -0
- package/dist/docker/piWebDockerCommandPlan.js.map +1 -0
- 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 +783 -0
- package/dist/nativeServices/serviceDoctor.js.map +1 -0
- package/dist/nativeServices/serviceInstall.js +35 -0
- package/dist/nativeServices/serviceInstall.js.map +1 -0
- package/dist/nativeServices/servicePlan.js +358 -0
- package/dist/nativeServices/servicePlan.js.map +1 -0
- package/dist/nativeServices/serviceProbe.js +447 -0
- package/dist/nativeServices/serviceProbe.js.map +1 -0
- package/dist/nativeServices/serviceRendering.js +132 -0
- package/dist/nativeServices/serviceRendering.js.map +1 -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/pi-web-plugins/git/git-backend.js +439 -0
- 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 +222 -0
- package/dist/pi-web-plugins/info/package.json +9 -0
- package/dist/pi-web-plugins/info/pi-web-plugin.js +48 -0
- package/dist/pi-web-plugins/relays/markdownDocument.js +81 -0
- package/dist/pi-web-plugins/relays/package.json +9 -0
- package/dist/pi-web-plugins/relays/pi-web-plugin.js +44 -0
- package/dist/pi-web-plugins/relays/relayDiscovery.js +228 -0
- package/dist/pi-web-plugins/relays/relaysPanelElement.js +550 -0
- package/dist/pi-web-plugins/relays/vendor/README.md +24 -0
- package/dist/pi-web-plugins/relays/vendor/marked.esm.js +76 -0
- package/dist/pi-web-plugins/updates/package.json +9 -0
- package/dist/pi-web-plugins/updates/pi-web-plugin.js +185 -0
- package/dist/pi-web-plugins/updates/updatesLogic.js +97 -0
- package/dist/pi-web-plugins/workspace-tasks/config.js +91 -0
- package/dist/pi-web-plugins/workspace-tasks/package.json +9 -0
- package/dist/pi-web-plugins/workspace-tasks/pi-web-plugin.js +48 -0
- package/dist/pi-web-plugins/workspace-tasks/taskRunner.js +12 -0
- package/dist/pi-web-plugins/workspace-tasks/tasksPanelElement.js +288 -0
- package/dist/pi-web-plugins/workspace-tasks/workspaceTasksClient.js +47 -0
- package/dist/piWebVersionReport.js +278 -0
- package/dist/piWebVersionReport.js.map +1 -0
- package/dist/plugin-api.d.ts +222 -0
- package/dist/pluginRecoveryCli.js +172 -0
- package/dist/pluginRecoveryCli.js.map +1 -0
- package/dist/server/activeAgentProfileProvider.js +25 -0
- package/dist/server/activeAgentProfileProvider.js.map +1 -0
- package/dist/server/activity/workspaceActivityService.js +106 -0
- package/dist/server/activity/workspaceActivityService.js.map +1 -0
- package/dist/server/app.js +218 -0
- package/dist/server/app.js.map +1 -0
- package/dist/server/browserMessageProjection.js +54 -0
- package/dist/server/browserMessageProjection.js.map +1 -0
- package/dist/server/configRoutes.js +293 -0
- package/dist/server/configRoutes.js.map +1 -0
- package/dist/server/diagnostics/nodePtyNativeModule.js +36 -0
- package/dist/server/diagnostics/nodePtyNativeModule.js.map +1 -0
- package/dist/server/diagnostics/nodePtySpawnHelper.js +135 -0
- package/dist/server/diagnostics/nodePtySpawnHelper.js.map +1 -0
- package/dist/server/git/gitEnv.js +15 -0
- package/dist/server/git/gitEnv.js.map +1 -0
- package/dist/server/goals/goalArchive.js +184 -0
- package/dist/server/goals/goalArchive.js.map +1 -0
- package/dist/server/goals/goalFile.js +200 -0
- package/dist/server/goals/goalFile.js.map +1 -0
- package/dist/server/goals/goalStore.js +65 -0
- package/dist/server/goals/goalStore.js.map +1 -0
- package/dist/server/index.js +7 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/machines/machineClient.js +191 -0
- package/dist/server/machines/machineClient.js.map +1 -0
- package/dist/server/machines/machinePluginProxyRoutes.js +247 -0
- package/dist/server/machines/machinePluginProxyRoutes.js.map +1 -0
- package/dist/server/machines/machineProxyRoutes.js +318 -0
- package/dist/server/machines/machineProxyRoutes.js.map +1 -0
- package/dist/server/machines/machineRoutes.js +56 -0
- package/dist/server/machines/machineRoutes.js.map +1 -0
- package/dist/server/machines/machineService.js +274 -0
- package/dist/server/machines/machineService.js.map +1 -0
- package/dist/server/machines/machineStore.js +143 -0
- package/dist/server/machines/machineStore.js.map +1 -0
- package/dist/server/piPackageRoutes.js +91 -0
- package/dist/server/piPackageRoutes.js.map +1 -0
- package/dist/server/piPackageService.js +101 -0
- package/dist/server/piPackageService.js.map +1 -0
- 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 +224 -0
- package/dist/server/piWebPluginService.js.map +1 -0
- package/dist/server/piWebReleaseLookupCache.js +37 -0
- package/dist/server/piWebReleaseLookupCache.js.map +1 -0
- package/dist/server/piWebStatus.js +624 -0
- package/dist/server/piWebStatus.js.map +1 -0
- package/dist/server/piWebStatusCache.js +45 -0
- package/dist/server/piWebStatusCache.js.map +1 -0
- 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/directorySuggestions.js +207 -0
- package/dist/server/projects/directorySuggestions.js.map +1 -0
- package/dist/server/projects/projectService.js +33 -0
- package/dist/server/projects/projectService.js.map +1 -0
- package/dist/server/realtime/sessionEventHub.js +93 -0
- package/dist/server/realtime/sessionEventHub.js.map +1 -0
- package/dist/server/requestCancellation.js +32 -0
- package/dist/server/requestCancellation.js.map +1 -0
- package/dist/server/sessiond/agentHttpDispatcher.js +108 -0
- package/dist/server/sessiond/agentHttpDispatcher.js.map +1 -0
- package/dist/server/sessiond/agentProcessEnvironment.js +61 -0
- package/dist/server/sessiond/agentProcessEnvironment.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 +31 -0
- package/dist/server/sessiond/sessionDaemonShutdown.js.map +1 -0
- package/dist/server/sessiond/sessionProxyRoutes.js +61 -0
- package/dist/server/sessiond/sessionProxyRoutes.js.map +1 -0
- package/dist/server/sessiond/sessionServiceDependencies.js +34 -0
- package/dist/server/sessiond/sessionServiceDependencies.js.map +1 -0
- 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 +387 -0
- package/dist/server/sessiond.js.map +1 -0
- package/dist/server/sessions/askUserTool.js +102 -0
- package/dist/server/sessions/askUserTool.js.map +1 -0
- package/dist/server/sessions/attachmentService.js +119 -0
- package/dist/server/sessions/attachmentService.js.map +1 -0
- package/dist/server/sessions/authProviderOptions.js +50 -0
- package/dist/server/sessions/authProviderOptions.js.map +1 -0
- package/dist/server/sessions/authRoutes.js +59 -0
- package/dist/server/sessions/authRoutes.js.map +1 -0
- package/dist/server/sessions/authService.js +122 -0
- package/dist/server/sessions/authService.js.map +1 -0
- package/dist/server/sessions/builtinCommands.js +27 -0
- package/dist/server/sessions/builtinCommands.js.map +1 -0
- package/dist/server/sessions/dockerEnvironmentFacts.js +254 -0
- package/dist/server/sessions/dockerEnvironmentFacts.js.map +1 -0
- package/dist/server/sessions/editPreview.js +196 -0
- package/dist/server/sessions/editPreview.js.map +1 -0
- package/dist/server/sessions/extensionDialogWaiters.js +76 -0
- package/dist/server/sessions/extensionDialogWaiters.js.map +1 -0
- package/dist/server/sessions/globalProviderPolicy.js +167 -0
- package/dist/server/sessions/globalProviderPolicy.js.map +1 -0
- package/dist/server/sessions/interruptedRunStore.js +147 -0
- package/dist/server/sessions/interruptedRunStore.js.map +1 -0
- package/dist/server/sessions/messagePaging.js +43 -0
- package/dist/server/sessions/messagePaging.js.map +1 -0
- package/dist/server/sessions/modelCatalogRefresher.js +193 -0
- package/dist/server/sessions/modelCatalogRefresher.js.map +1 -0
- package/dist/server/sessions/oauthLoginFlowService.js +346 -0
- package/dist/server/sessions/oauthLoginFlowService.js.map +1 -0
- package/dist/server/sessions/pendingAskStore.js +275 -0
- package/dist/server/sessions/pendingAskStore.js.map +1 -0
- package/dist/server/sessions/pendingExtensionDialogStore.js +196 -0
- package/dist/server/sessions/pendingExtensionDialogStore.js.map +1 -0
- package/dist/server/sessions/piSessionManagerGateway.js +246 -0
- package/dist/server/sessions/piSessionManagerGateway.js.map +1 -0
- package/dist/server/sessions/piSessionService.js +4059 -0
- package/dist/server/sessions/piSessionService.js.map +1 -0
- package/dist/server/sessions/plainTextTheme.js +112 -0
- package/dist/server/sessions/plainTextTheme.js.map +1 -0
- package/dist/server/sessions/sessionArchiveStore.js +273 -0
- package/dist/server/sessions/sessionArchiveStore.js.map +1 -0
- package/dist/server/sessions/sessionArchiveTree.js +35 -0
- package/dist/server/sessions/sessionArchiveTree.js.map +1 -0
- package/dist/server/sessions/sessionCleanup.js +157 -0
- package/dist/server/sessions/sessionCleanup.js.map +1 -0
- package/dist/server/sessions/sessionCommandService.js +336 -0
- package/dist/server/sessions/sessionCommandService.js.map +1 -0
- 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 +104 -0
- package/dist/server/sessions/sessionFileHeader.js.map +1 -0
- package/dist/server/sessions/sessionModelScope.js +141 -0
- package/dist/server/sessions/sessionModelScope.js.map +1 -0
- package/dist/server/sessions/sessionNameGenerator.js +90 -0
- package/dist/server/sessions/sessionNameGenerator.js.map +1 -0
- package/dist/server/sessions/sessionNotificationStore.js +484 -0
- package/dist/server/sessions/sessionNotificationStore.js.map +1 -0
- package/dist/server/sessions/sessionRoutes.js +744 -0
- package/dist/server/sessions/sessionRoutes.js.map +1 -0
- package/dist/server/sessions/sessionRuntimeStore.js +2 -0
- package/dist/server/sessions/sessionRuntimeStore.js.map +1 -0
- package/dist/server/sessions/sessionService.js +2 -0
- package/dist/server/sessions/sessionService.js.map +1 -0
- package/dist/server/sessions/sessionSummaryScanner.js +491 -0
- package/dist/server/sessions/sessionSummaryScanner.js.map +1 -0
- package/dist/server/sessions/sessionTreeProjection.js +250 -0
- package/dist/server/sessions/sessionTreeProjection.js.map +1 -0
- package/dist/server/sessions/sessionUnreadStore.js +520 -0
- package/dist/server/sessions/sessionUnreadStore.js.map +1 -0
- package/dist/server/sessions/shutdownDrain.js +73 -0
- package/dist/server/sessions/shutdownDrain.js.map +1 -0
- package/dist/server/sessions/spawnSessionTool.js +48 -0
- package/dist/server/sessions/spawnSessionTool.js.map +1 -0
- package/dist/server/sessions/spawnSubsessionTool.js +216 -0
- package/dist/server/sessions/spawnSubsessionTool.js.map +1 -0
- package/dist/server/sessions/spawnTargetResolver.js +23 -0
- package/dist/server/sessions/spawnTargetResolver.js.map +1 -0
- package/dist/server/sessions/subsessionTranscript.js +235 -0
- package/dist/server/sessions/subsessionTranscript.js.map +1 -0
- 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/projectStore.js +88 -0
- package/dist/server/storage/projectStore.js.map +1 -0
- package/dist/server/terminalProxyRoutes.js +141 -0
- package/dist/server/terminalProxyRoutes.js.map +1 -0
- package/dist/server/terminals/terminalRoutes.js +155 -0
- package/dist/server/terminals/terminalRoutes.js.map +1 -0
- package/dist/server/terminals/terminalService.js +305 -0
- package/dist/server/terminals/terminalService.js.map +1 -0
- package/dist/server/terminals/terminalSize.js +17 -0
- package/dist/server/terminals/terminalSize.js.map +1 -0
- package/dist/server/types.js +2 -0
- package/dist/server/types.js.map +1 -0
- package/dist/server/updates/fleetRoutes.js +111 -0
- package/dist/server/updates/fleetRoutes.js.map +1 -0
- package/dist/server/updates/restartRoutes.js +48 -0
- package/dist/server/updates/restartRoutes.js.map +1 -0
- package/dist/server/updates/selfUpdateRoutes.js +145 -0
- package/dist/server/updates/selfUpdateRoutes.js.map +1 -0
- package/dist/server/webSocketBridge.js +32 -0
- package/dist/server/webSocketBridge.js.map +1 -0
- package/dist/server/workingDirectory.js +44 -0
- package/dist/server/workingDirectory.js.map +1 -0
- package/dist/server/workspaceExplorerRoutes.js +147 -0
- package/dist/server/workspaceExplorerRoutes.js.map +1 -0
- package/dist/server/workspaces/effectivePathAccess.js +8 -0
- package/dist/server/workspaces/effectivePathAccess.js.map +1 -0
- package/dist/server/workspaces/fileContentService.js +190 -0
- package/dist/server/workspaces/fileContentService.js.map +1 -0
- 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/fileSuggestions.js +520 -0
- package/dist/server/workspaces/fileSuggestions.js.map +1 -0
- package/dist/server/workspaces/fileTreeService.js +35 -0
- package/dist/server/workspaces/fileTreeService.js.map +1 -0
- package/dist/server/workspaces/pathAccessPolicy.js +90 -0
- package/dist/server/workspaces/pathAccessPolicy.js.map +1 -0
- package/dist/server/workspaces/pathSafety.js +45 -0
- package/dist/server/workspaces/pathSafety.js.map +1 -0
- package/dist/server/workspaces/projectPiWebConfig.js +61 -0
- package/dist/server/workspaces/projectPiWebConfig.js.map +1 -0
- package/dist/server/workspaces/projectWorkspaceCwds.js +17 -0
- package/dist/server/workspaces/projectWorkspaceCwds.js.map +1 -0
- 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 +6 -0
- package/dist/server/workspaces/workspaceContext.js.map +1 -0
- package/dist/server/workspaces/workspaceDeletionRoutes.js +49 -0
- package/dist/server/workspaces/workspaceDeletionRoutes.js.map +1 -0
- 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 +12 -0
- package/dist/sessiond/activeAgentProfile.js.map +1 -0
- package/dist/sessiond/config.js +20 -0
- package/dist/sessiond/config.js.map +1 -0
- package/dist/sessiond/sessionDaemonClient.js +105 -0
- package/dist/sessiond/sessionDaemonClient.js.map +1 -0
- package/dist/shared/activeAgentProfile.js +37 -0
- package/dist/shared/activeAgentProfile.js.map +1 -0
- package/dist/shared/activity.js +16 -0
- package/dist/shared/activity.js.map +1 -0
- package/dist/shared/apiTypes.js +41 -0
- package/dist/shared/apiTypes.js.map +1 -0
- package/dist/shared/capabilities.js +37 -0
- package/dist/shared/capabilities.js.map +1 -0
- package/dist/shared/federatedRoutes.js +127 -0
- package/dist/shared/federatedRoutes.js.map +1 -0
- package/dist/shared/machinePluginIds.js +43 -0
- package/dist/shared/machinePluginIds.js.map +1 -0
- package/dist/shared/machineStatus.js +94 -0
- package/dist/shared/machineStatus.js.map +1 -0
- package/dist/shared/piWebStatusParsing.js +141 -0
- package/dist/shared/piWebStatusParsing.js.map +1 -0
- 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 +10 -0
- package/dist/shared/pluginIds.js.map +1 -0
- package/dist/shared/pluginRecoveryCommands.js +14 -0
- package/dist/shared/pluginRecoveryCommands.js.map +1 -0
- package/dist/shared/promptAttachments.js +92 -0
- package/dist/shared/promptAttachments.js.map +1 -0
- package/dist/shared/selfUpdate.js +3 -0
- package/dist/shared/selfUpdate.js.map +1 -0
- package/dist/shared/thinkingLevels.js +31 -0
- package/dist/shared/thinkingLevels.js.map +1 -0
- package/dist/shared/workspaceDeletion.js +12 -0
- package/dist/shared/workspaceDeletion.js.map +1 -0
- package/dist/shared/workspaceFiles.js +42 -0
- package/dist/shared/workspaceFiles.js.map +1 -0
- package/dist/shared/workspaceRemovalProtocol.js +24 -0
- package/dist/shared/workspaceRemovalProtocol.js.map +1 -0
- package/docs/assets/favicon.svg +11 -0
- package/docs/assets/pi-web-banner.png +0 -0
- package/docs/assets/pi-web-desktop.png +0 -0
- package/docs/assets/pi-web-mobile.png +0 -0
- package/docs/assets/pi-web-tablet.png +0 -0
- package/docs/config.md +444 -0
- package/docs/plugins.md +1305 -0
- 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/extensions/README-pi-web-restart-migration.md +45 -0
- package/extensions/pi-web.ts +324 -0
- package/install.sh +5 -0
- package/package.json +173 -0
- package/plugin-api.d.ts +1 -0
- package/server-plugin-api.d.ts +1 -0
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
import { access, readFile } from "node:fs/promises";
|
|
2
|
+
import { constants } from "node:fs";
|
|
3
|
+
import { isAbsolute, resolve } from "node:path";
|
|
4
|
+
import { diffLines } from "diff";
|
|
5
|
+
export async function computeEditPreview(path, edits, cwd) {
|
|
6
|
+
const absolutePath = isAbsolute(path) ? path : resolve(cwd, path);
|
|
7
|
+
try {
|
|
8
|
+
try {
|
|
9
|
+
await access(absolutePath, constants.R_OK);
|
|
10
|
+
}
|
|
11
|
+
catch (error) {
|
|
12
|
+
const message = error instanceof Error && "code" in error ? `Error code: ${String(error.code)}` : String(error);
|
|
13
|
+
return { error: `Could not edit file: ${path}. ${message}.` };
|
|
14
|
+
}
|
|
15
|
+
const rawContent = await readFile(absolutePath, "utf8");
|
|
16
|
+
const { text: content } = stripBom(rawContent);
|
|
17
|
+
const normalizedContent = normalizeToLF(content);
|
|
18
|
+
const { baseContent, newContent } = applyEditsToNormalizedContent(normalizedContent, edits, path);
|
|
19
|
+
return generateDiffString(baseContent, newContent);
|
|
20
|
+
}
|
|
21
|
+
catch (error) {
|
|
22
|
+
return { error: error instanceof Error ? error.message : String(error) };
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
function normalizeToLF(text) {
|
|
26
|
+
return text.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
|
|
27
|
+
}
|
|
28
|
+
function stripBom(content) {
|
|
29
|
+
return content.startsWith("\uFEFF") ? { bom: "\uFEFF", text: content.slice(1) } : { bom: "", text: content };
|
|
30
|
+
}
|
|
31
|
+
function normalizeForFuzzyMatch(text) {
|
|
32
|
+
return text
|
|
33
|
+
.normalize("NFKC")
|
|
34
|
+
.split("\n")
|
|
35
|
+
.map((line) => line.trimEnd())
|
|
36
|
+
.join("\n")
|
|
37
|
+
.replace(/[\u2018\u2019\u201A\u201B]/g, "'")
|
|
38
|
+
.replace(/[\u201C\u201D\u201E\u201F]/g, '"')
|
|
39
|
+
.replace(/[\u2010\u2011\u2012\u2013\u2014\u2015\u2212]/g, "-")
|
|
40
|
+
.replace(/[\u00A0\u2002-\u200A\u202F\u205F\u3000]/g, " ");
|
|
41
|
+
}
|
|
42
|
+
function fuzzyFindText(content, oldText) {
|
|
43
|
+
const exactIndex = content.indexOf(oldText);
|
|
44
|
+
if (exactIndex !== -1)
|
|
45
|
+
return { found: true, index: exactIndex, matchLength: oldText.length, usedFuzzyMatch: false };
|
|
46
|
+
const fuzzyContent = normalizeForFuzzyMatch(content);
|
|
47
|
+
const fuzzyOldText = normalizeForFuzzyMatch(oldText);
|
|
48
|
+
const fuzzyIndex = fuzzyContent.indexOf(fuzzyOldText);
|
|
49
|
+
if (fuzzyIndex === -1)
|
|
50
|
+
return { found: false, index: -1, matchLength: 0, usedFuzzyMatch: false };
|
|
51
|
+
return { found: true, index: fuzzyIndex, matchLength: fuzzyOldText.length, usedFuzzyMatch: true };
|
|
52
|
+
}
|
|
53
|
+
function countOccurrences(content, oldText) {
|
|
54
|
+
const fuzzyContent = normalizeForFuzzyMatch(content);
|
|
55
|
+
const fuzzyOldText = normalizeForFuzzyMatch(oldText);
|
|
56
|
+
if (fuzzyOldText === "")
|
|
57
|
+
return 0;
|
|
58
|
+
return fuzzyContent.split(fuzzyOldText).length - 1;
|
|
59
|
+
}
|
|
60
|
+
function applyEditsToNormalizedContent(normalizedContent, edits, path) {
|
|
61
|
+
const normalizedEdits = edits.map((edit) => ({ oldText: normalizeToLF(edit.oldText), newText: normalizeToLF(edit.newText) }));
|
|
62
|
+
for (let index = 0; index < normalizedEdits.length; index++) {
|
|
63
|
+
if ((normalizedEdits[index]?.oldText ?? "") === "")
|
|
64
|
+
throw editError("empty", path, index, normalizedEdits.length);
|
|
65
|
+
}
|
|
66
|
+
const initialMatches = normalizedEdits.map((edit) => fuzzyFindText(normalizedContent, edit.oldText));
|
|
67
|
+
const baseContent = initialMatches.some((match) => match.usedFuzzyMatch) ? normalizeForFuzzyMatch(normalizedContent) : normalizedContent;
|
|
68
|
+
const matchedEdits = [];
|
|
69
|
+
for (let index = 0; index < normalizedEdits.length; index++) {
|
|
70
|
+
const edit = normalizedEdits[index];
|
|
71
|
+
if (edit === undefined)
|
|
72
|
+
continue;
|
|
73
|
+
const match = fuzzyFindText(baseContent, edit.oldText);
|
|
74
|
+
if (!match.found)
|
|
75
|
+
throw editError("missing", path, index, normalizedEdits.length);
|
|
76
|
+
const occurrences = countOccurrences(baseContent, edit.oldText);
|
|
77
|
+
if (occurrences > 1)
|
|
78
|
+
throw editError("duplicate", path, index, normalizedEdits.length, occurrences);
|
|
79
|
+
matchedEdits.push({ editIndex: index, matchIndex: match.index, matchLength: match.matchLength, newText: edit.newText });
|
|
80
|
+
}
|
|
81
|
+
matchedEdits.sort((a, b) => a.matchIndex - b.matchIndex);
|
|
82
|
+
for (let index = 1; index < matchedEdits.length; index++) {
|
|
83
|
+
const previous = matchedEdits[index - 1];
|
|
84
|
+
const current = matchedEdits[index];
|
|
85
|
+
if (previous !== undefined && current !== undefined && previous.matchIndex + previous.matchLength > current.matchIndex) {
|
|
86
|
+
throw new Error(`edits[${String(previous.editIndex)}] and edits[${String(current.editIndex)}] overlap in ${path}. Merge them into one edit or target disjoint regions.`);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
let newContent = baseContent;
|
|
90
|
+
for (let index = matchedEdits.length - 1; index >= 0; index--) {
|
|
91
|
+
const edit = matchedEdits[index];
|
|
92
|
+
if (edit === undefined)
|
|
93
|
+
continue;
|
|
94
|
+
newContent = `${newContent.slice(0, edit.matchIndex)}${edit.newText}${newContent.slice(edit.matchIndex + edit.matchLength)}`;
|
|
95
|
+
}
|
|
96
|
+
if (baseContent === newContent)
|
|
97
|
+
throw editError("nochange", path, 0, normalizedEdits.length);
|
|
98
|
+
return { baseContent, newContent };
|
|
99
|
+
}
|
|
100
|
+
function editError(kind, path, editIndex, totalEdits, occurrences) {
|
|
101
|
+
const prefix = totalEdits === 1 ? "" : `edits[${String(editIndex)}].`;
|
|
102
|
+
if (kind === "empty")
|
|
103
|
+
return new Error(totalEdits === 1 ? `oldText must not be empty in ${path}.` : `${prefix}oldText must not be empty in ${path}.`);
|
|
104
|
+
if (kind === "missing")
|
|
105
|
+
return new Error(totalEdits === 1 ? `Could not find the exact text in ${path}. The old text must match exactly including all whitespace and newlines.` : `Could not find edits[${String(editIndex)}] in ${path}. The oldText must match exactly including all whitespace and newlines.`);
|
|
106
|
+
if (kind === "duplicate")
|
|
107
|
+
return new Error(totalEdits === 1 ? `Found ${String(occurrences)} occurrences of the text in ${path}. The text must be unique. Please provide more context to make it unique.` : `Found ${String(occurrences)} occurrences of edits[${String(editIndex)}] in ${path}. Each oldText must be unique. Please provide more context to make it unique.`);
|
|
108
|
+
return new Error(totalEdits === 1 ? `No changes made to ${path}. The replacement produced identical content.` : `No changes made to ${path}. The replacements produced identical content.`);
|
|
109
|
+
}
|
|
110
|
+
function generateDiffString(oldContent, newContent, contextLines = 4) {
|
|
111
|
+
const parts = diffLines(oldContent, newContent);
|
|
112
|
+
const output = [];
|
|
113
|
+
const oldLines = oldContent.split("\n");
|
|
114
|
+
const newLines = newContent.split("\n");
|
|
115
|
+
const maxLineNum = Math.max(oldLines.length, newLines.length);
|
|
116
|
+
const lineNumWidth = String(maxLineNum).length;
|
|
117
|
+
let oldLineNum = 1;
|
|
118
|
+
let newLineNum = 1;
|
|
119
|
+
let lastWasChange = false;
|
|
120
|
+
let firstChangedLine;
|
|
121
|
+
for (let index = 0; index < parts.length; index++) {
|
|
122
|
+
const part = parts[index];
|
|
123
|
+
if (part === undefined)
|
|
124
|
+
continue;
|
|
125
|
+
const raw = part.value.split("\n");
|
|
126
|
+
if (raw.at(-1) === "")
|
|
127
|
+
raw.pop();
|
|
128
|
+
if (part.added || part.removed) {
|
|
129
|
+
firstChangedLine ??= newLineNum;
|
|
130
|
+
for (const line of raw) {
|
|
131
|
+
if (part.added) {
|
|
132
|
+
output.push(`+${String(newLineNum).padStart(lineNumWidth, " ")} ${line}`);
|
|
133
|
+
newLineNum++;
|
|
134
|
+
}
|
|
135
|
+
else {
|
|
136
|
+
output.push(`-${String(oldLineNum).padStart(lineNumWidth, " ")} ${line}`);
|
|
137
|
+
oldLineNum++;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
lastWasChange = true;
|
|
141
|
+
continue;
|
|
142
|
+
}
|
|
143
|
+
const nextPart = parts[index + 1];
|
|
144
|
+
const nextPartIsChange = (nextPart?.added ?? false) || (nextPart?.removed ?? false);
|
|
145
|
+
const hasLeadingChange = lastWasChange;
|
|
146
|
+
const hasTrailingChange = nextPartIsChange;
|
|
147
|
+
if (hasLeadingChange && hasTrailingChange) {
|
|
148
|
+
if (raw.length <= contextLines * 2) {
|
|
149
|
+
appendContextLines(output, raw, lineNumWidth, () => oldLineNum++, () => newLineNum++);
|
|
150
|
+
}
|
|
151
|
+
else {
|
|
152
|
+
const leadingLines = raw.slice(0, contextLines);
|
|
153
|
+
const trailingLines = raw.slice(raw.length - contextLines);
|
|
154
|
+
const skippedLines = raw.length - leadingLines.length - trailingLines.length;
|
|
155
|
+
appendContextLines(output, leadingLines, lineNumWidth, () => oldLineNum++, () => newLineNum++);
|
|
156
|
+
output.push(` ${"".padStart(lineNumWidth, " ")} ...`);
|
|
157
|
+
oldLineNum += skippedLines;
|
|
158
|
+
newLineNum += skippedLines;
|
|
159
|
+
appendContextLines(output, trailingLines, lineNumWidth, () => oldLineNum++, () => newLineNum++);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
else if (hasLeadingChange) {
|
|
163
|
+
const shownLines = raw.slice(0, contextLines);
|
|
164
|
+
const skippedLines = raw.length - shownLines.length;
|
|
165
|
+
appendContextLines(output, shownLines, lineNumWidth, () => oldLineNum++, () => newLineNum++);
|
|
166
|
+
if (skippedLines > 0) {
|
|
167
|
+
output.push(` ${"".padStart(lineNumWidth, " ")} ...`);
|
|
168
|
+
oldLineNum += skippedLines;
|
|
169
|
+
newLineNum += skippedLines;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
else if (hasTrailingChange) {
|
|
173
|
+
const skippedLines = Math.max(0, raw.length - contextLines);
|
|
174
|
+
if (skippedLines > 0) {
|
|
175
|
+
output.push(` ${"".padStart(lineNumWidth, " ")} ...`);
|
|
176
|
+
oldLineNum += skippedLines;
|
|
177
|
+
newLineNum += skippedLines;
|
|
178
|
+
}
|
|
179
|
+
appendContextLines(output, raw.slice(skippedLines), lineNumWidth, () => oldLineNum++, () => newLineNum++);
|
|
180
|
+
}
|
|
181
|
+
else {
|
|
182
|
+
oldLineNum += raw.length;
|
|
183
|
+
newLineNum += raw.length;
|
|
184
|
+
}
|
|
185
|
+
lastWasChange = false;
|
|
186
|
+
}
|
|
187
|
+
return { diff: output.join("\n"), ...(firstChangedLine === undefined ? {} : { firstChangedLine }) };
|
|
188
|
+
}
|
|
189
|
+
function appendContextLines(output, lines, lineNumWidth, nextOldLine, nextNewLine) {
|
|
190
|
+
for (const line of lines) {
|
|
191
|
+
const oldLine = nextOldLine();
|
|
192
|
+
nextNewLine();
|
|
193
|
+
output.push(` ${String(oldLine).padStart(lineNumWidth, " ")} ${line}`);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
//# sourceMappingURL=editPreview.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"editPreview.js","sourceRoot":"","sources":["../../../src/server/sessions/editPreview.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/** The value an extension's dialog Promise settles with on any close without an answer. */
|
|
2
|
+
export function extensionDialogCancelValue(kind) {
|
|
3
|
+
return kind === "confirm" ? false : undefined;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* The auto-cancel delay of one dialog: the sooner of the extension's own
|
|
7
|
+
* `timeout` and the daemon's `extensionDialogsTimeoutMs` default, where `0`
|
|
8
|
+
* (or an invalid extension value, defensively ignored) means "waits forever".
|
|
9
|
+
*/
|
|
10
|
+
export function effectiveExtensionDialogTimeoutMs(extensionTimeoutMs, daemonDefaultMs) {
|
|
11
|
+
const fromExtension = typeof extensionTimeoutMs === "number" && Number.isFinite(extensionTimeoutMs) && extensionTimeoutMs > 0 ? extensionTimeoutMs : undefined;
|
|
12
|
+
const fromDaemon = daemonDefaultMs > 0 ? daemonDefaultMs : undefined;
|
|
13
|
+
if (fromExtension === undefined)
|
|
14
|
+
return fromDaemon;
|
|
15
|
+
if (fromDaemon === undefined)
|
|
16
|
+
return fromExtension;
|
|
17
|
+
return Math.min(fromExtension, fromDaemon);
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* The parked Promise resolvers behind open extension dialogs, plus the timers
|
|
21
|
+
* and signal subscriptions that can end a wait without the browser. Timers use
|
|
22
|
+
* the global `setTimeout`/`clearTimeout` looked up per call, the same seam the
|
|
23
|
+
* rest of the service's timer tests fake.
|
|
24
|
+
*
|
|
25
|
+
* Kept deliberately separate from {@link PendingExtensionDialogStore}: the
|
|
26
|
+
* store owns the domain state every browser sees, the waiters own the one
|
|
27
|
+
* in-memory resolver each open dialog parks inside extension code — state no
|
|
28
|
+
* browser ever observes and that must not survive the runtime. The pairing is
|
|
29
|
+
* the wiring's invariant: every open store record has exactly one parked
|
|
30
|
+
* waiter, and whoever closes the record settles the waiter exactly once.
|
|
31
|
+
*/
|
|
32
|
+
export class ExtensionDialogWaiters {
|
|
33
|
+
constructor() {
|
|
34
|
+
this.parked = new Map();
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Park the extension-facing Promise for a dialog the store just opened. Arms
|
|
38
|
+
* the timeout and signal triggers; both are disarmed when the wait settles,
|
|
39
|
+
* so a settled wait can never be triggered (nor trigger twice).
|
|
40
|
+
*/
|
|
41
|
+
park(dialog, triggers = {}) {
|
|
42
|
+
return new Promise((resolve) => {
|
|
43
|
+
const parked = { cancelValue: extensionDialogCancelValue(dialog.kind), resolve };
|
|
44
|
+
if (triggers.timeoutMs !== undefined) {
|
|
45
|
+
const handle = setTimeout(() => { triggers.onTrigger?.("timeout"); }, triggers.timeoutMs);
|
|
46
|
+
parked.cancelArmedTimeout = () => { clearTimeout(handle); };
|
|
47
|
+
}
|
|
48
|
+
if (triggers.signal !== undefined) {
|
|
49
|
+
const signal = triggers.signal;
|
|
50
|
+
const onAbort = () => { triggers.onTrigger?.("cancelled"); };
|
|
51
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
52
|
+
parked.removeSignalListener = () => { signal.removeEventListener("abort", onAbort); };
|
|
53
|
+
}
|
|
54
|
+
this.parked.set(dialog.dialogId, parked);
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
/** Resolve the parked wait with the user's answer, which the store has already validated and recorded. */
|
|
58
|
+
settleWithAnswer(dialogId, answer) {
|
|
59
|
+
return this.settle(dialogId, (parked) => { parked.resolve(answer); });
|
|
60
|
+
}
|
|
61
|
+
/** Resolve the parked wait with the dialog kind's cancel value after a close without an answer. */
|
|
62
|
+
settleWithCancelValue(dialogId) {
|
|
63
|
+
return this.settle(dialogId, (parked) => { parked.resolve(parked.cancelValue); });
|
|
64
|
+
}
|
|
65
|
+
settle(dialogId, resolveParked) {
|
|
66
|
+
const parked = this.parked.get(dialogId);
|
|
67
|
+
if (parked === undefined)
|
|
68
|
+
return false;
|
|
69
|
+
this.parked.delete(dialogId);
|
|
70
|
+
parked.cancelArmedTimeout?.();
|
|
71
|
+
parked.removeSignalListener?.();
|
|
72
|
+
resolveParked(parked);
|
|
73
|
+
return true;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=extensionDialogWaiters.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extensionDialogWaiters.js","sourceRoot":"","sources":["../../../src/server/sessions/extensionDialogWaiters.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import { mkdtemp, rm } from "node:fs/promises";
|
|
2
|
+
import { tmpdir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { isDeepStrictEqual } from "node:util";
|
|
5
|
+
import { createAgentSessionServices, } from "@earendil-works/pi-coding-agent";
|
|
6
|
+
const LOG_CONTEXT = "global-provider-bootstrap";
|
|
7
|
+
const MODELS_FIELD = "models";
|
|
8
|
+
/**
|
|
9
|
+
* Snapshot the merged config Pi holds for every config-registered provider.
|
|
10
|
+
* Pi merges defined values over the previous registration, so the runtime's
|
|
11
|
+
* own record — not the extension's last argument — is the accurate baseline.
|
|
12
|
+
* Native providers have no comparable config and are deliberately absent.
|
|
13
|
+
*/
|
|
14
|
+
function captureProviderConfigBaseline(runtime) {
|
|
15
|
+
const baseline = new Map();
|
|
16
|
+
for (const providerId of runtime.getRegisteredProviderIds()) {
|
|
17
|
+
const config = runtime.getRegisteredProviderConfig(providerId);
|
|
18
|
+
if (config)
|
|
19
|
+
baseline.set(providerId, config);
|
|
20
|
+
}
|
|
21
|
+
return baseline;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* True when `incoming` would change the model catalog of `baseline` and nothing
|
|
25
|
+
* else.
|
|
26
|
+
*
|
|
27
|
+
* Extensions that refresh their catalog re-send a complete provider config, so
|
|
28
|
+
* the test is "equal to the baseline except for models", not "contains only
|
|
29
|
+
* models". Omitted fields are not changes: Pi's merge keeps the previous value,
|
|
30
|
+
* which also makes an unchanged catalog a plain replay rather than an update.
|
|
31
|
+
* Function-valued fields (`streamSimple`, `refreshModels`, `oauth` methods)
|
|
32
|
+
* compare by reference under deep strict equality, so a freshly created closure
|
|
33
|
+
* reads as a mismatch. That conservative direction is intentional: an unclear
|
|
34
|
+
* comparison must fall back to the frozen no-op.
|
|
35
|
+
*/
|
|
36
|
+
function isModelsOnlyProviderUpdate(baseline, incoming) {
|
|
37
|
+
const baselineFields = new Map(Object.entries(baseline));
|
|
38
|
+
const otherFieldsMatch = Object.entries(incoming).every(([field, value]) => {
|
|
39
|
+
if (field === MODELS_FIELD || value === undefined)
|
|
40
|
+
return true;
|
|
41
|
+
return isDeepStrictEqual(value, baselineFields.get(field));
|
|
42
|
+
});
|
|
43
|
+
if (!otherFieldsMatch)
|
|
44
|
+
return false;
|
|
45
|
+
return incoming.models !== undefined && !isDeepStrictEqual(incoming.models, baseline.models);
|
|
46
|
+
}
|
|
47
|
+
async function loadGlobalExtensionServices(runtime, agentDir) {
|
|
48
|
+
const scratchCwd = await mkdtemp(join(tmpdir(), "pi-web-global-ext-"));
|
|
49
|
+
try {
|
|
50
|
+
return await createAgentSessionServices({ cwd: scratchCwd, agentDir, modelRuntime: runtime });
|
|
51
|
+
}
|
|
52
|
+
finally {
|
|
53
|
+
await rm(scratchCwd, { recursive: true, force: true });
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
function logBootstrapDiagnostic(logger, diagnostic) {
|
|
57
|
+
const details = {
|
|
58
|
+
context: LOG_CONTEXT,
|
|
59
|
+
diagnosticType: diagnostic.type,
|
|
60
|
+
diagnostic: diagnostic.message,
|
|
61
|
+
};
|
|
62
|
+
if (diagnostic.type === "error") {
|
|
63
|
+
logger.error(details, "global extension provider bootstrap diagnostic");
|
|
64
|
+
}
|
|
65
|
+
else if (diagnostic.type === "warning") {
|
|
66
|
+
logger.warn(details, "global extension provider bootstrap diagnostic");
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
logger.info(details, "global extension provider bootstrap diagnostic");
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
function freezeProviderMutations(runtime, logger, configBaseline) {
|
|
73
|
+
const originalMethods = {
|
|
74
|
+
registerNativeProvider: runtime.registerNativeProvider.bind(runtime),
|
|
75
|
+
registerProvider: runtime.registerProvider.bind(runtime),
|
|
76
|
+
unregisterProvider: runtime.unregisterProvider.bind(runtime),
|
|
77
|
+
};
|
|
78
|
+
const loggedProviderIds = {
|
|
79
|
+
registerNativeProvider: new Set(),
|
|
80
|
+
registerProvider: new Set(),
|
|
81
|
+
unregisterProvider: new Set(),
|
|
82
|
+
};
|
|
83
|
+
// Logging must never turn a provider mutation into an extension failure.
|
|
84
|
+
const logQuietly = (details, message) => {
|
|
85
|
+
try {
|
|
86
|
+
logger.info(details, message);
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
// Intentionally ignored; the mutation decision already stands.
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
const logIgnoredMutation = (operation, providerId) => {
|
|
93
|
+
const loggedIds = loggedProviderIds[operation];
|
|
94
|
+
if (loggedIds.has(providerId))
|
|
95
|
+
return;
|
|
96
|
+
loggedIds.add(providerId);
|
|
97
|
+
logQuietly({ context: LOG_CONTEXT, operation, providerId }, "ignored provider mutation after global bootstrap");
|
|
98
|
+
};
|
|
99
|
+
const frozenMethods = {
|
|
100
|
+
registerProvider(providerId, config) {
|
|
101
|
+
const baseline = configBaseline.get(providerId);
|
|
102
|
+
if (!baseline || !isModelsOnlyProviderUpdate(baseline, config)) {
|
|
103
|
+
logIgnoredMutation("registerProvider", providerId);
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
// Pi validates the registration and ends in a fire-and-forget local
|
|
107
|
+
// refresh, so this stays synchronous and never reaches the network.
|
|
108
|
+
originalMethods.registerProvider(providerId, config);
|
|
109
|
+
const accepted = runtime.getRegisteredProviderConfig(providerId);
|
|
110
|
+
// Re-read the merged record so the next comparison uses what Pi stored.
|
|
111
|
+
if (accepted)
|
|
112
|
+
configBaseline.set(providerId, accepted);
|
|
113
|
+
logQuietly({
|
|
114
|
+
context: LOG_CONTEXT,
|
|
115
|
+
operation: "registerProvider",
|
|
116
|
+
providerId,
|
|
117
|
+
modelCount: accepted?.models?.length ?? 0,
|
|
118
|
+
}, "applied models-only provider update after global bootstrap");
|
|
119
|
+
},
|
|
120
|
+
registerNativeProvider(provider) {
|
|
121
|
+
logIgnoredMutation("registerNativeProvider", provider.id);
|
|
122
|
+
},
|
|
123
|
+
unregisterProvider(providerId) {
|
|
124
|
+
logIgnoredMutation("unregisterProvider", providerId);
|
|
125
|
+
},
|
|
126
|
+
};
|
|
127
|
+
try {
|
|
128
|
+
Object.assign(runtime, frozenMethods);
|
|
129
|
+
}
|
|
130
|
+
catch (error) {
|
|
131
|
+
Object.assign(runtime, originalMethods);
|
|
132
|
+
throw error;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Load global extensions once against the shared model runtime, then make its
|
|
137
|
+
* extension-provider baseline immutable for the rest of the daemon lifetime.
|
|
138
|
+
* All sessions share this runtime, so accepting project-dependent mutations
|
|
139
|
+
* would leak provider configuration across workspaces. This is an accidental
|
|
140
|
+
* contamination guard, not a sandbox for otherwise trusted extensions.
|
|
141
|
+
*
|
|
142
|
+
* The temporary cwd is guaranteed to be empty, so Pi discovers agent-dir
|
|
143
|
+
* extensions without loading project resources. Documented initialization-time
|
|
144
|
+
* config and native registrations therefore reach the runtime through Pi's
|
|
145
|
+
* public service factory. Pi exposes no provider-freeze hook, so the daemon
|
|
146
|
+
* deliberately shadows the three public instance mutation methods afterward;
|
|
147
|
+
* every registration replay or later call is then a logged no-op.
|
|
148
|
+
*
|
|
149
|
+
* The one exception is a known config provider refreshing its own model
|
|
150
|
+
* catalog: a `registerProvider` call whose config matches the recorded
|
|
151
|
+
* baseline in every field except `models` is applied, because a catalog is a
|
|
152
|
+
* property of the provider rather than of the project. Native registration
|
|
153
|
+
* stays fully frozen — it passes a whole `Provider` object with no comparable
|
|
154
|
+
* config — as does unregistration.
|
|
155
|
+
*/
|
|
156
|
+
export async function bootstrapAndFreezeGlobalExtensionProviders(runtime, agentDir, logger) {
|
|
157
|
+
const services = await loadGlobalExtensionServices(runtime, agentDir);
|
|
158
|
+
const providerIds = Object.freeze([...runtime.getRegisteredProviderIds()].sort());
|
|
159
|
+
freezeProviderMutations(runtime, logger, captureProviderConfigBaseline(runtime));
|
|
160
|
+
for (const diagnostic of services.diagnostics)
|
|
161
|
+
logBootstrapDiagnostic(logger, diagnostic);
|
|
162
|
+
for (const extensionError of services.resourceLoader.getExtensions().errors) {
|
|
163
|
+
logger.error({ context: LOG_CONTEXT, error: extensionError.error }, "global extension failed during provider bootstrap");
|
|
164
|
+
}
|
|
165
|
+
logger.info({ context: LOG_CONTEXT, providerIds }, "global extension provider baseline bootstrapped and frozen");
|
|
166
|
+
}
|
|
167
|
+
//# sourceMappingURL=globalProviderPolicy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"globalProviderPolicy.js","sourceRoot":"","sources":["../../../src/server/sessions/globalProviderPolicy.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
2
|
+
import { dirname, join } from "node:path";
|
|
3
|
+
import { piWebDataDir } from "../../config.js";
|
|
4
|
+
const EMPTY = { runs: [] };
|
|
5
|
+
export function defaultInterruptedRunFilePath(env = process.env, cwd = process.cwd()) {
|
|
6
|
+
return join(piWebDataDir(env, cwd), "interrupted-runs.json");
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Persist the runs a shutdown interrupted.
|
|
10
|
+
*
|
|
11
|
+
* Overwrites rather than appends: the record answers "what did the last restart
|
|
12
|
+
* cut off", and an ever-growing list of historical interruptions is noise the
|
|
13
|
+
* user would have to clear repeatedly.
|
|
14
|
+
*
|
|
15
|
+
* Never throws. This runs during shutdown, and failing to write a convenience
|
|
16
|
+
* record must not stop the daemon exiting.
|
|
17
|
+
*/
|
|
18
|
+
export async function recordInterruptedRuns(runs, filePath = defaultInterruptedRunFilePath()) {
|
|
19
|
+
try {
|
|
20
|
+
if (runs.length === 0) {
|
|
21
|
+
await writeFile(filePath, `${JSON.stringify(EMPTY, null, 2)}\n`, "utf8");
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
await mkdir(dirname(filePath), { recursive: true });
|
|
25
|
+
await writeFile(filePath, `${JSON.stringify({ runs: [...runs] }, null, 2)}\n`, "utf8");
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
// Shutdown continues regardless.
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Read the record left by the previous shutdown.
|
|
33
|
+
*
|
|
34
|
+
* A missing or unreadable file means "nothing was interrupted", which is both
|
|
35
|
+
* the common case and the safe reading: inventing interruptions would send the
|
|
36
|
+
* user chasing work that finished normally.
|
|
37
|
+
*/
|
|
38
|
+
export async function readInterruptedRuns(filePath = defaultInterruptedRunFilePath()) {
|
|
39
|
+
let raw;
|
|
40
|
+
try {
|
|
41
|
+
raw = await readFile(filePath, "utf8");
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
return EMPTY;
|
|
45
|
+
}
|
|
46
|
+
try {
|
|
47
|
+
const parsed = JSON.parse(raw);
|
|
48
|
+
return { runs: parseRuns(parsed) };
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
return EMPTY;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
/** Clear the record once the user has seen it. */
|
|
55
|
+
export async function clearInterruptedRuns(filePath = defaultInterruptedRunFilePath()) {
|
|
56
|
+
await recordInterruptedRuns([], filePath);
|
|
57
|
+
}
|
|
58
|
+
function parseRuns(value) {
|
|
59
|
+
const root = asRecord(value);
|
|
60
|
+
const runs = root?.["runs"];
|
|
61
|
+
if (!Array.isArray(runs))
|
|
62
|
+
return [];
|
|
63
|
+
const parsed = [];
|
|
64
|
+
for (const entry of runs) {
|
|
65
|
+
const record = asRecord(entry);
|
|
66
|
+
if (record === undefined)
|
|
67
|
+
continue;
|
|
68
|
+
const sessionId = record["sessionId"];
|
|
69
|
+
const cwd = record["cwd"];
|
|
70
|
+
if (typeof sessionId !== "string" || sessionId === "")
|
|
71
|
+
continue;
|
|
72
|
+
if (typeof cwd !== "string" || cwd === "")
|
|
73
|
+
continue;
|
|
74
|
+
const interruptedAt = record["interruptedAt"];
|
|
75
|
+
parsed.push({ sessionId, cwd, interruptedAt: typeof interruptedAt === "string" ? interruptedAt : "" });
|
|
76
|
+
}
|
|
77
|
+
return parsed;
|
|
78
|
+
}
|
|
79
|
+
/** Narrow an unknown to a plain object without asserting a shape onto it. */
|
|
80
|
+
function asRecord(value) {
|
|
81
|
+
if (typeof value !== "object" || value === null || Array.isArray(value))
|
|
82
|
+
return undefined;
|
|
83
|
+
const result = {};
|
|
84
|
+
for (const [key, entry] of Object.entries(value))
|
|
85
|
+
result[key] = entry;
|
|
86
|
+
return result;
|
|
87
|
+
}
|
|
88
|
+
/** Where the live set of in-flight runs is kept. */
|
|
89
|
+
export function defaultInFlightRunFilePath(env = process.env, cwd = process.cwd()) {
|
|
90
|
+
return join(piWebDataDir(env, cwd), "in-flight-runs.json");
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Note that a run has started.
|
|
94
|
+
*
|
|
95
|
+
* Never throws: failing to write a convenience record must not fail the run it
|
|
96
|
+
* is describing.
|
|
97
|
+
*/
|
|
98
|
+
export async function markRunInFlight(run, filePath = defaultInFlightRunFilePath()) {
|
|
99
|
+
try {
|
|
100
|
+
const current = await readRuns(filePath);
|
|
101
|
+
if (current.some((entry) => entry.sessionId === run.sessionId))
|
|
102
|
+
return;
|
|
103
|
+
await writeRuns([...current, { ...run, interruptedAt: new Date().toISOString() }], filePath);
|
|
104
|
+
}
|
|
105
|
+
catch {
|
|
106
|
+
// The run proceeds regardless.
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
/** Note that a run finished, so it is not reported as interrupted. */
|
|
110
|
+
export async function clearRunInFlight(sessionId, filePath = defaultInFlightRunFilePath()) {
|
|
111
|
+
try {
|
|
112
|
+
const current = await readRuns(filePath);
|
|
113
|
+
const next = current.filter((entry) => entry.sessionId !== sessionId);
|
|
114
|
+
if (next.length === current.length)
|
|
115
|
+
return;
|
|
116
|
+
await writeRuns(next, filePath);
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
// Leaving a stale entry only risks over-reporting, which the user can dismiss.
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Read what the previous process left behind and clear it.
|
|
124
|
+
*
|
|
125
|
+
* Called once at startup: anything still marked in flight belongs to a process
|
|
126
|
+
* that is gone, so it did not finish. Clearing as part of reading means a
|
|
127
|
+
* restart cannot report the same interruption forever.
|
|
128
|
+
*/
|
|
129
|
+
export async function takeInterruptedRuns(filePath = defaultInFlightRunFilePath()) {
|
|
130
|
+
const runs = await readRuns(filePath);
|
|
131
|
+
if (runs.length > 0)
|
|
132
|
+
await writeRuns([], filePath);
|
|
133
|
+
return runs;
|
|
134
|
+
}
|
|
135
|
+
async function readRuns(filePath) {
|
|
136
|
+
try {
|
|
137
|
+
return parseRuns(JSON.parse(await readFile(filePath, "utf8")));
|
|
138
|
+
}
|
|
139
|
+
catch {
|
|
140
|
+
return [];
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
async function writeRuns(runs, filePath) {
|
|
144
|
+
await mkdir(dirname(filePath), { recursive: true });
|
|
145
|
+
await writeFile(filePath, `${JSON.stringify({ runs: [...runs] }, null, 2)}\n`, "utf8");
|
|
146
|
+
}
|
|
147
|
+
//# sourceMappingURL=interruptedRunStore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interruptedRunStore.js","sourceRoot":"","sources":["../../../src/server/sessions/interruptedRunStore.ts"],"names":[],"mappings":"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"}
|