@nextclaw/ui 0.15.22 → 0.15.23

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 (423) hide show
  1. package/CHANGELOG.md +49 -0
  2. package/dist/assets/{abnfDiagram-VRR7QNED-M4g_AyR8.js → abnfDiagram-VRR7QNED-DvTjgVMf.js} +1 -1
  3. package/dist/assets/{aiden0z-pptx-renderer.es-Bd99vut2.js → aiden0z-pptx-renderer.es-C1nfBAXR.js} +1 -1
  4. package/dist/assets/api-Glw2OGXK.js +13 -0
  5. package/dist/assets/appearance-settings-page-Bl_W_9m7.js +1 -0
  6. package/dist/assets/{arc-IO7WNWOB.js → arc-BvhODBXv.js} +1 -1
  7. package/dist/assets/architecture-TIHT7OUA-Bjp9jf0h.js +1 -0
  8. package/dist/assets/{architectureDiagram-ZJ3FMSHR-Dc-lvdUh.js → architectureDiagram-ZJ3FMSHR-BKO9RgNS.js} +1 -1
  9. package/dist/assets/{blockDiagram-677ZJIJ3-CcsoWpIY.js → blockDiagram-677ZJIJ3-DHpDXy7D.js} +1 -1
  10. package/dist/assets/{c4Diagram-LMCZKHZV-Bsrtg6b2.js → c4Diagram-LMCZKHZV-BG_iQnDr.js} +1 -1
  11. package/dist/assets/channel-5T3pdR-s.js +1 -0
  12. package/dist/assets/channels-list-page-C7E4Sxwd.js +8 -0
  13. package/dist/assets/chat-page-BT6dNI-4.js +1 -0
  14. package/dist/assets/chunk-2Q5K7J3B-DTZ3tGfE.js +1 -0
  15. package/dist/assets/{chunk-32BRIVSS-Bt08t8oG.js → chunk-32BRIVSS-DR9M0LLx.js} +1 -1
  16. package/dist/assets/{chunk-52WLFC77-Ddx68Xzx.js → chunk-52WLFC77-698iC3BB.js} +1 -1
  17. package/dist/assets/{chunk-5FCAYU7R-B7p9_q55.js → chunk-5FCAYU7R-DikTj9Ey.js} +1 -1
  18. package/dist/assets/{chunk-5HE753X5-D52KvdTm.js → chunk-5HE753X5-ko0o7_q0.js} +1 -1
  19. package/dist/assets/{chunk-5JV3BV7I-C329h8nI.js → chunk-5JV3BV7I-CEHufhgo.js} +1 -1
  20. package/dist/assets/{chunk-5TONJI2A-BZyUBxWt.js → chunk-5TONJI2A-CGgno1cu.js} +1 -1
  21. package/dist/assets/{chunk-5VM5RSS4-BUiYXZmu.js → chunk-5VM5RSS4-DkiB4cUQ.js} +1 -1
  22. package/dist/assets/{chunk-7BUUIJ7U-B7o-mn4r.js → chunk-7BUUIJ7U-DzptcytQ.js} +1 -1
  23. package/dist/assets/{chunk-BIQX33UG-Bey9GoRP.js → chunk-BIQX33UG-DMRSQJvT.js} +1 -1
  24. package/dist/assets/{chunk-C7G6YPKG-C6tosszM.js → chunk-C7G6YPKG-Bw1BwwuY.js} +1 -1
  25. package/dist/assets/{chunk-CQNSW5MT-BNrdkgGQ.js → chunk-CQNSW5MT-C0z6eHBk.js} +1 -1
  26. package/dist/assets/{chunk-CYSBUYHQ-DHODFeyB.js → chunk-CYSBUYHQ-ByPyAouO.js} +1 -1
  27. package/dist/assets/{chunk-EMLP6XTP-BcmLjrcq.js → chunk-EMLP6XTP-CJlAXWZg.js} +1 -1
  28. package/dist/assets/{chunk-EX3LRPZG-r-_eEtJI.js → chunk-EX3LRPZG-Dqq4zKJu.js} +1 -1
  29. package/dist/assets/{chunk-FWX5IMBZ-DOObDWbf.js → chunk-FWX5IMBZ-B0SNoCmi.js} +2 -2
  30. package/dist/assets/{chunk-HOUHSVGY-Bd0FnbWZ.js → chunk-HOUHSVGY-DG_GJih_.js} +1 -1
  31. package/dist/assets/{chunk-ICXQ74PX-ntNwAm4_.js → chunk-ICXQ74PX-Drxk_6bE.js} +1 -1
  32. package/dist/assets/{chunk-JG7HCLWE-YtRpblZN.js → chunk-JG7HCLWE-DdLFPpnd.js} +1 -1
  33. package/dist/assets/{chunk-JWPE2WC7-De5-D9ta.js → chunk-JWPE2WC7-B8M4G76F.js} +1 -1
  34. package/dist/assets/{chunk-MOJQB5TN-CdvKhyp2.js → chunk-MOJQB5TN-XP6FJHY_.js} +1 -1
  35. package/dist/assets/{chunk-MOZMSUNE-DJMMN_lu.js → chunk-MOZMSUNE-C_6x18Qw.js} +1 -1
  36. package/dist/assets/{chunk-OGEWGWER-DOFWVw3O.js → chunk-OGEWGWER-N25BzCmG.js} +1 -1
  37. package/dist/assets/{chunk-OSBZ3O6U-DZkrIN9r.js → chunk-OSBZ3O6U-ASDEm7y0.js} +1 -1
  38. package/dist/assets/{chunk-PUDLZKDR-D1wma2Yf.js → chunk-PUDLZKDR-CTlvAcn7.js} +1 -1
  39. package/dist/assets/{chunk-Q4XR5HBZ-CjPy94Lz.js → chunk-Q4XR5HBZ-Da9BWfB6.js} +1 -1
  40. package/dist/assets/{chunk-QBLGF6JB-Hy1bEgS-.js → chunk-QBLGF6JB-Bi6RpTJO.js} +1 -1
  41. package/dist/assets/{chunk-R7FJI6CG-CUPIHyh-.js → chunk-R7FJI6CG-DkMsSPvK.js} +1 -1
  42. package/dist/assets/{chunk-RYQCIY6F-D5Ua4pcv.js → chunk-RYQCIY6F-DZp0eU-j.js} +1 -1
  43. package/dist/assets/{chunk-U6XO7XAA-DaUQcqb7.js → chunk-U6XO7XAA-vfinDSrj.js} +1 -1
  44. package/dist/assets/{chunk-V7JOEXUC-DX2zLfQe.js → chunk-V7JOEXUC-C9Nksccs.js} +1 -1
  45. package/dist/assets/chunk-VAUOI2AC-HLGIHQ6k.js +1 -0
  46. package/dist/assets/{chunk-VR4S4FIN-CFA-WQik.js → chunk-VR4S4FIN-Xv6zfwXs.js} +1 -1
  47. package/dist/assets/{chunk-WYO6CB5R-Bk2HeDvJ.js → chunk-WYO6CB5R-mOJNzbWl.js} +2 -2
  48. package/dist/assets/chunk-XXDRQBXY-Dl0m6Ni-.js +1 -0
  49. package/dist/assets/{chunk-YOTPTUD7-DUG4FpBN.js → chunk-YOTPTUD7-1-aKSu4o.js} +1 -1
  50. package/dist/assets/{chunk-ZGVPDNZ5-70JdIGo0.js → chunk-ZGVPDNZ5-OJ8veMpK.js} +1 -1
  51. package/dist/assets/{chunk-ZIRB5QZD-XZdgBt5L.js → chunk-ZIRB5QZD-SR_Nq_PP.js} +1 -1
  52. package/dist/assets/classDiagram-OUVF2IWQ-DcDnzGNX.js +1 -0
  53. package/dist/assets/classDiagram-v2-EOCWNBFH-BKXKMzKM.js +1 -0
  54. package/dist/assets/{config-split-page-BgBsUmp1.js → config-split-page-D5BgtKrm.js} +1 -1
  55. package/dist/assets/confirm-dialog-Bf907Azu.js +5 -0
  56. package/dist/assets/{cose-bilkent-JH36ORCC-B-PQoGX-.js → cose-bilkent-JH36ORCC-NjVgz2Bw.js} +1 -1
  57. package/dist/assets/cynefin-VYW2F7L2-BWg7U2UD.js +1 -0
  58. package/dist/assets/{cynefinDiagram-TSTJHNR4-BoLCPEM0.js → cynefinDiagram-TSTJHNR4-B_17LDqD.js} +1 -1
  59. package/dist/assets/{dagre-D7Ie4eXr.js → dagre-CMe101gk.js} +1 -1
  60. package/dist/assets/{dagre-VKFMJZFB-CKRrwZA-.js → dagre-VKFMJZFB-qo8nLb3B.js} +1 -1
  61. package/dist/assets/desktop-update-config-BwuyBPJb.js +1 -0
  62. package/dist/assets/{diagram-FQU43EPY-CASL1J3_.js → diagram-FQU43EPY-Ba3XIklC.js} +1 -1
  63. package/dist/assets/{diagram-G47NLZAW-CvLPBIzf.js → diagram-G47NLZAW-CG45TcUx.js} +1 -1
  64. package/dist/assets/{diagram-NH7WQ7WH-Ba6fGdYP.js → diagram-NH7WQ7WH-2F2HrwV-.js} +1 -1
  65. package/dist/assets/{diagram-OA4YK3LP-DkpfgEjM.js → diagram-OA4YK3LP-CXfWH9NZ.js} +1 -1
  66. package/dist/assets/{diagram-WEI45ONY-BP5UMVsN.js → diagram-WEI45ONY-CH_4yepc.js} +1 -1
  67. package/dist/assets/dist-CtLyEJeO.js +1 -0
  68. package/dist/assets/dist-dv_SUR54.js +1 -0
  69. package/dist/assets/doc-browser-C23NDGh5.js +1 -0
  70. package/dist/assets/doc-browser-DlOOhBxI.js +1 -0
  71. package/dist/assets/doc-browser-context-BIBjkwfV.js +1 -0
  72. package/dist/assets/{docx-preview-D0tp3a9T.js → docx-preview-CoM4JK7_.js} +1 -1
  73. package/dist/assets/{ebnfDiagram-CCIWWBDH-TJKbUcmc.js → ebnfDiagram-CCIWWBDH-BwiG4Ea1.js} +1 -1
  74. package/dist/assets/{erDiagram-Q63AITRT-DzGPKkKH.js → erDiagram-Q63AITRT-BML3hpnQ.js} +1 -1
  75. package/dist/assets/eventmodeling-45OFAUF4-SB-J4tpq.js +1 -0
  76. package/dist/assets/flowDiagram-23GEKE2U-BQ_u-eLM.js +1 -0
  77. package/dist/assets/{form-actions-CgjYZUzM.js → form-actions-DAzi68Cn.js} +1 -1
  78. package/dist/assets/{ganttDiagram-NO4QXBWP-JhJzsGp2.js → ganttDiagram-NO4QXBWP-80enfWbD.js} +1 -1
  79. package/dist/assets/gitGraph-TEB2WS4Q-DPxNwsFd.js +1 -0
  80. package/dist/assets/{gitGraphDiagram-IHSO6WYX-DZ1CKMj8.js → gitGraphDiagram-IHSO6WYX-CVLqXr-b.js} +1 -1
  81. package/dist/assets/host-capabilities-D9C4CBK5.js +1 -0
  82. package/dist/assets/index-BLNg2yg0.css +1 -0
  83. package/dist/assets/index-D3EKjEyK.js +107 -0
  84. package/dist/assets/info-DKCQHKI2-DNlNGH90.js +1 -0
  85. package/dist/assets/{infoDiagram-FWYZ7A6U-BNXNKfRQ.js → infoDiagram-FWYZ7A6U-Dyvs2t0i.js} +1 -1
  86. package/dist/assets/{ishikawaDiagram-FXEZZL3T-DoiEfjNw.js → ishikawaDiagram-FXEZZL3T-sSnxDKfh.js} +1 -1
  87. package/dist/assets/{journeyDiagram-5HDEW3XC-D6oK2HSy.js → journeyDiagram-5HDEW3XC-D22V71Mf.js} +1 -1
  88. package/dist/assets/{kanban-definition-HUTT4EX6-B2UnLOH-.js → kanban-definition-HUTT4EX6-D3ds0p-g.js} +1 -1
  89. package/dist/assets/{line-BM7PoxY5.js → line-CbyFs065.js} +1 -1
  90. package/dist/assets/{linear-B3DiqMjk.js → linear-4DKtnZBS.js} +1 -1
  91. package/dist/assets/loader-circle-BSg5u0r4.js +1 -0
  92. package/dist/assets/{map-BAAdHTqR.js → map-CcZzEoz6.js} +1 -1
  93. package/dist/assets/mcp-marketplace-page-ByhvQQj5.js +9 -0
  94. package/dist/assets/mcp-marketplace-page-CytXwnUs.js +1 -0
  95. package/dist/assets/{mermaid-parser.core-BeMviefY.js → mermaid-parser.core-DPmMOjXD.js} +2 -2
  96. package/dist/assets/{mermaid.core-D0Q77r9I.js → mermaid.core-BSf-ddRa.js} +3 -3
  97. package/dist/assets/{mindmap-definition-LN4V7U3C-BQ7r7bR8.js → mindmap-definition-LN4V7U3C-BUTwWPyx.js} +1 -1
  98. package/dist/assets/model-config-page-bgEx3MjQ.js +1 -0
  99. package/dist/assets/navigation-link-CB0OQbnY.js +3 -0
  100. package/dist/assets/{ordinal-Bt2N4IkA.js → ordinal-BgLYtOZE.js} +1 -1
  101. package/dist/assets/packet-7NZHBO7P-BpeiqkBZ.js +1 -0
  102. package/dist/assets/{pegDiagram-2B236MQR-B-C9-LGz.js → pegDiagram-2B236MQR-BEu_ZBjc.js} +1 -1
  103. package/dist/assets/pie-RZYD4A2V-Cy1yxsPd.js +1 -0
  104. package/dist/assets/{pieDiagram-ENE6RG2P-CtirZLtn.js → pieDiagram-ENE6RG2P-CAwAwuBd.js} +1 -1
  105. package/dist/assets/plus-CNjWdLhZ.js +1 -0
  106. package/dist/assets/provider-scoped-model-input-8F6JMd2n.js +1 -0
  107. package/dist/assets/providers-config-page-CxpTjR81.js +1 -0
  108. package/dist/assets/{quadrantDiagram-ABIIQ3AL-DiBWAzDU.js → quadrantDiagram-ABIIQ3AL-CwE6F-_2.js} +1 -1
  109. package/dist/assets/radar-I7S5WNFK-CEcPKCj8.js +1 -0
  110. package/dist/assets/railroad-3IZDKUUU-CW38eNDs.js +1 -0
  111. package/dist/assets/railroad-abnf-AHOZXSZD-ByrylcXf.js +1 -0
  112. package/dist/assets/railroad-ebnf-EBAXGLYW-CNB6GwP-.js +1 -0
  113. package/dist/assets/railroad-peg-LSFZ7HO6-x6hnqlBG.js +1 -0
  114. package/dist/assets/{railroadDiagram-RFXS5EU6-CP6b3PBI.js → railroadDiagram-RFXS5EU6-xgLekU3B.js} +1 -1
  115. package/dist/assets/react-Bk2ydNTe.js +8 -0
  116. package/dist/assets/{refresh-cw-CkKwPztT.js → refresh-cw-Ba0LZou4.js} +1 -1
  117. package/dist/assets/remote-Dv38PuMV.js +1 -0
  118. package/dist/assets/{requirementDiagram-TGXJPOKE-D8YV0-Jz.js → requirementDiagram-TGXJPOKE-CyVUzEX5.js} +1 -1
  119. package/dist/assets/rotate-cw-IkYVk9JX.js +1 -0
  120. package/dist/assets/runtime-config-page-C0ByyUVr.js +1 -0
  121. package/dist/assets/{sankeyDiagram-HTMAVEWB-C2vA4ojE.js → sankeyDiagram-HTMAVEWB-JK6bFmYB.js} +1 -1
  122. package/dist/assets/{save-BINMWate.js → save-DTOAvqzt.js} +1 -1
  123. package/dist/assets/{search-7M38azRp.js → search-D4X5DNMe.js} +1 -1
  124. package/dist/assets/search-config-page-Cr6254K5.js +1 -0
  125. package/dist/assets/{secrets-config-page-2mVejXf2.js → secrets-config-page-W2Hx332d.js} +2 -2
  126. package/dist/assets/security-config-1E8OF4kR.js +1 -0
  127. package/dist/assets/select-CDv0g2Pj.js +41 -0
  128. package/dist/assets/{sequenceDiagram-DBY2YBRQ-B9LBmpUo.js → sequenceDiagram-DBY2YBRQ-BR5IokXV.js} +1 -1
  129. package/dist/assets/{settings-2-DqZstREV.js → settings-2-CoxzNABp.js} +1 -1
  130. package/dist/assets/{sizeCapture-X5ZJPWSS-9UIfya9-.js → sizeCapture-X5ZJPWSS-SxG_YnMA.js} +1 -1
  131. package/dist/assets/skeleton-DW018fJv.js +1 -0
  132. package/dist/assets/{src-DKf77Yzo.js → src-vgz8E_-O.js} +1 -1
  133. package/dist/assets/{stateDiagram-2N3HPSRC-oTW44vds.js → stateDiagram-2N3HPSRC-DD4OoYhn.js} +1 -1
  134. package/dist/assets/stateDiagram-v2-6OUMAXLB-ZC6dFORv.js +1 -0
  135. package/dist/assets/{swimlanes-5IMT3BWC-Cf7lcsay.js → swimlanes-5IMT3BWC-BWkFeyCT.js} +2 -2
  136. package/dist/assets/swimlanesDiagram-G3AALYLV-CRkh51Im.js +8 -0
  137. package/dist/assets/{tag-chip-BoDaLnWt.js → tag-chip-CjkZEoS2.js} +1 -1
  138. package/dist/assets/{timeline-definition-FHXFAJF6-DoCuWKDJ.js → timeline-definition-FHXFAJF6-VTRPy6KA.js} +1 -1
  139. package/dist/assets/treeView-QDETBFTQ-Bw0DSCH7.js +1 -0
  140. package/dist/assets/treemap-6X3UGDF4-DFWBFcfh.js +1 -0
  141. package/dist/assets/use-confirm-dialog-CavtY1vJ.js +1 -0
  142. package/dist/assets/{vennDiagram-L72KCM5P-CpU0pzGe.js → vennDiagram-L72KCM5P-Bvk42Pek.js} +1 -1
  143. package/dist/assets/wardley-OPB4EBWU-CoWturk0.js +1 -0
  144. package/dist/assets/{wardleyDiagram-EHGQE667-CkN6nn6-.js → wardleyDiagram-EHGQE667-DOFjx2s3.js} +1 -1
  145. package/dist/assets/x-PTXYTEwz.js +1 -0
  146. package/dist/assets/{xychartDiagram-FW5EYKEG-DATpapm2.js → xychartDiagram-FW5EYKEG-DY5yRTUc.js} +1 -1
  147. package/dist/index.html +30 -32
  148. package/index.html +8 -0
  149. package/package.json +9 -9
  150. package/src/app/components/layout/page-layout.tsx +15 -6
  151. package/src/app/styles/charcoal-theme.css +85 -0
  152. package/src/app/styles/design-system.css +11 -13
  153. package/src/features/agents/components/__tests__/agents-page.test.tsx +36 -24
  154. package/src/features/agents/components/agent-advanced-config-fields.tsx +7 -7
  155. package/src/features/agents/components/agent-details-dialog.tsx +8 -8
  156. package/src/features/agents/components/agent-dialogs.tsx +7 -7
  157. package/src/features/agents/components/agents-page.tsx +42 -62
  158. package/src/features/chat/components/conversation/__tests__/chat-conversation-content.test.tsx +27 -3
  159. package/src/features/chat/components/conversation/__tests__/chat-conversation-header-section.test.tsx +16 -0
  160. package/src/features/chat/components/conversation/__tests__/chat-conversation-panel.test.tsx +8 -22
  161. package/src/features/chat/components/conversation/__tests__/chat-conversation-workspace-section.test.tsx +69 -3
  162. package/src/features/chat/components/conversation/chat-conversation-content.tsx +20 -6
  163. package/src/features/chat/components/conversation/chat-conversation-header-section.tsx +30 -31
  164. package/src/features/chat/components/conversation/chat-conversation-panel.tsx +1 -8
  165. package/src/features/chat/components/conversation/chat-conversation-workspace-section.tsx +16 -4
  166. package/src/features/chat/components/layout/__tests__/chat-page-shell.test.tsx +23 -0
  167. package/src/features/chat/components/layout/__tests__/chat-sidebar-toolbar.test.tsx +6 -0
  168. package/src/features/chat/components/layout/chat-page-shell.tsx +5 -4
  169. package/src/features/chat/components/layout/chat-sidebar-toolbar.tsx +4 -4
  170. package/src/features/chat/components/providers/chat-presenter.provider.tsx +2 -0
  171. package/src/features/chat/features/conversation/components/__tests__/session-conversation-area.test.tsx +84 -12
  172. package/src/features/chat/features/conversation/components/__tests__/session-conversation-input.streaming.test.tsx +243 -5
  173. package/src/features/chat/features/conversation/components/session-conversation-area.tsx +48 -31
  174. package/src/features/chat/features/conversation/components/session-conversation-input.tsx +46 -37
  175. package/src/features/chat/features/conversation/hooks/__tests__/use-session-conversation-controller.test.tsx +128 -1
  176. package/src/features/chat/features/conversation/hooks/__tests__/use-session-conversation-input-state.test.tsx +67 -1
  177. package/src/features/chat/features/conversation/hooks/__tests__/use-session-conversation-slash-commands.test.tsx +4 -0
  178. package/src/features/chat/features/conversation/hooks/__tests__/use-session-provider-model-catalog.test.tsx +109 -0
  179. package/src/features/chat/features/conversation/hooks/use-chat-composer-reference-intent.ts +46 -0
  180. package/src/features/chat/features/conversation/hooks/use-session-conversation-composer-nodes.ts +26 -0
  181. package/src/features/chat/features/conversation/hooks/use-session-conversation-controller.ts +45 -12
  182. package/src/features/chat/features/conversation/hooks/use-session-conversation-input-query.ts +28 -3
  183. package/src/features/chat/features/conversation/hooks/use-session-conversation-input-state.ts +91 -37
  184. package/src/features/chat/features/conversation/hooks/use-session-conversation-recovery-actions.ts +64 -0
  185. package/src/features/chat/features/conversation/hooks/use-session-conversation-slash-commands.ts +2 -0
  186. package/src/features/chat/features/conversation/hooks/use-session-provider-model-catalog.ts +84 -0
  187. package/src/features/chat/features/conversation/utils/__tests__/session-message-composer.utils.test.ts +34 -0
  188. package/src/features/chat/features/conversation/utils/session-conversation-input-toolbar.utils.ts +17 -0
  189. package/src/features/chat/features/conversation/utils/session-message-composer.utils.ts +117 -0
  190. package/src/features/chat/features/conversation/utils/session-queued-input.utils.ts +10 -98
  191. package/src/features/chat/features/input/input-surface-plugins/__tests__/slash-command-plugin.test.ts +2 -1
  192. package/src/features/chat/features/input/input-surface-plugins/slash-command-plugin.utils.ts +3 -1
  193. package/src/features/chat/features/input/utils/__tests__/chat-composer-state.utils.test.ts +22 -1
  194. package/src/features/chat/features/input/utils/__tests__/chat-inline-token.utils.test.ts +23 -0
  195. package/src/features/chat/features/input/utils/__tests__/chat-input-bar.utils.test.ts +102 -0
  196. package/src/features/chat/features/input/utils/chat-composer-state.utils.ts +27 -2
  197. package/src/features/chat/features/input/utils/chat-composer-token-protocol.utils.ts +5 -0
  198. package/src/features/chat/features/input/utils/chat-inline-token.utils.ts +97 -32
  199. package/src/features/chat/features/input/utils/chat-input-bar.utils.ts +1 -0
  200. package/src/features/chat/features/input/utils/chat-input-toolbar.utils.ts +61 -10
  201. package/src/features/chat/features/message/components/__tests__/chat-message-assistant-header.container.test.tsx +149 -0
  202. package/src/features/chat/features/message/components/__tests__/chat-message-inline-editor.test.tsx +59 -0
  203. package/src/features/chat/features/message/components/__tests__/chat-message-list.container.test.tsx +123 -90
  204. package/src/features/chat/features/message/components/__tests__/chat-message-timeline-dividers.test.tsx +43 -0
  205. package/src/features/chat/features/message/components/chat-message-inline-editor.tsx +111 -0
  206. package/src/features/chat/features/message/components/chat-message-list.container.tsx +81 -172
  207. package/src/features/chat/features/message/components/chat-message-timeline-dividers.tsx +75 -0
  208. package/src/features/chat/features/message/hooks/use-chat-inline-token-actions.ts +125 -0
  209. package/src/features/chat/features/message/hooks/use-chat-message-actions.tsx +187 -0
  210. package/src/features/chat/features/message/utils/__tests__/chat-message-action-targets.utils.test.ts +89 -0
  211. package/src/features/chat/features/message/utils/__tests__/chat-message-timeline-compaction.utils.test.ts +194 -0
  212. package/src/features/chat/features/message/utils/__tests__/chat-message-timeline-continuation-compaction.utils.test.ts +167 -0
  213. package/src/features/chat/features/message/utils/__tests__/chat-message-timeline.utils.test.ts +175 -1
  214. package/src/features/chat/features/message/utils/__tests__/chat-message.utils.test.ts +26 -0
  215. package/src/features/chat/features/message/utils/chat-message-action-targets.utils.ts +28 -0
  216. package/src/features/chat/features/message/utils/chat-message-part.utils.ts +38 -0
  217. package/src/features/chat/features/message/utils/chat-message-texts.utils.ts +1 -0
  218. package/src/features/chat/features/message/utils/chat-message-timeline.utils.ts +201 -7
  219. package/src/features/chat/features/ncp/hooks/__tests__/use-ncp-agent-runtime.test.tsx +180 -1
  220. package/src/features/chat/features/ncp/hooks/__tests__/use-ncp-session-conversation.test.tsx +184 -10
  221. package/src/features/chat/features/ncp/hooks/use-hydrated-ncp-agent.integration.test.tsx +57 -0
  222. package/src/features/chat/features/ncp/hooks/use-ncp-session-conversation.ts +90 -1
  223. package/src/features/chat/features/ncp/utils/__tests__/ncp-chat-query-derived.utils.test.ts +110 -0
  224. package/src/features/chat/features/ncp/utils/ncp-chat-query-derived.utils.ts +65 -3
  225. package/src/features/chat/features/session/components/session-header/__tests__/chat-session-header-actions.test.tsx +17 -0
  226. package/src/features/chat/features/session/components/session-header/chat-session-header-actions.tsx +63 -54
  227. package/src/features/chat/features/session/hooks/__tests__/use-selected-session-context-window-indicator.test.tsx +87 -0
  228. package/src/features/chat/features/session/utils/__tests__/ncp-session-adapter.utils.test.ts +19 -0
  229. package/src/features/chat/features/session/utils/chat-context-window-indicator.utils.ts +44 -5
  230. package/src/features/chat/features/session/utils/ncp-session-adapter.utils.ts +10 -0
  231. package/src/features/chat/features/session/utils/ncp-session-context-metadata.utils.ts +42 -4
  232. package/src/features/chat/features/welcome/components/__tests__/chat-welcome.test.tsx +17 -2
  233. package/src/features/chat/features/welcome/components/chat-welcome-project-picker.tsx +8 -3
  234. package/src/features/chat/features/welcome/components/chat-welcome.tsx +2 -2
  235. package/src/features/chat/features/welcome/utils/__tests__/chat-welcome-project-options.utils.test.ts +22 -6
  236. package/src/features/chat/features/welcome/utils/chat-welcome-project-options.utils.ts +13 -0
  237. package/src/features/chat/features/workspace/components/__tests__/chat-session-workspace-panel-content.test.tsx +72 -2
  238. package/src/features/chat/features/workspace/components/__tests__/chat-session-workspace-panel.test.tsx +21 -1
  239. package/src/features/chat/features/workspace/components/__tests__/chat-session-workspace-text-selection.test.tsx +75 -0
  240. package/src/features/chat/features/workspace/components/__tests__/workspace-text-selection-menu.test.tsx +102 -0
  241. package/src/features/chat/features/workspace/components/chat-session-workspace-directory-browser.tsx +145 -26
  242. package/src/features/chat/features/workspace/components/chat-session-workspace-file-preview.tsx +42 -18
  243. package/src/features/chat/features/workspace/components/chat-session-workspace-panel-content.tsx +50 -10
  244. package/src/features/chat/features/workspace/components/chat-session-workspace-panel-nav.tsx +48 -22
  245. package/src/features/chat/features/workspace/components/chat-session-workspace-panel.tsx +13 -2
  246. package/src/features/chat/features/workspace/components/workspace-text-selection-menu.tsx +223 -0
  247. package/src/features/chat/features/workspace/utils/__tests__/chat-workspace-panel-view-model.utils.test.ts +80 -0
  248. package/src/features/chat/features/workspace/utils/__tests__/workspace-text-excerpt.utils.test.ts +54 -0
  249. package/src/features/chat/features/workspace/utils/chat-thread-workspace-session.utils.ts +47 -0
  250. package/src/features/chat/features/workspace/utils/chat-workspace-file-tab.utils.ts +16 -0
  251. package/src/features/chat/features/workspace/utils/chat-workspace-panel-view-model.utils.ts +22 -1
  252. package/src/features/chat/features/workspace/utils/workspace-text-excerpt.utils.ts +53 -0
  253. package/src/features/chat/index.ts +1 -0
  254. package/src/features/chat/managers/__tests__/chat-composer-intent.manager.test.ts +106 -0
  255. package/src/features/chat/managers/__tests__/chat-session-list.manager.test.ts +38 -2
  256. package/src/features/chat/managers/__tests__/chat-thread-workspace.manager.test.ts +93 -1
  257. package/src/features/chat/managers/__tests__/provider-model-catalog-notice.manager.test.ts +57 -0
  258. package/src/features/chat/managers/chat-composer-intent.manager.ts +145 -0
  259. package/src/features/chat/managers/chat-session-list.manager.ts +13 -4
  260. package/src/features/chat/managers/chat-thread.manager.ts +30 -11
  261. package/src/features/chat/managers/provider-model-catalog-notice.manager.ts +121 -0
  262. package/src/features/chat/presenters/chat.presenter.ts +3 -0
  263. package/src/features/chat/stores/__tests__/chat-composer-draft.store.test.ts +55 -0
  264. package/src/features/chat/stores/chat-composer-draft.store.ts +92 -0
  265. package/src/features/chat/stores/chat-thread.store.ts +2 -4
  266. package/src/features/chat/types/chat-input-bar.types.ts +5 -0
  267. package/src/features/chat/types/chat-input.types.ts +5 -0
  268. package/src/features/chat/types/chat-message.types.ts +5 -0
  269. package/src/features/cron/components/__tests__/cron-config.test.tsx +100 -19
  270. package/src/features/cron/components/cron-config.tsx +19 -33
  271. package/src/features/cron/components/cron-job-detail-dialog.tsx +42 -16
  272. package/src/features/cron/components/cron-job-row.tsx +18 -1
  273. package/src/features/inbox/components/inbox-delivery-content.test.tsx +8 -2
  274. package/src/features/inbox/components/inbox-delivery-content.tsx +1 -1
  275. package/src/features/inbox/components/inbox-reader-dialog.test.tsx +10 -4
  276. package/src/features/inbox/components/inbox-reader-dialog.tsx +37 -61
  277. package/src/features/inbox/pages/inbox-page.tsx +90 -98
  278. package/src/features/notifications/components/__tests__/app-notification-toast.test.tsx +28 -6
  279. package/src/features/notifications/components/app-notification-toast.tsx +54 -15
  280. package/src/features/notifications/managers/__tests__/app-notification.manager.test.ts +2 -0
  281. package/src/features/notifications/managers/app-notification.manager.ts +3 -0
  282. package/src/features/panel-apps/utils/panel-app-doc-browser.utils.tsx +1 -0
  283. package/src/features/pwa/managers/__tests__/pwa-shell-theme.manager.test.ts +9 -0
  284. package/src/features/pwa/managers/pwa-shell-theme.manager.ts +1 -0
  285. package/src/features/service-apps/components/__tests__/service-apps-panel.test.tsx +5 -4
  286. package/src/features/service-apps/components/service-app-list-item.tsx +470 -0
  287. package/src/features/service-apps/components/service-apps-panel.tsx +76 -490
  288. package/src/features/settings/components/config/__tests__/provider-models-section.test.tsx +239 -0
  289. package/src/features/settings/components/config/provider-form-detail-pane.tsx +307 -0
  290. package/src/features/settings/components/config/provider-form.tsx +149 -360
  291. package/src/features/settings/components/config/provider-model-list.tsx +293 -0
  292. package/src/features/settings/components/config/provider-model-suggestions-panel.tsx +151 -0
  293. package/src/features/settings/components/config/provider-models-section.tsx +178 -149
  294. package/src/features/settings/hooks/__tests__/use-provider-connectivity.test.tsx +98 -0
  295. package/src/features/settings/hooks/__tests__/use-provider-model-suggestions.test.tsx +107 -0
  296. package/src/features/settings/hooks/use-provider-connectivity.ts +132 -0
  297. package/src/features/settings/hooks/use-provider-model-suggestions.ts +51 -0
  298. package/src/features/settings/pages/__tests__/appearance-settings-page.test.tsx +2 -2
  299. package/src/features/settings/pages/__tests__/search-config-page.test.tsx +48 -0
  300. package/src/features/settings/pages/search-config-page.tsx +17 -8
  301. package/src/features/settings/utils/__tests__/provider-form-support.utils.test.ts +42 -0
  302. package/src/features/settings/utils/provider-form-context.utils.ts +2 -0
  303. package/src/features/settings/utils/provider-form-model.utils.ts +25 -0
  304. package/src/features/settings/utils/provider-form-support.utils.ts +21 -5
  305. package/src/index.css +1 -1
  306. package/src/platforms/desktop/types/desktop-update.types.ts +5 -0
  307. package/src/shared/components/actions/__tests__/navigation-link.test.tsx +14 -3
  308. package/src/shared/components/actions/navigation-link.tsx +35 -15
  309. package/src/shared/components/common/__tests__/agent-avatar.test.tsx +3 -2
  310. package/src/shared/components/common/agent-avatar.tsx +3 -3
  311. package/src/shared/components/doc-browser/__tests__/doc-browser.test.tsx +66 -0
  312. package/src/shared/components/doc-browser/doc-browser-panel-parts.tsx +4 -1
  313. package/src/shared/components/doc-browser/doc-browser-renderer.types.ts +1 -0
  314. package/src/shared/components/doc-browser/doc-browser.tsx +9 -0
  315. package/src/shared/components/doc-browser/hooks/use-doc-browser-scroll-restoration.ts +126 -0
  316. package/src/shared/components/settings/settings-page.tsx +1 -1
  317. package/src/shared/components/ui/context-menu/__tests__/context-menu.test.tsx +103 -0
  318. package/src/shared/components/ui/context-menu/context-menu.tsx +263 -0
  319. package/src/shared/components/ui/tab-strip/__tests__/compact-tab-strip.test.tsx +19 -6
  320. package/src/shared/components/ui/tab-strip/compact-tab-strip.tsx +28 -67
  321. package/src/shared/hooks/use-config.ts +33 -1
  322. package/src/shared/lib/api/__tests__/ncp-session-query-cache.utils.test.ts +26 -0
  323. package/src/shared/lib/api/ncp-session-query-cache.utils.ts +7 -10
  324. package/src/shared/lib/api/ncp-session.types.ts +6 -0
  325. package/src/shared/lib/api/types.ts +36 -1
  326. package/src/shared/lib/api/utils/config.utils.ts +14 -0
  327. package/src/shared/lib/cron/cron-job-view.utils.ts +4 -0
  328. package/src/shared/lib/host-capabilities/__tests__/host-capability.manager.test.ts +26 -0
  329. package/src/shared/lib/host-capabilities/host-capability.manager.ts +28 -0
  330. package/src/shared/lib/i18n/locales/en-US/chat.json +33 -4
  331. package/src/shared/lib/i18n/locales/en-US/core.json +26 -0
  332. package/src/shared/lib/i18n/locales/en-US/doc-browser.json +1 -0
  333. package/src/shared/lib/i18n/locales/en-US/search.json +1 -0
  334. package/src/shared/lib/i18n/locales/zh-CN/chat.json +33 -4
  335. package/src/shared/lib/i18n/locales/zh-CN/core.json +26 -0
  336. package/src/shared/lib/i18n/locales/zh-CN/doc-browser.json +1 -0
  337. package/src/shared/lib/i18n/locales/zh-CN/search.json +1 -0
  338. package/src/shared/lib/session-project/__tests__/workspace-file-breadcrumb.test.ts +28 -1
  339. package/src/shared/lib/session-project/workspace-file-breadcrumb.utils.ts +23 -0
  340. package/src/shared/lib/theme/index.test.ts +11 -0
  341. package/src/shared/lib/theme/index.ts +2 -0
  342. package/dist/assets/api-B1yHQYs-.js +0 -13
  343. package/dist/assets/app-presenter-provider-D3BuuOyZ.css +0 -1
  344. package/dist/assets/app-presenter-provider-uP9waOzv.js +0 -108
  345. package/dist/assets/appearance-settings-page-C9Zq3hP9.js +0 -1
  346. package/dist/assets/architecture-TIHT7OUA-Cii4JyA2.js +0 -1
  347. package/dist/assets/book-open-oSmyVXea.js +0 -1
  348. package/dist/assets/card-CGvJZTZp.js +0 -1
  349. package/dist/assets/channel-BSKkTPe8.js +0 -1
  350. package/dist/assets/channels-list-page-5BTxpQHw.js +0 -8
  351. package/dist/assets/chat-page-jTvli8Jp.js +0 -1
  352. package/dist/assets/chunk-2Q5K7J3B-CDMOR1xZ.js +0 -1
  353. package/dist/assets/chunk-VAUOI2AC-BRvqNW76.js +0 -1
  354. package/dist/assets/chunk-XXDRQBXY-CwX_mqJ3.js +0 -1
  355. package/dist/assets/classDiagram-OUVF2IWQ-RzbGxG77.js +0 -1
  356. package/dist/assets/classDiagram-v2-EOCWNBFH-C_gWB7WT.js +0 -1
  357. package/dist/assets/confirm-dialog-h849QRWO.js +0 -5
  358. package/dist/assets/cynefin-VYW2F7L2-fSLIS0X3.js +0 -1
  359. package/dist/assets/desktop-update-config-BGGHxClR.js +0 -1
  360. package/dist/assets/dist-CxUhurq9.js +0 -41
  361. package/dist/assets/doc-browser-0eL8AX42.js +0 -1
  362. package/dist/assets/doc-browser-DEqE9lsh.js +0 -1
  363. package/dist/assets/doc-browser-context-DkzFIUoK.js +0 -1
  364. package/dist/assets/eventmodeling-45OFAUF4-XVcQGgha.js +0 -1
  365. package/dist/assets/eye-gOWQGt8N.js +0 -1
  366. package/dist/assets/flowDiagram-23GEKE2U-BiFSctqz.js +0 -1
  367. package/dist/assets/gitGraph-TEB2WS4Q-C014uXqS.js +0 -1
  368. package/dist/assets/host-capabilities-B-TtABsP.js +0 -1
  369. package/dist/assets/index-DSAUWCfl.js +0 -2
  370. package/dist/assets/index-G7cBryJ4.css +0 -1
  371. package/dist/assets/info-DKCQHKI2-CQ2qjGhU.js +0 -1
  372. package/dist/assets/loader-circle-BAuycGf6.js +0 -1
  373. package/dist/assets/logo-badge-BNcsDsUM.js +0 -1
  374. package/dist/assets/mcp-marketplace-page-BX39MtPa.js +0 -9
  375. package/dist/assets/mcp-marketplace-page-CkDtOEA4.js +0 -1
  376. package/dist/assets/model-config-page-7MIXg2fQ.js +0 -1
  377. package/dist/assets/navigation-link-B3iFOdxx.js +0 -1
  378. package/dist/assets/packet-7NZHBO7P-6IFyydij.js +0 -1
  379. package/dist/assets/pie-RZYD4A2V-spXQC_wr.js +0 -1
  380. package/dist/assets/plus-yvhFgfal.js +0 -1
  381. package/dist/assets/popover-Cpep_rJe.js +0 -1
  382. package/dist/assets/provider-models-CUrptZ-o.js +0 -1
  383. package/dist/assets/provider-scoped-model-input-CHmOzz7x.js +0 -1
  384. package/dist/assets/providers-config-page-A6J7Y0II.js +0 -1
  385. package/dist/assets/radar-I7S5WNFK-DWVA8lvY.js +0 -1
  386. package/dist/assets/railroad-3IZDKUUU-Ce51u8y1.js +0 -1
  387. package/dist/assets/railroad-abnf-AHOZXSZD-D7i7cqI_.js +0 -1
  388. package/dist/assets/railroad-ebnf-EBAXGLYW-BEg2hcPs.js +0 -1
  389. package/dist/assets/railroad-peg-LSFZ7HO6-CxROSzbi.js +0 -1
  390. package/dist/assets/react-BCJGCjrP.js +0 -8
  391. package/dist/assets/remote-FD-ZfSIn.js +0 -1
  392. package/dist/assets/rotate-cw-DrJMfHhp.js +0 -1
  393. package/dist/assets/runtime-config-page-DwjO-Vs6.js +0 -1
  394. package/dist/assets/search-config-page-T6tMhXbP.js +0 -1
  395. package/dist/assets/security-config-DD5RrjDe.js +0 -1
  396. package/dist/assets/select-BvidP5Oa.js +0 -1
  397. package/dist/assets/skeleton-BEQW2Dva.js +0 -1
  398. package/dist/assets/stateDiagram-v2-6OUMAXLB-Bui4RXQK.js +0 -1
  399. package/dist/assets/swimlanesDiagram-G3AALYLV-DTwUsCBz.js +0 -8
  400. package/dist/assets/tabs-BeLxVmkt.js +0 -1
  401. package/dist/assets/trash-2-CYUskMMN.js +0 -1
  402. package/dist/assets/treeView-QDETBFTQ-D5zsTiuL.js +0 -1
  403. package/dist/assets/treemap-6X3UGDF4-CR3dxqNs.js +0 -1
  404. package/dist/assets/use-config-CxKRXXCl.js +0 -1
  405. package/dist/assets/use-confirm-dialog-HASTvOP2.js +0 -1
  406. package/dist/assets/use-viewport-layout-CJxkjoRz.js +0 -1
  407. package/dist/assets/wardley-OPB4EBWU-LatRT_Lx.js +0 -1
  408. package/dist/assets/x-DdUwjre5.js +0 -1
  409. /package/dist/assets/{array-CAkJT3no.js → array-NADKd9aU.js} +0 -0
  410. /package/dist/assets/{chunk-KEIR6QF5-BgdDoWEH.js → chunk-KEIR6QF5-BuyuzJJL.js} +0 -0
  411. /package/dist/assets/{chunk-Y2CYZVJY-pTllD0P3.js → chunk-Y2CYZVJY-D_B2ZRNt.js} +0 -0
  412. /package/dist/assets/{config-hints-S3g-UVZb.js → config-hints-BcfVUMij.js} +0 -0
  413. /package/dist/assets/{cytoscape.esm-DmURt-5G.js → cytoscape.esm-BANTlgza.js} +0 -0
  414. /package/dist/assets/{defaultLocale-BKy_KP3O.js → defaultLocale-C4_L0aEs.js} +0 -0
  415. /package/dist/assets/{dist-IgNNB7K9.js → dist-DAPEIJbz.js} +0 -0
  416. /package/dist/assets/{graphlib-xw_TBHyH.js → graphlib-ChqXg0dI.js} +0 -0
  417. /package/dist/assets/{init-C9xlLIAu.js → init-D8wZg9xq.js} +0 -0
  418. /package/dist/assets/{jszip.min-Das2IAnb.js → jszip.min-CkbBfwAQ.js} +0 -0
  419. /package/dist/assets/{katex-DSy1eD2d.js → katex-TZJFa0J_.js} +0 -0
  420. /package/dist/assets/{middleware-Df-a4x-q.js → middleware-B3k-TSmZ.js} +0 -0
  421. /package/dist/assets/{path-DB0USYHi.js → path-DodfxcX7.js} +0 -0
  422. /package/dist/assets/{rough.esm-B1B52ZQS.js → rough.esm-CUaa1Rbe.js} +0 -0
  423. /package/dist/assets/{xlsx-DfjC_iml.js → xlsx-CxByi7bR.js} +0 -0
