@nextclaw/ui 0.19.2 → 0.19.3

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 (249) hide show
  1. package/CHANGELOG.md +14 -1
  2. package/dist/assets/{abnfDiagram-VRR7QNED-DvTjgVMf.js → abnfDiagram-VRR7QNED-DrbfiNNF.js} +1 -1
  3. package/dist/assets/{aiden0z-pptx-renderer.es-C1nfBAXR.js → aiden0z-pptx-renderer.es-DdLb2IVc.js} +1 -1
  4. package/dist/assets/{api-BH6Oslx4.js → api-CUSlBpt_.js} +3 -3
  5. package/dist/assets/{appearance-settings-page-zhgfcGgW.js → appearance-settings-page-cTuZdROP.js} +1 -1
  6. package/dist/assets/{arc-BvhODBXv.js → arc-BXlMc9B0.js} +1 -1
  7. package/dist/assets/architecture-TIHT7OUA-Bq0i9WiE.js +1 -0
  8. package/dist/assets/{architectureDiagram-ZJ3FMSHR-BKO9RgNS.js → architectureDiagram-ZJ3FMSHR-DXAJxxO0.js} +1 -1
  9. package/dist/assets/{blockDiagram-677ZJIJ3-DHpDXy7D.js → blockDiagram-677ZJIJ3-i4Kz7zU0.js} +1 -1
  10. package/dist/assets/{book-open-DGTS6oEO.js → book-open-BJ-xAIp9.js} +1 -1
  11. package/dist/assets/{c4Diagram-LMCZKHZV-BG_iQnDr.js → c4Diagram-LMCZKHZV-BDc0TkPd.js} +1 -1
  12. package/dist/assets/channel-iCaZQ87u.js +1 -0
  13. package/dist/assets/{channels-list-page-3D5lhZoT.js → channels-list-page-nRHOasWA.js} +2 -2
  14. package/dist/assets/chunk-2Q5K7J3B-DFQtlnJS.js +1 -0
  15. package/dist/assets/{chunk-32BRIVSS-DR9M0LLx.js → chunk-32BRIVSS-DuReei0Z.js} +1 -1
  16. package/dist/assets/{chunk-52WLFC77-698iC3BB.js → chunk-52WLFC77-D8APq0tm.js} +1 -1
  17. package/dist/assets/{chunk-5FCAYU7R-DikTj9Ey.js → chunk-5FCAYU7R-BsPrNXNS.js} +1 -1
  18. package/dist/assets/{chunk-5HE753X5-ko0o7_q0.js → chunk-5HE753X5-BRtkOPoJ.js} +1 -1
  19. package/dist/assets/{chunk-5JV3BV7I-CEHufhgo.js → chunk-5JV3BV7I-ChPc8e8U.js} +1 -1
  20. package/dist/assets/{chunk-5TONJI2A-CGgno1cu.js → chunk-5TONJI2A-CzTjlJGb.js} +1 -1
  21. package/dist/assets/{chunk-5VM5RSS4-DkiB4cUQ.js → chunk-5VM5RSS4-xsv_22jR.js} +1 -1
  22. package/dist/assets/{chunk-7BUUIJ7U-DzptcytQ.js → chunk-7BUUIJ7U-CwECujme.js} +1 -1
  23. package/dist/assets/{chunk-BIQX33UG-DMRSQJvT.js → chunk-BIQX33UG-DQAm173p.js} +1 -1
  24. package/dist/assets/{chunk-C7G6YPKG-Bw1BwwuY.js → chunk-C7G6YPKG-BkpajeQb.js} +1 -1
  25. package/dist/assets/{chunk-CQNSW5MT-C0z6eHBk.js → chunk-CQNSW5MT-ND65pWRA.js} +1 -1
  26. package/dist/assets/{chunk-CYSBUYHQ-ByPyAouO.js → chunk-CYSBUYHQ-vMu6ijxG.js} +1 -1
  27. package/dist/assets/{chunk-EMLP6XTP-CJlAXWZg.js → chunk-EMLP6XTP-CEaeW3gH.js} +1 -1
  28. package/dist/assets/{chunk-EX3LRPZG-Dqq4zKJu.js → chunk-EX3LRPZG-a4ER-HDr.js} +1 -1
  29. package/dist/assets/{chunk-FWX5IMBZ-B0SNoCmi.js → chunk-FWX5IMBZ-C_8fQssn.js} +2 -2
  30. package/dist/assets/{chunk-HOUHSVGY-DG_GJih_.js → chunk-HOUHSVGY-CEvw-PEd.js} +1 -1
  31. package/dist/assets/{chunk-ICXQ74PX-Drxk_6bE.js → chunk-ICXQ74PX-BEtF0fGY.js} +1 -1
  32. package/dist/assets/{chunk-JG7HCLWE-DdLFPpnd.js → chunk-JG7HCLWE-DGRrVp8-.js} +1 -1
  33. package/dist/assets/{chunk-JWPE2WC7-B8M4G76F.js → chunk-JWPE2WC7-DRqpp_nM.js} +1 -1
  34. package/dist/assets/{chunk-MOJQB5TN-XP6FJHY_.js → chunk-MOJQB5TN-BDEriOXs.js} +1 -1
  35. package/dist/assets/{chunk-MOZMSUNE-C_6x18Qw.js → chunk-MOZMSUNE-JWRNzdnw.js} +1 -1
  36. package/dist/assets/{chunk-OGEWGWER-N25BzCmG.js → chunk-OGEWGWER-DS2VTgCx.js} +1 -1
  37. package/dist/assets/{chunk-OSBZ3O6U-ASDEm7y0.js → chunk-OSBZ3O6U-3LiYTBUB.js} +1 -1
  38. package/dist/assets/{chunk-PUDLZKDR-CTlvAcn7.js → chunk-PUDLZKDR-o9M2s_SO.js} +1 -1
  39. package/dist/assets/{chunk-Q4XR5HBZ-Da9BWfB6.js → chunk-Q4XR5HBZ-DTB7Ma2N.js} +1 -1
  40. package/dist/assets/{chunk-QBLGF6JB-Bi6RpTJO.js → chunk-QBLGF6JB-DpkxZJL5.js} +1 -1
  41. package/dist/assets/{chunk-R7FJI6CG-DkMsSPvK.js → chunk-R7FJI6CG-CRejkHJU.js} +1 -1
  42. package/dist/assets/{chunk-RYQCIY6F-DZp0eU-j.js → chunk-RYQCIY6F-B1boBjLt.js} +1 -1
  43. package/dist/assets/{chunk-U6XO7XAA-vfinDSrj.js → chunk-U6XO7XAA-DgKa97bj.js} +1 -1
  44. package/dist/assets/{chunk-V7JOEXUC-C9Nksccs.js → chunk-V7JOEXUC-DE56eh0N.js} +1 -1
  45. package/dist/assets/chunk-VAUOI2AC-CF9A-TeE.js +1 -0
  46. package/dist/assets/{chunk-VR4S4FIN-Xv6zfwXs.js → chunk-VR4S4FIN-BzomPZq2.js} +1 -1
  47. package/dist/assets/{chunk-WYO6CB5R-mOJNzbWl.js → chunk-WYO6CB5R-C6gy8rSd.js} +2 -2
  48. package/dist/assets/chunk-XXDRQBXY-BRxdfVCU.js +1 -0
  49. package/dist/assets/{chunk-YOTPTUD7-1-aKSu4o.js → chunk-YOTPTUD7-BK98yfl9.js} +1 -1
  50. package/dist/assets/{chunk-ZGVPDNZ5-OJ8veMpK.js → chunk-ZGVPDNZ5-DFXAhwUT.js} +1 -1
  51. package/dist/assets/{chunk-ZIRB5QZD-SR_Nq_PP.js → chunk-ZIRB5QZD-Bbu6BiNC.js} +1 -1
  52. package/dist/assets/classDiagram-OUVF2IWQ-Bo28fPi-.js +1 -0
  53. package/dist/assets/classDiagram-v2-EOCWNBFH-BOVN9wUz.js +1 -0
  54. package/dist/assets/{config-split-page-B55XD_ZY.js → config-split-page-DO1Oyb-r.js} +1 -1
  55. package/dist/assets/{confirm-dialog-BCCreI_f.js → confirm-dialog-CCae9Fr4.js} +1 -1
  56. package/dist/assets/{cose-bilkent-JH36ORCC-NjVgz2Bw.js → cose-bilkent-JH36ORCC-BV8KR4uF.js} +1 -1
  57. package/dist/assets/cynefin-VYW2F7L2-B7rF3JRp.js +1 -0
  58. package/dist/assets/{cynefinDiagram-TSTJHNR4-B_17LDqD.js → cynefinDiagram-TSTJHNR4-Ckd6nU9t.js} +1 -1
  59. package/dist/assets/{dagre-CMe101gk.js → dagre-D_T-FW5i.js} +1 -1
  60. package/dist/assets/{dagre-VKFMJZFB-qo8nLb3B.js → dagre-VKFMJZFB-CyDaQpD4.js} +1 -1
  61. package/dist/assets/desktop-update-config-XSV-DjJW.js +1 -0
  62. package/dist/assets/{diagram-FQU43EPY-Ba3XIklC.js → diagram-FQU43EPY-CghnwS0H.js} +1 -1
  63. package/dist/assets/{diagram-G47NLZAW-CG45TcUx.js → diagram-G47NLZAW-DK4DJ3Kx.js} +1 -1
  64. package/dist/assets/{diagram-NH7WQ7WH-2F2HrwV-.js → diagram-NH7WQ7WH-CUgDkZCJ.js} +1 -1
  65. package/dist/assets/{diagram-OA4YK3LP-CXfWH9NZ.js → diagram-OA4YK3LP-vO2gyH6n.js} +1 -1
  66. package/dist/assets/{diagram-WEI45ONY-CH_4yepc.js → diagram-WEI45ONY-DbSBRDSr.js} +1 -1
  67. package/dist/assets/{dist-IRWcJpfm.js → dist-1N9UpL3c.js} +1 -1
  68. package/dist/assets/{dist-BYSUQaO2.js → dist-C-2H76Cv.js} +1 -1
  69. package/dist/assets/doc-browser-BHFCZIoL.js +1 -0
  70. package/dist/assets/{doc-browser-D8rNrWHk.js → doc-browser-CRlpqMwH.js} +1 -1
  71. package/dist/assets/{doc-browser-context-DjTbIbQc.js → doc-browser-context-C0Bns1J6.js} +1 -1
  72. package/dist/assets/{docx-preview-CoM4JK7_.js → docx-preview-DfxIm9IB.js} +1 -1
  73. package/dist/assets/{ebnfDiagram-CCIWWBDH-BwiG4Ea1.js → ebnfDiagram-CCIWWBDH-W7CAcK7r.js} +1 -1
  74. package/dist/assets/{erDiagram-Q63AITRT-BML3hpnQ.js → erDiagram-Q63AITRT-LA0JWL8-.js} +1 -1
  75. package/dist/assets/eventmodeling-45OFAUF4-DzQLXa3s.js +1 -0
  76. package/dist/assets/flowDiagram-23GEKE2U-C81eexJZ.js +1 -0
  77. package/dist/assets/{form-actions-C8hazgNP.js → form-actions-CMxhPact.js} +1 -1
  78. package/dist/assets/{ganttDiagram-NO4QXBWP-80enfWbD.js → ganttDiagram-NO4QXBWP-_PiTPavJ.js} +1 -1
  79. package/dist/assets/gitGraph-TEB2WS4Q-Dt3ZqpFD.js +1 -0
  80. package/dist/assets/{gitGraphDiagram-IHSO6WYX-CVLqXr-b.js → gitGraphDiagram-IHSO6WYX-DsRB1ZMU.js} +1 -1
  81. package/dist/assets/index-DdYOaKm7.js +109 -0
  82. package/dist/assets/index-DxCGKhAw.css +1 -0
  83. package/dist/assets/info-DKCQHKI2-CCCE7dXC.js +1 -0
  84. package/dist/assets/{infoDiagram-FWYZ7A6U-Dyvs2t0i.js → infoDiagram-FWYZ7A6U-wIRraYx5.js} +1 -1
  85. package/dist/assets/{ishikawaDiagram-FXEZZL3T-sSnxDKfh.js → ishikawaDiagram-FXEZZL3T-CNzsrcrh.js} +1 -1
  86. package/dist/assets/{journeyDiagram-5HDEW3XC-D22V71Mf.js → journeyDiagram-5HDEW3XC-Dy9huHxy.js} +1 -1
  87. package/dist/assets/{kanban-definition-HUTT4EX6-D3ds0p-g.js → kanban-definition-HUTT4EX6-BOCIN365.js} +1 -1
  88. package/dist/assets/{line-CbyFs065.js → line-BxsizOTs.js} +1 -1
  89. package/dist/assets/{linear-4DKtnZBS.js → linear-C_YHf92I.js} +1 -1
  90. package/dist/assets/loader-circle-B-UdXjl4.js +1 -0
  91. package/dist/assets/{map-CcZzEoz6.js → map-CobcjgZ8.js} +1 -1
  92. package/dist/assets/mcp-marketplace-page-BUIGtSda.js +1 -0
  93. package/dist/assets/mcp-marketplace-page-CStb8ml2.js +9 -0
  94. package/dist/assets/{mermaid-parser.core-DPmMOjXD.js → mermaid-parser.core-D7lu2RbA.js} +2 -2
  95. package/dist/assets/{mermaid.core-BSf-ddRa.js → mermaid.core-CbfW2Rk8.js} +3 -3
  96. package/dist/assets/{mindmap-definition-LN4V7U3C-BUTwWPyx.js → mindmap-definition-LN4V7U3C-DUjGXlIC.js} +1 -1
  97. package/dist/assets/model-config-page-BkfUYm95.js +1 -0
  98. package/dist/assets/{navigation-link-kGAcL2N2.js → navigation-link-v3FaWcIr.js} +1 -1
  99. package/dist/assets/{ordinal-BgLYtOZE.js → ordinal-CjoUCHto.js} +1 -1
  100. package/dist/assets/packet-7NZHBO7P-D19yoxFV.js +1 -0
  101. package/dist/assets/{pegDiagram-2B236MQR-BEu_ZBjc.js → pegDiagram-2B236MQR-BQY2DgiP.js} +1 -1
  102. package/dist/assets/pie-RZYD4A2V-hMaJbLrn.js +1 -0
  103. package/dist/assets/{pieDiagram-ENE6RG2P-CAwAwuBd.js → pieDiagram-ENE6RG2P-D18owe4D.js} +1 -1
  104. package/dist/assets/plus-Dw9QFnKr.js +1 -0
  105. package/dist/assets/{privacy-settings-page-v9LTFvJe.js → privacy-settings-page-CYM1Dxwo.js} +1 -1
  106. package/dist/assets/providers-config-page-fxL4I4bz.js +1 -0
  107. package/dist/assets/{quadrantDiagram-ABIIQ3AL-CwE6F-_2.js → quadrantDiagram-ABIIQ3AL-B8F7YoTA.js} +1 -1
  108. package/dist/assets/radar-I7S5WNFK-C8BkvScA.js +1 -0
  109. package/dist/assets/railroad-3IZDKUUU-CozZOitC.js +1 -0
  110. package/dist/assets/railroad-abnf-AHOZXSZD-BqIoFXFi.js +1 -0
  111. package/dist/assets/railroad-ebnf-EBAXGLYW-CD2e3dng.js +1 -0
  112. package/dist/assets/railroad-peg-LSFZ7HO6-DoKlRUOF.js +1 -0
  113. package/dist/assets/{railroadDiagram-RFXS5EU6-xgLekU3B.js → railroadDiagram-RFXS5EU6-RU8GpxN5.js} +1 -1
  114. package/dist/assets/{react-Dwvp5yeX.js → react-Dlz_IxoP.js} +1 -1
  115. package/dist/assets/{refresh-cw-C_oj_h_s.js → refresh-cw-CK4I5UFv.js} +1 -1
  116. package/dist/assets/remote-B0pPgtC6.js +1 -0
  117. package/dist/assets/{requirementDiagram-TGXJPOKE-CyVUzEX5.js → requirementDiagram-TGXJPOKE-ubPOmmNi.js} +1 -1
  118. package/dist/assets/rotate-cw-Z48dmh13.js +1 -0
  119. package/dist/assets/runtime-config-page-C7vksFVD.js +1 -0
  120. package/dist/assets/{sankeyDiagram-HTMAVEWB-JK6bFmYB.js → sankeyDiagram-HTMAVEWB-8L_hXJWW.js} +1 -1
  121. package/dist/assets/{save-BZE6H02N.js → save-Bo37cIFb.js} +1 -1
  122. package/dist/assets/{search-C7Tj40kC.js → search-CZiEm7YD.js} +1 -1
  123. package/dist/assets/search-config-page-DKdEf7m9.js +1 -0
  124. package/dist/assets/{secrets-config-page-B__VLAEQ.js → secrets-config-page-COlMqSfL.js} +2 -2
  125. package/dist/assets/security-config-CitLihXA.js +1 -0
  126. package/dist/assets/{select-fZ5tifar.js → select-BACzapV3.js} +1 -1
  127. package/dist/assets/{sequenceDiagram-DBY2YBRQ-BR5IokXV.js → sequenceDiagram-DBY2YBRQ-Dom6Qor5.js} +1 -1
  128. package/dist/assets/{sizeCapture-X5ZJPWSS-SxG_YnMA.js → sizeCapture-X5ZJPWSS-cZcFSpLJ.js} +1 -1
  129. package/dist/assets/skeleton-B2PCAZJG.js +1 -0
  130. package/dist/assets/{src-vgz8E_-O.js → src-BE9E1xcR.js} +1 -1
  131. package/dist/assets/{stateDiagram-2N3HPSRC-DD4OoYhn.js → stateDiagram-2N3HPSRC-CHrpxmGO.js} +1 -1
  132. package/dist/assets/stateDiagram-v2-6OUMAXLB-b1pZQlDD.js +1 -0
  133. package/dist/assets/{swimlanes-5IMT3BWC-BWkFeyCT.js → swimlanes-5IMT3BWC-D6nJS2xQ.js} +2 -2
  134. package/dist/assets/swimlanesDiagram-G3AALYLV-CowxgWVn.js +8 -0
  135. package/dist/assets/{tag-chip-CwYZcRoe.js → tag-chip-BnamTQVX.js} +1 -1
  136. package/dist/assets/{timeline-definition-FHXFAJF6-VTRPy6KA.js → timeline-definition-FHXFAJF6-DJNn-HQO.js} +1 -1
  137. package/dist/assets/treeView-QDETBFTQ-BQlYkJbz.js +1 -0
  138. package/dist/assets/treemap-6X3UGDF4-DzTOd1bd.js +1 -0
  139. package/dist/assets/{vennDiagram-L72KCM5P-Bvk42Pek.js → vennDiagram-L72KCM5P-CCEzHoXt.js} +1 -1
  140. package/dist/assets/wardley-OPB4EBWU-D80jQc0y.js +1 -0
  141. package/dist/assets/{wardleyDiagram-EHGQE667-DOFjx2s3.js → wardleyDiagram-EHGQE667-BhyVxVXt.js} +1 -1
  142. package/dist/assets/x-BzYEzkLA.js +1 -0
  143. package/dist/assets/{xychartDiagram-FW5EYKEG-DY5yRTUc.js → xychartDiagram-FW5EYKEG-CacW_246.js} +1 -1
  144. package/dist/index.html +70 -22
  145. package/index.html +49 -1
  146. package/package.json +8 -8
  147. package/src/app/index.tsx +1 -3
  148. package/src/app/managers/__tests__/viewport-layout.manager.test.ts +12 -0
  149. package/src/app/managers/viewport-layout.manager.ts +12 -0
  150. package/src/app/stores/viewport-layout.store.ts +23 -11
  151. package/src/features/apps/components/__tests__/app-marketplace-catalog.test.tsx +161 -0
  152. package/src/features/apps/components/app-marketplace-catalog.tsx +36 -7
  153. package/src/features/apps/components/app-marketplace-detail.tsx +29 -6
  154. package/src/features/apps/components/app-marketplace-dialog.tsx +71 -55
  155. package/src/features/apps/components/app-marketplace-operation.tsx +128 -16
  156. package/src/features/apps/components/app-packages-panel.tsx +1 -0
  157. package/src/features/apps/utils/app-marketplace-platform.utils.test.ts +59 -0
  158. package/src/features/apps/utils/app-marketplace-platform.utils.ts +33 -0
  159. package/src/features/chat/features/conversation/components/__tests__/session-conversation-area.test.tsx +6 -0
  160. package/src/features/chat/features/conversation/components/__tests__/session-conversation-input.streaming.test.tsx +6 -2
  161. package/src/features/chat/features/conversation/components/__tests__/session-queued-input-rows.test.tsx +46 -0
  162. package/src/features/chat/features/conversation/components/session-conversation-area.tsx +15 -2
  163. package/src/features/chat/features/conversation/components/session-conversation-input.tsx +5 -3
  164. package/src/features/chat/features/conversation/components/session-queued-input-rows.tsx +59 -5
  165. package/src/features/chat/features/conversation/hooks/__tests__/use-session-conversation-controller.test.tsx +35 -1
  166. package/src/features/chat/features/conversation/hooks/__tests__/use-session-run-queue.test.tsx +25 -19
  167. package/src/features/chat/features/conversation/hooks/use-session-conversation-controller.ts +148 -134
  168. package/src/features/chat/features/conversation/hooks/use-session-pending-input-actions.ts +135 -0
  169. package/src/features/chat/features/conversation/hooks/use-session-run-queue.ts +19 -4
  170. package/src/features/chat/features/conversation/utils/__tests__/session-queued-input.utils.test.ts +52 -2
  171. package/src/features/chat/features/conversation/utils/session-queued-input.utils.ts +46 -5
  172. package/src/features/chat/features/message/utils/chat-message-texts.utils.ts +1 -0
  173. package/src/features/chat/features/ncp/hooks/__tests__/use-hydrated-ncp-agent.test.tsx +102 -0
  174. package/src/features/chat/features/ncp/hooks/__tests__/use-ncp-session-conversation.test.tsx +117 -1
  175. package/src/features/chat/features/ncp/hooks/use-ncp-session-conversation.ts +2 -2
  176. package/src/features/chat/features/ncp/hooks/use-ncp-session-message-history.ts +31 -81
  177. package/src/features/chat/features/ncp/hooks/use-ncp-session-seed-loader.ts +134 -0
  178. package/src/features/chat/features/session/utils/ncp-session-adapter.utils.ts +1 -6
  179. package/src/features/panel-apps/components/__tests__/panel-app-list-item.test.tsx +8 -0
  180. package/src/features/panel-apps/components/__tests__/panel-app-main-sidebar-nav.test.tsx +99 -13
  181. package/src/features/panel-apps/components/panel-app-main-sidebar-menu-item.tsx +4 -0
  182. package/src/features/panel-apps/components/panel-app-main-sidebar-nav.tsx +166 -31
  183. package/src/shared/lib/api/utils/ncp-attachments.utils.ts +8 -1
  184. package/src/shared/lib/api/utils/ncp-session.utils.ts +1 -0
  185. package/src/shared/lib/i18n/locales/en-US/chat.json +3 -0
  186. package/src/shared/lib/i18n/locales/en-US/doc-browser.json +11 -1
  187. package/src/shared/lib/i18n/locales/zh-CN/chat.json +3 -0
  188. package/src/shared/lib/i18n/locales/zh-CN/doc-browser.json +11 -1
  189. package/src/vite-env.d.ts +9 -0
  190. package/dist/assets/architecture-TIHT7OUA-Bjp9jf0h.js +0 -1
  191. package/dist/assets/channel-5T3pdR-s.js +0 -1
  192. package/dist/assets/chat-page-BXu3hnOK.js +0 -1
  193. package/dist/assets/chunk-2Q5K7J3B-DTZ3tGfE.js +0 -1
  194. package/dist/assets/chunk-VAUOI2AC-HLGIHQ6k.js +0 -1
  195. package/dist/assets/chunk-XXDRQBXY-Dl0m6Ni-.js +0 -1
  196. package/dist/assets/classDiagram-OUVF2IWQ-DcDnzGNX.js +0 -1
  197. package/dist/assets/classDiagram-v2-EOCWNBFH-BKXKMzKM.js +0 -1
  198. package/dist/assets/cynefin-VYW2F7L2-BWg7U2UD.js +0 -1
  199. package/dist/assets/desktop-update-config-Blol-Umu.js +0 -1
  200. package/dist/assets/doc-browser-BExPq1Hk.js +0 -1
  201. package/dist/assets/eventmodeling-45OFAUF4-SB-J4tpq.js +0 -1
  202. package/dist/assets/flowDiagram-23GEKE2U-BQ_u-eLM.js +0 -1
  203. package/dist/assets/gitGraph-TEB2WS4Q-DPxNwsFd.js +0 -1
  204. package/dist/assets/index-Btj8yN4T.css +0 -1
  205. package/dist/assets/index-CHcGqqBe.js +0 -109
  206. package/dist/assets/info-DKCQHKI2-DNlNGH90.js +0 -1
  207. package/dist/assets/loader-circle-C75DUmmm.js +0 -1
  208. package/dist/assets/mcp-marketplace-page-CIMRYgOY.js +0 -9
  209. package/dist/assets/mcp-marketplace-page-D2NlhG1k.js +0 -1
  210. package/dist/assets/model-config-page-ChR-ENjp.js +0 -1
  211. package/dist/assets/packet-7NZHBO7P-BpeiqkBZ.js +0 -1
  212. package/dist/assets/pie-RZYD4A2V-Cy1yxsPd.js +0 -1
  213. package/dist/assets/plus-TzSIMKWW.js +0 -1
  214. package/dist/assets/provider-scoped-model-input-DiSpKSk0.js +0 -1
  215. package/dist/assets/providers-config-page-BvXa03cp.js +0 -1
  216. package/dist/assets/radar-I7S5WNFK-CEcPKCj8.js +0 -1
  217. package/dist/assets/railroad-3IZDKUUU-CW38eNDs.js +0 -1
  218. package/dist/assets/railroad-abnf-AHOZXSZD-ByrylcXf.js +0 -1
  219. package/dist/assets/railroad-ebnf-EBAXGLYW-CNB6GwP-.js +0 -1
  220. package/dist/assets/railroad-peg-LSFZ7HO6-x6hnqlBG.js +0 -1
  221. package/dist/assets/remote-BgYduCQR.js +0 -1
  222. package/dist/assets/rotate-cw-BT8HxlcB.js +0 -1
  223. package/dist/assets/runtime-config-page-BuYof2Ty.js +0 -1
  224. package/dist/assets/search-config-page-CQTJOsOf.js +0 -1
  225. package/dist/assets/security-config-CtJqaPVL.js +0 -1
  226. package/dist/assets/settings-2-BHGgNlOH.js +0 -1
  227. package/dist/assets/skeleton-CJLc1CWn.js +0 -1
  228. package/dist/assets/stateDiagram-v2-6OUMAXLB-ZC6dFORv.js +0 -1
  229. package/dist/assets/swimlanesDiagram-G3AALYLV-CRkh51Im.js +0 -8
  230. package/dist/assets/treeView-QDETBFTQ-Bw0DSCH7.js +0 -1
  231. package/dist/assets/treemap-6X3UGDF4-DFWBFcfh.js +0 -1
  232. package/dist/assets/wardley-OPB4EBWU-CoWturk0.js +0 -1
  233. package/dist/assets/x-BMl7cucN.js +0 -1
  234. /package/dist/assets/{array-NADKd9aU.js → array-COEOjKUv.js} +0 -0
  235. /package/dist/assets/{chunk-KEIR6QF5-BuyuzJJL.js → chunk-KEIR6QF5-D7oHAcry.js} +0 -0
  236. /package/dist/assets/{chunk-Y2CYZVJY-D_B2ZRNt.js → chunk-Y2CYZVJY-08IUpgTP.js} +0 -0
  237. /package/dist/assets/{config-hints-BcfVUMij.js → config-hints-BoE41XDI.js} +0 -0
  238. /package/dist/assets/{cytoscape.esm-BANTlgza.js → cytoscape.esm-HifWufkp.js} +0 -0
  239. /package/dist/assets/{defaultLocale-C4_L0aEs.js → defaultLocale-CA-_SsC1.js} +0 -0
  240. /package/dist/assets/{dist-DAPEIJbz.js → dist-C60rvfy8.js} +0 -0
  241. /package/dist/assets/{graphlib-ChqXg0dI.js → graphlib-CGYCNsoJ.js} +0 -0
  242. /package/dist/assets/{host-capabilities-D9C4CBK5.js → host-capabilities-DPNRAjIj.js} +0 -0
  243. /package/dist/assets/{init-D8wZg9xq.js → init-C3plFVsG.js} +0 -0
  244. /package/dist/assets/{jszip.min-CkbBfwAQ.js → jszip.min-CeYs17Gn.js} +0 -0
  245. /package/dist/assets/{katex-TZJFa0J_.js → katex-DRThweSG.js} +0 -0
  246. /package/dist/assets/{middleware-B3k-TSmZ.js → middleware-D05fK5Sb.js} +0 -0
  247. /package/dist/assets/{path-DodfxcX7.js → path-BKtKxQ6Y.js} +0 -0
  248. /package/dist/assets/{rough.esm-CUaa1Rbe.js → rough.esm-DurL7-u7.js} +0 -0
  249. /package/dist/assets/{xlsx-CxByi7bR.js → xlsx-Sg8fZ6nH.js} +0 -0
