@cats-inc/cats-platform 0.1.10 → 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 (516) hide show
  1. package/.env.example +9 -16
  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 +264 -77
  8. package/build/desktop/bootstrapPage.js.map +1 -1
  9. package/build/desktop/cliInventoryProbe.d.ts +23 -2
  10. package/build/desktop/cliInventoryProbe.d.ts.map +1 -1
  11. package/build/desktop/cliInventoryProbe.js +54 -9
  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 +19 -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 +177 -201
  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 +49 -35
  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/tray.d.ts +1 -1
  51. package/build/desktop/tray.d.ts.map +1 -1
  52. package/build/desktop/tray.js +2 -7
  53. package/build/desktop/tray.js.map +1 -1
  54. package/build/desktop/trayMenu.d.ts +23 -2
  55. package/build/desktop/trayMenu.d.ts.map +1 -1
  56. package/build/desktop/trayMenu.js +24 -30
  57. package/build/desktop/trayMenu.js.map +1 -1
  58. package/build/desktop/updateDialog.d.ts +66 -0
  59. package/build/desktop/updateDialog.d.ts.map +1 -0
  60. package/build/desktop/updateDialog.js +258 -0
  61. package/build/desktop/updateDialog.js.map +1 -0
  62. package/build/desktop/updaterAdapter.d.ts +1 -0
  63. package/build/desktop/updaterAdapter.d.ts.map +1 -1
  64. package/build/desktop/updaterAdapter.js +13 -1
  65. package/build/desktop/updaterAdapter.js.map +1 -1
  66. package/build/renderer/assets/{ActiveSessionPermissionChip-Dl2UOFgh.js → ActiveSessionPermissionChip-CAgN-tXv.js} +1 -1
  67. package/build/renderer/assets/App-BZA23O2J.js +2 -0
  68. package/build/renderer/assets/App-DxsV-tKS.css +1 -0
  69. package/build/renderer/assets/{App-ChvP0G9X.js → App-YqprEL2n.js} +1 -1
  70. package/build/renderer/assets/App-rGw9J8PZ.js +1 -0
  71. package/build/renderer/assets/WorkspaceAppRoutes-BCHCikmJ.js +1 -0
  72. package/build/renderer/assets/app-BV3UAQkR.css +1 -0
  73. package/build/renderer/assets/app-CVPqqfZo.js +45 -0
  74. package/build/renderer/assets/conversationSidebarRecentEntries-iqaLqA1n.js +6 -0
  75. package/build/renderer/assets/{useDraftSessionChips-By3XXabI.js → useDraftSessionChips-D9BX6X92.js} +1 -1
  76. package/build/renderer/index.html +2 -2
  77. package/build/server/app/renderer/auth/api.d.ts +28 -2
  78. package/build/server/app/renderer/auth/api.d.ts.map +1 -1
  79. package/build/server/app/renderer/auth/api.js +29 -4
  80. package/build/server/app/renderer/auth/api.js.map +1 -1
  81. package/build/server/app/renderer/providerCatalogClient.d.ts.map +1 -1
  82. package/build/server/app/renderer/providerCatalogClient.js +15 -6
  83. package/build/server/app/renderer/providerCatalogClient.js.map +1 -1
  84. package/build/server/app/renderer/providerRegistryClient.d.ts +1 -1
  85. package/build/server/app/renderer/providerRegistryClient.d.ts.map +1 -1
  86. package/build/server/app/renderer/providerRegistryClient.js +23 -41
  87. package/build/server/app/renderer/providerRegistryClient.js.map +1 -1
  88. package/build/server/app/renderer/settings/settingsDesktopUpdateLabels.d.ts +11 -4
  89. package/build/server/app/renderer/settings/settingsDesktopUpdateLabels.d.ts.map +1 -1
  90. package/build/server/app/renderer/settings/settingsDesktopUpdateLabels.js +25 -5
  91. package/build/server/app/renderer/settings/settingsDesktopUpdateLabels.js.map +1 -1
  92. package/build/server/app/server/appPackageRoutes.d.ts +2 -0
  93. package/build/server/app/server/appPackageRoutes.d.ts.map +1 -1
  94. package/build/server/app/server/appPackageRoutes.js +105 -0
  95. package/build/server/app/server/appPackageRoutes.js.map +1 -1
  96. package/build/server/app/server/authGatePolicy.js +8 -3
  97. package/build/server/app/server/authGatePolicy.js.map +1 -1
  98. package/build/server/app/server/authRoutes.d.ts +14 -1
  99. package/build/server/app/server/authRoutes.d.ts.map +1 -1
  100. package/build/server/app/server/authRoutes.js +395 -76
  101. package/build/server/app/server/authRoutes.js.map +1 -1
  102. package/build/server/app/server/contracts.d.ts +19 -1
  103. package/build/server/app/server/contracts.d.ts.map +1 -1
  104. package/build/server/app/server/dependencies.d.ts.map +1 -1
  105. package/build/server/app/server/dependencies.js +48 -2
  106. package/build/server/app/server/dependencies.js.map +1 -1
  107. package/build/server/app/server/goldenPathStartupResume.d.ts +55 -0
  108. package/build/server/app/server/goldenPathStartupResume.d.ts.map +1 -0
  109. package/build/server/app/server/goldenPathStartupResume.js +109 -0
  110. package/build/server/app/server/goldenPathStartupResume.js.map +1 -0
  111. package/build/server/app/server/platformSetupRoutes.d.ts +2 -1
  112. package/build/server/app/server/platformSetupRoutes.d.ts.map +1 -1
  113. package/build/server/app/server/platformSetupRoutes.js +117 -64
  114. package/build/server/app/server/platformSetupRoutes.js.map +1 -1
  115. package/build/server/app/server/polling.d.ts.map +1 -1
  116. package/build/server/app/server/polling.js +2 -0
  117. package/build/server/app/server/polling.js.map +1 -1
  118. package/build/server/app/server/requestRouter.d.ts.map +1 -1
  119. package/build/server/app/server/requestRouter.js +33 -0
  120. package/build/server/app/server/requestRouter.js.map +1 -1
  121. package/build/server/app/server/runtimeSurfaceProxy.d.ts.map +1 -1
  122. package/build/server/app/server/runtimeSurfaceProxy.js +16 -19
  123. package/build/server/app/server/runtimeSurfaceProxy.js.map +1 -1
  124. package/build/server/app/server/startupRecovery.d.ts.map +1 -1
  125. package/build/server/app/server/startupRecovery.js +5 -0
  126. package/build/server/app/server/startupRecovery.js.map +1 -1
  127. package/build/server/app/server/telegramCommandSurface.d.ts +29 -0
  128. package/build/server/app/server/telegramCommandSurface.d.ts.map +1 -0
  129. package/build/server/app/server/telegramCommandSurface.js +123 -0
  130. package/build/server/app/server/telegramCommandSurface.js.map +1 -0
  131. package/build/server/app/server/transportWorkGoldenPath.d.ts +82 -0
  132. package/build/server/app/server/transportWorkGoldenPath.d.ts.map +1 -0
  133. package/build/server/app/server/transportWorkGoldenPath.js +307 -0
  134. package/build/server/app/server/transportWorkGoldenPath.js.map +1 -0
  135. package/build/server/config.d.ts +22 -3
  136. package/build/server/config.d.ts.map +1 -1
  137. package/build/server/config.js +14 -13
  138. package/build/server/config.js.map +1 -1
  139. package/build/server/design/components/providerModelFieldsSupport.d.ts +3 -3
  140. package/build/server/design/components/providerModelFieldsSupport.d.ts.map +1 -1
  141. package/build/server/design/components/providerModelFieldsSupport.js +40 -38
  142. package/build/server/design/components/providerModelFieldsSupport.js.map +1 -1
  143. package/build/server/design/components/useProviderCatalogState.d.ts +1 -0
  144. package/build/server/design/components/useProviderCatalogState.d.ts.map +1 -1
  145. package/build/server/design/components/useProviderCatalogState.js +1 -0
  146. package/build/server/design/components/useProviderCatalogState.js.map +1 -1
  147. package/build/server/design/components/useProviderRegistryAutoRecheck.d.ts.map +1 -1
  148. package/build/server/design/components/useProviderRegistryAutoRecheck.js +20 -13
  149. package/build/server/design/components/useProviderRegistryAutoRecheck.js.map +1 -1
  150. package/build/server/design/components/useProviderRegistryState.d.ts.map +1 -1
  151. package/build/server/design/components/useProviderRegistryState.js +12 -25
  152. package/build/server/design/components/useProviderRegistryState.js.map +1 -1
  153. package/build/server/design/components/useProviderTargetReconciliation.d.ts.map +1 -1
  154. package/build/server/design/components/useProviderTargetReconciliation.js +5 -2
  155. package/build/server/design/components/useProviderTargetReconciliation.js.map +1 -1
  156. package/build/server/index.js +4 -0
  157. package/build/server/index.js.map +1 -1
  158. package/build/server/platform/apps/packageInstaller.d.ts +19 -0
  159. package/build/server/platform/apps/packageInstaller.d.ts.map +1 -0
  160. package/build/server/platform/apps/packageInstaller.js +92 -0
  161. package/build/server/platform/apps/packageInstaller.js.map +1 -0
  162. package/build/server/platform/apps/registry.d.ts +6 -0
  163. package/build/server/platform/apps/registry.d.ts.map +1 -1
  164. package/build/server/platform/apps/registry.js +24 -0
  165. package/build/server/platform/apps/registry.js.map +1 -1
  166. package/build/server/platform/apps/renderer.d.ts +6 -0
  167. package/build/server/platform/apps/renderer.d.ts.map +1 -0
  168. package/build/server/platform/apps/renderer.js +18 -0
  169. package/build/server/platform/apps/renderer.js.map +1 -0
  170. package/build/server/platform/auth/actionGrant.d.ts +61 -0
  171. package/build/server/platform/auth/actionGrant.d.ts.map +1 -0
  172. package/build/server/platform/auth/actionGrant.js +108 -0
  173. package/build/server/platform/auth/actionGrant.js.map +1 -0
  174. package/build/server/platform/auth/adminCredentials.d.ts +37 -0
  175. package/build/server/platform/auth/adminCredentials.d.ts.map +1 -0
  176. package/build/server/platform/auth/adminCredentials.js +63 -0
  177. package/build/server/platform/auth/adminCredentials.js.map +1 -0
  178. package/build/server/platform/auth/bootstrap.d.ts +14 -0
  179. package/build/server/platform/auth/bootstrap.d.ts.map +1 -1
  180. package/build/server/platform/auth/bootstrap.js +29 -4
  181. package/build/server/platform/auth/bootstrap.js.map +1 -1
  182. package/build/server/platform/auth/config.d.ts.map +1 -1
  183. package/build/server/platform/auth/config.js +1 -1
  184. package/build/server/platform/auth/config.js.map +1 -1
  185. package/build/server/platform/auth/errorCodes.d.ts +2 -0
  186. package/build/server/platform/auth/errorCodes.d.ts.map +1 -1
  187. package/build/server/platform/auth/errorCodes.js +2 -0
  188. package/build/server/platform/auth/errorCodes.js.map +1 -1
  189. package/build/server/platform/auth/googleAccount.d.ts +40 -13
  190. package/build/server/platform/auth/googleAccount.d.ts.map +1 -1
  191. package/build/server/platform/auth/googleAccount.js +89 -70
  192. package/build/server/platform/auth/googleAccount.js.map +1 -1
  193. package/build/server/platform/auth/index.d.ts +4 -0
  194. package/build/server/platform/auth/index.d.ts.map +1 -1
  195. package/build/server/platform/auth/index.js +4 -0
  196. package/build/server/platform/auth/index.js.map +1 -1
  197. package/build/server/platform/auth/localLogin.d.ts +10 -0
  198. package/build/server/platform/auth/localLogin.d.ts.map +1 -1
  199. package/build/server/platform/auth/localLogin.js +17 -0
  200. package/build/server/platform/auth/localLogin.js.map +1 -1
  201. package/build/server/platform/auth/loginMethods.d.ts +18 -0
  202. package/build/server/platform/auth/loginMethods.d.ts.map +1 -0
  203. package/build/server/platform/auth/loginMethods.js +19 -0
  204. package/build/server/platform/auth/loginMethods.js.map +1 -0
  205. package/build/server/platform/auth/securityEvents.d.ts +31 -0
  206. package/build/server/platform/auth/securityEvents.d.ts.map +1 -0
  207. package/build/server/platform/auth/securityEvents.js +45 -0
  208. package/build/server/platform/auth/securityEvents.js.map +1 -0
  209. package/build/server/platform/runtime/deliveryClient.d.ts +111 -0
  210. package/build/server/platform/runtime/deliveryClient.d.ts.map +1 -0
  211. package/build/server/platform/runtime/deliveryClient.js +289 -0
  212. package/build/server/platform/runtime/deliveryClient.js.map +1 -0
  213. package/build/server/platform/supervision/providerCapabilityBootstrapYaml.d.ts +1 -0
  214. package/build/server/platform/supervision/providerCapabilityBootstrapYaml.d.ts.map +1 -1
  215. package/build/server/platform/supervision/providerCapabilityBootstrapYaml.js +10 -0
  216. package/build/server/platform/supervision/providerCapabilityBootstrapYaml.js.map +1 -1
  217. package/build/server/platform/supervision/runtimeBoundary.d.ts +11 -1
  218. package/build/server/platform/supervision/runtimeBoundary.d.ts.map +1 -1
  219. package/build/server/platform/supervision/runtimeBoundary.js +2 -2
  220. package/build/server/platform/supervision/runtimeBoundary.js.map +1 -1
  221. package/build/server/platform/transports/telegram/bridge.d.ts +18 -0
  222. package/build/server/platform/transports/telegram/bridge.d.ts.map +1 -1
  223. package/build/server/platform/transports/telegram/bridge.js +176 -0
  224. package/build/server/platform/transports/telegram/bridge.js.map +1 -1
  225. package/build/server/platform/transports/telegram/commandPort.d.ts +40 -0
  226. package/build/server/platform/transports/telegram/commandPort.d.ts.map +1 -0
  227. package/build/server/platform/transports/telegram/commandPort.js +17 -0
  228. package/build/server/platform/transports/telegram/commandPort.js.map +1 -0
  229. package/build/server/platform/transports/telegram/commandRouter.d.ts +22 -0
  230. package/build/server/platform/transports/telegram/commandRouter.d.ts.map +1 -1
  231. package/build/server/platform/transports/telegram/commandRouter.js.map +1 -1
  232. package/build/server/platform/transports/telegram/commands/index.d.ts.map +1 -1
  233. package/build/server/platform/transports/telegram/commands/index.js +38 -0
  234. package/build/server/platform/transports/telegram/commands/index.js.map +1 -1
  235. package/build/server/platform/transports/telegram/ingressDispatch.d.ts +56 -0
  236. package/build/server/platform/transports/telegram/ingressDispatch.d.ts.map +1 -0
  237. package/build/server/platform/transports/telegram/ingressDispatch.js +93 -0
  238. package/build/server/platform/transports/telegram/ingressDispatch.js.map +1 -0
  239. package/build/server/platform/transports/telegram/polling.d.ts +34 -0
  240. package/build/server/platform/transports/telegram/polling.d.ts.map +1 -1
  241. package/build/server/platform/transports/telegram/polling.js +86 -9
  242. package/build/server/platform/transports/telegram/polling.js.map +1 -1
  243. package/build/server/platform/transports/telegram/relay/index.d.ts +3 -0
  244. package/build/server/platform/transports/telegram/relay/index.d.ts.map +1 -1
  245. package/build/server/platform/transports/telegram/relay/index.js +5 -1
  246. package/build/server/platform/transports/telegram/relay/index.js.map +1 -1
  247. package/build/server/platform/transports/telegram/relay/ingress.d.ts +2 -0
  248. package/build/server/platform/transports/telegram/relay/ingress.d.ts.map +1 -1
  249. package/build/server/platform/transports/telegram/relay/ingress.js +1 -1
  250. package/build/server/platform/transports/telegram/relay/ingress.js.map +1 -1
  251. package/build/server/platform/transports/work-delivery/actionTokens.d.ts +66 -0
  252. package/build/server/platform/transports/work-delivery/actionTokens.d.ts.map +1 -0
  253. package/build/server/platform/transports/work-delivery/actionTokens.js +145 -0
  254. package/build/server/platform/transports/work-delivery/actionTokens.js.map +1 -0
  255. package/build/server/platform/transports/work-delivery/contracts.d.ts +172 -0
  256. package/build/server/platform/transports/work-delivery/contracts.d.ts.map +1 -0
  257. package/build/server/platform/transports/work-delivery/contracts.js +26 -0
  258. package/build/server/platform/transports/work-delivery/contracts.js.map +1 -0
  259. package/build/server/platform/transports/work-delivery/deliveryGates.d.ts +32 -0
  260. package/build/server/platform/transports/work-delivery/deliveryGates.d.ts.map +1 -0
  261. package/build/server/platform/transports/work-delivery/deliveryGates.js +45 -0
  262. package/build/server/platform/transports/work-delivery/deliveryGates.js.map +1 -0
  263. package/build/server/platform/transports/work-delivery/inboundClassification.d.ts +31 -0
  264. package/build/server/platform/transports/work-delivery/inboundClassification.d.ts.map +1 -0
  265. package/build/server/platform/transports/work-delivery/inboundClassification.js +52 -0
  266. package/build/server/platform/transports/work-delivery/inboundClassification.js.map +1 -0
  267. package/build/server/platform/transports/work-delivery/outbox.d.ts +84 -0
  268. package/build/server/platform/transports/work-delivery/outbox.d.ts.map +1 -0
  269. package/build/server/platform/transports/work-delivery/outbox.js +270 -0
  270. package/build/server/platform/transports/work-delivery/outbox.js.map +1 -0
  271. package/build/server/platform/transports/work-delivery/permissionEnvelope.d.ts +57 -0
  272. package/build/server/platform/transports/work-delivery/permissionEnvelope.d.ts.map +1 -0
  273. package/build/server/platform/transports/work-delivery/permissionEnvelope.js +74 -0
  274. package/build/server/platform/transports/work-delivery/permissionEnvelope.js.map +1 -0
  275. package/build/server/platform/transports/work-delivery/port.d.ts +60 -0
  276. package/build/server/platform/transports/work-delivery/port.d.ts.map +1 -0
  277. package/build/server/platform/transports/work-delivery/port.js +15 -0
  278. package/build/server/platform/transports/work-delivery/port.js.map +1 -0
  279. package/build/server/platform/transports/work-delivery/proposal.d.ts +31 -0
  280. package/build/server/platform/transports/work-delivery/proposal.d.ts.map +1 -0
  281. package/build/server/platform/transports/work-delivery/proposal.js +59 -0
  282. package/build/server/platform/transports/work-delivery/proposal.js.map +1 -0
  283. package/build/server/platform/transports/work-delivery/readiness.d.ts +61 -0
  284. package/build/server/platform/transports/work-delivery/readiness.d.ts.map +1 -0
  285. package/build/server/platform/transports/work-delivery/readiness.js +123 -0
  286. package/build/server/platform/transports/work-delivery/readiness.js.map +1 -0
  287. package/build/server/platform/transports/work-delivery/stageProjection.d.ts +43 -0
  288. package/build/server/platform/transports/work-delivery/stageProjection.d.ts.map +1 -0
  289. package/build/server/platform/transports/work-delivery/stageProjection.js +132 -0
  290. package/build/server/platform/transports/work-delivery/stageProjection.js.map +1 -0
  291. package/build/server/platform/transports/work-delivery/stateStore.d.ts +21 -0
  292. package/build/server/platform/transports/work-delivery/stateStore.d.ts.map +1 -0
  293. package/build/server/platform/transports/work-delivery/stateStore.js +193 -0
  294. package/build/server/platform/transports/work-delivery/stateStore.js.map +1 -0
  295. package/build/server/platform/transports/work-delivery/telemetry.d.ts +49 -0
  296. package/build/server/platform/transports/work-delivery/telemetry.d.ts.map +1 -0
  297. package/build/server/platform/transports/work-delivery/telemetry.js +80 -0
  298. package/build/server/platform/transports/work-delivery/telemetry.js.map +1 -0
  299. package/build/server/products/chat/api/contracts.d.ts +10 -8
  300. package/build/server/products/chat/api/contracts.d.ts.map +1 -1
  301. package/build/server/products/chat/api/resources/channelRoutes.d.ts.map +1 -1
  302. package/build/server/products/chat/api/resources/channelRoutes.js +27 -1
  303. package/build/server/products/chat/api/resources/channelRoutes.js.map +1 -1
  304. package/build/server/products/chat/api/routeSupport.d.ts +8 -0
  305. package/build/server/products/chat/api/routeSupport.d.ts.map +1 -1
  306. package/build/server/products/chat/api/routeSupport.js +5 -4
  307. package/build/server/products/chat/api/routeSupport.js.map +1 -1
  308. package/build/server/products/chat/api/setupRoutes.d.ts.map +1 -1
  309. package/build/server/products/chat/api/setupRoutes.js +24 -91
  310. package/build/server/products/chat/api/setupRoutes.js.map +1 -1
  311. package/build/server/products/chat/state/model/channelExecutionTargets.d.ts +15 -0
  312. package/build/server/products/chat/state/model/channelExecutionTargets.d.ts.map +1 -1
  313. package/build/server/products/chat/state/model/channelExecutionTargets.js +25 -0
  314. package/build/server/products/chat/state/model/channelExecutionTargets.js.map +1 -1
  315. package/build/server/products/chat/state/model/index.d.ts +1 -1
  316. package/build/server/products/chat/state/model/index.d.ts.map +1 -1
  317. package/build/server/products/chat/state/model/index.js +1 -1
  318. package/build/server/products/chat/state/model/index.js.map +1 -1
  319. package/build/server/products/code/api/relayRoutes.d.ts.map +1 -1
  320. package/build/server/products/code/api/relayRoutes.js +36 -7
  321. package/build/server/products/code/api/relayRoutes.js.map +1 -1
  322. package/build/server/products/code/state/relayState.d.ts +2 -1
  323. package/build/server/products/code/state/relayState.d.ts.map +1 -1
  324. package/build/server/products/code/state/relayState.js +7 -7
  325. package/build/server/products/code/state/relayState.js.map +1 -1
  326. package/build/server/products/shared/api/workspaceContracts.d.ts +5 -8
  327. package/build/server/products/shared/api/workspaceContracts.d.ts.map +1 -1
  328. package/build/server/products/work/api/goldenPathProjection.d.ts +156 -0
  329. package/build/server/products/work/api/goldenPathProjection.d.ts.map +1 -0
  330. package/build/server/products/work/api/goldenPathProjection.js +252 -0
  331. package/build/server/products/work/api/goldenPathProjection.js.map +1 -0
  332. package/build/server/products/work/api/index.d.ts +54 -1
  333. package/build/server/products/work/api/index.d.ts.map +1 -1
  334. package/build/server/products/work/api/index.js +182 -4
  335. package/build/server/products/work/api/index.js.map +1 -1
  336. package/build/server/products/work/api/projection.d.ts +7 -1
  337. package/build/server/products/work/api/projection.d.ts.map +1 -1
  338. package/build/server/products/work/api/projection.js +7 -1
  339. package/build/server/products/work/api/projection.js.map +1 -1
  340. package/build/server/products/work/shared/apiPaths.d.ts +8 -0
  341. package/build/server/products/work/shared/apiPaths.d.ts.map +1 -1
  342. package/build/server/products/work/shared/apiPaths.js +8 -0
  343. package/build/server/products/work/shared/apiPaths.js.map +1 -1
  344. package/build/server/products/work/shared/workGoldenPathMessages.d.ts +83 -0
  345. package/build/server/products/work/shared/workGoldenPathMessages.d.ts.map +1 -0
  346. package/build/server/products/work/shared/workGoldenPathMessages.js +211 -0
  347. package/build/server/products/work/shared/workGoldenPathMessages.js.map +1 -0
  348. package/build/server/products/work/shared/workGoldenPathMetadata.d.ts +45 -0
  349. package/build/server/products/work/shared/workGoldenPathMetadata.d.ts.map +1 -0
  350. package/build/server/products/work/shared/workGoldenPathMetadata.js +122 -0
  351. package/build/server/products/work/shared/workGoldenPathMetadata.js.map +1 -0
  352. package/build/server/products/work/state/workCompletionEvidence.d.ts +42 -0
  353. package/build/server/products/work/state/workCompletionEvidence.d.ts.map +1 -0
  354. package/build/server/products/work/state/workCompletionEvidence.js +59 -0
  355. package/build/server/products/work/state/workCompletionEvidence.js.map +1 -0
  356. package/build/server/products/work/state/workExecutionTaskDelegate.d.ts +16 -0
  357. package/build/server/products/work/state/workExecutionTaskDelegate.d.ts.map +1 -1
  358. package/build/server/products/work/state/workExecutionTaskDelegate.js +91 -68
  359. package/build/server/products/work/state/workExecutionTaskDelegate.js.map +1 -1
  360. package/build/server/products/work/state/workGoldenPathAdmission.d.ts +78 -0
  361. package/build/server/products/work/state/workGoldenPathAdmission.d.ts.map +1 -0
  362. package/build/server/products/work/state/workGoldenPathAdmission.js +249 -0
  363. package/build/server/products/work/state/workGoldenPathAdmission.js.map +1 -0
  364. package/build/server/products/work/state/workGoldenPathDeliveryEvidence.d.ts +33 -0
  365. package/build/server/products/work/state/workGoldenPathDeliveryEvidence.d.ts.map +1 -0
  366. package/build/server/products/work/state/workGoldenPathDeliveryEvidence.js +161 -0
  367. package/build/server/products/work/state/workGoldenPathDeliveryEvidence.js.map +1 -0
  368. package/build/server/products/work/state/workGoldenPathIntake.d.ts +34 -0
  369. package/build/server/products/work/state/workGoldenPathIntake.d.ts.map +1 -0
  370. package/build/server/products/work/state/workGoldenPathIntake.js +50 -0
  371. package/build/server/products/work/state/workGoldenPathIntake.js.map +1 -0
  372. package/build/server/products/work/state/workGoldenPathLifecycle.d.ts +44 -0
  373. package/build/server/products/work/state/workGoldenPathLifecycle.d.ts.map +1 -0
  374. package/build/server/products/work/state/workGoldenPathLifecycle.js +146 -0
  375. package/build/server/products/work/state/workGoldenPathLifecycle.js.map +1 -0
  376. package/build/server/products/work/state/workGoldenPathPublish.d.ts +84 -0
  377. package/build/server/products/work/state/workGoldenPathPublish.d.ts.map +1 -0
  378. package/build/server/products/work/state/workGoldenPathPublish.js +488 -0
  379. package/build/server/products/work/state/workGoldenPathPublish.js.map +1 -0
  380. package/build/server/products/work/state/workGoldenPathRunner.d.ts +121 -0
  381. package/build/server/products/work/state/workGoldenPathRunner.d.ts.map +1 -0
  382. package/build/server/products/work/state/workGoldenPathRunner.js +447 -0
  383. package/build/server/products/work/state/workGoldenPathRunner.js.map +1 -0
  384. package/build/server/products/work/state/workGoldenPathRuntimeExecutor.d.ts +74 -0
  385. package/build/server/products/work/state/workGoldenPathRuntimeExecutor.d.ts.map +1 -0
  386. package/build/server/products/work/state/workGoldenPathRuntimeExecutor.js +239 -0
  387. package/build/server/products/work/state/workGoldenPathRuntimeExecutor.js.map +1 -0
  388. package/build/server/products/work/state/workGoldenPathService.d.ts +152 -0
  389. package/build/server/products/work/state/workGoldenPathService.d.ts.map +1 -0
  390. package/build/server/products/work/state/workGoldenPathService.js +1057 -0
  391. package/build/server/products/work/state/workGoldenPathService.js.map +1 -0
  392. package/build/server/products/work/state/workGoldenPathTelegramPort.d.ts +87 -0
  393. package/build/server/products/work/state/workGoldenPathTelegramPort.d.ts.map +1 -0
  394. package/build/server/products/work/state/workGoldenPathTelegramPort.js +220 -0
  395. package/build/server/products/work/state/workGoldenPathTelegramPort.js.map +1 -0
  396. package/build/server/runtime/client.d.ts +24 -0
  397. package/build/server/runtime/client.d.ts.map +1 -1
  398. package/build/server/runtime/client.js +62 -1
  399. package/build/server/runtime/client.js.map +1 -1
  400. package/build/server/runtime/setup.d.ts +10 -4
  401. package/build/server/runtime/setup.d.ts.map +1 -1
  402. package/build/server/runtime/setup.js +14 -18
  403. package/build/server/runtime/setup.js.map +1 -1
  404. package/build/server/runtime/usageSnapshot.d.ts +3 -0
  405. package/build/server/runtime/usageSnapshot.d.ts.map +1 -0
  406. package/build/server/runtime/usageSnapshot.js +69 -0
  407. package/build/server/runtime/usageSnapshot.js.map +1 -0
  408. package/build/server/server/routes/providerCapabilityBootstrap.d.ts +69 -0
  409. package/build/server/server/routes/providerCapabilityBootstrap.d.ts.map +1 -0
  410. package/build/server/server/routes/providerCapabilityBootstrap.js +165 -0
  411. package/build/server/server/routes/providerCapabilityBootstrap.js.map +1 -0
  412. package/build/server/server/routes/providers.d.ts.map +1 -1
  413. package/build/server/server/routes/providers.js +112 -81
  414. package/build/server/server/routes/providers.js.map +1 -1
  415. package/build/server/server/routes/telegram.d.ts +9 -0
  416. package/build/server/server/routes/telegram.d.ts.map +1 -1
  417. package/build/server/server/routes/telegram.js +79 -72
  418. package/build/server/server/routes/telegram.js.map +1 -1
  419. package/build/server/shared/catsAppManifest.d.ts +3 -1
  420. package/build/server/shared/catsAppManifest.d.ts.map +1 -1
  421. package/build/server/shared/catsAppManifest.js +2 -0
  422. package/build/server/shared/catsAppManifest.js.map +1 -1
  423. package/build/server/shared/executionLabel.d.ts.map +1 -1
  424. package/build/server/shared/executionLabel.js +8 -1
  425. package/build/server/shared/executionLabel.js.map +1 -1
  426. package/build/server/shared/i18n/catalogs/en.d.ts.map +1 -1
  427. package/build/server/shared/i18n/catalogs/en.js +238 -3
  428. package/build/server/shared/i18n/catalogs/en.js.map +1 -1
  429. package/build/server/shared/i18n/catalogs/zh-TW.d.ts.map +1 -1
  430. package/build/server/shared/i18n/catalogs/zh-TW.js +236 -3
  431. package/build/server/shared/i18n/catalogs/zh-TW.js.map +1 -1
  432. package/build/server/shared/i18n/index.d.ts +231 -0
  433. package/build/server/shared/i18n/index.d.ts.map +1 -1
  434. package/build/server/shared/i18n/messageKeys.d.ts +231 -0
  435. package/build/server/shared/i18n/messageKeys.d.ts.map +1 -1
  436. package/build/server/shared/i18n/messageKeys.js +231 -0
  437. package/build/server/shared/i18n/messageKeys.js.map +1 -1
  438. package/build/server/shared/platformSetupOperation.d.ts +2 -0
  439. package/build/server/shared/platformSetupOperation.d.ts.map +1 -0
  440. package/build/server/shared/platformSetupOperation.js +9 -0
  441. package/build/server/shared/platformSetupOperation.js.map +1 -0
  442. package/build/server/shared/providerCatalog.d.ts +6 -2
  443. package/build/server/shared/providerCatalog.d.ts.map +1 -1
  444. package/build/server/shared/providerCatalog.js +15 -1
  445. package/build/server/shared/providerCatalog.js.map +1 -1
  446. package/build/server/shared/providerCatalogData.d.ts +38 -22
  447. package/build/server/shared/providerCatalogData.d.ts.map +1 -1
  448. package/build/server/shared/providerCatalogData.js +31 -10
  449. package/build/server/shared/providerCatalogData.js.map +1 -1
  450. package/build/server/shared/providerCatalogInstances.d.ts.map +1 -1
  451. package/build/server/shared/providerCatalogInstances.js +6 -0
  452. package/build/server/shared/providerCatalogInstances.js.map +1 -1
  453. package/build/server/shared/providerModelLabelRegistry.d.ts +29 -0
  454. package/build/server/shared/providerModelLabelRegistry.d.ts.map +1 -0
  455. package/build/server/shared/providerModelLabelRegistry.js +49 -0
  456. package/build/server/shared/providerModelLabelRegistry.js.map +1 -0
  457. package/build/server/shared/providerSelection.d.ts.map +1 -1
  458. package/build/server/shared/providerSelection.js +10 -13
  459. package/build/server/shared/providerSelection.js.map +1 -1
  460. package/build/server/shared/runtimeSetup.d.ts +17 -4
  461. package/build/server/shared/runtimeSetup.d.ts.map +1 -1
  462. package/build/server/shared/runtimeStatusPresentation.js +1 -1
  463. package/build/server/shared/runtimeStatusPresentation.js.map +1 -1
  464. package/package.json +23 -1
  465. package/packages/app-sdk/browser.d.ts +51 -0
  466. package/packages/app-sdk/browser.js +48 -0
  467. package/packages/app-sdk/package.d.ts +14 -0
  468. package/packages/app-sdk/package.js +131 -0
  469. package/packages/app-sdk/package.json +7 -0
  470. package/scripts/README.md +73 -26
  471. package/scripts/build-desktop-installer.mjs +15 -0
  472. package/scripts/build-test-ui.mjs +1 -1
  473. package/scripts/bundle-server.mjs +23 -10
  474. package/scripts/linux/build-desktop-package.sh +6 -6
  475. package/scripts/linux/install-antigravity.sh +0 -0
  476. package/scripts/linux/install-devin.sh +0 -0
  477. package/scripts/linux/install-meta-cli.sh +8 -0
  478. package/scripts/linux/node-cli-common.sh +2 -75
  479. package/scripts/linux/provider-cli-common.sh +103 -30
  480. package/scripts/linux/sync-agent-skills.sh +27 -5
  481. package/scripts/linux/test-linux-package-smoke.sh +4 -3
  482. package/scripts/linux/upgrade-cli-tools.sh +1 -1
  483. package/scripts/macos/build-desktop-package.sh +5 -5
  484. package/scripts/macos/install-antigravity.sh +0 -0
  485. package/scripts/macos/install-devin.sh +0 -0
  486. package/scripts/macos/install-meta-cli.sh +8 -0
  487. package/scripts/macos/node-cli-common.sh +2 -75
  488. package/scripts/macos/provider-cli-common.sh +103 -30
  489. package/scripts/macos/sync-agent-skills.sh +27 -5
  490. package/scripts/macos/test-macos-package-smoke.sh +4 -3
  491. package/scripts/macos/upgrade-cli-tools.sh +1 -1
  492. package/scripts/package-desktop.mjs +15 -2
  493. package/scripts/testing/check-usage-app.mts +266 -0
  494. package/scripts/testing/usage-app-smoke-electron.cjs +10 -0
  495. package/scripts/testing/usage-app-smoke-renderer.tsx +8 -0
  496. package/scripts/verify-desktop-app-bundle.mjs +108 -0
  497. package/scripts/windows/Build-DesktopPackage.ps1 +9 -6
  498. package/scripts/windows/Check-WindowsSetupReadiness.ps1 +14 -443
  499. package/scripts/windows/{Install-Aider.ps1 → Install-MetaCli.ps1} +180 -92
  500. package/scripts/windows/Install-Ollama.ps1 +4 -1
  501. package/scripts/windows/Remove-MergedBranches.ps1 +229 -0
  502. package/scripts/windows/Sync-AgentSkills.ps1 +29 -6
  503. package/scripts/windows/Test-WindowsInstallerSmoke.ps1 +2 -1
  504. package/build/desktop/updateNotifications.d.ts +0 -64
  505. package/build/desktop/updateNotifications.d.ts.map +0 -1
  506. package/build/desktop/updateNotifications.js +0 -143
  507. package/build/desktop/updateNotifications.js.map +0 -1
  508. package/build/renderer/assets/App-C57f4p8k.js +0 -2
  509. package/build/renderer/assets/App-CPqGDXVi.js +0 -1
  510. package/build/renderer/assets/App-DGwkRFZl.css +0 -1
  511. package/build/renderer/assets/WorkspaceAppRoutes-DYg2vnjz.js +0 -1
  512. package/build/renderer/assets/app-DVN9Ghrk.js +0 -43
  513. package/build/renderer/assets/app-XnXwkcD2.css +0 -1
  514. package/build/renderer/assets/conversationSidebarRecentEntries-XZVCnMLw.js +0 -6
  515. package/scripts/linux/install-aider.sh +0 -8
  516. package/scripts/macos/install-aider.sh +0 -8