@@ -2,10 +2,10 @@ import * as React from "react";
2
2
  import { MoreVertical, X } from "lucide-react";
3
3
  import { IconActionButton } from "@/shared/components/ui/actions/icon-action-button";
4
4
  import {
5
- Popover,
6
- PopoverContent,
7
- PopoverTrigger,
8
- } from "@/shared/components/ui/popover";
5
+ ContextMenu,
6
+ ContextMenuTrigger,
7
+ type ContextMenuGroup,
8
+ } from "@/shared/components/ui/context-menu/context-menu";
9
9
  import {
10
10
  Tooltip,
11
11
  TooltipContent,
@@ -26,7 +26,7 @@ export type CompactTabStripTab = {
26
26
  closeLabel?: string;
27
27
  closePlacement?: "leading-hover" | "trailing";
28
28
  menuLabel?: string;
29
- menuActions?: readonly CompactTabStripAction[];
29
+ menuGroups?: readonly ContextMenuGroup[];
30
30
  onSelect: () => void;
31
31
  onClose?: () => void;
32
32
  };
@@ -64,73 +64,28 @@ function closeCompactTab(event: React.MouseEvent<HTMLButtonElement>, onClose: ()
64
64
  }
65
65
 
66
66
  function CompactTabMenu({ tab }: { tab: CompactTabStripTab }) {
67
- const [open, setOpen] = React.useState(false);
68
- const restoreTriggerFocus = React.useRef(true);
69
- if (!tab.menuActions?.length) {
67
+ if (!tab.menuGroups?.some((group) => group.items.length > 0)) {
70
68
  return null;
71
69
  }
72
70
 
73
71
  const menuLabel = tab.menuLabel ?? tab.label;
74
72
  return (
75
- <Popover
76
- open={open}
77
- onOpenChange={(nextOpen) => {
78
- if (nextOpen) {
79
- restoreTriggerFocus.current = true;
80
- }
81
- setOpen(nextOpen);
82
- }}
73
+ <div
74
+ className={cn(
75
+ "-ml-1.5 flex w-0 shrink-0 overflow-hidden opacity-0 transition-[width,margin,opacity] group-hover:ml-0 group-hover:w-5 group-hover:opacity-100 group-focus-within:ml-0 group-focus-within:w-5 group-focus-within:opacity-100",
76
+ "group-data-[context-menu-open]:ml-0 group-data-[context-menu-open]:w-5 group-data-[context-menu-open]:opacity-100",
77
+ )}
83
78
  >
84
- <div
85
- className={cn(
86
- "-ml-1.5 flex w-0 shrink-0 overflow-hidden opacity-0 transition-[width,margin,opacity] group-hover:ml-0 group-hover:w-5 group-hover:opacity-100 group-focus-within:ml-0 group-focus-within:w-5 group-focus-within:opacity-100",
87
- open ? "ml-0 w-5 opacity-100" : null,
88
- )}
89
- >
90
- <PopoverTrigger asChild>
91
- <button
92
- type="button"
93
- aria-label={menuLabel}
94
- onClick={(event) => event.stopPropagation()}
95
- className="inline-flex h-5 w-5 shrink-0 items-center justify-center rounded-md text-gray-400 transition-colors hover:bg-gray-200 hover:text-gray-700 focus-visible:bg-gray-200 focus-visible:text-gray-700 focus-visible:outline-none"
96
- >
97
- <MoreVertical className="h-3.5 w-3.5" />
98
- </button>
99
- </PopoverTrigger>
100
- </div>
101
- <PopoverContent
102
- align="end"
103
- className="w-40 rounded-xl p-1.5"
104
- onClick={(event) => event.stopPropagation()}
105
- onCloseAutoFocus={(event) => {
106
- if (!restoreTriggerFocus.current) {
107
- event.preventDefault();
108
- }
109
- }}
110
- >
111
- <div role="menu" aria-label={menuLabel}>
112
- {tab.menuActions.map((action) => (
113
- <button
114
- key={action.key}
115
- type="button"
116
- role="menuitem"
117
- disabled={action.disabled}
118
- className="flex w-full items-center gap-2 rounded-lg px-2.5 py-2 text-left text-xs text-gray-700 transition-colors hover:bg-gray-100 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-border disabled:cursor-not-allowed disabled:opacity-45"
119
- onClick={() => {
120
- restoreTriggerFocus.current = false;
121
- setOpen(false);
122
- action.onClick();
123
- }}
124
- >
125
- <span className="inline-flex h-4 w-4 shrink-0 items-center justify-center">
126
- {action.icon}
127
- </span>
128
- <span>{action.label}</span>
129
- </button>
130
- ))}
131
- </div>
132
- </PopoverContent>
133
- </Popover>
79
+ <ContextMenuTrigger>
80
+ <button
81
+ type="button"
82
+ aria-label={menuLabel}
83
+ className="inline-flex h-5 w-5 shrink-0 items-center justify-center rounded-md text-gray-400 transition-colors hover:bg-gray-200 hover:text-gray-700 focus-visible:bg-gray-200 focus-visible:text-gray-700 focus-visible:outline-none"
84
+ >
85
+ <MoreVertical className="h-3.5 w-3.5" />
86
+ </button>
87
+ </ContextMenuTrigger>
88
+ </div>
134
89
  );
135
90
  }
136
91
 
@@ -196,7 +151,7 @@ function CompactTabItem({
196
151
  | "tabBaseClassName"
197
152
  > & { itemRef?: React.Ref<HTMLDivElement>; tab: CompactTabStripTab }) {
198
153
  const leadingClose = tab.onClose && tab.closePlacement === "leading-hover";
199
- return (
154
+ const item = (
200
155
  <div
201
156
  ref={itemRef}
202
157
  data-compact-tab-item=""
@@ -237,6 +192,12 @@ function CompactTabItem({
237
192
  ) : null}
238
193
  </div>
239
194
  );
195
+
196
+ return tab.menuGroups?.some((group) => group.items.length > 0) ? (
197
+ <ContextMenu groups={tab.menuGroups} label={tab.menuLabel ?? tab.label}>
198
+ {item}
199
+ </ContextMenu>
200
+ ) : item;
240
201
  }
241
202
 
242
203
  export function CompactTabStrip({
@@ -4,6 +4,7 @@ import {
4
4
  fetchConfigMeta,
5
5
  fetchConfigSchema,
6
6
  fetchProviders,
7
+ fetchProviderModelCatalog,
7
8
  fetchProviderTemplates,
8
9
  updateModel,
9
10
  updateSearch,
@@ -11,6 +12,7 @@ import {
11
12
  deleteProvider,
12
13
  updateProvider,
13
14
  testProviderConnection,
15
+ discoverProviderModels,
14
16
  startProviderAuth,
15
17
  pollProviderAuth,
16
18
  importProviderAuthFromCli,
@@ -21,6 +23,7 @@ import {
21
23
  } from '@/shared/lib/api';
22
24
  import { toast } from 'sonner';
23
25
  import { t } from '@/shared/lib/i18n';
26
+ import type { ProvidersView } from '@/shared/lib/api';
24
27
 
25
28
  export function useConfig() {
26
29
  return useQuery({
@@ -56,6 +59,20 @@ export function useProviderTemplates() {
56
59
  });
57
60
  }
58
61
 
62
+ export function useProviderModelCatalog(options: {
63
+ pollWhileRefreshing?: boolean;
64
+ refreshOnMount?: boolean;
65
+ } = {}) {
66
+ return useQuery({
67
+ queryKey: ['provider-model-catalog'],
68
+ queryFn: fetchProviderModelCatalog,
69
+ staleTime: 30_000,
70
+ refetchInterval: (query) => options.pollWhileRefreshing && query.state.data?.refreshing ? 1_000 : false,
71
+ refetchOnMount: options.refreshOnMount ? 'always' : true,
72
+ refetchOnWindowFocus: true
73
+ });
74
+ }
75
+
59
76
  export function useConfigSchema() {
60
77
  return useQuery({
61
78
  queryKey: ['config-schema'],
@@ -101,7 +118,15 @@ export function useUpdateProvider() {
101
118
  return useMutation({
102
119
  mutationFn: ({ provider, data }: { provider: string; data: unknown; silentSuccess?: boolean }) =>
103
120
  updateProvider(provider, data as Parameters<typeof updateProvider>[1]),
104
- onSuccess: (_data, variables) => {
121
+ onSuccess: (data, variables) => {
122
+ queryClient.setQueryData<ProvidersView>(['providers'], (current) => current
123
+ ? {
124
+ providers: {
125
+ ...current.providers,
126
+ [variables.provider]: data,
127
+ },
128
+ }
129
+ : current);
105
130
  queryClient.invalidateQueries({ queryKey: ['providers'] });
106
131
  queryClient.invalidateQueries({ queryKey: ['config'] });
107
132
  if (!variables.silentSuccess) {
@@ -154,6 +179,13 @@ export function useTestProviderConnection() {
154
179
  });
155
180
  }
156
181
 
182
+ export function useDiscoverProviderModels() {
183
+ return useMutation({
184
+ mutationFn: ({ provider, data }: { provider: string; data: unknown }) =>
185
+ discoverProviderModels(provider, data as Parameters<typeof discoverProviderModels>[1])
186
+ });
187
+ }
188
+
157
189
  export function useStartProviderAuth() {
158
190
  return useMutation({
159
191
  mutationFn: ({ provider, data }: { provider: string; data?: unknown }) =>
@@ -154,6 +154,32 @@ describe('ncp-session-query-cache', () => {
154
154
  });
155
155
  });
156
156
 
157
+ it.each(['cancelled', 'failed'] as const)(
158
+ 'clears a stale running overlay when a newer %s summary arrives',
159
+ (state) => {
160
+ const current = updateNcpSessionRunStatusList(createSessionsList(), {
161
+ sessionKey: 'session-1',
162
+ status: 'running'
163
+ });
164
+
165
+ const updated = upsertNcpSessionSummaryList(current, {
166
+ sessionId: 'session-1',
167
+ messageCount: 2,
168
+ createdAt: '2026-03-29T08:00:00.000Z',
169
+ updatedAt: '2026-03-29T10:01:00.000Z',
170
+ lastMessageAt: '2026-03-29T10:01:00.000Z',
171
+ status: 'idle',
172
+ metadata: { last_activity_preview: { state } }
173
+ });
174
+
175
+ expect(updated?.sessions[0]).toMatchObject({
176
+ sessionId: 'session-1',
177
+ messageCount: 2,
178
+ status: 'idle'
179
+ });
180
+ }
181
+ );
182
+
157
183
  it('applies realtime upsert/delete events to every ncp-sessions query cache entry', () => {
158
184
  const queryClient = new QueryClient();
159
185
  queryClient.setQueryData(['ncp-sessions', 200], createSessionsList());
@@ -5,20 +5,17 @@ function readSessionActivityAt(summary: NcpSessionSummaryView): string {
5
5
  return summary.lastMessageAt ?? summary.createdAt ?? summary.updatedAt;
6
6
  }
7
7
 
8
+ function isSessionActivityRunning(summary: NcpSessionSummaryView): boolean {
9
+ return (summary.metadata?.last_activity_preview as { state?: unknown } | undefined)?.state === 'running';
10
+ }
11
+
8
12
  function sortSessionSummaries(summaries: readonly NcpSessionSummaryView[]): NcpSessionSummaryView[] {
9
13
  return [...summaries].sort((left, right) => readSessionActivityAt(right).localeCompare(readSessionActivityAt(left)));
10
14
  }
11
15
 
12
- function shouldReplaceSessionSummary(
13
- current: NcpSessionSummaryView,
14
- next: NcpSessionSummaryView
15
- ): boolean {
16
+ function shouldReplaceSessionSummary(current: NcpSessionSummaryView, next: NcpSessionSummaryView): boolean {
16
17
  const timeOrder = next.updatedAt.localeCompare(current.updatedAt);
17
- if (timeOrder !== 0) {
18
- return timeOrder > 0;
19
- }
20
-
21
- return current.status === next.status || next.status === 'idle';
18
+ return timeOrder === 0 ? current.status === next.status || next.status === 'idle' : timeOrder > 0;
22
19
  }
23
20
 
24
21
  function queryKeyAcceptsSessionSummary(queryKey: readonly unknown[], summary: NcpSessionSummaryView): boolean {
@@ -44,7 +41,7 @@ export function upsertNcpSessionSummaryList(
44
41
  index === existingIndex && shouldReplaceSessionSummary(session, summary)
45
42
  ? {
46
43
  ...summary,
47
- status: session.status === 'running' && summary.status === 'idle' ? 'running' : summary.status
44
+ status: summary.status === 'idle' && isSessionActivityRunning(summary) ? session.status : summary.status
48
45
  }
49
46
  : session
50
47
  )
@@ -21,8 +21,14 @@ export type RuntimeEntryView = {
21
21
  };
22
22
 
23
23
  export type SessionContextWindowView = {
24
+ completeInputBudget?: boolean;
24
25
  usedContextTokens: number;
25
26
  totalContextTokens: number;
27
+ fixedInputTokens?: number;
28
+ dynamicInputTokens?: number;
29
+ reservedContextTokens?: number;
30
+ triggerContextTokens?: number;
31
+ availableBeforeCompactionTokens?: number;
26
32
  prunedUsedContextTokens: number;
27
33
  availableContextTokens: number;
28
34
  droppedHistoryCount: number;
@@ -102,6 +102,11 @@ export type ProviderConnectionTestRequest = ProviderConfigUpdate & {
102
102
  model?: string | null;
103
103
  };
104
104
 
105
+ export type ProviderModelDiscoveryRequest = Pick<
106
+ ProviderConfigUpdate,
107
+ 'apiKey' | 'apiBase' | 'extraHeaders'
108
+ >;
109
+
105
110
  export type ProviderCreateRequest = ProviderConfigUpdate & {
106
111
  providerId?: string | null;
107
112
  };
@@ -135,7 +140,31 @@ export type ProviderConnectionTestResult = {
135
140
  hint?: string;
136
141
  };
137
142
 
138
- export type SearchProviderName = "bocha" | "tavily" | "brave";
143
+ export type ProviderModelDiscoveryResult = {
144
+ provider: string;
145
+ models: string[];
146
+ source: 'provider' | 'catalog';
147
+ fetchedAt: string;
148
+ };
149
+
150
+ export type ProviderModelCatalogView = {
151
+ refreshIntervalMs: number;
152
+ refreshing: boolean;
153
+ lastRefreshStartedAt: string | null;
154
+ lastRefreshCompletedAt: string | null;
155
+ providers: Record<string, {
156
+ providerId: string;
157
+ models: string[];
158
+ source: 'provider' | 'catalog' | null;
159
+ fetchedAt: string | null;
160
+ lastError: {
161
+ message: string;
162
+ occurredAt: string;
163
+ } | null;
164
+ }>;
165
+ };
166
+
167
+ export type SearchProviderName = "bocha" | "tavily" | "brave" | "exa";
139
168
  export type BochaFreshnessValue = "noLimit" | "oneDay" | "oneWeek" | "oneMonth" | "oneYear" | string;
140
169
  export type TavilySearchDepthValue = "basic" | "advanced";
141
170
 
@@ -161,6 +190,7 @@ export type SearchConfigView = {
161
190
  bocha: SearchProviderConfigView;
162
191
  tavily: SearchProviderConfigView;
163
192
  brave: SearchProviderConfigView;
193
+ exa: SearchProviderConfigView;
164
194
  };
165
195
  };
166
196
 
@@ -188,6 +218,10 @@ export type SearchConfigUpdate = {
188
218
  apiKey?: string | null;
189
219
  baseUrl?: string | null;
190
220
  };
221
+ exa?: {
222
+ apiKey?: string | null;
223
+ baseUrl?: string | null;
224
+ };
191
225
  };
192
226
  };
193
227
 
@@ -651,6 +685,7 @@ export type ProviderTemplateView = {
651
685
  supportsCliImport?: boolean;
652
686
  };
653
687
  defaultModels?: string[];
688
+ supportsModelDiscovery?: boolean;
654
689
  modelConfig?: Record<string, {
655
690
  thinking?: { supported: ThinkingLevel[]; default?: ThinkingLevel | null };
656
691
  vision?: boolean;
@@ -17,6 +17,9 @@ import type {
17
17
  ProviderConfigUpdate,
18
18
  ProviderConnectionTestRequest,
19
19
  ProviderConnectionTestResult,
20
+ ProviderModelDiscoveryRequest,
21
+ ProviderModelDiscoveryResult,
22
+ ProviderModelCatalogView,
20
23
  ProviderAuthStartRequest,
21
24
  ProviderAuthStartResult,
22
25
  ProviderAuthPollRequest,
@@ -90,6 +93,10 @@ export async function fetchProviderTemplates(): Promise<ProviderTemplatesView> {
90
93
  return await nextclawClient.providers.listTemplates();
91
94
  }
92
95
 
96
+ export async function fetchProviderModelCatalog(): Promise<ProviderModelCatalogView> {
97
+ return await nextclawClient.providers.listModelCatalog();
98
+ }
99
+
93
100
  export async function fetchConfigSchema(): Promise<ConfigSchemaResponse> {
94
101
  return await nextclawClient.config.fetchSchema();
95
102
  }
@@ -121,6 +128,13 @@ export async function testProviderConnection(
121
128
  return await nextclawClient.providers.testConnection(provider, data);
122
129
  }
123
130
 
131
+ export async function discoverProviderModels(
132
+ provider: string,
133
+ data: ProviderModelDiscoveryRequest
134
+ ): Promise<ProviderModelDiscoveryResult> {
135
+ return await nextclawClient.providers.discoverModels(provider, data);
136
+ }
137
+
124
138
  export async function startProviderAuth(
125
139
  provider: string,
126
140
  data: ProviderAuthStartRequest = {}
@@ -156,6 +156,10 @@ export function describeCronSession(job: CronJobView): string {
156
156
  return job.payload.sessionId?.trim() || `cron:${job.id}`;
157
157
  }
158
158
 
159
+ export function canOpenCronSession(job: CronJobView): boolean {
160
+ return Boolean(job.payload.sessionId?.trim() || job.state.lastRunAt);
161
+ }
162
+
159
163
  export function isCronJobForSession(
160
164
  job: CronJobView,
161
165
  sessionKey: string | null | undefined,
@@ -47,4 +47,30 @@ describe("HostCapabilityManager", () => {
47
47
  reason: "popup-blocked"
48
48
  });
49
49
  });
50
+
51
+ it("reveals a path only through the explicit desktop bridge", async () => {
52
+ const revealPath = vi.fn(async () => ({ revealed: true as const }));
53
+ const manager = new HostCapabilityManager(() => ({
54
+ open: vi.fn(),
55
+ nextclawDesktop: {
56
+ host: { revealPath }
57
+ }
58
+ } as unknown as Window));
59
+
60
+ expect(manager.canRevealPath()).toBe(true);
61
+ await expect(manager.revealPath(" /tmp/demo.txt ")).resolves.toEqual({ revealed: true });
62
+ expect(revealPath).toHaveBeenCalledWith("/tmp/demo.txt");
63
+ });
64
+
65
+ it("does not invent a web fallback for revealing local paths", async () => {
66
+ const manager = new HostCapabilityManager(() => ({
67
+ open: vi.fn()
68
+ } as unknown as Window));
69
+
70
+ expect(manager.canRevealPath()).toBe(false);
71
+ await expect(manager.revealPath("/tmp/demo.txt")).resolves.toEqual({
72
+ revealed: false,
73
+ reason: "host-unavailable"
74
+ });
75
+ });
50
76
  });
@@ -7,10 +7,18 @@ export type OpenExternalUrlResult =
7
7
  | { opened: true }
8
8
  | { opened: false; reason: OpenExternalUrlFailureReason };
9
9
 
10
+ export type RevealPathResult =
11
+ | { revealed: true }
12
+ | {
13
+ revealed: false;
14
+ reason: "unsupported-path" | "host-unavailable" | "bridge-failed";
15
+ };
16
+
10
17
  type HostWindow = Pick<Window, "open"> & {
11
18
  nextclawDesktop?: {
12
19
  host?: {
13
20
  openExternalUrl?: (url: string) => Promise<OpenExternalUrlResult>;
21
+ revealPath?: (path: string) => Promise<RevealPathResult>;
14
22
  };
15
23
  };
16
24
  };
@@ -45,6 +53,26 @@ export class HostCapabilityManager {
45
53
  return { opened: false, reason: "bridge-failed" };
46
54
  }
47
55
  };
56
+
57
+ canRevealPath = (): boolean => {
58
+ return Boolean(this.getWindow()?.nextclawDesktop?.host?.revealPath);
59
+ };
60
+
61
+ revealPath = async (rawPath: string): Promise<RevealPathResult> => {
62
+ const path = rawPath.trim();
63
+ if (!path) {
64
+ return { revealed: false, reason: "unsupported-path" };
65
+ }
66
+ const revealPath = this.getWindow()?.nextclawDesktop?.host?.revealPath;
67
+ if (!revealPath) {
68
+ return { revealed: false, reason: "host-unavailable" };
69
+ }
70
+ try {
71
+ return await revealPath(path);
72
+ } catch {
73
+ return { revealed: false, reason: "bridge-failed" };
74
+ }
75
+ };
48
76
  }
49
77
 
50
78
  export const hostCapabilityManager = new HostCapabilityManager();
@@ -53,8 +53,8 @@
53
53
  "chatWorkspaceChildSessionsEmpty": "No child sessions yet.",
54
54
  "chatWorkspaceSessionCronJobsDescription": "Review scheduled tasks associated with this session.",
55
55
  "chatWorkspaceProjectFiles": "Project files",
56
- "chatWorkspaceProjectFilesDescription": "Browse files from this session's project directory.",
57
- "chatWorkspaceProjectFilesUnavailable": "This session does not have a project directory yet.",
56
+ "chatWorkspaceProjectFilesDescription": "Browse files from the selected project directory.",
57
+ "chatWorkspaceProjectFilesUnavailable": "Select a project directory to browse its files.",
58
58
  "chatWorkspaceSideChatDraftTitle": "Side chat",
59
59
  "chatWorkspaceSideChatDraftSubtitle": "This draft will inherit the parent session context when you send the first message.",
60
60
  "chatWorkspaceChildSessions": "Child sessions",
@@ -73,6 +73,14 @@
73
73
  "chatWorkspaceOpenFile": "Open file",
74
74
  "chatWorkspaceDirectoryEmpty": "This directory is empty.",
75
75
  "chatWorkspaceDirectoryLoadFailed": "Failed to load directory",
76
+ "chatWorkspaceFileContextMenu": "Project file actions",
77
+ "chatWorkspaceAddToChat": "Add to chat",
78
+ "chatWorkspaceExcerptSelectionTooLong": "Selection is too long",
79
+ "chatWorkspaceRevealInFileManager": "Reveal in file manager",
80
+ "chatWorkspaceCopyPath": "Copy path",
81
+ "chatWorkspaceCopyRelativePath": "Copy relative path",
82
+ "chatWorkspaceCopyPathFailed": "Could not copy the path.",
83
+ "chatWorkspaceRevealPathFailed": "Could not reveal this item in the file manager.",
76
84
  "chatWorkspacePreviewUnsupported": "This file is not supported in the sidebar preview yet.",
77
85
  "chatWorkspacePreviewUnsupportedHint": "Legacy Word or PowerPoint files, archives, and other unsupported formats can be downloaded and opened with a local app.",
78
86
  "chatWorkspacePreviewFailed": "The file could not be previewed. You can still download it and open it with a local app.",
@@ -285,21 +293,40 @@
285
293
  "chatFavoriteModel": "Add to favorites",
286
294
  "chatUnfavoriteModel": "Remove from favorites",
287
295
  "chatManageModels": "Manage models and providers",
296
+ "chatDiscoveredModelsSummary": "{count} new models available",
297
+ "chatDiscoveredModelsView": "View",
298
+ "chatDiscoveredModelsGroup": "New models",
299
+ "chatDiscoveredModelsDismiss": "Don't remind me about these",
300
+ "chatDiscoveredModelAdd": "Add",
301
+ "chatDiscoveredModelAdded": "Added {model}",
302
+ "chatDiscoveredModelUnavailable": "This model is no longer available. Reopen the model selector.",
288
303
  "chatPickerAllSkills": "All skills",
289
304
  "chatSend": "Send",
305
+ "chatContinueRun": "Continue",
306
+ "chatEditMessage": "Edit message",
307
+ "chatEditMessageCancel": "Cancel",
308
+ "chatEditMessagePlaceholder": "Edit your message",
309
+ "chatEditMessageSubmit": "Send",
290
310
  "chatStop": "Stop",
291
311
  "chatStopPreparing": "Preparing stoppable run…",
292
312
  "chatStopUnavailable": "Manual stop is not supported by the current backend engine.",
293
313
  "chatContextWindow": "Context window",
294
314
  "chatContextWindowUsed": "Projected use",
315
+ "chatContextWindowFixed": "System and tools",
316
+ "chatContextWindowDynamic": "Conversation",
317
+ "chatContextWindowTrigger": "Auto-compaction threshold",
318
+ "chatContextWindowReserve": "Output reserve",
295
319
  "chatContextWindowTotal": "Total",
296
320
  "chatContextWindowAvailable": "Available",
321
+ "chatContextWindowAvailableBeforeCompaction": "Until auto-compaction",
297
322
  "chatContextWindowPruned": "After safety pruning",
298
323
  "chatContextWindowDroppedHistory": "Dropped history",
299
324
  "chatContextWindowTruncatedTools": "Truncated tool results",
300
325
  "chatContextWindowUpdatedAt": "Updated",
301
326
  "chatContextCompactionCompressing": "Compressing earlier context",
302
327
  "chatContextCompactionCompressed": "Earlier context was auto-compacted",
328
+ "chatContextCompactionCancelled": "Context compaction was cancelled",
329
+ "chatContextCompactionFailed": "Context compaction failed",
303
330
  "chatContextCompactionCoveredMessages": "Covered messages",
304
331
  "chatContextCompactionOriginalTokens": "Estimated before compaction",
305
332
  "chatContextCompactionProjectedTokens": "Estimated after compaction",
@@ -357,7 +384,6 @@
357
384
  "chatSessionErrorTitle": "Something went wrong",
358
385
  "chatSessionActivityInterrupted": "The run was interrupted. Send the message again.",
359
386
  "chatSendFailed": "Failed to send message",
360
- "chatErrorDetails": "Details",
361
387
  "chatRoleUser": "You",
362
388
  "chatRoleAssistant": "Assistant",
363
389
  "chatRoleTool": "Tool",
@@ -429,7 +455,8 @@
429
455
  "chatWelcomeContextLabel": "Task context",
430
456
  "chatWelcomeProjectPickerLabel": "Choose working directory",
431
457
  "chatWelcomeProjectPickerPlaceholder": "Choose working directory",
432
- "chatWelcomeProjectRecentTitle": "Recent projects",
458
+ "chatWelcomeProjectRecentTitle": "Working directories",
459
+ "chatWelcomeProjectDefaultBadge": "Default",
433
460
  "chatWelcomeProjectNoRecent": "No recent projects yet",
434
461
  "chatWelcomeProjectOpenFolder": "Open folder",
435
462
  "chatWelcomeSessionTypePickerLabel": "Choose session type",
@@ -448,6 +475,8 @@
448
475
  "chatSkillPreviewUnavailable": "This skill file is unavailable. It may have been moved or removed.",
449
476
  "chatInputAdd": "Add content",
450
477
  "chatInputAttach": "Attach file",
478
+ "chatInputRemoveReference": "Remove reference",
479
+ "chatWorkspaceExcerptCharacterCount": "{count} characters",
451
480
  "chatInputAttachmentUnsupported": "This file type is not supported in the current upload flow.",
452
481
  "chatInputAttachmentTooLarge": "Files must be {maxMb} MB or smaller.",
453
482
  "chatInputAttachmentReadFailed": "Failed to read the file. Please try again."
@@ -40,6 +40,7 @@
40
40
  "saving": "Saving...",
41
41
  "remove": "Remove",
42
42
  "more": "More",
43
+ "notificationDismiss": "Dismiss notification",
43
44
  "all": "All",
44
45
  "yes": "Yes",
45
46
  "no": "No",
@@ -56,6 +57,7 @@
56
57
  "themeDawn": "Dawn",
57
58
  "themeGraphite": "Graphite",
58
59
  "themeNight": "Night",
60
+ "themeCharcoal": "Charcoal",
59
61
  "themeProbe": "Probe",
60
62
  "isRequired": "is required",
61
63
  "duplicate": "duplicate",
@@ -115,6 +117,30 @@
115
117
  "providerTestConnectionSuccess": "Connection test passed",
116
118
  "providerTestConnectionFailed": "Connection test failed",
117
119
  "providerModelsTitle": "Available Models",
120
+ "providerModelsFetch": "Fetch model list",
121
+ "providerModelsFetching": "Fetching...",
122
+ "providerModelsFetchSuccess": "Model list fetched",
123
+ "providerModelsFetchFailed": "Failed to fetch model list",
124
+ "providerModelsApiKeyRequired": "Please enter an API Key before fetching the model list",
125
+ "providerModelsAuthorizationFailed": "Authentication failed. Check the API Key and API address",
126
+ "providerModelsSuggestionsChecking": "Loading the model catalog…",
127
+ "providerModelsSuggestionsFailed": "Unable to load the model catalog. Check the API Key, API address, or network connection; you can still add models manually.",
128
+ "providerModelsSuggestionsSummary": "Catalog models not added: {count}",
129
+ "providerModelsFetchedSuggestionsSummary": "{count} fetched models available to add",
130
+ "providerModelsFetchedAllConfigured": "Fetched {count} models; all are already in the current list",
131
+ "providerModelsSuggestionsAddAll": "Add all",
132
+ "providerModelsSuggestionSelect": "Select model {model}",
133
+ "providerModelsSuggestionsSelected": "{count} selected",
134
+ "providerModelsSuggestionsAddSelected": "Add selected",
135
+ "providerModelsSuggestionsSaveHint": "Save to apply the added models.",
136
+ "providerModelsSuggestionsSearchPlaceholder": "Search catalog models",
137
+ "providerModelsSuggestionsSearchEmpty": "No matching models",
138
+ "providerModelsSuggestionsShowing": "Showing the first {visible} of {count} matches; refine your search to narrow the list",
139
+ "providerModelsBulkRemove": "Bulk delete",
140
+ "providerModelsSelectAll": "Select all",
141
+ "providerModelsClearSelection": "Clear selection",
142
+ "providerModelsRemoveSelected": "Delete selected",
143
+ "providerModelsRemoveSaveHint": "Deletion only changes this draft and applies after you save.",
118
144
  "providerModelInputPlaceholder": "Enter provider-local model id (may contain /)",
119
145
  "providerModelInputHint": "The list is only a reference. You can type and add models that are not listed.",
120
146
  "providerAddModel": "Add Model",
@@ -68,6 +68,7 @@
68
68
  "serviceAppsEmptyTitle": "No service apps",
69
69
  "serviceAppsEmptyDescription": "Service apps expose local runtimes and actions that panel apps can call.",
70
70
  "serviceAppsRefresh": "Refresh service apps",
71
+ "serviceAppsConnect": "Connect",
71
72
  "serviceAppsDiscoverActions": "Connect and discover actions",
72
73
  "serviceAppsDiscoverActionsHint": "Connect to the service app runtime and discover its available actions.",
73
74
  "serviceAppsDisconnectRuntime": "Disconnect runtime",
@@ -15,6 +15,7 @@
15
15
  "searchProviderBochaDescription": "AI-ready search that works better for mainland China users.",
16
16
  "searchProviderTavilyDescription": "Research-focused search with configurable answer synthesis.",
17
17
  "searchProviderBraveDescription": "Keep Brave as an optional provider.",
18
+ "searchProviderExaDescription": "Semantic search with page content for research and discovery.",
18
19
  "searchStatusConfigured": "Configured",
19
20
  "searchStatusNeedsSetup": "Needs Setup",
20
21
  "searchFreshnessNoLimit": "No Limit",