@nextclaw/ui 0.26.5 → 0.27.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (433) hide show
  1. package/CHANGELOG.md +82 -0
  2. package/dist/.vite/manifest.json +1342 -1227
  3. package/dist/assets/{abnfDiagram-VRR7QNED-Dcw10Yt1.js → abnfDiagram-VRR7QNED-BT0_ycaq.js} +1 -1
  4. package/dist/assets/account-panel-BVNV8XqM.js +1 -0
  5. package/dist/assets/agents-CfpN8PQc.js +1 -0
  6. package/dist/assets/agents-E4nu-17c.js +1 -0
  7. package/dist/assets/{aiden0z-pptx-renderer.es--oNqetPA.js → aiden0z-pptx-renderer.es-ClCaf_Wh.js} +1 -1
  8. package/dist/assets/api-CI6_8Qt1.js +20 -0
  9. package/dist/assets/app-presenter-provider-2DwHRRle.js +28 -0
  10. package/dist/assets/app-presenter-provider-D3BuuOyZ.css +1 -0
  11. package/dist/assets/appearance-settings-page-Cn9w3F-K.js +1 -0
  12. package/dist/assets/apps-YFlJirpx.js +1 -0
  13. package/dist/assets/{arc-DBRedCax.js → arc-cmSdpq1Z.js} +1 -1
  14. package/dist/assets/architecture-TIHT7OUA-BImoGh10.js +1 -0
  15. package/dist/assets/{architectureDiagram-ZJ3FMSHR-Dufhtuv-.js → architectureDiagram-ZJ3FMSHR-aYglVeoS.js} +1 -1
  16. package/dist/assets/{blockDiagram-677ZJIJ3-BUk0vtJ7.js → blockDiagram-677ZJIJ3-Di_PBl5q.js} +1 -1
  17. package/dist/assets/{book-open-Bcnn2_uV.js → book-open-i_BjUBqL.js} +1 -1
  18. package/dist/assets/{c4Diagram-LMCZKHZV-CxDcVE9p.js → c4Diagram-LMCZKHZV-CfuxybOL.js} +1 -1
  19. package/dist/assets/{card-Cqs73hGI.js → card-DokH7OBp.js} +1 -1
  20. package/dist/assets/channel-BDQry0ob.js +1 -0
  21. package/dist/assets/channels-list-page-B7G9lHUm.js +8 -0
  22. package/dist/assets/chunk-2Q5K7J3B-DkgSFfIy.js +1 -0
  23. package/dist/assets/{chunk-32BRIVSS-DSF3KElA.js → chunk-32BRIVSS-CCGc4qg4.js} +1 -1
  24. package/dist/assets/{chunk-52WLFC77-Costxzr3.js → chunk-52WLFC77-aJoxU2Ow.js} +1 -1
  25. package/dist/assets/{chunk-5FCAYU7R-rhqzGGZo.js → chunk-5FCAYU7R-CGwtZSax.js} +1 -1
  26. package/dist/assets/{chunk-5HE753X5-BsEsmIao.js → chunk-5HE753X5-DqaMSMeS.js} +1 -1
  27. package/dist/assets/{chunk-5JV3BV7I-Dqw_DCoN.js → chunk-5JV3BV7I-DnabINcd.js} +1 -1
  28. package/dist/assets/{chunk-5TONJI2A-Cft82fp8.js → chunk-5TONJI2A-BhpKv1k2.js} +1 -1
  29. package/dist/assets/{chunk-5VM5RSS4-DqNHn9Dl.js → chunk-5VM5RSS4-DvkRPit_.js} +1 -1
  30. package/dist/assets/{chunk-7BUUIJ7U-A5SBEMYY.js → chunk-7BUUIJ7U-CgDQOLnC.js} +1 -1
  31. package/dist/assets/{chunk-BIQX33UG-1Ng3mTrH.js → chunk-BIQX33UG-9FEv5b7T.js} +1 -1
  32. package/dist/assets/{chunk-C7G6YPKG-DRJEy8ZI.js → chunk-C7G6YPKG-CNGFAFYL.js} +1 -1
  33. package/dist/assets/{chunk-CQNSW5MT-Bydv_J3J.js → chunk-CQNSW5MT-DovTZx0M.js} +1 -1
  34. package/dist/assets/{chunk-CYSBUYHQ-HkMIg12u.js → chunk-CYSBUYHQ-DpLEgYa1.js} +1 -1
  35. package/dist/assets/{chunk-EMLP6XTP-C5ndDvm3.js → chunk-EMLP6XTP-D4NuN01W.js} +1 -1
  36. package/dist/assets/{chunk-EX3LRPZG-DzeloZRo.js → chunk-EX3LRPZG-D8Jf4kc2.js} +1 -1
  37. package/dist/assets/{chunk-FWX5IMBZ-n_2_CLTQ.js → chunk-FWX5IMBZ-BdHymAs0.js} +2 -2
  38. package/dist/assets/{chunk-HOUHSVGY-kx_slvu3.js → chunk-HOUHSVGY-Dd_Ycn9Z.js} +1 -1
  39. package/dist/assets/{chunk-ICXQ74PX-sQLMURqL.js → chunk-ICXQ74PX-BRPUu3ff.js} +1 -1
  40. package/dist/assets/{chunk-JG7HCLWE-CMUn5Elc.js → chunk-JG7HCLWE-DnCasQja.js} +1 -1
  41. package/dist/assets/{chunk-JWPE2WC7-Cra3s-Uk.js → chunk-JWPE2WC7-C3CkbEj1.js} +1 -1
  42. package/dist/assets/{chunk-MOJQB5TN-umcrg5Bi.js → chunk-MOJQB5TN-Pi--K4-1.js} +1 -1
  43. package/dist/assets/{chunk-MOZMSUNE-BnljD1ig.js → chunk-MOZMSUNE-3VTspvlh.js} +1 -1
  44. package/dist/assets/{chunk-OGEWGWER-BXx5pQjU.js → chunk-OGEWGWER-BetLLyJt.js} +1 -1
  45. package/dist/assets/{chunk-OSBZ3O6U-D-1qfdWu.js → chunk-OSBZ3O6U-D1VcupAj.js} +1 -1
  46. package/dist/assets/{chunk-PUDLZKDR-DLzX78LC.js → chunk-PUDLZKDR-Cy4G8SjV.js} +1 -1
  47. package/dist/assets/{chunk-Q4XR5HBZ-DTK-rtW6.js → chunk-Q4XR5HBZ-UYxXzi7_.js} +1 -1
  48. package/dist/assets/{chunk-QBLGF6JB-CsFeIGfr.js → chunk-QBLGF6JB-CHiGeRY1.js} +1 -1
  49. package/dist/assets/{chunk-R7FJI6CG-4xNYUeng.js → chunk-R7FJI6CG-C5kVJus8.js} +1 -1
  50. package/dist/assets/{chunk-RYQCIY6F-DJiHiTE5.js → chunk-RYQCIY6F-C6cuuEBn.js} +1 -1
  51. package/dist/assets/{chunk-U6XO7XAA-BVYkauHz.js → chunk-U6XO7XAA-CM0EK7Y0.js} +1 -1
  52. package/dist/assets/{chunk-V7JOEXUC-BsazE8cS.js → chunk-V7JOEXUC-DWJZIsME.js} +1 -1
  53. package/dist/assets/chunk-VAUOI2AC-CsTIB8qD.js +1 -0
  54. package/dist/assets/{chunk-VR4S4FIN-7RoZQffO.js → chunk-VR4S4FIN-CY5KYeEi.js} +1 -1
  55. package/dist/assets/{chunk-WYO6CB5R-DEuS6N1R.js → chunk-WYO6CB5R-B30N3ZP8.js} +3 -3
  56. package/dist/assets/chunk-XXDRQBXY-DK6dz0Q3.js +1 -0
  57. package/dist/assets/{chunk-YOTPTUD7-9KBrosZL.js → chunk-YOTPTUD7-CBu82JpO.js} +1 -1
  58. package/dist/assets/{chunk-ZGVPDNZ5-IYgN9f5A.js → chunk-ZGVPDNZ5-BN5NX5qA.js} +1 -1
  59. package/dist/assets/{chunk-ZIRB5QZD-BUo0-zcp.js → chunk-ZIRB5QZD-DcDXK29L.js} +1 -1
  60. package/dist/assets/{circle-dashed-EY1ScSMe.js → circle-dashed-Cx8CIEbg.js} +1 -1
  61. package/dist/assets/classDiagram-OUVF2IWQ-BYygHCrp.js +1 -0
  62. package/dist/assets/classDiagram-v2-EOCWNBFH-BgQ0XKYz.js +1 -0
  63. package/dist/assets/{client-CH7w6yRV.js → client-CUJUci3r.js} +1 -1
  64. package/dist/assets/config-split-page-hY1xug28.js +1 -0
  65. package/dist/assets/confirm-dialog-B-ejV666.js +1 -0
  66. package/dist/assets/{app-presenter-provider-jNGlmBLe.css → context-menu-DEcVZfaU.css} +1 -1
  67. package/dist/assets/context-menu-dGVv8klA.js +211 -0
  68. package/dist/assets/{cose-bilkent-JH36ORCC-DhqbC1fR.js → cose-bilkent-JH36ORCC-CmeJVoTw.js} +1 -1
  69. package/dist/assets/{createLucideIcon-Cfo2ySi5.js → createLucideIcon-reFMl-W-.js} +1 -1
  70. package/dist/assets/cron-CH5c55CR.js +1 -0
  71. package/dist/assets/cynefin-VYW2F7L2-DKbotNWS.js +1 -0
  72. package/dist/assets/{cynefinDiagram-TSTJHNR4-C-TBRi5V.js → cynefinDiagram-TSTJHNR4-DGOUMgPP.js} +1 -1
  73. package/dist/assets/{dagre-CrgsRasE.js → dagre-CMxSkbJJ.js} +1 -1
  74. package/dist/assets/{dagre-VKFMJZFB-BmafJymp.js → dagre-VKFMJZFB-3YUBEXwo.js} +1 -1
  75. package/dist/assets/{desktop-capabilities-page-BDYITStl.js → desktop-capabilities-page-CYJTQ3nC.js} +1 -1
  76. package/dist/assets/desktop-update-config-guKAozXO.js +1 -0
  77. package/dist/assets/{diagram-FQU43EPY-BoOMwa6D.js → diagram-FQU43EPY-Br1g--ww.js} +1 -1
  78. package/dist/assets/{diagram-G47NLZAW-Le7N6Uym.js → diagram-G47NLZAW-D1wJCBgr.js} +1 -1
  79. package/dist/assets/{diagram-NH7WQ7WH-Fbpj3-MO.js → diagram-NH7WQ7WH-Cgg2auLH.js} +1 -1
  80. package/dist/assets/{diagram-OA4YK3LP-D3QuGGuu.js → diagram-OA4YK3LP-R-wHiWqh.js} +1 -1
  81. package/dist/assets/{diagram-WEI45ONY-Cxu1uiN6.js → diagram-WEI45ONY-CsNnKV0P.js} +1 -1
  82. package/dist/assets/dialog-DLOwdjT1.js +1 -0
  83. package/dist/assets/dist-ZaFFmAGl.js +41 -0
  84. package/dist/assets/doc-browser-ClDUWo9V.js +1 -0
  85. package/dist/assets/doc-browser-context-CTmOmuqa.js +1 -0
  86. package/dist/assets/{docx-preview-CkU2psnd.js → docx-preview-kPn_EtAr.js} +1 -1
  87. package/dist/assets/{download-BoaKzDJk.js → download-DovI3Yvf.js} +1 -1
  88. package/dist/assets/{ebnfDiagram-CCIWWBDH-CCAjuQM6.js → ebnfDiagram-CCIWWBDH-DCyhIPdi.js} +1 -1
  89. package/dist/assets/{erDiagram-Q63AITRT-BuzUAq-d.js → erDiagram-Q63AITRT-D0ZJYAUf.js} +1 -1
  90. package/dist/assets/eventmodeling-45OFAUF4-SIhbIFIw.js +1 -0
  91. package/dist/assets/extensions-BZ3qrM8M.js +1 -0
  92. package/dist/assets/external-link-DUD3AbsF.js +1 -0
  93. package/dist/assets/flowDiagram-23GEKE2U-DdAjkU7I.js +1 -0
  94. package/dist/assets/{form-actions-D9JWSFQu.js → form-actions-B8VniHts.js} +1 -1
  95. package/dist/assets/{ganttDiagram-NO4QXBWP-cJmWVY8F.js → ganttDiagram-NO4QXBWP-CiXDcXZD.js} +1 -1
  96. package/dist/assets/gitGraph-TEB2WS4Q-DnMNpESZ.js +1 -0
  97. package/dist/assets/{gitGraphDiagram-IHSO6WYX-F58o-vtP.js → gitGraphDiagram-IHSO6WYX-BSiIV48S.js} +1 -1
  98. package/dist/assets/{i18n-Bm3Ov7Fy.js → i18n-IGQbjBqS.js} +2 -2
  99. package/dist/assets/inbox-BjBZIbgx.js +1 -0
  100. package/dist/assets/inbox-ClAG7SI_.js +1 -0
  101. package/dist/assets/info-DKCQHKI2-BSm-69p_.js +1 -0
  102. package/dist/assets/{infoDiagram-FWYZ7A6U-Gt59b83C.js → infoDiagram-FWYZ7A6U-CCIgBCVq.js} +1 -1
  103. package/dist/assets/{ishikawaDiagram-FXEZZL3T-1u4IAj1I.js → ishikawaDiagram-FXEZZL3T-nQ_baN5u.js} +1 -1
  104. package/dist/assets/{journeyDiagram-5HDEW3XC-CCQsfV-5.js → journeyDiagram-5HDEW3XC-ABueIPzj.js} +1 -1
  105. package/dist/assets/{kanban-definition-HUTT4EX6-vlB6O_Zn.js → kanban-definition-HUTT4EX6-8FKS3fmQ.js} +1 -1
  106. package/dist/assets/katex-DPgHtix3.js +1 -0
  107. package/dist/assets/keyboard-shortcuts-settings-page-BqfbbKir.js +1 -0
  108. package/dist/assets/{line-D_bHubTL.js → line-Biw8iEUz.js} +1 -1
  109. package/dist/assets/{linear-ChlwuS5y.js → linear-D7CWUHTF.js} +1 -1
  110. package/dist/assets/login-page-BxSMwUsc.js +1 -0
  111. package/dist/assets/{login-page-C-DvcG3L.js → login-page-DYaozpzz.js} +1 -1
  112. package/dist/assets/main-CWYF9QU_.js +2 -0
  113. package/dist/assets/main-D_zmSVS1.css +1 -0
  114. package/dist/assets/main-i18n-catalog.config-itg3Gvzp.js +1 -0
  115. package/dist/assets/{map-oGHTsIu8.js → map-CDu47gTf.js} +1 -1
  116. package/dist/assets/marketplace-CnQ5USfr.js +1 -0
  117. package/dist/assets/mcp-marketplace-page-Dor6H9IC.js +1 -0
  118. package/dist/assets/{mermaid-parser.core-CuRe1ZG4.js → mermaid-parser.core-Cc9wjl82.js} +2 -2
  119. package/dist/assets/{mermaid.core-u4YCFKRf.js → mermaid.core-GWlaVWz1.js} +3 -3
  120. package/dist/assets/{mindmap-definition-LN4V7U3C-DeJAQYTu.js → mindmap-definition-LN4V7U3C-oqnKsz-R.js} +1 -1
  121. package/dist/assets/model-config-page-Cduyz2Hy.js +1 -0
  122. package/dist/assets/{navigation-link-CjxNC8aT.js → navigation-link-D-JSWFxj.js} +2 -2
  123. package/dist/assets/{ordinal-C6JFfkKN.js → ordinal-DImbxqBz.js} +1 -1
  124. package/dist/assets/packet-7NZHBO7P-1YQvC6mT.js +1 -0
  125. package/dist/assets/panel-app-BBTg0tVp.js +1 -0
  126. package/dist/assets/panel-app-i18n-catalog.config-BfLHr1tc.js +1 -0
  127. package/dist/assets/panel-apps-C-izvtu9.js +1 -0
  128. package/dist/assets/panelStandalone-XRlWxbRS.css +1 -0
  129. package/dist/assets/panelStandalone-oHxbXvYt.js +2 -0
  130. package/dist/assets/{pegDiagram-2B236MQR-nVMkxShH.js → pegDiagram-2B236MQR-DYAB8CEz.js} +1 -1
  131. package/dist/assets/pie-RZYD4A2V-BGoNOSwu.js +1 -0
  132. package/dist/assets/{pieDiagram-ENE6RG2P-8aUH44QZ.js → pieDiagram-ENE6RG2P-DGsH0Kk5.js} +1 -1
  133. package/dist/assets/plus-DUdl68Eo.js +1 -0
  134. package/dist/assets/privacy-settings-page-DG9E8N-F.js +1 -0
  135. package/dist/assets/projects-CzBaTOTL.js +1 -0
  136. package/dist/assets/provider-models-COzjYl29.js +1 -0
  137. package/dist/assets/provider-scoped-model-input-Cvy74uj8.js +1 -0
  138. package/dist/assets/providers-config-page-7rCwVnhh.js +1 -0
  139. package/dist/assets/puzzle-C5Wfpjk_.js +1 -0
  140. package/dist/assets/pwa-CAg_9zFs.js +1 -0
  141. package/dist/assets/{quadrantDiagram-ABIIQ3AL-EY8hpFv8.js → quadrantDiagram-ABIIQ3AL-BegGcT3l.js} +1 -1
  142. package/dist/assets/radar-I7S5WNFK-uPku9RRq.js +1 -0
  143. package/dist/assets/railroad-3IZDKUUU-DHnmbuIo.js +1 -0
  144. package/dist/assets/railroad-abnf-AHOZXSZD-DiZs--Iw.js +1 -0
  145. package/dist/assets/railroad-ebnf-EBAXGLYW-Nr53gnNE.js +1 -0
  146. package/dist/assets/railroad-peg-LSFZ7HO6-Cm_PuwJS.js +1 -0
  147. package/dist/assets/{railroadDiagram-RFXS5EU6-CNhcIeji.js → railroadDiagram-RFXS5EU6-B3yJ2yxE.js} +1 -1
  148. package/dist/assets/{refresh-cw-BlXDrVP0.js → refresh-cw-OhwaPDn1.js} +1 -1
  149. package/dist/assets/remote-DvCdHjzA.js +1 -0
  150. package/dist/assets/{requirementDiagram-TGXJPOKE-D8Dcs-Rt.js → requirementDiagram-TGXJPOKE-DtEyoEXG.js} +1 -1
  151. package/dist/assets/{rotate-cw-ei6rPD6z.js → rotate-cw-aBponvp7.js} +1 -1
  152. package/dist/assets/runtime-config-page-BF1wxvzR.js +1 -0
  153. package/dist/assets/{sankeyDiagram-HTMAVEWB-HTrb6aa-.js → sankeyDiagram-HTMAVEWB-h9AYS2UB.js} +1 -1
  154. package/dist/assets/{save-DdF-bXgC.js → save-394QCMXn.js} +1 -1
  155. package/dist/assets/search-BG2qAlNZ.js +1 -0
  156. package/dist/assets/search-config-page-D4LeiB9y.js +1 -0
  157. package/dist/assets/secrets-config-page-BzGcr5Vw.js +3 -0
  158. package/dist/assets/security-config-vD_V0BQF.js +1 -0
  159. package/dist/assets/select-xUXYV0Gr.js +1 -0
  160. package/dist/assets/{sequenceDiagram-DBY2YBRQ-6f_4X16Y.js → sequenceDiagram-DBY2YBRQ-D-uxCkob.js} +1 -1
  161. package/dist/assets/service-apps-panel-D3wwPRzV.js +1 -0
  162. package/dist/assets/{settings-2-CrNhfInU.js → settings-2-CWOGRRaA.js} +1 -1
  163. package/dist/assets/{sizeCapture-X5ZJPWSS-Ck9rsuwL.js → sizeCapture-X5ZJPWSS-DBzZytQo.js} +1 -1
  164. package/dist/assets/{src-C8AUg09O.js → src-zrGbZsfc.js} +1 -1
  165. package/dist/assets/{stateDiagram-2N3HPSRC-Cm33MLHu.js → stateDiagram-2N3HPSRC-DyDy7AHq.js} +1 -1
  166. package/dist/assets/stateDiagram-v2-6OUMAXLB-CtkpO6aA.js +1 -0
  167. package/dist/assets/{status-dot-C3SRFEta.js → status-dot-CYifnSnt.js} +1 -1
  168. package/dist/assets/{swimlanes-5IMT3BWC-B107vmvM.js → swimlanes-5IMT3BWC-BzOduS38.js} +2 -2
  169. package/dist/assets/swimlanesDiagram-G3AALYLV-BSdi6mvi.js +8 -0
  170. package/dist/assets/tag-chip-CjM6lyeh.js +1 -0
  171. package/dist/assets/theme-provider-BToFZGZG.js +1 -0
  172. package/dist/assets/{timeline-definition-FHXFAJF6-CJEoAj33.js → timeline-definition-FHXFAJF6-CmgnEF2t.js} +1 -1
  173. package/dist/assets/trash-2-DvJ6duOW.js +1 -0
  174. package/dist/assets/treeView-QDETBFTQ-DBoqypPR.js +1 -0
  175. package/dist/assets/treemap-6X3UGDF4-BMeL3P0q.js +1 -0
  176. package/dist/assets/use-config-COusaY5p.js +1 -0
  177. package/dist/assets/{use-desktop-capabilities-BYDjFlpt.js → use-desktop-capabilities-B-u6ojjW.js} +1 -1
  178. package/dist/assets/use-viewport-layout-IKKGpjzF.js +1 -0
  179. package/dist/assets/{vennDiagram-L72KCM5P-DzsUHk5I.js → vennDiagram-L72KCM5P-DwS7D2kg.js} +1 -1
  180. package/dist/assets/wardley-OPB4EBWU-Dqxe7zN6.js +1 -0
  181. package/dist/assets/{wardleyDiagram-EHGQE667-1NfFs5ua.js → wardleyDiagram-EHGQE667-B4X8OOL4.js} +1 -1
  182. package/dist/assets/x-E9VB4HQx.js +1 -0
  183. package/dist/assets/{xychartDiagram-FW5EYKEG-Ci8AI3Qo.js → xychartDiagram-FW5EYKEG-BjRQ_0nx.js} +1 -1
  184. package/dist/index.html +44 -106
  185. package/dist/panel-standalone.html +19 -13
  186. package/index.html +15 -66
  187. package/package.json +5 -5
  188. package/src/app/styles/design-system.css +85 -1
  189. package/src/app/styles/island-theme.css +8 -6
  190. package/src/features/agents/components/__tests__/agents-page.test.tsx +8 -5
  191. package/src/features/agents/components/agent-details-dialog.tsx +24 -18
  192. package/src/features/agents/components/agents-page.tsx +27 -38
  193. package/src/features/app-data/components/app-retained-data-section.tsx +4 -4
  194. package/src/features/apps/components/__tests__/app-marketplace-catalog.test.tsx +2 -2
  195. package/src/features/apps/components/__tests__/app-packages-panel.test.tsx +94 -23
  196. package/src/features/apps/components/__tests__/apps-panel.test.tsx +5 -3
  197. package/src/features/apps/components/app-document-access-section.tsx +17 -14
  198. package/src/features/apps/components/app-marketplace-catalog.tsx +69 -42
  199. package/src/features/apps/components/app-marketplace-cover.tsx +5 -2
  200. package/src/features/apps/components/app-marketplace-detail.tsx +20 -8
  201. package/src/features/apps/components/app-marketplace-operation.tsx +8 -3
  202. package/src/features/apps/components/app-marketplace-panel.tsx +168 -0
  203. package/src/features/apps/components/app-package-card.tsx +224 -147
  204. package/src/features/apps/components/app-package-details-dialog.tsx +103 -0
  205. package/src/features/apps/components/app-packages-panel.tsx +162 -147
  206. package/src/features/apps/components/apps-panel.tsx +43 -12
  207. package/src/features/chat/components/conversation/chat-conversation-header-section.tsx +1 -1
  208. package/src/features/chat/components/conversation/chat-conversation-header.tsx +1 -1
  209. package/src/features/chat/components/layout/chat-sidebar-toolbar.tsx +2 -2
  210. package/src/features/chat/components/layout/chat-sidebar-utility-menu.tsx +9 -7
  211. package/src/features/chat/components/providers/chat-runtime.provider.tsx +1 -1
  212. package/src/features/chat/features/conversation/components/__tests__/session-conversation-area.test.tsx +0 -1
  213. package/src/features/chat/features/conversation/components/__tests__/session-conversation-input.streaming.test.tsx +13 -2
  214. package/src/features/chat/features/conversation/components/floating-session-conversation.tsx +2 -3
  215. package/src/features/chat/features/conversation/components/session-conversation-area.tsx +9 -1
  216. package/src/features/chat/features/conversation/components/session-conversation-input-top-slot.tsx +44 -0
  217. package/src/features/chat/features/conversation/components/session-conversation-input.tsx +4 -38
  218. package/src/features/chat/features/conversation/hooks/__tests__/use-session-conversation-controller.test.tsx +86 -10
  219. package/src/features/chat/features/conversation/hooks/__tests__/use-session-conversation-input-state.test.tsx +44 -1
  220. package/src/features/chat/features/conversation/hooks/use-session-conversation-controller.ts +85 -73
  221. package/src/features/chat/features/conversation/hooks/use-session-conversation-input-query.ts +5 -15
  222. package/src/features/chat/features/conversation/hooks/use-session-conversation-input-state.ts +53 -13
  223. package/src/features/chat/features/conversation/hooks/use-session-submission-recovery.ts +83 -0
  224. package/src/features/chat/features/conversation/types/session-conversation-input.types.ts +38 -0
  225. package/src/features/chat/features/input/utils/__tests__/ncp-chat-input-availability.utils.test.ts +1 -29
  226. package/src/features/chat/features/input/utils/ncp-chat-input-availability.utils.ts +1 -8
  227. package/src/features/chat/features/message/components/__tests__/chat-message-list-skill-preview.container.test.tsx +14 -1
  228. package/src/features/chat/features/message/hooks/use-chat-inline-token-actions.ts +7 -2
  229. package/src/features/chat/features/message/utils/chat-message-execution-summary.utils.ts +3 -0
  230. package/src/features/chat/features/message/utils/chat-message-texts.utils.ts +1 -0
  231. package/src/features/chat/features/message/utils/chat-message-trigger-details.utils.ts +3 -0
  232. package/src/features/chat/features/session/components/chat-sidebar-project-groups.tsx +1 -1
  233. package/src/features/chat/features/session/components/session-header/chat-session-metadata-dialog.tsx +1 -1
  234. package/src/features/chat/features/session/components/session-header/chat-session-project-badge.tsx +2 -2
  235. package/src/features/chat/features/session/utils/__tests__/chat-session-route.utils.test.ts +26 -0
  236. package/src/features/chat/features/session/utils/chat-session-preference-governance.utils.ts +14 -8
  237. package/src/features/chat/features/session/utils/chat-session-route.utils.ts +9 -12
  238. package/src/features/chat/features/welcome/components/__tests__/chat-welcome.test.tsx +31 -6
  239. package/src/features/chat/features/welcome/components/chat-conversation-welcome.tsx +13 -1
  240. package/src/features/chat/features/welcome/components/chat-welcome-agent-picker.tsx +1 -1
  241. package/src/features/chat/features/welcome/components/chat-welcome-project-picker.tsx +1 -1
  242. package/src/features/chat/features/welcome/components/chat-welcome-prompt-suggestions.tsx +56 -13
  243. package/src/features/chat/features/welcome/components/chat-welcome-session-type-picker.tsx +3 -3
  244. package/src/features/chat/features/welcome/components/chat-welcome.tsx +14 -4
  245. package/src/features/chat/features/welcome/utils/__tests__/chat-welcome-continuation.utils.test.ts +40 -0
  246. package/src/features/chat/features/welcome/utils/chat-welcome-continuation.utils.ts +21 -0
  247. package/src/features/chat/features/workspace/components/__tests__/chat-session-workspace-file-preview.selection.test.tsx +14 -2
  248. package/src/features/chat/features/workspace/components/__tests__/session-cron-job-content.test.tsx +5 -1
  249. package/src/features/chat/features/workspace/components/chat-session-workspace-directory-browser.tsx +1 -1
  250. package/src/features/chat/features/workspace/components/chat-session-workspace-file-breadcrumbs.tsx +3 -7
  251. package/src/features/chat/features/workspace/components/chat-session-workspace-file-preview.tsx +6 -5
  252. package/src/features/chat/features/workspace/components/chat-session-workspace-panel-content.tsx +27 -27
  253. package/src/features/chat/features/workspace/components/overview/chat-session-continuous-attention.tsx +11 -11
  254. package/src/features/chat/features/workspace/components/overview/chat-session-token-usage.tsx +15 -15
  255. package/src/features/chat/features/workspace/components/project-files/workspace-directory-tree.tsx +2 -2
  256. package/src/features/chat/features/workspace/components/project-files/workspace-new-folder-tree-item.tsx +1 -1
  257. package/src/features/chat/features/workspace/components/project-files/workspace-project-files-toolbar.tsx +2 -2
  258. package/src/features/chat/features/workspace/components/session-cron-job-content.tsx +13 -26
  259. package/src/features/chat/index.ts +1 -0
  260. package/src/features/chat/pages/__tests__/ncp-chat-page.test.ts +37 -47
  261. package/src/features/chat/pages/ncp-chat-page.tsx +3 -3
  262. package/src/features/chat/stores/__tests__/chat-composer-draft.store.test.ts +67 -1
  263. package/src/features/chat/stores/chat-composer-draft.store.ts +230 -29
  264. package/src/features/cron/components/__tests__/cron-config.test.tsx +8 -2
  265. package/src/features/cron/components/cron-config.tsx +6 -17
  266. package/src/features/cron/components/cron-job-detail-dialog.tsx +10 -9
  267. package/src/features/cron/components/cron-job-resource.tsx +51 -0
  268. package/src/features/cron/components/cron-job-row.tsx +5 -4
  269. package/src/features/cron/index.ts +1 -0
  270. package/src/features/desktop-capabilities/components/desktop-authorization-dialog.tsx +5 -5
  271. package/src/features/inbox/components/inbox-reader-dialog.test.tsx +46 -6
  272. package/src/features/inbox/components/inbox-reader-dialog.tsx +38 -29
  273. package/src/features/inbox/managers/inbox.manager.test.ts +28 -0
  274. package/src/features/inbox/managers/inbox.manager.ts +18 -4
  275. package/src/features/inbox/pages/inbox-page.test.ts +4 -2
  276. package/src/features/inbox/pages/inbox-page.tsx +14 -10
  277. package/src/features/marketplace/components/__tests__/marketplace-page-detail.test.tsx +1 -0
  278. package/src/features/marketplace/components/__tests__/marketplace-page.test.tsx +1 -0
  279. package/src/features/marketplace/components/mcp/__tests__/mcp-marketplace-page.test.tsx +2 -0
  280. package/src/features/marketplace/components/mcp/mcp-marketplace-card.tsx +2 -2
  281. package/src/features/marketplace/components/mcp/mcp-marketplace-page.tsx +23 -1
  282. package/src/features/marketplace/hooks/use-marketplace-item-detail.ts +11 -0
  283. package/src/features/panel-apps/components/panel-app-list-item.tsx +4 -3
  284. package/src/features/panel-apps/components/panel-app-service-action-authorization-dialog.tsx +2 -2
  285. package/src/features/panel-apps/index.ts +1 -0
  286. package/src/features/panel-apps/utils/panel-app-doc-browser.utils.tsx +5 -24
  287. package/src/features/projects/components/work/project-work-item-drawer.tsx +7 -10
  288. package/src/features/projects/components/work/project-work-items.tsx +1 -1
  289. package/src/features/projects/pages/project-home-page.tsx +18 -23
  290. package/src/features/projects/pages/projects-page.test.tsx +4 -1
  291. package/src/features/pwa/managers/__tests__/pwa-shell-theme.manager.test.ts +3 -3
  292. package/src/features/pwa/managers/pwa-shell-theme.manager.ts +8 -3
  293. package/src/features/right-panel-resources/components/__tests__/page-resource-icon.test.tsx +13 -2
  294. package/src/features/right-panel-resources/components/__tests__/system-object-resource.test.tsx +74 -6
  295. package/src/features/right-panel-resources/components/native-object-resource.tsx +134 -0
  296. package/src/features/right-panel-resources/components/page-resource-icon.tsx +16 -8
  297. package/src/features/right-panel-resources/components/system-object-resource.tsx +66 -1
  298. package/src/features/right-panel-resources/components/workspace-file-resource.tsx +9 -0
  299. package/src/features/right-panel-resources/configs/right-panel-resource-routes.config.ts +11 -21
  300. package/src/features/right-panel-resources/index.ts +3 -0
  301. package/src/features/right-panel-resources/managers/__tests__/page-resource.manager.test.ts +14 -4
  302. package/src/features/right-panel-resources/managers/page-resource.manager.ts +38 -21
  303. package/src/features/right-panel-resources/utils/__tests__/right-panel-resource-route-resolver.utils.test.ts +17 -0
  304. package/src/features/right-panel-resources/utils/right-panel-resource-uri.utils.ts +3 -2
  305. package/src/features/service-apps/components/service-action-row.tsx +4 -3
  306. package/src/features/service-apps/components/service-app-delete-dialog.tsx +2 -2
  307. package/src/features/service-apps/components/service-app-list-item.tsx +5 -4
  308. package/src/features/service-apps/components/service-apps-panel.tsx +5 -2
  309. package/src/features/settings/components/config/provider-model-suggestions-panel.tsx +1 -1
  310. package/src/features/settings/pages/providers-config-page.tsx +3 -2
  311. package/src/index.css +42 -8
  312. package/src/shared/components/doc-browser/__tests__/doc-browser-context.test.tsx +16 -0
  313. package/src/shared/components/doc-browser/__tests__/doc-browser.test.tsx +2 -2
  314. package/src/shared/components/doc-browser/__tests__/resource-link-interceptor.test.tsx +29 -1
  315. package/src/shared/components/doc-browser/doc-browser-tab-strip.tsx +2 -2
  316. package/src/shared/components/doc-browser/stores/doc-browser.store.ts +13 -7
  317. package/src/shared/components/doc-browser/utils/doc-browser-url.utils.ts +2 -1
  318. package/src/shared/components/path-picker/server-path-picker-dialog.tsx +5 -3
  319. package/src/shared/components/ui/__tests__/dialog.test.tsx +37 -1
  320. package/src/shared/components/ui/actions/action-feedback.ts +1 -8
  321. package/src/shared/components/ui/actions/icon-action-button.tsx +1 -1
  322. package/src/shared/components/ui/confirm-dialog.tsx +1 -2
  323. package/src/shared/components/ui/context-menu/context-menu-items.tsx +2 -2
  324. package/src/shared/components/ui/dialog.tsx +29 -7
  325. package/src/shared/components/ui/popover.tsx +14 -3
  326. package/src/shared/components/ui/skeleton.tsx +16 -2
  327. package/src/shared/components/ui/tab-strip/compact-tab-strip.tsx +2 -2
  328. package/src/shared/components/ui/tooltip.tsx +2 -1
  329. package/src/shared/components/workbench/__tests__/workbench-surface.test.tsx +21 -0
  330. package/src/shared/components/workbench/workbench-surface-toolbar.tsx +4 -0
  331. package/src/shared/components/workbench/workbench-surface.tsx +4 -1
  332. package/src/shared/lib/i18n/locales/en-US/chat.json +21 -7
  333. package/src/shared/lib/i18n/locales/en-US/core.json +5 -1
  334. package/src/shared/lib/i18n/locales/en-US/doc-browser.json +10 -5
  335. package/src/shared/lib/i18n/locales/en-US/inbox.json +1 -0
  336. package/src/shared/lib/i18n/locales/zh-CN/chat.json +21 -7
  337. package/src/shared/lib/i18n/locales/zh-CN/core.json +5 -1
  338. package/src/shared/lib/i18n/locales/zh-CN/doc-browser.json +11 -6
  339. package/src/shared/lib/i18n/locales/zh-CN/inbox.json +1 -0
  340. package/src/shared/lib/theme/index.test.ts +28 -1
  341. package/src/shared/lib/theme/index.ts +14 -3
  342. package/src/shared/lib/transport/__tests__/local-transport.service.test.ts +24 -0
  343. package/src/shared/lib/transport/local-transport.service.ts +8 -6
  344. package/dist/assets/account-panel-BAH7FW6z.js +0 -1
  345. package/dist/assets/api-DjiZvIa0.js +0 -20
  346. package/dist/assets/app-presenter-provider-CCRFsFYr.js +0 -232
  347. package/dist/assets/appearance-settings-page-CdP86QJ7.js +0 -1
  348. package/dist/assets/architecture-TIHT7OUA-CvnC-LeA.js +0 -1
  349. package/dist/assets/channel-CpMstUPF.js +0 -1
  350. package/dist/assets/channels-list-page-5qGagKuE.js +0 -8
  351. package/dist/assets/chunk-2Q5K7J3B-Djp3VF0s.js +0 -1
  352. package/dist/assets/chunk-VAUOI2AC-BrbiIC1Q.js +0 -1
  353. package/dist/assets/chunk-XXDRQBXY-Cx9N40wF.js +0 -1
  354. package/dist/assets/classDiagram-OUVF2IWQ-DFN1v3PQ.js +0 -1
  355. package/dist/assets/classDiagram-v2-EOCWNBFH-DRvglADa.js +0 -1
  356. package/dist/assets/config-split-page-CuEGQL8Z.js +0 -1
  357. package/dist/assets/confirm-dialog-CxfecBzO.js +0 -1
  358. package/dist/assets/context-menu-BsCj2fRs.js +0 -1
  359. package/dist/assets/cynefin-VYW2F7L2-DXUGnpJH.js +0 -1
  360. package/dist/assets/desktop-update-config-e-zhkJuS.js +0 -1
  361. package/dist/assets/dialog-QjQoKbIV.js +0 -5
  362. package/dist/assets/doc-browser-CLEdkH9z.js +0 -1
  363. package/dist/assets/doc-browser-context-DwgG6wrz.js +0 -1
  364. package/dist/assets/es2015-Bp6cuSGh.js +0 -41
  365. package/dist/assets/eventmodeling-45OFAUF4-ZBfVS3ZC.js +0 -1
  366. package/dist/assets/extensions-CgShSIkd.js +0 -1
  367. package/dist/assets/eye-kisejBFH.js +0 -1
  368. package/dist/assets/flowDiagram-23GEKE2U-CqdsKk6x.js +0 -1
  369. package/dist/assets/gitGraph-TEB2WS4Q-fHYFd9Es.js +0 -1
  370. package/dist/assets/info-DKCQHKI2-CSaOL_bb.js +0 -1
  371. package/dist/assets/katex-B4FQSo9k.js +0 -1
  372. package/dist/assets/keyboard-shortcuts-settings-page-DZ8A1iLg.js +0 -1
  373. package/dist/assets/loader-circle-Bd1fTm-x.js +0 -1
  374. package/dist/assets/login-page-D99JjH9F.js +0 -1
  375. package/dist/assets/main-Bt5r6b21.js +0 -2
  376. package/dist/assets/main-DXd_aKJV.css +0 -1
  377. package/dist/assets/main-i18n-catalog.config-D0Ll36J_.js +0 -1
  378. package/dist/assets/mcp-marketplace-page-DUoGfSmY.js +0 -1
  379. package/dist/assets/model-config-page-9NNf-mzK.js +0 -1
  380. package/dist/assets/packet-7NZHBO7P-D-YFTczs.js +0 -1
  381. package/dist/assets/panel-app-BYfQu_TS.js +0 -1
  382. package/dist/assets/panel-app-i18n-catalog.config-Ddf2Kv8A.js +0 -1
  383. package/dist/assets/panelStandalone-BRg7B1EI.css +0 -1
  384. package/dist/assets/panelStandalone-BaUzY8Wy.js +0 -2
  385. package/dist/assets/pie-RZYD4A2V-VEnYu9s5.js +0 -1
  386. package/dist/assets/privacy-settings-page-CVMBFuak.js +0 -1
  387. package/dist/assets/projects-BEsU3box.js +0 -1
  388. package/dist/assets/provider-models-Dm-pmWAA.js +0 -1
  389. package/dist/assets/provider-scoped-model-input-CzrXg4cX.js +0 -1
  390. package/dist/assets/providers-config-page-839uUADZ.js +0 -1
  391. package/dist/assets/puzzle-BGvD2DPZ.js +0 -1
  392. package/dist/assets/pwa-DNNK_8E9.js +0 -1
  393. package/dist/assets/radar-I7S5WNFK-BFNIekC1.js +0 -1
  394. package/dist/assets/railroad-3IZDKUUU-lVqJ3Hak.js +0 -1
  395. package/dist/assets/railroad-abnf-AHOZXSZD-DYaefdFC.js +0 -1
  396. package/dist/assets/railroad-ebnf-EBAXGLYW-CTAk6lVq.js +0 -1
  397. package/dist/assets/railroad-peg-LSFZ7HO6-Cob294tg.js +0 -1
  398. package/dist/assets/remote-B5qIuUbT.js +0 -1
  399. package/dist/assets/runtime-config-page-Bf-4JYxQ.js +0 -1
  400. package/dist/assets/search-config-page-C0qA3j-T.js +0 -1
  401. package/dist/assets/secrets-config-page-DxfZWpnk.js +0 -3
  402. package/dist/assets/security-config-CItfIQZ4.js +0 -1
  403. package/dist/assets/select-CWyjnar7.js +0 -1
  404. package/dist/assets/service-apps-panel-D3SOkRVv.js +0 -1
  405. package/dist/assets/stateDiagram-v2-6OUMAXLB-BrNv-raG.js +0 -1
  406. package/dist/assets/swimlanesDiagram-G3AALYLV-ntcxaPXp.js +0 -8
  407. package/dist/assets/tag-chip-BIuavK2K.js +0 -1
  408. package/dist/assets/theme-provider-CWUz4yO9.js +0 -1
  409. package/dist/assets/trash-2-hAbJh9VZ.js +0 -1
  410. package/dist/assets/treeView-QDETBFTQ-DbFmr-gw.js +0 -1
  411. package/dist/assets/treemap-6X3UGDF4-C8aY96pi.js +0 -1
  412. package/dist/assets/use-config-evzage09.js +0 -1
  413. package/dist/assets/use-viewport-layout-D_9XWGDV.js +0 -1
  414. package/dist/assets/wardley-OPB4EBWU-D8d6DbbJ.js +0 -1
  415. package/dist/assets/x-ChPbNv39.js +0 -1
  416. package/src/features/apps/components/app-marketplace-dialog.tsx +0 -168
  417. /package/dist/assets/{array-BV9OtnO8.js → array-DsNX3jRj.js} +0 -0
  418. /package/dist/assets/{chunk-KEIR6QF5-Cx-8EJ4_.js → chunk-KEIR6QF5-BOAXXeyv.js} +0 -0
  419. /package/dist/assets/{chunk-Y2CYZVJY-Dy1ufvjf.js → chunk-Y2CYZVJY-CHjSjwoV.js} +0 -0
  420. /package/dist/assets/{config-hints-DbmiyTKg.js → config-hints-CaB3I7KP.js} +0 -0
  421. /package/dist/assets/{cytoscape.esm-CSCjuT4Z.js → cytoscape.esm-j4J9a91l.js} +0 -0
  422. /package/dist/assets/{defaultLocale-DWTiNsbT.js → defaultLocale-Bmxjp-V_.js} +0 -0
  423. /package/dist/assets/{dist-BVCSkfWY.js → dist-DwLj1Wg5.js} +0 -0
  424. /package/dist/assets/{graphlib-B1yb1Wl8.js → graphlib-CC0HTn1v.js} +0 -0
  425. /package/dist/assets/{host-capabilities-DuIFVsvM.js → host-capabilities-B107nwS3.js} +0 -0
  426. /package/dist/assets/{init-BF6GH5oe.js → init-Biz9Rus1.js} +0 -0
  427. /package/dist/assets/{jszip.min-D12teKzP.js → jszip.min-DQvBVV_R.js} +0 -0
  428. /package/dist/assets/{katex-CsAM73R9.js → katex-BzT-4KBu.js} +0 -0
  429. /package/dist/assets/{navigation-history-CzErJuPG.js → navigation-history-CCnxsAKR.js} +0 -0
  430. /package/dist/assets/{path-C56XkznJ.js → path-4azsBPZv.js} +0 -0
  431. /package/dist/assets/{preload-helper-ca-nBW7U.js → preload-helper-DWTEM3RW.js} +0 -0
  432. /package/dist/assets/{rough.esm-CGfeEbtE.js → rough.esm-w1lBArN6.js} +0 -0
  433. /package/dist/assets/{xlsx-sds5nUpL.js → xlsx--SB9KlFl.js} +0 -0
