@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.
Files changed (448) hide show
  1. package/.env.example +3 -7
  2. package/README.md +18 -0
  3. package/build/desktop/bootstrapNavigation.d.ts.map +1 -1
  4. package/build/desktop/bootstrapNavigation.js +6 -13
  5. package/build/desktop/bootstrapNavigation.js.map +1 -1
  6. package/build/desktop/bootstrapPage.d.ts.map +1 -1
  7. package/build/desktop/bootstrapPage.js +114 -34
  8. package/build/desktop/bootstrapPage.js.map +1 -1
  9. package/build/desktop/cliInventoryProbe.d.ts +5 -2
  10. package/build/desktop/cliInventoryProbe.d.ts.map +1 -1
  11. package/build/desktop/cliInventoryProbe.js +14 -11
  12. package/build/desktop/cliInventoryProbe.js.map +1 -1
  13. package/build/desktop/config.d.ts +0 -4
  14. package/build/desktop/config.d.ts.map +1 -1
  15. package/build/desktop/config.js +1 -6
  16. package/build/desktop/config.js.map +1 -1
  17. package/build/desktop/contracts.d.ts +10 -2
  18. package/build/desktop/contracts.d.ts.map +1 -1
  19. package/build/desktop/contracts.js +1 -2
  20. package/build/desktop/contracts.js.map +1 -1
  21. package/build/desktop/hostVersion.d.ts.map +1 -1
  22. package/build/desktop/hostVersion.js +3 -5
  23. package/build/desktop/hostVersion.js.map +1 -1
  24. package/build/desktop/main.js +144 -249
  25. package/build/desktop/main.js.map +1 -1
  26. package/build/desktop/packaging.d.ts +2 -0
  27. package/build/desktop/packaging.d.ts.map +1 -1
  28. package/build/desktop/packaging.js +34 -14
  29. package/build/desktop/packaging.js.map +1 -1
  30. package/build/desktop/preload.cjs +7 -0
  31. package/build/desktop/preload.cjs.map +1 -1
  32. package/build/desktop/processSupervisor.d.ts.map +1 -1
  33. package/build/desktop/processSupervisor.js +3 -0
  34. package/build/desktop/processSupervisor.js.map +1 -1
  35. package/build/desktop/providerSelection.d.ts +37 -0
  36. package/build/desktop/providerSelection.d.ts.map +1 -0
  37. package/build/desktop/providerSelection.js +112 -0
  38. package/build/desktop/providerSelection.js.map +1 -0
  39. package/build/desktop/readiness.d.ts +2 -0
  40. package/build/desktop/readiness.d.ts.map +1 -1
  41. package/build/desktop/readiness.js +14 -33
  42. package/build/desktop/readiness.js.map +1 -1
  43. package/build/desktop/setupAssets.d.ts.map +1 -1
  44. package/build/desktop/setupAssets.js +16 -14
  45. package/build/desktop/setupAssets.js.map +1 -1
  46. package/build/desktop/setupAudit.d.ts +2 -3
  47. package/build/desktop/setupAudit.d.ts.map +1 -1
  48. package/build/desktop/setupAudit.js +14 -34
  49. package/build/desktop/setupAudit.js.map +1 -1
  50. package/build/desktop/updateDialog.d.ts +27 -1
  51. package/build/desktop/updateDialog.d.ts.map +1 -1
  52. package/build/desktop/updateDialog.js +85 -5
  53. package/build/desktop/updateDialog.js.map +1 -1
  54. package/build/renderer/assets/{ActiveSessionPermissionChip-DImsuR9T.js → ActiveSessionPermissionChip-CAgN-tXv.js} +1 -1
  55. package/build/renderer/assets/App-BZA23O2J.js +2 -0
  56. package/build/renderer/assets/App-DxsV-tKS.css +1 -0
  57. package/build/renderer/assets/{App-DKOSn0o_.js → App-YqprEL2n.js} +1 -1
  58. package/build/renderer/assets/App-rGw9J8PZ.js +1 -0
  59. package/build/renderer/assets/WorkspaceAppRoutes-BCHCikmJ.js +1 -0
  60. package/build/renderer/assets/app-BV3UAQkR.css +1 -0
  61. package/build/renderer/assets/app-CVPqqfZo.js +45 -0
  62. package/build/renderer/assets/conversationSidebarRecentEntries-iqaLqA1n.js +6 -0
  63. package/build/renderer/assets/{useDraftSessionChips-DCIId0eY.js → useDraftSessionChips-D9BX6X92.js} +1 -1
  64. package/build/renderer/index.html +2 -2
  65. package/build/server/app/renderer/providerCatalogClient.d.ts.map +1 -1
  66. package/build/server/app/renderer/providerCatalogClient.js +15 -6
  67. package/build/server/app/renderer/providerCatalogClient.js.map +1 -1
  68. package/build/server/app/renderer/providerRegistryClient.d.ts +1 -1
  69. package/build/server/app/renderer/providerRegistryClient.d.ts.map +1 -1
  70. package/build/server/app/renderer/providerRegistryClient.js +23 -41
  71. package/build/server/app/renderer/providerRegistryClient.js.map +1 -1
  72. package/build/server/app/server/appPackageRoutes.d.ts +2 -0
  73. package/build/server/app/server/appPackageRoutes.d.ts.map +1 -1
  74. package/build/server/app/server/appPackageRoutes.js +105 -0
  75. package/build/server/app/server/appPackageRoutes.js.map +1 -1
  76. package/build/server/app/server/authGatePolicy.js +7 -1
  77. package/build/server/app/server/authGatePolicy.js.map +1 -1
  78. package/build/server/app/server/contracts.d.ts +15 -0
  79. package/build/server/app/server/contracts.d.ts.map +1 -1
  80. package/build/server/app/server/dependencies.d.ts.map +1 -1
  81. package/build/server/app/server/dependencies.js +42 -1
  82. package/build/server/app/server/dependencies.js.map +1 -1
  83. package/build/server/app/server/goldenPathStartupResume.d.ts +55 -0
  84. package/build/server/app/server/goldenPathStartupResume.d.ts.map +1 -0
  85. package/build/server/app/server/goldenPathStartupResume.js +109 -0
  86. package/build/server/app/server/goldenPathStartupResume.js.map +1 -0
  87. package/build/server/app/server/platformSetupRoutes.d.ts.map +1 -1
  88. package/build/server/app/server/platformSetupRoutes.js +1 -13
  89. package/build/server/app/server/platformSetupRoutes.js.map +1 -1
  90. package/build/server/app/server/polling.d.ts.map +1 -1
  91. package/build/server/app/server/polling.js +2 -0
  92. package/build/server/app/server/polling.js.map +1 -1
  93. package/build/server/app/server/requestRouter.d.ts.map +1 -1
  94. package/build/server/app/server/requestRouter.js +30 -0
  95. package/build/server/app/server/requestRouter.js.map +1 -1
  96. package/build/server/app/server/runtimeSurfaceProxy.d.ts.map +1 -1
  97. package/build/server/app/server/runtimeSurfaceProxy.js +4 -2
  98. package/build/server/app/server/runtimeSurfaceProxy.js.map +1 -1
  99. package/build/server/app/server/startupRecovery.d.ts.map +1 -1
  100. package/build/server/app/server/startupRecovery.js +5 -0
  101. package/build/server/app/server/startupRecovery.js.map +1 -1
  102. package/build/server/app/server/telegramCommandSurface.d.ts +29 -0
  103. package/build/server/app/server/telegramCommandSurface.d.ts.map +1 -0
  104. package/build/server/app/server/telegramCommandSurface.js +123 -0
  105. package/build/server/app/server/telegramCommandSurface.js.map +1 -0
  106. package/build/server/app/server/transportWorkGoldenPath.d.ts +82 -0
  107. package/build/server/app/server/transportWorkGoldenPath.d.ts.map +1 -0
  108. package/build/server/app/server/transportWorkGoldenPath.js +307 -0
  109. package/build/server/app/server/transportWorkGoldenPath.js.map +1 -0
  110. package/build/server/config.d.ts +21 -0
  111. package/build/server/config.d.ts.map +1 -1
  112. package/build/server/config.js +12 -0
  113. package/build/server/config.js.map +1 -1
  114. package/build/server/design/components/providerModelFieldsSupport.d.ts +3 -3
  115. package/build/server/design/components/providerModelFieldsSupport.d.ts.map +1 -1
  116. package/build/server/design/components/providerModelFieldsSupport.js +37 -38
  117. package/build/server/design/components/providerModelFieldsSupport.js.map +1 -1
  118. package/build/server/design/components/useProviderCatalogState.d.ts +1 -0
  119. package/build/server/design/components/useProviderCatalogState.d.ts.map +1 -1
  120. package/build/server/design/components/useProviderCatalogState.js +1 -0
  121. package/build/server/design/components/useProviderCatalogState.js.map +1 -1
  122. package/build/server/design/components/useProviderRegistryAutoRecheck.d.ts.map +1 -1
  123. package/build/server/design/components/useProviderRegistryAutoRecheck.js +20 -13
  124. package/build/server/design/components/useProviderRegistryAutoRecheck.js.map +1 -1
  125. package/build/server/design/components/useProviderRegistryState.d.ts.map +1 -1
  126. package/build/server/design/components/useProviderRegistryState.js +12 -25
  127. package/build/server/design/components/useProviderRegistryState.js.map +1 -1
  128. package/build/server/design/components/useProviderTargetReconciliation.d.ts.map +1 -1
  129. package/build/server/design/components/useProviderTargetReconciliation.js +2 -1
  130. package/build/server/design/components/useProviderTargetReconciliation.js.map +1 -1
  131. package/build/server/index.js +4 -0
  132. package/build/server/index.js.map +1 -1
  133. package/build/server/platform/apps/packageInstaller.d.ts +19 -0
  134. package/build/server/platform/apps/packageInstaller.d.ts.map +1 -0
  135. package/build/server/platform/apps/packageInstaller.js +92 -0
  136. package/build/server/platform/apps/packageInstaller.js.map +1 -0
  137. package/build/server/platform/apps/registry.d.ts +6 -0
  138. package/build/server/platform/apps/registry.d.ts.map +1 -1
  139. package/build/server/platform/apps/registry.js +24 -0
  140. package/build/server/platform/apps/registry.js.map +1 -1
  141. package/build/server/platform/apps/renderer.d.ts +6 -0
  142. package/build/server/platform/apps/renderer.d.ts.map +1 -0
  143. package/build/server/platform/apps/renderer.js +18 -0
  144. package/build/server/platform/apps/renderer.js.map +1 -0
  145. package/build/server/platform/runtime/deliveryClient.d.ts +111 -0
  146. package/build/server/platform/runtime/deliveryClient.d.ts.map +1 -0
  147. package/build/server/platform/runtime/deliveryClient.js +289 -0
  148. package/build/server/platform/runtime/deliveryClient.js.map +1 -0
  149. package/build/server/platform/supervision/providerCapabilityBootstrapYaml.d.ts +1 -0
  150. package/build/server/platform/supervision/providerCapabilityBootstrapYaml.d.ts.map +1 -1
  151. package/build/server/platform/supervision/providerCapabilityBootstrapYaml.js +10 -0
  152. package/build/server/platform/supervision/providerCapabilityBootstrapYaml.js.map +1 -1
  153. package/build/server/platform/supervision/runtimeBoundary.d.ts +11 -1
  154. package/build/server/platform/supervision/runtimeBoundary.d.ts.map +1 -1
  155. package/build/server/platform/supervision/runtimeBoundary.js +2 -2
  156. package/build/server/platform/supervision/runtimeBoundary.js.map +1 -1
  157. package/build/server/platform/transports/telegram/bridge.d.ts +18 -0
  158. package/build/server/platform/transports/telegram/bridge.d.ts.map +1 -1
  159. package/build/server/platform/transports/telegram/bridge.js +176 -0
  160. package/build/server/platform/transports/telegram/bridge.js.map +1 -1
  161. package/build/server/platform/transports/telegram/commandPort.d.ts +40 -0
  162. package/build/server/platform/transports/telegram/commandPort.d.ts.map +1 -0
  163. package/build/server/platform/transports/telegram/commandPort.js +17 -0
  164. package/build/server/platform/transports/telegram/commandPort.js.map +1 -0
  165. package/build/server/platform/transports/telegram/commandRouter.d.ts +22 -0
  166. package/build/server/platform/transports/telegram/commandRouter.d.ts.map +1 -1
  167. package/build/server/platform/transports/telegram/commandRouter.js.map +1 -1
  168. package/build/server/platform/transports/telegram/commands/index.d.ts.map +1 -1
  169. package/build/server/platform/transports/telegram/commands/index.js +38 -0
  170. package/build/server/platform/transports/telegram/commands/index.js.map +1 -1
  171. package/build/server/platform/transports/telegram/ingressDispatch.d.ts +56 -0
  172. package/build/server/platform/transports/telegram/ingressDispatch.d.ts.map +1 -0
  173. package/build/server/platform/transports/telegram/ingressDispatch.js +93 -0
  174. package/build/server/platform/transports/telegram/ingressDispatch.js.map +1 -0
  175. package/build/server/platform/transports/telegram/polling.d.ts +34 -0
  176. package/build/server/platform/transports/telegram/polling.d.ts.map +1 -1
  177. package/build/server/platform/transports/telegram/polling.js +86 -9
  178. package/build/server/platform/transports/telegram/polling.js.map +1 -1
  179. package/build/server/platform/transports/telegram/relay/index.d.ts +3 -0
  180. package/build/server/platform/transports/telegram/relay/index.d.ts.map +1 -1
  181. package/build/server/platform/transports/telegram/relay/index.js +5 -1
  182. package/build/server/platform/transports/telegram/relay/index.js.map +1 -1
  183. package/build/server/platform/transports/telegram/relay/ingress.d.ts +2 -0
  184. package/build/server/platform/transports/telegram/relay/ingress.d.ts.map +1 -1
  185. package/build/server/platform/transports/telegram/relay/ingress.js +1 -1
  186. package/build/server/platform/transports/telegram/relay/ingress.js.map +1 -1
  187. package/build/server/platform/transports/work-delivery/actionTokens.d.ts +66 -0
  188. package/build/server/platform/transports/work-delivery/actionTokens.d.ts.map +1 -0
  189. package/build/server/platform/transports/work-delivery/actionTokens.js +145 -0
  190. package/build/server/platform/transports/work-delivery/actionTokens.js.map +1 -0
  191. package/build/server/platform/transports/work-delivery/contracts.d.ts +172 -0
  192. package/build/server/platform/transports/work-delivery/contracts.d.ts.map +1 -0
  193. package/build/server/platform/transports/work-delivery/contracts.js +26 -0
  194. package/build/server/platform/transports/work-delivery/contracts.js.map +1 -0
  195. package/build/server/platform/transports/work-delivery/deliveryGates.d.ts +32 -0
  196. package/build/server/platform/transports/work-delivery/deliveryGates.d.ts.map +1 -0
  197. package/build/server/platform/transports/work-delivery/deliveryGates.js +45 -0
  198. package/build/server/platform/transports/work-delivery/deliveryGates.js.map +1 -0
  199. package/build/server/platform/transports/work-delivery/inboundClassification.d.ts +31 -0
  200. package/build/server/platform/transports/work-delivery/inboundClassification.d.ts.map +1 -0
  201. package/build/server/platform/transports/work-delivery/inboundClassification.js +52 -0
  202. package/build/server/platform/transports/work-delivery/inboundClassification.js.map +1 -0
  203. package/build/server/platform/transports/work-delivery/outbox.d.ts +84 -0
  204. package/build/server/platform/transports/work-delivery/outbox.d.ts.map +1 -0
  205. package/build/server/platform/transports/work-delivery/outbox.js +270 -0
  206. package/build/server/platform/transports/work-delivery/outbox.js.map +1 -0
  207. package/build/server/platform/transports/work-delivery/permissionEnvelope.d.ts +57 -0
  208. package/build/server/platform/transports/work-delivery/permissionEnvelope.d.ts.map +1 -0
  209. package/build/server/platform/transports/work-delivery/permissionEnvelope.js +74 -0
  210. package/build/server/platform/transports/work-delivery/permissionEnvelope.js.map +1 -0
  211. package/build/server/platform/transports/work-delivery/port.d.ts +60 -0
  212. package/build/server/platform/transports/work-delivery/port.d.ts.map +1 -0
  213. package/build/server/platform/transports/work-delivery/port.js +15 -0
  214. package/build/server/platform/transports/work-delivery/port.js.map +1 -0
  215. package/build/server/platform/transports/work-delivery/proposal.d.ts +31 -0
  216. package/build/server/platform/transports/work-delivery/proposal.d.ts.map +1 -0
  217. package/build/server/platform/transports/work-delivery/proposal.js +59 -0
  218. package/build/server/platform/transports/work-delivery/proposal.js.map +1 -0
  219. package/build/server/platform/transports/work-delivery/readiness.d.ts +61 -0
  220. package/build/server/platform/transports/work-delivery/readiness.d.ts.map +1 -0
  221. package/build/server/platform/transports/work-delivery/readiness.js +123 -0
  222. package/build/server/platform/transports/work-delivery/readiness.js.map +1 -0
  223. package/build/server/platform/transports/work-delivery/stageProjection.d.ts +43 -0
  224. package/build/server/platform/transports/work-delivery/stageProjection.d.ts.map +1 -0
  225. package/build/server/platform/transports/work-delivery/stageProjection.js +132 -0
  226. package/build/server/platform/transports/work-delivery/stageProjection.js.map +1 -0
  227. package/build/server/platform/transports/work-delivery/stateStore.d.ts +21 -0
  228. package/build/server/platform/transports/work-delivery/stateStore.d.ts.map +1 -0
  229. package/build/server/platform/transports/work-delivery/stateStore.js +193 -0
  230. package/build/server/platform/transports/work-delivery/stateStore.js.map +1 -0
  231. package/build/server/platform/transports/work-delivery/telemetry.d.ts +49 -0
  232. package/build/server/platform/transports/work-delivery/telemetry.d.ts.map +1 -0
  233. package/build/server/platform/transports/work-delivery/telemetry.js +80 -0
  234. package/build/server/platform/transports/work-delivery/telemetry.js.map +1 -0
  235. package/build/server/products/chat/api/contracts.d.ts +10 -0
  236. package/build/server/products/chat/api/contracts.d.ts.map +1 -1
  237. package/build/server/products/chat/api/resources/channelRoutes.d.ts.map +1 -1
  238. package/build/server/products/chat/api/resources/channelRoutes.js +27 -1
  239. package/build/server/products/chat/api/resources/channelRoutes.js.map +1 -1
  240. package/build/server/products/chat/api/routeSupport.d.ts +8 -0
  241. package/build/server/products/chat/api/routeSupport.d.ts.map +1 -1
  242. package/build/server/products/chat/api/routeSupport.js +5 -4
  243. package/build/server/products/chat/api/routeSupport.js.map +1 -1
  244. package/build/server/products/chat/api/setupRoutes.d.ts.map +1 -1
  245. package/build/server/products/chat/api/setupRoutes.js +23 -8
  246. package/build/server/products/chat/api/setupRoutes.js.map +1 -1
  247. package/build/server/products/chat/state/model/channelExecutionTargets.d.ts +15 -0
  248. package/build/server/products/chat/state/model/channelExecutionTargets.d.ts.map +1 -1
  249. package/build/server/products/chat/state/model/channelExecutionTargets.js +25 -0
  250. package/build/server/products/chat/state/model/channelExecutionTargets.js.map +1 -1
  251. package/build/server/products/chat/state/model/index.d.ts +1 -1
  252. package/build/server/products/chat/state/model/index.d.ts.map +1 -1
  253. package/build/server/products/chat/state/model/index.js +1 -1
  254. package/build/server/products/chat/state/model/index.js.map +1 -1
  255. package/build/server/products/code/api/relayRoutes.d.ts.map +1 -1
  256. package/build/server/products/code/api/relayRoutes.js +36 -7
  257. package/build/server/products/code/api/relayRoutes.js.map +1 -1
  258. package/build/server/products/code/state/relayState.d.ts +2 -1
  259. package/build/server/products/code/state/relayState.d.ts.map +1 -1
  260. package/build/server/products/code/state/relayState.js +7 -7
  261. package/build/server/products/code/state/relayState.js.map +1 -1
  262. package/build/server/products/shared/api/workspaceContracts.d.ts +5 -0
  263. package/build/server/products/shared/api/workspaceContracts.d.ts.map +1 -1
  264. package/build/server/products/work/api/goldenPathProjection.d.ts +156 -0
  265. package/build/server/products/work/api/goldenPathProjection.d.ts.map +1 -0
  266. package/build/server/products/work/api/goldenPathProjection.js +252 -0
  267. package/build/server/products/work/api/goldenPathProjection.js.map +1 -0
  268. package/build/server/products/work/api/index.d.ts +54 -1
  269. package/build/server/products/work/api/index.d.ts.map +1 -1
  270. package/build/server/products/work/api/index.js +182 -4
  271. package/build/server/products/work/api/index.js.map +1 -1
  272. package/build/server/products/work/api/projection.d.ts +7 -1
  273. package/build/server/products/work/api/projection.d.ts.map +1 -1
  274. package/build/server/products/work/api/projection.js +7 -1
  275. package/build/server/products/work/api/projection.js.map +1 -1
  276. package/build/server/products/work/shared/apiPaths.d.ts +8 -0
  277. package/build/server/products/work/shared/apiPaths.d.ts.map +1 -1
  278. package/build/server/products/work/shared/apiPaths.js +8 -0
  279. package/build/server/products/work/shared/apiPaths.js.map +1 -1
  280. package/build/server/products/work/shared/workGoldenPathMessages.d.ts +83 -0
  281. package/build/server/products/work/shared/workGoldenPathMessages.d.ts.map +1 -0
  282. package/build/server/products/work/shared/workGoldenPathMessages.js +211 -0
  283. package/build/server/products/work/shared/workGoldenPathMessages.js.map +1 -0
  284. package/build/server/products/work/shared/workGoldenPathMetadata.d.ts +45 -0
  285. package/build/server/products/work/shared/workGoldenPathMetadata.d.ts.map +1 -0
  286. package/build/server/products/work/shared/workGoldenPathMetadata.js +122 -0
  287. package/build/server/products/work/shared/workGoldenPathMetadata.js.map +1 -0
  288. package/build/server/products/work/state/workCompletionEvidence.d.ts +42 -0
  289. package/build/server/products/work/state/workCompletionEvidence.d.ts.map +1 -0
  290. package/build/server/products/work/state/workCompletionEvidence.js +59 -0
  291. package/build/server/products/work/state/workCompletionEvidence.js.map +1 -0
  292. package/build/server/products/work/state/workExecutionTaskDelegate.d.ts +16 -0
  293. package/build/server/products/work/state/workExecutionTaskDelegate.d.ts.map +1 -1
  294. package/build/server/products/work/state/workExecutionTaskDelegate.js +91 -68
  295. package/build/server/products/work/state/workExecutionTaskDelegate.js.map +1 -1
  296. package/build/server/products/work/state/workGoldenPathAdmission.d.ts +78 -0
  297. package/build/server/products/work/state/workGoldenPathAdmission.d.ts.map +1 -0
  298. package/build/server/products/work/state/workGoldenPathAdmission.js +249 -0
  299. package/build/server/products/work/state/workGoldenPathAdmission.js.map +1 -0
  300. package/build/server/products/work/state/workGoldenPathDeliveryEvidence.d.ts +33 -0
  301. package/build/server/products/work/state/workGoldenPathDeliveryEvidence.d.ts.map +1 -0
  302. package/build/server/products/work/state/workGoldenPathDeliveryEvidence.js +161 -0
  303. package/build/server/products/work/state/workGoldenPathDeliveryEvidence.js.map +1 -0
  304. package/build/server/products/work/state/workGoldenPathIntake.d.ts +34 -0
  305. package/build/server/products/work/state/workGoldenPathIntake.d.ts.map +1 -0
  306. package/build/server/products/work/state/workGoldenPathIntake.js +50 -0
  307. package/build/server/products/work/state/workGoldenPathIntake.js.map +1 -0
  308. package/build/server/products/work/state/workGoldenPathLifecycle.d.ts +44 -0
  309. package/build/server/products/work/state/workGoldenPathLifecycle.d.ts.map +1 -0
  310. package/build/server/products/work/state/workGoldenPathLifecycle.js +146 -0
  311. package/build/server/products/work/state/workGoldenPathLifecycle.js.map +1 -0
  312. package/build/server/products/work/state/workGoldenPathPublish.d.ts +84 -0
  313. package/build/server/products/work/state/workGoldenPathPublish.d.ts.map +1 -0
  314. package/build/server/products/work/state/workGoldenPathPublish.js +488 -0
  315. package/build/server/products/work/state/workGoldenPathPublish.js.map +1 -0
  316. package/build/server/products/work/state/workGoldenPathRunner.d.ts +121 -0
  317. package/build/server/products/work/state/workGoldenPathRunner.d.ts.map +1 -0
  318. package/build/server/products/work/state/workGoldenPathRunner.js +447 -0
  319. package/build/server/products/work/state/workGoldenPathRunner.js.map +1 -0
  320. package/build/server/products/work/state/workGoldenPathRuntimeExecutor.d.ts +74 -0
  321. package/build/server/products/work/state/workGoldenPathRuntimeExecutor.d.ts.map +1 -0
  322. package/build/server/products/work/state/workGoldenPathRuntimeExecutor.js +239 -0
  323. package/build/server/products/work/state/workGoldenPathRuntimeExecutor.js.map +1 -0
  324. package/build/server/products/work/state/workGoldenPathService.d.ts +152 -0
  325. package/build/server/products/work/state/workGoldenPathService.d.ts.map +1 -0
  326. package/build/server/products/work/state/workGoldenPathService.js +1057 -0
  327. package/build/server/products/work/state/workGoldenPathService.js.map +1 -0
  328. package/build/server/products/work/state/workGoldenPathTelegramPort.d.ts +87 -0
  329. package/build/server/products/work/state/workGoldenPathTelegramPort.d.ts.map +1 -0
  330. package/build/server/products/work/state/workGoldenPathTelegramPort.js +220 -0
  331. package/build/server/products/work/state/workGoldenPathTelegramPort.js.map +1 -0
  332. package/build/server/runtime/client.d.ts +13 -0
  333. package/build/server/runtime/client.d.ts.map +1 -1
  334. package/build/server/runtime/client.js +39 -0
  335. package/build/server/runtime/client.js.map +1 -1
  336. package/build/server/runtime/setup.d.ts +10 -4
  337. package/build/server/runtime/setup.d.ts.map +1 -1
  338. package/build/server/runtime/setup.js +14 -18
  339. package/build/server/runtime/setup.js.map +1 -1
  340. package/build/server/runtime/usageSnapshot.d.ts +3 -0
  341. package/build/server/runtime/usageSnapshot.d.ts.map +1 -0
  342. package/build/server/runtime/usageSnapshot.js +69 -0
  343. package/build/server/runtime/usageSnapshot.js.map +1 -0
  344. package/build/server/server/routes/providerCapabilityBootstrap.d.ts +69 -0
  345. package/build/server/server/routes/providerCapabilityBootstrap.d.ts.map +1 -0
  346. package/build/server/server/routes/providerCapabilityBootstrap.js +165 -0
  347. package/build/server/server/routes/providerCapabilityBootstrap.js.map +1 -0
  348. package/build/server/server/routes/providers.d.ts.map +1 -1
  349. package/build/server/server/routes/providers.js +112 -81
  350. package/build/server/server/routes/providers.js.map +1 -1
  351. package/build/server/server/routes/telegram.d.ts +9 -0
  352. package/build/server/server/routes/telegram.d.ts.map +1 -1
  353. package/build/server/server/routes/telegram.js +79 -72
  354. package/build/server/server/routes/telegram.js.map +1 -1
  355. package/build/server/shared/catsAppManifest.d.ts +3 -1
  356. package/build/server/shared/catsAppManifest.d.ts.map +1 -1
  357. package/build/server/shared/catsAppManifest.js +2 -0
  358. package/build/server/shared/catsAppManifest.js.map +1 -1
  359. package/build/server/shared/executionLabel.d.ts.map +1 -1
  360. package/build/server/shared/executionLabel.js +8 -1
  361. package/build/server/shared/executionLabel.js.map +1 -1
  362. package/build/server/shared/i18n/catalogs/en.d.ts.map +1 -1
  363. package/build/server/shared/i18n/catalogs/en.js +198 -3
  364. package/build/server/shared/i18n/catalogs/en.js.map +1 -1
  365. package/build/server/shared/i18n/catalogs/zh-TW.d.ts.map +1 -1
  366. package/build/server/shared/i18n/catalogs/zh-TW.js +197 -3
  367. package/build/server/shared/i18n/catalogs/zh-TW.js.map +1 -1
  368. package/build/server/shared/i18n/index.d.ts +192 -0
  369. package/build/server/shared/i18n/index.d.ts.map +1 -1
  370. package/build/server/shared/i18n/messageKeys.d.ts +192 -0
  371. package/build/server/shared/i18n/messageKeys.d.ts.map +1 -1
  372. package/build/server/shared/i18n/messageKeys.js +192 -0
  373. package/build/server/shared/i18n/messageKeys.js.map +1 -1
  374. package/build/server/shared/platformSetupOperation.d.ts +2 -0
  375. package/build/server/shared/platformSetupOperation.d.ts.map +1 -0
  376. package/build/server/shared/platformSetupOperation.js +9 -0
  377. package/build/server/shared/platformSetupOperation.js.map +1 -0
  378. package/build/server/shared/providerCatalog.d.ts +5 -2
  379. package/build/server/shared/providerCatalog.d.ts.map +1 -1
  380. package/build/server/shared/providerCatalog.js +6 -0
  381. package/build/server/shared/providerCatalog.js.map +1 -1
  382. package/build/server/shared/providerCatalogData.d.ts +28 -22
  383. package/build/server/shared/providerCatalogData.d.ts.map +1 -1
  384. package/build/server/shared/providerCatalogData.js +22 -10
  385. package/build/server/shared/providerCatalogData.js.map +1 -1
  386. package/build/server/shared/providerCatalogInstances.d.ts.map +1 -1
  387. package/build/server/shared/providerCatalogInstances.js +3 -0
  388. package/build/server/shared/providerCatalogInstances.js.map +1 -1
  389. package/build/server/shared/providerModelLabelRegistry.d.ts +29 -0
  390. package/build/server/shared/providerModelLabelRegistry.d.ts.map +1 -0
  391. package/build/server/shared/providerModelLabelRegistry.js +49 -0
  392. package/build/server/shared/providerModelLabelRegistry.js.map +1 -0
  393. package/build/server/shared/providerSelection.d.ts.map +1 -1
  394. package/build/server/shared/providerSelection.js +10 -13
  395. package/build/server/shared/providerSelection.js.map +1 -1
  396. package/build/server/shared/runtimeSetup.d.ts +17 -4
  397. package/build/server/shared/runtimeSetup.d.ts.map +1 -1
  398. package/build/server/shared/runtimeStatusPresentation.js +1 -1
  399. package/build/server/shared/runtimeStatusPresentation.js.map +1 -1
  400. package/package.json +23 -1
  401. package/packages/app-sdk/browser.d.ts +51 -0
  402. package/packages/app-sdk/browser.js +48 -0
  403. package/packages/app-sdk/package.d.ts +14 -0
  404. package/packages/app-sdk/package.js +131 -0
  405. package/packages/app-sdk/package.json +7 -0
  406. package/scripts/README.md +43 -26
  407. package/scripts/build-desktop-installer.mjs +15 -0
  408. package/scripts/build-test-ui.mjs +1 -1
  409. package/scripts/bundle-server.mjs +23 -10
  410. package/scripts/linux/build-desktop-package.sh +6 -6
  411. package/scripts/linux/install-antigravity.sh +0 -0
  412. package/scripts/linux/install-devin.sh +0 -0
  413. package/scripts/linux/install-meta-cli.sh +8 -0
  414. package/scripts/linux/provider-cli-common.sh +103 -30
  415. package/scripts/linux/sync-agent-skills.sh +27 -5
  416. package/scripts/linux/test-linux-package-smoke.sh +4 -3
  417. package/scripts/linux/upgrade-cli-tools.sh +1 -1
  418. package/scripts/macos/build-desktop-package.sh +5 -5
  419. package/scripts/macos/install-antigravity.sh +0 -0
  420. package/scripts/macos/install-devin.sh +0 -0
  421. package/scripts/macos/install-meta-cli.sh +8 -0
  422. package/scripts/macos/provider-cli-common.sh +103 -30
  423. package/scripts/macos/sync-agent-skills.sh +27 -5
  424. package/scripts/macos/test-macos-package-smoke.sh +4 -3
  425. package/scripts/macos/upgrade-cli-tools.sh +1 -1
  426. package/scripts/package-desktop.mjs +15 -2
  427. package/scripts/testing/check-usage-app.mts +266 -0
  428. package/scripts/testing/usage-app-smoke-electron.cjs +10 -0
  429. package/scripts/testing/usage-app-smoke-renderer.tsx +8 -0
  430. package/scripts/verify-desktop-app-bundle.mjs +108 -0
  431. package/scripts/windows/Build-DesktopPackage.ps1 +9 -6
  432. package/scripts/windows/{Install-Aider.ps1 → Install-MetaCli.ps1} +180 -92
  433. package/scripts/windows/Install-Ollama.ps1 +4 -1
  434. package/scripts/windows/Sync-AgentSkills.ps1 +29 -6
  435. package/scripts/windows/Test-WindowsInstallerSmoke.ps1 +2 -1
  436. package/build/desktop/updateNotifications.d.ts +0 -64
  437. package/build/desktop/updateNotifications.d.ts.map +0 -1
  438. package/build/desktop/updateNotifications.js +0 -143
  439. package/build/desktop/updateNotifications.js.map +0 -1
  440. package/build/renderer/assets/App-BfOvMP2m.js +0 -1
  441. package/build/renderer/assets/App-DGwkRFZl.css +0 -1
  442. package/build/renderer/assets/App-DWd7I3Z2.js +0 -2
  443. package/build/renderer/assets/WorkspaceAppRoutes-CrbTA9En.js +0 -1
  444. package/build/renderer/assets/app-BTww3Hl4.js +0 -43
  445. package/build/renderer/assets/app-CPxWQwLA.css +0 -1
  446. package/build/renderer/assets/conversationSidebarRecentEntries-QuaOPxCb.js +0 -6
  447. package/scripts/linux/install-aider.sh +0 -8
  448. 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-aider.sh" 'bundled macOS Aider installer helper'
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-aider-native-installer-script'), 'macOS target includes the bundled Aider installer asset');
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-aider.sh install-goose.sh install-junie.sh install-kiro-cli.sh install-grok.sh; do
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
- if ($OutputDir) {
38
- node .\scripts\package-desktop.mjs --platform $Platform --output-dir $OutputDir
39
- } else {
40
- node .\scripts\package-desktop.mjs --platform $Platform
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
  }