@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,520 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { mkdir, readFile, rename, rm, writeFile } from "node:fs/promises";
|
|
3
|
+
import { dirname, join } from "node:path";
|
|
4
|
+
import { piWebDataDir } from "../../config.js";
|
|
5
|
+
import { SESSION_UNREAD_CATALOG_ID_MAX_LENGTH, SESSION_UNREAD_COMPLETED_AT_MAX_LENGTH, SESSION_UNREAD_CWD_MAX_LENGTH, SESSION_UNREAD_LIMIT, SESSION_UNREAD_SESSION_ID_MAX_LENGTH, } from "../../shared/apiTypes.js";
|
|
6
|
+
const SESSION_UNREAD_STATE_VERSION = 1;
|
|
7
|
+
const SESSION_UNREAD_FILE_MODE = 0o600;
|
|
8
|
+
/**
|
|
9
|
+
* Daemon-owned unread completion catalog.
|
|
10
|
+
*
|
|
11
|
+
* Completion orders are global and never reused within a catalog epoch. An
|
|
12
|
+
* acknowledgement must carry both the epoch and the observed completion order,
|
|
13
|
+
* so neither an old completion nor a client from reset state can clear newer
|
|
14
|
+
* work.
|
|
15
|
+
*/
|
|
16
|
+
export class SessionUnreadStore {
|
|
17
|
+
constructor(options = {}) {
|
|
18
|
+
this.unreadByIdentity = new Map();
|
|
19
|
+
this.activeByIdentity = new Map();
|
|
20
|
+
this.excludedByIdentity = new Map();
|
|
21
|
+
this.catalogRevision = 0;
|
|
22
|
+
this.nextCompletionOrder = 0;
|
|
23
|
+
this.persistenceGeneration = 0;
|
|
24
|
+
this.durablePersistenceGeneration = 0;
|
|
25
|
+
this.now = options.now ?? (() => new Date());
|
|
26
|
+
this.persistence = options.persistence;
|
|
27
|
+
this.createCatalogId = options.createCatalogId ?? randomUUID;
|
|
28
|
+
this.onPersistenceError = options.onPersistenceError ?? (() => undefined);
|
|
29
|
+
this.loaded = this.persistence === undefined;
|
|
30
|
+
// A persisted store receives its epoch from disk or creates one during
|
|
31
|
+
// load; synchronous in-memory stores are ready immediately.
|
|
32
|
+
this.catalogId = this.loaded ? this.freshCatalogId() : "";
|
|
33
|
+
}
|
|
34
|
+
load() {
|
|
35
|
+
if (this.loaded)
|
|
36
|
+
return Promise.resolve();
|
|
37
|
+
if (this.loadPromise !== undefined)
|
|
38
|
+
return this.loadPromise;
|
|
39
|
+
const loadPromise = this.loadPersistedState();
|
|
40
|
+
this.loadPromise = loadPromise;
|
|
41
|
+
return loadPromise;
|
|
42
|
+
}
|
|
43
|
+
/** Current in-memory state. Transport boundaries should use `durableCatalogSnapshot`. */
|
|
44
|
+
catalogSnapshot() {
|
|
45
|
+
this.requireLoaded();
|
|
46
|
+
return {
|
|
47
|
+
catalogId: this.catalogId,
|
|
48
|
+
catalogRevision: this.catalogRevision,
|
|
49
|
+
sessions: [...this.unreadByIdentity.values()]
|
|
50
|
+
.sort((left, right) => right.completionOrder - left.completionOrder)
|
|
51
|
+
.map((summary) => ({ ...summary })),
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
observeActivityState(sessionId, cwd, active) {
|
|
55
|
+
this.requireLoaded();
|
|
56
|
+
const identity = requireIdentity(sessionId, cwd);
|
|
57
|
+
const key = sessionIdentityKey(identity);
|
|
58
|
+
if (this.excludedByIdentity.has(key)) {
|
|
59
|
+
this.activeByIdentity.delete(key);
|
|
60
|
+
return [];
|
|
61
|
+
}
|
|
62
|
+
if (active) {
|
|
63
|
+
this.activeByIdentity.set(key, identity);
|
|
64
|
+
return [];
|
|
65
|
+
}
|
|
66
|
+
if (!this.activeByIdentity.has(key))
|
|
67
|
+
return [];
|
|
68
|
+
const completionOrder = incrementSafe(this.nextCompletionOrder, "Session unread completion order exhausted");
|
|
69
|
+
const willExceedLimit = !this.unreadByIdentity.has(key) && this.unreadByIdentity.size >= SESSION_UNREAD_LIMIT;
|
|
70
|
+
this.assertRevisionCapacity(willExceedLimit ? 2 : 1);
|
|
71
|
+
const completedAt = this.now().toISOString();
|
|
72
|
+
this.activeByIdentity.delete(key);
|
|
73
|
+
this.nextCompletionOrder = completionOrder;
|
|
74
|
+
const summary = {
|
|
75
|
+
sessionId,
|
|
76
|
+
cwd,
|
|
77
|
+
completionOrder,
|
|
78
|
+
completedAt,
|
|
79
|
+
};
|
|
80
|
+
// Reinsert existing identities so map order remains completion order.
|
|
81
|
+
this.unreadByIdentity.delete(key);
|
|
82
|
+
this.unreadByIdentity.set(key, summary);
|
|
83
|
+
const mutations = [this.mutation(identity, summary), ...this.trimToLimit()];
|
|
84
|
+
this.schedulePersist();
|
|
85
|
+
return mutations;
|
|
86
|
+
}
|
|
87
|
+
/** Clear only the transient active latch for a runtime that is closing or rebinding. */
|
|
88
|
+
forgetActivity(sessionId, cwd) {
|
|
89
|
+
this.requireLoaded();
|
|
90
|
+
const identity = requireIdentity(sessionId, cwd);
|
|
91
|
+
this.activeByIdentity.delete(sessionIdentityKey(identity));
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Suppress unread tracking until this identity is explicitly forgotten and
|
|
95
|
+
* remove state recorded before it was verified as a tracked sub-session.
|
|
96
|
+
*/
|
|
97
|
+
excludeSession(sessionId, cwd) {
|
|
98
|
+
this.requireLoaded();
|
|
99
|
+
const identity = requireIdentity(sessionId, cwd);
|
|
100
|
+
const key = sessionIdentityKey(identity);
|
|
101
|
+
const current = this.unreadByIdentity.get(key);
|
|
102
|
+
this.assertRevisionCapacity(current === undefined ? 0 : 1);
|
|
103
|
+
this.excludedByIdentity.set(key, identity);
|
|
104
|
+
this.activeByIdentity.delete(key);
|
|
105
|
+
if (current === undefined)
|
|
106
|
+
return [];
|
|
107
|
+
this.unreadByIdentity.delete(key);
|
|
108
|
+
const mutations = [this.mutation(identity, null)];
|
|
109
|
+
this.schedulePersist();
|
|
110
|
+
return mutations;
|
|
111
|
+
}
|
|
112
|
+
acknowledge(sessionId, request) {
|
|
113
|
+
this.requireLoaded();
|
|
114
|
+
const identity = requireIdentity(sessionId, request.cwd);
|
|
115
|
+
requireCatalogId(request.catalogId);
|
|
116
|
+
requirePositiveSafeInteger(request.throughCompletionOrder, "throughCompletionOrder");
|
|
117
|
+
if (request.catalogId !== this.catalogId)
|
|
118
|
+
return { mutations: [] };
|
|
119
|
+
const key = sessionIdentityKey(identity);
|
|
120
|
+
const current = this.unreadByIdentity.get(key);
|
|
121
|
+
if (current === undefined || current.completionOrder > request.throughCompletionOrder) {
|
|
122
|
+
return { mutations: [] };
|
|
123
|
+
}
|
|
124
|
+
this.assertRevisionCapacity(1);
|
|
125
|
+
this.unreadByIdentity.delete(key);
|
|
126
|
+
const mutations = [this.mutation(identity, null)];
|
|
127
|
+
this.schedulePersist();
|
|
128
|
+
return { mutations };
|
|
129
|
+
}
|
|
130
|
+
/** Remove durable unread and all transient lifecycle state for one identity. */
|
|
131
|
+
forgetSession(sessionId, cwd) {
|
|
132
|
+
this.requireLoaded();
|
|
133
|
+
const identity = requireIdentity(sessionId, cwd);
|
|
134
|
+
const key = sessionIdentityKey(identity);
|
|
135
|
+
const current = this.unreadByIdentity.get(key);
|
|
136
|
+
this.assertRevisionCapacity(current === undefined ? 0 : 1);
|
|
137
|
+
this.activeByIdentity.delete(key);
|
|
138
|
+
this.excludedByIdentity.delete(key);
|
|
139
|
+
if (current === undefined)
|
|
140
|
+
return [];
|
|
141
|
+
this.unreadByIdentity.delete(key);
|
|
142
|
+
const mutations = [this.mutation(identity, null)];
|
|
143
|
+
this.schedulePersist();
|
|
144
|
+
return mutations;
|
|
145
|
+
}
|
|
146
|
+
reconcileCwd(cwd, sessionIds) {
|
|
147
|
+
this.requireLoaded();
|
|
148
|
+
const boundedCwd = requireBoundedNonEmptyString(cwd, "cwd", SESSION_UNREAD_CWD_MAX_LENGTH);
|
|
149
|
+
const retained = new Set(sessionIds);
|
|
150
|
+
const removed = [...this.unreadByIdentity.entries()]
|
|
151
|
+
.filter(([, summary]) => summary.cwd === boundedCwd && !retained.has(summary.sessionId));
|
|
152
|
+
this.assertRevisionCapacity(removed.length);
|
|
153
|
+
for (const [key, identity] of this.activeByIdentity) {
|
|
154
|
+
if (identity.cwd === boundedCwd && !retained.has(identity.sessionId))
|
|
155
|
+
this.activeByIdentity.delete(key);
|
|
156
|
+
}
|
|
157
|
+
for (const [key, identity] of this.excludedByIdentity) {
|
|
158
|
+
if (identity.cwd === boundedCwd && !retained.has(identity.sessionId))
|
|
159
|
+
this.excludedByIdentity.delete(key);
|
|
160
|
+
}
|
|
161
|
+
const mutations = [];
|
|
162
|
+
for (const [key, summary] of removed) {
|
|
163
|
+
this.unreadByIdentity.delete(key);
|
|
164
|
+
mutations.push(this.mutation(summary, null));
|
|
165
|
+
}
|
|
166
|
+
if (mutations.length > 0)
|
|
167
|
+
this.schedulePersist();
|
|
168
|
+
return mutations;
|
|
169
|
+
}
|
|
170
|
+
/** Wait until all currently queued state is durably represented or throw. */
|
|
171
|
+
async flush() {
|
|
172
|
+
this.requireLoaded();
|
|
173
|
+
await this.waitForPersistenceWorker();
|
|
174
|
+
if (this.persistenceFailure === undefined
|
|
175
|
+
&& this.persistenceGeneration === this.durablePersistenceGeneration)
|
|
176
|
+
return;
|
|
177
|
+
// Retry the latest complete snapshot once. Failed/intermediate snapshots
|
|
178
|
+
// are coalesced because completion orders and revisions are cumulative.
|
|
179
|
+
this.ensurePersistenceWorker();
|
|
180
|
+
await this.waitForPersistenceWorker();
|
|
181
|
+
this.throwIfPersistenceFailed();
|
|
182
|
+
}
|
|
183
|
+
/** Snapshot safe to expose to a client that may subsequently acknowledge it. */
|
|
184
|
+
async durableCatalogSnapshot() {
|
|
185
|
+
let snapshot;
|
|
186
|
+
do {
|
|
187
|
+
await this.flush();
|
|
188
|
+
snapshot = this.catalogSnapshot();
|
|
189
|
+
} while (this.persistenceGeneration !== this.durablePersistenceGeneration);
|
|
190
|
+
return snapshot;
|
|
191
|
+
}
|
|
192
|
+
async loadPersistedState() {
|
|
193
|
+
const persistence = this.persistence;
|
|
194
|
+
if (persistence === undefined) {
|
|
195
|
+
this.loaded = true;
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
let value;
|
|
199
|
+
let resetState = false;
|
|
200
|
+
try {
|
|
201
|
+
value = await persistence.load();
|
|
202
|
+
}
|
|
203
|
+
catch (error) {
|
|
204
|
+
this.reportPersistenceError("load", error);
|
|
205
|
+
if (!(error instanceof SessionUnreadPersistenceCorruptionError))
|
|
206
|
+
throw error;
|
|
207
|
+
resetState = true;
|
|
208
|
+
}
|
|
209
|
+
if (!resetState && value !== undefined) {
|
|
210
|
+
try {
|
|
211
|
+
this.installPersistedState(parsePersistedState(value));
|
|
212
|
+
}
|
|
213
|
+
catch (error) {
|
|
214
|
+
this.reportPersistenceError("load", error);
|
|
215
|
+
resetState = true;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
else if (value === undefined) {
|
|
219
|
+
resetState = true;
|
|
220
|
+
}
|
|
221
|
+
if (resetState) {
|
|
222
|
+
this.resetInMemoryState();
|
|
223
|
+
// Persist even an empty epoch so the catalog identity itself survives a
|
|
224
|
+
// clean daemon restart and a corrupt file is repaired once.
|
|
225
|
+
this.schedulePersist();
|
|
226
|
+
await this.waitForPersistenceWorker();
|
|
227
|
+
try {
|
|
228
|
+
this.throwIfPersistenceFailed();
|
|
229
|
+
}
|
|
230
|
+
catch (error) {
|
|
231
|
+
this.loaded = false;
|
|
232
|
+
throw error;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
this.loaded = true;
|
|
236
|
+
}
|
|
237
|
+
resetInMemoryState() {
|
|
238
|
+
this.catalogId = this.freshCatalogId();
|
|
239
|
+
this.catalogRevision = 0;
|
|
240
|
+
this.nextCompletionOrder = 0;
|
|
241
|
+
this.unreadByIdentity.clear();
|
|
242
|
+
this.activeByIdentity.clear();
|
|
243
|
+
this.excludedByIdentity.clear();
|
|
244
|
+
}
|
|
245
|
+
mutation(identity, unread) {
|
|
246
|
+
this.catalogRevision = incrementSafe(this.catalogRevision, "Session unread catalog revision exhausted");
|
|
247
|
+
return {
|
|
248
|
+
event: {
|
|
249
|
+
type: "sessions.unread",
|
|
250
|
+
catalogId: this.catalogId,
|
|
251
|
+
catalogRevision: this.catalogRevision,
|
|
252
|
+
sessionId: identity.sessionId,
|
|
253
|
+
cwd: identity.cwd,
|
|
254
|
+
unread: unread === null ? null : { ...unread },
|
|
255
|
+
},
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
trimToLimit() {
|
|
259
|
+
const mutations = [];
|
|
260
|
+
while (this.unreadByIdentity.size > SESSION_UNREAD_LIMIT) {
|
|
261
|
+
let oldestKey;
|
|
262
|
+
let oldest;
|
|
263
|
+
for (const [key, summary] of this.unreadByIdentity) {
|
|
264
|
+
if (oldest === undefined || summary.completionOrder < oldest.completionOrder) {
|
|
265
|
+
oldestKey = key;
|
|
266
|
+
oldest = summary;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
if (oldestKey === undefined || oldest === undefined)
|
|
270
|
+
break;
|
|
271
|
+
this.unreadByIdentity.delete(oldestKey);
|
|
272
|
+
mutations.push(this.mutation(oldest, null));
|
|
273
|
+
}
|
|
274
|
+
return mutations;
|
|
275
|
+
}
|
|
276
|
+
assertRevisionCapacity(count) {
|
|
277
|
+
if (!Number.isSafeInteger(this.catalogRevision + count)) {
|
|
278
|
+
throw new Error("Session unread catalog revision exhausted");
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
schedulePersist() {
|
|
282
|
+
if (this.persistence === undefined)
|
|
283
|
+
return;
|
|
284
|
+
const generation = incrementSafe(this.persistenceGeneration, "Session unread persistence generation exhausted");
|
|
285
|
+
this.persistenceGeneration = generation;
|
|
286
|
+
this.pendingPersistence = { generation, state: this.persistedState() };
|
|
287
|
+
// Once a save fails, mutations continue replacing the one pending snapshot
|
|
288
|
+
// but do not hammer storage; the service's backoff (or an explicit flush)
|
|
289
|
+
// owns the next retry attempt.
|
|
290
|
+
if (this.persistenceFailure === undefined)
|
|
291
|
+
this.ensurePersistenceWorker();
|
|
292
|
+
}
|
|
293
|
+
ensurePersistenceWorker() {
|
|
294
|
+
if (this.persistence === undefined || this.persistenceWorker !== undefined || this.pendingPersistence === undefined)
|
|
295
|
+
return;
|
|
296
|
+
const worker = this.runPersistenceWorker();
|
|
297
|
+
this.persistenceWorker = worker;
|
|
298
|
+
void worker.finally(() => {
|
|
299
|
+
if (this.persistenceWorker === worker)
|
|
300
|
+
this.persistenceWorker = undefined;
|
|
301
|
+
});
|
|
302
|
+
}
|
|
303
|
+
async runPersistenceWorker() {
|
|
304
|
+
const persistence = this.persistence;
|
|
305
|
+
if (persistence === undefined)
|
|
306
|
+
return;
|
|
307
|
+
while (this.pendingPersistence !== undefined) {
|
|
308
|
+
const pending = this.pendingPersistence;
|
|
309
|
+
this.pendingPersistence = undefined;
|
|
310
|
+
try {
|
|
311
|
+
await persistence.save(pending.state);
|
|
312
|
+
this.durablePersistenceGeneration = pending.generation;
|
|
313
|
+
this.persistenceFailure = undefined;
|
|
314
|
+
}
|
|
315
|
+
catch (error) {
|
|
316
|
+
// A newer pending snapshot subsumes this failed one. Otherwise retain
|
|
317
|
+
// this exact snapshot so a later flush can retry without a new mutation.
|
|
318
|
+
this.pendingPersistence ??= pending;
|
|
319
|
+
this.persistenceFailure = { error };
|
|
320
|
+
this.reportPersistenceError("save", error);
|
|
321
|
+
return;
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
async waitForPersistenceWorker() {
|
|
326
|
+
let worker = this.persistenceWorker;
|
|
327
|
+
while (worker !== undefined) {
|
|
328
|
+
await worker;
|
|
329
|
+
worker = this.persistenceWorker;
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
throwIfPersistenceFailed() {
|
|
333
|
+
const failure = this.persistenceFailure;
|
|
334
|
+
if (failure !== undefined)
|
|
335
|
+
throw failure.error;
|
|
336
|
+
}
|
|
337
|
+
persistedState() {
|
|
338
|
+
return {
|
|
339
|
+
version: SESSION_UNREAD_STATE_VERSION,
|
|
340
|
+
catalogId: this.catalogId,
|
|
341
|
+
catalogRevision: this.catalogRevision,
|
|
342
|
+
nextCompletionOrder: this.nextCompletionOrder,
|
|
343
|
+
sessions: [...this.unreadByIdentity.values()].map((summary) => ({ ...summary })),
|
|
344
|
+
};
|
|
345
|
+
}
|
|
346
|
+
installPersistedState(state) {
|
|
347
|
+
this.catalogId = state.catalogId;
|
|
348
|
+
this.catalogRevision = state.catalogRevision;
|
|
349
|
+
this.nextCompletionOrder = state.nextCompletionOrder;
|
|
350
|
+
this.unreadByIdentity.clear();
|
|
351
|
+
for (const summary of [...state.sessions].sort((left, right) => left.completionOrder - right.completionOrder)) {
|
|
352
|
+
this.unreadByIdentity.set(sessionIdentityKey(summary), { ...summary });
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
freshCatalogId() {
|
|
356
|
+
return requireCatalogId(this.createCatalogId());
|
|
357
|
+
}
|
|
358
|
+
requireLoaded() {
|
|
359
|
+
if (!this.loaded)
|
|
360
|
+
throw new Error("Session unread store must be loaded before use");
|
|
361
|
+
}
|
|
362
|
+
reportPersistenceError(operation, error) {
|
|
363
|
+
try {
|
|
364
|
+
this.onPersistenceError(operation, error);
|
|
365
|
+
}
|
|
366
|
+
catch {
|
|
367
|
+
// Error reporting must not poison future serialized persistence work.
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
class SessionUnreadPersistenceCorruptionError extends Error {
|
|
372
|
+
constructor(cause) {
|
|
373
|
+
super("Session unread persistence contains invalid JSON", { cause });
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
export class FileSessionUnreadPersistence {
|
|
377
|
+
constructor(filePath = defaultSessionUnreadFilePath()) {
|
|
378
|
+
this.filePath = filePath;
|
|
379
|
+
}
|
|
380
|
+
async load() {
|
|
381
|
+
let source;
|
|
382
|
+
try {
|
|
383
|
+
source = await readFile(this.filePath, "utf8");
|
|
384
|
+
}
|
|
385
|
+
catch (error) {
|
|
386
|
+
if (isNodeError(error) && error.code === "ENOENT")
|
|
387
|
+
return undefined;
|
|
388
|
+
throw error;
|
|
389
|
+
}
|
|
390
|
+
try {
|
|
391
|
+
const value = JSON.parse(source);
|
|
392
|
+
return value;
|
|
393
|
+
}
|
|
394
|
+
catch (error) {
|
|
395
|
+
throw new SessionUnreadPersistenceCorruptionError(error);
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
async save(state) {
|
|
399
|
+
await mkdir(dirname(this.filePath), { recursive: true });
|
|
400
|
+
const tempPath = `${this.filePath}.${process.pid.toString()}-${randomUUID()}.tmp`;
|
|
401
|
+
try {
|
|
402
|
+
await writeFile(tempPath, `${JSON.stringify(state, null, 2)}\n`, {
|
|
403
|
+
encoding: "utf8",
|
|
404
|
+
mode: SESSION_UNREAD_FILE_MODE,
|
|
405
|
+
flag: "wx",
|
|
406
|
+
});
|
|
407
|
+
await rename(tempPath, this.filePath);
|
|
408
|
+
}
|
|
409
|
+
finally {
|
|
410
|
+
await rm(tempPath, { force: true }).catch(() => undefined);
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
export function defaultSessionUnreadFilePath(env = process.env, cwd = process.cwd()) {
|
|
415
|
+
return join(piWebDataDir(env, cwd), "session-unread.json");
|
|
416
|
+
}
|
|
417
|
+
function parsePersistedState(value) {
|
|
418
|
+
const record = requireRecord(value, "Session unread state must be an object");
|
|
419
|
+
if (record["version"] !== SESSION_UNREAD_STATE_VERSION)
|
|
420
|
+
throw new Error("Unsupported session unread state version");
|
|
421
|
+
const catalogId = requireCatalogId(record["catalogId"]);
|
|
422
|
+
const catalogRevision = requireNonNegativeSafeInteger(record["catalogRevision"], "catalogRevision");
|
|
423
|
+
const nextCompletionOrder = requireNonNegativeSafeInteger(record["nextCompletionOrder"], "nextCompletionOrder");
|
|
424
|
+
const rawSessions = record["sessions"];
|
|
425
|
+
if (!Array.isArray(rawSessions))
|
|
426
|
+
throw new Error("Session unread sessions must be an array");
|
|
427
|
+
if (rawSessions.length > SESSION_UNREAD_LIMIT)
|
|
428
|
+
throw new Error("Session unread state exceeds its session limit");
|
|
429
|
+
const sessions = rawSessions.map(parseSummary);
|
|
430
|
+
const identities = new Set();
|
|
431
|
+
const orders = new Set();
|
|
432
|
+
for (const summary of sessions) {
|
|
433
|
+
const key = sessionIdentityKey(summary);
|
|
434
|
+
if (identities.has(key))
|
|
435
|
+
throw new Error("Duplicate session unread identity");
|
|
436
|
+
if (orders.has(summary.completionOrder))
|
|
437
|
+
throw new Error("Duplicate session unread completion order");
|
|
438
|
+
identities.add(key);
|
|
439
|
+
orders.add(summary.completionOrder);
|
|
440
|
+
}
|
|
441
|
+
const maxOrder = sessions.reduce((maximum, summary) => Math.max(maximum, summary.completionOrder), 0);
|
|
442
|
+
if (nextCompletionOrder < maxOrder)
|
|
443
|
+
throw new Error("Session unread completion order is inconsistent");
|
|
444
|
+
if (catalogRevision < nextCompletionOrder)
|
|
445
|
+
throw new Error("Session unread catalog revision is inconsistent");
|
|
446
|
+
return {
|
|
447
|
+
version: SESSION_UNREAD_STATE_VERSION,
|
|
448
|
+
catalogId,
|
|
449
|
+
catalogRevision,
|
|
450
|
+
nextCompletionOrder,
|
|
451
|
+
sessions,
|
|
452
|
+
};
|
|
453
|
+
}
|
|
454
|
+
function parseSummary(value) {
|
|
455
|
+
const record = requireRecord(value, "Session unread summary must be an object");
|
|
456
|
+
const completedAt = requireBoundedNonEmptyString(record["completedAt"], "completedAt", SESSION_UNREAD_COMPLETED_AT_MAX_LENGTH);
|
|
457
|
+
const completedDate = new Date(completedAt);
|
|
458
|
+
if (!Number.isFinite(completedDate.getTime()) || completedDate.toISOString() !== completedAt) {
|
|
459
|
+
throw new Error("Session unread completedAt must be a canonical ISO timestamp");
|
|
460
|
+
}
|
|
461
|
+
return {
|
|
462
|
+
sessionId: requireBoundedNonEmptyString(record["sessionId"], "sessionId", SESSION_UNREAD_SESSION_ID_MAX_LENGTH),
|
|
463
|
+
cwd: requireBoundedNonEmptyString(record["cwd"], "cwd", SESSION_UNREAD_CWD_MAX_LENGTH),
|
|
464
|
+
completionOrder: requirePositiveSafeInteger(record["completionOrder"], "completionOrder"),
|
|
465
|
+
completedAt,
|
|
466
|
+
};
|
|
467
|
+
}
|
|
468
|
+
function requireRecord(value, message) {
|
|
469
|
+
if (!isRecord(value))
|
|
470
|
+
throw new Error(message);
|
|
471
|
+
return value;
|
|
472
|
+
}
|
|
473
|
+
function isRecord(value) {
|
|
474
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
475
|
+
}
|
|
476
|
+
function requireNonEmptyString(value, field) {
|
|
477
|
+
if (typeof value !== "string" || value === "")
|
|
478
|
+
throw new Error(`Session unread ${field} must be a non-empty string`);
|
|
479
|
+
return value;
|
|
480
|
+
}
|
|
481
|
+
function requireBoundedNonEmptyString(value, field, maxLength) {
|
|
482
|
+
const parsed = requireNonEmptyString(value, field);
|
|
483
|
+
if (parsed.length > maxLength)
|
|
484
|
+
throw new Error(`Session unread ${field} exceeds its length limit`);
|
|
485
|
+
return parsed;
|
|
486
|
+
}
|
|
487
|
+
function requireCatalogId(value) {
|
|
488
|
+
return requireBoundedNonEmptyString(value, "catalogId", SESSION_UNREAD_CATALOG_ID_MAX_LENGTH);
|
|
489
|
+
}
|
|
490
|
+
function requireNonNegativeSafeInteger(value, field) {
|
|
491
|
+
if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 0) {
|
|
492
|
+
throw new Error(`Session unread ${field} must be a non-negative safe integer`);
|
|
493
|
+
}
|
|
494
|
+
return value;
|
|
495
|
+
}
|
|
496
|
+
function requirePositiveSafeInteger(value, field) {
|
|
497
|
+
const parsed = requireNonNegativeSafeInteger(value, field);
|
|
498
|
+
if (parsed === 0)
|
|
499
|
+
throw new Error(`Session unread ${field} must be positive`);
|
|
500
|
+
return parsed;
|
|
501
|
+
}
|
|
502
|
+
function requireIdentity(sessionId, cwd) {
|
|
503
|
+
return {
|
|
504
|
+
sessionId: requireBoundedNonEmptyString(sessionId, "sessionId", SESSION_UNREAD_SESSION_ID_MAX_LENGTH),
|
|
505
|
+
cwd: requireBoundedNonEmptyString(cwd, "cwd", SESSION_UNREAD_CWD_MAX_LENGTH),
|
|
506
|
+
};
|
|
507
|
+
}
|
|
508
|
+
function sessionIdentityKey(identity) {
|
|
509
|
+
return JSON.stringify([identity.sessionId, identity.cwd]);
|
|
510
|
+
}
|
|
511
|
+
function incrementSafe(value, message) {
|
|
512
|
+
const next = value + 1;
|
|
513
|
+
if (!Number.isSafeInteger(next))
|
|
514
|
+
throw new Error(message);
|
|
515
|
+
return next;
|
|
516
|
+
}
|
|
517
|
+
function isNodeError(error) {
|
|
518
|
+
return error instanceof Error && "code" in error;
|
|
519
|
+
}
|
|
520
|
+
//# sourceMappingURL=sessionUnreadStore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sessionUnreadStore.js","sourceRoot":"","sources":["../../../src/server/sessions/sessionUnreadStore.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC1E,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EACL,oCAAoC,EACpC,sCAAsC,EACtC,6BAA6B,EAC7B,oBAAoB,EACpB,oCAAoC,GAKrC,MAAM,0BAA0B,CAAC;AAElC,MAAM,4BAA4B,GAAG,CAAC,CAAC;AACvC,MAAM,wBAAwB,GAAG,KAAK,CAAC;AAwCvC;;;;;;;GAOG;AACH,MAAM,OAAO,kBAAkB;IAmB7B,YAAY,UAAqC,EAAE;QAdlC,qBAAgB,GAAG,IAAI,GAAG,EAAgC,CAAC;QAC3D,qBAAgB,GAAG,IAAI,GAAG,EAAiC,CAAC;QAC5D,uBAAkB,GAAG,IAAI,GAAG,EAAiC,CAAC;QAEvE,oBAAe,GAAG,CAAC,CAAC;QACpB,wBAAmB,GAAG,CAAC,CAAC;QAGxB,0BAAqB,GAAG,CAAC,CAAC;QAC1B,iCAA4B,GAAG,CAAC,CAAC;QAMvC,IAAI,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;QAC7C,IAAI,CAAC,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC;QACvC,IAAI,CAAC,eAAe,GAAG,OAAO,CAAC,eAAe,IAAI,UAAU,CAAC;QAC7D,IAAI,CAAC,kBAAkB,GAAG,OAAO,CAAC,kBAAkB,IAAI,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QAC1E,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,WAAW,KAAK,SAAS,CAAC;QAC7C,uEAAuE;QACvE,4DAA4D;QAC5D,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IAC5D,CAAC;IAED,IAAI;QACF,IAAI,IAAI,CAAC,MAAM;YAAE,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;QAC1C,IAAI,IAAI,CAAC,WAAW,KAAK,SAAS;YAAE,OAAO,IAAI,CAAC,WAAW,CAAC;QAC5D,MAAM,WAAW,GAAG,IAAI,CAAC,kBAAkB,EAAE,CAAC;QAC9C,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;QAC/B,OAAO,WAAW,CAAC;IACrB,CAAC;IAED,yFAAyF;IACzF,eAAe;QACb,IAAI,CAAC,aAAa,EAAE,CAAC;QACrB,OAAO;YACL,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,eAAe,EAAE,IAAI,CAAC,eAAe;YACrC,QAAQ,EAAE,CAAC,GAAG,IAAI,CAAC,gBAAgB,CAAC,MAAM,EAAE,CAAC;iBAC1C,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,eAAe,GAAG,IAAI,CAAC,eAAe,CAAC;iBACnE,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC;SACtC,CAAC;IACJ,CAAC;IAED,oBAAoB,CAAC,SAAiB,EAAE,GAAW,EAAE,MAAe;QAClE,IAAI,CAAC,aAAa,EAAE,CAAC;QACrB,MAAM,QAAQ,GAAG,eAAe,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;QACjD,MAAM,GAAG,GAAG,kBAAkB,CAAC,QAAQ,CAAC,CAAC;QACzC,IAAI,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YACrC,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAClC,OAAO,EAAE,CAAC;QACZ,CAAC;QACD,IAAI,MAAM,EAAE,CAAC;YACX,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;YACzC,OAAO,EAAE,CAAC;QACZ,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,OAAO,EAAE,CAAC;QAE/C,MAAM,eAAe,GAAG,aAAa,CAAC,IAAI,CAAC,mBAAmB,EAAE,2CAA2C,CAAC,CAAC;QAC7G,MAAM,eAAe,GAAG,CAAC,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,gBAAgB,CAAC,IAAI,IAAI,oBAAoB,CAAC;QAC9G,IAAI,CAAC,sBAAsB,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACrD,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE,CAAC;QAE7C,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAClC,IAAI,CAAC,mBAAmB,GAAG,eAAe,CAAC;QAC3C,MAAM,OAAO,GAAyB;YACpC,SAAS;YACT,GAAG;YACH,eAAe;YACf,WAAW;SACZ,CAAC;QACF,sEAAsE;QACtE,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAClC,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QACxC,MAAM,SAAS,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,EAAE,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;QAC5E,IAAI,CAAC,eAAe,EAAE,CAAC;QACvB,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,wFAAwF;IACxF,cAAc,CAAC,SAAiB,EAAE,GAAW;QAC3C,IAAI,CAAC,aAAa,EAAE,CAAC;QACrB,MAAM,QAAQ,GAAG,eAAe,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;QACjD,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,kBAAkB,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC7D,CAAC;IAED;;;OAGG;IACH,cAAc,CAAC,SAAiB,EAAE,GAAW;QAC3C,IAAI,CAAC,aAAa,EAAE,CAAC;QACrB,MAAM,QAAQ,GAAG,eAAe,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;QACjD,MAAM,GAAG,GAAG,kBAAkB,CAAC,QAAQ,CAAC,CAAC;QACzC,MAAM,OAAO,GAAG,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC/C,IAAI,CAAC,sBAAsB,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAE3D,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;QAC3C,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAClC,IAAI,OAAO,KAAK,SAAS;YAAE,OAAO,EAAE,CAAC;QAErC,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAClC,MAAM,SAAS,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAC;QAClD,IAAI,CAAC,eAAe,EAAE,CAAC;QACvB,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,WAAW,CAAC,SAAiB,EAAE,OAAwC;QACrE,IAAI,CAAC,aAAa,EAAE,CAAC;QACrB,MAAM,QAAQ,GAAG,eAAe,CAAC,SAAS,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC;QACzD,gBAAgB,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QACpC,0BAA0B,CAAC,OAAO,CAAC,sBAAsB,EAAE,wBAAwB,CAAC,CAAC;QACrF,IAAI,OAAO,CAAC,SAAS,KAAK,IAAI,CAAC,SAAS;YAAE,OAAO,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC;QAEnE,MAAM,GAAG,GAAG,kBAAkB,CAAC,QAAQ,CAAC,CAAC;QACzC,MAAM,OAAO,GAAG,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC/C,IAAI,OAAO,KAAK,SAAS,IAAI,OAAO,CAAC,eAAe,GAAG,OAAO,CAAC,sBAAsB,EAAE,CAAC;YACtF,OAAO,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC;QAC3B,CAAC;QAED,IAAI,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC;QAC/B,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAClC,MAAM,SAAS,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAC;QAClD,IAAI,CAAC,eAAe,EAAE,CAAC;QACvB,OAAO,EAAE,SAAS,EAAE,CAAC;IACvB,CAAC;IAED,gFAAgF;IAChF,aAAa,CAAC,SAAiB,EAAE,GAAW;QAC1C,IAAI,CAAC,aAAa,EAAE,CAAC;QACrB,MAAM,QAAQ,GAAG,eAAe,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;QACjD,MAAM,GAAG,GAAG,kBAAkB,CAAC,QAAQ,CAAC,CAAC;QACzC,MAAM,OAAO,GAAG,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC/C,IAAI,CAAC,sBAAsB,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAE3D,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAClC,IAAI,CAAC,kBAAkB,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACpC,IAAI,OAAO,KAAK,SAAS;YAAE,OAAO,EAAE,CAAC;QAErC,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAClC,MAAM,SAAS,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAC;QAClD,IAAI,CAAC,eAAe,EAAE,CAAC;QACvB,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,YAAY,CAAC,GAAW,EAAE,UAA4B;QACpD,IAAI,CAAC,aAAa,EAAE,CAAC;QACrB,MAAM,UAAU,GAAG,4BAA4B,CAAC,GAAG,EAAE,KAAK,EAAE,6BAA6B,CAAC,CAAC;QAC3F,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,CAAC;QACrC,MAAM,OAAO,GAAG,CAAC,GAAG,IAAI,CAAC,gBAAgB,CAAC,OAAO,EAAE,CAAC;aACjD,MAAM,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,KAAK,UAAU,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC;QAC3F,IAAI,CAAC,sBAAsB,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAE5C,KAAK,MAAM,CAAC,GAAG,EAAE,QAAQ,CAAC,IAAI,IAAI,CAAC,gBAAgB,EAAE,CAAC;YACpD,IAAI,QAAQ,CAAC,GAAG,KAAK,UAAU,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,SAAS,CAAC;gBAAE,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC1G,CAAC;QACD,KAAK,MAAM,CAAC,GAAG,EAAE,QAAQ,CAAC,IAAI,IAAI,CAAC,kBAAkB,EAAE,CAAC;YACtD,IAAI,QAAQ,CAAC,GAAG,KAAK,UAAU,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,SAAS,CAAC;gBAAE,IAAI,CAAC,kBAAkB,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC5G,CAAC;QAED,MAAM,SAAS,GAA4B,EAAE,CAAC;QAC9C,KAAK,MAAM,CAAC,GAAG,EAAE,OAAO,CAAC,IAAI,OAAO,EAAE,CAAC;YACrC,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAClC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC;QAC/C,CAAC;QACD,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC;YAAE,IAAI,CAAC,eAAe,EAAE,CAAC;QACjD,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,6EAA6E;IAC7E,KAAK,CAAC,KAAK;QACT,IAAI,CAAC,aAAa,EAAE,CAAC;QACrB,MAAM,IAAI,CAAC,wBAAwB,EAAE,CAAC;QACtC,IAAI,IAAI,CAAC,kBAAkB,KAAK,SAAS;eACpC,IAAI,CAAC,qBAAqB,KAAK,IAAI,CAAC,4BAA4B;YAAE,OAAO;QAE9E,yEAAyE;QACzE,wEAAwE;QACxE,IAAI,CAAC,uBAAuB,EAAE,CAAC;QAC/B,MAAM,IAAI,CAAC,wBAAwB,EAAE,CAAC;QACtC,IAAI,CAAC,wBAAwB,EAAE,CAAC;IAClC,CAAC;IAED,gFAAgF;IAChF,KAAK,CAAC,sBAAsB;QAC1B,IAAI,QAAsC,CAAC;QAC3C,GAAG,CAAC;YACF,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC;YACnB,QAAQ,GAAG,IAAI,CAAC,eAAe,EAAE,CAAC;QACpC,CAAC,QAAQ,IAAI,CAAC,qBAAqB,KAAK,IAAI,CAAC,4BAA4B,EAAE;QAC3E,OAAO,QAAQ,CAAC;IAClB,CAAC;IAEO,KAAK,CAAC,kBAAkB;QAC9B,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,CAAC;QACrC,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;YAC9B,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;YACnB,OAAO;QACT,CAAC;QAED,IAAI,KAAc,CAAC;QACnB,IAAI,UAAU,GAAG,KAAK,CAAC;QACvB,IAAI,CAAC;YACH,KAAK,GAAG,MAAM,WAAW,CAAC,IAAI,EAAE,CAAC;QACnC,CAAC;QAAC,OAAO,KAAc,EAAE,CAAC;YACxB,IAAI,CAAC,sBAAsB,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;YAC3C,IAAI,CAAC,CAAC,KAAK,YAAY,uCAAuC,CAAC;gBAAE,MAAM,KAAK,CAAC;YAC7E,UAAU,GAAG,IAAI,CAAC;QACpB,CAAC;QAED,IAAI,CAAC,UAAU,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACvC,IAAI,CAAC;gBACH,IAAI,CAAC,qBAAqB,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC,CAAC;YACzD,CAAC;YAAC,OAAO,KAAc,EAAE,CAAC;gBACxB,IAAI,CAAC,sBAAsB,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;gBAC3C,UAAU,GAAG,IAAI,CAAC;YACpB,CAAC;QACH,CAAC;aAAM,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YAC/B,UAAU,GAAG,IAAI,CAAC;QACpB,CAAC;QAED,IAAI,UAAU,EAAE,CAAC;YACf,IAAI,CAAC,kBAAkB,EAAE,CAAC;YAC1B,wEAAwE;YACxE,4DAA4D;YAC5D,IAAI,CAAC,eAAe,EAAE,CAAC;YACvB,MAAM,IAAI,CAAC,wBAAwB,EAAE,CAAC;YACtC,IAAI,CAAC;gBACH,IAAI,CAAC,wBAAwB,EAAE,CAAC;YAClC,CAAC;YAAC,OAAO,KAAc,EAAE,CAAC;gBACxB,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;gBACpB,MAAM,KAAK,CAAC;YACd,CAAC;QACH,CAAC;QACD,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;IACrB,CAAC;IAEO,kBAAkB;QACxB,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC;QACvC,IAAI,CAAC,eAAe,GAAG,CAAC,CAAC;QACzB,IAAI,CAAC,mBAAmB,GAAG,CAAC,CAAC;QAC7B,IAAI,CAAC,gBAAgB,CAAC,KAAK,EAAE,CAAC;QAC9B,IAAI,CAAC,gBAAgB,CAAC,KAAK,EAAE,CAAC;QAC9B,IAAI,CAAC,kBAAkB,CAAC,KAAK,EAAE,CAAC;IAClC,CAAC;IAEO,QAAQ,CAAC,QAA+B,EAAE,MAAmC;QACnF,IAAI,CAAC,eAAe,GAAG,aAAa,CAAC,IAAI,CAAC,eAAe,EAAE,2CAA2C,CAAC,CAAC;QACxG,OAAO;YACL,KAAK,EAAE;gBACL,IAAI,EAAE,iBAAiB;gBACvB,SAAS,EAAE,IAAI,CAAC,SAAS;gBACzB,eAAe,EAAE,IAAI,CAAC,eAAe;gBACrC,SAAS,EAAE,QAAQ,CAAC,SAAS;gBAC7B,GAAG,EAAE,QAAQ,CAAC,GAAG;gBACjB,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,GAAG,MAAM,EAAE;aAC/C;SACF,CAAC;IACJ,CAAC;IAEO,WAAW;QACjB,MAAM,SAAS,GAA4B,EAAE,CAAC;QAC9C,OAAO,IAAI,CAAC,gBAAgB,CAAC,IAAI,GAAG,oBAAoB,EAAE,CAAC;YACzD,IAAI,SAA6B,CAAC;YAClC,IAAI,MAAwC,CAAC;YAC7C,KAAK,MAAM,CAAC,GAAG,EAAE,OAAO,CAAC,IAAI,IAAI,CAAC,gBAAgB,EAAE,CAAC;gBACnD,IAAI,MAAM,KAAK,SAAS,IAAI,OAAO,CAAC,eAAe,GAAG,MAAM,CAAC,eAAe,EAAE,CAAC;oBAC7E,SAAS,GAAG,GAAG,CAAC;oBAChB,MAAM,GAAG,OAAO,CAAC;gBACnB,CAAC;YACH,CAAC;YACD,IAAI,SAAS,KAAK,SAAS,IAAI,MAAM,KAAK,SAAS;gBAAE,MAAM;YAC3D,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;YACxC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC;QAC9C,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IAEO,sBAAsB,CAAC,KAAa;QAC1C,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,eAAe,GAAG,KAAK,CAAC,EAAE,CAAC;YACxD,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;QAC/D,CAAC;IACH,CAAC;IAEO,eAAe;QACrB,IAAI,IAAI,CAAC,WAAW,KAAK,SAAS;YAAE,OAAO;QAC3C,MAAM,UAAU,GAAG,aAAa,CAAC,IAAI,CAAC,qBAAqB,EAAE,iDAAiD,CAAC,CAAC;QAChH,IAAI,CAAC,qBAAqB,GAAG,UAAU,CAAC;QACxC,IAAI,CAAC,kBAAkB,GAAG,EAAE,UAAU,EAAE,KAAK,EAAE,IAAI,CAAC,cAAc,EAAE,EAAE,CAAC;QACvE,2EAA2E;QAC3E,0EAA0E;QAC1E,+BAA+B;QAC/B,IAAI,IAAI,CAAC,kBAAkB,KAAK,SAAS;YAAE,IAAI,CAAC,uBAAuB,EAAE,CAAC;IAC5E,CAAC;IAEO,uBAAuB;QAC7B,IAAI,IAAI,CAAC,WAAW,KAAK,SAAS,IAAI,IAAI,CAAC,iBAAiB,KAAK,SAAS,IAAI,IAAI,CAAC,kBAAkB,KAAK,SAAS;YAAE,OAAO;QAC5H,MAAM,MAAM,GAAG,IAAI,CAAC,oBAAoB,EAAE,CAAC;QAC3C,IAAI,CAAC,iBAAiB,GAAG,MAAM,CAAC;QAChC,KAAK,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE;YACvB,IAAI,IAAI,CAAC,iBAAiB,KAAK,MAAM;gBAAE,IAAI,CAAC,iBAAiB,GAAG,SAAS,CAAC;QAC5E,CAAC,CAAC,CAAC;IACL,CAAC;IAEO,KAAK,CAAC,oBAAoB;QAChC,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,CAAC;QACrC,IAAI,WAAW,KAAK,SAAS;YAAE,OAAO;QACtC,OAAO,IAAI,CAAC,kBAAkB,KAAK,SAAS,EAAE,CAAC;YAC7C,MAAM,OAAO,GAAG,IAAI,CAAC,kBAAkB,CAAC;YACxC,IAAI,CAAC,kBAAkB,GAAG,SAAS,CAAC;YACpC,IAAI,CAAC;gBACH,MAAM,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;gBACtC,IAAI,CAAC,4BAA4B,GAAG,OAAO,CAAC,UAAU,CAAC;gBACvD,IAAI,CAAC,kBAAkB,GAAG,SAAS,CAAC;YACtC,CAAC;YAAC,OAAO,KAAc,EAAE,CAAC;gBACxB,sEAAsE;gBACtE,yEAAyE;gBACzE,IAAI,CAAC,kBAAkB,KAAK,OAAO,CAAC;gBACpC,IAAI,CAAC,kBAAkB,GAAG,EAAE,KAAK,EAAE,CAAC;gBACpC,IAAI,CAAC,sBAAsB,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;gBAC3C,OAAO;YACT,CAAC;QACH,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,wBAAwB;QACpC,IAAI,MAAM,GAAG,IAAI,CAAC,iBAAiB,CAAC;QACpC,OAAO,MAAM,KAAK,SAAS,EAAE,CAAC;YAC5B,MAAM,MAAM,CAAC;YACb,MAAM,GAAG,IAAI,CAAC,iBAAiB,CAAC;QAClC,CAAC;IACH,CAAC;IAEO,wBAAwB;QAC9B,MAAM,OAAO,GAAG,IAAI,CAAC,kBAAkB,CAAC;QACxC,IAAI,OAAO,KAAK,SAAS;YAAE,MAAM,OAAO,CAAC,KAAK,CAAC;IACjD,CAAC;IAEO,cAAc;QACpB,OAAO;YACL,OAAO,EAAE,4BAA4B;YACrC,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,eAAe,EAAE,IAAI,CAAC,eAAe;YACrC,mBAAmB,EAAE,IAAI,CAAC,mBAAmB;YAC7C,QAAQ,EAAE,CAAC,GAAG,IAAI,CAAC,gBAAgB,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC;SACjF,CAAC;IACJ,CAAC;IAEO,qBAAqB,CAAC,KAAkC;QAC9D,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC,SAAS,CAAC;QACjC,IAAI,CAAC,eAAe,GAAG,KAAK,CAAC,eAAe,CAAC;QAC7C,IAAI,CAAC,mBAAmB,GAAG,KAAK,CAAC,mBAAmB,CAAC;QACrD,IAAI,CAAC,gBAAgB,CAAC,KAAK,EAAE,CAAC;QAC9B,KAAK,MAAM,OAAO,IAAI,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,eAAe,GAAG,KAAK,CAAC,eAAe,CAAC,EAAE,CAAC;YAC9G,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,kBAAkB,CAAC,OAAO,CAAC,EAAE,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC;QACzE,CAAC;IACH,CAAC;IAEO,cAAc;QACpB,OAAO,gBAAgB,CAAC,IAAI,CAAC,eAAe,EAAE,CAAC,CAAC;IAClD,CAAC;IAEO,aAAa;QACnB,IAAI,CAAC,IAAI,CAAC,MAAM;YAAE,MAAM,IAAI,KAAK,CAAC,gDAAgD,CAAC,CAAC;IACtF,CAAC;IAEO,sBAAsB,CAAC,SAA0B,EAAE,KAAc;QACvE,IAAI,CAAC;YACH,IAAI,CAAC,kBAAkB,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;QAC5C,CAAC;QAAC,MAAM,CAAC;YACP,sEAAsE;QACxE,CAAC;IACH,CAAC;CACF;AAED,MAAM,uCAAwC,SAAQ,KAAK;IACzD,YAAY,KAAc;QACxB,KAAK,CAAC,kDAAkD,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;IACvE,CAAC;CACF;AAED,MAAM,OAAO,4BAA4B;IACvC,YAAqB,WAAW,4BAA4B,EAAE;QAAzC,aAAQ,GAAR,QAAQ,CAAiC;IAAG,CAAC;IAElE,KAAK,CAAC,IAAI;QACR,IAAI,MAAc,CAAC;QACnB,IAAI,CAAC;YACH,MAAM,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QACjD,CAAC;QAAC,OAAO,KAAc,EAAE,CAAC;YACxB,IAAI,WAAW,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ;gBAAE,OAAO,SAAS,CAAC;YACpE,MAAM,KAAK,CAAC;QACd,CAAC;QACD,IAAI,CAAC;YACH,MAAM,KAAK,GAAY,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;YAC1C,OAAO,KAAK,CAAC;QACf,CAAC;QAAC,OAAO,KAAc,EAAE,CAAC;YACxB,MAAM,IAAI,uCAAuC,CAAC,KAAK,CAAC,CAAC;QAC3D,CAAC;IACH,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,KAAkC;QAC3C,MAAM,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACzD,MAAM,QAAQ,GAAG,GAAG,IAAI,CAAC,QAAQ,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,UAAU,EAAE,MAAM,CAAC;QAClF,IAAI,CAAC;YACH,MAAM,SAAS,CAAC,QAAQ,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE;gBAC/D,QAAQ,EAAE,MAAM;gBAChB,IAAI,EAAE,wBAAwB;gBAC9B,IAAI,EAAE,IAAI;aACX,CAAC,CAAC;YACH,MAAM,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;QACxC,CAAC;gBAAS,CAAC;YACT,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QAC7D,CAAC;IACH,CAAC;CACF;AAED,MAAM,UAAU,4BAA4B,CAAC,MAAyB,OAAO,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE;IACpG,OAAO,IAAI,CAAC,YAAY,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,qBAAqB,CAAC,CAAC;AAC7D,CAAC;AAED,SAAS,mBAAmB,CAAC,KAAc;IACzC,MAAM,MAAM,GAAG,aAAa,CAAC,KAAK,EAAE,wCAAwC,CAAC,CAAC;IAC9E,IAAI,MAAM,CAAC,SAAS,CAAC,KAAK,4BAA4B;QAAE,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;IACpH,MAAM,SAAS,GAAG,gBAAgB,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC;IACxD,MAAM,eAAe,GAAG,6BAA6B,CAAC,MAAM,CAAC,iBAAiB,CAAC,EAAE,iBAAiB,CAAC,CAAC;IACpG,MAAM,mBAAmB,GAAG,6BAA6B,CAAC,MAAM,CAAC,qBAAqB,CAAC,EAAE,qBAAqB,CAAC,CAAC;IAChH,MAAM,WAAW,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC;IACvC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;IAC7F,IAAI,WAAW,CAAC,MAAM,GAAG,oBAAoB;QAAE,MAAM,IAAI,KAAK,CAAC,gDAAgD,CAAC,CAAC;IAEjH,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;IAC/C,MAAM,UAAU,GAAG,IAAI,GAAG,EAAU,CAAC;IACrC,MAAM,MAAM,GAAG,IAAI,GAAG,EAAU,CAAC;IACjC,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,MAAM,GAAG,GAAG,kBAAkB,CAAC,OAAO,CAAC,CAAC;QACxC,IAAI,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;QAC9E,IAAI,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,eAAe,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;QACtG,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACpB,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;IACtC,CAAC;IACD,MAAM,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,eAAe,CAAC,EAAE,CAAC,CAAC,CAAC;IACtG,IAAI,mBAAmB,GAAG,QAAQ;QAAE,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;IACvG,IAAI,eAAe,GAAG,mBAAmB;QAAE,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;IAC9G,OAAO;QACL,OAAO,EAAE,4BAA4B;QACrC,SAAS;QACT,eAAe;QACf,mBAAmB;QACnB,QAAQ;KACT,CAAC;AACJ,CAAC;AAED,SAAS,YAAY,CAAC,KAAc;IAClC,MAAM,MAAM,GAAG,aAAa,CAAC,KAAK,EAAE,0CAA0C,CAAC,CAAC;IAChF,MAAM,WAAW,GAAG,4BAA4B,CAC9C,MAAM,CAAC,aAAa,CAAC,EACrB,aAAa,EACb,sCAAsC,CACvC,CAAC;IACF,MAAM,aAAa,GAAG,IAAI,IAAI,CAAC,WAAW,CAAC,CAAC;IAC5C,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC,OAAO,EAAE,CAAC,IAAI,aAAa,CAAC,WAAW,EAAE,KAAK,WAAW,EAAE,CAAC;QAC7F,MAAM,IAAI,KAAK,CAAC,8DAA8D,CAAC,CAAC;IAClF,CAAC;IACD,OAAO;QACL,SAAS,EAAE,4BAA4B,CACrC,MAAM,CAAC,WAAW,CAAC,EACnB,WAAW,EACX,oCAAoC,CACrC;QACD,GAAG,EAAE,4BAA4B,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,6BAA6B,CAAC;QACtF,eAAe,EAAE,0BAA0B,CAAC,MAAM,CAAC,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;QACzF,WAAW;KACZ,CAAC;AACJ,CAAC;AAED,SAAS,aAAa,CAAC,KAAc,EAAE,OAAe;IACpD,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC;IAC/C,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,QAAQ,CAAC,KAAc;IAC9B,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAC9E,CAAC;AAED,SAAS,qBAAqB,CAAC,KAAc,EAAE,KAAa;IAC1D,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,kBAAkB,KAAK,6BAA6B,CAAC,CAAC;IACrH,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,4BAA4B,CAAC,KAAc,EAAE,KAAa,EAAE,SAAiB;IACpF,MAAM,MAAM,GAAG,qBAAqB,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IACnD,IAAI,MAAM,CAAC,MAAM,GAAG,SAAS;QAAE,MAAM,IAAI,KAAK,CAAC,kBAAkB,KAAK,2BAA2B,CAAC,CAAC;IACnG,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,gBAAgB,CAAC,KAAc;IACtC,OAAO,4BAA4B,CAAC,KAAK,EAAE,WAAW,EAAE,oCAAoC,CAAC,CAAC;AAChG,CAAC;AAED,SAAS,6BAA6B,CAAC,KAAc,EAAE,KAAa;IAClE,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;QAC3E,MAAM,IAAI,KAAK,CAAC,kBAAkB,KAAK,sCAAsC,CAAC,CAAC;IACjF,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,0BAA0B,CAAC,KAAc,EAAE,KAAa;IAC/D,MAAM,MAAM,GAAG,6BAA6B,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IAC3D,IAAI,MAAM,KAAK,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,kBAAkB,KAAK,mBAAmB,CAAC,CAAC;IAC9E,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,eAAe,CAAC,SAAiB,EAAE,GAAW;IACrD,OAAO;QACL,SAAS,EAAE,4BAA4B,CAAC,SAAS,EAAE,WAAW,EAAE,oCAAoC,CAAC;QACrG,GAAG,EAAE,4BAA4B,CAAC,GAAG,EAAE,KAAK,EAAE,6BAA6B,CAAC;KAC7E,CAAC;AACJ,CAAC;AAED,SAAS,kBAAkB,CAAC,QAA+B;IACzD,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,QAAQ,CAAC,SAAS,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC;AAC5D,CAAC;AAED,SAAS,aAAa,CAAC,KAAa,EAAE,OAAe;IACnD,MAAM,IAAI,GAAG,KAAK,GAAG,CAAC,CAAC;IACvB,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC;IAC1D,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,WAAW,CAAC,KAAc;IACjC,OAAO,KAAK,YAAY,KAAK,IAAI,MAAM,IAAI,KAAK,CAAC;AACnD,CAAC"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Letting in-flight agent runs finish before the daemon exits.
|
|
3
|
+
*
|
|
4
|
+
* Restarting to pick up an update currently kills whatever the agent was in the
|
|
5
|
+
* middle of. There is no way to resume such a run afterwards — it is a live
|
|
6
|
+
* streaming request plus a tool-call loop, and once the process is gone there is
|
|
7
|
+
* no execution point left to return to — so the only honest way to make updates
|
|
8
|
+
* non-disruptive is to not interrupt the run in the first place.
|
|
9
|
+
*
|
|
10
|
+
* The daemon therefore stops accepting new work immediately on the signal, then
|
|
11
|
+
* waits for the runs already underway. The wait is bounded: a stuck run must not
|
|
12
|
+
* hold a service restart open forever, and an operator who sent the signal is
|
|
13
|
+
* entitled to have the process eventually go away.
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* Decide whether to keep draining.
|
|
17
|
+
*
|
|
18
|
+
* A zero timeout means the previous behaviour — exit immediately — so the
|
|
19
|
+
* feature can be turned off without removing it.
|
|
20
|
+
*/
|
|
21
|
+
export function drainDecision(state) {
|
|
22
|
+
if (state.timeoutMs <= 0) {
|
|
23
|
+
return { wait: false, reason: "drain-disabled", activeSessionIds: state.activeSessionIds };
|
|
24
|
+
}
|
|
25
|
+
if (state.activeSessionIds.length === 0) {
|
|
26
|
+
return { wait: false, reason: "no-active-work", activeSessionIds: [] };
|
|
27
|
+
}
|
|
28
|
+
if (state.elapsedMs >= state.timeoutMs) {
|
|
29
|
+
// Deliberately gives up rather than waiting out an unbounded run: the
|
|
30
|
+
// sessions still working are reported so they are not lost silently.
|
|
31
|
+
return { wait: false, reason: "deadline-reached", activeSessionIds: state.activeSessionIds };
|
|
32
|
+
}
|
|
33
|
+
return { wait: true, reason: "waiting-for-active-work", activeSessionIds: state.activeSessionIds };
|
|
34
|
+
}
|
|
35
|
+
/** Default wait: long enough for a typical turn, short enough for a service restart. */
|
|
36
|
+
export const DEFAULT_DRAIN_TIMEOUT_MS = 60_000;
|
|
37
|
+
/**
|
|
38
|
+
* Resolve the drain timeout from the environment.
|
|
39
|
+
*
|
|
40
|
+
* `PI_WEB_SHUTDOWN_DRAIN_MS=0` restores the immediate-exit behaviour. An
|
|
41
|
+
* unparseable value falls back to the default rather than failing a shutdown,
|
|
42
|
+
* because refusing to stop is a worse outcome than a mistyped timeout.
|
|
43
|
+
*/
|
|
44
|
+
export function resolveDrainTimeoutMs(env, fallback = DEFAULT_DRAIN_TIMEOUT_MS) {
|
|
45
|
+
const raw = env["PI_WEB_SHUTDOWN_DRAIN_MS"];
|
|
46
|
+
if (raw === undefined || raw.trim() === "")
|
|
47
|
+
return fallback;
|
|
48
|
+
const parsed = Number(raw);
|
|
49
|
+
if (!Number.isFinite(parsed) || parsed < 0)
|
|
50
|
+
return fallback;
|
|
51
|
+
return Math.floor(parsed);
|
|
52
|
+
}
|
|
53
|
+
/** How often the drain re-checks. Frequent enough to exit promptly once idle. */
|
|
54
|
+
export const DRAIN_POLL_MS = 250;
|
|
55
|
+
/**
|
|
56
|
+
* Wait until no session is working, the deadline passes, or draining is off.
|
|
57
|
+
* Returns the decision that ended the wait, so the caller can log what happened
|
|
58
|
+
* and record which sessions were still running if it gave up.
|
|
59
|
+
*/
|
|
60
|
+
export async function drainActiveWork(timeoutMs, deps) {
|
|
61
|
+
for (;;) {
|
|
62
|
+
const decision = drainDecision({
|
|
63
|
+
activeSessionIds: deps.activeSessionIds(),
|
|
64
|
+
elapsedMs: deps.elapsedMs(),
|
|
65
|
+
timeoutMs,
|
|
66
|
+
});
|
|
67
|
+
deps.onProgress?.(decision);
|
|
68
|
+
if (!decision.wait)
|
|
69
|
+
return decision;
|
|
70
|
+
await deps.wait(DRAIN_POLL_MS);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=shutdownDrain.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shutdownDrain.js","sourceRoot":"","sources":["../../../src/server/sessions/shutdownDrain.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAiBH;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAAC,KAAiB;IAC7C,IAAI,KAAK,CAAC,SAAS,IAAI,CAAC,EAAE,CAAC;QACzB,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,KAAK,CAAC,gBAAgB,EAAE,CAAC;IAC7F,CAAC;IACD,IAAI,KAAK,CAAC,gBAAgB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxC,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,EAAE,EAAE,CAAC;IACzE,CAAC;IACD,IAAI,KAAK,CAAC,SAAS,IAAI,KAAK,CAAC,SAAS,EAAE,CAAC;QACvC,sEAAsE;QACtE,qEAAqE;QACrE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,KAAK,CAAC,gBAAgB,EAAE,CAAC;IAC/F,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,yBAAyB,EAAE,gBAAgB,EAAE,KAAK,CAAC,gBAAgB,EAAE,CAAC;AACrG,CAAC;AAED,wFAAwF;AACxF,MAAM,CAAC,MAAM,wBAAwB,GAAG,MAAM,CAAC;AAE/C;;;;;;GAMG;AACH,MAAM,UAAU,qBAAqB,CACnC,GAAiD,EACjD,QAAQ,GAAG,wBAAwB;IAEnC,MAAM,GAAG,GAAG,GAAG,CAAC,0BAA0B,CAAC,CAAC;IAC5C,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,CAAC,IAAI,EAAE,KAAK,EAAE;QAAE,OAAO,QAAQ,CAAC;IAC5D,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;IAC3B,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,MAAM,GAAG,CAAC;QAAE,OAAO,QAAQ,CAAC;IAC5D,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;AAC5B,CAAC;AAYD,iFAAiF;AACjF,MAAM,CAAC,MAAM,aAAa,GAAG,GAAG,CAAC;AAEjC;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,SAAiB,EAAE,IAAe;IACtE,SAAS,CAAC;QACR,MAAM,QAAQ,GAAG,aAAa,CAAC;YAC7B,gBAAgB,EAAE,IAAI,CAAC,gBAAgB,EAAE;YACzC,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE;YAC3B,SAAS;SACV,CAAC,CAAC;QACH,IAAI,CAAC,UAAU,EAAE,CAAC,QAAQ,CAAC,CAAC;QAC5B,IAAI,CAAC,QAAQ,CAAC,IAAI;YAAE,OAAO,QAAQ,CAAC;QACpC,MAAM,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IACjC,CAAC;AACH,CAAC"}
|