@@ -23,7 +23,7 @@ function createSnapshot(overrides: Partial<AvailabilitySnapshot> = {}): Availabi
23
23
  }
24
24
 
25
25
  describe('ncp-chat-input-availability.utils', () => {
26
- it('keeps the composer editable during cold start while runtime blocking still prevents send', () => {
26
+ it('keeps editing and sending available when runtime readiness is misreported', () => {
27
27
  const snapshot = createSnapshot({
28
28
  isProviderStateResolved: false,
29
29
  modelOptions: [],
@@ -35,25 +35,7 @@ describe('ncp-chat-input-availability.utils', () => {
35
35
  expect(isNcpChatComposerDisabled(snapshot)).toBe(false);
36
36
  expect(
37
37
  isNcpChatSendDisabled({
38
- snapshot,
39
38
  hasSendableDraft: true,
40
- isRuntimeBlocked: true,
41
- })
42
- ).toBe(true);
43
- });
44
-
45
- it('does not block send only because model options have not loaded yet', () => {
46
- const snapshot = createSnapshot({
47
- isProviderStateResolved: false,
48
- modelOptions: [],
49
- sessionTypeUnavailable: false,
50
- });
51
-
52
- expect(
53
- isNcpChatSendDisabled({
54
- snapshot,
55
- hasSendableDraft: true,
56
- isRuntimeBlocked: false,
57
39
  })
58
40
  ).toBe(false);
59
41
  });
@@ -81,25 +63,15 @@ describe('ncp-chat-input-availability.utils', () => {
81
63
  expect(isNcpChatComposerDisabled(snapshot)).toBe(false);
82
64
  expect(
83
65
  isNcpChatSendDisabled({
84
- snapshot,
85
66
  hasSendableDraft: true,
86
- isRuntimeBlocked: false,
87
67
  })
88
68
  ).toBe(false);
89
69
  });
90
70
 
91
71
  it('blocks send when there is no sendable draft', () => {
92
- const snapshot = createSnapshot({
93
- isProviderStateResolved: true,
94
- modelOptions: [],
95
- sessionTypeUnavailable: true,
96
- });
97
-
98
72
  expect(
99
73
  isNcpChatSendDisabled({
100
- snapshot,
101
74
  hasSendableDraft: false,
102
- isRuntimeBlocked: false,
103
75
  })
104
76
  ).toBe(true);
105
77
  });
@@ -30,13 +30,6 @@ export function isNcpChatComposerDisabled(
30
30
 
31
31
  export function isNcpChatSendDisabled(params: {
32
32
  hasSendableDraft: boolean;
33
- snapshot: ChatInputAvailabilitySnapshot;
34
- isRuntimeBlocked: boolean;
35
33
  }): boolean {
36
- const { hasSendableDraft, isRuntimeBlocked } = params;
37
-
38
- return (
39
- isRuntimeBlocked ||
40
- !hasSendableDraft
41
- );
34
+ return !params.hasSendableDraft;
42
35
  }
@@ -23,6 +23,8 @@ function ChatMessageListContainer({
23
23
  }
24
24
 
25
25
  const captures = vi.hoisted(() => ({
26
+ resolveResource: vi.fn(),
27
+ openResource: vi.fn(),
26
28
  renders: [] as Array<{
27
29
  onInlineTokenClick?: (token: unknown) => void;
28
30
  }>,
@@ -98,6 +100,8 @@ vi.mock("@/shared/lib/i18n", () => ({
98
100
  }));
99
101
 
100
102
  beforeEach(() => {
103
+ captures.resolveResource.mockReset();
104
+ captures.openResource.mockReset();
101
105
  captures.renders = [];
102
106
  captures.openFilePreview.mockReset();
103
107
  captures.fetchSessionSkills.mockReset();
@@ -116,6 +120,15 @@ function clickSkill(token: Record<string, unknown>, sessionKey?: string): void {
116
120
  captures.renders[captures.renders.length - 1]?.onInlineTokenClick?.(token);
117
121
  }
118
122
 
123
+ it("opens a quoted object through the resource opener instead of treating its URI as a local path", () => {
124
+ const page = { uri: "nextclaw://objects/agent/philosopher" };
125
+ captures.resolveResource.mockReturnValue(page);
126
+ clickSkill({ kind: "workspace_excerpt", path: page.uri, excerpt: "Description", label: "Philosopher", startLine: null, endLine: null });
127
+ expect(captures.resolveResource).toHaveBeenCalledWith(page.uri);
128
+ expect(captures.openResource).toHaveBeenCalledWith(page, "default", expect.any(Function));
129
+ expect(captures.openFilePreview).not.toHaveBeenCalled();
130
+ });
131
+
119
132
  it("opens a persisted skill path without consulting the session catalog", () => {
120
133
  clickSkill({
121
134
  kind: "skill", ref: "global:/skills/review", name: "review", source: "global",
@@ -170,4 +183,4 @@ it("shows an error when a persisted v1 skill is no longer resolvable", async ()
170
183
  });
171
184
 
172
185
  vi.mock("react-router-dom", async (importOriginal) => ({ ...(await importOriginal<object>()), useNavigate: () => vi.fn() }));
173
- vi.mock("@/app/components/app-presenter-provider", () => ({ useAppPresenter: () => ({ pageResourceManager: { resolve: vi.fn(), open: vi.fn() } }) }));
186
+ vi.mock("@/app/components/app-presenter-provider", () => ({ useAppPresenter: () => ({ pageResourceManager: { resolve: captures.resolveResource, open: captures.openResource } }) }));
@@ -30,8 +30,13 @@ export function useChatInlineTokenActions(params: {
30
30
  const projectRoot = selectedSession?.projectRoot ?? selectedSession?.workingDir;
31
31
 
32
32
  const handleInlineTokenClick = useCallback((token: ChatInlineTokenViewModel) => {
33
- if ((token.kind === CHAT_UI_RESOURCE_TOKEN_KIND || token.kind === CHAT_SYSTEM_OBJECT_TOKEN_KIND) && "key" in token) {
34
- const page = appPresenter.pageResourceManager.resolve(token.key);
33
+ const resourceUri = (token.kind === CHAT_UI_RESOURCE_TOKEN_KIND || token.kind === CHAT_SYSTEM_OBJECT_TOKEN_KIND) && "key" in token
34
+ ? token.key
35
+ : token.kind === CHAT_WORKSPACE_EXCERPT_TOKEN_KIND && "excerpt" in token && token.path.startsWith("nextclaw://")
36
+ ? token.path
37
+ : null;
38
+ if (resourceUri) {
39
+ const page = appPresenter.pageResourceManager.resolve(resourceUri);
35
40
  if (page) appPresenter.pageResourceManager.open(page, 'default', navigate);
36
41
  return;
37
42
  }
@@ -1,4 +1,6 @@
1
1
  import type { ChatMessageMoreActionsViewModel } from "@nextclaw/agent-chat-ui";
2
+ import { createElement } from "react";
3
+ import { Braces } from "lucide-react";
2
4
  import {
3
5
  readNcpAiExecutionMetadata,
4
6
  type NcpAiExecutionMetadata,
@@ -159,6 +161,7 @@ export function buildChatMessageExecutionPresentation(params: {
159
161
  items: [
160
162
  {
161
163
  key: "ai-execution-metadata",
164
+ icon: createElement(Braces, { className: "h-4 w-4" }),
162
165
  label: labels.viewMetadata,
163
166
  dialog: {
164
167
  title: labels.metadataTitle,
@@ -190,6 +190,7 @@ export function buildChatMessageTexts(
190
190
  excerptCharacterCountTemplate: t("chatWorkspaceExcerptCharacterCount"),
191
191
  mermaidDiagramLabel: t("chatMermaidDiagram"),
192
192
  frontmatterLabel: t("chatMarkdownFrontmatter"),
193
+ detailsLabel: t("chatMarkdownDetails"),
193
194
  mermaidExpandLabel: t("chatMermaidExpand"),
194
195
  mermaidLoadingLabel: t("chatMermaidLoading"),
195
196
  mermaidRenderErrorLabel: t("chatMermaidRenderError"),
@@ -1,4 +1,6 @@
1
1
  import type { ChatMessageMoreActionsViewModel } from "@nextclaw/agent-chat-ui";
2
+ import { createElement } from "react";
3
+ import { Zap } from "lucide-react";
2
4
  import {
3
5
  readNcpAiExecutionMetadata,
4
6
  readNcpRunTriggerMetadata,
@@ -106,6 +108,7 @@ export function buildChatMessageTriggerDetails(params: {
106
108
  triggerLabel: labels.moreActions,
107
109
  items: [{
108
110
  key: "run-trigger-metadata",
111
+ icon: createElement(Zap, { className: "h-4 w-4" }),
109
112
  label: labels.viewTrigger,
110
113
  dialog: {
111
114
  title: labels.title,
@@ -262,7 +262,7 @@ export function ChatSidebarProjectGroups(props: ChatSidebarProjectGroupsProps) {
262
262
  onClick={(event) => event.stopPropagation()}
263
263
  />
264
264
  </PopoverTrigger>
265
- <ChatPopoverContent align="end" className="w-56 p-2">
265
+ <ChatPopoverContent align="end" variant="menu">
266
266
  <ChatSessionHeaderMenuItem
267
267
  icon={FolderMinus}
268
268
  label={t("projectsRemoveFromList")}
@@ -29,7 +29,7 @@ export function ChatSessionMetadataDialog({
29
29
  return (
30
30
  <Dialog open={open} onOpenChange={onOpenChange}>
31
31
  <DialogContent className="max-w-2xl gap-0 overflow-hidden p-0">
32
- <DialogHeader className="border-b border-border px-5 py-4 pr-12">
32
+ <DialogHeader className="border-b border-border px-5 py-4">
33
33
  <DialogTitle className="text-base">{t('chatSessionMetadataDialogTitle')}</DialogTitle>
34
34
  <DialogDescription className="sr-only">
35
35
  {t('chatSessionMetadataDialogDescription')}
@@ -56,8 +56,8 @@ export function ChatSessionProjectBadge({
56
56
  <PopoverTrigger asChild>
57
57
  <button
58
58
  type="button"
59
- title={projectRoot ?? undefined}
60
- className="min-w-0 max-w-[320px] shrink rounded-full border border-border bg-muted px-2 py-0.5 text-[11px] font-medium text-muted-foreground transition-colors hover:border-primary/35 hover:bg-[var(--interaction-hover)] hover:text-accent-foreground disabled:cursor-not-allowed disabled:opacity-60"
59
+ title={projectRoot ? `${projectName}\n${projectRoot}` : projectName}
60
+ className="min-w-0 max-w-[40%] shrink-0 rounded-full border border-border bg-muted px-2 py-0.5 text-[11px] font-medium text-muted-foreground transition-colors hover:bg-[var(--interaction-hover)] hover:text-accent-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-border disabled:cursor-not-allowed disabled:opacity-60"
61
61
  aria-label={t('chatSessionSetProject')}
62
62
  disabled={isProjectPending}
63
63
  >
@@ -1,11 +1,37 @@
1
1
  import { describe, expect, it } from 'vitest';
2
2
  import {
3
3
  CHAT_DRAFT_SESSION_PATH,
4
+ buildSessionPanelUrl,
5
+ parseSessionKeyFromPanelUrl,
6
+ encodeSessionRouteId,
4
7
  buildSessionPath,
5
8
  parseSessionKeyFromRoute,
6
9
  } from '@/features/chat/features/session/utils/chat-session-route.utils';
7
10
 
8
11
  describe('chat session route utils', () => {
12
+ it.each(['ncp-mu2x4zdy-9wzl0otb', 'agent:main:会话/一 %2F', 'sid_literal', 'draft'])(
13
+ 'round-trips resource and browser links for %s', (id) => {
14
+ expect(buildSessionPanelUrl(id)).toBe(`nextclaw://sessions/${encodeURIComponent(id)}`);
15
+ expect(parseSessionKeyFromPanelUrl(buildSessionPanelUrl(id))).toBe(id);
16
+ expect(parseSessionKeyFromRoute(buildSessionPath(id).slice('/chat/'.length))).toBe(id);
17
+ expect(parseSessionKeyFromPanelUrl(`nextclaw://chat-session/${encodeSessionRouteId(id)}`)).toBe(id);
18
+ },
19
+ );
20
+ it('keeps ordinary IDs readable in the address bar', () => {
21
+ expect(buildSessionPath('ncp-mu2x4zdy-9wzl0otb')).toBe('/chat/ncp-mu2x4zdy-9wzl0otb');
22
+ });
23
+ it.each(['sessions', 'chat-session', 'objects/chat-session', 'objects/chat-sessions'])(
24
+ 'recovers already delivered %s links', (namespace) => {
25
+ expect(parseSessionKeyFromPanelUrl(`nextclaw://${namespace}/ncp-mu2x4zdy-9wzl0otb`)).toBe('ncp-mu2x4zdy-9wzl0otb');
26
+ },
27
+ );
28
+ it.each(['nextclaw://sessions/', 'nextclaw://sessions/a/b', 'nextclaw://sessions/%ZZ',
29
+ 'nextclaw://sessions/%20', 'nextclaw://chat-session/sid_%%%','nextclaw://sessions/a?other=b',
30
+ 'https://sessions/a', 'nextclaw://user@sessions/a', 'nextclaw://objects/project/a'])(
31
+ 'rejects malformed or unrelated session links: %s', (uri) => {
32
+ expect(parseSessionKeyFromPanelUrl(uri)).toBeNull();
33
+ },
34
+ );
9
35
  it('keeps the draft route separate from real session keys', () => {
10
36
  expect(CHAT_DRAFT_SESSION_PATH).toBe('/chat/draft');
11
37
  expect(parseSessionKeyFromRoute('draft')).toBeNull();
@@ -129,15 +129,17 @@ export function resolveSelectedThinkingLevelValue(params: {
129
129
  });
130
130
  }
131
131
 
132
- export function resolveRecentSessionPreferredValue<T>(params: {
132
+ export function resolveRecentSessionPreferenceSnapshot(params: {
133
133
  sessions: readonly SessionEntryView[];
134
134
  selectedSessionKey?: string | null;
135
135
  sessionType?: string | null;
136
- readPreference: (session: SessionEntryView) => T | null | undefined;
137
- }): T | undefined {
138
- const { sessions, selectedSessionKey, sessionType, readPreference } = params;
136
+ }): {
137
+ model: string;
138
+ thinking?: ThinkingLevel;
139
+ } | undefined {
140
+ const { sessions, selectedSessionKey, sessionType } = params;
139
141
  const targetSessionType = normalizeSessionType(sessionType);
140
- let bestValue: T | undefined;
142
+ let bestValue: { model: string; thinking?: ThinkingLevel } | undefined;
141
143
  let bestTimestamp = Number.NEGATIVE_INFINITY;
142
144
  for (const session of sessions) {
143
145
  if (session.key === selectedSessionKey) {
@@ -146,14 +148,18 @@ export function resolveRecentSessionPreferredValue<T>(params: {
146
148
  if (normalizeSessionType(session.sessionType) !== targetSessionType) {
147
149
  continue;
148
150
  }
149
- const value = readPreference(session);
150
- if (value === null || value === undefined) {
151
+ const model = session.preferredModel?.trim() || undefined;
152
+ const thinking = session.preferredThinking ?? undefined;
153
+ if (model === undefined) {
151
154
  continue;
152
155
  }
153
156
  const updatedAtTimestamp = Date.parse(session.updatedAt);
154
157
  const comparableTimestamp = Number.isFinite(updatedAtTimestamp) ? updatedAtTimestamp : Number.NEGATIVE_INFINITY;
155
158
  if (bestValue === undefined || comparableTimestamp > bestTimestamp) {
156
- bestValue = value;
159
+ bestValue = {
160
+ model,
161
+ ...(thinking ? { thinking } : {}),
162
+ };
157
163
  bestTimestamp = comparableTimestamp;
158
164
  }
159
165
  }
@@ -1,16 +1,9 @@
1
+ import { createSessionResourceUri, parseSessionResourceUri } from '@nextclaw/shared';
2
+
1
3
  const SESSION_ROUTE_PREFIX = 'sid_';
2
4
  export const CHAT_SESSION_PANEL_KIND = 'chat-session';
3
- const SESSION_PANEL_PREFIX = 'nextclaw://chat-session/';
4
-
5
- export function buildSessionPanelUrl(sessionKey: string): string {
6
- return SESSION_PANEL_PREFIX + encodeSessionRouteId(sessionKey);
7
- }
8
-
9
- export function parseSessionKeyFromPanelUrl(url: string): string | null {
10
- return url.startsWith(SESSION_PANEL_PREFIX)
11
- ? decodeSessionRouteId(url.slice(SESSION_PANEL_PREFIX.length))
12
- : null;
13
- }
5
+ export const buildSessionPanelUrl = createSessionResourceUri;
6
+ export const parseSessionKeyFromPanelUrl = parseSessionResourceUri;
14
7
  export const CHAT_DRAFT_SESSION_PATH = '/chat/draft';
15
8
  const DRAFT_SESSION_ROUTE_ID = CHAT_DRAFT_SESSION_PATH.slice('/chat/'.length);
16
9
 
@@ -55,5 +48,9 @@ export function parseSessionKeyFromRoute(routeValue?: string): string | null {
55
48
  }
56
49
 
57
50
  export function buildSessionPath(sessionKey: string): string {
58
- return `/chat/${encodeSessionRouteId(sessionKey)}`;
51
+ // Keep reserved historical route tokens unambiguous; ordinary IDs stay readable.
52
+ const routeId = sessionKey === DRAFT_SESSION_ROUTE_ID || sessionKey.startsWith(SESSION_ROUTE_PREFIX)
53
+ ? encodeSessionRouteId(sessionKey)
54
+ : encodeURIComponent(sessionKey);
55
+ return `/chat/${routeId}`;
59
56
  }
@@ -1,6 +1,8 @@
1
1
  import { fireEvent, render, screen, waitFor } from '@testing-library/react';
2
2
  import { describe, expect, it, vi } from 'vitest';
3
3
  import { ChatWelcome } from '@/features/chat/features/welcome/components/chat-welcome';
4
+ import { MemoryRouter } from 'react-router-dom';
5
+ import { buildSessionPath } from '@/features/chat/features/session/utils/chat-session-route.utils';
4
6
 
5
7
  vi.mock(
6
8
  '@/features/chat/features/session/components/session-header/chat-session-project-dialog',
@@ -18,12 +20,14 @@ function renderWelcome(
18
20
  overrides: Partial<Parameters<typeof ChatWelcome>[0]> = {},
19
21
  ) {
20
22
  return render(
23
+ <MemoryRouter>
21
24
  <ChatWelcome
22
25
  agents={[
23
26
  { id: 'main', displayName: 'Main' },
24
27
  { id: 'engineer', displayName: 'Engineer' },
25
28
  ]}
26
29
  projectOptions={[]}
30
+ selectedProjectRoot="/tmp/project"
27
31
  selectedAgentId="main"
28
32
  selectedSessionType="native"
29
33
  sessionTypeOptions={sessionTypeOptions}
@@ -31,11 +35,34 @@ function renderWelcome(
31
35
  onSelectPrompt={vi.fn()}
32
36
  onSelectSessionType={vi.fn()}
33
37
  {...overrides}
34
- />,
38
+ />
39
+ </MemoryRouter>,
35
40
  );
36
41
  }
37
42
 
38
43
  describe('ChatWelcome', () => {
44
+ it('offers an open-ended starting point outside an explicit project', () => {
45
+ renderWelcome({ selectedProjectRoot: null });
46
+ expect(screen.getByRole('button', { name: 'Talk about how I’ve been' })).toBeTruthy();
47
+ expect(screen.queryByRole('button', { name: 'Move this project forward' })).toBeNull();
48
+ });
49
+
50
+ it('links to the original session and can dismiss it without removing history', () => {
51
+ renderWelcome({ continuation: { sessionKey: 'session/one', title: 'A real conversation' } });
52
+ const link = screen.getByRole('link', { name: /A real conversation/ });
53
+ expect(link.getAttribute('href')).toBe(buildSessionPath('session/one'));
54
+ expect(screen.getByRole('button', { name: 'Talk about how I’ve been' })).toBeTruthy();
55
+ fireEvent.click(screen.getByRole('button', { name: 'Hide this conversation suggestion for now' }));
56
+ expect(screen.queryByRole('link')).toBeNull();
57
+ expect(screen.getByRole('button', { name: 'Move this project forward' })).toBeTruthy();
58
+ });
59
+
60
+ it('hides starting suggestions while composing but keeps context controls available', () => {
61
+ renderWelcome({ hasDraftContent: true });
62
+ expect(screen.queryByRole('button', { name: 'Move this project forward' })).toBeNull();
63
+ expect(screen.getByRole('combobox', { name: 'Draft agent' })).toBeTruthy();
64
+ expect(screen.getByRole('button', { name: 'Choose session type' })).toBeTruthy();
65
+ });
39
66
  it('renders a lightweight draft agent select and allows switching', () => {
40
67
  const onSelectAgent = vi.fn();
41
68
 
@@ -53,12 +80,10 @@ describe('ChatWelcome', () => {
53
80
  it('renders a single-purpose welcome surface with compact prompt suggestions', () => {
54
81
  renderWelcome({ agents: [{ id: 'main', displayName: 'Main' }] });
55
82
 
56
- expect(screen.getByRole('heading', { name: 'What would you like to get done?' })).toBeTruthy();
83
+ expect(screen.getByRole('heading', { name: 'Where shall we start today?' })).toBeTruthy();
57
84
  expect(screen.queryByText(/Describe the goal/)).toBeNull();
58
85
  expect(screen.getByRole('group', { name: 'Task context' })).toBeTruthy();
59
- const suggestion = screen.getByRole('button', { name: 'Review this project' });
60
- expect(suggestion.className).toContain('rounded-full');
61
- expect(suggestion.className).not.toContain('border');
86
+ const suggestion = screen.getByRole('button', { name: 'Move this project forward' });
62
87
  expect(suggestion.parentElement?.className).toContain('flex-wrap');
63
88
  });
64
89
 
@@ -67,7 +92,7 @@ describe('ChatWelcome', () => {
67
92
 
68
93
  renderWelcome({ onSelectPrompt });
69
94
 
70
- fireEvent.click(screen.getByRole('button', { name: 'Review this project' }));
95
+ fireEvent.click(screen.getByRole('button', { name: 'Move this project forward' }));
71
96
 
72
97
  expect(onSelectPrompt).toHaveBeenCalledWith(
73
98
  expect.stringContaining('next three concrete things'),
@@ -19,11 +19,13 @@ import { useAgents } from "@/shared/hooks/use-agents";
19
19
  import { useProjects } from "@/shared/hooks/use-projects";
20
20
  import type { NcpSessionSummaryView } from "@/shared/lib/api";
21
21
  import { normalizeSessionProjectRootValue } from "@/shared/lib/session-project";
22
+ import { resolveChatWelcomeContinuation } from "@/features/chat/features/welcome/utils/chat-welcome-continuation.utils";
22
23
 
23
24
  const EMPTY_NCP_SESSION_SUMMARIES: NcpSessionSummaryView[] = [];
24
25
 
25
26
  type ChatConversationWelcomeProps = {
26
27
  inputSlot: ReactNode;
28
+ hasDraftContent?: boolean;
27
29
  pendingProjectRoot: string | null;
28
30
  pendingSessionType: string;
29
31
  selectedSessionTypeValue: string | null;
@@ -34,6 +36,7 @@ type ChatConversationWelcomeProps = {
34
36
 
35
37
  export function ChatConversationWelcome({
36
38
  inputSlot,
39
+ hasDraftContent = false,
37
40
  pendingProjectRoot,
38
41
  pendingSessionType,
39
42
  selectedSessionTypeValue,
@@ -50,7 +53,9 @@ export function ChatConversationWelcome({
50
53
  (state) => state.snapshot.configQuery?.data ?? null,
51
54
  );
52
55
  const sessionSummaries = useChatQueryStore(
53
- (state) => state.snapshot.sessionsQuery?.data?.sessions ?? EMPTY_NCP_SESSION_SUMMARIES,
56
+ (state) => state.snapshot.sessionsQuery?.isSuccess
57
+ ? state.snapshot.sessionsQuery.data?.sessions ?? EMPTY_NCP_SESSION_SUMMARIES
58
+ : EMPTY_NCP_SESSION_SUMMARIES,
54
59
  );
55
60
  const sessionTypesData = useChatQueryStore(
56
61
  (state) => state.snapshot.sessionTypesQuery?.data ?? null,
@@ -104,6 +109,13 @@ export function ChatConversationWelcome({
104
109
  agents={availableAgents}
105
110
  defaultProjectRoot={defaultProjectRoot}
106
111
  inputSlot={inputSlot}
112
+ hasDraftContent={hasDraftContent}
113
+ continuation={resolveChatWelcomeContinuation({
114
+ sessions: sessionSummaries,
115
+ projectRoot: selectedProjectRoot ?? defaultProjectRoot,
116
+ defaultProjectRoot,
117
+ agentId: draftAgentId,
118
+ })}
107
119
  projectOptions={projectOptions}
108
120
  selectedAgentId={draftAgentId}
109
121
  selectedProjectRoot={selectedProjectRoot}
@@ -28,7 +28,7 @@ export function ChatWelcomeAgentPicker({
28
28
  <Select value={selectedAgentId} onValueChange={onSelectAgent}>
29
29
  <SelectTrigger
30
30
  aria-label={t('chatDraftAgentTitle')}
31
- className="h-auto w-auto min-w-0 gap-1 rounded-lg border-0 bg-transparent px-2 py-1.5 text-muted-foreground shadow-none hover:bg-[var(--interaction-hover)] hover:text-accent-foreground focus:ring-0"
31
+ className="h-9 w-auto min-w-0 gap-1.5 rounded-lg border-0 bg-transparent px-2 py-1.5 text-sm font-medium text-foreground/80 shadow-none hover:bg-[var(--interaction-hover)] hover:text-foreground focus:ring-1 focus:ring-border"
32
32
  >
33
33
  <span className="sr-only">{t('chatDraftAgentTitle')}</span>
34
34
  <div className="flex min-w-0 items-center gap-1.5">
@@ -43,7 +43,7 @@ export function ChatWelcomeProjectPicker({
43
43
  <PopoverTrigger asChild>
44
44
  <button
45
45
  type="button"
46
- className="inline-flex min-w-0 max-w-full items-center gap-1.5 rounded-lg px-2 py-1.5 text-left font-medium text-muted-foreground transition-colors hover:bg-[var(--interaction-hover)] hover:text-accent-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-border"
46
+ className="inline-flex h-9 min-w-0 max-w-full items-center gap-1.5 rounded-lg px-2 py-1.5 text-left text-sm font-medium text-foreground/80 transition-colors hover:bg-[var(--interaction-hover)] hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-border"
47
47
  title={projectRoot ?? undefined}
48
48
  aria-label={t('chatWelcomeProjectPickerLabel')}
49
49
  disabled={!selectable || isSaving}
@@ -1,9 +1,14 @@
1
+ import { useState } from 'react';
2
+ import { Link } from 'react-router-dom';
3
+ import { ArrowUpRight, History, X } from 'lucide-react';
4
+ import { buildSessionPath } from '@/features/chat/features/session/utils/chat-session-route.utils';
5
+ import type { ChatWelcomeContinuation } from '@/features/chat/features/welcome/utils/chat-welcome-continuation.utils';
1
6
  import { t } from '@/shared/lib/i18n';
2
7
 
3
8
  const WELCOME_PROMPT_SUGGESTIONS = [
4
9
  {
5
- labelKey: 'chatWelcomeSuggestion1Label' as const,
6
- promptKey: 'chatWelcomeSuggestion1Prompt' as const,
10
+ labelKey: 'chatWelcomeOpenStartLabel' as const,
11
+ promptKey: 'chatWelcomeOpenStartPrompt' as const,
7
12
  },
8
13
  {
9
14
  labelKey: 'chatWelcomeSuggestion2Label' as const,
@@ -17,21 +22,59 @@ const WELCOME_PROMPT_SUGGESTIONS = [
17
22
 
18
23
  export function ChatWelcomePromptSuggestions({
19
24
  onSelectPrompt,
25
+ hasDraftContent = false,
26
+ hasProject = false,
27
+ continuation,
20
28
  }: {
21
29
  onSelectPrompt: (prompt: string) => void;
30
+ hasDraftContent?: boolean;
31
+ hasProject?: boolean;
32
+ continuation?: ChatWelcomeContinuation | null;
22
33
  }) {
34
+ const [dismissedSessionKey, setDismissedSessionKey] = useState<string | null>(null);
35
+ const showContinuation = continuation && continuation.sessionKey !== dismissedSessionKey;
23
36
  return (
24
- <div className="mt-5 flex flex-wrap justify-center gap-2">
25
- {WELCOME_PROMPT_SUGGESTIONS.map((suggestion) => (
26
- <button
27
- key={suggestion.labelKey}
28
- type="button"
29
- onClick={() => onSelectPrompt(t(suggestion.promptKey))}
30
- className="rounded-full bg-muted/55 px-3.5 py-2 text-xs font-medium text-muted-foreground transition-colors hover:bg-[var(--interaction-hover)] hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2"
31
- >
32
- {t(suggestion.labelKey)}
33
- </button>
34
- ))}
37
+ <div className={`mt-3 min-h-32 ${hasDraftContent ? 'invisible' : ''}`} aria-hidden={hasDraftContent || undefined}>
38
+ <div className="flex flex-wrap justify-center gap-x-2 gap-y-1">
39
+ {WELCOME_PROMPT_SUGGESTIONS.map((suggestion, index) => {
40
+ const projectStart = index === 2 && hasProject;
41
+ return (
42
+ <button
43
+ key={suggestion.labelKey}
44
+ type="button"
45
+ onClick={() => onSelectPrompt(t(projectStart ? 'chatWelcomeSuggestion1Prompt' : suggestion.promptKey))}
46
+ className="rounded-lg bg-muted/70 px-3 py-1.5 text-[13px] font-normal leading-5 text-foreground/80 transition-colors hover:bg-[var(--interaction-hover)] hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2"
47
+ >
48
+ {t(projectStart ? 'chatWelcomeSuggestion1Label' : suggestion.labelKey)}
49
+ </button>
50
+ );
51
+ })}
52
+ </div>
53
+ {continuation ? (
54
+ <div className={`mx-auto mt-5 flex min-w-0 max-w-lg items-center gap-1 border-t border-border/50 pt-3 ${showContinuation ? '' : 'invisible'}`} aria-hidden={!showContinuation || undefined}>
55
+ <Link
56
+ to={buildSessionPath(continuation.sessionKey)}
57
+ title={t('chatWelcomeContinueHint')}
58
+ className="flex min-w-0 flex-1 items-center gap-3 rounded-lg px-2 py-2 transition-colors hover:bg-[var(--interaction-hover)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
59
+ >
60
+ <History aria-hidden="true" className="h-4 w-4 shrink-0 text-muted-foreground" />
61
+ <span className="min-w-0 flex-1">
62
+ <span className="block text-xs text-muted-foreground">{t('chatWelcomeContinueLabel')}</span>
63
+ <span className="mt-1 block truncate text-sm text-foreground">{continuation.title}</span>
64
+ </span>
65
+ <ArrowUpRight aria-hidden="true" className="h-4 w-4 shrink-0 text-muted-foreground" />
66
+ </Link>
67
+ <button
68
+ type="button"
69
+ aria-label={t('chatWelcomeDismissContinue')}
70
+ title={t('chatWelcomeDismissContinue')}
71
+ onClick={() => setDismissedSessionKey(continuation.sessionKey)}
72
+ className="mr-1 flex h-9 w-9 shrink-0 items-center justify-center rounded-lg text-muted-foreground hover:bg-[var(--interaction-hover)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
73
+ >
74
+ <X aria-hidden="true" className="h-3.5 w-3.5" />
75
+ </button>
76
+ </div>
77
+ ) : null}
35
78
  </div>
36
79
  );
37
80
  }
@@ -1,5 +1,5 @@
1
1
  import { useState } from 'react';
2
- import { Bot, ChevronDown } from 'lucide-react';
2
+ import { Cpu, ChevronDown } from 'lucide-react';
3
3
  import { SessionContextIconNode } from '@/features/chat/features/session/components/session-context-icon';
4
4
  import { ChatSessionTypeOptionItem } from '@/features/chat/features/session-type/components/chat-session-type-option-item';
5
5
  import type { ChatSessionTypeOption } from '@/features/chat/features/session-type/utils/chat-session-type.utils';
@@ -39,7 +39,7 @@ export function ChatWelcomeSessionTypePicker({
39
39
  <PopoverTrigger asChild>
40
40
  <button
41
41
  type="button"
42
- className="inline-flex min-w-0 max-w-full items-center gap-1.5 rounded-lg px-2 py-1.5 text-left font-medium text-muted-foreground transition-colors hover:bg-[var(--interaction-hover)] hover:text-accent-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-border"
42
+ className="inline-flex h-9 min-w-0 max-w-full items-center gap-1.5 rounded-lg px-2 py-1.5 text-left text-sm font-medium text-foreground/80 transition-colors hover:bg-[var(--interaction-hover)] hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-border"
43
43
  aria-label={t('chatWelcomeSessionTypePickerLabel')}
44
44
  >
45
45
  {selectedOption.icon?.src ? (
@@ -53,7 +53,7 @@ export function ChatWelcomeSessionTypePicker({
53
53
  className="h-4 w-4"
54
54
  />
55
55
  ) : (
56
- <Bot className="h-4 w-4 shrink-0" />
56
+ <Cpu className="h-3.5 w-3.5 shrink-0" />
57
57
  )}
58
58
  <span className="truncate">{selectedOption.label}</span>
59
59
  <ChevronDown className="h-3.5 w-3.5 shrink-0 text-muted-foreground/70" />