@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
@@ -11,7 +11,9 @@ import {
11
11
 
12
12
  import { PageHeader, PageLayout } from "@/app/components/layout/page-layout";
13
13
  import { usePresenter } from "@/features/chat";
14
- import { CronJobDetailDialog } from "@/features/cron/components/cron-job-detail-dialog";
14
+ import { useAppPresenter } from "@/app/components/app-presenter-provider";
15
+ import { useNavigate } from "react-router-dom";
16
+ import { pageResourceFromSystemObject } from "@/features/right-panel-resources";
15
17
  import { CronJobRow } from "@/features/cron/components/cron-job-row";
16
18
  import {
17
19
  CronTaskComposer,
@@ -146,12 +148,13 @@ function CronPagination({
146
148
  }
147
149
 
148
150
  export function CronConfig() {
151
+ const app = useAppPresenter();
152
+ const navigate = useNavigate();
149
153
  const [composerPrompt, setComposerPrompt] = useState("");
150
154
  const [query, setQuery] = useState("");
151
155
  const [status, setStatus] = useState<CronListStatus>("all");
152
156
  const [page, setPage] = useState(0);
153
157
  const [expandedJobId, setExpandedJobId] = useState<string | null>(null);
154
- const [selectedJobId, setSelectedJobId] = useState<string | null>(null);
155
158
  const deferredQuery = useDeferredValue(query.trim());
156
159
  const composerRef = useRef<HTMLInputElement>(null);
157
160
  const presenter = usePresenter();
@@ -166,7 +169,6 @@ export function CronConfig() {
166
169
  const jobs = cronQuery.data?.jobs ?? [];
167
170
  const total = cronQuery.data?.total ?? 0;
168
171
  const summary = cronQuery.data?.summary;
169
- const selectedJob = jobs.find((job) => job.id === selectedJobId) ?? null;
170
172
 
171
173
  const startDraftConversation = () => {
172
174
  const prompt = composerPrompt.trim();
@@ -185,7 +187,6 @@ export function CronConfig() {
185
187
  const handleDelete = (job: CronJobView) => {
186
188
  void cronActions.deleteJob(job, () => {
187
189
  setExpandedJobId(null);
188
- setSelectedJobId(null);
189
190
  if (jobs.length === 1 && page > 0) {
190
191
  setPage(page - 1);
191
192
  }
@@ -333,7 +334,7 @@ export function CronConfig() {
333
334
  expanded={expandedJobId === job.id}
334
335
  job={job}
335
336
  onDelete={handleDelete}
336
- onEdit={(item) => setSelectedJobId(item.id)}
337
+ onEdit={(item) => app.pageResourceManager.open(pageResourceFromSystemObject("cron-job", item.id, item.name || item.id), "default", navigate)}
337
338
  onRun={handleRun}
338
339
  onToggleExpanded={handleToggleExpanded}
339
340
  onToggle={handleToggle}
@@ -409,18 +410,6 @@ export function CronConfig() {
409
410
  </>
410
411
  )}
411
412
 
412
- <CronJobDetailDialog
413
- job={selectedJob}
414
- open={Boolean(selectedJob)}
415
- onOpenChange={(open) => {
416
- if (!open) {
417
- setSelectedJobId(null);
418
- }
419
- }}
420
- onDelete={handleDelete}
421
- onRun={handleRun}
422
- onToggle={handleToggle}
423
- />
424
413
  <cronActions.ConfirmDialog />
425
414
  </PageLayout>
426
415
  );
@@ -43,6 +43,7 @@ function DetailRow({
43
43
  }
44
44
 
45
45
  type CronJobDetailDialogProps = {
46
+ readonly embedded?: boolean;
46
47
  readonly job: CronJobView | null;
47
48
  readonly open: boolean;
48
49
  readonly onDelete: (job: CronJobView) => void;
@@ -52,6 +53,7 @@ type CronJobDetailDialogProps = {
52
53
  };
53
54
 
54
55
  export function CronJobDetailDialog({
56
+ embedded = false,
55
57
  job,
56
58
  open,
57
59
  onDelete,
@@ -74,13 +76,8 @@ export function CronJobDetailDialog({
74
76
  )
75
77
  : t("cronNeverRun");
76
78
 
77
- return (
78
- <Sheet open={open} onOpenChange={onOpenChange}>
79
- <SheetContent
80
- side="right"
81
- closeLabel={t("cronCloseDetails")}
82
- className="flex w-full flex-col overflow-hidden p-0 sm:max-w-[510px]"
83
- >
79
+ const content = (
80
+ <>
84
81
  <SheetHeader className="shrink-0 border-b border-border/60 px-5 pb-5 pt-6 pr-14 sm:px-7 sm:pt-7">
85
82
  <div className="mb-1 flex flex-wrap items-center gap-2 text-xs text-muted-foreground">
86
83
  <span>{describeCronSchedule(job)}</span>
@@ -232,7 +229,11 @@ export function CronJobDetailDialog({
232
229
  {t("cronRunNow")}
233
230
  </Button>
234
231
  </SheetFooter>
235
- </SheetContent>
236
- </Sheet>
232
+ </>
237
233
  );
234
+ return <Sheet open={!embedded && open} onOpenChange={onOpenChange}>
235
+ {embedded ? <div className="flex h-full min-h-0 flex-col" data-testid="cron-job-detail">{content}</div> : (
236
+ <SheetContent side="right" closeLabel={t("cronCloseDetails")} className="flex w-full flex-col overflow-hidden p-0 sm:max-w-[510px]">{content}</SheetContent>
237
+ )}
238
+ </Sheet>;
238
239
  }
@@ -0,0 +1,51 @@
1
+ import { CronJobDetailDialog } from "./cron-job-detail-dialog";
2
+ import { useCronJobs } from "@/features/cron/hooks/use-cron-jobs";
3
+ import { useCronJobActions } from "@/features/cron/hooks/use-cron-job-actions";
4
+ import { t } from "@/shared/lib/i18n";
5
+
6
+ export function CronJobResource({ jobId }: { jobId: string }) {
7
+ const query = useCronJobs({ all: true });
8
+ const actions = useCronJobActions();
9
+ const job = query.data?.jobs.find((item) => item.id === jobId);
10
+ if (query.isPending)
11
+ return (
12
+ <p role="status" className="p-4">
13
+ {t("loading")}
14
+ </p>
15
+ );
16
+ if (query.isError)
17
+ return (
18
+ <div className="p-4">
19
+ <p role="alert">{t("resourceLoadFailed")}</p>
20
+ <button onClick={() => void query.refetch()}>
21
+ {t("resourceRetry")}
22
+ </button>
23
+ </div>
24
+ );
25
+ if (!job)
26
+ return (
27
+ <p role="alert" className="p-4">
28
+ {t("resourceNotFound")}
29
+ </p>
30
+ );
31
+ return (
32
+ <>
33
+ <CronJobDetailDialog
34
+ embedded
35
+ job={job}
36
+ open
37
+ onOpenChange={() => {}}
38
+ onDelete={(value) => {
39
+ void actions.deleteJob(value);
40
+ }}
41
+ onRun={(value) => {
42
+ void actions.runJob(value);
43
+ }}
44
+ onToggle={(value, enabled) => {
45
+ void actions.toggleJob(value, enabled);
46
+ }}
47
+ />
48
+ <actions.ConfirmDialog />
49
+ </>
50
+ );
51
+ }
@@ -1,3 +1,4 @@
1
+ import { ACTION_FEEDBACK, ACTION_MENU_ITEM_CLASS } from '@/shared/components/ui/actions/action-feedback';
1
2
  import { PageResourceActionItems } from '@/features/right-panel-resources';
2
3
  import { pageResourceFromSystemObject } from '@/features/right-panel-resources';
3
4
  import { useState } from "react";
@@ -206,9 +207,9 @@ export function CronJobRow({
206
207
  setMenuOpen(false);
207
208
  onRun(job);
208
209
  }}
209
- className="flex w-full items-center gap-2 rounded-lg px-3 py-2 text-sm text-foreground transition-colors hover:bg-[var(--interaction-hover)]"
210
+ className={`${ACTION_MENU_ITEM_CLASS} text-foreground ${ACTION_FEEDBACK.item}`}
210
211
  >
211
- <Play className="h-3.5 w-3.5 text-muted-foreground" />
212
+ <Play className="h-4 w-4 shrink-0 text-muted-foreground" />
212
213
  {t("cronRunNow")}
213
214
  </button>
214
215
  <button
@@ -217,9 +218,9 @@ export function CronJobRow({
217
218
  setMenuOpen(false);
218
219
  onDelete(job);
219
220
  }}
220
- className="flex w-full items-center gap-2 rounded-lg px-3 py-2 text-sm text-red-600 transition-colors hover:bg-destructive/10"
221
+ className={`${ACTION_MENU_ITEM_CLASS} ${ACTION_FEEDBACK.destructive}`}
221
222
  >
222
- <Trash2 className="h-3.5 w-3.5" />
223
+ <Trash2 className="h-4 w-4 shrink-0" />
223
224
  {t("delete")}
224
225
  </button>
225
226
  <div className="my-1 h-px bg-border" />
@@ -1,4 +1,5 @@
1
1
  export { CronConfig } from "./components/cron-config";
2
+ export { CronJobResource } from "./components/cron-job-resource";
2
3
  export { CronJobDetailDialog } from "./components/cron-job-detail-dialog";
3
4
  export { useCronJobActions } from "./hooks/use-cron-job-actions";
4
5
  export {
@@ -11,13 +11,13 @@ import {
11
11
  } from "@/shared/components/ui/dialog";
12
12
  import { Button } from "@/shared/components/ui/button";
13
13
  import { appQueryClient } from "@/app-query-client";
14
- import { nextclawClient } from "@/shared/lib/api/managers/client.manager";
14
+ import { nextclawClient } from "@/shared/lib/api";
15
15
  import { t } from "@/shared/lib/i18n";
16
- import { desktopCapabilityManager } from "../managers/desktop-capability.manager";
16
+ import { desktopCapabilityManager } from "@/features/desktop-capabilities/managers/desktop-capability.manager";
17
17
  import {
18
18
  type DesktopAuthorizationRequest,
19
19
  useDesktopAuthorizationStore,
20
- } from "../stores/desktop-authorization.store";
20
+ } from "@/features/desktop-capabilities/stores/desktop-authorization.store";
21
21
 
22
22
  const AUTHORIZATION_EVENT_TYPE = "desktop.authorization.required";
23
23
 
@@ -61,8 +61,8 @@ export function DesktopAuthorizationDialog() {
61
61
  if (!open && !isGranting) clear();
62
62
  }}
63
63
  >
64
- <DialogContent className="[&>:last-child]:hidden">
65
- <DialogHeader>
64
+ <DialogContent>
65
+ <DialogHeader showClose={false}>
66
66
  <DialogTitle className="flex items-center gap-2">
67
67
  <ShieldAlert className="h-4 w-4 text-amber-600" />
68
68
  {t("desktopAuthorizationTitle")}
@@ -1,7 +1,7 @@
1
1
  import { fireEvent, render, screen, waitFor } from "@testing-library/react";
2
2
  import { MemoryRouter, useLocation } from "react-router-dom";
3
3
  import { beforeEach, describe, expect, it, vi } from "vitest";
4
- import { CHAT_DRAFT_SESSION_PATH } from "@/features/chat";
4
+ import { buildSessionPath, CHAT_DRAFT_SESSION_PATH } from "@/features/chat";
5
5
  import { InboxReaderDialog } from "@/features/inbox/components/inbox-reader-dialog";
6
6
  import { useInboxStore } from "@/features/inbox/stores/inbox.store";
7
7
  import { t } from "@/shared/lib/i18n";
@@ -9,6 +9,7 @@ import { t } from "@/shared/lib/i18n";
9
9
  const mocks = vi.hoisted(() => ({
10
10
  closeReader: vi.fn(),
11
11
  contentType: "markdown",
12
+ deliveryCount: 1,
12
13
  prepareChatReference: vi.fn(),
13
14
  requestSystemObjectReference: vi.fn(),
14
15
  markRead: vi.fn(),
@@ -17,16 +18,17 @@ const mocks = vi.hoisted(() => ({
17
18
 
18
19
  vi.mock("@/app/components/app-presenter-provider", () => ({
19
20
  useAppPresenter: () => ({
21
+ docBrowserManager: { close: vi.fn() },
20
22
  inboxManager: mocks,
21
- chatDraftIntentManager: { requestSystemObjectReference: mocks.requestSystemObjectReference },
23
+ chatComposerIntentManager: { requestSystemObjectReference: mocks.requestSystemObjectReference },
22
24
  }),
23
25
  }));
24
26
 
25
27
  vi.mock("@/features/inbox/hooks/use-inbox-deliveries", () => ({
26
28
  useInboxDeliveries: () => ({
27
29
  data: {
28
- deliveries: [{
29
- id: "delivery-1",
30
+ deliveries: Array.from({ length: mocks.deliveryCount }, (_, index) => ({
31
+ id: `delivery-${index + 1}`,
30
32
  title: "A considered report",
31
33
  summary: "A concise summary",
32
34
  content: mocks.contentType === "html"
@@ -39,7 +41,7 @@ vi.mock("@/features/inbox/hooks/use-inbox-deliveries", () => ({
39
41
  presentedAt: "2026-08-06T00:01:00.000Z",
40
42
  readAt: null,
41
43
  archivedAt: null,
42
- }],
44
+ })),
43
45
  },
44
46
  }),
45
47
  }));
@@ -58,7 +60,9 @@ describe("InboxReaderDialog", () => {
58
60
  beforeEach(() => {
59
61
  vi.clearAllMocks();
60
62
  mocks.contentType = "markdown";
63
+ mocks.deliveryCount = 1;
61
64
  mocks.prepareChatReference.mockResolvedValue({
65
+ targetSessionKey: null,
62
66
  reference: {
63
67
  uri: "nextclaw://objects/inbox-delivery/delivery-1",
64
68
  label: "A considered report",
@@ -110,9 +114,45 @@ describe("InboxReaderDialog", () => {
110
114
  });
111
115
  expect(mocks.prepareChatReference).toHaveBeenCalledWith("delivery-1");
112
116
  expect(mocks.requestSystemObjectReference).toHaveBeenCalledWith(
113
- expect.objectContaining({ uri: "nextclaw://objects/inbox-delivery/delivery-1" }),
117
+ { targetSessionKey: null, reference: expect.objectContaining({ uri: "nextclaw://objects/inbox-delivery/delivery-1" }) },
114
118
  );
115
119
  });
120
+
121
+ it("keeps every reader action accessible and opens the current report in Inbox", async () => {
122
+ render(<MemoryRouter><InboxReaderDialog /><CurrentPath /></MemoryRouter>);
123
+ for (const key of ["inboxReadLater", "inboxMarkRead", "inboxOpenInbox", "inboxContinueChat"] as const) {
124
+ expect(screen.getByRole("button", { name: t(key) })).toBeTruthy();
125
+ }
126
+ fireEvent.click(screen.getByRole("button", { name: t("inboxOpenInbox") }));
127
+ await waitFor(() => expect(screen.getByTestId("current-path").textContent).toBe("/inbox/delivery-1"));
128
+ expect(mocks.markRead).toHaveBeenCalledWith("delivery-1");
129
+ expect(mocks.closeReader).toHaveBeenCalled();
130
+ });
131
+
132
+ it("returns to the report source instead of consuming the reference in the current session", async () => {
133
+ const reference = { uri: "nextclaw://objects/inbox-delivery/delivery-1", label: "A considered report" };
134
+ mocks.prepareChatReference.mockResolvedValue({ reference, targetSessionKey: "source-session" });
135
+ render(<MemoryRouter initialEntries={[buildSessionPath("other-session")]}><InboxReaderDialog /><CurrentPath /></MemoryRouter>);
136
+ fireEvent.click(screen.getByRole("button", { name: t("inboxContinueChat") }));
137
+ await waitFor(() => expect(screen.getByTestId("current-path").textContent).toBe(buildSessionPath("source-session")));
138
+ expect(mocks.requestSystemObjectReference).toHaveBeenCalledWith({ targetSessionKey: "source-session", reference });
139
+ });
140
+
141
+ it("closes through the shared icon action", () => {
142
+ render(<MemoryRouter><InboxReaderDialog /></MemoryRouter>);
143
+ fireEvent.click(screen.getByRole("button", { name: t("close") }));
144
+ expect(mocks.closeReader).toHaveBeenCalledOnce();
145
+ });
146
+
147
+ it("navigates multiple reports without triggering the adjacent close action", async () => {
148
+ mocks.deliveryCount = 2;
149
+ render(<MemoryRouter><InboxReaderDialog /></MemoryRouter>);
150
+ expect((screen.getByRole("button", { name: t("inboxPrevious") }) as HTMLButtonElement).disabled).toBe(true);
151
+ fireEvent.click(screen.getByRole("button", { name: t("inboxNext") }));
152
+ await waitFor(() => expect(mocks.selectInReader).toHaveBeenCalledWith("delivery-2"));
153
+ expect(mocks.closeReader).not.toHaveBeenCalled();
154
+ expect(screen.getAllByRole("button", { name: t("close") })).toHaveLength(1);
155
+ });
116
156
  });
117
157
 
118
158
  // Resource policy has separate integration coverage; keep this fixture scoped to its business UI.
@@ -4,7 +4,8 @@ import { useRef, useState } from "react";
4
4
  import { ChevronLeft, ChevronRight, Inbox } from "lucide-react";
5
5
  import { useNavigate } from "react-router-dom";
6
6
  import { useAppPresenter } from "@/app/components/app-presenter-provider";
7
- import { CHAT_DRAFT_SESSION_PATH } from "@/features/chat";
7
+ import { useViewportLayout } from "@/app/hooks/use-viewport-layout";
8
+ import { buildSessionPath, CHAT_DRAFT_SESSION_PATH } from "@/features/chat";
8
9
  import { InboxDeliveryContent } from "@/features/inbox/components/inbox-delivery-content";
9
10
  import { useInboxDeliveries } from "@/features/inbox/hooks/use-inbox-deliveries";
10
11
  import { useInboxStore } from "@/features/inbox/stores/inbox.store";
@@ -13,6 +14,7 @@ import {
13
14
  Dialog,
14
15
  DialogContent,
15
16
  DialogDescription,
17
+ DialogHeader,
16
18
  DialogTitle,
17
19
  } from "@/shared/components/ui/dialog";
18
20
  import { IconActionButton } from "@/shared/components/ui/actions/icon-action-button";
@@ -28,7 +30,8 @@ function formatPosition(current: number, total: number): string {
28
30
  export function InboxReaderDialog() {
29
31
  const titleRef = useRef<HTMLHeadingElement>(null);
30
32
  const navigate = useNavigate();
31
- const { chatDraftIntentManager, inboxManager } = useAppPresenter();
33
+ const { chatComposerIntentManager, docBrowserManager, inboxManager } = useAppPresenter();
34
+ const { isMobile } = useViewportLayout();
32
35
  const { data } = useInboxDeliveries();
33
36
  const { activeDeliveryId, readerOpen } = useInboxStore((state) => state.snapshot);
34
37
  const [pendingAction, setPendingAction] = useState<string | null>(null);
@@ -77,9 +80,10 @@ export function InboxReaderDialog() {
77
80
  return;
78
81
  }
79
82
  void runAction("continue", async () => {
80
- const { reference } = await inboxManager.prepareChatReference(activeDelivery.id);
81
- chatDraftIntentManager.requestSystemObjectReference(reference);
82
- navigate(CHAT_DRAFT_SESSION_PATH);
83
+ const { reference, targetSessionKey } = await inboxManager.prepareChatReference(activeDelivery.id);
84
+ chatComposerIntentManager.requestSystemObjectReference({ targetSessionKey, reference });
85
+ if (isMobile) docBrowserManager.close();
86
+ navigate(targetSessionKey ? buildSessionPath(targetSessionKey) : CHAT_DRAFT_SESSION_PATH);
83
87
  });
84
88
  };
85
89
 
@@ -96,15 +100,18 @@ export function InboxReaderDialog() {
96
100
  const positionControls = unreadDeliveries.length > 1 ? (
97
101
  <div className="flex shrink-0 items-center gap-1 pr-1">
98
102
  <span className="mr-1 text-[11px] tabular-nums text-muted-foreground">
99
- {formatPosition(activeIndex + 1, unreadDeliveries.length)}
103
+ <span className="hidden md:inline">{formatPosition(activeIndex + 1, unreadDeliveries.length)}</span>
104
+ <span className="md:hidden" aria-label={formatPosition(activeIndex + 1, unreadDeliveries.length)}>{activeIndex + 1}/{unreadDeliveries.length}</span>
100
105
  </span>
101
106
  <IconActionButton
107
+ size="sm"
102
108
  icon={<ChevronLeft className="h-4 w-4" />}
103
109
  label={t("inboxPrevious")}
104
110
  disabled={activeIndex <= 0 || pendingAction === "select"}
105
111
  onClick={() => selectAt(activeIndex - 1)}
106
112
  />
107
113
  <IconActionButton
114
+ size="sm"
108
115
  icon={<ChevronRight className="h-4 w-4" />}
109
116
  label={t("inboxNext")}
110
117
  disabled={activeIndex >= unreadDeliveries.length - 1 || pendingAction === "select"}
@@ -123,7 +130,7 @@ export function InboxReaderDialog() {
123
130
  }}
124
131
  >
125
132
  <DialogContent
126
- className="flex h-[min(82vh,760px)] w-[calc(100vw-2rem)] max-w-[820px] flex-col gap-0 overflow-hidden rounded-[24px] border-border/70 bg-background p-0 shadow-[0_20px_55px_-22px_rgba(15,23,42,0.32)] max-sm:h-[100dvh] max-sm:max-h-none max-sm:w-screen max-sm:rounded-none max-sm:border-0"
133
+ className="flex h-[min(82vh,760px)] w-[calc(100vw-2rem)] max-w-[820px] flex-col gap-0 overflow-hidden rounded-[24px] border-border/70 bg-background p-0 shadow-[0_20px_55px_-22px_rgba(15,23,42,0.32)] max-md:h-[100dvh] max-md:max-h-[100dvh] max-md:w-screen max-md:max-w-none max-md:rounded-none max-md:border-0 max-md:pt-[env(safe-area-inset-top,0px)] max-md:pb-[env(safe-area-inset-bottom,0px)]"
127
134
  onOpenAutoFocus={(event) => {
128
135
  event.preventDefault();
129
136
  titleRef.current?.focus();
@@ -131,10 +138,15 @@ export function InboxReaderDialog() {
131
138
  >
132
139
  {activeDelivery ? (
133
140
  <>
134
- <header className="shrink-0 border-b border-border/50 px-5 py-3 pr-14 sm:px-6">
135
- <div className="flex min-h-7 items-center justify-between gap-3">
141
+ <DialogHeader
142
+ className="items-center gap-1 border-b border-border/50 px-3 py-2 md:gap-3 md:px-6 md:py-3"
143
+ actions={<>
144
+ {positionControls}
145
+ <PageResourceActionsMenu page={pageResourceFromSystemObject("inbox-delivery", activeDelivery.id, activeDelivery.title)} />
146
+ </>}
147
+ >
136
148
  <div className="flex min-w-0 items-center gap-2">
137
- <span className="flex h-7 w-7 shrink-0 items-center justify-center rounded-lg bg-muted/70 text-muted-foreground">
149
+ <span className="hidden h-7 w-7 shrink-0 items-center justify-center rounded-lg bg-muted/70 text-muted-foreground md:flex">
138
150
  <Inbox className="h-3.5 w-3.5" />
139
151
  </span>
140
152
  <DialogTitle
@@ -145,29 +157,24 @@ export function InboxReaderDialog() {
145
157
  >
146
158
  {activeDelivery.title}
147
159
  </DialogTitle>
148
- <span className="hidden shrink-0 text-muted-foreground sm:inline" aria-hidden="true">·</span>
160
+ <span className="hidden shrink-0 text-muted-foreground md:inline" aria-hidden="true">·</span>
149
161
  <time
150
- className="hidden shrink-0 text-[11px] tabular-nums text-muted-foreground sm:block"
162
+ className="hidden shrink-0 text-[11px] tabular-nums text-muted-foreground md:block"
151
163
  dateTime={activeDelivery.createdAt}
152
164
  >
153
165
  {formatDateTime(activeDelivery.createdAt)}
154
166
  </time>
155
167
  </div>
156
- <div className="flex shrink-0 items-center gap-1">
157
- {positionControls}
158
- <PageResourceActionsMenu page={pageResourceFromSystemObject("inbox-delivery", activeDelivery.id, activeDelivery.title)} />
159
- </div>
160
- </div>
161
168
  <DialogDescription className="sr-only">
162
169
  {activeDelivery.summary ?? t("inboxNoSummary")}
163
170
  </DialogDescription>
164
- </header>
171
+ </DialogHeader>
165
172
 
166
173
  <div className={cn(
167
174
  "min-h-0 flex-1",
168
175
  isHtml
169
- ? "p-3 sm:p-4"
170
- : "custom-scrollbar overflow-y-auto px-6 py-5 sm:px-8 sm:py-6",
176
+ ? "p-0 md:p-4"
177
+ : "custom-scrollbar overflow-y-auto overscroll-contain px-4 py-3 md:px-8 md:py-6",
171
178
  )}>
172
179
  <InboxDeliveryContent
173
180
  className={isHtml ? "h-full" : undefined}
@@ -178,24 +185,26 @@ export function InboxReaderDialog() {
178
185
  />
179
186
  </div>
180
187
 
181
- <footer className="shrink-0 border-t border-border/50 bg-background px-5 py-3 sm:px-6">
188
+ <footer className="shrink-0 border-t border-border/50 bg-background px-3 py-2 md:px-6 md:py-3">
182
189
  {error ? (
183
190
  <p role="alert" className="mb-3 text-sm text-destructive">{error}</p>
184
191
  ) : null}
185
- <div className="flex flex-col-reverse gap-2 sm:flex-row sm:items-center sm:justify-between">
186
- <div className="flex flex-col-reverse gap-1 sm:flex-row sm:flex-wrap">
187
- <Button size="sm" variant="ghost" onClick={inboxManager.closeReader}>
192
+ <div className="flex items-center justify-between gap-2 [--control-touch-size:2rem]">
193
+ <div className="flex items-center gap-1">
194
+ <Button size="sm" className="px-2 md:px-3" variant="ghost" onClick={inboxManager.closeReader}>
188
195
  {t("inboxReadLater")}
189
196
  </Button>
190
- <Button size="sm" variant="outline" disabled={pendingAction !== null} onClick={markRead}>
197
+ <Button size="sm" className="px-2 md:px-3" variant="outline" disabled={pendingAction !== null} onClick={markRead}>
191
198
  {t("inboxMarkRead")}
192
199
  </Button>
193
- <Button size="sm" variant="ghost" disabled={pendingAction !== null} onClick={openInbox}>
194
- {t("inboxOpenInbox")}
200
+ <Button size="sm" className="px-2 md:px-3" variant="ghost" aria-label={t("inboxOpenInbox")} disabled={pendingAction !== null} onClick={openInbox}>
201
+ <span className="md:hidden">{t("inboxTitle")}</span>
202
+ <span className="hidden md:inline">{t("inboxOpenInbox")}</span>
195
203
  </Button>
196
204
  </div>
197
- <Button size="sm" disabled={pendingAction !== null} onClick={continueInChat}>
198
- {t("inboxContinueChat")}
205
+ <Button size="sm" className="px-2 md:px-3" aria-label={t("inboxContinueChat")} disabled={pendingAction !== null} onClick={continueInChat}>
206
+ <span className="md:hidden">{t("inboxContinueChatCompact")}</span>
207
+ <span className="hidden md:inline">{t("inboxContinueChat")}</span>
199
208
  </Button>
200
209
  </div>
201
210
  </footer>
@@ -1,10 +1,13 @@
1
1
  import { QueryClient } from "@tanstack/react-query";
2
2
  import { beforeEach, describe, expect, it, vi } from "vitest";
3
3
  import type { InboxDelivery } from "@nextclaw/shared";
4
+ import { NextClawClientError } from "@nextclaw/client-sdk";
4
5
  import { InboxManager } from "@/features/inbox/managers/inbox.manager";
5
6
  import { useInboxStore } from "@/features/inbox/stores/inbox.store";
6
7
 
7
8
  const mocks = vi.hoisted(() => ({
9
+ getDelivery: vi.fn(),
10
+ getSession: vi.fn(),
8
11
  delete: vi.fn(),
9
12
  resolveReference: vi.fn(),
10
13
  list: vi.fn(),
@@ -16,6 +19,7 @@ vi.mock("@/shared/lib/api", () => ({
16
19
  nextclawClient: {
17
20
  eventBus: { on: mocks.on },
18
21
  inboxDeliveries: {
22
+ get: mocks.getDelivery,
19
23
  delete: mocks.delete,
20
24
  list: mocks.list,
21
25
  updateState: mocks.updateState,
@@ -23,6 +27,7 @@ vi.mock("@/shared/lib/api", () => ({
23
27
  systemObjectReferences: {
24
28
  resolve: mocks.resolveReference,
25
29
  },
30
+ sessions: { get: mocks.getSession },
26
31
  },
27
32
  }));
28
33
 
@@ -43,6 +48,8 @@ const delivery: InboxDelivery = {
43
48
  describe("InboxManager", () => {
44
49
  beforeEach(() => {
45
50
  vi.clearAllMocks();
51
+ mocks.getDelivery.mockResolvedValue(delivery);
52
+ mocks.getSession.mockResolvedValue({ sessionId: "source-session" });
46
53
  Object.defineProperty(document, "visibilityState", { configurable: true, value: "visible" });
47
54
  useInboxStore.setState({
48
55
  snapshot: { readerOpen: false, activeDeliveryId: null },
@@ -107,5 +114,26 @@ describe("InboxManager", () => {
107
114
  );
108
115
  expect(mocks.updateState).toHaveBeenCalledWith(delivery.id, "read");
109
116
  expect(result.reference.assetUri).toBe("asset://store/report");
117
+ expect(result.targetSessionKey).toBeNull();
118
+ });
119
+
120
+ it("targets the original report session", async () => {
121
+ mocks.getDelivery.mockResolvedValue({ ...delivery, source: { ...delivery.source, sessionId: "source-session" } });
122
+ const result = await new InboxManager(new QueryClient()).prepareChatReference(delivery.id);
123
+ expect(mocks.getSession).toHaveBeenCalledWith("source-session");
124
+ expect(result.targetSessionKey).toBe("source-session");
125
+ });
126
+
127
+ it("falls back to a draft only when the source session was deleted", async () => {
128
+ mocks.getDelivery.mockResolvedValue({ ...delivery, source: { ...delivery.source, sessionId: "deleted" } });
129
+ mocks.getSession.mockRejectedValueOnce(new NextClawClientError({ message: "Missing", status: 404 }));
130
+ expect((await new InboxManager(new QueryClient()).prepareChatReference(delivery.id)).targetSessionKey).toBeNull();
131
+ });
132
+
133
+ it("keeps the report unread when the source session lookup fails", async () => {
134
+ mocks.getDelivery.mockResolvedValue({ ...delivery, source: { ...delivery.source, sessionId: "source-session" } });
135
+ mocks.getSession.mockRejectedValueOnce(new NextClawClientError({ message: "Offline", status: 503 }));
136
+ await expect(new InboxManager(new QueryClient()).prepareChatReference(delivery.id)).rejects.toThrow("Offline");
137
+ expect(mocks.updateState).not.toHaveBeenCalled();
110
138
  });
111
139
  });
@@ -13,6 +13,7 @@ import {
13
13
  import { appQueryClient } from "@/app-query-client";
14
14
  import { useInboxStore } from "@/features/inbox/stores/inbox.store";
15
15
  import { nextclawClient } from "@/shared/lib/api";
16
+ import { NextClawClientError } from "@nextclaw/client-sdk";
16
17
 
17
18
  export const INBOX_DELIVERIES_QUERY_KEY = ["inbox-deliveries"] as const;
18
19
 
@@ -112,13 +113,26 @@ export class InboxManager {
112
113
  prepareChatReference = async (deliveryId: string): Promise<{
113
114
  delivery: InboxDelivery;
114
115
  reference: SystemObjectResolvedReference;
116
+ targetSessionKey: string | null;
115
117
  }> => {
116
- const reference = await nextclawClient.systemObjectReferences.resolve(
117
- createSystemObjectReferenceUri(SYSTEM_OBJECT_TYPE_INBOX_DELIVERY, deliveryId),
118
- );
118
+ const [reference, sourceDelivery] = await Promise.all([
119
+ nextclawClient.systemObjectReferences.resolve(
120
+ createSystemObjectReferenceUri(SYSTEM_OBJECT_TYPE_INBOX_DELIVERY, deliveryId),
121
+ ),
122
+ nextclawClient.inboxDeliveries.get(deliveryId),
123
+ ]);
124
+ let targetSessionKey = sourceDelivery.source.sessionId?.trim() || null;
125
+ if (targetSessionKey) {
126
+ try {
127
+ await nextclawClient.sessions.get(targetSessionKey);
128
+ } catch (error) {
129
+ if (!(error instanceof NextClawClientError) || error.status !== 404) throw error;
130
+ targetSessionKey = null;
131
+ }
132
+ }
119
133
  const delivery = await this.updateState(deliveryId, "read");
120
134
  this.closeReader();
121
- return { delivery, reference };
135
+ return { delivery, reference, targetSessionKey };
122
136
  };
123
137
 
124
138
  private updateState = async (
@@ -14,7 +14,8 @@ const mocks = vi.hoisted(() => ({
14
14
 
15
15
  vi.mock("@/app/components/app-presenter-provider", () => ({
16
16
  useAppPresenter: () => ({
17
- chatDraftIntentManager: {
17
+ docBrowserManager: { close: vi.fn() },
18
+ chatComposerIntentManager: {
18
19
  requestSystemObjectReference: mocks.requestSystemObjectReference,
19
20
  },
20
21
  inboxManager: {
@@ -104,6 +105,7 @@ describe("InboxPage", () => {
104
105
  vi.clearAllMocks();
105
106
  mocks.isMobile = false;
106
107
  mocks.prepareChatReference.mockResolvedValue({
108
+ targetSessionKey: null,
107
109
  reference: {
108
110
  uri: "nextclaw://objects/inbox-delivery/delivery-1",
109
111
  label: "A considered report",
@@ -150,7 +152,7 @@ describe("InboxPage", () => {
150
152
  });
151
153
  expect(mocks.prepareChatReference).toHaveBeenCalledWith("delivery-1");
152
154
  expect(mocks.requestSystemObjectReference).toHaveBeenCalledWith(
153
- expect.objectContaining({ uri: "nextclaw://objects/inbox-delivery/delivery-1" }),
155
+ { targetSessionKey: null, reference: expect.objectContaining({ uri: "nextclaw://objects/inbox-delivery/delivery-1" }) },
154
156
  );
155
157
  });
156
158
  });