@@ -52,7 +52,7 @@ provider_display_name() {
52
52
  antigravity) printf '%s\n' 'Antigravity CLI' ;;
53
53
  grok) printf '%s\n' 'Grok CLI' ;;
54
54
  devin) printf '%s\n' 'Devin CLI' ;;
55
- aider) printf '%s\n' 'Aider' ;;
55
+ muse) printf '%s\n' 'Meta Muse CLI' ;;
56
56
  claude) printf '%s\n' 'Claude Code CLI' ;;
57
57
  cursor) printf '%s\n' 'Cursor Agent CLI' ;;
58
58
  goose) printf '%s\n' 'Goose CLI' ;;
@@ -67,7 +67,7 @@ provider_primary_command() {
67
67
  antigravity) printf '%s\n' 'agy' ;;
68
68
  grok) printf '%s\n' 'grok' ;;
69
69
  devin) printf '%s\n' 'devin' ;;
70
- aider) printf '%s\n' 'aider' ;;
70
+ muse) printf '%s\n' 'muse' ;;
71
71
  claude) printf '%s\n' 'claude' ;;
72
72
  cursor) printf '%s\n' 'cursor-agent' ;;
73
73
  goose) printf '%s\n' 'goose' ;;
@@ -98,7 +98,7 @@ provider_install_url() {
98
98
  antigravity) printf '%s\n' 'https://antigravity.google/cli/install.sh' ;;
