@cats-inc/cats-platform 0.1.21 → 0.2.8
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/.env.example +3 -7
- package/README.md +18 -0
- package/build/desktop/bootstrapNavigation.d.ts.map +1 -1
- package/build/desktop/bootstrapNavigation.js +6 -13
- package/build/desktop/bootstrapNavigation.js.map +1 -1
- package/build/desktop/bootstrapPage.d.ts.map +1 -1
- package/build/desktop/bootstrapPage.js +114 -34
- package/build/desktop/bootstrapPage.js.map +1 -1
- package/build/desktop/cliInventoryProbe.d.ts +5 -2
- package/build/desktop/cliInventoryProbe.d.ts.map +1 -1
- package/build/desktop/cliInventoryProbe.js +14 -11
- package/build/desktop/cliInventoryProbe.js.map +1 -1
- package/build/desktop/config.d.ts +0 -4
- package/build/desktop/config.d.ts.map +1 -1
- package/build/desktop/config.js +1 -6
- package/build/desktop/config.js.map +1 -1
- package/build/desktop/contracts.d.ts +10 -2
- package/build/desktop/contracts.d.ts.map +1 -1
- package/build/desktop/contracts.js +1 -2
- package/build/desktop/contracts.js.map +1 -1
- package/build/desktop/hostVersion.d.ts.map +1 -1
- package/build/desktop/hostVersion.js +3 -5
- package/build/desktop/hostVersion.js.map +1 -1
- package/build/desktop/main.js +144 -249
- package/build/desktop/main.js.map +1 -1
- package/build/desktop/packaging.d.ts +2 -0
- package/build/desktop/packaging.d.ts.map +1 -1
- package/build/desktop/packaging.js +34 -14
- package/build/desktop/packaging.js.map +1 -1
- package/build/desktop/preload.cjs +7 -0
- package/build/desktop/preload.cjs.map +1 -1
- package/build/desktop/processSupervisor.d.ts.map +1 -1
- package/build/desktop/processSupervisor.js +3 -0
- package/build/desktop/processSupervisor.js.map +1 -1
- package/build/desktop/providerSelection.d.ts +37 -0
- package/build/desktop/providerSelection.d.ts.map +1 -0
- package/build/desktop/providerSelection.js +112 -0
- package/build/desktop/providerSelection.js.map +1 -0
- package/build/desktop/readiness.d.ts +2 -0
- package/build/desktop/readiness.d.ts.map +1 -1
- package/build/desktop/readiness.js +14 -33
- package/build/desktop/readiness.js.map +1 -1
- package/build/desktop/setupAssets.d.ts.map +1 -1
- package/build/desktop/setupAssets.js +16 -14
- package/build/desktop/setupAssets.js.map +1 -1
- package/build/desktop/setupAudit.d.ts +2 -3
- package/build/desktop/setupAudit.d.ts.map +1 -1
- package/build/desktop/setupAudit.js +14 -34
- package/build/desktop/setupAudit.js.map +1 -1
- package/build/desktop/updateDialog.d.ts +27 -1
- package/build/desktop/updateDialog.d.ts.map +1 -1
- package/build/desktop/updateDialog.js +85 -5
- package/build/desktop/updateDialog.js.map +1 -1
- package/build/renderer/assets/{ActiveSessionPermissionChip-DImsuR9T.js → ActiveSessionPermissionChip-CAgN-tXv.js} +1 -1
- package/build/renderer/assets/App-BZA23O2J.js +2 -0
- package/build/renderer/assets/App-DxsV-tKS.css +1 -0
- package/build/renderer/assets/{App-DKOSn0o_.js → App-YqprEL2n.js} +1 -1
- package/build/renderer/assets/App-rGw9J8PZ.js +1 -0
- package/build/renderer/assets/WorkspaceAppRoutes-BCHCikmJ.js +1 -0
- package/build/renderer/assets/app-BV3UAQkR.css +1 -0
- package/build/renderer/assets/app-CVPqqfZo.js +45 -0
- package/build/renderer/assets/conversationSidebarRecentEntries-iqaLqA1n.js +6 -0
- package/build/renderer/assets/{useDraftSessionChips-DCIId0eY.js → useDraftSessionChips-D9BX6X92.js} +1 -1
- package/build/renderer/index.html +2 -2
- package/build/server/app/renderer/providerCatalogClient.d.ts.map +1 -1
- package/build/server/app/renderer/providerCatalogClient.js +15 -6
- package/build/server/app/renderer/providerCatalogClient.js.map +1 -1
- package/build/server/app/renderer/providerRegistryClient.d.ts +1 -1
- package/build/server/app/renderer/providerRegistryClient.d.ts.map +1 -1
- package/build/server/app/renderer/providerRegistryClient.js +23 -41
- package/build/server/app/renderer/providerRegistryClient.js.map +1 -1
- package/build/server/app/server/appPackageRoutes.d.ts +2 -0
- package/build/server/app/server/appPackageRoutes.d.ts.map +1 -1
- package/build/server/app/server/appPackageRoutes.js +105 -0
- package/build/server/app/server/appPackageRoutes.js.map +1 -1
- package/build/server/app/server/authGatePolicy.js +7 -1
- package/build/server/app/server/authGatePolicy.js.map +1 -1
- package/build/server/app/server/contracts.d.ts +15 -0
- package/build/server/app/server/contracts.d.ts.map +1 -1
- package/build/server/app/server/dependencies.d.ts.map +1 -1
- package/build/server/app/server/dependencies.js +42 -1
- package/build/server/app/server/dependencies.js.map +1 -1
- package/build/server/app/server/goldenPathStartupResume.d.ts +55 -0
- package/build/server/app/server/goldenPathStartupResume.d.ts.map +1 -0
- package/build/server/app/server/goldenPathStartupResume.js +109 -0
- package/build/server/app/server/goldenPathStartupResume.js.map +1 -0
- package/build/server/app/server/platformSetupRoutes.d.ts.map +1 -1
- package/build/server/app/server/platformSetupRoutes.js +1 -13
- package/build/server/app/server/platformSetupRoutes.js.map +1 -1
- package/build/server/app/server/polling.d.ts.map +1 -1
- package/build/server/app/server/polling.js +2 -0
- package/build/server/app/server/polling.js.map +1 -1
- package/build/server/app/server/requestRouter.d.ts.map +1 -1
- package/build/server/app/server/requestRouter.js +30 -0
- package/build/server/app/server/requestRouter.js.map +1 -1
- package/build/server/app/server/runtimeSurfaceProxy.d.ts.map +1 -1
- package/build/server/app/server/runtimeSurfaceProxy.js +4 -2
- package/build/server/app/server/runtimeSurfaceProxy.js.map +1 -1
- package/build/server/app/server/startupRecovery.d.ts.map +1 -1
- package/build/server/app/server/startupRecovery.js +5 -0
- package/build/server/app/server/startupRecovery.js.map +1 -1
- package/build/server/app/server/telegramCommandSurface.d.ts +29 -0
- package/build/server/app/server/telegramCommandSurface.d.ts.map +1 -0
- package/build/server/app/server/telegramCommandSurface.js +123 -0
- package/build/server/app/server/telegramCommandSurface.js.map +1 -0
- package/build/server/app/server/transportWorkGoldenPath.d.ts +82 -0
- package/build/server/app/server/transportWorkGoldenPath.d.ts.map +1 -0
- package/build/server/app/server/transportWorkGoldenPath.js +307 -0
- package/build/server/app/server/transportWorkGoldenPath.js.map +1 -0
- package/build/server/config.d.ts +21 -0
- package/build/server/config.d.ts.map +1 -1
- package/build/server/config.js +12 -0
- package/build/server/config.js.map +1 -1
- package/build/server/design/components/providerModelFieldsSupport.d.ts +3 -3
- package/build/server/design/components/providerModelFieldsSupport.d.ts.map +1 -1
- package/build/server/design/components/providerModelFieldsSupport.js +37 -38
- package/build/server/design/components/providerModelFieldsSupport.js.map +1 -1
- package/build/server/design/components/useProviderCatalogState.d.ts +1 -0
- package/build/server/design/components/useProviderCatalogState.d.ts.map +1 -1
- package/build/server/design/components/useProviderCatalogState.js +1 -0
- package/build/server/design/components/useProviderCatalogState.js.map +1 -1
- package/build/server/design/components/useProviderRegistryAutoRecheck.d.ts.map +1 -1
- package/build/server/design/components/useProviderRegistryAutoRecheck.js +20 -13
- package/build/server/design/components/useProviderRegistryAutoRecheck.js.map +1 -1
- package/build/server/design/components/useProviderRegistryState.d.ts.map +1 -1
- package/build/server/design/components/useProviderRegistryState.js +12 -25
- package/build/server/design/components/useProviderRegistryState.js.map +1 -1
- package/build/server/design/components/useProviderTargetReconciliation.d.ts.map +1 -1
- package/build/server/design/components/useProviderTargetReconciliation.js +2 -1
- package/build/server/design/components/useProviderTargetReconciliation.js.map +1 -1
- package/build/server/index.js +4 -0
- package/build/server/index.js.map +1 -1
- package/build/server/platform/apps/packageInstaller.d.ts +19 -0
- package/build/server/platform/apps/packageInstaller.d.ts.map +1 -0
- package/build/server/platform/apps/packageInstaller.js +92 -0
- package/build/server/platform/apps/packageInstaller.js.map +1 -0
- package/build/server/platform/apps/registry.d.ts +6 -0
- package/build/server/platform/apps/registry.d.ts.map +1 -1
- package/build/server/platform/apps/registry.js +24 -0
- package/build/server/platform/apps/registry.js.map +1 -1
- package/build/server/platform/apps/renderer.d.ts +6 -0
- package/build/server/platform/apps/renderer.d.ts.map +1 -0
- package/build/server/platform/apps/renderer.js +18 -0
- package/build/server/platform/apps/renderer.js.map +1 -0
- package/build/server/platform/runtime/deliveryClient.d.ts +111 -0
- package/build/server/platform/runtime/deliveryClient.d.ts.map +1 -0
- package/build/server/platform/runtime/deliveryClient.js +289 -0
- package/build/server/platform/runtime/deliveryClient.js.map +1 -0
- package/build/server/platform/supervision/providerCapabilityBootstrapYaml.d.ts +1 -0
- package/build/server/platform/supervision/providerCapabilityBootstrapYaml.d.ts.map +1 -1
- package/build/server/platform/supervision/providerCapabilityBootstrapYaml.js +10 -0
- package/build/server/platform/supervision/providerCapabilityBootstrapYaml.js.map +1 -1
- package/build/server/platform/supervision/runtimeBoundary.d.ts +11 -1
- package/build/server/platform/supervision/runtimeBoundary.d.ts.map +1 -1
- package/build/server/platform/supervision/runtimeBoundary.js +2 -2
- package/build/server/platform/supervision/runtimeBoundary.js.map +1 -1
- package/build/server/platform/transports/telegram/bridge.d.ts +18 -0
- package/build/server/platform/transports/telegram/bridge.d.ts.map +1 -1
- package/build/server/platform/transports/telegram/bridge.js +176 -0
- package/build/server/platform/transports/telegram/bridge.js.map +1 -1
- package/build/server/platform/transports/telegram/commandPort.d.ts +40 -0
- package/build/server/platform/transports/telegram/commandPort.d.ts.map +1 -0
- package/build/server/platform/transports/telegram/commandPort.js +17 -0
- package/build/server/platform/transports/telegram/commandPort.js.map +1 -0
- package/build/server/platform/transports/telegram/commandRouter.d.ts +22 -0
- package/build/server/platform/transports/telegram/commandRouter.d.ts.map +1 -1
- package/build/server/platform/transports/telegram/commandRouter.js.map +1 -1
- package/build/server/platform/transports/telegram/commands/index.d.ts.map +1 -1
- package/build/server/platform/transports/telegram/commands/index.js +38 -0
- package/build/server/platform/transports/telegram/commands/index.js.map +1 -1
- package/build/server/platform/transports/telegram/ingressDispatch.d.ts +56 -0
- package/build/server/platform/transports/telegram/ingressDispatch.d.ts.map +1 -0
- package/build/server/platform/transports/telegram/ingressDispatch.js +93 -0
- package/build/server/platform/transports/telegram/ingressDispatch.js.map +1 -0
- package/build/server/platform/transports/telegram/polling.d.ts +34 -0
- package/build/server/platform/transports/telegram/polling.d.ts.map +1 -1
- package/build/server/platform/transports/telegram/polling.js +86 -9
- package/build/server/platform/transports/telegram/polling.js.map +1 -1
- package/build/server/platform/transports/telegram/relay/index.d.ts +3 -0
- package/build/server/platform/transports/telegram/relay/index.d.ts.map +1 -1
- package/build/server/platform/transports/telegram/relay/index.js +5 -1
- package/build/server/platform/transports/telegram/relay/index.js.map +1 -1
- package/build/server/platform/transports/telegram/relay/ingress.d.ts +2 -0
- package/build/server/platform/transports/telegram/relay/ingress.d.ts.map +1 -1
- package/build/server/platform/transports/telegram/relay/ingress.js +1 -1
- package/build/server/platform/transports/telegram/relay/ingress.js.map +1 -1
- package/build/server/platform/transports/work-delivery/actionTokens.d.ts +66 -0
- package/build/server/platform/transports/work-delivery/actionTokens.d.ts.map +1 -0
- package/build/server/platform/transports/work-delivery/actionTokens.js +145 -0
- package/build/server/platform/transports/work-delivery/actionTokens.js.map +1 -0
- package/build/server/platform/transports/work-delivery/contracts.d.ts +172 -0
- package/build/server/platform/transports/work-delivery/contracts.d.ts.map +1 -0
- package/build/server/platform/transports/work-delivery/contracts.js +26 -0
- package/build/server/platform/transports/work-delivery/contracts.js.map +1 -0
- package/build/server/platform/transports/work-delivery/deliveryGates.d.ts +32 -0
- package/build/server/platform/transports/work-delivery/deliveryGates.d.ts.map +1 -0
- package/build/server/platform/transports/work-delivery/deliveryGates.js +45 -0
- package/build/server/platform/transports/work-delivery/deliveryGates.js.map +1 -0
- package/build/server/platform/transports/work-delivery/inboundClassification.d.ts +31 -0
- package/build/server/platform/transports/work-delivery/inboundClassification.d.ts.map +1 -0
- package/build/server/platform/transports/work-delivery/inboundClassification.js +52 -0
- package/build/server/platform/transports/work-delivery/inboundClassification.js.map +1 -0
- package/build/server/platform/transports/work-delivery/outbox.d.ts +84 -0
- package/build/server/platform/transports/work-delivery/outbox.d.ts.map +1 -0
- package/build/server/platform/transports/work-delivery/outbox.js +270 -0
- package/build/server/platform/transports/work-delivery/outbox.js.map +1 -0
- package/build/server/platform/transports/work-delivery/permissionEnvelope.d.ts +57 -0
- package/build/server/platform/transports/work-delivery/permissionEnvelope.d.ts.map +1 -0
- package/build/server/platform/transports/work-delivery/permissionEnvelope.js +74 -0
- package/build/server/platform/transports/work-delivery/permissionEnvelope.js.map +1 -0
- package/build/server/platform/transports/work-delivery/port.d.ts +60 -0
- package/build/server/platform/transports/work-delivery/port.d.ts.map +1 -0
- package/build/server/platform/transports/work-delivery/port.js +15 -0
- package/build/server/platform/transports/work-delivery/port.js.map +1 -0
- package/build/server/platform/transports/work-delivery/proposal.d.ts +31 -0
- package/build/server/platform/transports/work-delivery/proposal.d.ts.map +1 -0
- package/build/server/platform/transports/work-delivery/proposal.js +59 -0
- package/build/server/platform/transports/work-delivery/proposal.js.map +1 -0
- package/build/server/platform/transports/work-delivery/readiness.d.ts +61 -0
- package/build/server/platform/transports/work-delivery/readiness.d.ts.map +1 -0
- package/build/server/platform/transports/work-delivery/readiness.js +123 -0
- package/build/server/platform/transports/work-delivery/readiness.js.map +1 -0
- package/build/server/platform/transports/work-delivery/stageProjection.d.ts +43 -0
- package/build/server/platform/transports/work-delivery/stageProjection.d.ts.map +1 -0
- package/build/server/platform/transports/work-delivery/stageProjection.js +132 -0
- package/build/server/platform/transports/work-delivery/stageProjection.js.map +1 -0
- package/build/server/platform/transports/work-delivery/stateStore.d.ts +21 -0
- package/build/server/platform/transports/work-delivery/stateStore.d.ts.map +1 -0
- package/build/server/platform/transports/work-delivery/stateStore.js +193 -0
- package/build/server/platform/transports/work-delivery/stateStore.js.map +1 -0
- package/build/server/platform/transports/work-delivery/telemetry.d.ts +49 -0
- package/build/server/platform/transports/work-delivery/telemetry.d.ts.map +1 -0
- package/build/server/platform/transports/work-delivery/telemetry.js +80 -0
- package/build/server/platform/transports/work-delivery/telemetry.js.map +1 -0
- package/build/server/products/chat/api/contracts.d.ts +10 -0
- package/build/server/products/chat/api/contracts.d.ts.map +1 -1
- package/build/server/products/chat/api/resources/channelRoutes.d.ts.map +1 -1
- package/build/server/products/chat/api/resources/channelRoutes.js +27 -1
- package/build/server/products/chat/api/resources/channelRoutes.js.map +1 -1
- package/build/server/products/chat/api/routeSupport.d.ts +8 -0
- package/build/server/products/chat/api/routeSupport.d.ts.map +1 -1
- package/build/server/products/chat/api/routeSupport.js +5 -4
- package/build/server/products/chat/api/routeSupport.js.map +1 -1
- package/build/server/products/chat/api/setupRoutes.d.ts.map +1 -1
- package/build/server/products/chat/api/setupRoutes.js +23 -8
- package/build/server/products/chat/api/setupRoutes.js.map +1 -1
- package/build/server/products/chat/state/model/channelExecutionTargets.d.ts +15 -0
- package/build/server/products/chat/state/model/channelExecutionTargets.d.ts.map +1 -1
- package/build/server/products/chat/state/model/channelExecutionTargets.js +25 -0
- package/build/server/products/chat/state/model/channelExecutionTargets.js.map +1 -1
- package/build/server/products/chat/state/model/index.d.ts +1 -1
- package/build/server/products/chat/state/model/index.d.ts.map +1 -1
- package/build/server/products/chat/state/model/index.js +1 -1
- package/build/server/products/chat/state/model/index.js.map +1 -1
- package/build/server/products/code/api/relayRoutes.d.ts.map +1 -1
- package/build/server/products/code/api/relayRoutes.js +36 -7
- package/build/server/products/code/api/relayRoutes.js.map +1 -1
- package/build/server/products/code/state/relayState.d.ts +2 -1
- package/build/server/products/code/state/relayState.d.ts.map +1 -1
- package/build/server/products/code/state/relayState.js +7 -7
- package/build/server/products/code/state/relayState.js.map +1 -1
- package/build/server/products/shared/api/workspaceContracts.d.ts +5 -0
- package/build/server/products/shared/api/workspaceContracts.d.ts.map +1 -1
- package/build/server/products/work/api/goldenPathProjection.d.ts +156 -0
- package/build/server/products/work/api/goldenPathProjection.d.ts.map +1 -0
- package/build/server/products/work/api/goldenPathProjection.js +252 -0
- package/build/server/products/work/api/goldenPathProjection.js.map +1 -0
- package/build/server/products/work/api/index.d.ts +54 -1
- package/build/server/products/work/api/index.d.ts.map +1 -1
- package/build/server/products/work/api/index.js +182 -4
- package/build/server/products/work/api/index.js.map +1 -1
- package/build/server/products/work/api/projection.d.ts +7 -1
- package/build/server/products/work/api/projection.d.ts.map +1 -1
- package/build/server/products/work/api/projection.js +7 -1
- package/build/server/products/work/api/projection.js.map +1 -1
- package/build/server/products/work/shared/apiPaths.d.ts +8 -0
- package/build/server/products/work/shared/apiPaths.d.ts.map +1 -1
- package/build/server/products/work/shared/apiPaths.js +8 -0
- package/build/server/products/work/shared/apiPaths.js.map +1 -1
- package/build/server/products/work/shared/workGoldenPathMessages.d.ts +83 -0
- package/build/server/products/work/shared/workGoldenPathMessages.d.ts.map +1 -0
- package/build/server/products/work/shared/workGoldenPathMessages.js +211 -0
- package/build/server/products/work/shared/workGoldenPathMessages.js.map +1 -0
- package/build/server/products/work/shared/workGoldenPathMetadata.d.ts +45 -0
- package/build/server/products/work/shared/workGoldenPathMetadata.d.ts.map +1 -0
- package/build/server/products/work/shared/workGoldenPathMetadata.js +122 -0
- package/build/server/products/work/shared/workGoldenPathMetadata.js.map +1 -0
- package/build/server/products/work/state/workCompletionEvidence.d.ts +42 -0
- package/build/server/products/work/state/workCompletionEvidence.d.ts.map +1 -0
- package/build/server/products/work/state/workCompletionEvidence.js +59 -0
- package/build/server/products/work/state/workCompletionEvidence.js.map +1 -0
- package/build/server/products/work/state/workExecutionTaskDelegate.d.ts +16 -0
- package/build/server/products/work/state/workExecutionTaskDelegate.d.ts.map +1 -1
- package/build/server/products/work/state/workExecutionTaskDelegate.js +91 -68
- package/build/server/products/work/state/workExecutionTaskDelegate.js.map +1 -1
- package/build/server/products/work/state/workGoldenPathAdmission.d.ts +78 -0
- package/build/server/products/work/state/workGoldenPathAdmission.d.ts.map +1 -0
- package/build/server/products/work/state/workGoldenPathAdmission.js +249 -0
- package/build/server/products/work/state/workGoldenPathAdmission.js.map +1 -0
- package/build/server/products/work/state/workGoldenPathDeliveryEvidence.d.ts +33 -0
- package/build/server/products/work/state/workGoldenPathDeliveryEvidence.d.ts.map +1 -0
- package/build/server/products/work/state/workGoldenPathDeliveryEvidence.js +161 -0
- package/build/server/products/work/state/workGoldenPathDeliveryEvidence.js.map +1 -0
- package/build/server/products/work/state/workGoldenPathIntake.d.ts +34 -0
- package/build/server/products/work/state/workGoldenPathIntake.d.ts.map +1 -0
- package/build/server/products/work/state/workGoldenPathIntake.js +50 -0
- package/build/server/products/work/state/workGoldenPathIntake.js.map +1 -0
- package/build/server/products/work/state/workGoldenPathLifecycle.d.ts +44 -0
- package/build/server/products/work/state/workGoldenPathLifecycle.d.ts.map +1 -0
- package/build/server/products/work/state/workGoldenPathLifecycle.js +146 -0
- package/build/server/products/work/state/workGoldenPathLifecycle.js.map +1 -0
- package/build/server/products/work/state/workGoldenPathPublish.d.ts +84 -0
- package/build/server/products/work/state/workGoldenPathPublish.d.ts.map +1 -0
- package/build/server/products/work/state/workGoldenPathPublish.js +488 -0
- package/build/server/products/work/state/workGoldenPathPublish.js.map +1 -0
- package/build/server/products/work/state/workGoldenPathRunner.d.ts +121 -0
- package/build/server/products/work/state/workGoldenPathRunner.d.ts.map +1 -0
- package/build/server/products/work/state/workGoldenPathRunner.js +447 -0
- package/build/server/products/work/state/workGoldenPathRunner.js.map +1 -0
- package/build/server/products/work/state/workGoldenPathRuntimeExecutor.d.ts +74 -0
- package/build/server/products/work/state/workGoldenPathRuntimeExecutor.d.ts.map +1 -0
- package/build/server/products/work/state/workGoldenPathRuntimeExecutor.js +239 -0
- package/build/server/products/work/state/workGoldenPathRuntimeExecutor.js.map +1 -0
- package/build/server/products/work/state/workGoldenPathService.d.ts +152 -0
- package/build/server/products/work/state/workGoldenPathService.d.ts.map +1 -0
- package/build/server/products/work/state/workGoldenPathService.js +1057 -0
- package/build/server/products/work/state/workGoldenPathService.js.map +1 -0
- package/build/server/products/work/state/workGoldenPathTelegramPort.d.ts +87 -0
- package/build/server/products/work/state/workGoldenPathTelegramPort.d.ts.map +1 -0
- package/build/server/products/work/state/workGoldenPathTelegramPort.js +220 -0
- package/build/server/products/work/state/workGoldenPathTelegramPort.js.map +1 -0
- package/build/server/runtime/client.d.ts +13 -0
- package/build/server/runtime/client.d.ts.map +1 -1
- package/build/server/runtime/client.js +39 -0
- package/build/server/runtime/client.js.map +1 -1
- package/build/server/runtime/setup.d.ts +10 -4
- package/build/server/runtime/setup.d.ts.map +1 -1
- package/build/server/runtime/setup.js +14 -18
- package/build/server/runtime/setup.js.map +1 -1
- package/build/server/runtime/usageSnapshot.d.ts +3 -0
- package/build/server/runtime/usageSnapshot.d.ts.map +1 -0
- package/build/server/runtime/usageSnapshot.js +69 -0
- package/build/server/runtime/usageSnapshot.js.map +1 -0
- package/build/server/server/routes/providerCapabilityBootstrap.d.ts +69 -0
- package/build/server/server/routes/providerCapabilityBootstrap.d.ts.map +1 -0
- package/build/server/server/routes/providerCapabilityBootstrap.js +165 -0
- package/build/server/server/routes/providerCapabilityBootstrap.js.map +1 -0
- package/build/server/server/routes/providers.d.ts.map +1 -1
- package/build/server/server/routes/providers.js +112 -81
- package/build/server/server/routes/providers.js.map +1 -1
- package/build/server/server/routes/telegram.d.ts +9 -0
- package/build/server/server/routes/telegram.d.ts.map +1 -1
- package/build/server/server/routes/telegram.js +79 -72
- package/build/server/server/routes/telegram.js.map +1 -1
- package/build/server/shared/catsAppManifest.d.ts +3 -1
- package/build/server/shared/catsAppManifest.d.ts.map +1 -1
- package/build/server/shared/catsAppManifest.js +2 -0
- package/build/server/shared/catsAppManifest.js.map +1 -1
- package/build/server/shared/executionLabel.d.ts.map +1 -1
- package/build/server/shared/executionLabel.js +8 -1
- package/build/server/shared/executionLabel.js.map +1 -1
- package/build/server/shared/i18n/catalogs/en.d.ts.map +1 -1
- package/build/server/shared/i18n/catalogs/en.js +198 -3
- package/build/server/shared/i18n/catalogs/en.js.map +1 -1
- package/build/server/shared/i18n/catalogs/zh-TW.d.ts.map +1 -1
- package/build/server/shared/i18n/catalogs/zh-TW.js +197 -3
- package/build/server/shared/i18n/catalogs/zh-TW.js.map +1 -1
- package/build/server/shared/i18n/index.d.ts +192 -0
- package/build/server/shared/i18n/index.d.ts.map +1 -1
- package/build/server/shared/i18n/messageKeys.d.ts +192 -0
- package/build/server/shared/i18n/messageKeys.d.ts.map +1 -1
- package/build/server/shared/i18n/messageKeys.js +192 -0
- package/build/server/shared/i18n/messageKeys.js.map +1 -1
- package/build/server/shared/platformSetupOperation.d.ts +2 -0
- package/build/server/shared/platformSetupOperation.d.ts.map +1 -0
- package/build/server/shared/platformSetupOperation.js +9 -0
- package/build/server/shared/platformSetupOperation.js.map +1 -0
- package/build/server/shared/providerCatalog.d.ts +5 -2
- package/build/server/shared/providerCatalog.d.ts.map +1 -1
- package/build/server/shared/providerCatalog.js +6 -0
- package/build/server/shared/providerCatalog.js.map +1 -1
- package/build/server/shared/providerCatalogData.d.ts +28 -22
- package/build/server/shared/providerCatalogData.d.ts.map +1 -1
- package/build/server/shared/providerCatalogData.js +22 -10
- package/build/server/shared/providerCatalogData.js.map +1 -1
- package/build/server/shared/providerCatalogInstances.d.ts.map +1 -1
- package/build/server/shared/providerCatalogInstances.js +3 -0
- package/build/server/shared/providerCatalogInstances.js.map +1 -1
- package/build/server/shared/providerModelLabelRegistry.d.ts +29 -0
- package/build/server/shared/providerModelLabelRegistry.d.ts.map +1 -0
- package/build/server/shared/providerModelLabelRegistry.js +49 -0
- package/build/server/shared/providerModelLabelRegistry.js.map +1 -0
- package/build/server/shared/providerSelection.d.ts.map +1 -1
- package/build/server/shared/providerSelection.js +10 -13
- package/build/server/shared/providerSelection.js.map +1 -1
- package/build/server/shared/runtimeSetup.d.ts +17 -4
- package/build/server/shared/runtimeSetup.d.ts.map +1 -1
- package/build/server/shared/runtimeStatusPresentation.js +1 -1
- package/build/server/shared/runtimeStatusPresentation.js.map +1 -1
- package/package.json +23 -1
- package/packages/app-sdk/browser.d.ts +51 -0
- package/packages/app-sdk/browser.js +48 -0
- package/packages/app-sdk/package.d.ts +14 -0
- package/packages/app-sdk/package.js +131 -0
- package/packages/app-sdk/package.json +7 -0
- package/scripts/README.md +43 -26
- package/scripts/build-desktop-installer.mjs +15 -0
- package/scripts/build-test-ui.mjs +1 -1
- package/scripts/bundle-server.mjs +23 -10
- package/scripts/linux/build-desktop-package.sh +6 -6
- package/scripts/linux/install-antigravity.sh +0 -0
- package/scripts/linux/install-devin.sh +0 -0
- package/scripts/linux/install-meta-cli.sh +8 -0
- package/scripts/linux/provider-cli-common.sh +103 -30
- package/scripts/linux/sync-agent-skills.sh +27 -5
- package/scripts/linux/test-linux-package-smoke.sh +4 -3
- package/scripts/linux/upgrade-cli-tools.sh +1 -1
- package/scripts/macos/build-desktop-package.sh +5 -5
- package/scripts/macos/install-antigravity.sh +0 -0
- package/scripts/macos/install-devin.sh +0 -0
- package/scripts/macos/install-meta-cli.sh +8 -0
- package/scripts/macos/provider-cli-common.sh +103 -30
- package/scripts/macos/sync-agent-skills.sh +27 -5
- package/scripts/macos/test-macos-package-smoke.sh +4 -3
- package/scripts/macos/upgrade-cli-tools.sh +1 -1
- package/scripts/package-desktop.mjs +15 -2
- package/scripts/testing/check-usage-app.mts +266 -0
- package/scripts/testing/usage-app-smoke-electron.cjs +10 -0
- package/scripts/testing/usage-app-smoke-renderer.tsx +8 -0
- package/scripts/verify-desktop-app-bundle.mjs +108 -0
- package/scripts/windows/Build-DesktopPackage.ps1 +9 -6
- package/scripts/windows/{Install-Aider.ps1 → Install-MetaCli.ps1} +180 -92
- package/scripts/windows/Install-Ollama.ps1 +4 -1
- package/scripts/windows/Sync-AgentSkills.ps1 +29 -6
- package/scripts/windows/Test-WindowsInstallerSmoke.ps1 +2 -1
- package/build/desktop/updateNotifications.d.ts +0 -64
- package/build/desktop/updateNotifications.d.ts.map +0 -1
- package/build/desktop/updateNotifications.js +0 -143
- package/build/desktop/updateNotifications.js.map +0 -1
- package/build/renderer/assets/App-BfOvMP2m.js +0 -1
- package/build/renderer/assets/App-DGwkRFZl.css +0 -1
- package/build/renderer/assets/App-DWd7I3Z2.js +0 -2
- package/build/renderer/assets/WorkspaceAppRoutes-CrbTA9En.js +0 -1
- package/build/renderer/assets/app-BTww3Hl4.js +0 -43
- package/build/renderer/assets/app-CPxWQwLA.css +0 -1
- package/build/renderer/assets/conversationSidebarRecentEntries-QuaOPxCb.js +0 -6
- package/scripts/linux/install-aider.sh +0 -8
- package/scripts/macos/install-aider.sh +0 -8
|
@@ -37,10 +37,11 @@ assert_file "${RESOURCES_ROOT}/app-sidecar/build/renderer/index.html" 'bundled c
|
|
|
37
37
|
assert_file "${RESOURCES_ROOT}/app-sidecar/package.json" 'bundled cats app package manifest'
|
|
38
38
|
assert_file "${RESOURCES_ROOT}/app-sidecar/node_modules/js-yaml/package.json" 'bundled cats app js-yaml dependency marker'
|
|
39
39
|
assert_file "${RESOURCES_ROOT}/app-sidecar/node_modules/argparse/package.json" 'bundled cats app argparse dependency marker'
|
|
40
|
+
assert_file "${RESOURCES_ROOT}/app-sidecar/config/provider-capability-bootstrap.yaml.example" 'bundled cats capability bootstrap example'
|
|
40
41
|
assert_file "${RESOURCES_ROOT}/cats-runtime/build/runtime/index.js" 'bundled cats-runtime entry'
|
|
41
42
|
assert_file "${RESOURCES_ROOT}/cats-runtime/package.json" 'bundled cats-runtime package manifest'
|
|
42
43
|
assert_file "${RESOURCES_ROOT}/cats-runtime/public/provider-setup.html" 'bundled cats-runtime setup UI'
|
|
43
|
-
assert_file "${RESOURCES_ROOT}/cats-runtime/skills/README.md" 'bundled cats-runtime skills catalog root'
|
|
44
|
+
assert_file "${RESOURCES_ROOT}/cats-runtime/runtime-skills/README.md" 'bundled cats-runtime skills catalog root'
|
|
44
45
|
assert_file "${RESOURCES_ROOT}/cats-runtime/config/management.yaml.example" 'bundled cats-runtime management config example'
|
|
45
46
|
assert_file "${RESOURCES_ROOT}/cats-runtime/config/providers.yaml.example" 'bundled cats-runtime provider config example'
|
|
46
47
|
assert_file "${RESOURCES_ROOT}/cats-runtime/config/curated-model-catalogs.yaml.example" 'bundled cats-runtime curated model catalog example'
|
|
@@ -53,7 +54,7 @@ assert_file "${RESOURCES_ROOT}/desktop/setup-assets/macos/install-antigravity.sh
|
|
|
53
54
|
assert_file "${RESOURCES_ROOT}/desktop/setup-assets/macos/install-grok.sh" 'bundled macOS Grok installer helper'
|
|
54
55
|
assert_file "${RESOURCES_ROOT}/desktop/setup-assets/macos/install-cline.sh" 'bundled macOS Cline installer helper'
|
|
55
56
|
assert_file "${RESOURCES_ROOT}/desktop/setup-assets/macos/install-devin.sh" 'bundled macOS Devin installer helper'
|
|
56
|
-
assert_file "${RESOURCES_ROOT}/desktop/setup-assets/macos/install-
|
|
57
|
+
assert_file "${RESOURCES_ROOT}/desktop/setup-assets/macos/install-meta-cli.sh" 'bundled macOS Meta Muse installer helper'
|
|
57
58
|
assert_file "${RESOURCES_ROOT}/desktop/setup-assets/macos/install-copilot.sh" 'bundled macOS GitHub Copilot installer helper'
|
|
58
59
|
assert_file "${RESOURCES_ROOT}/desktop/setup-assets/macos/install-opencode.sh" 'bundled macOS OpenCode installer helper'
|
|
59
60
|
assert_file "${RESOURCES_ROOT}/desktop/setup-assets/macos/install-kilo.sh" 'bundled macOS Kilo Code installer helper'
|
|
@@ -102,7 +103,7 @@ assert(macTarget.artifacts.some((artifact) => artifact.id === 'macos-antigravity
|
|
|
102
103
|
assert(macTarget.artifacts.some((artifact) => artifact.id === 'macos-grok-native-installer-script'), 'macOS target includes the bundled Grok installer asset');
|
|
103
104
|
assert(macTarget.artifacts.some((artifact) => artifact.id === 'macos-cline-native-installer-script'), 'macOS target includes the bundled Cline installer asset');
|
|
104
105
|
assert(macTarget.artifacts.some((artifact) => artifact.id === 'macos-devin-native-installer-script'), 'macOS target includes the bundled Devin installer asset');
|
|
105
|
-
assert(macTarget.artifacts.some((artifact) => artifact.id === 'macos-
|
|
106
|
+
assert(macTarget.artifacts.some((artifact) => artifact.id === 'macos-muse-native-installer-script'), 'macOS target includes the bundled Meta Muse installer asset');
|
|
106
107
|
assert(macTarget.artifacts.some((artifact) => artifact.id === 'macos-setup-readiness-audit-script'), 'macOS target includes the bundled readiness audit asset');
|
|
107
108
|
assert(macTarget.artifacts.some((artifact) => artifact.id === 'macos-provider-cli-common-support-script'), 'macOS target includes the macOS provider helper asset');
|
|
108
109
|
assert(macTarget.artifacts.some((artifact) => artifact.id === 'macos-node-cli-common-support-script'), 'macOS target includes the macOS npm helper asset');
|
|
@@ -35,7 +35,7 @@ while [ $# -gt 0 ]; do
|
|
|
35
35
|
shift
|
|
36
36
|
done
|
|
37
37
|
|
|
38
|
-
for script_name in install-claude-code.sh install-antigravity.sh install-cursor-agent.sh install-devin.sh install-
|
|
38
|
+
for script_name in install-claude-code.sh install-antigravity.sh install-cursor-agent.sh install-devin.sh install-meta-cli.sh install-goose.sh install-junie.sh install-kiro-cli.sh install-grok.sh; do
|
|
39
39
|
"$SCRIPT_DIR/$script_name" -Upgrade
|
|
40
40
|
done
|
|
41
41
|
|
|
@@ -4,6 +4,7 @@ import process from 'node:process';
|
|
|
4
4
|
import { access, readFile } from 'node:fs/promises';
|
|
5
5
|
import { resolve } from 'node:path';
|
|
6
6
|
import { fileURLToPath } from 'node:url';
|
|
7
|
+
import { resolveAppLock } from '#cats-app-package';
|
|
7
8
|
|
|
8
9
|
const SCRIPT_PATH = fileURLToPath(import.meta.url);
|
|
9
10
|
const PROJECT_ROOT = resolve(fileURLToPath(new URL('..', import.meta.url)));
|
|
@@ -36,6 +37,7 @@ Options:
|
|
|
36
37
|
--platform <all|windows|macos|linux> Filter staged target manifests
|
|
37
38
|
--output-dir <path> Override packaging output root
|
|
38
39
|
--sidecar-layout <split|bundle> Choose loose-file or bundled sidecars for both app/runtime
|
|
40
|
+
--apps-lock <path> Exact App ID/version/SHA-256 selection (no latest resolution)
|
|
39
41
|
--help Show this help text
|
|
40
42
|
`);
|
|
41
43
|
}
|
|
@@ -54,17 +56,23 @@ export function parseArgs(argv, env = process.env) {
|
|
|
54
56
|
let platform = 'all';
|
|
55
57
|
let outputDir = null;
|
|
56
58
|
let sidecarLayout = resolveSidecarLayout(env.CATS_DESKTOP_SIDECAR_LAYOUT);
|
|
59
|
+
let appsLock = env.CATS_DESKTOP_APPS_LOCK?.trim() || null;
|
|
57
60
|
|
|
58
61
|
for (let index = 0; index < argv.length; index += 1) {
|
|
59
62
|
const value = argv[index];
|
|
60
63
|
if (value === '--help' || value === '-h') {
|
|
61
|
-
return { help: true, platform, outputDir, sidecarLayout };
|
|
64
|
+
return { help: true, platform, outputDir, sidecarLayout, ...(appsLock ? { appsLock } : {}) };
|
|
62
65
|
}
|
|
63
66
|
if (value === '--platform') {
|
|
64
67
|
platform = argv[index + 1] ?? 'all';
|
|
65
68
|
index += 1;
|
|
66
69
|
continue;
|
|
67
70
|
}
|
|
71
|
+
if (value === '--apps-lock') {
|
|
72
|
+
appsLock = argv[++index];
|
|
73
|
+
if (!appsLock || appsLock.startsWith('--')) throw new Error('--apps-lock requires a path.');
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
68
76
|
if (value === '--output-dir') {
|
|
69
77
|
outputDir = argv[index + 1] ?? null;
|
|
70
78
|
index += 1;
|
|
@@ -78,7 +86,7 @@ export function parseArgs(argv, env = process.env) {
|
|
|
78
86
|
throw new Error(`Unknown option: ${value}`);
|
|
79
87
|
}
|
|
80
88
|
|
|
81
|
-
return { help: false, platform, outputDir, sidecarLayout };
|
|
89
|
+
return { help: false, platform, outputDir, sidecarLayout, ...(appsLock ? { appsLock } : {}) };
|
|
82
90
|
}
|
|
83
91
|
|
|
84
92
|
export function resolveRequiredDesktopIconPaths(projectRoot = PROJECT_ROOT) {
|
|
@@ -176,6 +184,9 @@ async function main() {
|
|
|
176
184
|
const { resolveDesktopHostConfig } = await import('../build/desktop/config.js');
|
|
177
185
|
const { stageDesktopPackagingOutputs } = await import('../build/desktop/packaging.js');
|
|
178
186
|
|
|
187
|
+
const apps = parsed.appsLock ? await resolveAppLock(resolve(parsed.appsLock)) : [];
|
|
188
|
+
if (!parsed.appsLock) process.stderr.write('[desktop-package] No --apps-lock selected; this package contains no optional Apps.\n');
|
|
189
|
+
|
|
179
190
|
await assertDesktopIconAssetsPresent(PROJECT_ROOT);
|
|
180
191
|
const config = resolveDesktopHostConfig({
|
|
181
192
|
env: process.env,
|
|
@@ -185,10 +196,12 @@ async function main() {
|
|
|
185
196
|
outputRoot: parsed.outputDir ? resolve(PROJECT_ROOT, parsed.outputDir) : undefined,
|
|
186
197
|
platforms: allowedPlatforms,
|
|
187
198
|
sidecarLayout: parsed.sidecarLayout,
|
|
199
|
+
apps,
|
|
188
200
|
});
|
|
189
201
|
|
|
190
202
|
process.stdout.write(JSON.stringify({
|
|
191
203
|
outputRoot: plan.outputRoot,
|
|
204
|
+
apps: plan.apps,
|
|
192
205
|
sidecarLayout: plan.sidecarLayout,
|
|
193
206
|
targets: plan.targets.map((target) => ({
|
|
194
207
|
id: target.id,
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Integration-only: built App archive + real host surface/route + fixture runtime.
|
|
3
|
+
// Usage: node --import tsx scripts/testing/check-usage-app.mts --apps-lock <path>
|
|
4
|
+
// Requires CATS_TEST_PLAYWRIGHT_MODULE (absolute module file) and CATS_TEST_BROWSER_EXECUTABLE.
|
|
5
|
+
import assert from 'node:assert/strict';
|
|
6
|
+
import { createServer } from 'node:http';
|
|
7
|
+
import { mkdtemp, mkdir, readFile } from 'node:fs/promises';
|
|
8
|
+
import { tmpdir } from 'node:os';
|
|
9
|
+
import path from 'node:path';
|
|
10
|
+
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
11
|
+
import { build } from 'esbuild';
|
|
12
|
+
import { resolveAppLock } from '#cats-app-package';
|
|
13
|
+
import { installRendererPackage } from '../../src/platform/apps/packageInstaller.js';
|
|
14
|
+
import { FileCatsAppRegistry } from '../../src/platform/apps/registry.js';
|
|
15
|
+
import { resolveCatsAppStoragePathsFromChatState } from '../../src/platform/apps/paths.js';
|
|
16
|
+
import { projectUsageSnapshot, projectUsageQuotaRefresh } from '../../src/runtime/usageSnapshot.js';
|
|
17
|
+
import { toPlatformInstalledAppDescriptor } from '../../src/platform/apps/envelope.js';
|
|
18
|
+
import { routeRequest } from '../../src/app/server/requestRouter.js';
|
|
19
|
+
import type { ResolvedServerDependencies } from '../../src/app/server/contracts.js';
|
|
20
|
+
import { loadConfig } from '../../src/config.js';
|
|
21
|
+
import { createDefaultCoreState } from '../../src/core/model/index.js';
|
|
22
|
+
import { MemoryCoreStore } from '../../src/core/store.js';
|
|
23
|
+
import { createEmptyPlatformAuthState, createFirstAdminLocalAuthState, MemoryPlatformAuthStore } from '../../src/platform/auth/index.js';
|
|
24
|
+
|
|
25
|
+
const args = process.argv.slice(2);
|
|
26
|
+
if (args.includes('--help')) {
|
|
27
|
+
process.stdout.write('Usage: node --import tsx scripts/testing/check-usage-app.mts --apps-lock <path> [--renderer-root <built renderer directory>] [--electron] [--check-loading-recovery]\nRequires CATS_TEST_PLAYWRIGHT_MODULE and CATS_TEST_BROWSER_EXECUTABLE; no real user state is read.\n');
|
|
28
|
+
process.exit(0);
|
|
29
|
+
}
|
|
30
|
+
const lockPath = args[args.indexOf('--apps-lock') + 1];
|
|
31
|
+
const rendererRoot = args.includes('--renderer-root') ? path.resolve(args[args.indexOf('--renderer-root') + 1]!) : null;
|
|
32
|
+
if (args.includes('--electron') && args.includes('--check-loading-recovery')) {
|
|
33
|
+
throw new Error('Loading fault injection requires Chromium/Edge. Run Electron functional checks without --check-loading-recovery.');
|
|
34
|
+
}
|
|
35
|
+
if (args.indexOf('--apps-lock') < 0 || !lockPath || !process.env.CATS_TEST_PLAYWRIGHT_MODULE || !process.env.CATS_TEST_BROWSER_EXECUTABLE) throw new Error('App lock and isolated browser test inputs are required.');
|
|
36
|
+
const root = await mkdtemp(path.join(tmpdir(), 'cats-usage-browser-'));
|
|
37
|
+
const chatStatePath = path.join(root, 'state', 'chat-state.local.json');
|
|
38
|
+
const apps = await resolveAppLock(path.resolve(lockPath));
|
|
39
|
+
const usage = apps.find((app) => app.id === 'cats.usage');
|
|
40
|
+
if (!usage) throw new Error('The selected lock must contain a built Usage package.');
|
|
41
|
+
const entryPath = rendererRoot ? '/apps/cats.usage' : `/?appVersion=${encodeURIComponent(usage.version)}`;
|
|
42
|
+
await installRendererPackage({ chatStatePath, bytes: usage.bytes, pin: usage, source: 'local-package', enable: true });
|
|
43
|
+
const registry = new FileCatsAppRegistry({ registryPath: resolveCatsAppStoragePathsFromChatState(chatStatePath).registryPath });
|
|
44
|
+
const bundle = rendererRoot ? null : await build({ entryPoints: [fileURLToPath(new URL('./usage-app-smoke-renderer.tsx', import.meta.url))], bundle: true,
|
|
45
|
+
format: 'esm', platform: 'browser', write: false, jsx: 'automatic', define: { 'process.env.NODE_ENV': '"production"' } });
|
|
46
|
+
const js = bundle?.outputFiles[0]!.contents;
|
|
47
|
+
const installed = (await registry.getInstalledApp(usage.id))!;
|
|
48
|
+
const hostEnvelope = {
|
|
49
|
+
app: { name: 'cats-platform', stage: 'phase-2-shell', runtimeBoundary: 'cats-runtime' },
|
|
50
|
+
products: [], installedApps: [toPlatformInstalledAppDescriptor(installed)],
|
|
51
|
+
desktop: { startAtLogin: false, openWindowOnStartup: true, systemTrayEnabled: true,
|
|
52
|
+
mobilePairing: { enabled: false, transport: 'tailscale', installId: null, displayName: null } },
|
|
53
|
+
language: { uiLanguagePreference: 'zh-TW' },
|
|
54
|
+
lobby: { animationMode: 'reduced', cats: [] },
|
|
55
|
+
runtime: { baseUrl: 'http://127.0.0.1', reachable: true, status: 'ok', service: 'cats-runtime' },
|
|
56
|
+
runtimeSetup: { source: 'runtime', bootstrapRequired: false, status: 'ready', stateStatus: 'ready', summary: 'Ready',
|
|
57
|
+
scannedAt: null, lastManualScanAt: null, appliedAt: null, providerCount: 0, availableCount: 0,
|
|
58
|
+
providersReadyToApply: [], providersNeedingAttention: [], suggestedProviders: [], canRunManualScan: true, canApply: false, error: null },
|
|
59
|
+
metadata: { generatedAt: new Date().toISOString(), host: '127.0.0.1', port: 0 },
|
|
60
|
+
bootstrapAttemptId: null, scopeId: 'isolated-usage-smoke', setupCompleteAt: new Date().toISOString(),
|
|
61
|
+
ownerDisplayName: 'Test', ownerAvatarColor: null, ownerAvatarUrl: null, lastProductSurface: null, guideCat: null,
|
|
62
|
+
};
|
|
63
|
+
let offline = false; let epoch = 'fixture-epoch'; let stale = false; let reads = 0;
|
|
64
|
+
const queries: string[] = [];
|
|
65
|
+
const timestamp = () => new Date().toISOString();
|
|
66
|
+
const totals = (totalTokens: number | null, currency = 'USD') => ({ observations: totalTokens === null ? 0 : 1,
|
|
67
|
+
inputTokens: totalTokens === null ? null : Math.floor(totalTokens * 0.8), outputTokens: totalTokens === null ? null : Math.ceil(totalTokens * 0.2),
|
|
68
|
+
totalTokens, costs: totalTokens === null ? [] : [{ currency, amount: 0.12, observations: 1 }],
|
|
69
|
+
confidence: { reported: totalTokens === null ? 0 : 1, aggregated: 0, estimated: 0, unknown: 0 }, lastObservedAt: timestamp() });
|
|
70
|
+
const runtimeClient = { async getUsageSnapshot() {
|
|
71
|
+
reads++; if (offline) throw new Error('Fixture offline');
|
|
72
|
+
const observedAt = new Date(Date.now() - (stale ? 600_000 : 30_000)).toISOString();
|
|
73
|
+
const resetsAt = new Date(Date.now() + (stale ? -60_000 : 3_600_000)).toISOString();
|
|
74
|
+
const targets = ['claude', 'codex', 'copilot', 'antigravity', 'kiro'].map((provider, index) => {
|
|
75
|
+
const queried = queries.includes(provider);
|
|
76
|
+
const source = queried ? { claude: 'claude.get_usage', codex: 'codex.account/rateLimits/read',
|
|
77
|
+
copilot: 'copilot.account.getQuota', antigravity: 'antigravity.usage' }[provider]
|
|
78
|
+
: index === 0 ? 'claude.rate_limit_event' : index === 1 ? 'codex.account/rateLimits/updated' : null;
|
|
79
|
+
const windows = queried && provider === 'copilot' ? [
|
|
80
|
+
{ id: 'premium_interactions', unit: 'requests', used: 0, limit: 1500, remaining: 1500, usedPercent: 0, resetsAt },
|
|
81
|
+
{ id: 'chat', unit: 'requests', used: 0, unlimited: true, resetsAt },
|
|
82
|
+
] : queried ? [{ id: provider === 'antigravity' ? 'gemini_models_weekly' : 'seven_day', unit: 'percent',
|
|
83
|
+
usedPercent: provider === 'claude' ? 6 : 22, windowMinutes: 10080, resetsAt }]
|
|
84
|
+
: index < 2 ? [{ id: index ? 'primary' : 'five_hour', unit: 'percent', usedPercent: index ? 60 : 25, resetsAt, windowMinutes: 300 }] : [];
|
|
85
|
+
return { provider, instance: 'default', backend: 'cli', usage: totals(index >= 2 ? null : 12500 + index * 1000, index ? 'EUR' : 'USD'), guardrails: [],
|
|
86
|
+
quota: { status: index === 4 ? 'unsupported' : windows.length ? 'available' : 'unavailable', freshness: stale ? 'stale' : 'fresh',
|
|
87
|
+
source, observedAt: windows.length ? observedAt : null, accountId: null, accountLinkage: 'unverified',
|
|
88
|
+
automaticRefresh: false, refreshSupported: index < 4, windows } };
|
|
89
|
+
});
|
|
90
|
+
return { schemaVersion: 1, generatedAt: timestamp(), runtime: { status: 'available', epoch },
|
|
91
|
+
coverage: { mode: 'memory', scope: 'runtime_observed_results', startedAt: observedAt, retainedRecords: 2, droppedRecords: 0, droppedQuotaTargets: 0, truncated: false, historyAvailable: false },
|
|
92
|
+
totals: { ...totals(26000), costs: [{ currency: 'USD', amount: 0.12 }, { currency: 'EUR', amount: 0.12 }] }, targets,
|
|
93
|
+
sessions: targets.slice(0, 2).map((target, index) => ({ ...target, sessionId: `fixture-session-${index + 1}` })), incidents: [], guardrails: [] };
|
|
94
|
+
}, async refreshUsageQuota(target: { provider: string; instance: string }) {
|
|
95
|
+
assert.equal(target.instance, 'default'); assert.ok(['codex', 'copilot', 'claude', 'antigravity'].includes(target.provider));
|
|
96
|
+
queries.push(target.provider);
|
|
97
|
+
return { status: 'updated', nextRefreshAt: null, snapshot: await this.getUsageSnapshot() };
|
|
98
|
+
} };
|
|
99
|
+
const sessionSecret = 'isolated-usage-smoke-session-secret';
|
|
100
|
+
const auth = await createFirstAdminLocalAuthState({ state: createEmptyPlatformAuthState(), displayName: 'Test',
|
|
101
|
+
identifier: 'test@example.test', password: 'isolated-fixture-password', sessionSecret, sessionTtlMs: 600_000 });
|
|
102
|
+
const core = createDefaultCoreState(); core.setupCompleteAt = new Date().toISOString();
|
|
103
|
+
const dependencies = { shared: {
|
|
104
|
+
config: loadConfig({ CATS_HOME_DIR: root, CATS_PLATFORM_DIR: root, CATS_CHAT_STATE_PATH: chatStatePath,
|
|
105
|
+
CATS_AUTH_SESSION_SECRET: sessionSecret }),
|
|
106
|
+
coreStore: new MemoryCoreStore(core), authStore: new MemoryPlatformAuthStore(auth.state),
|
|
107
|
+
runtimeClient: { getUsageSnapshot: async () => projectUsageSnapshot(await runtimeClient.getUsageSnapshot()),
|
|
108
|
+
refreshUsageQuota: async (target: { provider: string; instance: string }) => projectUsageQuotaRefresh(await runtimeClient.refreshUsageQuota(target)) },
|
|
109
|
+
}, chat: {}, work: {}, code: {} } as unknown as ResolvedServerDependencies;
|
|
110
|
+
// Use the same temp path as the package installer regardless of config environment aliases.
|
|
111
|
+
dependencies.shared.config.chatStatePath = chatStatePath;
|
|
112
|
+
const server = createServer(async (request, response) => {
|
|
113
|
+
try {
|
|
114
|
+
const url = new URL(request.url ?? '/', 'http://127.0.0.1');
|
|
115
|
+
if (rendererRoot && url.pathname === '/api/app-shell') {
|
|
116
|
+
response.writeHead(200, { 'content-type': 'application/json' }); response.end(JSON.stringify(hostEnvelope)); return;
|
|
117
|
+
}
|
|
118
|
+
if (url.pathname === '/smoke.js') { response.writeHead(200, { 'content-type': 'text/javascript' }); response.end(js); return; }
|
|
119
|
+
if (url.pathname.startsWith('/api/')) {
|
|
120
|
+
if (url.pathname.startsWith('/api/apps/') || url.pathname === '/api/auth/status') { await routeRequest(request, response, dependencies); return; }
|
|
121
|
+
response.writeHead(404); response.end(); return;
|
|
122
|
+
}
|
|
123
|
+
if (rendererRoot) {
|
|
124
|
+
const asset = url.pathname.startsWith('/assets/') ? url.pathname.slice(1) : 'index.html';
|
|
125
|
+
const assetPath = path.resolve(rendererRoot, asset);
|
|
126
|
+
if (!assetPath.startsWith(`${rendererRoot}${path.sep}`)) { response.writeHead(404); response.end(); return; }
|
|
127
|
+
const contentType = asset.endsWith('.js') ? 'text/javascript' : asset.endsWith('.css') ? 'text/css' : 'text/html';
|
|
128
|
+
response.writeHead(200, { 'content-type': contentType, 'cache-control': 'no-store' });
|
|
129
|
+
response.end(await readFile(assetPath)); return;
|
|
130
|
+
}
|
|
131
|
+
response.writeHead(200, { 'content-type': 'text/html', 'cache-control': 'no-store' });
|
|
132
|
+
response.end('<!doctype html><html><head><meta name="viewport" content="width=device-width, initial-scale=1"></head><body style="margin:0;background:#f4f5f2"><div id="root"></div><script type="module" src="/smoke.js"></script></body></html>');
|
|
133
|
+
} catch { response.writeHead(500); response.end('Fixture failure'); }
|
|
134
|
+
});
|
|
135
|
+
await new Promise<void>((resolve) => server.listen(0, '127.0.0.1', resolve));
|
|
136
|
+
const address = server.address();
|
|
137
|
+
if (!address || typeof address === 'string') throw new Error('No fixture port');
|
|
138
|
+
const { chromium, _electron } = await import(pathToFileURL(process.env.CATS_TEST_PLAYWRIGHT_MODULE).href);
|
|
139
|
+
const electronMode = args.includes('--electron');
|
|
140
|
+
await mkdir(path.join(root, 'electron-profile'), { recursive: true });
|
|
141
|
+
const browser = electronMode
|
|
142
|
+
? await _electron.launch({ executablePath: process.env.CATS_TEST_BROWSER_EXECUTABLE,
|
|
143
|
+
env: { ...process.env, CATS_USAGE_SMOKE_PROFILE_DIR: path.join(root, 'electron-profile') },
|
|
144
|
+
args: [fileURLToPath(new URL('./usage-app-smoke-electron.cjs', import.meta.url))] })
|
|
145
|
+
: await chromium.launch({ executablePath: process.env.CATS_TEST_BROWSER_EXECUTABLE, headless: true });
|
|
146
|
+
try {
|
|
147
|
+
const page = electronMode ? await browser.firstWindow()
|
|
148
|
+
: await browser.newPage({ viewport: { width: 1440, height: 1200 }, locale: 'zh-TW' });
|
|
149
|
+
await page.context().addCookies([{ name: 'cats_session', value: auth.session.token, url: `http://127.0.0.1:${address.port}` }]);
|
|
150
|
+
const errors: string[] = []; page.on('pageerror', (error: Error) => errors.push(error.message));
|
|
151
|
+
await page.goto(`http://127.0.0.1:${address.port}${entryPath}`);
|
|
152
|
+
const frame = page.frameLocator('iframe[title="Usage"]');
|
|
153
|
+
try { await frame.getByText('75% 剩餘', { exact: true }).waitFor({ timeout: 15_000 }); }
|
|
154
|
+
catch (error) {
|
|
155
|
+
process.stderr.write(`${JSON.stringify({ errors, body: await page.locator('body').innerText(), secure: await page.evaluate(() => isSecureContext) })}\n`);
|
|
156
|
+
throw error;
|
|
157
|
+
}
|
|
158
|
+
assert.equal(await page.locator('iframe').getAttribute('sandbox'), 'allow-scripts');
|
|
159
|
+
process.stdout.write('Usage iframe rendered and received the fixture snapshot.\n');
|
|
160
|
+
assert.equal(await frame.getByText('尚未支援', { exact: true }).count(), 1);
|
|
161
|
+
assert.equal(queries.length, 0, 'Opening the App never queries a CLI');
|
|
162
|
+
assert.equal(await frame.locator('[data-query-provider="kiro"]').count(), 0);
|
|
163
|
+
for (const provider of ['copilot', 'claude', 'antigravity']) {
|
|
164
|
+
await new Promise((resolve) => setTimeout(resolve, 1100));
|
|
165
|
+
await frame.locator(`[data-query-provider="${provider}"]`).click();
|
|
166
|
+
try { await frame.getByText(/已透過 .* CLI 取得額度回報/).first().waitFor({ timeout: 5000 }); }
|
|
167
|
+
catch (error) {
|
|
168
|
+
process.stderr.write(`${JSON.stringify({ queries, provider, body: await page.locator('body').innerText(),
|
|
169
|
+
frame: await frame.locator('body').innerText({ timeout: 1000 }).catch(() => 'Frame unavailable'), errors })}\n`);
|
|
170
|
+
throw error;
|
|
171
|
+
}
|
|
172
|
+
const expected = provider === 'copilot' ? /1,500 requests/ : provider === 'claude' ? /^94% 剩餘$/ : /^78% 剩餘$/;
|
|
173
|
+
await frame.getByText(expected).first().waitFor();
|
|
174
|
+
}
|
|
175
|
+
assert.deepEqual(queries, ['copilot', 'claude', 'antigravity']);
|
|
176
|
+
await frame.getByText('不限額', { exact: true }).waitFor();
|
|
177
|
+
assert.equal(await frame.locator('.stat .cost').innerText(), 'USD 0.12\nEUR 0.12');
|
|
178
|
+
const innerFrame = page.frames().find((candidate: { parentFrame(): unknown }) => candidate.parentFrame() !== null);
|
|
179
|
+
assert.ok(innerFrame);
|
|
180
|
+
await innerFrame.evaluate(() => new Promise((resolve) => requestAnimationFrame(() => requestAnimationFrame(resolve))));
|
|
181
|
+
const frameBounds = await page.locator('iframe').boundingBox();
|
|
182
|
+
assert.ok(frameBounds && frameBounds.width >= 800 && frameBounds.height >= 520, 'Dashboard has a usable desktop viewport');
|
|
183
|
+
const screenshotDir = path.resolve('build', 'usage-smoke'); await mkdir(screenshotDir, { recursive: true });
|
|
184
|
+
if (!electronMode) {
|
|
185
|
+
// Viewport/frame captures keep the opaque iframe's paint surface intact.
|
|
186
|
+
// Chromium full-page resizing can mispaint that surface even with correct DOM bounds.
|
|
187
|
+
await page.screenshot({ path: path.join(screenshotDir, 'usage-desktop.png') });
|
|
188
|
+
await page.locator('iframe').screenshot({ path: path.join(screenshotDir, 'usage-frame.png') });
|
|
189
|
+
}
|
|
190
|
+
await frame.locator('#provider').selectOption('copilot');
|
|
191
|
+
assert.equal(await frame.locator('.stat').first().locator('strong').innerText(), '—');
|
|
192
|
+
await frame.locator('#provider').selectOption('claude');
|
|
193
|
+
assert.equal(await frame.locator('.provider').count(), 1);
|
|
194
|
+
assert.equal(await frame.locator('tbody tr').count(), 1);
|
|
195
|
+
await frame.locator('#provider').selectOption('');
|
|
196
|
+
const refresh = async () => {
|
|
197
|
+
// The real host deliberately permits at most one UI request per second.
|
|
198
|
+
await new Promise((resolve) => setTimeout(resolve, 1100));
|
|
199
|
+
const before = reads;
|
|
200
|
+
await frame.getByRole('button', { name: '重新整理', exact: true }).click();
|
|
201
|
+
await page.waitForFunction(() => document.querySelector('iframe') !== null);
|
|
202
|
+
for (let attempt = 0; reads === before && attempt < 30; attempt++) await new Promise((resolve) => setTimeout(resolve, 50));
|
|
203
|
+
assert.ok(reads > before, 'Refresh reached the real host route');
|
|
204
|
+
};
|
|
205
|
+
offline = true; await refresh();
|
|
206
|
+
await frame.getByText('Runtime 無法連線 · 以下保留最後快照', { exact: true }).waitFor();
|
|
207
|
+
assert.equal(await frame.getByText('94% 剩餘', { exact: true }).count(), 1);
|
|
208
|
+
offline = false; stale = true; await refresh();
|
|
209
|
+
await frame.getByText('已過回報的重設時間;目前沒有可靠的未來重設時間', { exact: true }).first().waitFor();
|
|
210
|
+
assert.equal(await frame.getByText('94% 剩餘', { exact: true }).count(), 1);
|
|
211
|
+
epoch = 'fixture-restarted'; await refresh();
|
|
212
|
+
await frame.getByText('Runtime 已重新啟動,本次用量觀測區間已重設。', { exact: true }).waitFor();
|
|
213
|
+
await page.setViewportSize({ width: 390, height: 844 });
|
|
214
|
+
if (!electronMode) await page.screenshot({ path: path.join(screenshotDir, 'usage-mobile.png'), fullPage: true });
|
|
215
|
+
assert.equal(await innerFrame.evaluate(() => document.documentElement.scrollWidth <= window.innerWidth), true);
|
|
216
|
+
assert.equal(await innerFrame.evaluate(() => { try { return !!parent.document.body; } catch { return false; } }), false);
|
|
217
|
+
assert.equal(await innerFrame.evaluate(async () => { try { await fetch('/api/apps'); return true; } catch { return false; } }), false);
|
|
218
|
+
await registry.updateAppState('cats.usage', { installState: 'disabled' });
|
|
219
|
+
await new Promise((resolve) => setTimeout(resolve, 1100));
|
|
220
|
+
await frame.getByRole('button', { name: '重新整理', exact: true }).click();
|
|
221
|
+
await page.getByRole('alert').waitFor();
|
|
222
|
+
assert.equal(await page.locator('iframe').count(), 0);
|
|
223
|
+
await registry.updateAppState('cats.usage', { installState: 'enabled' });
|
|
224
|
+
offline = false; stale = false;
|
|
225
|
+
if (rendererRoot) {
|
|
226
|
+
await page.getByRole('button', { name: '返回大廳', exact: true }).click();
|
|
227
|
+
await page.getByRole('button', { name: /Usage/ }).click();
|
|
228
|
+
await page.frameLocator('iframe[title="Usage"]').getByText('94% 剩餘', { exact: true }).waitFor();
|
|
229
|
+
}
|
|
230
|
+
if (args.includes('--check-loading-recovery')) {
|
|
231
|
+
await page.clock.install();
|
|
232
|
+
const rendererPattern = '**/api/apps/cats.usage/renderer?*';
|
|
233
|
+
let releaseRequest!: () => void;
|
|
234
|
+
await page.route(rendererPattern, async (route: any) => {
|
|
235
|
+
await new Promise<void>((resolve) => { releaseRequest = resolve; });
|
|
236
|
+
await route.abort().catch(() => {}); // The host timeout may already have aborted it.
|
|
237
|
+
});
|
|
238
|
+
await page.goto(`http://127.0.0.1:${address.port}${entryPath}`);
|
|
239
|
+
await page.getByRole('status').filter({ hasText: '載入 Usage' }).waitFor();
|
|
240
|
+
await page.clock.fastForward(15_001);
|
|
241
|
+
await page.getByRole('alert').filter({ hasText: '載入逾時' }).waitFor();
|
|
242
|
+
await page.screenshot({ path: path.join(screenshotDir, 'usage-loading-timeout.png') });
|
|
243
|
+
await page.unroute(rendererPattern);
|
|
244
|
+
releaseRequest();
|
|
245
|
+
await page.getByRole('button', { name: '重新載入', exact: true }).click();
|
|
246
|
+
await page.frameLocator('iframe[title="Usage"]').getByText('94% 剩餘', { exact: true }).waitFor();
|
|
247
|
+
await page.route(rendererPattern, async (route: any) => {
|
|
248
|
+
const response = await route.fetch();
|
|
249
|
+
await route.fulfill({ response, json: { ...await response.json(), sdk: '' } });
|
|
250
|
+
});
|
|
251
|
+
await page.goto(`http://127.0.0.1:${address.port}${entryPath}`);
|
|
252
|
+
await page.locator('iframe[title="Usage"]').waitFor();
|
|
253
|
+
await page.clock.fastForward(15_001);
|
|
254
|
+
await page.getByRole('alert').filter({ hasText: '載入逾時' }).waitFor();
|
|
255
|
+
assert.equal(await page.locator('iframe').count(), 0);
|
|
256
|
+
await page.unroute(rendererPattern);
|
|
257
|
+
await page.getByRole('button', { name: '重新載入', exact: true }).click();
|
|
258
|
+
await page.frameLocator('iframe[title="Usage"]').getByText('94% 剩餘', { exact: true }).waitFor();
|
|
259
|
+
}
|
|
260
|
+
assert.deepEqual(errors, []);
|
|
261
|
+
process.stdout.write(`${JSON.stringify({ ok: true, reads, queries, rendererRoot, electronMode, loadingRecovery: args.includes('--check-loading-recovery'),
|
|
262
|
+
app: { id: usage.id, version: usage.version, sha256: usage.sha256 }, screenshotDir: electronMode ? null : screenshotDir, isolatedRegistry: root }, null, 2)}\n`);
|
|
263
|
+
} finally {
|
|
264
|
+
await browser.close();
|
|
265
|
+
await new Promise<void>((resolve, reject) => server.close((error) => error ? reject(error) : resolve()));
|
|
266
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// Isolated Electron fixture: no Desktop supervisor, user profile, or live services.
|
|
2
|
+
const { app, BrowserWindow } = require('electron');
|
|
3
|
+
app.setPath('userData', process.env.CATS_USAGE_SMOKE_PROFILE_DIR);
|
|
4
|
+
app.whenReady().then(async () => {
|
|
5
|
+
globalThis.testWindow = new BrowserWindow({ width: 1440, height: 1200, show: false,
|
|
6
|
+
webPreferences: { contextIsolation: true, nodeIntegration: false, sandbox: true, backgroundThrottling: false },
|
|
7
|
+
});
|
|
8
|
+
await globalThis.testWindow.loadURL('about:blank');
|
|
9
|
+
});
|
|
10
|
+
app.on('window-all-closed', () => app.quit());
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { createRoot } from 'react-dom/client';
|
|
2
|
+
import { AppRendererSurface } from '../../src/app/renderer/AppRendererSurface.js';
|
|
3
|
+
import { installCsrfFetch } from '../../src/app/renderer/csrfFetch.js';
|
|
4
|
+
|
|
5
|
+
installCsrfFetch();
|
|
6
|
+
createRoot(document.getElementById('root')!).render(<AppRendererSurface appId="cats.usage" version={new URLSearchParams(location.search).get('appVersion') ?? ''}
|
|
7
|
+
title="Usage" locale={new URLSearchParams(location.search).get('locale') ?? 'zh-TW'}
|
|
8
|
+
onLobby={() => { document.body.textContent = 'Returned to lobby'; }} />);
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Verify the actual unpacked installer resources and offline App activation.
|
|
3
|
+
// Usage: node scripts/verify-desktop-app-bundle.mjs --release-root release --expect-lock config/desktop-apps.lock.json
|
|
4
|
+
// Alternatively pass --resources <resources-directory>. Uses only a temporary registry;
|
|
5
|
+
// does not start provider CLIs, download Apps, or touch the user's installed state.
|
|
6
|
+
import assert from 'node:assert/strict';
|
|
7
|
+
import { access, mkdtemp, readFile, readdir, rm } from 'node:fs/promises';
|
|
8
|
+
import { tmpdir } from 'node:os';
|
|
9
|
+
import path from 'node:path';
|
|
10
|
+
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
11
|
+
import { createRequire } from 'node:module';
|
|
12
|
+
import { resolveDesktopHostConfig } from '../build/desktop/config.js';
|
|
13
|
+
import { buildManagedServiceSpecs } from '../build/desktop/processSupervisor.js';
|
|
14
|
+
import { installBundledApps } from '../build/server/platform/apps/packageInstaller.js';
|
|
15
|
+
import { FileCatsAppRegistry } from '../build/server/platform/apps/registry.js';
|
|
16
|
+
import { readAppRenderer } from '../build/server/platform/apps/renderer.js';
|
|
17
|
+
|
|
18
|
+
const pins = (apps) => apps.map(({ id, version, sha256 }) => ({ id, version, sha256 }));
|
|
19
|
+
|
|
20
|
+
export async function verifyDesktopAppBundle(resourcesRoot, expectedLockPath) {
|
|
21
|
+
const root = await mkdtemp(path.join(tmpdir(), 'cats-packaged-app-check-'));
|
|
22
|
+
try {
|
|
23
|
+
const config = resolveDesktopHostConfig({
|
|
24
|
+
env: {}, packaged: true, resourcesPath: path.resolve(resourcesRoot),
|
|
25
|
+
userDataDir: path.join(root, 'desktop'), catsHomeDir: path.join(root, 'cats-home'),
|
|
26
|
+
});
|
|
27
|
+
const [, platform] = buildManagedServiceSpecs(config, {}, process.platform);
|
|
28
|
+
const sdk = await import(pathToFileURL(path.join(config.packageRoot, 'packages/app-sdk/package.js')).href);
|
|
29
|
+
const expected = sdk.parseAppLock(JSON.parse(await readFile(expectedLockPath, 'utf8')));
|
|
30
|
+
const bundledLock = platform.env.CATS_APP_BUNDLE_PATH;
|
|
31
|
+
assert.equal(bundledLock, path.join(config.packageRoot, 'official-apps/bundle.lock.json'));
|
|
32
|
+
assert.equal(config.paths.platformBundledConfigDir, path.join(config.packageRoot, 'config'));
|
|
33
|
+
await access(config.paths.appEntryScript);
|
|
34
|
+
await access(path.join(config.paths.platformBundledConfigDir, 'provider-capability-bootstrap.yaml.example'));
|
|
35
|
+
const bundled = sdk.parseAppLock(JSON.parse(await readFile(bundledLock, 'utf8')));
|
|
36
|
+
const plan = JSON.parse(await readFile(path.join(resourcesRoot, 'desktop-package-plan.json'), 'utf8'));
|
|
37
|
+
assert.deepEqual(pins(bundled.apps), pins(expected.apps), 'Installer must contain the selected exact App set');
|
|
38
|
+
assert.deepEqual(pins(plan.apps ?? []), pins(expected.apps), 'Packaging plan must retain the selected App set');
|
|
39
|
+
if (expected.apps.length > 0) {
|
|
40
|
+
assert.equal(createRequire(pathToFileURL(config.paths.appEntryScript)).resolve('#cats-app-package'),
|
|
41
|
+
path.join(config.packageRoot, 'packages/app-sdk/package.js'), 'Sidecar SDK alias must resolve to its shipped package');
|
|
42
|
+
if (plan.sidecarLayout?.app === 'bundle') {
|
|
43
|
+
const entry = await readFile(config.paths.appEntryScript, 'utf8');
|
|
44
|
+
assert.match(entry, /\bfrom\s+['"]#cats-app-package['"]/u,
|
|
45
|
+
'Bundled sidecar must retain the SDK package import; inlining relocates browser.js');
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
assert.ok((await sdk.readBrowserSdk()).includes('getSnapshot'), 'Shipped browser SDK must be readable');
|
|
49
|
+
for (const app of bundled.apps) {
|
|
50
|
+
assert.equal(app.artifact, `${app.id}-${app.version}.catsapp`, 'Startup must use adjacent offline archives');
|
|
51
|
+
sdk.decodeAppPackage(await readFile(path.join(path.dirname(bundledLock), app.artifact)), app);
|
|
52
|
+
}
|
|
53
|
+
// Exercise the same installer invoked before the Platform HTTP server starts.
|
|
54
|
+
// These compiled modules come from this build; bytes and SDK above come from
|
|
55
|
+
// the actual installer resources, including bundled-sidecar builds.
|
|
56
|
+
await installBundledApps(config.paths.appStatePath, bundledLock);
|
|
57
|
+
await installBundledApps(config.paths.appStatePath, bundledLock);
|
|
58
|
+
const registry = new FileCatsAppRegistry({ registryPath: path.join(config.paths.platformDir, 'apps/registry.json') });
|
|
59
|
+
const installed = await registry.listInstalledApps();
|
|
60
|
+
assert.equal(installed.length, expected.apps.length);
|
|
61
|
+
for (const app of installed) {
|
|
62
|
+
assert.equal(app.enabled, true);
|
|
63
|
+
assert.equal(app.installState, 'enabled');
|
|
64
|
+
assert.equal(app.packageSource, 'desktop-bundle');
|
|
65
|
+
assert.ok(app.manifest.contributions.lobbyApps.length > 0);
|
|
66
|
+
assert.ok((await readAppRenderer(app)).html.includes('<head>'));
|
|
67
|
+
}
|
|
68
|
+
return { resources: path.resolve(resourcesRoot), apps: pins(bundled.apps), offlineActivation: true };
|
|
69
|
+
} finally {
|
|
70
|
+
await rm(root, { recursive: true, force: true });
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
async function findResources(directory, depth = 0) {
|
|
75
|
+
try {
|
|
76
|
+
await access(path.join(directory, 'desktop-package-plan.json'));
|
|
77
|
+
return [directory];
|
|
78
|
+
} catch { /* Look only through unpacked distribution directories below. */ }
|
|
79
|
+
if (depth >= 6) return [];
|
|
80
|
+
const entries = await readdir(directory, { withFileTypes: true });
|
|
81
|
+
const nested = await Promise.all(entries.filter((entry) => entry.isDirectory()
|
|
82
|
+
&& !['node_modules', 'app-sidecar', 'cats-runtime'].includes(entry.name))
|
|
83
|
+
.map((entry) => findResources(path.join(directory, entry.name), depth + 1)));
|
|
84
|
+
return nested.flat();
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
async function main() {
|
|
88
|
+
const args = process.argv.slice(2);
|
|
89
|
+
if (args.includes('--help')) {
|
|
90
|
+
console.log('Usage: verify-desktop-app-bundle.mjs (--release-root <directory> | --resources <directory>) --expect-lock <lock>');
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
const options = {};
|
|
94
|
+
for (let index = 0; index < args.length; index += 2) {
|
|
95
|
+
if (!['--resources', '--release-root', '--expect-lock'].includes(args[index])
|
|
96
|
+
|| !args[index + 1] || args[index + 1].startsWith('--')) throw new Error('Invalid verifier arguments. Use --help.');
|
|
97
|
+
options[args[index]] = path.resolve(args[index + 1]);
|
|
98
|
+
}
|
|
99
|
+
assert.ok(options['--expect-lock'], '--expect-lock is required');
|
|
100
|
+
assert.ok(Boolean(options['--resources']) !== Boolean(options['--release-root']), 'Select resources or release-root');
|
|
101
|
+
const roots = options['--resources'] ? [options['--resources']] : await findResources(options['--release-root']);
|
|
102
|
+
assert.ok(roots.length > 0, 'No unpacked installer resources found');
|
|
103
|
+
for (const resources of roots) console.log(JSON.stringify(await verifyDesktopAppBundle(resources, options['--expect-lock']), null, 2));
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (path.resolve(process.argv[1] ?? '') === fileURLToPath(import.meta.url)) {
|
|
107
|
+
main().catch((error) => { console.error(error); process.exitCode = 1; });
|
|
108
|
+
}
|
|
@@ -13,6 +13,9 @@
|
|
|
13
13
|
.PARAMETER OutputDir
|
|
14
14
|
Optional override for the packaging output directory.
|
|
15
15
|
|
|
16
|
+
.PARAMETER AppsLock
|
|
17
|
+
App selection lock with exact IDs, versions and SHA-256 hashes.
|
|
18
|
+
|
|
16
19
|
.EXAMPLE
|
|
17
20
|
.\scripts\windows\Build-DesktopPackage.ps1 -Platform windows
|
|
18
21
|
Build the staged Windows packaging outputs.
|
|
@@ -20,7 +23,8 @@
|
|
|
20
23
|
param(
|
|
21
24
|
[ValidateSet('all', 'windows', 'macos', 'linux')]
|
|
22
25
|
[string]$Platform = 'all',
|
|
23
|
-
[string]$OutputDir = ''
|
|
26
|
+
[string]$OutputDir = '',
|
|
27
|
+
[string]$AppsLock = ''
|
|
24
28
|
)
|
|
25
29
|
|
|
26
30
|
Set-StrictMode -Version Latest
|
|
@@ -34,11 +38,10 @@ try {
|
|
|
34
38
|
if ($LASTEXITCODE -ne 0) {
|
|
35
39
|
throw "npm run build failed with exit code $LASTEXITCODE"
|
|
36
40
|
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
}
|
|
41
|
+
$packageArguments = @('.\scripts\package-desktop.mjs', '--platform', $Platform)
|
|
42
|
+
if ($OutputDir) { $packageArguments += @('--output-dir', $OutputDir) }
|
|
43
|
+
if ($AppsLock) { $packageArguments += @('--apps-lock', $AppsLock) }
|
|
44
|
+
node @packageArguments
|
|
42
45
|
if ($LASTEXITCODE -ne 0) {
|
|
43
46
|
throw "desktop packaging failed with exit code $LASTEXITCODE"
|
|
44
47
|
}
|