@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
|
@@ -2,6 +2,7 @@ import { ChevronRight, GitBranch, MessageSquarePlus } from 'lucide-react';
|
|
|
2
2
|
|
|
3
3
|
import { usePresenter } from '@/features/chat/components/providers/chat-presenter.provider';
|
|
4
4
|
import type { ResolvedChildSessionTab } from '@/features/chat/features/ncp/hooks/use-ncp-child-session-tabs-view';
|
|
5
|
+
import { ChatSessionMoreActionsMenu } from '@/features/chat/features/session/components/session-header/chat-session-more-actions-menu';
|
|
5
6
|
import { t } from '@/shared/lib/i18n';
|
|
6
7
|
|
|
7
8
|
export function ChatSessionChildSessions({
|
|
@@ -38,25 +39,35 @@ export function ChatSessionChildSessions({
|
|
|
38
39
|
) : (
|
|
39
40
|
<div className="mt-4 space-y-2">
|
|
40
41
|
{childSessionTabs.map((tab) => (
|
|
41
|
-
<
|
|
42
|
+
<div
|
|
42
43
|
key={tab.sessionKey}
|
|
43
|
-
|
|
44
|
-
className="group flex w-full items-center gap-3 rounded-lg border border-gray-200/80 bg-white px-3 py-3 text-left transition-colors hover:border-gray-300 hover:bg-gray-50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/25"
|
|
45
|
-
onClick={() => presenter.chatThreadManager.selectChildSessionDetail(tab.sessionKey)}
|
|
44
|
+
className="group relative flex w-full items-center rounded-lg border border-gray-200/80 bg-white transition-colors hover:border-gray-300 hover:bg-gray-50"
|
|
46
45
|
>
|
|
47
|
-
<
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
<
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
46
|
+
<button
|
|
47
|
+
type="button"
|
|
48
|
+
className="flex min-w-0 flex-1 items-center gap-3 px-3 py-3 pr-12 text-left focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-primary/25"
|
|
49
|
+
onClick={() => presenter.chatThreadManager.selectChildSessionDetail(tab.sessionKey)}
|
|
50
|
+
>
|
|
51
|
+
<span className="inline-flex h-8 w-8 shrink-0 items-center justify-center rounded-lg bg-gray-100 text-gray-600">
|
|
52
|
+
<GitBranch className="h-4 w-4" />
|
|
53
|
+
</span>
|
|
54
|
+
<span className="min-w-0 flex-1">
|
|
55
|
+
<span className="block truncate text-sm font-medium text-gray-900">{tab.title}</span>
|
|
56
|
+
{tab.projectName || tab.sessionTypeLabel ? (
|
|
57
|
+
<span className="mt-0.5 block truncate text-xs text-gray-500">
|
|
58
|
+
{[tab.sessionTypeLabel, tab.projectName].filter(Boolean).join(' · ')}
|
|
59
|
+
</span>
|
|
60
|
+
) : null}
|
|
61
|
+
</span>
|
|
62
|
+
<ChevronRight className="h-4 w-4 shrink-0 text-gray-300 transition-transform group-hover:translate-x-0.5 group-hover:text-gray-500" />
|
|
63
|
+
</button>
|
|
64
|
+
<ChatSessionMoreActionsMenu
|
|
65
|
+
sessionKey={tab.sessionKey}
|
|
66
|
+
triggerSize="sm"
|
|
67
|
+
triggerTone="strong"
|
|
68
|
+
className="absolute right-2 top-1/2 -translate-y-1/2 bg-white opacity-100 md:opacity-0 md:group-hover:opacity-100 md:group-focus-within:opacity-100"
|
|
69
|
+
/>
|
|
70
|
+
</div>
|
|
60
71
|
))}
|
|
61
72
|
</div>
|
|
62
73
|
)}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { render, screen } from '@testing-library/react';
|
|
2
|
+
import userEvent from '@testing-library/user-event';
|
|
3
|
+
import { beforeEach, expect, it, vi } from 'vitest';
|
|
4
|
+
import { ChatSessionContinuousAttention } from '@/features/chat/features/workspace/components/overview/chat-session-continuous-attention';
|
|
5
|
+
|
|
6
|
+
const mocks = vi.hoisted(() => ({
|
|
7
|
+
mutateAsync: vi.fn(),
|
|
8
|
+
}));
|
|
9
|
+
|
|
10
|
+
vi.mock('@/features/chat/features/ncp/hooks/use-ncp-session-queries', () => ({
|
|
11
|
+
useNcpSessionObservations: () => ({
|
|
12
|
+
data: {
|
|
13
|
+
sessionId: 'session-1',
|
|
14
|
+
bindings: [{
|
|
15
|
+
id: 'binding-1',
|
|
16
|
+
kind: 'context',
|
|
17
|
+
extensionId: 'world-extension',
|
|
18
|
+
title: 'World',
|
|
19
|
+
description: 'Latest state',
|
|
20
|
+
status: 'active',
|
|
21
|
+
createdAt: '2026-08-23T08:00:00.000Z',
|
|
22
|
+
lastReadAt: '2026-08-23T08:05:00.000Z',
|
|
23
|
+
safeConfigPreview: 'project: nextclaw',
|
|
24
|
+
}],
|
|
25
|
+
subscriptions: [{
|
|
26
|
+
id: 'subscription-1',
|
|
27
|
+
kind: 'events',
|
|
28
|
+
extensionId: 'world-extension',
|
|
29
|
+
title: 'World events',
|
|
30
|
+
status: 'paused',
|
|
31
|
+
createdAt: '2026-08-23T08:01:00.000Z',
|
|
32
|
+
pendingCount: 2,
|
|
33
|
+
}],
|
|
34
|
+
counts: { total: 2, context: 1, events: 1, needsAttention: 1 },
|
|
35
|
+
},
|
|
36
|
+
isPending: false,
|
|
37
|
+
isError: false,
|
|
38
|
+
refetch: vi.fn(),
|
|
39
|
+
}),
|
|
40
|
+
useNcpObservationAction: () => ({
|
|
41
|
+
isPending: false,
|
|
42
|
+
variables: undefined,
|
|
43
|
+
mutateAsync: mocks.mutateAsync,
|
|
44
|
+
}),
|
|
45
|
+
}));
|
|
46
|
+
|
|
47
|
+
beforeEach(() => {
|
|
48
|
+
vi.clearAllMocks();
|
|
49
|
+
mocks.mutateAsync.mockResolvedValue(undefined);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it('separates state and event relationships and manages the active relationship', async () => {
|
|
53
|
+
const user = userEvent.setup();
|
|
54
|
+
render(<ChatSessionContinuousAttention sessionKey="session-1" />);
|
|
55
|
+
|
|
56
|
+
expect(screen.getByText('World')).toBeTruthy();
|
|
57
|
+
expect(screen.getByText('Needs attention')).toBeTruthy();
|
|
58
|
+
await user.click(screen.getByRole('tab', { name: /Events/ }));
|
|
59
|
+
expect(screen.getByText('World events')).toBeTruthy();
|
|
60
|
+
await user.click(screen.getByRole('button', { name: 'Resume' }));
|
|
61
|
+
|
|
62
|
+
expect(mocks.mutateAsync).toHaveBeenCalledWith({
|
|
63
|
+
kind: 'events',
|
|
64
|
+
id: 'subscription-1',
|
|
65
|
+
action: 'resume',
|
|
66
|
+
});
|
|
67
|
+
});
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
import { AlertTriangle, Clock3, Eye, Inbox, Pause, Play, RefreshCw, Trash2 } from 'lucide-react';
|
|
2
|
+
import { useState } from 'react';
|
|
3
|
+
import { formatDateTime, t } from '@/shared/lib/i18n';
|
|
4
|
+
import { useConfirmDialog } from '@/shared/hooks/use-confirm-dialog';
|
|
5
|
+
import {
|
|
6
|
+
useNcpObservationAction,
|
|
7
|
+
useNcpSessionObservations,
|
|
8
|
+
} from '@/features/chat/features/ncp/hooks/use-ncp-session-queries';
|
|
9
|
+
import type {
|
|
10
|
+
NcpSessionObservationAction,
|
|
11
|
+
NcpSessionObservationKind,
|
|
12
|
+
NcpSessionObservationView,
|
|
13
|
+
} from '@/shared/lib/api';
|
|
14
|
+
import { cn } from '@/shared/lib/utils';
|
|
15
|
+
|
|
16
|
+
type AttentionGroup = NcpSessionObservationKind;
|
|
17
|
+
|
|
18
|
+
const statusTone: Record<NcpSessionObservationView['status'], string> = {
|
|
19
|
+
active: 'border-emerald-200 bg-emerald-50 text-emerald-700',
|
|
20
|
+
paused: 'border-amber-200 bg-amber-50 text-amber-700',
|
|
21
|
+
degraded: 'border-orange-200 bg-orange-50 text-orange-700',
|
|
22
|
+
expired: 'border-gray-200 bg-gray-100 text-gray-600',
|
|
23
|
+
broken: 'border-rose-200 bg-rose-50 text-rose-700',
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
function replaceCount(template: string, count: number): string {
|
|
27
|
+
return template.replace('{count}', String(count));
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function getStatusLabel(status: NcpSessionObservationView['status']): string {
|
|
31
|
+
return t(`chatWorkspaceContinuousAttentionStatus${status[0].toUpperCase()}${status.slice(1)}`);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function getGroupLabel(kind: AttentionGroup): string {
|
|
35
|
+
return t(kind === 'context' ? 'chatWorkspaceContinuousAttentionState' : 'chatWorkspaceContinuousAttentionEvents');
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function ObservationRow({
|
|
39
|
+
item,
|
|
40
|
+
isPending,
|
|
41
|
+
onAction,
|
|
42
|
+
}: {
|
|
43
|
+
item: NcpSessionObservationView;
|
|
44
|
+
isPending: boolean;
|
|
45
|
+
onAction: (action: NcpSessionObservationAction) => void;
|
|
46
|
+
}) {
|
|
47
|
+
const canToggle = item.status === 'active' || item.status === 'paused';
|
|
48
|
+
const toggleAction = item.status === 'active' ? 'pause' : 'resume';
|
|
49
|
+
const toggleLabel = toggleAction === 'pause'
|
|
50
|
+
? t('chatWorkspaceContinuousAttentionPause')
|
|
51
|
+
: t('chatWorkspaceContinuousAttentionResume');
|
|
52
|
+
|
|
53
|
+
return (
|
|
54
|
+
<article className="rounded-xl border border-gray-200/80 bg-white p-3 shadow-sm">
|
|
55
|
+
<div className="flex min-w-0 items-start gap-3">
|
|
56
|
+
<span className="mt-0.5 inline-flex h-8 w-8 shrink-0 items-center justify-center rounded-lg bg-gray-100 text-gray-500">
|
|
57
|
+
{item.kind === 'context' ? <Eye className="h-4 w-4" /> : <Inbox className="h-4 w-4" />}
|
|
58
|
+
</span>
|
|
59
|
+
<div className="min-w-0 flex-1">
|
|
60
|
+
<div className="flex flex-wrap items-center gap-2">
|
|
61
|
+
<h3 className="truncate text-sm font-semibold text-gray-900">{item.title}</h3>
|
|
62
|
+
<span className={cn('rounded-full border px-1.5 py-0.5 text-[10px] font-medium', statusTone[item.status])}>
|
|
63
|
+
{getStatusLabel(item.status)}
|
|
64
|
+
</span>
|
|
65
|
+
</div>
|
|
66
|
+
<p className="mt-0.5 truncate text-[11px] text-gray-400">{item.extensionId} · {getGroupLabel(item.kind)}</p>
|
|
67
|
+
{item.description ? <p className="mt-2 text-xs leading-5 text-gray-600">{item.description}</p> : null}
|
|
68
|
+
{item.statusReason ? (
|
|
69
|
+
<p className="mt-2 flex gap-1.5 text-xs leading-5 text-orange-700">
|
|
70
|
+
<AlertTriangle className="mt-0.5 h-3.5 w-3.5 shrink-0" />
|
|
71
|
+
<span>{item.statusReason}</span>
|
|
72
|
+
</p>
|
|
73
|
+
) : null}
|
|
74
|
+
{item.safeConfigPreview ? (
|
|
75
|
+
<p className="mt-2 rounded-md bg-gray-50 px-2 py-1.5 text-[11px] leading-5 text-gray-500">
|
|
76
|
+
{item.safeConfigPreview}
|
|
77
|
+
</p>
|
|
78
|
+
) : null}
|
|
79
|
+
<div className="mt-2 flex flex-wrap gap-x-3 gap-y-1 text-[11px] text-gray-400">
|
|
80
|
+
<span>{t('chatWorkspaceContinuousAttentionCreated')}: {formatDateTime(item.createdAt)}</span>
|
|
81
|
+
{item.expiresAt ? <span>{t('chatWorkspaceContinuousAttentionExpires')}: {formatDateTime(item.expiresAt)}</span> : null}
|
|
82
|
+
{item.lastReadAt ? <span>{t('chatWorkspaceContinuousAttentionLastRead')}: {formatDateTime(item.lastReadAt)}</span> : null}
|
|
83
|
+
{item.kind === 'events' ? (
|
|
84
|
+
<>
|
|
85
|
+
<span>{replaceCount(t('chatWorkspaceContinuousAttentionPending'), item.pendingCount ?? 0)}</span>
|
|
86
|
+
{item.suppressedCount ? <span>{replaceCount(t('chatWorkspaceContinuousAttentionSuppressed'), item.suppressedCount)}</span> : null}
|
|
87
|
+
{item.deliveryFailureCount ? <span className="text-rose-600">{replaceCount(t('chatWorkspaceContinuousAttentionFailures'), item.deliveryFailureCount)}</span> : null}
|
|
88
|
+
</>
|
|
89
|
+
) : null}
|
|
90
|
+
</div>
|
|
91
|
+
</div>
|
|
92
|
+
</div>
|
|
93
|
+
<div className="mt-3 flex items-center justify-end gap-2 border-t border-gray-100 pt-2">
|
|
94
|
+
{canToggle ? (
|
|
95
|
+
<button
|
|
96
|
+
type="button"
|
|
97
|
+
data-testid={`observation-${item.id}-${toggleAction}`}
|
|
98
|
+
disabled={isPending}
|
|
99
|
+
className="inline-flex items-center gap-1.5 rounded-md border border-gray-200 px-2.5 py-1.5 text-xs font-medium text-gray-700 transition-colors hover:bg-gray-50 disabled:cursor-not-allowed disabled:opacity-50"
|
|
100
|
+
onClick={() => onAction(toggleAction)}
|
|
101
|
+
>
|
|
102
|
+
{toggleAction === 'pause' ? <Pause className="h-3.5 w-3.5" /> : <Play className="h-3.5 w-3.5" />}
|
|
103
|
+
{isPending ? t('chatWorkspaceContinuousAttentionUpdating') : toggleLabel}
|
|
104
|
+
</button>
|
|
105
|
+
) : null}
|
|
106
|
+
<button
|
|
107
|
+
type="button"
|
|
108
|
+
data-testid={`observation-${item.id}-remove`}
|
|
109
|
+
disabled={isPending}
|
|
110
|
+
className="inline-flex items-center gap-1.5 rounded-md border border-rose-200 px-2.5 py-1.5 text-xs font-medium text-rose-700 transition-colors hover:bg-rose-50 disabled:cursor-not-allowed disabled:opacity-50"
|
|
111
|
+
onClick={() => onAction('remove')}
|
|
112
|
+
>
|
|
113
|
+
<Trash2 className="h-3.5 w-3.5" />
|
|
114
|
+
{t('chatWorkspaceContinuousAttentionRemove')}
|
|
115
|
+
</button>
|
|
116
|
+
</div>
|
|
117
|
+
</article>
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export function ChatSessionContinuousAttention({ sessionKey }: { sessionKey: string | null }) {
|
|
122
|
+
const [activeGroup, setActiveGroup] = useState<AttentionGroup>('context');
|
|
123
|
+
const [actionError, setActionError] = useState(false);
|
|
124
|
+
const query = useNcpSessionObservations(sessionKey);
|
|
125
|
+
const action = useNcpObservationAction(sessionKey);
|
|
126
|
+
const { confirm, ConfirmDialog } = useConfirmDialog();
|
|
127
|
+
|
|
128
|
+
if (!sessionKey) return null;
|
|
129
|
+
|
|
130
|
+
const view = query.data;
|
|
131
|
+
const items = activeGroup === 'context' ? (view?.bindings ?? []) : (view?.subscriptions ?? []);
|
|
132
|
+
const runAction = async (item: NcpSessionObservationView, nextAction: NcpSessionObservationAction) => {
|
|
133
|
+
if (nextAction === 'remove') {
|
|
134
|
+
const confirmed = await confirm({
|
|
135
|
+
title: t('chatWorkspaceContinuousAttentionRemoveTitle'),
|
|
136
|
+
description: t('chatWorkspaceContinuousAttentionRemoveDescription'),
|
|
137
|
+
confirmLabel: t('chatWorkspaceContinuousAttentionRemove'),
|
|
138
|
+
variant: 'destructive',
|
|
139
|
+
});
|
|
140
|
+
if (!confirmed) return;
|
|
141
|
+
}
|
|
142
|
+
setActionError(false);
|
|
143
|
+
try {
|
|
144
|
+
await action.mutateAsync({ kind: item.kind, id: item.id, action: nextAction });
|
|
145
|
+
} catch {
|
|
146
|
+
setActionError(true);
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
return (
|
|
151
|
+
<div className="h-full overflow-auto bg-gray-50/45 px-4 py-5 custom-scrollbar">
|
|
152
|
+
<div className="mx-auto max-w-xl">
|
|
153
|
+
<ConfirmDialog />
|
|
154
|
+
<div className="flex items-start gap-3">
|
|
155
|
+
<span className="inline-flex h-9 w-9 shrink-0 items-center justify-center rounded-lg bg-primary/10 text-primary">
|
|
156
|
+
<Eye className="h-4 w-4" />
|
|
157
|
+
</span>
|
|
158
|
+
<div className="min-w-0">
|
|
159
|
+
<h2 className="text-base font-semibold text-gray-900">{t('chatWorkspaceContinuousAttention')}</h2>
|
|
160
|
+
<p className="mt-1 break-all text-xs leading-5 text-gray-500">{t('chatWorkspaceContinuousAttentionDescription')} · {sessionKey}</p>
|
|
161
|
+
</div>
|
|
162
|
+
</div>
|
|
163
|
+
|
|
164
|
+
{view ? (
|
|
165
|
+
<div className="mt-4 grid grid-cols-2 gap-2 sm:grid-cols-4">
|
|
166
|
+
<SummaryCard label={t('chatWorkspaceContinuousAttentionTotal')} value={view.counts.total} />
|
|
167
|
+
<SummaryCard label={t('chatWorkspaceContinuousAttentionState')} value={view.counts.context} />
|
|
168
|
+
<SummaryCard label={t('chatWorkspaceContinuousAttentionEvents')} value={view.counts.events} />
|
|
169
|
+
<SummaryCard label={t('chatWorkspaceContinuousAttentionNeedsAttention')} value={view.counts.needsAttention} />
|
|
170
|
+
</div>
|
|
171
|
+
) : null}
|
|
172
|
+
|
|
173
|
+
<div className="mt-4 flex rounded-lg border border-gray-200 bg-white p-1" role="tablist">
|
|
174
|
+
{(['context', 'events'] as const).map((group) => {
|
|
175
|
+
const count = group === 'context' ? (view?.counts.context ?? 0) : (view?.counts.events ?? 0);
|
|
176
|
+
return (
|
|
177
|
+
<button
|
|
178
|
+
key={group}
|
|
179
|
+
type="button"
|
|
180
|
+
role="tab"
|
|
181
|
+
aria-selected={activeGroup === group}
|
|
182
|
+
className={cn('flex-1 rounded-md px-3 py-2 text-xs font-medium transition-colors', activeGroup === group ? 'bg-gray-100 text-gray-900' : 'text-gray-500 hover:text-gray-700')}
|
|
183
|
+
onClick={() => setActiveGroup(group)}
|
|
184
|
+
>
|
|
185
|
+
{getGroupLabel(group)} <span className="ml-1 tabular-nums text-gray-400">{count}</span>
|
|
186
|
+
</button>
|
|
187
|
+
);
|
|
188
|
+
})}
|
|
189
|
+
</div>
|
|
190
|
+
{actionError ? <p className="mt-2 text-xs text-rose-600">{t('chatWorkspaceContinuousAttentionActionFailed')}</p> : null}
|
|
191
|
+
|
|
192
|
+
{query.isPending ? (
|
|
193
|
+
<div className="mt-3 space-y-2" aria-label={t('chatWorkspaceContinuousAttentionLoading')}>
|
|
194
|
+
{[0, 1].map((item) => <div key={item} className="h-28 animate-pulse rounded-xl border border-gray-200 bg-white" />)}
|
|
195
|
+
</div>
|
|
196
|
+
) : query.isError ? (
|
|
197
|
+
<div className="mt-4 rounded-xl border border-rose-200 bg-rose-50 px-4 py-5 text-center">
|
|
198
|
+
<p className="text-sm font-medium text-rose-800">{t('chatWorkspaceContinuousAttentionLoadFailed')}</p>
|
|
199
|
+
<button type="button" className="mt-3 inline-flex items-center gap-1.5 rounded-md border border-rose-200 bg-white px-3 py-1.5 text-xs font-medium text-rose-700" onClick={() => void query.refetch()}>
|
|
200
|
+
<RefreshCw className="h-3.5 w-3.5" />
|
|
201
|
+
{t('chatWorkspaceContinuousAttentionRetry')}
|
|
202
|
+
</button>
|
|
203
|
+
</div>
|
|
204
|
+
) : items.length === 0 ? (
|
|
205
|
+
<div className="mt-4 rounded-xl border border-dashed border-gray-300 bg-white px-4 py-8 text-center">
|
|
206
|
+
<Clock3 className="mx-auto h-5 w-5 text-gray-300" />
|
|
207
|
+
<p className="mt-2 text-sm font-medium text-gray-700">{t('chatWorkspaceContinuousAttentionEmpty')}</p>
|
|
208
|
+
<p className="mt-1 text-xs leading-5 text-gray-500">{t('chatWorkspaceContinuousAttentionEmptyDescription')}</p>
|
|
209
|
+
</div>
|
|
210
|
+
) : (
|
|
211
|
+
<div className="mt-3 space-y-2">
|
|
212
|
+
{items.map((item) => (
|
|
213
|
+
<ObservationRow
|
|
214
|
+
key={`${item.kind}:${item.id}`}
|
|
215
|
+
item={item}
|
|
216
|
+
isPending={action.isPending && action.variables?.id === item.id}
|
|
217
|
+
onAction={(nextAction) => void runAction(item, nextAction)}
|
|
218
|
+
/>
|
|
219
|
+
))}
|
|
220
|
+
</div>
|
|
221
|
+
)}
|
|
222
|
+
</div>
|
|
223
|
+
</div>
|
|
224
|
+
);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
function SummaryCard({ label, value }: { label: string; value: number }) {
|
|
228
|
+
return (
|
|
229
|
+
<div className="rounded-lg border border-gray-200/80 bg-white px-3 py-2">
|
|
230
|
+
<div className="text-[10px] uppercase tracking-wide text-gray-400">{label}</div>
|
|
231
|
+
<div className="mt-1 text-lg font-semibold tabular-nums text-gray-900">{value}</div>
|
|
232
|
+
</div>
|
|
233
|
+
);
|
|
234
|
+
}
|
|
@@ -221,6 +221,7 @@ describe("fixed workspace tabs", () => {
|
|
|
221
221
|
"overview",
|
|
222
222
|
"child-sessions",
|
|
223
223
|
"cron:session",
|
|
224
|
+
"continuous-attention",
|
|
224
225
|
"project-files",
|
|
225
226
|
]);
|
|
226
227
|
});
|
|
@@ -249,10 +250,10 @@ describe("fixed workspace tabs", () => {
|
|
|
249
250
|
expect(
|
|
250
251
|
tabs
|
|
251
252
|
.filter((tab) =>
|
|
252
|
-
["child-sessions", "cron", "project-files"].includes(tab.kind),
|
|
253
|
+
["child-sessions", "cron", "continuous-attention", "project-files"].includes(tab.kind),
|
|
253
254
|
)
|
|
254
255
|
.map((tab) => tab.title),
|
|
255
|
-
).toEqual(["子会话", "定时任务", "项目文件"]);
|
|
256
|
+
).toEqual(["子会话", "定时任务", "持续关注", "项目文件"]);
|
|
256
257
|
});
|
|
257
258
|
});
|
|
258
259
|
|
|
@@ -284,7 +285,7 @@ describe("buildWorkspaceTabsViewModel", () => {
|
|
|
284
285
|
onSelectCronJobs: vi.fn(),
|
|
285
286
|
});
|
|
286
287
|
|
|
287
|
-
expect(tabs[
|
|
288
|
+
expect(tabs[5]).toMatchObject({
|
|
288
289
|
key: "child:child-1",
|
|
289
290
|
kind: "child-session",
|
|
290
291
|
title: "Child session",
|
|
@@ -292,7 +293,7 @@ describe("buildWorkspaceTabsViewModel", () => {
|
|
|
292
293
|
showUnreadDot: true,
|
|
293
294
|
});
|
|
294
295
|
|
|
295
|
-
tabs[
|
|
296
|
+
tabs[5]?.onSelect();
|
|
296
297
|
expect(onSelectSession).toHaveBeenCalledWith("child-1");
|
|
297
298
|
});
|
|
298
299
|
|
|
@@ -328,11 +329,12 @@ describe("buildWorkspaceTabsViewModel", () => {
|
|
|
328
329
|
"overview",
|
|
329
330
|
"child-sessions",
|
|
330
331
|
"cron:session",
|
|
332
|
+
"continuous-attention",
|
|
331
333
|
"project-files",
|
|
332
334
|
"side-chat-draft:draft-1",
|
|
333
335
|
"child:child-1",
|
|
334
336
|
]);
|
|
335
|
-
expect(tabs[
|
|
337
|
+
expect(tabs[5]).toMatchObject({
|
|
336
338
|
kind: "side-chat-draft",
|
|
337
339
|
active: true,
|
|
338
340
|
});
|
|
@@ -378,7 +380,7 @@ describe("buildWorkspaceTabsViewModel", () => {
|
|
|
378
380
|
onSelectCronJobs: vi.fn(),
|
|
379
381
|
});
|
|
380
382
|
|
|
381
|
-
expect(tabs.slice(
|
|
383
|
+
expect(tabs.slice(5)).toEqual([
|
|
382
384
|
expect.objectContaining({
|
|
383
385
|
key: "file:parent::preview::demo.html",
|
|
384
386
|
active: true,
|
|
@@ -401,7 +403,7 @@ describe("buildWorkspaceTabsViewModel", () => {
|
|
|
401
403
|
}),
|
|
402
404
|
}),
|
|
403
405
|
]);
|
|
404
|
-
tabs[
|
|
406
|
+
tabs[5]?.alternateViewerAction?.onSelect();
|
|
405
407
|
expect(onOpenFileViewer).toHaveBeenCalledWith(
|
|
406
408
|
"parent::preview::demo.html",
|
|
407
409
|
"rendered",
|
|
@@ -21,7 +21,8 @@ export function areWorkspaceNavigationEntriesEqual(
|
|
|
21
21
|
current.kind === 'overview' ||
|
|
22
22
|
current.kind === 'child-sessions' ||
|
|
23
23
|
current.kind === 'project-files' ||
|
|
24
|
-
current.kind === 'cron'
|
|
24
|
+
current.kind === 'cron' ||
|
|
25
|
+
current.kind === 'continuous-attention'
|
|
25
26
|
) {
|
|
26
27
|
return true;
|
|
27
28
|
}
|
|
@@ -30,6 +31,7 @@ export function areWorkspaceNavigationEntriesEqual(
|
|
|
30
31
|
next.kind !== 'child-sessions' &&
|
|
31
32
|
next.kind !== 'project-files' &&
|
|
32
33
|
next.kind !== 'cron' &&
|
|
34
|
+
next.kind !== 'continuous-attention' &&
|
|
33
35
|
current.key === next.key
|
|
34
36
|
);
|
|
35
37
|
}
|
|
@@ -50,7 +52,8 @@ export function createWorkspaceNavigationEntryFromSnapshot(
|
|
|
50
52
|
activeWorkspacePanelKind === 'overview' ||
|
|
51
53
|
activeWorkspacePanelKind === 'child-sessions' ||
|
|
52
54
|
activeWorkspacePanelKind === 'project-files' ||
|
|
53
|
-
activeWorkspacePanelKind === 'cron'
|
|
55
|
+
activeWorkspacePanelKind === 'cron' ||
|
|
56
|
+
activeWorkspacePanelKind === 'continuous-attention'
|
|
54
57
|
) {
|
|
55
58
|
return { kind: activeWorkspacePanelKind };
|
|
56
59
|
}
|
|
@@ -72,7 +75,8 @@ export function createWorkspaceSelectionPatch(
|
|
|
72
75
|
if (
|
|
73
76
|
entry.kind === 'overview' ||
|
|
74
77
|
entry.kind === 'child-sessions' ||
|
|
75
|
-
entry.kind === 'project-files'
|
|
78
|
+
entry.kind === 'project-files' ||
|
|
79
|
+
entry.kind === 'continuous-attention'
|
|
76
80
|
) {
|
|
77
81
|
return {
|
|
78
82
|
activeWorkspacePanelKind: entry.kind,
|
|
@@ -128,7 +132,8 @@ export function closeWorkspaceTabSnapshot(
|
|
|
128
132
|
entry.kind === 'overview' ||
|
|
129
133
|
entry.kind === 'child-sessions' ||
|
|
130
134
|
entry.kind === 'cron' ||
|
|
131
|
-
entry.kind === 'project-files'
|
|
135
|
+
entry.kind === 'project-files' ||
|
|
136
|
+
entry.kind === 'continuous-attention'
|
|
132
137
|
) {
|
|
133
138
|
return null;
|
|
134
139
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ResolvedChildSessionTab } from "@/features/chat/features/ncp/hooks/use-ncp-child-session-tabs-view";
|
|
2
|
+
import type { ContextMenuGroup } from "@/shared/components/ui/context-menu/context-menu";
|
|
2
3
|
import { shouldShowUnreadSessionIndicator } from "@/features/chat/stores/chat-session-list.store";
|
|
3
4
|
import type {
|
|
4
5
|
ChatWorkspaceNavigationEntry,
|
|
@@ -39,6 +40,9 @@ export type WorkspaceSelection =
|
|
|
39
40
|
}
|
|
40
41
|
| {
|
|
41
42
|
kind: "cron";
|
|
43
|
+
}
|
|
44
|
+
| {
|
|
45
|
+
kind: "continuous-attention";
|
|
42
46
|
};
|
|
43
47
|
|
|
44
48
|
export type WorkspaceTabViewModel = {
|
|
@@ -48,6 +52,7 @@ export type WorkspaceTabViewModel = {
|
|
|
48
52
|
tooltip: string;
|
|
49
53
|
active: boolean;
|
|
50
54
|
agentId?: string | null;
|
|
55
|
+
sessionKey?: string | null;
|
|
51
56
|
fileName?: string | null;
|
|
52
57
|
showUnreadDot?: boolean;
|
|
53
58
|
viewMode?: "preview" | "diff";
|
|
@@ -60,6 +65,8 @@ export type WorkspaceTabViewModel = {
|
|
|
60
65
|
onAddToChat?: () => void;
|
|
61
66
|
onSelect: () => void;
|
|
62
67
|
onClose?: () => void;
|
|
68
|
+
menuLabel?: string;
|
|
69
|
+
menuGroups?: readonly ContextMenuGroup[];
|
|
63
70
|
};
|
|
64
71
|
|
|
65
72
|
export function readWorkspaceFileTitle(file: ChatWorkspaceFileTab): string {
|
|
@@ -100,6 +107,10 @@ export function resolveWorkspaceSelection(params: {
|
|
|
100
107
|
return { kind: "cron" };
|
|
101
108
|
}
|
|
102
109
|
|
|
110
|
+
if (activePanelKind === "continuous-attention") {
|
|
111
|
+
return { kind: "continuous-attention" };
|
|
112
|
+
}
|
|
113
|
+
|
|
103
114
|
if (activePanelKind === "side-chat-draft" && activeSideChatDraft) {
|
|
104
115
|
return {
|
|
105
116
|
kind: "side-chat-draft",
|
|
@@ -173,6 +184,7 @@ type WorkspaceTabsViewModelParams = {
|
|
|
173
184
|
onSelectChildSessions: () => void;
|
|
174
185
|
onSelectProjectFiles: () => void;
|
|
175
186
|
onSelectCronJobs: () => void;
|
|
187
|
+
onSelectContinuousAttention?: () => void;
|
|
176
188
|
};
|
|
177
189
|
|
|
178
190
|
function buildWorkspacePageTabs({
|
|
@@ -182,6 +194,7 @@ function buildWorkspacePageTabs({
|
|
|
182
194
|
onSelectCronJobs,
|
|
183
195
|
onSelectOverview,
|
|
184
196
|
onSelectProjectFiles,
|
|
197
|
+
onSelectContinuousAttention,
|
|
185
198
|
}: Pick<
|
|
186
199
|
WorkspaceTabsViewModelParams,
|
|
187
200
|
| "activeSelection"
|
|
@@ -190,6 +203,7 @@ function buildWorkspacePageTabs({
|
|
|
190
203
|
| "onSelectCronJobs"
|
|
191
204
|
| "onSelectOverview"
|
|
192
205
|
| "onSelectProjectFiles"
|
|
206
|
+
| "onSelectContinuousAttention"
|
|
193
207
|
>): WorkspaceTabViewModel[] {
|
|
194
208
|
const pageTabs: WorkspaceTabViewModel[] = [
|
|
195
209
|
{
|
|
@@ -216,6 +230,14 @@ function buildWorkspacePageTabs({
|
|
|
216
230
|
active: activeSelection?.kind === "cron",
|
|
217
231
|
onSelect: onSelectCronJobs,
|
|
218
232
|
},
|
|
233
|
+
{
|
|
234
|
+
key: "continuous-attention",
|
|
235
|
+
kind: "continuous-attention",
|
|
236
|
+
title: t("chatWorkspaceContinuousAttention"),
|
|
237
|
+
tooltip: t("chatWorkspaceContinuousAttention"),
|
|
238
|
+
active: activeSelection?.kind === "continuous-attention",
|
|
239
|
+
onSelect: onSelectContinuousAttention ?? (() => undefined),
|
|
240
|
+
},
|
|
219
241
|
{
|
|
220
242
|
key: "project-files",
|
|
221
243
|
kind: "project-files",
|
|
@@ -251,6 +273,7 @@ export function buildWorkspaceTabsViewModel(
|
|
|
251
273
|
onSelectChildSessions,
|
|
252
274
|
onSelectProjectFiles,
|
|
253
275
|
onSelectCronJobs,
|
|
276
|
+
onSelectContinuousAttention = () => undefined,
|
|
254
277
|
} = params;
|
|
255
278
|
|
|
256
279
|
const workspacePages = buildWorkspacePageTabs({
|
|
@@ -260,6 +283,7 @@ export function buildWorkspaceTabsViewModel(
|
|
|
260
283
|
onSelectCronJobs,
|
|
261
284
|
onSelectOverview,
|
|
262
285
|
onSelectProjectFiles,
|
|
286
|
+
onSelectContinuousAttention,
|
|
263
287
|
});
|
|
264
288
|
|
|
265
289
|
const sideChatDraftTabs = activeSideChatDraft
|
|
@@ -304,6 +328,7 @@ export function buildWorkspaceTabsViewModel(
|
|
|
304
328
|
title: tab.title,
|
|
305
329
|
tooltip: tab.title,
|
|
306
330
|
agentId: tab.agentId,
|
|
331
|
+
sessionKey: tab.sessionKey,
|
|
307
332
|
active:
|
|
308
333
|
activeSelection?.kind === "child-session" &&
|
|
309
334
|
activeSelection.tab.sessionKey === tab.sessionKey,
|
|
@@ -174,7 +174,7 @@ export class ChatThreadManager {
|
|
|
174
174
|
|
|
175
175
|
private openWorkspacePage = (
|
|
176
176
|
rawParentSessionKey: string | null,
|
|
177
|
-
kind: 'overview' | 'child-sessions' | 'project-files' | 'cron',
|
|
177
|
+
kind: 'overview' | 'child-sessions' | 'project-files' | 'cron' | 'continuous-attention',
|
|
178
178
|
) => {
|
|
179
179
|
const parentSessionKey = rawParentSessionKey?.trim() || null;
|
|
180
180
|
if (!parentSessionKey && kind !== 'project-files') {
|
|
@@ -234,13 +234,11 @@ export class ChatThreadManager {
|
|
|
234
234
|
if (snapshot) useChatThreadStore.getState().setSnapshot(snapshot);
|
|
235
235
|
};
|
|
236
236
|
|
|
237
|
-
openChildSessions = (sessionKey: string) =>
|
|
238
|
-
this.openWorkspacePage(sessionKey, 'child-sessions');
|
|
239
|
-
};
|
|
237
|
+
openChildSessions = (sessionKey: string) => this.openWorkspacePage(sessionKey, 'child-sessions');
|
|
240
238
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
239
|
+
openContinuousAttention = (sessionKey: string) => this.openWorkspacePage(sessionKey, 'continuous-attention');
|
|
240
|
+
|
|
241
|
+
openProjectFiles = (sessionKey: string | null) => this.openWorkspacePage(sessionKey, 'project-files');
|
|
244
242
|
|
|
245
243
|
materializeRootDraftSession = (rawSessionKey: string) => {
|
|
246
244
|
const sessionKey = rawSessionKey.trim();
|
|
@@ -57,7 +57,8 @@ export type ChatWorkspacePanelKind =
|
|
|
57
57
|
| 'side-chat-draft'
|
|
58
58
|
| 'project-files'
|
|
59
59
|
| 'file'
|
|
60
|
-
| 'cron'
|
|
60
|
+
| 'cron'
|
|
61
|
+
| 'continuous-attention';
|
|
61
62
|
|
|
62
63
|
export type ChatWorkspaceNavigationEntry =
|
|
63
64
|
| { kind: 'overview' }
|
|
@@ -66,7 +67,8 @@ export type ChatWorkspaceNavigationEntry =
|
|
|
66
67
|
| { kind: 'side-chat-draft'; key: string }
|
|
67
68
|
| { kind: 'project-files' }
|
|
68
69
|
| { kind: 'file'; key: string }
|
|
69
|
-
| { kind: 'cron' }
|
|
70
|
+
| { kind: 'cron' }
|
|
71
|
+
| { kind: 'continuous-attention' };
|
|
70
72
|
|
|
71
73
|
export type ChatThreadSnapshot = {
|
|
72
74
|
sessionTypeLabel?: string | null;
|
|
@@ -102,7 +104,7 @@ export type ChatThreadSnapshot = {
|
|
|
102
104
|
};
|
|
103
105
|
|
|
104
106
|
const CHAT_THREAD_WORKSPACE_STORAGE_KEY = 'nextclaw.chat.workspace-panel.state';
|
|
105
|
-
const CHAT_THREAD_WORKSPACE_STORAGE_VERSION =
|
|
107
|
+
const CHAT_THREAD_WORKSPACE_STORAGE_VERSION = 3;
|
|
106
108
|
const CHAT_THREAD_MAX_PERSISTED_WORKSPACE_FILE_TABS = 8;
|
|
107
109
|
|
|
108
110
|
type ChatThreadStore = {
|
|
@@ -207,7 +209,8 @@ function normalizePersistedWorkspaceNavigationEntry(value: unknown): ChatWorkspa
|
|
|
207
209
|
value.kind === 'overview' ||
|
|
208
210
|
value.kind === 'child-sessions' ||
|
|
209
211
|
value.kind === 'project-files' ||
|
|
210
|
-
value.kind === 'cron'
|
|
212
|
+
value.kind === 'cron' ||
|
|
213
|
+
value.kind === 'continuous-attention'
|
|
211
214
|
) {
|
|
212
215
|
return { kind: value.kind };
|
|
213
216
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { useQuery } from '@tanstack/react-query';
|
|
2
|
+
import { fetchExtensionCatalog } from '@/shared/lib/api';
|
|
3
|
+
|
|
4
|
+
export function useExtensions() {
|
|
5
|
+
return useQuery({
|
|
6
|
+
queryKey: ['extension-catalog'],
|
|
7
|
+
queryFn: fetchExtensionCatalog,
|
|
8
|
+
staleTime: 5_000,
|
|
9
|
+
refetchOnWindowFocus: true,
|
|
10
|
+
});
|
|
11
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { ExtensionsConfigPage } from "./pages/extensions-config-page";
|