@@ -0,0 +1,161 @@
1
+ import { fireEvent, render, screen } from '@testing-library/react';
2
+ import { describe, expect, it, vi } from 'vitest';
3
+ import { AppMarketplaceCatalog } from '@/features/apps/components/app-marketplace-catalog';
4
+ import type { AppMarketplaceItemView } from '@/features/apps/types/app-marketplace.types';
5
+ import { Dialog } from '@/shared/components/ui/dialog';
6
+ import { TooltipProvider } from '@/shared/components/ui/tooltip';
7
+ import { setLanguage } from '@/shared/lib/i18n';
8
+
9
+ const LINUX_ONLY_APP: AppMarketplaceItemView = {
10
+ id: 'rust-todo',
11
+ slug: 'rust-todo',
12
+ appId: 'peiiii.rust-todo',
13
+ name: 'Rust Todo',
14
+ summary: '轻量待办应用',
15
+ summaryI18n: {},
16
+ tags: ['todo'],
17
+ latestVersion: '0.1.0',
18
+ featured: false,
19
+ availability: {
20
+ mode: 'targeted',
21
+ targets: ['linux-x64-gnu'],
22
+ operatingSystems: ['linux'],
23
+ },
24
+ publisher: { id: 'peiiii', name: 'peiiii' },
25
+ install: {
26
+ kind: 'registry',
27
+ spec: 'peiiii.rust-todo',
28
+ registry: 'https://apps-registry.nextclaw.io',
29
+ },
30
+ webUrl: 'https://nextclaw.io/apps/rust-todo',
31
+ };
32
+
33
+ describe('AppMarketplaceCatalog compatibility actions', () => {
34
+ it('keeps an incompatible app discoverable but disables installation and hides stale failures', () => {
35
+ setLanguage('zh');
36
+ const onInstall = vi.fn();
37
+ const onSelect = vi.fn();
38
+
39
+ render(
40
+ <TooltipProvider>
41
+ <Dialog>
42
+ <AppMarketplaceCatalog
43
+ error={null}
44
+ filter="all"
45
+ hostTarget={{
46
+ key: 'darwin-arm64',
47
+ operatingSystem: 'darwin',
48
+ architecture: 'arm64',
49
+ }}
50
+ installedById={new Map()}
51
+ isError={false}
52
+ isFetchingNextPage={false}
53
+ isLoading={false}
54
+ isStarting={false}
55
+ items={[LINUX_ONLY_APP]}
56
+ localeFallbacks={['zh-CN']}
57
+ onFilterChange={vi.fn()}
58
+ onInstall={onInstall}
59
+ onLoadMore={vi.fn()}
60
+ onSearchChange={vi.fn()}
61
+ onSelect={onSelect}
62
+ onUpdate={vi.fn()}
63
+ operations={[{
64
+ id: 'failed-install',
65
+ action: 'install',
66
+ appId: 'peiiii.rust-todo',
67
+ source: 'peiiii.rust-todo',
68
+ status: 'failed',
69
+ completedSteps: 0,
70
+ totalSteps: 1,
71
+ createdAt: '2026-08-20T00:00:00.000Z',
72
+ updatedAt: '2026-08-20T00:00:00.000Z',
73
+ error: 'raw registry failure',
74
+ }]}
75
+ hasNextPage={false}
76
+ search=""
77
+ />
78
+ </Dialog>
79
+ </TooltipProvider>,
80
+ );
81
+
82
+ expect(screen.getByText('仅支持 Linux')).toBeTruthy();
83
+ expect(screen.getByText('这台设备无法安装')).toBeTruthy();
84
+ const installButton = screen.getByRole('button', { name: '无法安装' });
85
+ expect((installButton as HTMLButtonElement).disabled).toBe(true);
86
+ expect(screen.queryByText('raw registry failure')).toBeNull();
87
+
88
+ fireEvent.click(installButton);
89
+ expect(onInstall).not.toHaveBeenCalled();
90
+
91
+ fireEvent.click(screen.getAllByRole('button', { name: /Rust Todo/ })[0]);
92
+ expect(onSelect).toHaveBeenCalledWith('rust-todo');
93
+ });
94
+
95
+ it('does not project a persisted terminal failure back into a compatible card', () => {
96
+ setLanguage('zh');
97
+ const onInstall = vi.fn();
98
+
99
+ render(
100
+ <TooltipProvider>
101
+ <Dialog>
102
+ <AppMarketplaceCatalog
103
+ error={null}
104
+ filter="all"
105
+ hostTarget={{
106
+ key: 'darwin-arm64',
107
+ operatingSystem: 'darwin',
108
+ architecture: 'arm64',
109
+ }}
110
+ installedById={new Map()}
111
+ isError={false}
112
+ isFetchingNextPage={false}
113
+ isLoading={false}
114
+ isStarting={false}
115
+ items={[{
116
+ ...LINUX_ONLY_APP,
117
+ availability: {
118
+ mode: 'universal',
119
+ targets: [],
120
+ operatingSystems: [],
121
+ },
122
+ }]}
123
+ localeFallbacks={['zh-CN']}
124
+ onFilterChange={vi.fn()}
125
+ onInstall={onInstall}
126
+ onLoadMore={vi.fn()}
127
+ onSearchChange={vi.fn()}
128
+ onSelect={vi.fn()}
129
+ onUpdate={vi.fn()}
130
+ operations={[{
131
+ id: 'persisted-failure',
132
+ action: 'install',
133
+ appId: 'peiiii.rust-todo',
134
+ source: 'peiiii.rust-todo',
135
+ status: 'failed',
136
+ completedSteps: 0,
137
+ totalSteps: 1,
138
+ createdAt: '2026-08-19T00:00:00.000Z',
139
+ updatedAt: '2026-08-19T00:00:01.000Z',
140
+ completedAt: '2026-08-19T00:00:01.000Z',
141
+ error: 'persisted registry failure',
142
+ }]}
143
+ hasNextPage={false}
144
+ search=""
145
+ />
146
+ </Dialog>
147
+ </TooltipProvider>,
148
+ );
149
+
150
+ expect(screen.queryByText('persisted registry failure')).toBeNull();
151
+ expect(screen.queryByRole('button', { name: '重试' })).toBeNull();
152
+ const installButton = screen.getByRole('button', { name: '安装应用' });
153
+ expect((installButton as HTMLButtonElement).disabled).toBe(false);
154
+
155
+ fireEvent.click(installButton);
156
+ expect(onInstall).toHaveBeenCalledWith(
157
+ 'peiiii.rust-todo',
158
+ 'https://apps-registry.nextclaw.io',
159
+ );
160
+ });
161
+ });
@@ -1,15 +1,21 @@
1
- import type { AppPackageOperationView, AppPackageView } from '@nextclaw/client-sdk';
1
+ import type { AppPackageHostTarget, AppPackageOperationView, AppPackageView } from '@nextclaw/client-sdk';
2
2
  import { ChevronRight, Search, Sparkles } from 'lucide-react';
