@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
|
@@ -48,14 +48,19 @@ export function useSessionRunQueue(sessionKey: string | null) {
|
|
|
48
48
|
);
|
|
49
49
|
}, [normalizedSessionKey]);
|
|
50
50
|
|
|
51
|
-
const
|
|
51
|
+
const refreshPendingInputs = useCallback(async (): Promise<readonly UiNcpSessionPendingInputView[]> => {
|
|
52
52
|
if (!normalizedSessionKey) {
|
|
53
53
|
return [];
|
|
54
54
|
}
|
|
55
55
|
const result = await refetch();
|
|
56
|
-
return result.data?.inputs
|
|
56
|
+
return result.data?.inputs ?? [];
|
|
57
57
|
}, [normalizedSessionKey, refetch]);
|
|
58
58
|
|
|
59
|
+
const refreshQueuedInputs = useCallback(async (): Promise<readonly UiNcpSessionQueuedInputView[]> => {
|
|
60
|
+
const inputs = await refreshPendingInputs();
|
|
61
|
+
return inputs.filter(({ placement }) => placement === 'queued');
|
|
62
|
+
}, [refreshPendingInputs]);
|
|
63
|
+
|
|
59
64
|
const steerQueuedInput = useCallback(async (
|
|
60
65
|
queuedInputId: string,
|
|
61
66
|
): Promise<UiNcpSessionPendingInputView | null> => {
|
|
@@ -69,6 +74,7 @@ export function useSessionRunQueue(sessionKey: string | null) {
|
|
|
69
74
|
inputs: inputs.filter(({ placement }) => placement === 'queued'),
|
|
70
75
|
pendingInputs: inputs,
|
|
71
76
|
isLoading,
|
|
77
|
+
refreshPendingInputs,
|
|
72
78
|
refreshQueuedInputs,
|
|
73
79
|
removeQueuedInput,
|
|
74
80
|
steerQueuedInput,
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { render, screen } from "@testing-library/react";
|
|
2
|
+
import { expect, it, vi } from "vitest";
|
|
3
|
+
import { ChatMessageObservationEvent } from "@/features/chat/features/message/components/chat-message-observation-event";
|
|
4
|
+
|
|
5
|
+
vi.mock("@/app/components/i18n-provider", () => ({
|
|
6
|
+
useI18n: () => ({ language: "en" }),
|
|
7
|
+
}));
|
|
8
|
+
|
|
9
|
+
vi.mock("@/shared/lib/i18n", () => ({
|
|
10
|
+
formatDateTime: (value: string) => `formatted:${value}`,
|
|
11
|
+
t: (key: string) => key,
|
|
12
|
+
}));
|
|
13
|
+
|
|
14
|
+
it("shows the event identity and keeps the payload behind an expandable detail", () => {
|
|
15
|
+
render(
|
|
16
|
+
<ChatMessageObservationEvent
|
|
17
|
+
event={{
|
|
18
|
+
deliveryId: "delivery-1",
|
|
19
|
+
extensionId: "calendar-extension",
|
|
20
|
+
eventId: "event-1",
|
|
21
|
+
eventType: "calendar.event.created",
|
|
22
|
+
occurredAt: "2026-08-23T10:00:00.000Z",
|
|
23
|
+
payload: { title: "Planning" },
|
|
24
|
+
}}
|
|
25
|
+
/>,
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
expect(screen.getByTestId("chat-observation-event")).toBeTruthy();
|
|
29
|
+
expect(screen.getAllByText("calendar.event.created")).toHaveLength(2);
|
|
30
|
+
expect(screen.getByText(/calendar-extension/)).toBeTruthy();
|
|
31
|
+
const eventDetails = screen.getByTestId(
|
|
32
|
+
"chat-observation-event",
|
|
33
|
+
) as HTMLDetailsElement;
|
|
34
|
+
expect(eventDetails.querySelector("summary")).toBeTruthy();
|
|
35
|
+
expect(eventDetails.open).toBe(false);
|
|
36
|
+
expect(screen.getByText(/event-1/)).toBeTruthy();
|
|
37
|
+
expect(screen.getByText(/Planning/)).toBeTruthy();
|
|
38
|
+
expect(screen.getByText("chatObservationEventDetailsTitle")).toBeTruthy();
|
|
39
|
+
expect(screen.getByText("chatObservationEventPayloadLabel")).toBeTruthy();
|
|
40
|
+
|
|
41
|
+
expect(eventDetails.className).toContain("my-3");
|
|
42
|
+
expect(eventDetails.querySelector("summary")?.textContent).toContain(
|
|
43
|
+
"calendar.event.created",
|
|
44
|
+
);
|
|
45
|
+
expect(eventDetails.className).not.toContain("amber");
|
|
46
|
+
});
|
|
@@ -64,6 +64,11 @@ import { buildServerPathContentUrl } from "@/shared/lib/api";
|
|
|
64
64
|
import { formatDateTime, formatNumber, t } from "@/shared/lib/i18n";
|
|
65
65
|
import { cn } from "@/shared/lib/utils";
|
|
66
66
|
import type { SessionMessageToolPayloadState } from "@/features/chat/features/ncp/hooks/use-ncp-session-message-history";
|
|
67
|
+
import { ChatMessageObservationEvent } from "@/features/chat/features/message/components/chat-message-observation-event";
|
|
68
|
+
import {
|
|
69
|
+
isObservationEventPartExtensionType,
|
|
70
|
+
readObservationEventPartData,
|
|
71
|
+
} from "@/features/chat/features/message/utils/chat-message-observation-event.utils";
|
|
67
72
|
|
|
68
73
|
type ChatMessageListContainerProps = {
|
|
69
74
|
canContinue?: boolean;
|
|
@@ -371,6 +376,10 @@ export function ChatMessageListContainer({
|
|
|
371
376
|
}, []);
|
|
372
377
|
const renderCustomPart = useCallback(
|
|
373
378
|
(part: Extract<ChatMessageViewModel["parts"][number], { type: "custom" }>) => {
|
|
379
|
+
if (isObservationEventPartExtensionType(part.customType)) {
|
|
380
|
+
const event = readObservationEventPartData(part.data);
|
|
381
|
+
return event ? <ChatMessageObservationEvent event={event} /> : undefined;
|
|
382
|
+
}
|
|
374
383
|
if (part.customType !== CONTEXT_COMPACTION_PART_EXTENSION_TYPE) {
|
|
375
384
|
return undefined;
|
|
376
385
|
}
|
|
@@ -411,6 +420,8 @@ export function ChatMessageListContainer({
|
|
|
411
420
|
<ChatContextCompactionDivider checkpoint={item.checkpoint} />
|
|
412
421
|
) : item.kind === "context-inheritance" ? (
|
|
413
422
|
<ChatContextInheritanceDivider inheritance={item.inheritance} />
|
|
423
|
+
) : item.kind === "observation-event" ? (
|
|
424
|
+
<ChatMessageObservationEvent event={item.event} />
|
|
414
425
|
) : (
|
|
415
426
|
<div className={item.kind === "message" ? "pb-5" : undefined}>
|
|
416
427
|
<ChatMessageList
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { ChevronDown } from "lucide-react";
|
|
2
|
+
import { formatDateTime, t } from "@/shared/lib/i18n";
|
|
3
|
+
import { useI18n } from "@/app/components/i18n-provider";
|
|
4
|
+
import {
|
|
5
|
+
stringifyObservationEventPayload,
|
|
6
|
+
type ObservationEventPartData,
|
|
7
|
+
} from "@/features/chat/features/message/utils/chat-message-observation-event.utils";
|
|
8
|
+
|
|
9
|
+
type ChatMessageObservationEventProps = {
|
|
10
|
+
event: ObservationEventPartData;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export function ChatMessageObservationEvent({
|
|
14
|
+
event,
|
|
15
|
+
}: ChatMessageObservationEventProps) {
|
|
16
|
+
const { language } = useI18n();
|
|
17
|
+
const payload = stringifyObservationEventPayload(event.payload);
|
|
18
|
+
|
|
19
|
+
return (
|
|
20
|
+
<details
|
|
21
|
+
aria-label={t("chatObservationEventLabel", language)}
|
|
22
|
+
data-testid="chat-observation-event"
|
|
23
|
+
className="group my-3 min-w-0 text-[11px] text-muted-foreground"
|
|
24
|
+
>
|
|
25
|
+
<summary
|
|
26
|
+
aria-label={`${t("chatObservationEventLabel", language)}: ${event.eventType}. ${t("chatObservationEventShowDetails", language)}`}
|
|
27
|
+
className="flex cursor-pointer list-none items-center gap-3 rounded-lg outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 [&::-webkit-details-marker]:hidden"
|
|
28
|
+
>
|
|
29
|
+
<span className="h-px min-w-4 flex-1 bg-border/70" />
|
|
30
|
+
<span className="inline-flex min-w-0 max-w-[min(80%,32rem)] items-center gap-1.5 px-1 text-xs text-muted-foreground transition-colors hover:text-foreground">
|
|
31
|
+
<span
|
|
32
|
+
aria-hidden="true"
|
|
33
|
+
className="h-1.5 w-1.5 shrink-0 rounded-full bg-muted-foreground/50"
|
|
34
|
+
/>
|
|
35
|
+
<span className="shrink-0">
|
|
36
|
+
{t("chatObservationEventLabel", language)}
|
|
37
|
+
</span>
|
|
38
|
+
<span aria-hidden="true" className="text-muted-foreground/60">·</span>
|
|
39
|
+
<span className="min-w-0 truncate">
|
|
40
|
+
{event.eventType}
|
|
41
|
+
</span>
|
|
42
|
+
<ChevronDown
|
|
43
|
+
className="h-3.5 w-3.5 shrink-0 transition-transform group-open:rotate-180"
|
|
44
|
+
aria-hidden="true"
|
|
45
|
+
/>
|
|
46
|
+
</span>
|
|
47
|
+
<span className="h-px min-w-4 flex-1 bg-border/70" />
|
|
48
|
+
</summary>
|
|
49
|
+
<div className="mx-auto mt-3 max-w-2xl overflow-hidden rounded-xl border border-border/70 bg-card shadow-sm">
|
|
50
|
+
<div className="flex min-w-0 items-center gap-2 border-b border-border/60 bg-muted/35 px-3 py-2">
|
|
51
|
+
<span
|
|
52
|
+
aria-hidden="true"
|
|
53
|
+
className="h-1.5 w-1.5 shrink-0 rounded-full bg-muted-foreground/55"
|
|
54
|
+
/>
|
|
55
|
+
<span className="shrink-0 text-xs font-medium text-foreground/85">
|
|
56
|
+
{t("chatObservationEventDetailsTitle", language)}
|
|
57
|
+
</span>
|
|
58
|
+
<span aria-hidden="true" className="text-muted-foreground/50">·</span>
|
|
59
|
+
<span className="min-w-0 truncate text-[11px] text-muted-foreground">
|
|
60
|
+
{event.eventType}
|
|
61
|
+
</span>
|
|
62
|
+
</div>
|
|
63
|
+
<dl className="grid grid-cols-[max-content_minmax(0,1fr)] gap-x-4 gap-y-2 px-3 py-3 text-xs">
|
|
64
|
+
<dt className="text-muted-foreground">
|
|
65
|
+
{t("chatObservationEventExtension", language)}
|
|
66
|
+
</dt>
|
|
67
|
+
<dd className="min-w-0 truncate text-foreground/80">{event.extensionId}</dd>
|
|
68
|
+
<dt className="text-muted-foreground">
|
|
69
|
+
{t("chatObservationEventId", language)}
|
|
70
|
+
</dt>
|
|
71
|
+
<dd className="min-w-0 break-all font-mono text-[11px] text-foreground/75">
|
|
72
|
+
{event.eventId}
|
|
73
|
+
</dd>
|
|
74
|
+
<dt className="text-muted-foreground">{t("chatObservationEventTime", language)}</dt>
|
|
75
|
+
<dd className="text-foreground/80">
|
|
76
|
+
<time dateTime={event.occurredAt}>
|
|
77
|
+
{formatDateTime(event.occurredAt, language)}
|
|
78
|
+
</time>
|
|
79
|
+
</dd>
|
|
80
|
+
</dl>
|
|
81
|
+
<div className="border-t border-border/60 px-3 py-3">
|
|
82
|
+
<div className="mb-1.5 text-[11px] font-medium text-muted-foreground">
|
|
83
|
+
{t("chatObservationEventPayloadLabel", language)}
|
|
84
|
+
</div>
|
|
85
|
+
<pre className="max-h-64 overflow-auto whitespace-pre-wrap break-words rounded-lg bg-muted/55 px-3 py-2.5 text-[11px] leading-5 text-muted-foreground">
|
|
86
|
+
{payload || t("chatObservationEventPayloadEmpty", language)}
|
|
87
|
+
</pre>
|
|
88
|
+
</div>
|
|
89
|
+
</div>
|
|
90
|
+
</details>
|
|
91
|
+
);
|
|
92
|
+
}
|
|
@@ -90,6 +90,44 @@ describe("mid-run compaction timeline projection", () => {
|
|
|
90
90
|
}).map((item) => item.kind)).toEqual(["message"]);
|
|
91
91
|
});
|
|
92
92
|
|
|
93
|
+
it("keeps a deferred tool part in the coordinate space used by compaction", () => {
|
|
94
|
+
const activeAssistant = {
|
|
95
|
+
...visibleMessage,
|
|
96
|
+
status: "streaming" as const,
|
|
97
|
+
parts: [
|
|
98
|
+
{
|
|
99
|
+
type: "tool-invocation" as const,
|
|
100
|
+
toolCallId: "tool-visible",
|
|
101
|
+
toolName: "exec",
|
|
102
|
+
state: "result" as const,
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
type: "tool-invocation" as const,
|
|
106
|
+
toolCallId: "tool-deferred",
|
|
107
|
+
toolName: "read_file",
|
|
108
|
+
state: "result" as const,
|
|
109
|
+
payloadDeferred: true,
|
|
110
|
+
},
|
|
111
|
+
{ type: "text" as const, text: "after" },
|
|
112
|
+
],
|
|
113
|
+
};
|
|
114
|
+
const compactionMessage = createCompactionMessage({
|
|
115
|
+
assistantId: activeAssistant.id,
|
|
116
|
+
coveredPartCount: activeAssistant.parts.length,
|
|
117
|
+
id: "context-compaction-deferred-tool",
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
expect(projectVisibleChatMessages([
|
|
121
|
+
activeAssistant,
|
|
122
|
+
compactionMessage,
|
|
123
|
+
])[0]?.parts.map((part) => part.type)).toEqual([
|
|
124
|
+
"tool-invocation",
|
|
125
|
+
"tool-invocation",
|
|
126
|
+
"text",
|
|
127
|
+
"extension",
|
|
128
|
+
]);
|
|
129
|
+
});
|
|
130
|
+
|
|
93
131
|
it("keeps repeated compactions ordered inside one assistant message", () => {
|
|
94
132
|
const activeAssistant = {
|
|
95
133
|
...visibleMessage,
|
package/src/features/chat/features/message/utils/__tests__/chat-message-timeline.utils.test.ts
CHANGED
|
@@ -62,6 +62,58 @@ describe("chat message timeline visibility", () => {
|
|
|
62
62
|
]);
|
|
63
63
|
});
|
|
64
64
|
|
|
65
|
+
it("renders a standalone observation message at its timeline boundary", () => {
|
|
66
|
+
const observationMessage = {
|
|
67
|
+
...visibleMessage,
|
|
68
|
+
id: "observation-event-1",
|
|
69
|
+
role: "service" as const,
|
|
70
|
+
timestamp: "2026-08-07T00:01:00.000Z",
|
|
71
|
+
parts: [{
|
|
72
|
+
type: "extension" as const,
|
|
73
|
+
extensionType: "observation.event",
|
|
74
|
+
data: {
|
|
75
|
+
deliveryId: "delivery-1",
|
|
76
|
+
extensionId: "calendar-extension",
|
|
77
|
+
eventId: "event-1",
|
|
78
|
+
eventType: "calendar.event.created",
|
|
79
|
+
occurredAt: "2026-08-07T00:00:59.000Z",
|
|
80
|
+
payload: { title: "Planning" },
|
|
81
|
+
},
|
|
82
|
+
}],
|
|
83
|
+
} satisfies NcpMessage;
|
|
84
|
+
const afterMessage = {
|
|
85
|
+
...visibleMessage,
|
|
86
|
+
id: "assistant-after-observation",
|
|
87
|
+
timestamp: "2026-08-07T00:02:00.000Z",
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
expect(projectVisibleChatMessages([
|
|
91
|
+
visibleMessage,
|
|
92
|
+
observationMessage,
|
|
93
|
+
afterMessage,
|
|
94
|
+
]).map((message) => message.id)).toEqual([
|
|
95
|
+
visibleMessage.id,
|
|
96
|
+
afterMessage.id,
|
|
97
|
+
]);
|
|
98
|
+
const items = buildChatMessageTimelineItems({
|
|
99
|
+
rawMessages: [visibleMessage, observationMessage, afterMessage],
|
|
100
|
+
messages: [
|
|
101
|
+
{ id: visibleMessage.id } as never,
|
|
102
|
+
{ id: afterMessage.id } as never,
|
|
103
|
+
],
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
expect(items.map((item) => item.kind)).toEqual([
|
|
107
|
+
"message",
|
|
108
|
+
"observation-event",
|
|
109
|
+
"message",
|
|
110
|
+
]);
|
|
111
|
+
expect(items[1]).toMatchObject({
|
|
112
|
+
kind: "observation-event",
|
|
113
|
+
event: { eventId: "event-1" },
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
|
|
65
117
|
it("hides internal and legacy silent messages", () => {
|
|
66
118
|
expect(isVisibleChatMessage({
|
|
67
119
|
...visibleMessage,
|
|
@@ -116,6 +116,40 @@ it("maps context compaction extensions into stable process parts", () => {
|
|
|
116
116
|
}]);
|
|
117
117
|
});
|
|
118
118
|
|
|
119
|
+
it("maps observation event extensions into visible custom parts", () => {
|
|
120
|
+
const adapted = adapt([{
|
|
121
|
+
id: "observation-event-message-1",
|
|
122
|
+
role: "system",
|
|
123
|
+
parts: [{
|
|
124
|
+
type: "extension",
|
|
125
|
+
extensionType: "observation.event",
|
|
126
|
+
data: {
|
|
127
|
+
deliveryId: "delivery-1",
|
|
128
|
+
extensionId: "calendar-extension",
|
|
129
|
+
eventId: "event-1",
|
|
130
|
+
eventType: "calendar.event.created",
|
|
131
|
+
occurredAt: "2026-08-23T10:00:00.000Z",
|
|
132
|
+
payload: { title: "Planning" },
|
|
133
|
+
},
|
|
134
|
+
}],
|
|
135
|
+
}]);
|
|
136
|
+
|
|
137
|
+
expect(adapted[0]?.role).toBe("system");
|
|
138
|
+
expect(adapted[0]?.parts).toEqual([{
|
|
139
|
+
type: "custom",
|
|
140
|
+
id: "delivery-1",
|
|
141
|
+
customType: "observation.event",
|
|
142
|
+
data: {
|
|
143
|
+
deliveryId: "delivery-1",
|
|
144
|
+
extensionId: "calendar-extension",
|
|
145
|
+
eventId: "event-1",
|
|
146
|
+
eventType: "calendar.event.created",
|
|
147
|
+
occurredAt: "2026-08-23T10:00:00.000Z",
|
|
148
|
+
payload: { title: "Planning" },
|
|
149
|
+
},
|
|
150
|
+
}]);
|
|
151
|
+
});
|
|
152
|
+
|
|
119
153
|
it("maps tool lifecycle statuses into visible card state feedback", () => {
|
|
120
154
|
const adapted = adapt([
|
|
121
155
|
{
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { OBSERVATION_EVENT_EXTENSION_TYPE } from "@nextclaw/ncp";
|
|
2
|
+
|
|
3
|
+
export const OBSERVATION_EVENT_PART_EXTENSION_TYPE =
|
|
4
|
+
OBSERVATION_EVENT_EXTENSION_TYPE;
|
|
5
|
+
const LEGACY_OBSERVATION_EVENT_PART_EXTENSION_TYPE =
|
|
6
|
+
"nextclaw.observation.event";
|
|
7
|
+
const PREVIOUS_OBSERVATION_EVENT_PART_EXTENSION_TYPE =
|
|
8
|
+
"ncp.observation.event";
|
|
9
|
+
|
|
10
|
+
export function isObservationEventPartExtensionType(value: string): boolean {
|
|
11
|
+
return value === OBSERVATION_EVENT_PART_EXTENSION_TYPE ||
|
|
12
|
+
value === PREVIOUS_OBSERVATION_EVENT_PART_EXTENSION_TYPE ||
|
|
13
|
+
value === LEGACY_OBSERVATION_EVENT_PART_EXTENSION_TYPE;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export type ObservationEventPartData = {
|
|
17
|
+
deliveryId: string;
|
|
18
|
+
extensionId: string;
|
|
19
|
+
eventId: string;
|
|
20
|
+
eventType: string;
|
|
21
|
+
occurredAt: string;
|
|
22
|
+
payload: unknown;
|
|
23
|
+
sourceRefs?: unknown;
|
|
24
|
+
causationId?: string;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
28
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function readRequiredString(
|
|
32
|
+
record: Record<string, unknown>,
|
|
33
|
+
key: string,
|
|
34
|
+
): string | null {
|
|
35
|
+
const value = record[key];
|
|
36
|
+
return typeof value === "string" && value.trim() ? value.trim() : null;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function readObservationEventPartData(
|
|
40
|
+
value: unknown,
|
|
41
|
+
): ObservationEventPartData | null {
|
|
42
|
+
if (!isRecord(value)) return null;
|
|
43
|
+
const deliveryId = readRequiredString(value, "deliveryId");
|
|
44
|
+
const extensionId = readRequiredString(value, "extensionId");
|
|
45
|
+
const eventId = readRequiredString(value, "eventId");
|
|
46
|
+
const eventType = readRequiredString(value, "eventType");
|
|
47
|
+
const occurredAt = readRequiredString(value, "occurredAt");
|
|
48
|
+
if (!deliveryId || !extensionId || !eventId || !eventType || !occurredAt) {
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
return {
|
|
52
|
+
deliveryId,
|
|
53
|
+
extensionId,
|
|
54
|
+
eventId,
|
|
55
|
+
eventType,
|
|
56
|
+
occurredAt,
|
|
57
|
+
payload: value.payload,
|
|
58
|
+
...(value.sourceRefs !== undefined ? { sourceRefs: value.sourceRefs } : {}),
|
|
59
|
+
...(typeof value.causationId === "string" && value.causationId.trim()
|
|
60
|
+
? { causationId: value.causationId.trim() }
|
|
61
|
+
: {}),
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export function stringifyObservationEventPayload(
|
|
66
|
+
value: unknown,
|
|
67
|
+
maxChars = 6000,
|
|
68
|
+
): string {
|
|
69
|
+
let serialized: string;
|
|
70
|
+
if (typeof value === "string") {
|
|
71
|
+
serialized = value;
|
|
72
|
+
} else {
|
|
73
|
+
try {
|
|
74
|
+
serialized = JSON.stringify(value, null, 2) ?? "";
|
|
75
|
+
} catch {
|
|
76
|
+
serialized = String(value);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
if (serialized.length <= maxChars) return serialized;
|
|
80
|
+
return `${serialized.slice(0, Math.max(0, maxChars - 16))}\n…`;
|
|
81
|
+
}
|
|
@@ -27,6 +27,10 @@ import {
|
|
|
27
27
|
CONTEXT_COMPACTION_PART_EXTENSION_TYPE,
|
|
28
28
|
type ContextCompactionPartData,
|
|
29
29
|
} from "@/features/chat/features/message/utils/chat-message-timeline.utils";
|
|
30
|
+
import {
|
|
31
|
+
isObservationEventPartExtensionType,
|
|
32
|
+
readObservationEventPartData,
|
|
33
|
+
} from "@/features/chat/features/message/utils/chat-message-observation-event.utils";
|
|
30
34
|
|
|
31
35
|
export type {
|
|
32
36
|
ChatMessageAdapterTexts,
|
|
@@ -243,6 +247,16 @@ function isToolInvocationPart(
|
|
|
243
247
|
function buildExtensionPart(
|
|
244
248
|
part: Extract<ChatMessagePartSource, { type: "extension" }>,
|
|
245
249
|
): Extract<ChatMessagePartViewModel, { type: "custom" }> | null {
|
|
250
|
+
if (isObservationEventPartExtensionType(part.extensionType)) {
|
|
251
|
+
const data = readObservationEventPartData(part.data);
|
|
252
|
+
if (!data) return null;
|
|
253
|
+
return {
|
|
254
|
+
type: "custom",
|
|
255
|
+
id: data.deliveryId,
|
|
256
|
+
customType: part.extensionType,
|
|
257
|
+
data,
|
|
258
|
+
};
|
|
259
|
+
}
|
|
246
260
|
if (part.extensionType !== CONTEXT_COMPACTION_PART_EXTENSION_TYPE) {
|
|
247
261
|
return null;
|
|
248
262
|
}
|
|
@@ -288,7 +302,7 @@ export function adaptChatMessagePart(
|
|
|
288
302
|
return buildToolInvocationPart(part, texts);
|
|
289
303
|
}
|
|
290
304
|
if (isExtensionPart(part)) {
|
|
291
|
-
return buildExtensionPart(part);
|
|
305
|
+
return buildExtensionPart(part) ?? buildUnknownPart(part, texts);
|
|
292
306
|
}
|
|
293
307
|
return buildUnknownPart(part, texts);
|
|
294
308
|
}
|
|
@@ -8,6 +8,11 @@ import {
|
|
|
8
8
|
readContextCompactionTimeline,
|
|
9
9
|
type ContextCompactionTimelineView,
|
|
10
10
|
} from "@/features/chat/features/session/utils/ncp-session-context-metadata.utils";
|
|
11
|
+
import {
|
|
12
|
+
isObservationEventPartExtensionType,
|
|
13
|
+
readObservationEventPartData,
|
|
14
|
+
type ObservationEventPartData,
|
|
15
|
+
} from "@/features/chat/features/message/utils/chat-message-observation-event.utils";
|
|
11
16
|
|
|
12
17
|
const INHERITED_FROM_SESSION_METADATA_KEY = "inherited_from_session_id";
|
|
13
18
|
export const CONTEXT_COMPACTION_PART_EXTENSION_TYPE =
|
|
@@ -43,6 +48,11 @@ export type ChatTimelineItem =
|
|
|
43
48
|
key: string;
|
|
44
49
|
inheritance: ContextInheritanceTimelineView;
|
|
45
50
|
}
|
|
51
|
+
| {
|
|
52
|
+
kind: "observation-event";
|
|
53
|
+
key: string;
|
|
54
|
+
event: ObservationEventPartData;
|
|
55
|
+
}
|
|
46
56
|
| {
|
|
47
57
|
kind: "typing";
|
|
48
58
|
key: "typing";
|
|
@@ -57,6 +67,21 @@ function readInheritedSourceSessionId(message: NcpMessage): string | null {
|
|
|
57
67
|
return typeof value === "string" && value.trim() ? value.trim() : null;
|
|
58
68
|
}
|
|
59
69
|
|
|
70
|
+
function readStandaloneObservationEvent(
|
|
71
|
+
message: NcpMessage,
|
|
72
|
+
): ObservationEventPartData | null {
|
|
73
|
+
if (message.parts.length !== 1) return null;
|
|
74
|
+
const part = message.parts[0];
|
|
75
|
+
if (
|
|
76
|
+
!part ||
|
|
77
|
+
part.type !== "extension" ||
|
|
78
|
+
!isObservationEventPartExtensionType(part.extensionType)
|
|
79
|
+
) {
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
return readObservationEventPartData(part.data);
|
|
83
|
+
}
|
|
84
|
+
|
|
60
85
|
export function isVisibleChatMessage(message: NcpMessage): boolean {
|
|
61
86
|
return (
|
|
62
87
|
!isHiddenNcpMessage(message) &&
|
|
@@ -100,6 +125,13 @@ function mergeAssistantContinuation(
|
|
|
100
125
|
type VisibleChatMessageProjection = {
|
|
101
126
|
messages: NcpMessage[];
|
|
102
127
|
inlineCompactionMessageIds: Set<string>;
|
|
128
|
+
observationEvents: ObservationEventTimelinePlacement[];
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
type ObservationEventTimelinePlacement = {
|
|
132
|
+
boundaryIndex: number;
|
|
133
|
+
event: ObservationEventPartData;
|
|
134
|
+
messageId: string;
|
|
103
135
|
};
|
|
104
136
|
|
|
105
137
|
type ProjectedMessagePartAnchor = {
|
|
@@ -127,6 +159,7 @@ function projectVisibleChatMessageState(
|
|
|
127
159
|
);
|
|
128
160
|
const inlineCompactions: InlineCompactionPlacement[] = [];
|
|
129
161
|
const inlineCompactionMessageIds = new Set<string>();
|
|
162
|
+
const observationEvents: ObservationEventTimelinePlacement[] = [];
|
|
130
163
|
let pendingContinuationTargetId: string | null = null;
|
|
131
164
|
|
|
132
165
|
rawMessages.forEach((message, rawOrder) => {
|
|
@@ -166,6 +199,15 @@ function projectVisibleChatMessageState(
|
|
|
166
199
|
if (!isVisibleChatMessage(message)) {
|
|
167
200
|
return;
|
|
168
201
|
}
|
|
202
|
+
const observationEvent = readStandaloneObservationEvent(message);
|
|
203
|
+
if (observationEvent) {
|
|
204
|
+
observationEvents.push({
|
|
205
|
+
boundaryIndex: messages.length,
|
|
206
|
+
event: observationEvent,
|
|
207
|
+
messageId: message.id,
|
|
208
|
+
});
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
169
211
|
const targetIndex = pendingContinuationTargetId && message.role === "assistant"
|
|
170
212
|
? projectedIndexByMessageId.get(pendingContinuationTargetId)
|
|
171
213
|
: undefined;
|
|
@@ -238,7 +280,7 @@ function projectVisibleChatMessageState(
|
|
|
238
280
|
status: "pending",
|
|
239
281
|
};
|
|
240
282
|
}
|
|
241
|
-
return { messages, inlineCompactionMessageIds };
|
|
283
|
+
return { messages, inlineCompactionMessageIds, observationEvents };
|
|
242
284
|
}
|
|
243
285
|
|
|
244
286
|
export function projectVisibleChatMessages(
|
|
@@ -292,6 +334,7 @@ export function buildChatMessageTimelineItems(params: {
|
|
|
292
334
|
}): ChatTimelineItem[] {
|
|
293
335
|
const projection = projectVisibleChatMessageState(params.rawMessages);
|
|
294
336
|
const visibleRawMessages = projection.messages;
|
|
337
|
+
const observationEvents = projection.observationEvents;
|
|
295
338
|
const checkpoints = params.rawMessages
|
|
296
339
|
.map((message) => ({
|
|
297
340
|
rawMessageId: message.id,
|
|
@@ -324,6 +367,7 @@ export function buildChatMessageTimelineItems(params: {
|
|
|
324
367
|
const items: ChatTimelineItem[] = [];
|
|
325
368
|
let pendingMessages: ChatMessageViewModel[] = [];
|
|
326
369
|
let checkpointCursor = 0;
|
|
370
|
+
let observationEventCursor = 0;
|
|
327
371
|
const flushPendingMessages = () => {
|
|
328
372
|
if (pendingMessages.length === 0) {
|
|
329
373
|
return;
|
|
@@ -337,8 +381,24 @@ export function buildChatMessageTimelineItems(params: {
|
|
|
337
381
|
);
|
|
338
382
|
pendingMessages = [];
|
|
339
383
|
};
|
|
384
|
+
const flushObservationEvents = (boundaryIndex: number) => {
|
|
385
|
+
while (
|
|
386
|
+
observationEventCursor < observationEvents.length &&
|
|
387
|
+
observationEvents[observationEventCursor]!.boundaryIndex <= boundaryIndex
|
|
388
|
+
) {
|
|
389
|
+
const currentEvent = observationEvents[observationEventCursor]!;
|
|
390
|
+
flushPendingMessages();
|
|
391
|
+
items.push({
|
|
392
|
+
kind: "observation-event",
|
|
393
|
+
key: `observation-event:${currentEvent.messageId}`,
|
|
394
|
+
event: currentEvent.event,
|
|
395
|
+
});
|
|
396
|
+
observationEventCursor += 1;
|
|
397
|
+
}
|
|
398
|
+
};
|
|
340
399
|
|
|
341
400
|
visibleRawMessages.forEach((rawMessage, index) => {
|
|
401
|
+
flushObservationEvents(index);
|
|
342
402
|
if (contextInheritance?.boundaryIndex === index) {
|
|
343
403
|
flushPendingMessages();
|
|
344
404
|
items.push({
|
|
@@ -373,6 +433,7 @@ export function buildChatMessageTimelineItems(params: {
|
|
|
373
433
|
inheritance: contextInheritance,
|
|
374
434
|
});
|
|
375
435
|
}
|
|
436
|
+
flushObservationEvents(visibleRawMessages.length);
|
|
376
437
|
while (checkpointCursor < checkpoints.length) {
|
|
377
438
|
const currentCheckpoint = checkpoints[checkpointCursor];
|
|
378
439
|
flushPendingMessages();
|
|
@@ -1,8 +1,14 @@
|
|
|
1
|
-
import { useQuery } from '@tanstack/react-query';
|
|
1
|
+
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
|
|
2
2
|
import {
|
|
3
|
+
fetchNcpSessionObservations,
|
|
3
4
|
fetchNcpSessionSkills,
|
|
4
5
|
fetchNcpSessionTokenUsage,
|
|
5
|
-
fetchNcpSessions
|
|
6
|
+
fetchNcpSessions,
|
|
7
|
+
updateNcpSessionObservation,
|
|
8
|
+
} from '@/shared/lib/api';
|
|
9
|
+
import type {
|
|
10
|
+
NcpSessionObservationAction,
|
|
11
|
+
NcpSessionObservationKind,
|
|
6
12
|
} from '@/shared/lib/api';
|
|
7
13
|
|
|
8
14
|
const ncpSessionQueryDefaults = { staleTime: 5_000, retry: false } as const;
|
|
@@ -40,3 +46,31 @@ export function useNcpSessionTokenUsage(sessionId: string | null) {
|
|
|
40
46
|
...ncpSessionQueryDefaults
|
|
41
47
|
});
|
|
42
48
|
}
|
|
49
|
+
|
|
50
|
+
export const ncpSessionObservationsQueryKey = (sessionId: string | null) =>
|
|
51
|
+
['ncp-session-observations', sessionId] as const;
|
|
52
|
+
|
|
53
|
+
export function useNcpSessionObservations(sessionId: string | null) {
|
|
54
|
+
return useQuery({
|
|
55
|
+
queryKey: ncpSessionObservationsQueryKey(sessionId),
|
|
56
|
+
queryFn: () => fetchNcpSessionObservations(sessionId as string),
|
|
57
|
+
enabled: Boolean(sessionId),
|
|
58
|
+
...ncpSessionQueryDefaults
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export function useNcpObservationAction(sessionId: string | null) {
|
|
63
|
+
const queryClient = useQueryClient();
|
|
64
|
+
return useMutation({
|
|
65
|
+
mutationFn: (input: {
|
|
66
|
+
kind: NcpSessionObservationKind;
|
|
67
|
+
id: string;
|
|
68
|
+
action: NcpSessionObservationAction;
|
|
69
|
+
}) => updateNcpSessionObservation(sessionId as string, input),
|
|
70
|
+
onSuccess: () => {
|
|
71
|
+
void queryClient.invalidateQueries({
|
|
72
|
+
queryKey: ncpSessionObservationsQueryKey(sessionId),
|
|
73
|
+
});
|
|
74
|
+
},
|
|
75
|
+
});
|
|
76
|
+
}
|