@nextclaw/ui 0.17.1 → 0.18.0
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.
- package/CHANGELOG.md +30 -0
- package/dist/assets/{abnfDiagram-VRR7QNED-BcFJp_1X.js → abnfDiagram-VRR7QNED-DvTjgVMf.js} +1 -1
- package/dist/assets/{aiden0z-pptx-renderer.es-Dp2ezlQn.js → aiden0z-pptx-renderer.es-C1nfBAXR.js} +1 -1
- package/dist/assets/{api-DJ6ZKWFY.js → api-BJioGtWS.js} +3 -3
- package/dist/assets/{appearance-settings-page-B-juoJ6F.js → appearance-settings-page-DAF1fd14.js} +1 -1
- package/dist/assets/{arc-CkgyPMyW.js → arc-BvhODBXv.js} +1 -1
- package/dist/assets/architecture-TIHT7OUA-Bjp9jf0h.js +1 -0
- package/dist/assets/{architectureDiagram-ZJ3FMSHR-CMd4cIjI.js → architectureDiagram-ZJ3FMSHR-BKO9RgNS.js} +1 -1
- package/dist/assets/{blockDiagram-677ZJIJ3-Bz3tbhet.js → blockDiagram-677ZJIJ3-DHpDXy7D.js} +1 -1
- package/dist/assets/book-open-aDv6R1av.js +1 -0
- package/dist/assets/{c4Diagram-LMCZKHZV-D9hFNAGv.js → c4Diagram-LMCZKHZV-BG_iQnDr.js} +1 -1
- package/dist/assets/channel-5T3pdR-s.js +1 -0
- package/dist/assets/{channels-list-page-mVHYa7xW.js → channels-list-page-Dubt8r9S.js} +2 -2
- package/dist/assets/{chat-page-DsMYGNee.js → chat-page-JbwjeUo4.js} +1 -1
- package/dist/assets/chunk-2Q5K7J3B-DTZ3tGfE.js +1 -0
- package/dist/assets/{chunk-32BRIVSS-7NrjEITq.js → chunk-32BRIVSS-DR9M0LLx.js} +1 -1
- package/dist/assets/{chunk-52WLFC77-viIcqj9q.js → chunk-52WLFC77-698iC3BB.js} +1 -1
- package/dist/assets/{chunk-5FCAYU7R-Vsu4J-VM.js → chunk-5FCAYU7R-DikTj9Ey.js} +1 -1
- package/dist/assets/{chunk-5HE753X5-C-w6CQZK.js → chunk-5HE753X5-ko0o7_q0.js} +1 -1
- package/dist/assets/{chunk-5JV3BV7I-CuKgJQ4W.js → chunk-5JV3BV7I-CEHufhgo.js} +1 -1
- package/dist/assets/{chunk-5TONJI2A-CYeiWZKb.js → chunk-5TONJI2A-CGgno1cu.js} +1 -1
- package/dist/assets/{chunk-5VM5RSS4-DRCbfwIn.js → chunk-5VM5RSS4-DkiB4cUQ.js} +1 -1
- package/dist/assets/{chunk-7BUUIJ7U-BvydOcm3.js → chunk-7BUUIJ7U-DzptcytQ.js} +1 -1
- package/dist/assets/{chunk-BIQX33UG-RlppOXKo.js → chunk-BIQX33UG-DMRSQJvT.js} +1 -1
- package/dist/assets/{chunk-C7G6YPKG-DAizzYwr.js → chunk-C7G6YPKG-Bw1BwwuY.js} +1 -1
- package/dist/assets/{chunk-CQNSW5MT-5eChJHca.js → chunk-CQNSW5MT-C0z6eHBk.js} +1 -1
- package/dist/assets/{chunk-CYSBUYHQ-YHPr53fv.js → chunk-CYSBUYHQ-ByPyAouO.js} +1 -1
- package/dist/assets/{chunk-EMLP6XTP-CK4D7Hz5.js → chunk-EMLP6XTP-CJlAXWZg.js} +1 -1
- package/dist/assets/{chunk-EX3LRPZG-BmlDFIRW.js → chunk-EX3LRPZG-Dqq4zKJu.js} +1 -1
- package/dist/assets/{chunk-FWX5IMBZ-D0ksHZZ9.js → chunk-FWX5IMBZ-B0SNoCmi.js} +2 -2
- package/dist/assets/{chunk-HOUHSVGY-DPkq8FCm.js → chunk-HOUHSVGY-DG_GJih_.js} +1 -1
- package/dist/assets/{chunk-ICXQ74PX-FAatv5fC.js → chunk-ICXQ74PX-Drxk_6bE.js} +1 -1
- package/dist/assets/{chunk-JG7HCLWE-DLkIi4F7.js → chunk-JG7HCLWE-DdLFPpnd.js} +1 -1
- package/dist/assets/{chunk-JWPE2WC7-DawOjNE3.js → chunk-JWPE2WC7-B8M4G76F.js} +1 -1
- package/dist/assets/{chunk-MOJQB5TN-Di52TorW.js → chunk-MOJQB5TN-XP6FJHY_.js} +1 -1
- package/dist/assets/{chunk-MOZMSUNE-PfyK9w1-.js → chunk-MOZMSUNE-C_6x18Qw.js} +1 -1
- package/dist/assets/{chunk-OGEWGWER-C3jdH3Ty.js → chunk-OGEWGWER-N25BzCmG.js} +1 -1
- package/dist/assets/{chunk-OSBZ3O6U-CecHo-f0.js → chunk-OSBZ3O6U-ASDEm7y0.js} +1 -1
- package/dist/assets/{chunk-PUDLZKDR-f3IJh3sN.js → chunk-PUDLZKDR-CTlvAcn7.js} +1 -1
- package/dist/assets/{chunk-Q4XR5HBZ-DQFeUPxZ.js → chunk-Q4XR5HBZ-Da9BWfB6.js} +1 -1
- package/dist/assets/{chunk-QBLGF6JB-BhUeG0y2.js → chunk-QBLGF6JB-Bi6RpTJO.js} +1 -1
- package/dist/assets/{chunk-R7FJI6CG-C3XpZ-2u.js → chunk-R7FJI6CG-DkMsSPvK.js} +1 -1
- package/dist/assets/{chunk-RYQCIY6F-CAqa5klQ.js → chunk-RYQCIY6F-DZp0eU-j.js} +1 -1
- package/dist/assets/{chunk-U6XO7XAA-D_WXezeD.js → chunk-U6XO7XAA-vfinDSrj.js} +1 -1
- package/dist/assets/{chunk-V7JOEXUC-CZ70oOtp.js → chunk-V7JOEXUC-C9Nksccs.js} +1 -1
- package/dist/assets/chunk-VAUOI2AC-HLGIHQ6k.js +1 -0
- package/dist/assets/{chunk-VR4S4FIN-B7AHEYYk.js → chunk-VR4S4FIN-Xv6zfwXs.js} +1 -1
- package/dist/assets/{chunk-WYO6CB5R-Dn9To_OI.js → chunk-WYO6CB5R-mOJNzbWl.js} +2 -2
- package/dist/assets/chunk-XXDRQBXY-Dl0m6Ni-.js +1 -0
- package/dist/assets/{chunk-YOTPTUD7-BYEgRBk3.js → chunk-YOTPTUD7-1-aKSu4o.js} +1 -1
- package/dist/assets/{chunk-ZGVPDNZ5-C6YtZDU0.js → chunk-ZGVPDNZ5-OJ8veMpK.js} +1 -1
- package/dist/assets/{chunk-ZIRB5QZD-DMuYtnHF.js → chunk-ZIRB5QZD-SR_Nq_PP.js} +1 -1
- package/dist/assets/classDiagram-OUVF2IWQ-DcDnzGNX.js +1 -0
- package/dist/assets/classDiagram-v2-EOCWNBFH-BKXKMzKM.js +1 -0
- package/dist/assets/{config-split-page-BaqLcRxk.js → config-split-page-Bs1wArsX.js} +1 -1
- package/dist/assets/{confirm-dialog-DasFoaCT.js → confirm-dialog-BFatCZUq.js} +1 -1
- package/dist/assets/{cose-bilkent-JH36ORCC-Bc2Ex5Y3.js → cose-bilkent-JH36ORCC-NjVgz2Bw.js} +1 -1
- package/dist/assets/cynefin-VYW2F7L2-BWg7U2UD.js +1 -0
- package/dist/assets/{cynefinDiagram-TSTJHNR4-DVysQoGz.js → cynefinDiagram-TSTJHNR4-B_17LDqD.js} +1 -1
- package/dist/assets/{dagre-CMhQ1cAG.js → dagre-CMe101gk.js} +1 -1
- package/dist/assets/{dagre-VKFMJZFB-RYyWpPJZ.js → dagre-VKFMJZFB-qo8nLb3B.js} +1 -1
- package/dist/assets/{desktop-update-config-CoEvKrpB.js → desktop-update-config-DFefhK96.js} +1 -1
- package/dist/assets/{diagram-FQU43EPY-BD6KONdF.js → diagram-FQU43EPY-Ba3XIklC.js} +1 -1
- package/dist/assets/{diagram-G47NLZAW-CGB2ptRR.js → diagram-G47NLZAW-CG45TcUx.js} +1 -1
- package/dist/assets/{diagram-NH7WQ7WH-DnkOI6cU.js → diagram-NH7WQ7WH-2F2HrwV-.js} +1 -1
- package/dist/assets/{diagram-OA4YK3LP-DF82RZ7P.js → diagram-OA4YK3LP-CXfWH9NZ.js} +1 -1
- package/dist/assets/{diagram-WEI45ONY-Be2v7Ck9.js → diagram-WEI45ONY-CH_4yepc.js} +1 -1
- package/dist/assets/{dist-C741xUwt.js → dist-CV9wIyME.js} +1 -1
- package/dist/assets/{dist-zOKNc7QQ.js → dist-D1I3blO_.js} +1 -1
- package/dist/assets/doc-browser-BFfstBoh.js +1 -0
- package/dist/assets/doc-browser-DEdoMb3X.js +1 -0
- package/dist/assets/{doc-browser-context-BT8NWQyM.js → doc-browser-context-BcwcVwX_.js} +1 -1
- package/dist/assets/{docx-preview-BqwAjrj3.js → docx-preview-CoM4JK7_.js} +1 -1
- package/dist/assets/{ebnfDiagram-CCIWWBDH-CP98OYk8.js → ebnfDiagram-CCIWWBDH-BwiG4Ea1.js} +1 -1
- package/dist/assets/{erDiagram-Q63AITRT-ZLlx8xfs.js → erDiagram-Q63AITRT-BML3hpnQ.js} +1 -1
- package/dist/assets/eventmodeling-45OFAUF4-SB-J4tpq.js +1 -0
- package/dist/assets/flowDiagram-23GEKE2U-BQ_u-eLM.js +1 -0
- package/dist/assets/{form-actions-BcukaMyR.js → form-actions-YSnn7q_U.js} +1 -1
- package/dist/assets/{ganttDiagram-NO4QXBWP-DXCDjHR2.js → ganttDiagram-NO4QXBWP-80enfWbD.js} +1 -1
- package/dist/assets/gitGraph-TEB2WS4Q-DPxNwsFd.js +1 -0
- package/dist/assets/{gitGraphDiagram-IHSO6WYX-l2HWrTJp.js → gitGraphDiagram-IHSO6WYX-CVLqXr-b.js} +1 -1
- package/dist/assets/index-Bsoscjk7.css +1 -0
- package/dist/assets/index-L58BO782.js +109 -0
- package/dist/assets/info-DKCQHKI2-DNlNGH90.js +1 -0
- package/dist/assets/{infoDiagram-FWYZ7A6U-D-DjX-bn.js → infoDiagram-FWYZ7A6U-Dyvs2t0i.js} +1 -1
- package/dist/assets/{ishikawaDiagram-FXEZZL3T-y_Xy128F.js → ishikawaDiagram-FXEZZL3T-sSnxDKfh.js} +1 -1
- package/dist/assets/{journeyDiagram-5HDEW3XC-DJn5xYcQ.js → journeyDiagram-5HDEW3XC-D22V71Mf.js} +1 -1
- package/dist/assets/{kanban-definition-HUTT4EX6-DJVIOR21.js → kanban-definition-HUTT4EX6-D3ds0p-g.js} +1 -1
- package/dist/assets/{line-Cos7PIOj.js → line-CbyFs065.js} +1 -1
- package/dist/assets/{linear-BtDLqtzF.js → linear-4DKtnZBS.js} +1 -1
- package/dist/assets/loader-circle-CsNiT6VM.js +1 -0
- package/dist/assets/{map-BKnQyvd0.js → map-CcZzEoz6.js} +1 -1
- package/dist/assets/mcp-marketplace-page-DfUCF-L5.js +1 -0
- package/dist/assets/mcp-marketplace-page-ZTHpQTvi.js +9 -0
- package/dist/assets/{mermaid-parser.core-XUNZhr2W.js → mermaid-parser.core-DPmMOjXD.js} +2 -2
- package/dist/assets/{mermaid.core-ySrvolIe.js → mermaid.core-BSf-ddRa.js} +3 -3
- package/dist/assets/{mindmap-definition-LN4V7U3C-BypL9tei.js → mindmap-definition-LN4V7U3C-BUTwWPyx.js} +1 -1
- package/dist/assets/model-config-page-jYCwpq4U.js +1 -0
- package/dist/assets/{navigation-link-BoMNAKyw.js → navigation-link-7oSjAC9R.js} +1 -1
- package/dist/assets/{ordinal-CxxVWxYU.js → ordinal-BgLYtOZE.js} +1 -1
- package/dist/assets/packet-7NZHBO7P-BpeiqkBZ.js +1 -0
- package/dist/assets/{pegDiagram-2B236MQR-D-U2KBGv.js → pegDiagram-2B236MQR-BEu_ZBjc.js} +1 -1
- package/dist/assets/pie-RZYD4A2V-Cy1yxsPd.js +1 -0
- package/dist/assets/{pieDiagram-ENE6RG2P-CBi3GusJ.js → pieDiagram-ENE6RG2P-CAwAwuBd.js} +1 -1
- package/dist/assets/plus-D6UN8XN5.js +1 -0
- package/dist/assets/{provider-scoped-model-input-CB-vojwC.js → provider-scoped-model-input-C1CUHVJx.js} +1 -1
- package/dist/assets/{providers-config-page-C80nti5H.js → providers-config-page-CMvI4R1e.js} +1 -1
- package/dist/assets/{quadrantDiagram-ABIIQ3AL-H0ZuvnZL.js → quadrantDiagram-ABIIQ3AL-CwE6F-_2.js} +1 -1
- package/dist/assets/radar-I7S5WNFK-CEcPKCj8.js +1 -0
- package/dist/assets/railroad-3IZDKUUU-CW38eNDs.js +1 -0
- package/dist/assets/railroad-abnf-AHOZXSZD-ByrylcXf.js +1 -0
- package/dist/assets/railroad-ebnf-EBAXGLYW-CNB6GwP-.js +1 -0
- package/dist/assets/railroad-peg-LSFZ7HO6-x6hnqlBG.js +1 -0
- package/dist/assets/{railroadDiagram-RFXS5EU6-D7Y2EqSd.js → railroadDiagram-RFXS5EU6-xgLekU3B.js} +1 -1
- package/dist/assets/react-7zG0fz1I.js +8 -0
- package/dist/assets/{refresh-cw-DZ_Y89ld.js → refresh-cw-BUg7hI3u.js} +1 -1
- package/dist/assets/remote-BYPq49kD.js +1 -0
- package/dist/assets/{requirementDiagram-TGXJPOKE-BiXNX1NN.js → requirementDiagram-TGXJPOKE-CyVUzEX5.js} +1 -1
- package/dist/assets/rotate-cw-B3qmXtfJ.js +1 -0
- package/dist/assets/runtime-config-page-DYuYv5yM.js +1 -0
- package/dist/assets/{sankeyDiagram-HTMAVEWB-qzDeLztW.js → sankeyDiagram-HTMAVEWB-JK6bFmYB.js} +1 -1
- package/dist/assets/{save-BgMfxs5u.js → save-CTCYuZqu.js} +1 -1
- package/dist/assets/{search-C7ruoV7u.js → search-CfFUpaf7.js} +1 -1
- package/dist/assets/{search-config-page-BTjfOZ6q.js → search-config-page-GUtGbk6i.js} +1 -1
- package/dist/assets/{secrets-config-page-BFjiSz73.js → secrets-config-page-Delo8ab0.js} +2 -2
- package/dist/assets/security-config-DoVoel5I.js +1 -0
- package/dist/assets/{select-BMX2ooE-.js → select-MSvkWmPP.js} +1 -1
- package/dist/assets/{sequenceDiagram-DBY2YBRQ-BtRbPQtL.js → sequenceDiagram-DBY2YBRQ-BR5IokXV.js} +1 -1
- package/dist/assets/{settings-2-BNQF6hed.js → settings-2-DXUfAWgg.js} +1 -1
- package/dist/assets/{sizeCapture-X5ZJPWSS-CMYvM3SL.js → sizeCapture-X5ZJPWSS-SxG_YnMA.js} +1 -1
- package/dist/assets/skeleton-DDFivi9Y.js +1 -0
- package/dist/assets/{src-Bw-mzbQb.js → src-vgz8E_-O.js} +1 -1
- package/dist/assets/{stateDiagram-2N3HPSRC-BJ-mFeOz.js → stateDiagram-2N3HPSRC-DD4OoYhn.js} +1 -1
- package/dist/assets/stateDiagram-v2-6OUMAXLB-ZC6dFORv.js +1 -0
- package/dist/assets/{swimlanes-5IMT3BWC-BsucVOO2.js → swimlanes-5IMT3BWC-BWkFeyCT.js} +2 -2
- package/dist/assets/swimlanesDiagram-G3AALYLV-CRkh51Im.js +8 -0
- package/dist/assets/{tag-chip-BL-UXlVO.js → tag-chip-u8g0b0Nf.js} +1 -1
- package/dist/assets/{timeline-definition-FHXFAJF6-Bicewlzo.js → timeline-definition-FHXFAJF6-VTRPy6KA.js} +1 -1
- package/dist/assets/treeView-QDETBFTQ-Bw0DSCH7.js +1 -0
- package/dist/assets/treemap-6X3UGDF4-DFWBFcfh.js +1 -0
- package/dist/assets/{vennDiagram-L72KCM5P-BxOOnO9x.js → vennDiagram-L72KCM5P-Bvk42Pek.js} +1 -1
- package/dist/assets/wardley-OPB4EBWU-CoWturk0.js +1 -0
- package/dist/assets/{wardleyDiagram-EHGQE667-Cl7NltMv.js → wardleyDiagram-EHGQE667-DOFjx2s3.js} +1 -1
- package/dist/assets/x-DdOEUmR4.js +1 -0
- package/dist/assets/{xychartDiagram-FW5EYKEG-DiMIxQ7N.js → xychartDiagram-FW5EYKEG-DY5yRTUc.js} +1 -1
- package/dist/index.html +22 -21
- package/package.json +9 -9
- package/src/features/chat/features/conversation/components/__tests__/session-conversation-input.streaming.test.tsx +2 -0
- package/src/features/chat/features/conversation/components/session-conversation-area.tsx +2 -0
- package/src/features/chat/features/conversation/components/session-conversation-input.tsx +2 -0
- package/src/features/chat/features/conversation/hooks/__tests__/use-session-conversation-controller.test.tsx +46 -0
- package/src/features/chat/features/conversation/hooks/__tests__/use-session-conversation-slash-commands.test.tsx +20 -0
- package/src/features/chat/features/conversation/hooks/use-session-conversation-controller.ts +138 -54
- package/src/features/chat/features/conversation/hooks/use-session-conversation-slash-commands.ts +25 -2
- package/src/features/chat/features/message/utils/__tests__/chat-message-show-content-tool-card.utils.test.ts +46 -0
- package/src/features/chat/features/message/utils/chat-message-part.utils.ts +2 -0
- package/src/features/chat/features/message/utils/chat-message-tool-card.utils.ts +52 -2
- package/src/features/chat/features/ncp/hooks/__tests__/use-hydrated-ncp-agent.test.tsx +97 -10
- package/src/features/chat/features/ncp/hooks/use-ncp-session-conversation.ts +4 -0
- package/src/features/chat/features/ncp/hooks/use-ncp-session-queries.ts +10 -0
- package/src/features/chat/features/session/utils/__tests__/ncp-session-adapter.utils.test.ts +27 -0
- package/src/features/chat/features/session/utils/ncp-session-adapter.utils.ts +2 -1
- package/src/features/chat/features/workspace/components/__tests__/chat-session-child-sessions.test.tsx +51 -0
- package/src/features/chat/features/workspace/components/__tests__/chat-session-token-usage.test.tsx +90 -0
- package/src/features/chat/features/workspace/components/__tests__/chat-session-workspace-panel-content.test.tsx +9 -17
- package/src/features/chat/features/workspace/components/chat-session-workspace-panel-content.tsx +4 -45
- package/src/features/chat/features/workspace/components/child-sessions/chat-session-child-sessions.tsx +66 -0
- package/src/features/chat/features/workspace/components/overview/chat-session-token-usage.tsx +171 -0
- package/src/features/chat/types/chat-message.types.ts +5 -0
- package/src/shared/components/doc-browser/__tests__/doc-browser-tab-strip.test.tsx +78 -0
- package/src/shared/components/doc-browser/doc-browser-tab-strip.tsx +71 -3
- package/src/shared/components/ui/tab-strip/__tests__/compact-tab-strip.test.tsx +78 -1
- package/src/shared/components/ui/tab-strip/compact-tab-strip.tsx +97 -44
- package/src/shared/lib/api/__tests__/ncp-session-query-cache.utils.test.ts +2 -0
- package/src/shared/lib/api/ncp-session-query-cache.utils.ts +4 -0
- package/src/shared/lib/api/ncp-session.types.ts +3 -0
- package/src/shared/lib/api/types.ts +1 -0
- package/src/shared/lib/api/utils/ncp-session.utils.ts +8 -0
- package/src/shared/lib/i18n/locales/en-US/chat.json +23 -0
- package/src/shared/lib/i18n/locales/zh-CN/chat.json +24 -1
- package/dist/assets/architecture-TIHT7OUA-DO2x53FK.js +0 -1
- package/dist/assets/channel-nBvMaVyP.js +0 -1
- package/dist/assets/chunk-2Q5K7J3B-CJgqFDS4.js +0 -1
- package/dist/assets/chunk-VAUOI2AC-BGvh3yIx.js +0 -1
- package/dist/assets/chunk-XXDRQBXY-DaBxG5gs.js +0 -1
- package/dist/assets/classDiagram-OUVF2IWQ-P6N03G2R.js +0 -1
- package/dist/assets/classDiagram-v2-EOCWNBFH-B1_uLvMv.js +0 -1
- package/dist/assets/cynefin-VYW2F7L2-B-H8Qp-n.js +0 -1
- package/dist/assets/doc-browser-BbirIYbj.js +0 -1
- package/dist/assets/doc-browser-Crqog5cn.js +0 -1
- package/dist/assets/eventmodeling-45OFAUF4-YVtShyFA.js +0 -1
- package/dist/assets/flowDiagram-23GEKE2U-BeKXabVO.js +0 -1
- package/dist/assets/gitGraph-TEB2WS4Q-jTSiBj-p.js +0 -1
- package/dist/assets/index-1f4Pv2q3.css +0 -1
- package/dist/assets/index-BYWLjYFQ.js +0 -109
- package/dist/assets/info-DKCQHKI2-BIporNWb.js +0 -1
- package/dist/assets/loader-circle-LVHz84Xj.js +0 -1
- package/dist/assets/mcp-marketplace-page-2SsrbaiQ.js +0 -1
- package/dist/assets/mcp-marketplace-page-XgYLOAkK.js +0 -9
- package/dist/assets/model-config-page-DL8ljJK-.js +0 -1
- package/dist/assets/packet-7NZHBO7P-CuFMADV0.js +0 -1
- package/dist/assets/pie-RZYD4A2V-XUeIXhM9.js +0 -1
- package/dist/assets/plus-BeGZHC3f.js +0 -1
- package/dist/assets/radar-I7S5WNFK-D-NNGh1k.js +0 -1
- package/dist/assets/railroad-3IZDKUUU-C67_uDaM.js +0 -1
- package/dist/assets/railroad-abnf-AHOZXSZD-BZ8Yflnd.js +0 -1
- package/dist/assets/railroad-ebnf-EBAXGLYW-B7zO7RoK.js +0 -1
- package/dist/assets/railroad-peg-LSFZ7HO6-R63PTgLz.js +0 -1
- package/dist/assets/react-DND3vEAM.js +0 -8
- package/dist/assets/remote-Codkr9SX.js +0 -1
- package/dist/assets/rotate-cw-CP3pQ4R8.js +0 -1
- package/dist/assets/runtime-config-page-Um1XDqXJ.js +0 -1
- package/dist/assets/security-config-Dx-wMb4q.js +0 -1
- package/dist/assets/skeleton-CWZ0IO2D.js +0 -1
- package/dist/assets/stateDiagram-v2-6OUMAXLB-BE-HqxOK.js +0 -1
- package/dist/assets/swimlanesDiagram-G3AALYLV-Dr1H9LJH.js +0 -8
- package/dist/assets/treeView-QDETBFTQ-npJ5dbqS.js +0 -1
- package/dist/assets/treemap-6X3UGDF4-pYrBx6oa.js +0 -1
- package/dist/assets/wardley-OPB4EBWU-CmSRKLR8.js +0 -1
- package/dist/assets/x-BSu1xwPK.js +0 -1
- /package/dist/assets/{array-BQVzeGRt.js → array-NADKd9aU.js} +0 -0
- /package/dist/assets/{chunk-KEIR6QF5-f9psyCXK.js → chunk-KEIR6QF5-BuyuzJJL.js} +0 -0
- /package/dist/assets/{chunk-Y2CYZVJY-D1mAU_Po.js → chunk-Y2CYZVJY-D_B2ZRNt.js} +0 -0
- /package/dist/assets/{config-hints-nV5HPOvq.js → config-hints-BcfVUMij.js} +0 -0
- /package/dist/assets/{cytoscape.esm-0uDtdD0l.js → cytoscape.esm-BANTlgza.js} +0 -0
- /package/dist/assets/{defaultLocale-DSWXGgt0.js → defaultLocale-C4_L0aEs.js} +0 -0
- /package/dist/assets/{dist--ta5rX12.js → dist-DAPEIJbz.js} +0 -0
- /package/dist/assets/{graphlib-CQ6QV4yP.js → graphlib-ChqXg0dI.js} +0 -0
- /package/dist/assets/{host-capabilities-Tk038i04.js → host-capabilities-D9C4CBK5.js} +0 -0
- /package/dist/assets/{init-Y6h9jGtZ.js → init-D8wZg9xq.js} +0 -0
- /package/dist/assets/{jszip.min-8hyJpgpx.js → jszip.min-CkbBfwAQ.js} +0 -0
- /package/dist/assets/{katex-ARhY9PS1.js → katex-TZJFa0J_.js} +0 -0
- /package/dist/assets/{middleware-DXsbf9xI.js → middleware-B3k-TSmZ.js} +0 -0
- /package/dist/assets/{path-10BjdyLh.js → path-DodfxcX7.js} +0 -0
- /package/dist/assets/{rough.esm-DxgC_14r.js → rough.esm-CUaa1Rbe.js} +0 -0
- /package/dist/assets/{xlsx-DrDuDNAa.js → xlsx-CxByi7bR.js} +0 -0
|
@@ -1,13 +1,18 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { useState, type PointerEvent } from "react";
|
|
2
2
|
import {
|
|
3
|
+
AppWindow,
|
|
3
4
|
ArrowLeft,
|
|
4
5
|
ArrowRight,
|
|
6
|
+
BookOpen,
|
|
7
|
+
Boxes,
|
|
8
|
+
Github,
|
|
5
9
|
PanelRightOpen,
|
|
6
10
|
PictureInPicture2,
|
|
7
11
|
Pin,
|
|
8
12
|
PinOff,
|
|
9
13
|
Plus,
|
|
10
14
|
X,
|
|
15
|
+
type LucideIcon,
|
|
11
16
|
} from "lucide-react";
|
|
12
17
|
import type { DocBrowserDockState, DocBrowserTab } from "./doc-browser-context";
|
|
13
18
|
import type { ContextMenuGroup } from "@/shared/components/ui/context-menu/context-menu";
|
|
@@ -39,6 +44,68 @@ type DocBrowserTabStripProps = {
|
|
|
39
44
|
getTabMenuGroups?: (tab: DocBrowserTab) => readonly ContextMenuGroup[] | undefined;
|
|
40
45
|
};
|
|
41
46
|
|
|
47
|
+
const DOC_BROWSER_BUILTIN_TAB_ICONS: Record<string, LucideIcon> = {
|
|
48
|
+
apps: Boxes,
|
|
49
|
+
docs: BookOpen,
|
|
50
|
+
github: Github,
|
|
51
|
+
"new-tab": Plus,
|
|
52
|
+
"panel-app": AppWindow,
|
|
53
|
+
"service-apps": AppWindow,
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
function DocBrowserUrlTabIcon({
|
|
57
|
+
fallbackIcon: FallbackIcon,
|
|
58
|
+
url,
|
|
59
|
+
}: {
|
|
60
|
+
fallbackIcon: LucideIcon;
|
|
61
|
+
url: string;
|
|
62
|
+
}) {
|
|
63
|
+
const [loadFailed, setLoadFailed] = useState(false);
|
|
64
|
+
return loadFailed ? (
|
|
65
|
+
<FallbackIcon className="h-3.5 w-3.5 text-muted-foreground" aria-hidden="true" />
|
|
66
|
+
) : (
|
|
67
|
+
<img
|
|
68
|
+
src={url}
|
|
69
|
+
alt=""
|
|
70
|
+
className="h-3.5 w-3.5 rounded-sm object-cover"
|
|
71
|
+
onError={() => setLoadFailed(true)}
|
|
72
|
+
/>
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function DocBrowserTabIcon({ tab }: { tab: DocBrowserTab }) {
|
|
77
|
+
const { dockIcon } = tab;
|
|
78
|
+
const fallbackIcon = tab.kind === "docs"
|
|
79
|
+
? BookOpen
|
|
80
|
+
: tab.kind === "home"
|
|
81
|
+
? Plus
|
|
82
|
+
: tab.kind === "apps"
|
|
83
|
+
? Boxes
|
|
84
|
+
: AppWindow;
|
|
85
|
+
const Icon = dockIcon?.type === "builtin"
|
|
86
|
+
? (DOC_BROWSER_BUILTIN_TAB_ICONS[dockIcon.name] ?? fallbackIcon)
|
|
87
|
+
: fallbackIcon;
|
|
88
|
+
|
|
89
|
+
if (dockIcon?.type === "url") {
|
|
90
|
+
return (
|
|
91
|
+
<DocBrowserUrlTabIcon
|
|
92
|
+
key={dockIcon.url}
|
|
93
|
+
fallbackIcon={fallbackIcon}
|
|
94
|
+
url={dockIcon.url}
|
|
95
|
+
/>
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
if (dockIcon?.type === "text") {
|
|
99
|
+
return (
|
|
100
|
+
<span className="max-w-3.5 truncate text-[10px] font-semibold leading-none" aria-hidden="true">
|
|
101
|
+
{dockIcon.value}
|
|
102
|
+
</span>
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return <Icon className="h-3.5 w-3.5 text-muted-foreground" aria-hidden="true" />;
|
|
107
|
+
}
|
|
108
|
+
|
|
42
109
|
function shouldBlockHeaderDrag(target: EventTarget | null): boolean {
|
|
43
110
|
return target instanceof Element && Boolean(
|
|
44
111
|
target.closest("button, a, input, textarea, select, [data-compact-tab-item]"),
|
|
@@ -80,8 +147,9 @@ export function DocBrowserTabStrip({
|
|
|
80
147
|
label: tab.title || t("docBrowserTabUntitled"),
|
|
81
148
|
active: tab.id === activeTabId,
|
|
82
149
|
tooltip: tab.title,
|
|
150
|
+
leadingIcon: <DocBrowserTabIcon tab={tab} />,
|
|
83
151
|
closeLabel: closeTabLabel,
|
|
84
|
-
closePlacement: "
|
|
152
|
+
closePlacement: "leading-hover",
|
|
85
153
|
onSelect: () => onSetActiveTab(tab.id),
|
|
86
154
|
onClose: () => onCloseTab(tab.id),
|
|
87
155
|
menuLabel: t("docBrowserTabMoreActions"),
|
|
@@ -132,7 +200,7 @@ export function DocBrowserTabStrip({
|
|
|
132
200
|
tabsClassName="items-center gap-0.5"
|
|
133
201
|
actionsClassName="h-full items-center gap-0.5"
|
|
134
202
|
actionButtonClassName="rounded-md p-1.5 text-muted-foreground hover:bg-muted/60 hover:text-foreground disabled:opacity-50"
|
|
135
|
-
tabBaseClassName="
|
|
203
|
+
tabBaseClassName="inline-flex cursor-pointer items-center gap-0.5 h-7 px-2 rounded-md text-xs max-w-[220px] shrink-0 transition-colors"
|
|
136
204
|
activeTabClassName="bg-muted/80 text-foreground"
|
|
137
205
|
inactiveTabClassName="text-muted-foreground hover:bg-muted/45 hover:text-foreground"
|
|
138
206
|
labelClassName="px-0.5 text-xs font-normal"
|
|
@@ -113,7 +113,7 @@ describe("CompactTabStrip", () => {
|
|
|
113
113
|
active: false,
|
|
114
114
|
closeLabel: "Close preview",
|
|
115
115
|
closePlacement: "leading-hover",
|
|
116
|
-
leadingIcon: <span />,
|
|
116
|
+
leadingIcon: <span data-testid="preview-tab-icon" />,
|
|
117
117
|
onClose,
|
|
118
118
|
onSelect,
|
|
119
119
|
},
|
|
@@ -126,6 +126,83 @@ describe("CompactTabStrip", () => {
|
|
|
126
126
|
|
|
127
127
|
expect(onClose).toHaveBeenCalledTimes(1);
|
|
128
128
|
expect(onSelect).not.toHaveBeenCalled();
|
|
129
|
+
expect(
|
|
130
|
+
screen.getByTestId("preview-tab-icon").parentElement?.className,
|
|
131
|
+
).toContain("group-hover:opacity-0");
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
it("overlays the close action at the start without changing the tab width on hover", () => {
|
|
135
|
+
render(
|
|
136
|
+
<CompactTabStrip
|
|
137
|
+
tabs={[
|
|
138
|
+
{
|
|
139
|
+
key: "marketplace",
|
|
140
|
+
label: "NextClaw Marketplace",
|
|
141
|
+
active: true,
|
|
142
|
+
closeLabel: "Close tab",
|
|
143
|
+
closePlacement: "leading-hover",
|
|
144
|
+
menuLabel: "More tab actions",
|
|
145
|
+
menuGroups: [{ key: "tab", items: [{ key: "close", label: "Close", onSelect: vi.fn() }] }],
|
|
146
|
+
onClose: vi.fn(),
|
|
147
|
+
onSelect: vi.fn(),
|
|
148
|
+
},
|
|
149
|
+
]}
|
|
150
|
+
actions={[]}
|
|
151
|
+
/>,
|
|
152
|
+
);
|
|
153
|
+
|
|
154
|
+
const tabItem = screen.getByRole("button", { name: "NextClaw Marketplace" })
|
|
155
|
+
.closest("[data-compact-tab-item]");
|
|
156
|
+
const leadingActions = tabItem?.querySelector(
|
|
157
|
+
'[data-compact-tab-leading-actions=""]',
|
|
158
|
+
);
|
|
159
|
+
const trailingActions = tabItem?.querySelector(
|
|
160
|
+
'[data-compact-tab-trailing-actions=""]',
|
|
161
|
+
);
|
|
162
|
+
const trailingSpacer = tabItem?.querySelector(
|
|
163
|
+
'[data-compact-tab-trailing-spacer=""]',
|
|
164
|
+
);
|
|
165
|
+
const leadingSlot = tabItem?.querySelector(
|
|
166
|
+
'[data-compact-tab-leading-slot=""]',
|
|
167
|
+
);
|
|
168
|
+
|
|
169
|
+
expect(tabItem?.className).toContain("relative");
|
|
170
|
+
expect(tabItem?.className).toContain("max-w-[180px]");
|
|
171
|
+
expect(tabItem?.className).not.toContain("min-w-[");
|
|
172
|
+
expect(leadingSlot?.className).toContain("w-3.5");
|
|
173
|
+
expect(leadingSlot?.className).toContain("shrink-0");
|
|
174
|
+
expect(leadingActions?.className).toContain("absolute");
|
|
175
|
+
expect(leadingActions?.className).toContain("left-1");
|
|
176
|
+
expect(leadingActions?.className).toContain("opacity-0");
|
|
177
|
+
expect(leadingActions?.className).toContain("pointer-events-none");
|
|
178
|
+
expect(leadingActions?.className).not.toContain("bg-inherit");
|
|
179
|
+
expect(leadingActions?.className).toContain("group-hover:opacity-100");
|
|
180
|
+
expect(leadingActions?.className).toContain("group-focus-within:opacity-100");
|
|
181
|
+
expect(trailingActions?.className).toContain("absolute");
|
|
182
|
+
expect(trailingActions?.className).toContain("opacity-0");
|
|
183
|
+
expect(trailingActions?.className).toContain("pointer-events-none");
|
|
184
|
+
expect(trailingActions?.className).not.toContain("bg-inherit");
|
|
185
|
+
expect(trailingActions?.className).toContain("group-hover:opacity-100");
|
|
186
|
+
expect(trailingActions?.className).toContain("group-focus-within:opacity-100");
|
|
187
|
+
expect(trailingActions?.className).not.toContain("w-0");
|
|
188
|
+
expect(trailingActions?.className).not.toContain("transition-[width");
|
|
189
|
+
expect(trailingSpacer?.className).toContain("w-6");
|
|
190
|
+
expect(trailingSpacer?.className).toContain("shrink-0");
|
|
191
|
+
const closeButton = leadingActions?.querySelector<HTMLButtonElement>(
|
|
192
|
+
'[aria-label="Close tab"]',
|
|
193
|
+
);
|
|
194
|
+
const menuButton = trailingActions?.querySelector<HTMLButtonElement>(
|
|
195
|
+
'[aria-label="More tab actions"]',
|
|
196
|
+
);
|
|
197
|
+
expect(closeButton).toBeTruthy();
|
|
198
|
+
expect(menuButton).toBeTruthy();
|
|
199
|
+
expect(closeButton?.className).toBe(menuButton?.className);
|
|
200
|
+
expect(closeButton?.className).toContain("h-6");
|
|
201
|
+
expect(closeButton?.className).toContain("w-6");
|
|
202
|
+
expect(closeButton?.className).toContain("rounded-md");
|
|
203
|
+
expect(
|
|
204
|
+
trailingActions?.querySelector('[aria-label="Close tab"]'),
|
|
205
|
+
).toBeNull();
|
|
129
206
|
});
|
|
130
207
|
|
|
131
208
|
it("opens a tab action menu without selecting the tab or restoring stale focus after an action", async () => {
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import { MoreVertical, X } from "lucide-react";
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
IconActionButton,
|
|
5
|
+
type IconActionButtonProps,
|
|
6
|
+
} from "@/shared/components/ui/actions/icon-action-button";
|
|
4
7
|
import {
|
|
5
8
|
ContextMenu,
|
|
6
9
|
ContextMenuTrigger,
|
|
@@ -63,28 +66,94 @@ function closeCompactTab(event: React.MouseEvent<HTMLButtonElement>, onClose: ()
|
|
|
63
66
|
onClose();
|
|
64
67
|
}
|
|
65
68
|
|
|
69
|
+
function CompactTabActionButton(props: IconActionButtonProps) {
|
|
70
|
+
return <IconActionButton {...props} size="sm" tone="strong" />;
|
|
71
|
+
}
|
|
72
|
+
|
|
66
73
|
function CompactTabMenu({ tab }: { tab: CompactTabStripTab }) {
|
|
67
74
|
if (!tab.menuGroups?.some((group) => group.items.length > 0)) {
|
|
68
75
|
return null;
|
|
69
76
|
}
|
|
70
77
|
|
|
71
78
|
const menuLabel = tab.menuLabel ?? tab.label;
|
|
79
|
+
return (
|
|
80
|
+
<div className="flex shrink-0">
|
|
81
|
+
<ContextMenuTrigger>
|
|
82
|
+
<CompactTabActionButton
|
|
83
|
+
icon={<MoreVertical className="h-3.5 w-3.5" />}
|
|
84
|
+
label={menuLabel}
|
|
85
|
+
/>
|
|
86
|
+
</ContextMenuTrigger>
|
|
87
|
+
</div>
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function CompactTabTrailingActions({ tab }: { tab: CompactTabStripTab }) {
|
|
92
|
+
const hasMenu = tab.menuGroups?.some((group) => group.items.length > 0) ?? false;
|
|
93
|
+
const hasTrailingClose = Boolean(
|
|
94
|
+
tab.onClose && tab.closePlacement !== "leading-hover",
|
|
95
|
+
);
|
|
96
|
+
const close = hasTrailingClose ? (
|
|
97
|
+
<CompactTabActionButton
|
|
98
|
+
icon={<X className="h-3.5 w-3.5" />}
|
|
99
|
+
label={tab.closeLabel ?? ""}
|
|
100
|
+
tooltip={tab.closeLabel ?? null}
|
|
101
|
+
onClick={(event) => closeCompactTab(event, tab.onClose!)}
|
|
102
|
+
/>
|
|
103
|
+
) : null;
|
|
104
|
+
|
|
105
|
+
if (!hasMenu && !hasTrailingClose) {
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
return (
|
|
110
|
+
<>
|
|
111
|
+
<span
|
|
112
|
+
aria-hidden="true"
|
|
113
|
+
data-compact-tab-trailing-spacer=""
|
|
114
|
+
className={cn(
|
|
115
|
+
"shrink-0",
|
|
116
|
+
hasMenu && hasTrailingClose
|
|
117
|
+
? "w-[50px]"
|
|
118
|
+
: hasMenu
|
|
119
|
+
? "w-6"
|
|
120
|
+
: "w-6",
|
|
121
|
+
)}
|
|
122
|
+
/>
|
|
123
|
+
<div
|
|
124
|
+
data-compact-tab-trailing-actions=""
|
|
125
|
+
className={cn(
|
|
126
|
+
"pointer-events-none absolute inset-y-0 right-1 z-10 flex items-center gap-0.5 opacity-0",
|
|
127
|
+
"group-hover:pointer-events-auto group-hover:opacity-100 group-focus-within:pointer-events-auto group-focus-within:opacity-100",
|
|
128
|
+
"group-data-[context-menu-open]:pointer-events-auto group-data-[context-menu-open]:opacity-100",
|
|
129
|
+
)}
|
|
130
|
+
>
|
|
131
|
+
{hasMenu ? <CompactTabMenu tab={tab} /> : null}
|
|
132
|
+
{close}
|
|
133
|
+
</div>
|
|
134
|
+
</>
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function CompactTabLeadingCloseOverlay({ tab }: { tab: CompactTabStripTab }) {
|
|
139
|
+
if (!tab.onClose || tab.closePlacement !== "leading-hover") {
|
|
140
|
+
return null;
|
|
141
|
+
}
|
|
142
|
+
|
|
72
143
|
return (
|
|
73
144
|
<div
|
|
145
|
+
data-compact-tab-leading-actions=""
|
|
74
146
|
className={cn(
|
|
75
|
-
"-
|
|
76
|
-
"group-
|
|
147
|
+
"pointer-events-none absolute inset-y-0 left-1 z-10 flex items-center opacity-0",
|
|
148
|
+
"group-hover:pointer-events-auto group-hover:opacity-100 group-focus-within:pointer-events-auto group-focus-within:opacity-100",
|
|
77
149
|
)}
|
|
78
150
|
>
|
|
79
|
-
<
|
|
80
|
-
<
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
<MoreVertical className="h-3.5 w-3.5" />
|
|
86
|
-
</button>
|
|
87
|
-
</ContextMenuTrigger>
|
|
151
|
+
<CompactTabActionButton
|
|
152
|
+
icon={<X className="h-3.5 w-3.5" />}
|
|
153
|
+
label={tab.closeLabel ?? ""}
|
|
154
|
+
tooltip={tab.closeLabel ?? null}
|
|
155
|
+
onClick={(event) => closeCompactTab(event, tab.onClose!)}
|
|
156
|
+
/>
|
|
88
157
|
</div>
|
|
89
158
|
);
|
|
90
159
|
}
|
|
@@ -96,9 +165,9 @@ function CompactTabLabelButton({
|
|
|
96
165
|
labelClassName?: string;
|
|
97
166
|
tab: CompactTabStripTab;
|
|
98
167
|
}) {
|
|
99
|
-
const
|
|
100
|
-
|
|
101
|
-
|
|
168
|
+
const hasLeadingClose = Boolean(
|
|
169
|
+
tab.onClose && tab.closePlacement === "leading-hover",
|
|
170
|
+
);
|
|
102
171
|
const button = (
|
|
103
172
|
<button
|
|
104
173
|
type="button"
|
|
@@ -106,9 +175,15 @@ function CompactTabLabelButton({
|
|
|
106
175
|
aria-label={tab.label}
|
|
107
176
|
className="flex min-w-0 flex-1 items-center gap-1.5 text-left"
|
|
108
177
|
>
|
|
109
|
-
{leadingIcon ? (
|
|
110
|
-
<span
|
|
111
|
-
|
|
178
|
+
{tab.leadingIcon || hasLeadingClose ? (
|
|
179
|
+
<span
|
|
180
|
+
data-compact-tab-leading-slot=""
|
|
181
|
+
className={cn(
|
|
182
|
+
"inline-flex h-3.5 w-3.5 shrink-0 items-center justify-center",
|
|
183
|
+
hasLeadingClose && "group-hover:opacity-0 group-focus-within:opacity-0",
|
|
184
|
+
)}
|
|
185
|
+
>
|
|
186
|
+
{tab.leadingIcon}
|
|
112
187
|
</span>
|
|
113
188
|
) : null}
|
|
114
189
|
<span className={cn("min-w-0 truncate text-[12px] font-medium", labelClassName, tab.labelClassName)}>
|
|
@@ -150,7 +225,6 @@ function CompactTabItem({
|
|
|
150
225
|
| "labelClassName"
|
|
151
226
|
| "tabBaseClassName"
|
|
152
227
|
> & { itemRef?: React.Ref<HTMLDivElement>; tab: CompactTabStripTab }) {
|
|
153
|
-
const leadingClose = tab.onClose && tab.closePlacement === "leading-hover";
|
|
154
228
|
const item = (
|
|
155
229
|
<div
|
|
156
230
|
ref={itemRef}
|
|
@@ -158,38 +232,17 @@ function CompactTabItem({
|
|
|
158
232
|
onClick={(event) => event.target === event.currentTarget && tab.onSelect()}
|
|
159
233
|
className={cn(
|
|
160
234
|
tabBaseClassName ??
|
|
161
|
-
"
|
|
235
|
+
"flex max-w-[180px] cursor-pointer items-center gap-1.5 border-r border-gray-200/70 border-b-2 px-2.5 py-2 transition-colors",
|
|
236
|
+
"group relative",
|
|
162
237
|
tab.active
|
|
163
238
|
? (activeTabClassName ?? "border-b-primary bg-white text-gray-900")
|
|
164
239
|
: (inactiveTabClassName ??
|
|
165
240
|
"border-b-transparent bg-gray-50/85 text-gray-500 hover:bg-gray-100"),
|
|
166
241
|
)}
|
|
167
242
|
>
|
|
168
|
-
{leadingClose ? (
|
|
169
|
-
<button
|
|
170
|
-
type="button"
|
|
171
|
-
onClick={(event) => closeCompactTab(event, tab.onClose!)}
|
|
172
|
-
className="relative 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"
|
|
173
|
-
aria-label={tab.closeLabel}
|
|
174
|
-
>
|
|
175
|
-
<span className="flex items-center justify-center group-hover:hidden">
|
|
176
|
-
{tab.leadingIcon}
|
|
177
|
-
</span>
|
|
178
|
-
<X className="hidden h-3.5 w-3.5 group-hover:block" />
|
|
179
|
-
</button>
|
|
180
|
-
) : null}
|
|
181
243
|
<CompactTabLabelButton tab={tab} labelClassName={labelClassName} />
|
|
182
|
-
<
|
|
183
|
-
{tab
|
|
184
|
-
<IconActionButton
|
|
185
|
-
size="sm"
|
|
186
|
-
tone="strong"
|
|
187
|
-
icon={<X className="h-3 w-3" />}
|
|
188
|
-
label={tab.closeLabel ?? ""}
|
|
189
|
-
tooltip={tab.closeLabel ?? null}
|
|
190
|
-
onClick={(event) => closeCompactTab(event, tab.onClose!)}
|
|
191
|
-
/>
|
|
192
|
-
) : null}
|
|
244
|
+
<CompactTabLeadingCloseOverlay tab={tab} />
|
|
245
|
+
<CompactTabTrailingActions tab={tab} />
|
|
193
246
|
</div>
|
|
194
247
|
);
|
|
195
248
|
|
|
@@ -183,6 +183,7 @@ describe('ncp-session-query-cache', () => {
|
|
|
183
183
|
it('applies realtime upsert/delete events to every ncp-sessions query cache entry', () => {
|
|
184
184
|
const queryClient = new QueryClient();
|
|
185
185
|
queryClient.setQueryData(['ncp-sessions', 200], createSessionsList());
|
|
186
|
+
queryClient.setQueryData(['ncp-session-token-usage', 'session-3'], { runCount: 1 });
|
|
186
187
|
|
|
187
188
|
applyNcpSessionRealtimeEvent(queryClient, {
|
|
188
189
|
type: 'session.run-status',
|
|
@@ -212,6 +213,7 @@ describe('ncp-session-query-cache', () => {
|
|
|
212
213
|
expect(
|
|
213
214
|
queryClient.getQueryData<NcpSessionsListView>(['ncp-sessions', 200])?.sessions.map((session) => session.sessionId)
|
|
214
215
|
).toEqual(['session-3', 'session-1', 'session-2']);
|
|
216
|
+
expect(queryClient.getQueryState(['ncp-session-token-usage', 'session-3'])?.isInvalidated).toBe(true);
|
|
215
217
|
|
|
216
218
|
applyNcpSessionRealtimeEvent(queryClient, {
|
|
217
219
|
type: 'session.summary.delete',
|
|
@@ -155,6 +155,10 @@ export function applyNcpSessionRealtimeEvent(
|
|
|
155
155
|
}
|
|
156
156
|
if (event.type === 'session.summary.upsert') {
|
|
157
157
|
upsertNcpSessionSummaryInQueryClient(queryClient, event.payload.summary);
|
|
158
|
+
void queryClient?.invalidateQueries({
|
|
159
|
+
queryKey: ['ncp-session-token-usage', event.payload.summary.sessionId],
|
|
160
|
+
exact: true,
|
|
161
|
+
});
|
|
158
162
|
return;
|
|
159
163
|
}
|
|
160
164
|
|
|
@@ -4,6 +4,7 @@ import type {
|
|
|
4
4
|
NcpSessionStatus,
|
|
5
5
|
NcpSessionSummary,
|
|
6
6
|
} from "@nextclaw/ncp";
|
|
7
|
+
import type { UiNcpSessionTokenUsageView } from "@nextclaw/client-sdk";
|
|
7
8
|
import type { ThinkingLevel } from "./types";
|
|
8
9
|
|
|
9
10
|
export type SessionTypeIconView = {
|
|
@@ -114,3 +115,5 @@ export type NcpSessionMessagesView = {
|
|
|
114
115
|
total: number;
|
|
115
116
|
pageInfo: NcpSessionMessagePageInfo;
|
|
116
117
|
};
|
|
118
|
+
|
|
119
|
+
export type NcpSessionTokenUsageView = UiNcpSessionTokenUsageView;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { nextclawClient } from "@/shared/lib/api/managers/client.manager";
|
|
2
2
|
import type {
|
|
3
3
|
NcpSessionMessagesView,
|
|
4
|
+
NcpSessionTokenUsageView,
|
|
4
5
|
NcpSessionSkillsView,
|
|
5
6
|
NcpSessionsListView,
|
|
6
7
|
NcpSessionSummaryView,
|
|
@@ -26,6 +27,13 @@ export async function fetchNcpSessionMessages(
|
|
|
26
27
|
)) as NcpSessionMessagesView;
|
|
27
28
|
}
|
|
28
29
|
|
|
30
|
+
// GET /api/ncp/sessions/:sessionId/usage
|
|
31
|
+
export async function fetchNcpSessionTokenUsage(
|
|
32
|
+
sessionId: string,
|
|
33
|
+
): Promise<NcpSessionTokenUsageView> {
|
|
34
|
+
return (await nextclawClient.sessions.getUsage(sessionId)) as NcpSessionTokenUsageView;
|
|
35
|
+
}
|
|
36
|
+
|
|
29
37
|
// GET /api/ncp/sessions/:sessionId/skills
|
|
30
38
|
export async function fetchNcpSessionSkills(
|
|
31
39
|
sessionId: string,
|
|
@@ -49,8 +49,27 @@
|
|
|
49
49
|
"chatWorkspaceClosePanel": "Close workspace panel",
|
|
50
50
|
"chatWorkspaceOverview": "Overview",
|
|
51
51
|
"chatWorkspaceOverviewDescription": "Open this session's related conversations, scheduled work, and project files.",
|
|
52
|
+
"chatWorkspaceTokenUsage": "Token usage",
|
|
53
|
+
"chatWorkspaceTokenUsageDescription": "Counts this session's own AI runs. Cached input is included in input tokens; the hit rate is cached reads divided by all input.",
|
|
54
|
+
"chatWorkspaceTokenUsageLoading": "Calculating token usage…",
|
|
55
|
+
"chatWorkspaceTokenUsageLoadFailed": "Couldn’t load token usage.",
|
|
56
|
+
"chatWorkspaceTokenUsageRetry": "Retry",
|
|
57
|
+
"chatWorkspaceTokenUsageEmpty": "This session has no token usage to show yet. Some models and older runs may not report usage.",
|
|
58
|
+
"chatWorkspaceTokenUsageTotal": "Total tokens",
|
|
59
|
+
"chatWorkspaceTokenUsageInput": "Input",
|
|
60
|
+
"chatWorkspaceTokenUsageOutput": "Output",
|
|
61
|
+
"chatWorkspaceTokenUsageCachedInput": "Cached input",
|
|
62
|
+
"chatWorkspaceTokenUsageCacheHitRate": "Cache hit rate",
|
|
63
|
+
"chatWorkspaceTokenUsageRuns": "AI runs",
|
|
64
|
+
"chatWorkspaceTokenUsageByModel": "By model",
|
|
65
|
+
"chatWorkspaceTokenUsageModelRunCount": "Runs: {count}",
|
|
66
|
+
"chatWorkspaceTokenUsageModelCacheHitRate": "Cache hit rate: {rate}",
|
|
67
|
+
"chatWorkspaceTokenUsageReported": "Usage reported",
|
|
68
|
+
"chatWorkspaceTokenUsagePartial": "Partial usage",
|
|
69
|
+
"chatWorkspaceTokenUsageUnavailable": "Usage unavailable",
|
|
52
70
|
"chatWorkspaceChildSessionsDescription": "Review the child sessions created from this conversation.",
|
|
53
71
|
"chatWorkspaceChildSessionsEmpty": "No child sessions yet.",
|
|
72
|
+
"chatWorkspaceCreateChildSession": "New child session",
|
|
54
73
|
"chatWorkspaceSessionCronJobsDescription": "Review scheduled tasks associated with this session.",
|
|
55
74
|
"chatWorkspaceProjectFiles": "Project files",
|
|
56
75
|
"chatWorkspaceShowProjectFiles": "Show project files",
|
|
@@ -277,6 +296,10 @@
|
|
|
277
296
|
"chatSlashCommandCompactContextDetail": "Keeps the latest turn and the active task available for continuation.",
|
|
278
297
|
"chatSlashCommandCompactContextSuccess": "Context compacted",
|
|
279
298
|
"chatSlashCommandCompactContextFailed": "Couldn't compact context",
|
|
299
|
+
"chatSlashCommandUpdateSessionTitleTitle": "Update session title",
|
|
300
|
+
"chatSlashCommandUpdateSessionTitleDescription": "Ask AI to create a concise title from this conversation and update the session.",
|
|
301
|
+
"chatSlashCommandUpdateSessionTitleDetail": "Sends a message automatically without replacing your current draft.",
|
|
302
|
+
"chatSlashCommandUpdateSessionTitlePrompt": "Create a concise, accurate title based on this conversation, then use the sessions_update tool to update the current session title now. Do not only suggest a title.",
|
|
280
303
|
"chatSlashPanelAppHint": "Press Enter to open this panel app on the right.",
|
|
281
304
|
"chatSlashSkillHint": "Press Enter to add this skill for the next turn.",
|
|
282
305
|
"chatPanelAppReferenceLoading": "Loading panel apps...",
|
|
@@ -49,8 +49,27 @@
|
|
|
49
49
|
"chatWorkspaceClosePanel": "关闭工作区侧栏",
|
|
50
50
|
"chatWorkspaceOverview": "概览",
|
|
51
51
|
"chatWorkspaceOverviewDescription": "查看与当前会话相关的子会话、定时任务和项目文件。",
|
|
52
|
+
"chatWorkspaceTokenUsage": "Token 用量",
|
|
53
|
+
"chatWorkspaceTokenUsageDescription": "统计当前会话自身的 AI 运行。缓存输入已包含在输入 Token 中;命中率为缓存读取占全部输入的比例。",
|
|
54
|
+
"chatWorkspaceTokenUsageLoading": "正在统计 Token 用量…",
|
|
55
|
+
"chatWorkspaceTokenUsageLoadFailed": "Token 用量加载失败。",
|
|
56
|
+
"chatWorkspaceTokenUsageRetry": "重试",
|
|
57
|
+
"chatWorkspaceTokenUsageEmpty": "当前会话还没有可统计的 Token 用量。部分模型或旧运行可能不会报告用量。",
|
|
58
|
+
"chatWorkspaceTokenUsageTotal": "总 Token",
|
|
59
|
+
"chatWorkspaceTokenUsageInput": "输入",
|
|
60
|
+
"chatWorkspaceTokenUsageOutput": "输出",
|
|
61
|
+
"chatWorkspaceTokenUsageCachedInput": "缓存输入",
|
|
62
|
+
"chatWorkspaceTokenUsageCacheHitRate": "缓存命中率",
|
|
63
|
+
"chatWorkspaceTokenUsageRuns": "AI 运行",
|
|
64
|
+
"chatWorkspaceTokenUsageByModel": "按模型",
|
|
65
|
+
"chatWorkspaceTokenUsageModelRunCount": "{count} 次运行",
|
|
66
|
+
"chatWorkspaceTokenUsageModelCacheHitRate": "缓存命中率 {rate}",
|
|
67
|
+
"chatWorkspaceTokenUsageReported": "用量已报告",
|
|
68
|
+
"chatWorkspaceTokenUsagePartial": "部分用量",
|
|
69
|
+
"chatWorkspaceTokenUsageUnavailable": "用量不可用",
|
|
52
70
|
"chatWorkspaceChildSessionsDescription": "查看从当前会话创建的子会话。",
|
|
53
71
|
"chatWorkspaceChildSessionsEmpty": "当前还没有子会话。",
|
|
72
|
+
"chatWorkspaceCreateChildSession": "新建子会话",
|
|
54
73
|
"chatWorkspaceSessionCronJobsDescription": "查看与当前会话关联的定时任务。",
|
|
55
74
|
"chatWorkspaceProjectFiles": "项目文件",
|
|
56
75
|
"chatWorkspaceShowProjectFiles": "展开项目文件",
|
|
@@ -59,7 +78,7 @@
|
|
|
59
78
|
"chatWorkspaceProjectFilesDescription": "浏览已选项目目录中的文件。",
|
|
60
79
|
"chatWorkspaceProjectFilesUnavailable": "请先选择项目目录,再浏览其中的文件。",
|
|
61
80
|
"chatWorkspaceSideChatDraftTitle": "侧边对话",
|
|
62
|
-
"chatWorkspaceSideChatDraftSubtitle": "
|
|
81
|
+
"chatWorkspaceSideChatDraftSubtitle": "发送第一条消息后,会继承父会话上下文并创建真实子会话。",
|
|
63
82
|
"chatWorkspaceChildSessions": "子会话",
|
|
64
83
|
"chatWorkspaceOpen": "打开",
|
|
65
84
|
"chatWorkspaceOpenFiles": "打开的文件",
|
|
@@ -277,6 +296,10 @@
|
|
|
277
296
|
"chatSlashCommandCompactContextDetail": "保留最近一轮和当前任务,供后续继续处理。",
|
|
278
297
|
"chatSlashCommandCompactContextSuccess": "上下文已压缩",
|
|
279
298
|
"chatSlashCommandCompactContextFailed": "无法压缩上下文",
|
|
299
|
+
"chatSlashCommandUpdateSessionTitleTitle": "更新会话标题",
|
|
300
|
+
"chatSlashCommandUpdateSessionTitleDescription": "让 AI 根据当前会话内容生成简洁标题并完成更新。",
|
|
301
|
+
"chatSlashCommandUpdateSessionTitleDetail": "命令会自动发送一条消息,不会覆盖输入框中的草稿。",
|
|
302
|
+
"chatSlashCommandUpdateSessionTitlePrompt": "请根据当前会话内容生成一个简洁、准确的标题,然后立即使用 sessions_update 工具更新当前会话标题。不要只给出标题建议。",
|
|
280
303
|
"chatSlashPanelAppHint": "回车在右侧打开这个面板应用。",
|
|
281
304
|
"chatSlashSkillHint": "回车把该技能加入本轮请求。",
|
|
282
305
|
"chatPanelAppReferenceLoading": "加载面板应用中…",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import"./chunk-KEIR6QF5-f9psyCXK.js";import{n as e}from"./chunk-MOZMSUNE-PfyK9w1-.js";export{e as createArchitectureServices};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{at as e,ot as t}from"./chunk-WYO6CB5R-Dn9To_OI.js";var n=(n,r)=>t.lang.round(e.parse(n)[r]);export{n as t};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{n as e}from"./chunk-Y2CYZVJY-D1mAU_Po.js";var t=class{constructor(e){this.init=e,this.records=this.init()}static{e(this,`ImperativeState`)}reset(){this.records=this.init()}};export{t};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{n as e}from"./chunk-Y2CYZVJY-D1mAU_Po.js";import{p as t}from"./src-Bw-mzbQb.js";import{x as n}from"./chunk-WYO6CB5R-Dn9To_OI.js";var r=e(e=>{let{securityLevel:r}=n(),i=t(`body`);return r===`sandbox`&&(i=t((t(`#i${e}`).node()?.contentDocument??document).body)),i.select(`#${e}`)},`selectSvgElement`);export{r as t};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{n as e}from"./chunk-Y2CYZVJY-D1mAU_Po.js";import{p as t}from"./src-Bw-mzbQb.js";var n=e((e,n)=>{let r;return n===`sandbox`&&(r=t(`#i`+e)),t(n===`sandbox`?r.nodes()[0].contentDocument.body:`body`).select(`[id="${e}"]`)},`getDiagramElement`);export{n as t};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{n as e}from"./chunk-Y2CYZVJY-D1mAU_Po.js";import"./src-Bw-mzbQb.js";import"./chunk-WYO6CB5R-Dn9To_OI.js";import"./chunk-ICXQ74PX-FAatv5fC.js";import"./chunk-HOUHSVGY-DPkq8FCm.js";import"./chunk-Q4XR5HBZ-DQFeUPxZ.js";import"./chunk-7BUUIJ7U-BvydOcm3.js";import"./chunk-OGEWGWER-C3jdH3Ty.js";import"./chunk-32BRIVSS-7NrjEITq.js";import"./chunk-XXDRQBXY-DaBxG5gs.js";import"./chunk-VR4S4FIN-B7AHEYYk.js";import"./chunk-C7G6YPKG-DAizzYwr.js";import"./chunk-ZGVPDNZ5-C6YtZDU0.js";import"./chunk-52WLFC77-viIcqj9q.js";import"./chunk-FWX5IMBZ-D0ksHZZ9.js";import{i as t,n,r,t as i}from"./chunk-V7JOEXUC-CZ70oOtp.js";var a={parser:n,get db(){return new i},renderer:r,styles:t,init:e(e=>{e.class||={},e.class.arrowMarkerAbsolute=e.arrowMarkerAbsolute},`init`)};export{a as diagram};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{n as e}from"./chunk-Y2CYZVJY-D1mAU_Po.js";import"./src-Bw-mzbQb.js";import"./chunk-WYO6CB5R-Dn9To_OI.js";import"./chunk-ICXQ74PX-FAatv5fC.js";import"./chunk-HOUHSVGY-DPkq8FCm.js";import"./chunk-Q4XR5HBZ-DQFeUPxZ.js";import"./chunk-7BUUIJ7U-BvydOcm3.js";import"./chunk-OGEWGWER-C3jdH3Ty.js";import"./chunk-32BRIVSS-7NrjEITq.js";import"./chunk-XXDRQBXY-DaBxG5gs.js";import"./chunk-VR4S4FIN-B7AHEYYk.js";import"./chunk-C7G6YPKG-DAizzYwr.js";import"./chunk-ZGVPDNZ5-C6YtZDU0.js";import"./chunk-52WLFC77-viIcqj9q.js";import"./chunk-FWX5IMBZ-D0ksHZZ9.js";import{i as t,n,r,t as i}from"./chunk-V7JOEXUC-CZ70oOtp.js";var a={parser:n,get db(){return new i},renderer:r,styles:t,init:e(e=>{e.class||={},e.class.arrowMarkerAbsolute=e.arrowMarkerAbsolute},`init`)};export{a as diagram};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import"./chunk-KEIR6QF5-f9psyCXK.js";import{n as e}from"./chunk-OSBZ3O6U-CecHo-f0.js";export{e as createCynefinServices};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{t as e}from"./doc-browser-Crqog5cn.js";export{e as DocBrowser};
|