99
99
  grok) printf '%s\n' 'https://x.ai/cli/install.sh' ;;
100
100
  devin) printf '%s\n' 'https://cli.devin.ai/install.sh' ;;
101
- aider) printf '%s\n' 'https://aider.chat/install.sh' ;;
101
+ muse) printf '%s\n' 'https://dev.meta.ai/install.sh' ;;
102
102
  claude) printf '%s\n' 'https://claude.ai/install.sh' ;;
103
103
  cursor) printf '%s\n' 'https://cursor.com/install' ;;
104
104
  goose) printf '%s\n' 'https://github.com/block/goose/releases/download/stable/download_cli.sh' ;;
@@ -111,6 +111,7 @@ provider_install_url() {
111
111
  provider_install_dir() {
112
112
  case "$1" in
113
113
  grok) printf '%s\n' "$HOME/.grok/bin" ;;
114
+ muse) muse_install_dir ;;
114
115
  *) printf '%s\n' "$HOME/.local/bin" ;;
115
116
  esac
116
117
  }
@@ -249,12 +250,59 @@ ensure_provider_alias() {
249
250
  fi
250
251
  }
251
252
 
253
+ # muse's install directory holds the launcher, its state files, and one
254
+ # muse-bin-<version> build per version it has downloaded.
255
+ muse_install_dir() {
256
+ printf '%s\n' "${MUSE_INSTALL_DIR:-$HOME/.local/bin}"
257
+ }
258
+
259
+ # The version comes from the launcher's own state file, never from running muse.
260
+ # The launcher forwards every argument straight to the agent binary, so a flag
261
+ # that binary does not recognise opens the interactive TUI and hangs an
262
+ # unattended setup run forever.
263
+ muse_installed_version() {
264
+ local version_file
265
+ version_file="$(muse_install_dir)/.muse-version"
266
+ if [ -r "$version_file" ]; then
267
+ tr -d '\r\n' < "$version_file"
268
+ fi
269
+ }
270
+
271
+ # "Installed" means the launcher actually fetched a build. The official
272
+ # installer writes the launcher first and downloads muse-bin-<version> last, so
273
+ # a run that dies in between leaves a launcher with nothing behind it. Treating
274
+ # that as installed would skip the reinstall that repairs it.
275
+ muse_install_complete() {
276
+ local dir version
277
+ dir="$(muse_install_dir)"
278
+ [ -x "$dir/muse" ] || return 1
279
+ version="$(muse_installed_version)"
280
+ [ -n "$version" ] || return 1
281
+ [ -x "$dir/muse-bin-$version" ]
282
+ }
283
+
252
284
  detect_provider_command() {
253
285
  local platform="$1"
254
286
  local provider="$2"
255
287
  local primary_command
256
288
  local candidate
257
289
 
290
+ if [ "$provider" = 'muse' ]; then
291
+ if muse_install_complete; then
292
+ prepend_path_if_missing "$(muse_install_dir)"
293
+ printf '%s\n' "$(muse_install_dir)/muse"
294
+ return 0
295
+ fi
296
+ # A muse elsewhere on PATH is someone's own install; report it rather than
297
+ # claiming the tool is missing, but never treat a half-written install
298
+ # directory as one.
299
+ if [ -x "$(muse_install_dir)/muse" ]; then
300
+ return 1
301
+ fi
302
+ command -v muse 2>/dev/null && return 0
303
+ return 1
304
+ fi
305
+
258
306
  primary_command="$(provider_primary_command "$provider")"
259
307
  if command -v "$primary_command" >/dev/null 2>&1; then
260
308
  command -v "$primary_command"
@@ -276,9 +324,36 @@ EOF
276
324
 
277
325
  provider_version_line() {
278
326
  local command_path="$1"
327
+ local provider="${2:-}"
328
+
329
+ # muse is read, never run: see muse_installed_version.
330
+ if [ "$provider" = 'muse' ]; then
331
+ muse_installed_version
332
+ return 0
333
+ fi
334
+
279
335
  "$command_path" --version 2>&1 | head -1 || true
280
336
  }
281
337
 
338
+ # `curl ... | bash` returns 0 when the download itself fails, because bash reads
339
+ # empty input and succeeds. Staging the script first is what makes a failed
340
+ # install report as a failure.
341
+ run_downloaded_shell_installer() {
342
+ local url="$1"
343
+ local installer_path status=0
344
+
345
+ installer_path="$(mktemp)"
346
+ if ! curl -fsSL "$url" -o "$installer_path"; then
347
+ rm -f "$installer_path"
348
+ printf 'Failed to download the installer from %s\n' "$url" >&2
349
+ return 1
350
+ fi
351
+
352
+ bash "$installer_path" < /dev/null || status=$?
353
+ rm -f "$installer_path"
354
+ return "$status"
355
+ }
356
+
282
357
  # Devin's official install.sh ends by launching the interactive `devin setup`
283
358
  # wizard. Packaged setup runs non-interactively with no console a prompt can
284
359
  # reach, so an unstripped installer would stall the step rather than fail.
@@ -342,8 +417,10 @@ run_remote_pipe_installer() {
342
417
  goose)
343
418
  curl -fsSL "$url" | env CONFIGURE=false bash
344
419
  ;;
345
- aider)
346
- curl -LsSf "$url" | sh
420
+ muse)
421
+ # Download first, then run: with `curl ... | bash` a failed download still
422
+ # exits 0, because bash reads empty input and succeeds.
423
+ run_downloaded_shell_installer "$url"
347
424
  ;;