3
3
  import { AppArtwork } from '@/features/apps/components/app-artwork';
4
4
  import { AppMarketplaceCover } from '@/features/apps/components/app-marketplace-cover';
5
5
  import {
6
6
  findLatestAppPackageOperation,
7
+ MarketplaceCompatibilityBadge,
8
+ MarketplaceCompatibilityStatus,
7
9
  MarketplaceInstallButton,
8
10
  OperationProgress,
11
+ readMarketplaceCompatibilityPresentation,
9
12
  } from '@/features/apps/components/app-marketplace-operation';
10
13
  import { isAppPackageOperationActive } from '@/features/apps/hooks/use-app-packages';
11
14
  import type { AppMarketplaceItemView } from '@/features/apps/types/app-marketplace.types';
12
- import { formatAppMarketplacePlatforms } from '@/features/apps/utils/app-marketplace-platform.utils';
15
+ import {
16
+ formatAppMarketplacePlatforms,
17
+ resolveAppMarketplaceInstallability,
18
+ } from '@/features/apps/utils/app-marketplace-platform.utils';
13
19
  import { pickLocalizedText } from '@/features/marketplace';
14
20
  import {
15
21
  DialogDescription,
@@ -26,6 +32,7 @@ export type MarketplaceFilter = 'all' | 'featured' | 'personal' | 'local';
26
32
  export function AppMarketplaceCatalog({
27
33
  error,
28
34
  filter,
35
+ hostTarget,
29
36
  installedById,
30
37
  isError,
31
38
  isFetchingNextPage,
@@ -46,6 +53,7 @@ export function AppMarketplaceCatalog({
46
53
  }: {
47
54
  error: Error | null;
48
55
  filter: MarketplaceFilter;
56
+ hostTarget?: AppPackageHostTarget;
49
57
  installedById: Map<string, AppPackageView>;
50
58
  isError: boolean;
51
59
  isFetchingNextPage: boolean;
@@ -80,6 +88,7 @@ export function AppMarketplaceCatalog({
80
88
  ) : null}
81
89
  <MarketplaceCatalogContent
82
90
  installedById={installedById}
91
+ hostTarget={hostTarget}
83
92
  isError={isError}
84
93
  isFetchingNextPage={isFetchingNextPage}
85
94
  isLoading={isLoading}
@@ -158,6 +167,7 @@ function MarketplaceCatalogHeader({
158
167
 
159
168
  function MarketplaceCatalogContent({
160
169
  installedById,
170
+ hostTarget,
161
171
  isError,
162
172
  isFetchingNextPage,
163
173
  isLoading,
@@ -173,6 +183,7 @@ function MarketplaceCatalogContent({
173
183
  startingSource,
174
184
  }: {
175
185
  installedById: Map<string, AppPackageView>;
186
+ hostTarget?: AppPackageHostTarget;
176
187
  isError: boolean;
177
188
  isFetchingNextPage: boolean;
178
189
  isLoading: boolean;
@@ -221,6 +232,7 @@ function MarketplaceCatalogContent({
221
232
  <MarketplaceCatalogCard
222
233
  key={item.id}
223
234
  installedPackage={installedById.get(item.appId)}
235
+ hostTarget={hostTarget}
224
236
  isStarting={isStarting && startingSource === item.install.spec}
225
237
  item={item}
226
238
  localeFallbacks={localeFallbacks}
@@ -249,6 +261,7 @@ function MarketplaceCatalogContent({
249
261
 
250
262
  function MarketplaceCatalogCard({
251
263
  installedPackage,
264
+ hostTarget,
252
265
  isStarting,
253
266
  item,
254
267
  localeFallbacks,
@@ -258,6 +271,7 @@ function MarketplaceCatalogCard({
258
271
  operation,
259
272
  }: {
260
273
  installedPackage?: AppPackageView;
274
+ hostTarget?: AppPackageHostTarget;
261
275
  isStarting: boolean;
262
276
  item: AppMarketplaceItemView;
263
277
  localeFallbacks: string[];
@@ -271,10 +285,18 @@ function MarketplaceCatalogCard({
271
285
  : item.name;
272
286
  const summary = pickLocalizedText(item.summaryI18n, item.summary, localeFallbacks);
273
287
  const active = operation ? isAppPackageOperationActive(operation.status) : false;
274
- const failed = operation?.status === 'failed' || operation?.status === 'interrupted';
275
288
  const canUpdate = Boolean(
276
289
  installedPackage && installedPackage.activeVersion !== item.latestVersion,
277
290
  );
291
+ const supportedPlatforms = formatAppMarketplacePlatforms(
292
+ item.availability,
293
+ t('appPackagesAllPlatforms'),
294
+ );
295
+ const compatibility = readMarketplaceCompatibilityPresentation(
296
+ resolveAppMarketplaceInstallability(item.availability, hostTarget),
297
+ supportedPlatforms,
298
+ );
299
+ const blockAction = Boolean(compatibility && (!installedPackage || canUpdate));
278
300
  return (
279
301
  <article className="group relative overflow-hidden rounded-2xl border border-border/60 bg-card shadow-sm transition duration-200 hover:-translate-y-0.5 hover:border-border hover:shadow-lg">
280
302
  <button
@@ -296,32 +318,39 @@ function MarketplaceCatalogCard({
296
318
  <span className="truncate text-sm font-semibold text-foreground">{displayName}</span>
297
319
  {item.featured ? <Sparkles className="h-3.5 w-3.5 shrink-0 text-amber-500" aria-label={t('appPackagesMarketplaceFeatured')} /> : null}
298
320
  </span>
321
+ <MarketplaceCompatibilityBadge presentation={compatibility} />
299
322
  <span className="mt-1 line-clamp-2 block min-h-10 text-xs leading-5 text-muted-foreground">{summary}</span>
300
323
  <span className="mt-2 flex items-center gap-1.5 text-[11px] text-muted-foreground/75">
301
324
  <span>{item.publisher.name}</span>
302
325
  <span aria-hidden="true">·</span>
303
326
  <span>v{item.latestVersion}</span>
304
327
  <span aria-hidden="true">·</span>
305
- <span>{formatAppMarketplacePlatforms(item.availability, t('appPackagesAllPlatforms'))}</span>
328
+ <span>{supportedPlatforms}</span>
306
329
  <ChevronRight className="ml-0.5 h-3 w-3 opacity-0 transition-opacity group-hover:opacity-60" />
307
330
  </span>
308
331
  </button>
309
332
  </div>
310
- <div className="mt-3 flex items-center justify-end border-t border-border/50 pt-3">
333
+ <div className="mt-3 flex items-center justify-between gap-3 border-t border-border/50 pt-3">
334
+ <MarketplaceCompatibilityStatus
335
+ blocked={blockAction}
336
+ presentation={compatibility}
337
+ className="min-w-0 text-[11px] font-medium text-muted-foreground"
338
+ />
311
339
  <MarketplaceInstallButton
312
340
  active={active}
313
341
  canUpdate={canUpdate}
314
- failed={failed}
315
342
  installed={Boolean(installedPackage)}
316
343
  isStarting={isStarting}
317
344
  onAction={() => canUpdate
318
345
  ? onUpdate(item.appId)
319
346
  : onInstall(item.install.spec, item.install.registry)}
320
347
  operation={operation}
348
+ unavailableLabel={blockAction ? compatibility?.actionLabel : undefined}
349
+ unavailableReason={blockAction ? compatibility?.reason : undefined}
321
350
  />
322
351
  </div>
323
352
  </div>
324
- {operation && (active || failed) ? <div className="px-4 pb-4"><OperationProgress operation={operation} /></div> : null}
353
+ {operation && !blockAction && active ? <div className="px-4 pb-4"><OperationProgress operation={operation} /></div> : null}
325
354
  </article>
326
355
  );
327
356
  }
@@ -1,14 +1,20 @@
1
- import type { AppPackageOperationView, AppPackageView } from '@nextclaw/client-sdk';
1
+ import type { AppPackageHostTarget, AppPackageOperationView, AppPackageView } from '@nextclaw/client-sdk';
2
2
  import { ExternalLink, FileText, Monitor, Server, ShieldAlert, ShieldCheck, type LucideIcon } from 'lucide-react';
3
3
  import { AppArtwork } from '@/features/apps/components/app-artwork';
4
4
  import { AppMarketplaceCover } from '@/features/apps/components/app-marketplace-cover';
5
5
  import {
6
+ MarketplaceCompatibilityBadge,
7
+ MarketplaceCompatibilityStatus,
6
8
  MarketplaceInstallButton,
7
9
  OperationProgress,
10
+ readMarketplaceCompatibilityPresentation,
8
11
  } from '@/features/apps/components/app-marketplace-operation';
9
12
  import { isAppPackageOperationActive } from '@/features/apps/hooks/use-app-packages';
10
13
  import type { AppMarketplaceDetailView } from '@/features/apps/types/app-marketplace.types';
11
- import { formatAppMarketplacePlatforms } from '@/features/apps/utils/app-marketplace-platform.utils';
14
+ import {
15
+ formatAppMarketplacePlatforms,
16
+ resolveAppMarketplaceInstallability,
17
+ } from '@/features/apps/utils/app-marketplace-platform.utils';
12
18
  import { pickLocalizedText } from '@/features/marketplace';
13
19
  import { Skeleton } from '@/shared/components/ui/skeleton';
14
20
  import { t } from '@/shared/lib/i18n';
@@ -16,6 +22,7 @@ import { t } from '@/shared/lib/i18n';
16
22
  export function MarketplaceDetail({
17
23
  detail,
18
24
  error,
25
+ hostTarget,
19
26
  installedPackage,
20
27
  isLoading,
21
28
  isStarting,
@@ -26,6 +33,7 @@ export function MarketplaceDetail({
26
33
  }: {
27
34
  detail?: AppMarketplaceDetailView;
28
35
  error: Error | null;
36
+ hostTarget?: AppPackageHostTarget;
29
37
  installedPackage?: AppPackageView;
30
38
  isLoading: boolean;
31
39
  isStarting: boolean;
@@ -43,7 +51,6 @@ export function MarketplaceDetail({
43
51
  const summary = pickLocalizedText(detail.summaryI18n, detail.summary, localeFallbacks);
44
52
  const description = pickLocalizedText(detail.descriptionI18n, detail.description ?? summary, localeFallbacks);
45
53
  const active = operation ? isAppPackageOperationActive(operation.status) : false;
46
- const failed = operation?.status === 'failed' || operation?.status === 'interrupted';
47
54
  const components = detail.manifest.components ?? [];
48
55
  const panelCount = components.filter((entry) => entry.kind === 'panel').length;
49
56
  const serviceCount = components.filter((entry) => entry.kind === 'service').length;
@@ -52,6 +59,15 @@ export function MarketplaceDetail({
52
59
  const canUpdate = Boolean(
53
60
  installedPackage && installedPackage.activeVersion !== detail.latestVersion,
54
61
  );
62
+ const supportedPlatforms = formatAppMarketplacePlatforms(
63
+ detail.availability,
64
+ t('appPackagesAllPlatforms'),
65
+ );
66
+ const compatibility = readMarketplaceCompatibilityPresentation(
67
+ resolveAppMarketplaceInstallability(detail.availability, hostTarget),
68
+ supportedPlatforms,
69
+ );
70
+ const blockAction = Boolean(compatibility && (!installedPackage || canUpdate));
55
71
  return (
56
72
  <div className="mx-auto w-full max-w-3xl px-5 py-5 sm:px-7 sm:py-6">
57
73
  <div className="grid items-stretch gap-5 sm:grid-cols-[minmax(0,1.18fr)_minmax(240px,0.82fr)]">
@@ -61,6 +77,7 @@ export function MarketplaceDetail({
61
77
  <AppArtwork icon={detail.iconUrl ?? installedPackage?.icon} name={detail.name} className="h-14 w-14 rounded-2xl" />
62
78
  <div className="min-w-0 flex-1">
63
79
  <h2 className="text-lg font-semibold tracking-tight text-foreground">{detail.name}</h2>
80
+ <MarketplaceCompatibilityBadge presentation={compatibility} />
64
81
  <div className="mt-1.5 flex flex-wrap items-center gap-2 text-[11px] text-muted-foreground">
65
82
  <span className="inline-flex items-center gap-1"><ShieldCheck className="h-3.5 w-3.5" />{detail.publisher.name}</span>
66
83
  <span>v{detail.latestVersion}</span>
@@ -69,21 +86,27 @@ export function MarketplaceDetail({
69
86
  </div>
70
87
  <p className="mt-3 text-sm leading-6 text-muted-foreground">{summary}</p>
71
88
  <div className="mt-auto pt-4">
89
+ <MarketplaceCompatibilityStatus
90
+ blocked={blockAction}
91
+ presentation={compatibility}
92
+ className="mb-2 text-xs font-medium text-muted-foreground"
93
+ />
72
94
  <MarketplaceInstallButton
73
95
  active={active}
74
96
  canUpdate={canUpdate}
75
- failed={failed}
76
97
  installed={Boolean(installedPackage)}
77
98
  isStarting={isStarting}
78
99
  onAction={() => canUpdate
79
100
  ? onUpdate(detail.appId)
80
101
  : onInstall(detail.install.spec, detail.install.registry)}
81
102
  operation={operation}
103
+ unavailableLabel={blockAction ? compatibility?.actionLabel : undefined}
104
+ unavailableReason={blockAction ? compatibility?.reason : undefined}
82
105
  />
83
106
  </div>
84
107
  </div>
85
108
  </div>
86
- {operation && (active || failed) ? <OperationProgress operation={operation} /> : null}
109
+ {operation && !blockAction && active ? <OperationProgress operation={operation} /> : null}
87
110
 
88
111
  <section className="mt-7">
89
112
  <h3 className="text-sm font-semibold text-foreground">{t('appPackagesAboutApp')}</h3>
@@ -94,7 +117,7 @@ export function MarketplaceDetail({
94
117
  <DetailFact
95
118
  icon={Monitor}
96
119
  label={t('appPackagesPlatformsLabel')}
97
- value={formatAppMarketplacePlatforms(detail.availability, t('appPackagesAllPlatforms'))}
120
+ value={supportedPlatforms}
98
121
  />
99
122
  <DetailFact icon={FileText} label={t('appPackagesPanelsAdded')} value={panelCount > 0 ? String(panelCount) : t('appPackagesNone')} />
100
123
  <DetailFact icon={Server} label={t('appPackagesServicesAdded')} value={serviceCount > 0 ? String(serviceCount) : t('appPackagesNone')} />
@@ -1,5 +1,5 @@
1
1
  import { useEffect, useMemo, useState } from 'react';
2
- import type { AppPackageOperationView, AppPackageView } from '@nextclaw/client-sdk';
2
+ import type { AppPackageHostTarget, AppPackageOperationView, AppPackageView } from '@nextclaw/client-sdk';
3
3
  import { ArrowLeft, ShieldCheck } from 'lucide-react';
4
4
  import {
5
5
  AppMarketplaceCatalog,
@@ -12,10 +12,15 @@ import {
12
12
  useAppMarketplaceDetail,
13
13
  } from '@/features/apps/hooks/use-app-marketplace';
14
14
  import { buildLocaleFallbacks } from '@/features/marketplace';
15
+ import {
16
+ getAppMarketplaceInstallabilityRank,
17
+ resolveAppMarketplaceInstallability,
18
+ } from '@/features/apps/utils/app-marketplace-platform.utils';
15
19
  import {
16
20
  Dialog,
17
21
  DialogContent,
18
22
  } from '@/shared/components/ui/dialog';
23
+ import { TooltipProvider } from '@/shared/components/ui/tooltip';
19
24
  import { getLanguage, t } from '@/shared/lib/i18n';
20
25
 
21
26
  const HIDDEN_ENGINEERING_APPS = new Set([
@@ -25,6 +30,7 @@ const HIDDEN_ENGINEERING_APPS = new Set([
25
30
 
26
31
  export function AppMarketplaceDialog({
27
32
  error,
33
+ hostTarget,
28
34
  installedPackages,
29
35
  isStarting,
30
36
  onInstall,
@@ -35,6 +41,7 @@ export function AppMarketplaceDialog({
35
41
  startingSource,
36
42
  }: {
37
43
  error: Error | null;
44
+ hostTarget?: AppPackageHostTarget;
38
45
  installedPackages: AppPackageView[];
39
46
  isStarting: boolean;
40
47
  onInstall: (source: string, registryUrl: string) => void;
@@ -70,12 +77,17 @@ export function AppMarketplaceDialog({
70
77
  [installedPackages],
71
78
  );
72
79
  const localeFallbacks = buildLocaleFallbacks(getLanguage() === 'zh' ? 'zh-CN' : 'en-US');
73
- const items = useMemo(
74
- () => (marketplace.data?.items ?? []).filter(
75
- (item) => !HIDDEN_ENGINEERING_APPS.has(item.appId),
76
- ),
77
- [marketplace.data?.items],
78
- );
80
+ const items = useMemo(() => (marketplace.data?.items ?? [])
81
+ .filter((item) => !HIDDEN_ENGINEERING_APPS.has(item.appId))
82
+ .map((item, index) => ({
83
+ item,
84
+ index,
85
+ rank: getAppMarketplaceInstallabilityRank(
86
+ resolveAppMarketplaceInstallability(item.availability, hostTarget),
87
+ ),
88
+ }))
89
+ .sort((left, right) => left.rank - right.rank || left.index - right.index)
90
+ .map(({ item }) => item), [hostTarget, marketplace.data?.items]);
79
91
 
80
92
  const closeDialog = (nextOpen: boolean) => {
81
93
  if (!nextOpen) setSelectedSlug(null);
@@ -84,54 +96,58 @@ export function AppMarketplaceDialog({
84
96
 
85
97
  return (
86
98
  <Dialog open={open} onOpenChange={closeDialog}>
87
- <DialogContent className="flex h-dvh w-screen max-w-none flex-col gap-0 overflow-hidden rounded-none border-0 bg-background/95 p-0 shadow-[0_32px_100px_rgba(0,0,0,0.24)] backdrop-blur-xl [&>button.absolute]:top-[max(1rem,env(safe-area-inset-top))] sm:h-[min(680px,calc(100dvh-4rem))] sm:w-[min(920px,calc(100vw-3rem))] sm:max-w-none sm:rounded-2xl sm:border sm:border-border/55">
88
- {selectedSlug ? (
89
- <>
90
- <MarketplaceDetailHeader onBack={() => setSelectedSlug(null)} />
91
- <div className="custom-scrollbar min-h-0 flex-1 overflow-y-auto bg-background">
92
- <MarketplaceDetail
93
- detail={detail.data}
94
- error={detail.error instanceof Error ? detail.error : null}
95
- installedPackage={detail.data ? installedById.get(detail.data.appId) : undefined}
96
- isLoading={detail.isLoading}
97
- isStarting={isStarting && detail.data?.install.spec === startingSource}
98
- localeFallbacks={localeFallbacks}
99
- onInstall={onInstall}
100
- onUpdate={onUpdate}
101
- operation={detail.data
102
- ? findLatestAppPackageOperation(operations, detail.data.appId, detail.data.install.spec)
103
- : undefined}
104
- />
105
- </div>
106
- </>
107
- ) : (
108
- <AppMarketplaceCatalog
109
- error={error}
110
- filter={filter}
111
- installedById={installedById}
112
- isError={marketplace.isError}
113
- isFetchingNextPage={marketplace.isFetchingNextPage}
114
- isLoading={marketplace.isLoading}
115
- isStarting={isStarting}
116
- items={items}
117
- localeFallbacks={localeFallbacks}
118
- onFilterChange={setFilter}
119
- onInstall={onInstall}
120
- onLoadMore={() => void marketplace.fetchNextPage()}
121
- onSearchChange={setSearch}
122
- onSelect={setSelectedSlug}
123
- onUpdate={onUpdate}
124
- operations={operations}
125
- hasNextPage={marketplace.hasNextPage}
126
- search={search}
127
- startingSource={startingSource}
128
- />
129
- )}
130
- <div className="flex items-start gap-2 border-t border-border/60 bg-muted/25 px-5 pb-[max(.75rem,env(safe-area-inset-bottom))] pt-3 text-[11px] leading-4 text-muted-foreground sm:px-6 sm:pb-3">
131
- <ShieldCheck className="mt-0.5 h-3.5 w-3.5 shrink-0" />
132
- <span>{t('appPackagesMarketplaceTrustHint')}</span>
133
- </div>
134
- </DialogContent>
99
+ <TooltipProvider>
100
+ <DialogContent className="flex h-dvh w-screen max-w-none flex-col gap-0 overflow-hidden rounded-none border-0 bg-background/95 p-0 shadow-[0_32px_100px_rgba(0,0,0,0.24)] backdrop-blur-xl [&>button.absolute]:top-[max(1rem,env(safe-area-inset-top))] sm:h-[min(680px,calc(100dvh-4rem))] sm:w-[min(920px,calc(100vw-3rem))] sm:max-w-none sm:rounded-2xl sm:border sm:border-border/55">
101
+ {selectedSlug ? (
102
+ <>
103
+ <MarketplaceDetailHeader onBack={() => setSelectedSlug(null)} />
104
+ <div className="custom-scrollbar min-h-0 flex-1 overflow-y-auto bg-background">
105
+ <MarketplaceDetail
106
+ detail={detail.data}
107
+ error={detail.error instanceof Error ? detail.error : null}
108
+ installedPackage={detail.data ? installedById.get(detail.data.appId) : undefined}
109
+ hostTarget={hostTarget}
110
+ isLoading={detail.isLoading}
111
+ isStarting={isStarting && detail.data?.install.spec === startingSource}
112
+ localeFallbacks={localeFallbacks}
113
+ onInstall={onInstall}
114
+ onUpdate={onUpdate}
115
+ operation={detail.data
116
+ ? findLatestAppPackageOperation(operations, detail.data.appId, detail.data.install.spec)
117
+ : undefined}
118
+ />
119
+ </div>
120
+ </>
121
+ ) : (
122
+ <AppMarketplaceCatalog
123
+ error={error}
124
+ filter={filter}
125
+ installedById={installedById}
126
+ hostTarget={hostTarget}
127
+ isError={marketplace.isError}
128
+ isFetchingNextPage={marketplace.isFetchingNextPage}
129
+ isLoading={marketplace.isLoading}
130
+ isStarting={isStarting}
131
+ items={items}
132
+ localeFallbacks={localeFallbacks}
133
+ onFilterChange={setFilter}
134
+ onInstall={onInstall}
135
+ onLoadMore={() => void marketplace.fetchNextPage()}
136
+ onSearchChange={setSearch}
137
+ onSelect={setSelectedSlug}
138
+ onUpdate={onUpdate}
139
+ operations={operations}
140
+ hasNextPage={marketplace.hasNextPage}
141
+ search={search}
142
+ startingSource={startingSource}
143
+ />
144
+ )}
145
+ <div className="flex items-start gap-2 border-t border-border/60 bg-muted/25 px-5 pb-[max(.75rem,env(safe-area-inset-bottom))] pt-3 text-[11px] leading-4 text-muted-foreground sm:px-6 sm:pb-3">
146
+ <ShieldCheck className="mt-0.5 h-3.5 w-3.5 shrink-0" />
147
+ <span>{t('appPackagesMarketplaceTrustHint')}</span>
148
+ </div>
149
+ </DialogContent>
150
+ </TooltipProvider>
135
151
  </Dialog>
136
152
  );
137
153
  }