@nextclaw/ui 0.19.5 → 0.20.0-beta.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 +23 -0
- package/dist/assets/{abnfDiagram-VRR7QNED-DrbfiNNF.js → abnfDiagram-VRR7QNED-BcFJp_1X.js} +1 -1
- package/dist/assets/{aiden0z-pptx-renderer.es-DdLb2IVc.js → aiden0z-pptx-renderer.es-Dp2ezlQn.js} +1 -1
- package/dist/assets/api-C2iYhdTe.js +13 -0
- package/dist/assets/{appearance-settings-page-cTuZdROP.js → appearance-settings-page-BwQDQr0n.js} +1 -1
- package/dist/assets/{arc-BXlMc9B0.js → arc-CkgyPMyW.js} +1 -1
- package/dist/assets/architecture-TIHT7OUA-DO2x53FK.js +1 -0
- package/dist/assets/{architectureDiagram-ZJ3FMSHR-DXAJxxO0.js → architectureDiagram-ZJ3FMSHR-CMd4cIjI.js} +1 -1
- package/dist/assets/{blockDiagram-677ZJIJ3-i4Kz7zU0.js → blockDiagram-677ZJIJ3-Bz3tbhet.js} +1 -1
- package/dist/assets/book-open-C0IlT9zs.js +1 -0
- package/dist/assets/{c4Diagram-LMCZKHZV-BDc0TkPd.js → c4Diagram-LMCZKHZV-D9hFNAGv.js} +1 -1
- package/dist/assets/channel-nBvMaVyP.js +1 -0
- package/dist/assets/channels-list-page-B0z4bh8e.js +8 -0
- package/dist/assets/chunk-2Q5K7J3B-CJgqFDS4.js +1 -0
- package/dist/assets/{chunk-32BRIVSS-DuReei0Z.js → chunk-32BRIVSS-7NrjEITq.js} +1 -1
- package/dist/assets/{chunk-52WLFC77-D8APq0tm.js → chunk-52WLFC77-viIcqj9q.js} +1 -1
- package/dist/assets/{chunk-5FCAYU7R-BsPrNXNS.js → chunk-5FCAYU7R-Vsu4J-VM.js} +1 -1
- package/dist/assets/{chunk-5HE753X5-BRtkOPoJ.js → chunk-5HE753X5-C-w6CQZK.js} +1 -1
- package/dist/assets/{chunk-5JV3BV7I-ChPc8e8U.js → chunk-5JV3BV7I-CuKgJQ4W.js} +1 -1
- package/dist/assets/{chunk-5TONJI2A-CzTjlJGb.js → chunk-5TONJI2A-CYeiWZKb.js} +1 -1
- package/dist/assets/{chunk-5VM5RSS4-xsv_22jR.js → chunk-5VM5RSS4-DRCbfwIn.js} +1 -1
- package/dist/assets/{chunk-7BUUIJ7U-CwECujme.js → chunk-7BUUIJ7U-BvydOcm3.js} +1 -1
- package/dist/assets/{chunk-BIQX33UG-DQAm173p.js → chunk-BIQX33UG-RlppOXKo.js} +1 -1
- package/dist/assets/{chunk-C7G6YPKG-BkpajeQb.js → chunk-C7G6YPKG-DAizzYwr.js} +1 -1
- package/dist/assets/{chunk-CQNSW5MT-ND65pWRA.js → chunk-CQNSW5MT-5eChJHca.js} +1 -1
- package/dist/assets/{chunk-CYSBUYHQ-vMu6ijxG.js → chunk-CYSBUYHQ-YHPr53fv.js} +1 -1
- package/dist/assets/{chunk-EMLP6XTP-CEaeW3gH.js → chunk-EMLP6XTP-CK4D7Hz5.js} +1 -1
- package/dist/assets/{chunk-EX3LRPZG-a4ER-HDr.js → chunk-EX3LRPZG-BmlDFIRW.js} +1 -1
- package/dist/assets/{chunk-FWX5IMBZ-C_8fQssn.js → chunk-FWX5IMBZ-D0ksHZZ9.js} +2 -2
- package/dist/assets/{chunk-HOUHSVGY-CEvw-PEd.js → chunk-HOUHSVGY-DPkq8FCm.js} +1 -1
- package/dist/assets/{chunk-ICXQ74PX-BEtF0fGY.js → chunk-ICXQ74PX-FAatv5fC.js} +1 -1
- package/dist/assets/{chunk-JG7HCLWE-DGRrVp8-.js → chunk-JG7HCLWE-DLkIi4F7.js} +1 -1
- package/dist/assets/{chunk-JWPE2WC7-DRqpp_nM.js → chunk-JWPE2WC7-DawOjNE3.js} +1 -1
- package/dist/assets/{chunk-MOJQB5TN-BDEriOXs.js → chunk-MOJQB5TN-Di52TorW.js} +1 -1
- package/dist/assets/{chunk-MOZMSUNE-JWRNzdnw.js → chunk-MOZMSUNE-PfyK9w1-.js} +1 -1
- package/dist/assets/{chunk-OGEWGWER-DS2VTgCx.js → chunk-OGEWGWER-C3jdH3Ty.js} +1 -1
- package/dist/assets/{chunk-OSBZ3O6U-3LiYTBUB.js → chunk-OSBZ3O6U-CecHo-f0.js} +1 -1
- package/dist/assets/{chunk-PUDLZKDR-o9M2s_SO.js → chunk-PUDLZKDR-f3IJh3sN.js} +1 -1
- package/dist/assets/{chunk-Q4XR5HBZ-DTB7Ma2N.js → chunk-Q4XR5HBZ-DQFeUPxZ.js} +1 -1
- package/dist/assets/{chunk-QBLGF6JB-DpkxZJL5.js → chunk-QBLGF6JB-BhUeG0y2.js} +1 -1
- package/dist/assets/{chunk-R7FJI6CG-CRejkHJU.js → chunk-R7FJI6CG-C3XpZ-2u.js} +1 -1
- package/dist/assets/{chunk-RYQCIY6F-B1boBjLt.js → chunk-RYQCIY6F-CAqa5klQ.js} +1 -1
- package/dist/assets/{chunk-U6XO7XAA-DgKa97bj.js → chunk-U6XO7XAA-D_WXezeD.js} +1 -1
- package/dist/assets/{chunk-V7JOEXUC-DE56eh0N.js → chunk-V7JOEXUC-CZ70oOtp.js} +1 -1
- package/dist/assets/chunk-VAUOI2AC-BGvh3yIx.js +1 -0
- package/dist/assets/{chunk-VR4S4FIN-BzomPZq2.js → chunk-VR4S4FIN-B7AHEYYk.js} +1 -1
- package/dist/assets/{chunk-WYO6CB5R-C6gy8rSd.js → chunk-WYO6CB5R-Dn9To_OI.js} +2 -2
- package/dist/assets/chunk-XXDRQBXY-DaBxG5gs.js +1 -0
- package/dist/assets/{chunk-YOTPTUD7-BK98yfl9.js → chunk-YOTPTUD7-BYEgRBk3.js} +1 -1
- package/dist/assets/{chunk-ZGVPDNZ5-DFXAhwUT.js → chunk-ZGVPDNZ5-C6YtZDU0.js} +1 -1
- package/dist/assets/{chunk-ZIRB5QZD-Bbu6BiNC.js → chunk-ZIRB5QZD-DMuYtnHF.js} +1 -1
- package/dist/assets/classDiagram-OUVF2IWQ-P6N03G2R.js +1 -0
- package/dist/assets/classDiagram-v2-EOCWNBFH-B1_uLvMv.js +1 -0
- package/dist/assets/{config-split-page-DO1Oyb-r.js → config-split-page-VDTf3zZb.js} +1 -1
- package/dist/assets/confirm-dialog-BI_Vt2s_.js +5 -0
- package/dist/assets/{cose-bilkent-JH36ORCC-BV8KR4uF.js → cose-bilkent-JH36ORCC-Bc2Ex5Y3.js} +1 -1
- package/dist/assets/createLucideIcon-Bydi9Gc5.js +1 -0
- package/dist/assets/cynefin-VYW2F7L2-B-H8Qp-n.js +1 -0
- package/dist/assets/{cynefinDiagram-TSTJHNR4-Ckd6nU9t.js → cynefinDiagram-TSTJHNR4-DVysQoGz.js} +1 -1
- package/dist/assets/{dagre-D_T-FW5i.js → dagre-CMhQ1cAG.js} +1 -1
- package/dist/assets/{dagre-VKFMJZFB-CyDaQpD4.js → dagre-VKFMJZFB-RYyWpPJZ.js} +1 -1
- package/dist/assets/{desktop-update-config-XSV-DjJW.js → desktop-update-config-DVoD6NxG.js} +1 -1
- package/dist/assets/{diagram-FQU43EPY-CghnwS0H.js → diagram-FQU43EPY-BD6KONdF.js} +1 -1
- package/dist/assets/{diagram-G47NLZAW-DK4DJ3Kx.js → diagram-G47NLZAW-CGB2ptRR.js} +1 -1
- package/dist/assets/{diagram-NH7WQ7WH-CUgDkZCJ.js → diagram-NH7WQ7WH-DnkOI6cU.js} +1 -1
- package/dist/assets/{diagram-OA4YK3LP-vO2gyH6n.js → diagram-OA4YK3LP-DF82RZ7P.js} +1 -1
- package/dist/assets/{diagram-WEI45ONY-DbSBRDSr.js → diagram-WEI45ONY-Be2v7Ck9.js} +1 -1
- package/dist/assets/{dist-C-2H76Cv.js → dist-A5btQciA.js} +1 -1
- package/dist/assets/dist-CmHtkFbs.js +1 -0
- package/dist/assets/doc-browser-Cm_tMZ_C.js +1 -0
- package/dist/assets/doc-browser-Dto54tCf.js +1 -0
- package/dist/assets/{doc-browser-context-C0Bns1J6.js → doc-browser-context-Bxw0ora-.js} +1 -1
- package/dist/assets/{docx-preview-DfxIm9IB.js → docx-preview-BqwAjrj3.js} +1 -1
- package/dist/assets/{ebnfDiagram-CCIWWBDH-W7CAcK7r.js → ebnfDiagram-CCIWWBDH-CP98OYk8.js} +1 -1
- package/dist/assets/{erDiagram-Q63AITRT-LA0JWL8-.js → erDiagram-Q63AITRT-ZLlx8xfs.js} +1 -1
- package/dist/assets/eventmodeling-45OFAUF4-YVtShyFA.js +1 -0
- package/dist/assets/extensions-CG4voDCh.js +1 -0
- package/dist/assets/flowDiagram-23GEKE2U-BeKXabVO.js +1 -0
- package/dist/assets/{form-actions-CMxhPact.js → form-actions-lv47uGIB.js} +1 -1
- package/dist/assets/{ganttDiagram-NO4QXBWP-_PiTPavJ.js → ganttDiagram-NO4QXBWP-DXCDjHR2.js} +1 -1
- package/dist/assets/gitGraph-TEB2WS4Q-jTSiBj-p.js +1 -0
- package/dist/assets/{gitGraphDiagram-IHSO6WYX-DsRB1ZMU.js → gitGraphDiagram-IHSO6WYX-l2HWrTJp.js} +1 -1
- package/dist/assets/index-BTSwNDVi.js +109 -0
- package/dist/assets/index-QrdUWHfm.css +1 -0
- package/dist/assets/info-DKCQHKI2-BIporNWb.js +1 -0
- package/dist/assets/{infoDiagram-FWYZ7A6U-wIRraYx5.js → infoDiagram-FWYZ7A6U-D-DjX-bn.js} +1 -1
- package/dist/assets/{ishikawaDiagram-FXEZZL3T-CNzsrcrh.js → ishikawaDiagram-FXEZZL3T-y_Xy128F.js} +1 -1
- package/dist/assets/{journeyDiagram-5HDEW3XC-Dy9huHxy.js → journeyDiagram-5HDEW3XC-DJn5xYcQ.js} +1 -1
- package/dist/assets/{kanban-definition-HUTT4EX6-BOCIN365.js → kanban-definition-HUTT4EX6-DJVIOR21.js} +1 -1
- package/dist/assets/{line-BxsizOTs.js → line-Cos7PIOj.js} +1 -1
- package/dist/assets/{linear-C_YHf92I.js → linear-BtDLqtzF.js} +1 -1
- package/dist/assets/loader-circle-CkaqeEne.js +1 -0
- package/dist/assets/{map-CobcjgZ8.js → map-BKnQyvd0.js} +1 -1
- package/dist/assets/mcp-marketplace-page-BSk0qUOX.js +9 -0
- package/dist/assets/mcp-marketplace-page-BgZGc-S_.js +1 -0
- package/dist/assets/{mermaid-parser.core-D7lu2RbA.js → mermaid-parser.core-XUNZhr2W.js} +2 -2
- package/dist/assets/{mermaid.core-CbfW2Rk8.js → mermaid.core-ySrvolIe.js} +3 -3
- package/dist/assets/{mindmap-definition-LN4V7U3C-DUjGXlIC.js → mindmap-definition-LN4V7U3C-BypL9tei.js} +1 -1
- package/dist/assets/model-config-page-c8RnUGoH.js +1 -0
- package/dist/assets/{navigation-link-v3FaWcIr.js → navigation-link-D0agTj5t.js} +1 -1
- package/dist/assets/{ordinal-CjoUCHto.js → ordinal-CxxVWxYU.js} +1 -1
- package/dist/assets/packet-7NZHBO7P-CuFMADV0.js +1 -0
- package/dist/assets/{pegDiagram-2B236MQR-BQY2DgiP.js → pegDiagram-2B236MQR-D-U2KBGv.js} +1 -1
- package/dist/assets/pie-RZYD4A2V-XUeIXhM9.js +1 -0
- package/dist/assets/{pieDiagram-ENE6RG2P-D18owe4D.js → pieDiagram-ENE6RG2P-CBi3GusJ.js} +1 -1
- package/dist/assets/plus-BiMjkv3R.js +1 -0
- package/dist/assets/{privacy-settings-page-CYM1Dxwo.js → privacy-settings-page-CPkyTvEE.js} +1 -1
- package/dist/assets/providers-config-page-CGUEb5Dx.js +1 -0
- package/dist/assets/{quadrantDiagram-ABIIQ3AL-B8F7YoTA.js → quadrantDiagram-ABIIQ3AL-H0ZuvnZL.js} +1 -1
- package/dist/assets/radar-I7S5WNFK-D-NNGh1k.js +1 -0
- package/dist/assets/railroad-3IZDKUUU-C67_uDaM.js +1 -0
- package/dist/assets/railroad-abnf-AHOZXSZD-BZ8Yflnd.js +1 -0
- package/dist/assets/railroad-ebnf-EBAXGLYW-B7zO7RoK.js +1 -0
- package/dist/assets/railroad-peg-LSFZ7HO6-R63PTgLz.js +1 -0
- package/dist/assets/{railroadDiagram-RFXS5EU6-RU8GpxN5.js → railroadDiagram-RFXS5EU6-D7Y2EqSd.js} +1 -1
- package/dist/assets/react-BMYFkaGi.js +8 -0
- package/dist/assets/refresh-cw-DjgY2Eju.js +1 -0
- package/dist/assets/remote-1LxkpRED.js +1 -0
- package/dist/assets/{requirementDiagram-TGXJPOKE-ubPOmmNi.js → requirementDiagram-TGXJPOKE-BiXNX1NN.js} +1 -1
- package/dist/assets/rotate-cw-Dot4PVh0.js +1 -0
- package/dist/assets/{runtime-config-page-C7vksFVD.js → runtime-config-page-C6nzqTHg.js} +1 -1
- package/dist/assets/{sankeyDiagram-HTMAVEWB-8L_hXJWW.js → sankeyDiagram-HTMAVEWB-qzDeLztW.js} +1 -1
- package/dist/assets/save-B-jdTe_c.js +1 -0
- package/dist/assets/search-CEp2AIiV.js +1 -0
- package/dist/assets/{search-config-page-DKdEf7m9.js → search-config-page-Dp5guS5O.js} +1 -1
- package/dist/assets/{secrets-config-page-COlMqSfL.js → secrets-config-page-C7nRMjiv.js} +2 -2
- package/dist/assets/security-config-DvHUDxSg.js +1 -0
- package/dist/assets/{select-BACzapV3.js → select-BNA3cma8.js} +2 -2
- package/dist/assets/{sequenceDiagram-DBY2YBRQ-Dom6Qor5.js → sequenceDiagram-DBY2YBRQ-BtRbPQtL.js} +1 -1
- package/dist/assets/{sizeCapture-X5ZJPWSS-cZcFSpLJ.js → sizeCapture-X5ZJPWSS-CMYvM3SL.js} +1 -1
- package/dist/assets/skeleton-CbroEO8Q.js +1 -0
- package/dist/assets/{src-BE9E1xcR.js → src-Bw-mzbQb.js} +1 -1
- package/dist/assets/{stateDiagram-2N3HPSRC-CHrpxmGO.js → stateDiagram-2N3HPSRC-BJ-mFeOz.js} +1 -1
- package/dist/assets/stateDiagram-v2-6OUMAXLB-BE-HqxOK.js +1 -0
- package/dist/assets/{swimlanes-5IMT3BWC-D6nJS2xQ.js → swimlanes-5IMT3BWC-BsucVOO2.js} +2 -2
- package/dist/assets/swimlanesDiagram-G3AALYLV-Dr1H9LJH.js +8 -0
- package/dist/assets/{tag-chip-BnamTQVX.js → tag-chip-DmCNi4-9.js} +1 -1
- package/dist/assets/{timeline-definition-FHXFAJF6-DJNn-HQO.js → timeline-definition-FHXFAJF6-Bicewlzo.js} +1 -1
- package/dist/assets/treeView-QDETBFTQ-npJ5dbqS.js +1 -0
- package/dist/assets/treemap-6X3UGDF4-pYrBx6oa.js +1 -0
- package/dist/assets/{vennDiagram-L72KCM5P-CCEzHoXt.js → vennDiagram-L72KCM5P-BxOOnO9x.js} +1 -1
- package/dist/assets/wardley-OPB4EBWU-CmSRKLR8.js +1 -0
- package/dist/assets/{wardleyDiagram-EHGQE667-BhyVxVXt.js → wardleyDiagram-EHGQE667-Cl7NltMv.js} +1 -1
- package/dist/assets/x-BTo5-A8h.js +1 -0
- package/dist/assets/{xychartDiagram-FW5EYKEG-CacW_246.js → xychartDiagram-FW5EYKEG-DiMIxQ7N.js} +1 -1
- package/dist/index.html +23 -22
- package/package.json +8 -8
- package/src/app/components/layout/__tests__/sidebar.layout.test.tsx +4 -0
- package/src/app/configs/app-navigation.config.ts +6 -0
- package/src/app/index.tsx +7 -0
- package/src/features/chat/features/conversation/components/__tests__/session-conversation-area.test.tsx +33 -1
- package/src/features/chat/features/conversation/components/__tests__/session-conversation-input.streaming.test.tsx +1 -0
- package/src/features/chat/features/conversation/hooks/__tests__/use-session-conversation-controller.test.tsx +18 -1
- package/src/features/chat/features/conversation/hooks/__tests__/use-session-run-queue.test.tsx +26 -0
- package/src/features/chat/features/conversation/hooks/use-session-conversation-controller.ts +4 -1
- package/src/features/chat/features/conversation/hooks/use-session-run-queue.ts +8 -2
- package/src/features/chat/features/message/components/__tests__/chat-message-observation-event.test.tsx +46 -0
- package/src/features/chat/features/message/components/chat-message-list.container.tsx +11 -0
- package/src/features/chat/features/message/components/chat-message-observation-event.tsx +92 -0
- package/src/features/chat/features/message/utils/__tests__/chat-message-timeline-compaction.utils.test.ts +38 -0
- package/src/features/chat/features/message/utils/__tests__/chat-message-timeline.utils.test.ts +52 -0
- package/src/features/chat/features/message/utils/__tests__/chat-message.utils.test.ts +34 -0
- package/src/features/chat/features/message/utils/chat-message-observation-event.utils.ts +81 -0
- package/src/features/chat/features/message/utils/chat-message-part.utils.ts +15 -1
- package/src/features/chat/features/message/utils/chat-message-timeline.utils.ts +62 -1
- package/src/features/chat/features/ncp/hooks/use-ncp-session-queries.ts +36 -2
- package/src/features/chat/features/session/components/__tests__/chat-sidebar-session-item.test.tsx +28 -0
- package/src/features/chat/features/session/components/chat-sidebar-session-item.tsx +10 -2
- package/src/features/chat/features/session/components/session-header/__tests__/chat-session-header-actions.test.tsx +35 -0
- package/src/features/chat/features/session/components/session-header/chat-session-header-actions.tsx +26 -47
- package/src/features/chat/features/session/components/session-header/chat-session-more-actions-menu.tsx +73 -0
- package/src/features/chat/features/session/utils/__tests__/ncp-session-adapter.utils.test.ts +28 -0
- package/src/features/chat/features/session/utils/ncp-session-adapter.utils.ts +3 -1
- package/src/features/chat/features/session/utils/ncp-session-context-metadata.utils.ts +3 -4
- package/src/features/chat/features/workspace/components/__tests__/chat-session-child-sessions.test.tsx +27 -1
- package/src/features/chat/features/workspace/components/__tests__/chat-session-workspace-panel-content.test.tsx +13 -0
- package/src/features/chat/features/workspace/components/__tests__/chat-session-workspace-panel.test.tsx +29 -0
- package/src/features/chat/features/workspace/components/chat-session-workspace-panel-content.tsx +19 -0
- package/src/features/chat/features/workspace/components/chat-session-workspace-panel-nav.tsx +36 -2
- package/src/features/chat/features/workspace/components/chat-session-workspace-panel.tsx +4 -0
- package/src/features/chat/features/workspace/components/child-sessions/chat-session-child-sessions.tsx +28 -17
- package/src/features/chat/features/workspace/components/overview/__tests__/chat-session-continuous-attention.test.tsx +67 -0
- package/src/features/chat/features/workspace/components/overview/chat-session-continuous-attention.tsx +234 -0
- package/src/features/chat/features/workspace/utils/__tests__/chat-workspace-panel-view-model.utils.test.ts +9 -7
- package/src/features/chat/features/workspace/utils/chat-thread-workspace-session.utils.ts +9 -4
- package/src/features/chat/features/workspace/utils/chat-workspace-panel-view-model.utils.ts +25 -0
- package/src/features/chat/managers/chat-thread.manager.ts +5 -7
- package/src/features/chat/stores/chat-thread.store.ts +7 -4
- package/src/features/extensions/hooks/use-extensions.ts +11 -0
- package/src/features/extensions/index.ts +1 -0
- package/src/features/extensions/pages/__tests__/extensions-config-page.test.tsx +34 -0
- package/src/features/extensions/pages/extensions-config-page.tsx +136 -0
- package/src/shared/lib/api/ncp-session.types.ts +38 -0
- package/src/shared/lib/api/runtime-control.types.ts +17 -0
- package/src/shared/lib/api/types.ts +6 -0
- package/src/shared/lib/api/utils/ncp-session.utils.ts +35 -1
- package/src/shared/lib/api/utils/runtime-control.utils.ts +8 -0
- package/src/shared/lib/i18n/locales/en-US/chat.json +40 -0
- package/src/shared/lib/i18n/locales/en-US/core.json +27 -0
- package/src/shared/lib/i18n/locales/zh-CN/chat.json +40 -0
- package/src/shared/lib/i18n/locales/zh-CN/core.json +27 -0
- package/dist/assets/api-CUSlBpt_.js +0 -13
- package/dist/assets/architecture-TIHT7OUA-Bq0i9WiE.js +0 -1
- package/dist/assets/book-open-BJ-xAIp9.js +0 -1
- package/dist/assets/channel-iCaZQ87u.js +0 -1
- package/dist/assets/channels-list-page-nRHOasWA.js +0 -8
- package/dist/assets/chunk-2Q5K7J3B-DFQtlnJS.js +0 -1
- package/dist/assets/chunk-VAUOI2AC-CF9A-TeE.js +0 -1
- package/dist/assets/chunk-XXDRQBXY-BRxdfVCU.js +0 -1
- package/dist/assets/classDiagram-OUVF2IWQ-Bo28fPi-.js +0 -1
- package/dist/assets/classDiagram-v2-EOCWNBFH-BOVN9wUz.js +0 -1
- package/dist/assets/confirm-dialog-CCae9Fr4.js +0 -5
- package/dist/assets/cynefin-VYW2F7L2-B7rF3JRp.js +0 -1
- package/dist/assets/dist-1N9UpL3c.js +0 -1
- package/dist/assets/doc-browser-BHFCZIoL.js +0 -1
- package/dist/assets/doc-browser-CRlpqMwH.js +0 -1
- package/dist/assets/eventmodeling-45OFAUF4-DzQLXa3s.js +0 -1
- package/dist/assets/flowDiagram-23GEKE2U-C81eexJZ.js +0 -1
- package/dist/assets/gitGraph-TEB2WS4Q-Dt3ZqpFD.js +0 -1
- package/dist/assets/index-DdYOaKm7.js +0 -109
- package/dist/assets/index-DxCGKhAw.css +0 -1
- package/dist/assets/info-DKCQHKI2-CCCE7dXC.js +0 -1
- package/dist/assets/loader-circle-B-UdXjl4.js +0 -1
- package/dist/assets/mcp-marketplace-page-BUIGtSda.js +0 -1
- package/dist/assets/mcp-marketplace-page-CStb8ml2.js +0 -9
- package/dist/assets/model-config-page-BkfUYm95.js +0 -1
- package/dist/assets/packet-7NZHBO7P-D19yoxFV.js +0 -1
- package/dist/assets/pie-RZYD4A2V-hMaJbLrn.js +0 -1
- package/dist/assets/plus-Dw9QFnKr.js +0 -1
- package/dist/assets/providers-config-page-fxL4I4bz.js +0 -1
- package/dist/assets/radar-I7S5WNFK-C8BkvScA.js +0 -1
- package/dist/assets/railroad-3IZDKUUU-CozZOitC.js +0 -1
- package/dist/assets/railroad-abnf-AHOZXSZD-BqIoFXFi.js +0 -1
- package/dist/assets/railroad-ebnf-EBAXGLYW-CD2e3dng.js +0 -1
- package/dist/assets/railroad-peg-LSFZ7HO6-DoKlRUOF.js +0 -1
- package/dist/assets/react-Dlz_IxoP.js +0 -8
- package/dist/assets/refresh-cw-CK4I5UFv.js +0 -1
- package/dist/assets/remote-B0pPgtC6.js +0 -1
- package/dist/assets/rotate-cw-Z48dmh13.js +0 -1
- package/dist/assets/save-Bo37cIFb.js +0 -1
- package/dist/assets/search-CZiEm7YD.js +0 -1
- package/dist/assets/security-config-CitLihXA.js +0 -1
- package/dist/assets/skeleton-B2PCAZJG.js +0 -1
- package/dist/assets/stateDiagram-v2-6OUMAXLB-b1pZQlDD.js +0 -1
- package/dist/assets/swimlanesDiagram-G3AALYLV-CowxgWVn.js +0 -8
- package/dist/assets/treeView-QDETBFTQ-BQlYkJbz.js +0 -1
- package/dist/assets/treemap-6X3UGDF4-DzTOd1bd.js +0 -1
- package/dist/assets/wardley-OPB4EBWU-D80jQc0y.js +0 -1
- package/dist/assets/x-BzYEzkLA.js +0 -1
- /package/dist/assets/{array-COEOjKUv.js → array-BQVzeGRt.js} +0 -0
- /package/dist/assets/{chunk-KEIR6QF5-D7oHAcry.js → chunk-KEIR6QF5-f9psyCXK.js} +0 -0
- /package/dist/assets/{chunk-Y2CYZVJY-08IUpgTP.js → chunk-Y2CYZVJY-D1mAU_Po.js} +0 -0
- /package/dist/assets/{config-hints-BoE41XDI.js → config-hints-nV5HPOvq.js} +0 -0
- /package/dist/assets/{cytoscape.esm-HifWufkp.js → cytoscape.esm-0uDtdD0l.js} +0 -0
- /package/dist/assets/{defaultLocale-CA-_SsC1.js → defaultLocale-DSWXGgt0.js} +0 -0
- /package/dist/assets/{dist-C60rvfy8.js → dist--ta5rX12.js} +0 -0
- /package/dist/assets/{graphlib-CGYCNsoJ.js → graphlib-CQ6QV4yP.js} +0 -0
- /package/dist/assets/{host-capabilities-DPNRAjIj.js → host-capabilities-Tk038i04.js} +0 -0
- /package/dist/assets/{init-C3plFVsG.js → init-Y6h9jGtZ.js} +0 -0
- /package/dist/assets/{jszip.min-CeYs17Gn.js → jszip.min-8hyJpgpx.js} +0 -0
- /package/dist/assets/{katex-DRThweSG.js → katex-ARhY9PS1.js} +0 -0
- /package/dist/assets/{middleware-D05fK5Sb.js → middleware-DXsbf9xI.js} +0 -0
- /package/dist/assets/{path-BKtKxQ6Y.js → path-10BjdyLh.js} +0 -0
- /package/dist/assets/{rough.esm-DurL7-u7.js → rough.esm-DxgC_14r.js} +0 -0
- /package/dist/assets/{xlsx-Sg8fZ6nH.js → xlsx-DrDuDNAa.js} +0 -0
package/src/features/chat/features/session/components/__tests__/chat-sidebar-session-item.test.tsx
CHANGED
|
@@ -1,8 +1,26 @@
|
|
|
1
1
|
import { render, screen } from '@testing-library/react';
|
|
2
|
+
import userEvent from '@testing-library/user-event';
|
|
2
3
|
import { beforeEach, expect, it, vi } from 'vitest';
|
|
3
4
|
import { ChatSidebarSessionItem } from '@/features/chat/features/session/components/chat-sidebar-session-item';
|
|
4
5
|
|
|
6
|
+
const mocks = vi.hoisted(() => ({
|
|
7
|
+
copyText: vi.fn(),
|
|
8
|
+
}));
|
|
9
|
+
|
|
10
|
+
vi.mock('@nextclaw/agent-chat-ui', () => ({
|
|
11
|
+
copyText: mocks.copyText,
|
|
12
|
+
}));
|
|
13
|
+
|
|
14
|
+
vi.mock('sonner', () => ({
|
|
15
|
+
toast: {
|
|
16
|
+
success: vi.fn(),
|
|
17
|
+
error: vi.fn(),
|
|
18
|
+
},
|
|
19
|
+
}));
|
|
20
|
+
|
|
5
21
|
beforeEach(() => {
|
|
22
|
+
mocks.copyText.mockReset();
|
|
23
|
+
mocks.copyText.mockResolvedValue(true);
|
|
6
24
|
render(
|
|
7
25
|
<ChatSidebarSessionItem
|
|
8
26
|
sessionKey="session:current"
|
|
@@ -43,6 +61,16 @@ it('shows session actions only on hover or when an action owns focus', () => {
|
|
|
43
61
|
expect(actions?.className).not.toContain(
|
|
44
62
|
'group-focus-within/session:opacity-100',
|
|
45
63
|
);
|
|
64
|
+
expect(screen.getByRole('button', { name: 'More actions' })).toBeTruthy();
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it('copies the sidebar session ID from the more-actions menu', async () => {
|
|
68
|
+
const user = userEvent.setup();
|
|
69
|
+
|
|
70
|
+
await user.click(screen.getByRole('button', { name: 'More actions' }));
|
|
71
|
+
await user.click(screen.getByRole('button', { name: 'Copy session ID' }));
|
|
72
|
+
|
|
73
|
+
expect(mocks.copyText).toHaveBeenCalledWith('session:current');
|
|
46
74
|
});
|
|
47
75
|
|
|
48
76
|
it('sizes the runtime icon to the session title text', () => {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { AgentAvatar } from '@/shared/components/common/agent-avatar';
|
|
2
2
|
import { SessionContextIconNode } from '@/features/chat/features/session/components/session-context-icon';
|
|
3
3
|
import { SessionRunBadge } from '@/features/chat/features/session/components/session-run-badge';
|
|
4
|
+
import { ChatSessionMoreActionsMenu } from '@/features/chat/features/session/components/session-header/chat-session-more-actions-menu';
|
|
4
5
|
import { IconActionButton } from '@/shared/components/ui/actions/icon-action-button';
|
|
5
6
|
import { Input } from '@/shared/components/ui/input';
|
|
6
7
|
import { type SessionContextView } from '@/features/chat/features/session/utils/session-context.utils';
|
|
@@ -93,9 +94,10 @@ function ChatSidebarSessionEditingView({
|
|
|
93
94
|
type ChatSidebarSessionDisplayViewProps = Omit<
|
|
94
95
|
ChatSidebarSessionItemProps,
|
|
95
96
|
'sessionKey' | 'isEditing' | 'draftLabel' | 'isSaving' | 'onDraftLabelChange' | 'onSave' | 'onCancel'
|
|
96
|
-
>;
|
|
97
|
+
> & Pick<ChatSidebarSessionItemProps, 'sessionKey'>;
|
|
97
98
|
|
|
98
99
|
function ChatSidebarSessionDisplayView({
|
|
100
|
+
sessionKey,
|
|
99
101
|
active,
|
|
100
102
|
showUnreadDot,
|
|
101
103
|
runStatus,
|
|
@@ -113,7 +115,7 @@ function ChatSidebarSessionDisplayView({
|
|
|
113
115
|
onStartEditing,
|
|
114
116
|
onTogglePinned
|
|
115
117
|
}: ChatSidebarSessionDisplayViewProps) {
|
|
116
|
-
const trailingControlsClassName = childSessionCount > 0 && onOpenChildSessions ? 'pr-
|
|
118
|
+
const trailingControlsClassName = childSessionCount > 0 && onOpenChildSessions ? 'pr-32' : 'pr-20';
|
|
117
119
|
|
|
118
120
|
return (
|
|
119
121
|
<div className="group/session relative">
|
|
@@ -212,6 +214,11 @@ function ChatSidebarSessionDisplayView({
|
|
|
212
214
|
onStartEditing();
|
|
213
215
|
}}
|
|
214
216
|
/>
|
|
217
|
+
<ChatSessionMoreActionsMenu
|
|
218
|
+
sessionKey={sessionKey}
|
|
219
|
+
triggerSize="sm"
|
|
220
|
+
triggerTone="strong"
|
|
221
|
+
/>
|
|
215
222
|
</div>
|
|
216
223
|
</div>
|
|
217
224
|
);
|
|
@@ -262,6 +269,7 @@ export function ChatSidebarSessionItem({
|
|
|
262
269
|
/>
|
|
263
270
|
) : (
|
|
264
271
|
<ChatSidebarSessionDisplayView
|
|
272
|
+
sessionKey={sessionKey}
|
|
265
273
|
active={active}
|
|
266
274
|
showUnreadDot={showUnreadDot}
|
|
267
275
|
runStatus={runStatus}
|
|
@@ -4,11 +4,23 @@ import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
|
4
4
|
import { ChatSessionHeaderActions } from '@/features/chat/features/session/components/session-header/chat-session-header-actions';
|
|
5
5
|
|
|
6
6
|
const mocks = vi.hoisted(() => ({
|
|
7
|
+
copyText: vi.fn(),
|
|
7
8
|
updateSessionProject: vi.fn(),
|
|
8
9
|
onDeleteSession: vi.fn(),
|
|
9
10
|
onToggleWorkspace: vi.fn(),
|
|
10
11
|
}));
|
|
11
12
|
|
|
13
|
+
vi.mock('@nextclaw/agent-chat-ui', () => ({
|
|
14
|
+
copyText: mocks.copyText,
|
|
15
|
+
}));
|
|
16
|
+
|
|
17
|
+
vi.mock('sonner', () => ({
|
|
18
|
+
toast: {
|
|
19
|
+
success: vi.fn(),
|
|
20
|
+
error: vi.fn(),
|
|
21
|
+
},
|
|
22
|
+
}));
|
|
23
|
+
|
|
12
24
|
vi.mock('@/features/chat/features/session/hooks/use-chat-session-project', () => ({
|
|
13
25
|
useChatSessionProject: () => mocks.updateSessionProject,
|
|
14
26
|
}));
|
|
@@ -19,11 +31,34 @@ vi.mock('@/features/chat/features/session/components/session-header/chat-session
|
|
|
19
31
|
|
|
20
32
|
describe('ChatSessionHeaderActions', () => {
|
|
21
33
|
beforeEach(() => {
|
|
34
|
+
mocks.copyText.mockReset();
|
|
22
35
|
mocks.updateSessionProject.mockReset();
|
|
23
36
|
mocks.onDeleteSession.mockReset();
|
|
24
37
|
mocks.onToggleWorkspace.mockReset();
|
|
25
38
|
});
|
|
26
39
|
|
|
40
|
+
it('copies the current session ID from the more-actions menu', async () => {
|
|
41
|
+
const user = userEvent.setup();
|
|
42
|
+
mocks.copyText.mockResolvedValue(true);
|
|
43
|
+
|
|
44
|
+
render(
|
|
45
|
+
<ChatSessionHeaderActions
|
|
46
|
+
sessionKey="session-copy-me"
|
|
47
|
+
canDeleteSession
|
|
48
|
+
isDeletePending={false}
|
|
49
|
+
currentPath={null}
|
|
50
|
+
isWorkspaceOpen={false}
|
|
51
|
+
onToggleWorkspace={mocks.onToggleWorkspace}
|
|
52
|
+
onDeleteSession={mocks.onDeleteSession}
|
|
53
|
+
/>
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
await user.click(screen.getByRole('button', { name: 'More actions' }));
|
|
57
|
+
await user.click(screen.getByRole('button', { name: 'Copy session ID' }));
|
|
58
|
+
|
|
59
|
+
expect(mocks.copyText).toHaveBeenCalledWith('session-copy-me');
|
|
60
|
+
});
|
|
61
|
+
|
|
27
62
|
it('keeps only the set-project action in the more-actions menu when a project is already attached', async () => {
|
|
28
63
|
const user = userEvent.setup();
|
|
29
64
|
|
package/src/features/chat/features/session/components/session-header/chat-session-header-actions.tsx
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { useState } from 'react';
|
|
2
|
-
import { Braces, FolderOpen,
|
|
2
|
+
import { Braces, FolderOpen, PanelRightClose, PanelRightOpen, Trash2 } from 'lucide-react';
|
|
3
3
|
import { IconActionButton } from '@/shared/components/ui/actions/icon-action-button';
|
|
4
|
-
import { Popover, PopoverTrigger } from '@/shared/components/ui/popover';
|
|
5
|
-
import { ChatPopoverContent } from '@/features/chat/components/chat-popover-content';
|
|
6
4
|
import { useChatSessionProject } from '@/features/chat/features/session/hooks/use-chat-session-project';
|
|
7
5
|
import { ChatSessionHeaderMenuItem } from './chat-session-header-menu-item';
|
|
6
|
+
import { ChatSessionMoreActionsMenu } from './chat-session-more-actions-menu';
|
|
8
7
|
import { ChatSessionMetadataDialog } from './chat-session-metadata-dialog';
|
|
9
8
|
import { ChatSessionProjectDialog } from './chat-session-project-dialog';
|
|
10
9
|
import { t } from '@/shared/lib/i18n';
|
|
@@ -35,7 +34,6 @@ export function ChatSessionHeaderActions({
|
|
|
35
34
|
onDeleteSession,
|
|
36
35
|
}: ChatSessionHeaderActionsProps) {
|
|
37
36
|
const updateSessionProject = useChatSessionProject();
|
|
38
|
-
const [isMenuOpen, setIsMenuOpen] = useState(false);
|
|
39
37
|
const [isDialogOpen, setIsDialogOpen] = useState(false);
|
|
40
38
|
const [isMetadataDialogOpen, setIsMetadataDialogOpen] = useState(false);
|
|
41
39
|
const [isProjectPending, setIsProjectPending] = useState(false);
|
|
@@ -54,7 +52,6 @@ export function ChatSessionHeaderActions({
|
|
|
54
52
|
persistToServer,
|
|
55
53
|
});
|
|
56
54
|
setIsDialogOpen(false);
|
|
57
|
-
setIsMenuOpen(false);
|
|
58
55
|
} finally {
|
|
59
56
|
setIsProjectPending(false);
|
|
60
57
|
}
|
|
@@ -63,48 +60,30 @@ export function ChatSessionHeaderActions({
|
|
|
63
60
|
return (
|
|
64
61
|
<div className={SESSION_HEADER_ACTION_GROUP_CLASS}>
|
|
65
62
|
{sessionKey ? (
|
|
66
|
-
<
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
setIsMenuOpen(false);
|
|
91
|
-
setIsMetadataDialogOpen(true);
|
|
92
|
-
}}
|
|
93
|
-
disabled={isBusy}
|
|
94
|
-
/>
|
|
95
|
-
<ChatSessionHeaderMenuItem
|
|
96
|
-
icon={Trash2}
|
|
97
|
-
label={t('chatDeleteSession')}
|
|
98
|
-
onClick={() => {
|
|
99
|
-
setIsMenuOpen(false);
|
|
100
|
-
onDeleteSession();
|
|
101
|
-
}}
|
|
102
|
-
disabled={!canDeleteSession || isBusy}
|
|
103
|
-
destructive
|
|
104
|
-
/>
|
|
105
|
-
</div>
|
|
106
|
-
</ChatPopoverContent>
|
|
107
|
-
</Popover>
|
|
63
|
+
<ChatSessionMoreActionsMenu
|
|
64
|
+
sessionKey={sessionKey}
|
|
65
|
+
disabled={isBusy}
|
|
66
|
+
>
|
|
67
|
+
<ChatSessionHeaderMenuItem
|
|
68
|
+
icon={FolderOpen}
|
|
69
|
+
label={t('chatSessionSetProject')}
|
|
70
|
+
onClick={() => setIsDialogOpen(true)}
|
|
71
|
+
disabled={isBusy}
|
|
72
|
+
/>
|
|
73
|
+
<ChatSessionHeaderMenuItem
|
|
74
|
+
icon={Braces}
|
|
75
|
+
label={t('chatSessionViewMetadata')}
|
|
76
|
+
onClick={() => setIsMetadataDialogOpen(true)}
|
|
77
|
+
disabled={isBusy}
|
|
78
|
+
/>
|
|
79
|
+
<ChatSessionHeaderMenuItem
|
|
80
|
+
icon={Trash2}
|
|
81
|
+
label={t('chatDeleteSession')}
|
|
82
|
+
onClick={onDeleteSession}
|
|
83
|
+
disabled={!canDeleteSession || isBusy}
|
|
84
|
+
destructive
|
|
85
|
+
/>
|
|
86
|
+
</ChatSessionMoreActionsMenu>
|
|
108
87
|
) : null}
|
|
109
88
|
<IconActionButton
|
|
110
89
|
icon={
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { useState, type ReactNode } from 'react';
|
|
2
|
+
import { copyText } from '@nextclaw/agent-chat-ui';
|
|
3
|
+
import { Copy, MoreVertical } from 'lucide-react';
|
|
4
|
+
import { toast } from 'sonner';
|
|
5
|
+
import { ChatPopoverContent } from '@/features/chat/components/chat-popover-content';
|
|
6
|
+
import {
|
|
7
|
+
IconActionButton,
|
|
8
|
+
type IconActionButtonSize,
|
|
9
|
+
type IconActionButtonTone,
|
|
10
|
+
} from '@/shared/components/ui/actions/icon-action-button';
|
|
11
|
+
import { Popover, PopoverTrigger } from '@/shared/components/ui/popover';
|
|
12
|
+
import { t } from '@/shared/lib/i18n';
|
|
13
|
+
import { ChatSessionHeaderMenuItem } from './chat-session-header-menu-item';
|
|
14
|
+
|
|
15
|
+
type ChatSessionMoreActionsMenuProps = {
|
|
16
|
+
sessionKey: string;
|
|
17
|
+
children?: ReactNode;
|
|
18
|
+
disabled?: boolean;
|
|
19
|
+
triggerSize?: IconActionButtonSize;
|
|
20
|
+
triggerTone?: IconActionButtonTone;
|
|
21
|
+
className?: string;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export async function copySessionId(sessionKey: string) {
|
|
25
|
+
const copied = await copyText(sessionKey);
|
|
26
|
+
toast[copied ? 'success' : 'error'](
|
|
27
|
+
t(copied ? 'chatSessionCopyIdSuccess' : 'chatSessionCopyIdFailed'),
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function ChatSessionMoreActionsMenu({
|
|
32
|
+
sessionKey,
|
|
33
|
+
children,
|
|
34
|
+
disabled = false,
|
|
35
|
+
triggerSize = 'md',
|
|
36
|
+
triggerTone = 'default',
|
|
37
|
+
className,
|
|
38
|
+
}: ChatSessionMoreActionsMenuProps) {
|
|
39
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
40
|
+
|
|
41
|
+
const handleCopySessionId = () => {
|
|
42
|
+
setIsOpen(false);
|
|
43
|
+
void copySessionId(sessionKey);
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
return (
|
|
47
|
+
<Popover open={isOpen} onOpenChange={setIsOpen}>
|
|
48
|
+
<PopoverTrigger asChild>
|
|
49
|
+
<IconActionButton
|
|
50
|
+
icon={<MoreVertical className="h-4 w-4" />}
|
|
51
|
+
label={t('chatSessionMoreActions')}
|
|
52
|
+
tooltip={false}
|
|
53
|
+
size={triggerSize}
|
|
54
|
+
tone={triggerTone}
|
|
55
|
+
className={className}
|
|
56
|
+
disabled={disabled}
|
|
57
|
+
onClick={(event) => event.stopPropagation()}
|
|
58
|
+
/>
|
|
59
|
+
</PopoverTrigger>
|
|
60
|
+
<ChatPopoverContent align="end" className="w-56 p-2">
|
|
61
|
+
<div className="space-y-1" onClick={() => setIsOpen(false)}>
|
|
62
|
+
<ChatSessionHeaderMenuItem
|
|
63
|
+
icon={Copy}
|
|
64
|
+
label={t('chatSessionCopyId')}
|
|
65
|
+
onClick={handleCopySessionId}
|
|
66
|
+
disabled={disabled}
|
|
67
|
+
/>
|
|
68
|
+
{children}
|
|
69
|
+
</div>
|
|
70
|
+
</ChatPopoverContent>
|
|
71
|
+
</Popover>
|
|
72
|
+
);
|
|
73
|
+
}
|
package/src/features/chat/features/session/utils/__tests__/ncp-session-adapter.utils.test.ts
CHANGED
|
@@ -35,6 +35,34 @@ it('preserves NCP extension parts for the chat presentation adapter', () => {
|
|
|
35
35
|
]);
|
|
36
36
|
});
|
|
37
37
|
|
|
38
|
+
it('keeps deferred tool part slots out of the summary card view', () => {
|
|
39
|
+
const adapted = adaptNcpMessagePartsForChat([
|
|
40
|
+
{
|
|
41
|
+
type: 'tool-invocation',
|
|
42
|
+
toolCallId: 'tool-visible',
|
|
43
|
+
toolName: 'exec',
|
|
44
|
+
state: 'result',
|
|
45
|
+
args: undefined,
|
|
46
|
+
result: undefined,
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
type: 'tool-invocation',
|
|
50
|
+
toolCallId: 'tool-deferred',
|
|
51
|
+
toolName: 'read_file',
|
|
52
|
+
state: 'result',
|
|
53
|
+
payloadDeferred: true,
|
|
54
|
+
args: undefined,
|
|
55
|
+
result: undefined,
|
|
56
|
+
},
|
|
57
|
+
{ type: 'text', text: 'done' },
|
|
58
|
+
]);
|
|
59
|
+
|
|
60
|
+
expect(adapted.map((part) => part.type)).toEqual([
|
|
61
|
+
'tool-invocation',
|
|
62
|
+
'text',
|
|
63
|
+
]);
|
|
64
|
+
});
|
|
65
|
+
|
|
38
66
|
it('preserves standard tool execution timing without reading opaque result timing', () => {
|
|
39
67
|
const adapted = adaptNcpMessageToUiMessage({
|
|
40
68
|
id: 'ncp-message-timing-1',
|
|
@@ -194,7 +194,9 @@ function mapToolStatus(part: Extract<NcpMessagePart, { type: 'tool-invocation' }
|
|
|
194
194
|
|
|
195
195
|
function toUiParts(parts: NcpMessagePart[]): UIMessage['parts'] {
|
|
196
196
|
const uiParts: UIMessage['parts'] = [];
|
|
197
|
-
for (const part of parts)
|
|
197
|
+
for (const part of parts.filter((candidate) =>
|
|
198
|
+
candidate.type !== 'tool-invocation' || !candidate.payloadDeferred,
|
|
199
|
+
)) {
|
|
198
200
|
if (part.type === 'text') {
|
|
199
201
|
uiParts.push({ type: 'text', text: part.text });
|
|
200
202
|
continue;
|
|
@@ -80,7 +80,7 @@ export type ContextCompactionTimelineView = {
|
|
|
80
80
|
phase?: 'pre-run' | 'mid-run';
|
|
81
81
|
continuationMessageId?: string;
|
|
82
82
|
continuationMessageCoveredPartCount?: number;
|
|
83
|
-
summary
|
|
83
|
+
summary?: string;
|
|
84
84
|
coveredMessageCount: number;
|
|
85
85
|
coveredSessionMessageCount: number;
|
|
86
86
|
originalEstimatedTokens: number;
|
|
@@ -120,7 +120,7 @@ export function readContextCompactionTimeline(message: Pick<NcpMessageView, 'met
|
|
|
120
120
|
const continuationMessageCoveredPartCount = readNonNegativeInteger(
|
|
121
121
|
rawCheckpoint.continuationMessageCoveredPartCount,
|
|
122
122
|
);
|
|
123
|
-
const summary = typeof rawCheckpoint.summary === 'string' ? rawCheckpoint.summary :
|
|
123
|
+
const summary = typeof rawCheckpoint.summary === 'string' ? rawCheckpoint.summary : undefined;
|
|
124
124
|
const coveredMessageCount = readNonNegativeInteger(rawCheckpoint.coveredMessageCount);
|
|
125
125
|
const coveredSessionMessageCount = readNonNegativeInteger(rawCheckpoint.coveredSessionMessageCount);
|
|
126
126
|
const originalEstimatedTokens = readNonNegativeInteger(rawCheckpoint.originalEstimatedTokens);
|
|
@@ -130,7 +130,6 @@ export function readContextCompactionTimeline(message: Pick<NcpMessageView, 'met
|
|
|
130
130
|
if (
|
|
131
131
|
!id ||
|
|
132
132
|
!status ||
|
|
133
|
-
summary === null ||
|
|
134
133
|
coveredMessageCount === null ||
|
|
135
134
|
coveredSessionMessageCount === null ||
|
|
136
135
|
originalEstimatedTokens === null ||
|
|
@@ -148,7 +147,7 @@ export function readContextCompactionTimeline(message: Pick<NcpMessageView, 'met
|
|
|
148
147
|
...(continuationMessageCoveredPartCount !== null
|
|
149
148
|
? { continuationMessageCoveredPartCount }
|
|
150
149
|
: {}),
|
|
151
|
-
summary,
|
|
150
|
+
...(summary !== undefined ? { summary } : {}),
|
|
152
151
|
coveredMessageCount,
|
|
153
152
|
coveredSessionMessageCount,
|
|
154
153
|
originalEstimatedTokens,
|
|
@@ -5,15 +5,30 @@ import { ChatSessionChildSessions } from '@/features/chat/features/workspace/com
|
|
|
5
5
|
import type { ResolvedChildSessionTab } from '@/features/chat/features/ncp/hooks/use-ncp-child-session-tabs-view';
|
|
6
6
|
|
|
7
7
|
const mocks = vi.hoisted(() => ({
|
|
8
|
+
copyText: vi.fn(),
|
|
8
9
|
openSideChatDraft: vi.fn(),
|
|
9
10
|
selectChildSessionDetail: vi.fn(),
|
|
10
11
|
}));
|
|
11
12
|
|
|
13
|
+
vi.mock('@nextclaw/agent-chat-ui', () => ({
|
|
14
|
+
copyText: mocks.copyText,
|
|
15
|
+
}));
|
|
16
|
+
|
|
17
|
+
vi.mock('sonner', () => ({
|
|
18
|
+
toast: {
|
|
19
|
+
success: vi.fn(),
|
|
20
|
+
error: vi.fn(),
|
|
21
|
+
},
|
|
22
|
+
}));
|
|
23
|
+
|
|
12
24
|
vi.mock('@/features/chat/components/providers/chat-presenter.provider', () => ({
|
|
13
25
|
usePresenter: () => ({ chatThreadManager: mocks }),
|
|
14
26
|
}));
|
|
15
27
|
|
|
16
|
-
beforeEach(() =>
|
|
28
|
+
beforeEach(() => {
|
|
29
|
+
vi.clearAllMocks();
|
|
30
|
+
mocks.copyText.mockResolvedValue(true);
|
|
31
|
+
});
|
|
17
32
|
|
|
18
33
|
function createChildSession(): ResolvedChildSessionTab {
|
|
19
34
|
return {
|
|
@@ -49,3 +64,14 @@ it('keeps existing child sessions selectable beside the create action', async ()
|
|
|
49
64
|
await user.click(screen.getByRole('button', { name: /Research branch/ }));
|
|
50
65
|
expect(mocks.selectChildSessionDetail).toHaveBeenCalledWith('child-1');
|
|
51
66
|
});
|
|
67
|
+
|
|
68
|
+
it('copies a child session ID from its own more-actions menu', async () => {
|
|
69
|
+
const user = userEvent.setup();
|
|
70
|
+
render(<ChatSessionChildSessions childSessionTabs={[createChildSession()]} sessionKey="parent-1" />);
|
|
71
|
+
|
|
72
|
+
await user.click(screen.getByRole('button', { name: 'More actions' }));
|
|
73
|
+
await user.click(screen.getByRole('button', { name: 'Copy session ID' }));
|
|
74
|
+
|
|
75
|
+
expect(mocks.copyText).toHaveBeenCalledWith('child-1');
|
|
76
|
+
expect(mocks.selectChildSessionDetail).not.toHaveBeenCalled();
|
|
77
|
+
});
|
|
@@ -37,6 +37,7 @@ const mocks = vi.hoisted(() => ({
|
|
|
37
37
|
openFilePreview: vi.fn(),
|
|
38
38
|
openProjectFiles: vi.fn(),
|
|
39
39
|
openSessionCronPanel: vi.fn(),
|
|
40
|
+
openContinuousAttention: vi.fn(),
|
|
40
41
|
removeWorkspacePath: vi.fn(),
|
|
41
42
|
renameWorkspacePath: vi.fn(),
|
|
42
43
|
selectChildSessionDetail: vi.fn(),
|
|
@@ -95,6 +96,18 @@ vi.mock('@/features/chat/features/conversation/components/session-conversation-a
|
|
|
95
96
|
SessionConversationArea: () => <div data-testid="session-conversation-area" />,
|
|
96
97
|
}));
|
|
97
98
|
|
|
99
|
+
vi.mock('@/features/chat/features/ncp/hooks/use-ncp-session-queries', () => ({
|
|
100
|
+
useNcpSessionObservations: () => ({
|
|
101
|
+
data: {
|
|
102
|
+
counts: { total: 0, context: 0, events: 0, needsAttention: 0 },
|
|
103
|
+
bindings: [],
|
|
104
|
+
subscriptions: [],
|
|
105
|
+
},
|
|
106
|
+
isPending: false,
|
|
107
|
+
isError: false,
|
|
108
|
+
}),
|
|
109
|
+
}));
|
|
110
|
+
|
|
98
111
|
vi.mock('@/shared/hooks/use-server-path-browse', () => ({
|
|
99
112
|
useServerPathBrowse: ({ path }: { path?: string | null }) => ({
|
|
100
113
|
isLoading: false,
|
|
@@ -2,6 +2,7 @@ import { render, screen } from "@testing-library/react";
|
|
|
2
2
|
import userEvent from "@testing-library/user-event";
|
|
3
3
|
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
4
4
|
import { ChatSessionWorkspacePanel } from "@/features/chat/features/workspace/components/chat-session-workspace-panel";
|
|
5
|
+
import { WorkspaceTabsBar } from "@/features/chat/features/workspace/components/chat-session-workspace-panel-nav";
|
|
5
6
|
import type { ChatWorkspaceFileTab } from "@/features/chat/stores/chat-thread.store";
|
|
6
7
|
import type * as ReactQuery from "@tanstack/react-query";
|
|
7
8
|
|
|
@@ -112,6 +113,34 @@ describe("ChatSessionWorkspacePanel", () => {
|
|
|
112
113
|
).toBe("1");
|
|
113
114
|
});
|
|
114
115
|
|
|
116
|
+
it("shows more actions for a child-session workspace tab", async () => {
|
|
117
|
+
const user = userEvent.setup();
|
|
118
|
+
render(
|
|
119
|
+
<WorkspaceTabsBar
|
|
120
|
+
canGoBack={false}
|
|
121
|
+
canGoForward={false}
|
|
122
|
+
tabs={[
|
|
123
|
+
{
|
|
124
|
+
key: "child:child-1",
|
|
125
|
+
kind: "child-session",
|
|
126
|
+
title: "Child session",
|
|
127
|
+
tooltip: "Child session",
|
|
128
|
+
active: true,
|
|
129
|
+
sessionKey: "child-1",
|
|
130
|
+
onSelect: vi.fn(),
|
|
131
|
+
},
|
|
132
|
+
]}
|
|
133
|
+
onClose={vi.fn()}
|
|
134
|
+
onGoBack={vi.fn()}
|
|
135
|
+
onGoForward={vi.fn()}
|
|
136
|
+
/>,
|
|
137
|
+
);
|
|
138
|
+
|
|
139
|
+
await user.click(screen.getByRole("button", { name: "More actions" }));
|
|
140
|
+
|
|
141
|
+
expect(screen.getByRole("menuitem", { name: "Copy session ID" })).toBeTruthy();
|
|
142
|
+
});
|
|
143
|
+
|
|
115
144
|
it("adds an opened project file to the active chat from its action menu", async () => {
|
|
116
145
|
const user = userEvent.setup();
|
|
117
146
|
renderPanel();
|
package/src/features/chat/features/workspace/components/chat-session-workspace-panel-content.tsx
CHANGED
|
@@ -3,6 +3,7 @@ import type { ChatFileOpenActionViewModel } from '@nextclaw/agent-chat-ui';
|
|
|
3
3
|
import {
|
|
4
4
|
AlarmClock,
|
|
5
5
|
ChevronRight,
|
|
6
|
+
Eye,
|
|
6
7
|
FolderTree,
|
|
7
8
|
GitBranch,
|
|
8
9
|
MessageSquarePlus,
|
|
@@ -17,6 +18,8 @@ import { ChatSessionWorkspaceDirectoryBrowser } from '@/features/chat/features/w
|
|
|
17
18
|
import { SessionCronJobContent } from '@/features/chat/features/workspace/components/session-cron-job-content';
|
|
18
19
|
import { ChatSessionChildSessions } from '@/features/chat/features/workspace/components/child-sessions/chat-session-child-sessions';
|
|
19
20
|
import { ChatSessionTokenUsage } from '@/features/chat/features/workspace/components/overview/chat-session-token-usage';
|
|
21
|
+
import { ChatSessionContinuousAttention } from '@/features/chat/features/workspace/components/overview/chat-session-continuous-attention';
|
|
22
|
+
import { useNcpSessionObservations } from '@/features/chat/features/ncp/hooks/use-ncp-session-queries';
|
|
20
23
|
import type { ResolvedChildSessionTab } from '@/features/chat/features/ncp/hooks/use-ncp-child-session-tabs-view';
|
|
21
24
|
import type { WorkspaceSelection } from '@/features/chat/features/workspace/utils/chat-workspace-panel-view-model.utils';
|
|
22
25
|
import { useServerPathBrowse } from '@/shared/hooks/use-server-path-browse';
|
|
@@ -88,6 +91,7 @@ function WorkspaceOverview({
|
|
|
88
91
|
sessionKey: string | null;
|
|
89
92
|
}) {
|
|
90
93
|
const presenter = usePresenter();
|
|
94
|
+
const observationsQuery = useNcpSessionObservations(sessionKey);
|
|
91
95
|
|
|
92
96
|
return (
|
|
93
97
|
<div className="h-full overflow-auto bg-gray-50/45 px-4 py-5 custom-scrollbar">
|
|
@@ -95,6 +99,17 @@ function WorkspaceOverview({
|
|
|
95
99
|
<h2 className="text-base font-semibold text-gray-900">{t('chatWorkspaceOverview')}</h2>
|
|
96
100
|
<p className="mt-1 text-xs leading-5 text-gray-500">{t('chatWorkspaceOverviewDescription')}</p>
|
|
97
101
|
<div className="mt-4 space-y-2">
|
|
102
|
+
<WorkspaceOverviewEntry
|
|
103
|
+
count={observationsQuery.data?.counts.total ?? 0}
|
|
104
|
+
description={t('chatWorkspaceContinuousAttentionDescription')}
|
|
105
|
+
icon={<Eye className="h-4 w-4" />}
|
|
106
|
+
title={t('chatWorkspaceContinuousAttention')}
|
|
107
|
+
onClick={() => {
|
|
108
|
+
if (sessionKey) {
|
|
109
|
+
presenter.chatThreadManager.openContinuousAttention(sessionKey);
|
|
110
|
+
}
|
|
111
|
+
}}
|
|
112
|
+
/>
|
|
98
113
|
<WorkspaceOverviewEntry
|
|
99
114
|
count={childSessionTabs.length}
|
|
100
115
|
description={t('chatWorkspaceChildSessionsDescription')}
|
|
@@ -261,6 +276,10 @@ function WorkspaceSelectedContent({
|
|
|
261
276
|
return <ChatSessionChildSessions childSessionTabs={childSessionTabs} sessionKey={sessionKey} />;
|
|
262
277
|
}
|
|
263
278
|
|
|
279
|
+
if (activeSelection.kind === 'continuous-attention') {
|
|
280
|
+
return <ChatSessionContinuousAttention sessionKey={sessionKey} />;
|
|
281
|
+
}
|
|
282
|
+
|
|
264
283
|
if (activeSelection.kind === 'side-chat-draft') {
|
|
265
284
|
return (
|
|
266
285
|
<>
|
package/src/features/chat/features/workspace/components/chat-session-workspace-panel-nav.tsx
CHANGED
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
ArrowLeft,
|
|
4
4
|
ArrowRight,
|
|
5
5
|
Code2,
|
|
6
|
+
Copy,
|
|
6
7
|
Eye,
|
|
7
8
|
FolderTree,
|
|
8
9
|
GitBranch,
|
|
@@ -15,6 +16,7 @@ import {
|
|
|
15
16
|
X,
|
|
16
17
|
} from "lucide-react";
|
|
17
18
|
import type { WorkspaceTabViewModel } from "@/features/chat/features/workspace/utils/chat-workspace-panel-view-model.utils";
|
|
19
|
+
import { copySessionId } from "@/features/chat/features/session/components/session-header/chat-session-more-actions-menu";
|
|
18
20
|
import { AgentIdentityAvatar } from "@/shared/components/common/agent-identity";
|
|
19
21
|
import { FileTypeIcon } from "@/shared/components/file-type-icon";
|
|
20
22
|
import {
|
|
@@ -49,6 +51,10 @@ function WorkspaceTabIcon({
|
|
|
49
51
|
return <AlarmClock className="h-3.5 w-3.5 shrink-0 text-gray-400" />;
|
|
50
52
|
}
|
|
51
53
|
|
|
54
|
+
if (kind === "continuous-attention") {
|
|
55
|
+
return <Eye className="h-3.5 w-3.5 shrink-0 text-gray-400" />;
|
|
56
|
+
}
|
|
57
|
+
|
|
52
58
|
if (kind === "file") {
|
|
53
59
|
return <FileTypeIcon fileName={fileName ?? ""} size="compact" />;
|
|
54
60
|
}
|
|
@@ -109,6 +115,28 @@ function buildWorkspaceFileMenuGroups(
|
|
|
109
115
|
];
|
|
110
116
|
}
|
|
111
117
|
|
|
118
|
+
function buildWorkspaceSessionMenuGroups(
|
|
119
|
+
tab: WorkspaceTabViewModel,
|
|
120
|
+
): ContextMenuGroup[] | undefined {
|
|
121
|
+
if (tab.kind !== "child-session" || !tab.sessionKey) {
|
|
122
|
+
return undefined;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return [
|
|
126
|
+
{
|
|
127
|
+
key: "session",
|
|
128
|
+
items: [
|
|
129
|
+
{
|
|
130
|
+
key: "copy-session-id",
|
|
131
|
+
label: t("chatSessionCopyId"),
|
|
132
|
+
icon: <Copy className="h-4 w-4" />,
|
|
133
|
+
onSelect: () => void copySessionId(tab.sessionKey!),
|
|
134
|
+
},
|
|
135
|
+
],
|
|
136
|
+
},
|
|
137
|
+
];
|
|
138
|
+
}
|
|
139
|
+
|
|
112
140
|
function buildCompactWorkspaceTabs(
|
|
113
141
|
tabs: readonly WorkspaceTabViewModel[],
|
|
114
142
|
): CompactTabStripTab[] {
|
|
@@ -139,8 +167,14 @@ function buildCompactWorkspaceTabs(
|
|
|
139
167
|
closePlacement: "leading-hover",
|
|
140
168
|
onSelect: tab.onSelect,
|
|
141
169
|
onClose: tab.onClose,
|
|
142
|
-
menuLabel:
|
|
143
|
-
|
|
170
|
+
menuLabel:
|
|
171
|
+
tab.kind === "child-session"
|
|
172
|
+
? t("chatSessionMoreActions")
|
|
173
|
+
: t("chatWorkspaceFileMoreActions"),
|
|
174
|
+
menuGroups:
|
|
175
|
+
tab.menuGroups ??
|
|
176
|
+
buildWorkspaceSessionMenuGroups(tab) ??
|
|
177
|
+
buildWorkspaceFileMenuGroups(tab),
|
|
144
178
|
}));
|
|
145
179
|
}
|
|
146
180
|
|
|
@@ -129,6 +129,10 @@ export function ChatSessionWorkspacePanel({
|
|
|
129
129
|
if (sessionKey)
|
|
130
130
|
presenter.chatThreadManager.openSessionCronPanel(sessionKey);
|
|
131
131
|
},
|
|
132
|
+
onSelectContinuousAttention: () => {
|
|
133
|
+
if (sessionKey)
|
|
134
|
+
presenter.chatThreadManager.openContinuousAttention(sessionKey);
|
|
135
|
+
},
|
|
132
136
|
}),
|
|
133
137
|
[
|
|
134
138
|
activeSelection,
|