348
425
  cursor)
349
426
  curl "$url" -fsSL | bash
@@ -424,7 +501,9 @@ run_provider_install_action() {
424
501
  devin)
425
502
  run_devin_installer
426
503
  ;;
427
- aider)
504
+ muse)
505
+ # The official installer always refreshes the launcher and asks it to pull
506
+ # the newest build, so install, upgrade, and force are the same call.
428
507
  run_remote_pipe_installer "$provider"
429
508
  ;;
430
509
  claude)
@@ -559,28 +638,22 @@ UPNP_EOF
559
638
  esac
560
639
  fi
561
640
 
562
- # ~/.local/bin/aider is a uv tool shim, not the tool. Removing only the shim
563
- # leaves aider-chat installed in the uv tool environment and the shim
564
- # regenerable by any later `uv tool` command, so the tool is uninstalled
565
- # through uv first and path removal only mops up what uv left behind.
566
- #
567
- # The uv binary itself is deliberately left in place: Aider's installer drops
568
- # its own uv into ~/.local/bin, users commonly have another, and the helper
569
- # cannot tell them apart. Removing a uv the user installed separately is a
570
- # destructive false positive, so this warns instead (SPEC-112 PD4).
571
- if [ "$provider" = 'aider' ]; then
572
- if command -v uv >/dev/null 2>&1; then
573
- if [ "$dry_run" = 'true' ]; then
574
- __CATS_UNINSTALL_PLANNED+=("uv_tool_uninstall:aider-chat")
575
- elif uv tool uninstall aider-chat >/dev/null 2>&1; then
576
- __CATS_UNINSTALL_APPLIED+=("uv_tool_uninstalled:aider-chat")
577
- else
578
- __CATS_UNINSTALL_WARNINGS+=("uv_tool_uninstall_failed:aider-chat")
579
- fi
580
- else
581
- __CATS_UNINSTALL_WARNINGS+=("uv_missing_aider_chat_may_remain")
582
- fi
583
- __CATS_UNINSTALL_WARNINGS+=("bundled_uv_left_in_place_provenance_unknown")
641
+ # The muse launcher is not the tool either: every muse-bin-<version> build it
642
+ # has downloaded, plus its .muse-* state files, sit in the same directory and
643
+ # survive removing the launcher alone. They are named deterministically, so
644
+ # they can be removed without guessing at unrelated files in ~/.local/bin.
645
+ if [ "$provider" = 'muse' ]; then
646
+ local muse_dir muse_leftover
647
+ muse_dir="$(muse_install_dir)"
648
+ for muse_leftover in "$muse_dir"/muse-bin-* "$muse_dir"/.muse-*; do
649
+ case "$muse_leftover" in
650
+ "$HOME"/*)
651
+ if [ -e "$muse_leftover" ] || [ -L "$muse_leftover" ]; then
652
+ planned_paths+=("$muse_leftover")
653
+ fi
654
+ ;;
655
+ esac
656
+ done
584
657
  fi
585
658
 
586
659
  for path in "${planned_paths[@]}"; do
@@ -796,7 +869,7 @@ run_native_provider_installer() {
796
869
 
797
870
  if command_path="$(detect_provider_command "$platform" "$provider")"; then
798
871
  initial_installed='true'
799
- detected_version="$(provider_version_line "$command_path")"
872
+ detected_version="$(provider_version_line "$command_path" "$provider")"
800
873
  if [ "$check_only" = 'true' ]; then
801
874
  if [ "$emit_json" = 'true' ]; then
802
875
  printf '{'
@@ -928,7 +1001,7 @@ run_native_provider_installer() {
928
1001
 
929
1002
  while [ $attempt -le 3 ]; do
930
1003
  if command_path="$(detect_provider_command "$platform" "$provider")"; then
931
- detected_version="$(provider_version_line "$command_path")"
1004
+ detected_version="$(provider_version_line "$command_path" "$provider")"
932
1005
  if [ "$emit_json" = 'true' ]; then
933
1006
  warnings=("Reload your shell if ${display_name} is not visible yet: source ${shell_rc}")
934
1007
  printf '{'
@@ -76,11 +76,33 @@ if [[ -n "$agent" ]]; then
76
76
  fi
77
77
 
78
78
  skill_dirs=()
79
- for entry in "$skills_dir"/*; do
80
- [[ -d "$entry" ]] || continue
81
- [[ -f "$entry/SKILL.md" ]] || continue
82
- skill_dirs+=("$entry")
83
- done
79
+ discover_skills() {
80
+ local entry skill_name existing existing_name
81
+ for entry in "$1"/*; do
82
+ [[ -d "$entry" ]] || continue
83
+ [[ "$entry" != *.bootstrap ]] || continue
84
+ if [[ -L "$entry" ]]; then
85
+ echo "Linked skill directories are not supported: $entry" >&2
86
+ exit 1
87
+ fi
88
+ if [[ -f "$entry/SKILL.md" ]]; then
89
+ skill_name="$(basename "$entry" | tr '[:upper:]' '[:lower:]')"
90
+ # macOS Bash 3.2 treats an empty array as unset under nounset.
91
+ for existing in ${skill_dirs[@]+"${skill_dirs[@]}"}; do
92
+ existing_name="$(basename "$existing" | tr '[:upper:]' '[:lower:]')"
93
+ if [[ "$skill_name" == "$existing_name" ]]; then
94
+ echo "Duplicate skill '$skill_name': $existing and $entry" >&2
95
+ exit 1
96
+ fi
97
+ done
98
+ skill_dirs+=("$entry")
99
+ # Resources inside this package are copied intact, never discovered again.
100
+ else
101
+ discover_skills "$entry"
102
+ fi
103
+ done
104
+ }
105
+ discover_skills "$skills_dir"
84
106
 
85
107
  if [[ ${#skill_dirs[@]} -eq 0 ]]; then
86
108
  echo "No skills found in $skills_dir (no directories with SKILL.md)" >&2
@@ -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
+ }