@nextclaw/ui 0.27.0 → 0.27.2
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 +36 -0
- package/dist/.vite/manifest.json +1246 -1175
- package/dist/assets/{abnfDiagram-VRR7QNED-DmeCRAkd.js → abnfDiagram-VRR7QNED-BT0_ycaq.js} +1 -1
- package/dist/assets/account-panel-svU9I6E6.js +1 -0
- package/dist/assets/agents-CtI89gpb.js +1 -0
- package/dist/assets/agents-DWygCmAK.js +1 -0
- package/dist/assets/{aiden0z-pptx-renderer.es-ChX5DHqP.js → aiden0z-pptx-renderer.es-ClCaf_Wh.js} +1 -1
- package/dist/assets/api-CI6_8Qt1.js +20 -0
- package/dist/assets/app-presenter-provider-_UK6sArj.js +28 -0
- package/dist/assets/appearance-settings-page-BhedtMx9.js +1 -0
- package/dist/assets/apps-C4c4NXqB.js +1 -0
- package/dist/assets/{arc-Cu6Ols44.js → arc-cmSdpq1Z.js} +1 -1
- package/dist/assets/architecture-TIHT7OUA-BImoGh10.js +1 -0
- package/dist/assets/{architectureDiagram-ZJ3FMSHR-DrNB0eLE.js → architectureDiagram-ZJ3FMSHR-aYglVeoS.js} +1 -1
- package/dist/assets/{blockDiagram-677ZJIJ3-08rHt6DJ.js → blockDiagram-677ZJIJ3-Di_PBl5q.js} +1 -1
- package/dist/assets/{book-open-ClbJmmxP.js → book-open-i_BjUBqL.js} +1 -1
- package/dist/assets/{c4Diagram-LMCZKHZV-CCVgRG-u.js → c4Diagram-LMCZKHZV-CfuxybOL.js} +1 -1
- package/dist/assets/{card-BdC01NFF.js → card-DokH7OBp.js} +1 -1
- package/dist/assets/channel-BDQry0ob.js +1 -0
- package/dist/assets/{channels-list-page-BrIvJlop.js → channels-list-page-B7G9lHUm.js} +2 -2
- package/dist/assets/chunk-2Q5K7J3B-DkgSFfIy.js +1 -0
- package/dist/assets/{chunk-32BRIVSS-BeCaI-JN.js → chunk-32BRIVSS-CCGc4qg4.js} +1 -1
- package/dist/assets/{chunk-52WLFC77-ZXIcYPYs.js → chunk-52WLFC77-aJoxU2Ow.js} +1 -1
- package/dist/assets/{chunk-5FCAYU7R-DDwTPcy8.js → chunk-5FCAYU7R-CGwtZSax.js} +1 -1
- package/dist/assets/{chunk-5HE753X5-WygrMYPL.js → chunk-5HE753X5-DqaMSMeS.js} +1 -1
- package/dist/assets/{chunk-5JV3BV7I-o8T3KZgk.js → chunk-5JV3BV7I-DnabINcd.js} +1 -1
- package/dist/assets/{chunk-5TONJI2A-BKFbUT7J.js → chunk-5TONJI2A-BhpKv1k2.js} +1 -1
- package/dist/assets/{chunk-5VM5RSS4-DYxCRV86.js → chunk-5VM5RSS4-DvkRPit_.js} +1 -1
- package/dist/assets/{chunk-7BUUIJ7U-CvSeJlKZ.js → chunk-7BUUIJ7U-CgDQOLnC.js} +1 -1
- package/dist/assets/{chunk-BIQX33UG-BhH3RHCY.js → chunk-BIQX33UG-9FEv5b7T.js} +1 -1
- package/dist/assets/{chunk-C7G6YPKG-BTL0-xL3.js → chunk-C7G6YPKG-CNGFAFYL.js} +1 -1
- package/dist/assets/{chunk-CQNSW5MT-DWAU4QaD.js → chunk-CQNSW5MT-DovTZx0M.js} +1 -1
- package/dist/assets/{chunk-CYSBUYHQ-B7ZBMXTx.js → chunk-CYSBUYHQ-DpLEgYa1.js} +1 -1
- package/dist/assets/{chunk-EMLP6XTP-D92HvnHE.js → chunk-EMLP6XTP-D4NuN01W.js} +1 -1
- package/dist/assets/{chunk-EX3LRPZG-DfOGKwW8.js → chunk-EX3LRPZG-D8Jf4kc2.js} +1 -1
- package/dist/assets/{chunk-FWX5IMBZ-DUuJUrXJ.js → chunk-FWX5IMBZ-BdHymAs0.js} +2 -2
- package/dist/assets/{chunk-HOUHSVGY-i3MDyUY5.js → chunk-HOUHSVGY-Dd_Ycn9Z.js} +1 -1
- package/dist/assets/{chunk-ICXQ74PX-F_pmNX6t.js → chunk-ICXQ74PX-BRPUu3ff.js} +1 -1
- package/dist/assets/{chunk-JG7HCLWE-DygOelrU.js → chunk-JG7HCLWE-DnCasQja.js} +1 -1
- package/dist/assets/{chunk-JWPE2WC7-BpiZMeRl.js → chunk-JWPE2WC7-C3CkbEj1.js} +1 -1
- package/dist/assets/{chunk-MOJQB5TN-CV10sB1I.js → chunk-MOJQB5TN-Pi--K4-1.js} +1 -1
- package/dist/assets/{chunk-MOZMSUNE-Cf1WZNm0.js → chunk-MOZMSUNE-3VTspvlh.js} +1 -1
- package/dist/assets/{chunk-OGEWGWER-DuSw54VR.js → chunk-OGEWGWER-BetLLyJt.js} +1 -1
- package/dist/assets/{chunk-OSBZ3O6U-_rt_XKSZ.js → chunk-OSBZ3O6U-D1VcupAj.js} +1 -1
- package/dist/assets/{chunk-PUDLZKDR-BFPaAGNW.js → chunk-PUDLZKDR-Cy4G8SjV.js} +1 -1
- package/dist/assets/{chunk-Q4XR5HBZ-GE0v_E5y.js → chunk-Q4XR5HBZ-UYxXzi7_.js} +1 -1
- package/dist/assets/{chunk-QBLGF6JB-BK_FpnlJ.js → chunk-QBLGF6JB-CHiGeRY1.js} +1 -1
- package/dist/assets/{chunk-R7FJI6CG-CpYh6rGo.js → chunk-R7FJI6CG-C5kVJus8.js} +1 -1
- package/dist/assets/{chunk-RYQCIY6F-htnxL_Cl.js → chunk-RYQCIY6F-C6cuuEBn.js} +1 -1
- package/dist/assets/{chunk-U6XO7XAA-wDbE4BZ7.js → chunk-U6XO7XAA-CM0EK7Y0.js} +1 -1
- package/dist/assets/{chunk-V7JOEXUC-DDRSVFTB.js → chunk-V7JOEXUC-DWJZIsME.js} +1 -1
- package/dist/assets/chunk-VAUOI2AC-CsTIB8qD.js +1 -0
- package/dist/assets/{chunk-VR4S4FIN-COdhHR1o.js → chunk-VR4S4FIN-CY5KYeEi.js} +1 -1
- package/dist/assets/{chunk-WYO6CB5R-DPDGhyF6.js → chunk-WYO6CB5R-B30N3ZP8.js} +3 -3
- package/dist/assets/chunk-XXDRQBXY-DK6dz0Q3.js +1 -0
- package/dist/assets/{chunk-YOTPTUD7-D8ir9Nx5.js → chunk-YOTPTUD7-CBu82JpO.js} +1 -1
- package/dist/assets/{chunk-ZGVPDNZ5-BuNKD836.js → chunk-ZGVPDNZ5-BN5NX5qA.js} +1 -1
- package/dist/assets/{chunk-ZIRB5QZD-DyHzq8jH.js → chunk-ZIRB5QZD-DcDXK29L.js} +1 -1
- package/dist/assets/{circle-dashed-nDaMRmP-.js → circle-dashed-Cx8CIEbg.js} +1 -1
- package/dist/assets/classDiagram-OUVF2IWQ-BYygHCrp.js +1 -0
- package/dist/assets/classDiagram-v2-EOCWNBFH-BgQ0XKYz.js +1 -0
- package/dist/assets/{client-DlFB5dW5.js → client-CUJUci3r.js} +1 -1
- package/dist/assets/{config-split-page-C06fU9OQ.js → config-split-page-hY1xug28.js} +1 -1
- package/dist/assets/{confirm-dialog-DpcmlXhd.js → confirm-dialog-B-ejV666.js} +1 -1
- package/dist/assets/{context-menu-DKIEaY7f.js → context-menu-dGVv8klA.js} +9 -9
- package/dist/assets/{cose-bilkent-JH36ORCC-B1I1_P6a.js → cose-bilkent-JH36ORCC-CmeJVoTw.js} +1 -1
- package/dist/assets/{createLucideIcon-Lnt-4LMC.js → createLucideIcon-reFMl-W-.js} +1 -1
- package/dist/assets/cron-DkYSmE-f.js +1 -0
- package/dist/assets/cynefin-VYW2F7L2-DKbotNWS.js +1 -0
- package/dist/assets/{cynefinDiagram-TSTJHNR4-DcOnhnCo.js → cynefinDiagram-TSTJHNR4-DGOUMgPP.js} +1 -1
- package/dist/assets/{dagre-nSYhf9yY.js → dagre-CMxSkbJJ.js} +1 -1
- package/dist/assets/{dagre-VKFMJZFB-hAX89lg3.js → dagre-VKFMJZFB-3YUBEXwo.js} +1 -1
- package/dist/assets/{desktop-capabilities-page-DPORyZAu.js → desktop-capabilities-page-CYJTQ3nC.js} +1 -1
- package/dist/assets/{desktop-update-config-BMTeWZmn.js → desktop-update-config-guKAozXO.js} +1 -1
- package/dist/assets/{diagram-FQU43EPY-C1mRMD2k.js → diagram-FQU43EPY-Br1g--ww.js} +1 -1
- package/dist/assets/{diagram-G47NLZAW-D2XBn5al.js → diagram-G47NLZAW-D1wJCBgr.js} +1 -1
- package/dist/assets/{diagram-NH7WQ7WH-3LmRsmkC.js → diagram-NH7WQ7WH-Cgg2auLH.js} +1 -1
- package/dist/assets/{diagram-OA4YK3LP-CFWn-osC.js → diagram-OA4YK3LP-R-wHiWqh.js} +1 -1
- package/dist/assets/{diagram-WEI45ONY-BqNRbUvU.js → diagram-WEI45ONY-CsNnKV0P.js} +1 -1
- package/dist/assets/{dialog-BNXSPMX_.js → dialog-DLOwdjT1.js} +1 -1
- package/dist/assets/{dist-Cuiqqp1O.js → dist-ZaFFmAGl.js} +1 -1
- package/dist/assets/doc-browser-B0zg0EXA.js +1 -0
- package/dist/assets/doc-browser-context-CTmOmuqa.js +1 -0
- package/dist/assets/{docx-preview-CunAATyC.js → docx-preview-kPn_EtAr.js} +1 -1
- package/dist/assets/{download-f_sPcoLZ.js → download-DovI3Yvf.js} +1 -1
- package/dist/assets/{ebnfDiagram-CCIWWBDH-CYb8IwqD.js → ebnfDiagram-CCIWWBDH-DCyhIPdi.js} +1 -1
- package/dist/assets/{erDiagram-Q63AITRT-H47mUoeK.js → erDiagram-Q63AITRT-D0ZJYAUf.js} +1 -1
- package/dist/assets/eventmodeling-45OFAUF4-SIhbIFIw.js +1 -0
- package/dist/assets/{extensions-B-0xQz3L.js → extensions-BZ3qrM8M.js} +1 -1
- package/dist/assets/{external-link-CbVlnlNy.js → external-link-DUD3AbsF.js} +1 -1
- package/dist/assets/flowDiagram-23GEKE2U-DdAjkU7I.js +1 -0
- package/dist/assets/{form-actions-BoTqELHB.js → form-actions-B8VniHts.js} +1 -1
- package/dist/assets/{ganttDiagram-NO4QXBWP-hSX45zfV.js → ganttDiagram-NO4QXBWP-CiXDcXZD.js} +1 -1
- package/dist/assets/gitGraph-TEB2WS4Q-DnMNpESZ.js +1 -0
- package/dist/assets/{gitGraphDiagram-IHSO6WYX-Br0UW2qg.js → gitGraphDiagram-IHSO6WYX-BSiIV48S.js} +1 -1
- package/dist/assets/{i18n-B0V5NkFj.js → i18n-IGQbjBqS.js} +2 -2
- package/dist/assets/inbox-CJBCLB1X.js +1 -0
- package/dist/assets/{inbox-Bna8iUy0.js → inbox-ClAG7SI_.js} +1 -1
- package/dist/assets/info-DKCQHKI2-BSm-69p_.js +1 -0
- package/dist/assets/{infoDiagram-FWYZ7A6U-DQmP_67w.js → infoDiagram-FWYZ7A6U-CCIgBCVq.js} +1 -1
- package/dist/assets/{ishikawaDiagram-FXEZZL3T-BHAV2oes.js → ishikawaDiagram-FXEZZL3T-nQ_baN5u.js} +1 -1
- package/dist/assets/{journeyDiagram-5HDEW3XC-CFHax4_d.js → journeyDiagram-5HDEW3XC-ABueIPzj.js} +1 -1
- package/dist/assets/{kanban-definition-HUTT4EX6-B4ZA9rp5.js → kanban-definition-HUTT4EX6-8FKS3fmQ.js} +1 -1
- package/dist/assets/katex-DPgHtix3.js +1 -0
- package/dist/assets/keyboard-shortcuts-settings-page-B5oxyPS2.js +1 -0
- package/dist/assets/{line-BboM0HLF.js → line-Biw8iEUz.js} +1 -1
- package/dist/assets/{linear-4K_M1oYM.js → linear-D7CWUHTF.js} +1 -1
- package/dist/assets/login-page-BxSMwUsc.js +1 -0
- package/dist/assets/{login-page-JNr5JCEw.js → login-page-DYaozpzz.js} +1 -1
- package/dist/assets/main-D_zmSVS1.css +1 -0
- package/dist/assets/main-gFUvLF57.js +2 -0
- package/dist/assets/main-i18n-catalog.config-itg3Gvzp.js +1 -0
- package/dist/assets/{map-26GpO1wn.js → map-CDu47gTf.js} +1 -1
- package/dist/assets/marketplace-DsAf_rnt.js +1 -0
- package/dist/assets/mcp-marketplace-page-BqUz09cj.js +1 -0
- package/dist/assets/{mermaid-parser.core-BTJFnvRC.js → mermaid-parser.core-Cc9wjl82.js} +2 -2
- package/dist/assets/{mermaid.core-B7ufoXgq.js → mermaid.core-GWlaVWz1.js} +3 -3
- package/dist/assets/{mindmap-definition-LN4V7U3C-BHyru6KE.js → mindmap-definition-LN4V7U3C-oqnKsz-R.js} +1 -1
- package/dist/assets/{model-config-page-C-wbM6Fe.js → model-config-page-Cduyz2Hy.js} +1 -1
- package/dist/assets/{navigation-link-DFLSVIut.js → navigation-link-D-JSWFxj.js} +1 -1
- package/dist/assets/{ordinal-BqFe2ePF.js → ordinal-DImbxqBz.js} +1 -1
- package/dist/assets/packet-7NZHBO7P-1YQvC6mT.js +1 -0
- package/dist/assets/panel-app-i18n-catalog.config-BfLHr1tc.js +1 -0
- package/dist/assets/panel-apps-Bg5Fzm3T.js +1 -0
- package/dist/assets/panelStandalone-oHxbXvYt.js +2 -0
- package/dist/assets/{pegDiagram-2B236MQR-PVTatU5j.js → pegDiagram-2B236MQR-DYAB8CEz.js} +1 -1
- package/dist/assets/pie-RZYD4A2V-BGoNOSwu.js +1 -0
- package/dist/assets/{pieDiagram-ENE6RG2P-CGc-QCc7.js → pieDiagram-ENE6RG2P-DGsH0Kk5.js} +1 -1
- package/dist/assets/plus-DUdl68Eo.js +1 -0
- package/dist/assets/{privacy-settings-page-CPdEiouE.js → privacy-settings-page-DG9E8N-F.js} +1 -1
- package/dist/assets/projects-DvHyoKIF.js +1 -0
- package/dist/assets/{provider-models-XRArsply.js → provider-models-COzjYl29.js} +1 -1
- package/dist/assets/{provider-scoped-model-input-C8JI-hus.js → provider-scoped-model-input-Cvy74uj8.js} +1 -1
- package/dist/assets/{providers-config-page-fyMlVgvq.js → providers-config-page-7rCwVnhh.js} +1 -1
- package/dist/assets/{puzzle-Bk3ud1KI.js → puzzle-C5Wfpjk_.js} +1 -1
- package/dist/assets/{pwa-Cx6Fnox4.js → pwa-CAg_9zFs.js} +1 -1
- package/dist/assets/{quadrantDiagram-ABIIQ3AL-DGL36riv.js → quadrantDiagram-ABIIQ3AL-BegGcT3l.js} +1 -1
- package/dist/assets/radar-I7S5WNFK-uPku9RRq.js +1 -0
- package/dist/assets/railroad-3IZDKUUU-DHnmbuIo.js +1 -0
- package/dist/assets/railroad-abnf-AHOZXSZD-DiZs--Iw.js +1 -0
- package/dist/assets/railroad-ebnf-EBAXGLYW-Nr53gnNE.js +1 -0
- package/dist/assets/railroad-peg-LSFZ7HO6-Cm_PuwJS.js +1 -0
- package/dist/assets/{railroadDiagram-RFXS5EU6-CyNwvhSb.js → railroadDiagram-RFXS5EU6-B3yJ2yxE.js} +1 -1
- package/dist/assets/{refresh-cw-Ca2napNx.js → refresh-cw-OhwaPDn1.js} +1 -1
- package/dist/assets/remote-Dhr4K1oK.js +1 -0
- package/dist/assets/{requirementDiagram-TGXJPOKE-C31NMKJ0.js → requirementDiagram-TGXJPOKE-DtEyoEXG.js} +1 -1
- package/dist/assets/{rotate-cw-DXg7sNUE.js → rotate-cw-aBponvp7.js} +1 -1
- package/dist/assets/runtime-config-page-FI2pk3HH.js +1 -0
- package/dist/assets/{sankeyDiagram-HTMAVEWB-CwrQ_7PA.js → sankeyDiagram-HTMAVEWB-h9AYS2UB.js} +1 -1
- package/dist/assets/{save-DNigywZ9.js → save-394QCMXn.js} +1 -1
- package/dist/assets/{search-U9C0oTQJ.js → search-BG2qAlNZ.js} +1 -1
- package/dist/assets/{search-config-page-Bdx_RR1q.js → search-config-page-D4LeiB9y.js} +1 -1
- package/dist/assets/{secrets-config-page-CvMIcsfJ.js → secrets-config-page-BzGcr5Vw.js} +2 -2
- package/dist/assets/security-config-vD_V0BQF.js +1 -0
- package/dist/assets/{select-DxwDeKUR.js → select-xUXYV0Gr.js} +1 -1
- package/dist/assets/{sequenceDiagram-DBY2YBRQ-EFD482_y.js → sequenceDiagram-DBY2YBRQ-D-uxCkob.js} +1 -1
- package/dist/assets/service-apps-panel-BTqXn0pg.js +1 -0
- package/dist/assets/{settings-2-BrBUdRoY.js → settings-2-CWOGRRaA.js} +1 -1
- package/dist/assets/{sizeCapture-X5ZJPWSS-TDvULTE1.js → sizeCapture-X5ZJPWSS-DBzZytQo.js} +1 -1
- package/dist/assets/{src-CI2AvEMj.js → src-zrGbZsfc.js} +1 -1
- package/dist/assets/{stateDiagram-2N3HPSRC-JdPsIYHo.js → stateDiagram-2N3HPSRC-DyDy7AHq.js} +1 -1
- package/dist/assets/stateDiagram-v2-6OUMAXLB-CtkpO6aA.js +1 -0
- package/dist/assets/{status-dot-BbGsrkIX.js → status-dot-CYifnSnt.js} +1 -1
- package/dist/assets/{swimlanes-5IMT3BWC-BnxpKeK_.js → swimlanes-5IMT3BWC-BzOduS38.js} +2 -2
- package/dist/assets/swimlanesDiagram-G3AALYLV-BSdi6mvi.js +8 -0
- package/dist/assets/{tag-chip-BDbxcf6P.js → tag-chip-CjM6lyeh.js} +1 -1
- package/dist/assets/theme-provider-BToFZGZG.js +1 -0
- package/dist/assets/{timeline-definition-FHXFAJF6-2IL22-uC.js → timeline-definition-FHXFAJF6-CmgnEF2t.js} +1 -1
- package/dist/assets/{trash-2-DwSkRfeB.js → trash-2-DvJ6duOW.js} +1 -1
- package/dist/assets/treeView-QDETBFTQ-DBoqypPR.js +1 -0
- package/dist/assets/treemap-6X3UGDF4-BMeL3P0q.js +1 -0
- package/dist/assets/use-config-COusaY5p.js +1 -0
- package/dist/assets/{use-desktop-capabilities-D7odgaTB.js → use-desktop-capabilities-B-u6ojjW.js} +1 -1
- package/dist/assets/{use-viewport-layout-BANU5E1t.js → use-viewport-layout-IKKGpjzF.js} +1 -1
- package/dist/assets/{vennDiagram-L72KCM5P-Cjf6n5Va.js → vennDiagram-L72KCM5P-DwS7D2kg.js} +1 -1
- package/dist/assets/wardley-OPB4EBWU-Dqxe7zN6.js +1 -0
- package/dist/assets/{wardleyDiagram-EHGQE667-yv4qKbBO.js → wardleyDiagram-EHGQE667-B4X8OOL4.js} +1 -1
- package/dist/assets/{x-BqGj6_Vq.js → x-E9VB4HQx.js} +1 -1
- package/dist/assets/{xychartDiagram-FW5EYKEG-Bmp8Ck8X.js → xychartDiagram-FW5EYKEG-BjRQ_0nx.js} +1 -1
- package/dist/index.html +41 -40
- package/dist/panel-standalone.html +16 -16
- package/package.json +6 -6
- package/src/features/agents/components/__tests__/agents-page.test.tsx +8 -5
- package/src/features/agents/components/agent-details-dialog.tsx +19 -15
- package/src/features/agents/components/agents-page.tsx +27 -38
- package/src/features/app-data/components/app-retained-data-section.tsx +2 -2
- package/src/features/apps/components/app-marketplace-catalog.tsx +5 -5
- package/src/features/apps/components/app-marketplace-detail.tsx +11 -2
- package/src/features/apps/components/app-packages-panel.tsx +4 -4
- package/src/features/apps/components/apps-panel.tsx +3 -1
- package/src/features/chat/components/providers/chat-runtime.provider.tsx +1 -1
- package/src/features/chat/features/conversation/components/__tests__/session-conversation-area.test.tsx +0 -1
- package/src/features/chat/features/conversation/components/__tests__/session-conversation-input.streaming.test.tsx +13 -2
- package/src/features/chat/features/conversation/components/session-conversation-area.tsx +8 -1
- package/src/features/chat/features/conversation/components/session-conversation-input-top-slot.tsx +44 -0
- package/src/features/chat/features/conversation/components/session-conversation-input.tsx +4 -38
- package/src/features/chat/features/conversation/hooks/__tests__/use-session-conversation-controller.test.tsx +127 -10
- package/src/features/chat/features/conversation/hooks/__tests__/use-session-conversation-input-state.test.tsx +12 -2
- package/src/features/chat/features/conversation/hooks/use-session-conversation-controller.ts +88 -73
- package/src/features/chat/features/conversation/hooks/use-session-conversation-input-query.ts +5 -15
- package/src/features/chat/features/conversation/hooks/use-session-conversation-input-state.ts +53 -13
- package/src/features/chat/features/conversation/hooks/use-session-submission-recovery.ts +83 -0
- package/src/features/chat/features/conversation/types/session-conversation-input.types.ts +38 -0
- package/src/features/chat/features/input/utils/__tests__/ncp-chat-input-availability.utils.test.ts +1 -29
- package/src/features/chat/features/input/utils/ncp-chat-input-availability.utils.ts +1 -8
- package/src/features/chat/features/message/components/__tests__/chat-message-list-skill-preview.container.test.tsx +14 -1
- package/src/features/chat/features/message/hooks/use-chat-inline-token-actions.ts +7 -2
- package/src/features/chat/features/session/utils/__tests__/chat-session-route.utils.test.ts +26 -0
- package/src/features/chat/features/session/utils/chat-session-preference-governance.utils.ts +14 -8
- package/src/features/chat/features/session/utils/chat-session-route.utils.ts +9 -12
- package/src/features/chat/features/workspace/components/__tests__/chat-session-workspace-file-preview.selection.test.tsx +14 -2
- package/src/features/chat/features/workspace/components/__tests__/session-cron-job-content.test.tsx +5 -1
- package/src/features/chat/features/workspace/components/chat-session-workspace-file-preview.tsx +1 -1
- package/src/features/chat/features/workspace/components/session-cron-job-content.tsx +6 -22
- package/src/features/chat/index.ts +1 -0
- package/src/features/chat/pages/__tests__/ncp-chat-page.test.ts +37 -47
- package/src/features/chat/pages/ncp-chat-page.tsx +3 -3
- package/src/features/chat/stores/__tests__/chat-composer-draft.store.test.ts +67 -1
- package/src/features/chat/stores/chat-composer-draft.store.ts +230 -29
- package/src/features/cron/components/__tests__/cron-config.test.tsx +8 -2
- package/src/features/cron/components/cron-config.tsx +6 -17
- package/src/features/cron/components/cron-job-detail-dialog.tsx +10 -9
- package/src/features/cron/components/cron-job-resource.tsx +51 -0
- package/src/features/cron/index.ts +1 -0
- package/src/features/inbox/pages/inbox-page.tsx +8 -5
- package/src/features/marketplace/components/__tests__/marketplace-page-detail.test.tsx +1 -0
- package/src/features/marketplace/components/__tests__/marketplace-page.test.tsx +1 -0
- package/src/features/marketplace/components/mcp/__tests__/mcp-marketplace-page.test.tsx +2 -0
- package/src/features/marketplace/components/mcp/mcp-marketplace-card.tsx +2 -2
- package/src/features/marketplace/components/mcp/mcp-marketplace-page.tsx +23 -1
- package/src/features/marketplace/hooks/use-marketplace-item-detail.ts +11 -0
- package/src/features/panel-apps/index.ts +1 -0
- package/src/features/projects/components/work/project-work-item-drawer.tsx +7 -10
- package/src/features/projects/pages/project-home-page.tsx +18 -23
- package/src/features/projects/pages/projects-page.test.tsx +4 -1
- package/src/features/right-panel-resources/components/__tests__/system-object-resource.test.tsx +74 -6
- package/src/features/right-panel-resources/components/native-object-resource.tsx +134 -0
- package/src/features/right-panel-resources/components/page-resource-icon.tsx +1 -1
- package/src/features/right-panel-resources/components/system-object-resource.tsx +66 -1
- package/src/features/right-panel-resources/components/workspace-file-resource.tsx +9 -0
- package/src/features/right-panel-resources/configs/right-panel-resource-routes.config.ts +11 -21
- package/src/features/right-panel-resources/managers/__tests__/page-resource.manager.test.ts +14 -4
- package/src/features/right-panel-resources/managers/page-resource.manager.ts +38 -21
- package/src/features/right-panel-resources/utils/__tests__/right-panel-resource-route-resolver.utils.test.ts +12 -0
- package/src/features/service-apps/components/service-apps-panel.tsx +5 -2
- package/src/shared/components/doc-browser/__tests__/doc-browser-context.test.tsx +16 -0
- package/src/shared/components/doc-browser/__tests__/doc-browser.test.tsx +2 -2
- package/src/shared/components/doc-browser/__tests__/resource-link-interceptor.test.tsx +29 -1
- package/src/shared/components/doc-browser/stores/doc-browser.store.ts +13 -7
- package/src/shared/components/doc-browser/utils/doc-browser-url.utils.ts +2 -1
- package/src/shared/components/ui/skeleton.tsx +16 -2
- package/src/shared/lib/i18n/locales/en-US/chat.json +8 -0
- package/src/shared/lib/i18n/locales/zh-CN/chat.json +8 -0
- package/src/shared/lib/transport/__tests__/local-transport.service.test.ts +24 -0
- package/src/shared/lib/transport/local-transport.service.ts +8 -6
- package/dist/assets/account-panel-BYxGT4m4.js +0 -1
- package/dist/assets/api-CG22BskB.js +0 -20
- package/dist/assets/app-presenter-provider-CJFjhVYI.js +0 -28
- package/dist/assets/appearance-settings-page-BcXr0vHp.js +0 -1
- package/dist/assets/architecture-TIHT7OUA-CLjV_xu4.js +0 -1
- package/dist/assets/channel-BgpbPyEH.js +0 -1
- package/dist/assets/chunk-2Q5K7J3B-DjhMPqAC.js +0 -1
- package/dist/assets/chunk-VAUOI2AC-GYimZYx9.js +0 -1
- package/dist/assets/chunk-XXDRQBXY-KKCf0HV5.js +0 -1
- package/dist/assets/classDiagram-OUVF2IWQ-iRMPRR8M.js +0 -1
- package/dist/assets/classDiagram-v2-EOCWNBFH-BguFy_wj.js +0 -1
- package/dist/assets/cynefin-VYW2F7L2-CtbjXuCW.js +0 -1
- package/dist/assets/doc-browser-CDEapjmj.js +0 -1
- package/dist/assets/doc-browser-context-0QDWYorh.js +0 -1
- package/dist/assets/eventmodeling-45OFAUF4-Djd6id_u.js +0 -1
- package/dist/assets/flowDiagram-23GEKE2U-DUrsM_ZL.js +0 -1
- package/dist/assets/gitGraph-TEB2WS4Q-CU6P_2Cm.js +0 -1
- package/dist/assets/info-DKCQHKI2-Bj2P_7RC.js +0 -1
- package/dist/assets/katex-BprZ-Wwb.js +0 -1
- package/dist/assets/keyboard-shortcuts-settings-page-BluWKrSo.js +0 -1
- package/dist/assets/login-page-BMHW0Hh0.js +0 -1
- package/dist/assets/main-BCX_Untx.css +0 -1
- package/dist/assets/main-C5kbmGUV.js +0 -2
- package/dist/assets/main-i18n-catalog.config-DO4wNT7T.js +0 -1
- package/dist/assets/mcp-marketplace-page-CV-PHKTN.js +0 -1
- package/dist/assets/packet-7NZHBO7P-ti5ge2jr.js +0 -1
- package/dist/assets/panel-app-i18n-catalog.config-Bo52dPuF.js +0 -1
- package/dist/assets/panelStandalone-PuuMF65O.js +0 -2
- package/dist/assets/pie-RZYD4A2V-Bnep8TyV.js +0 -1
- package/dist/assets/plus-CywSlIbG.js +0 -1
- package/dist/assets/projects-D_cd_t4G.js +0 -1
- package/dist/assets/radar-I7S5WNFK-BYg-icAP.js +0 -1
- package/dist/assets/railroad-3IZDKUUU-_CHO-Fi1.js +0 -1
- package/dist/assets/railroad-abnf-AHOZXSZD-hbQDevHe.js +0 -1
- package/dist/assets/railroad-ebnf-EBAXGLYW-v4RZkOfi.js +0 -1
- package/dist/assets/railroad-peg-LSFZ7HO6-bC9BqkI5.js +0 -1
- package/dist/assets/remote-D5MBQNZE.js +0 -1
- package/dist/assets/runtime-config-page--ivCxBT4.js +0 -1
- package/dist/assets/security-config-CQmMqQ8v.js +0 -1
- package/dist/assets/service-apps-panel-CiYO1Be4.js +0 -1
- package/dist/assets/stateDiagram-v2-6OUMAXLB-4_aAQfB_.js +0 -1
- package/dist/assets/swimlanesDiagram-G3AALYLV-wCqfwsw-.js +0 -8
- package/dist/assets/theme-provider-D98XGa-c.js +0 -1
- package/dist/assets/treeView-QDETBFTQ-BAyOb14Z.js +0 -1
- package/dist/assets/treemap-6X3UGDF4-DgPDM0zS.js +0 -1
- package/dist/assets/use-config-D3cNzk2k.js +0 -1
- package/dist/assets/wardley-OPB4EBWU-eCElh8z5.js +0 -1
- /package/dist/assets/{array-DstOKG9P.js → array-DsNX3jRj.js} +0 -0
- /package/dist/assets/{chunk-KEIR6QF5-0TA8nwgf.js → chunk-KEIR6QF5-BOAXXeyv.js} +0 -0
- /package/dist/assets/{chunk-Y2CYZVJY-rfGCG6pM.js → chunk-Y2CYZVJY-CHjSjwoV.js} +0 -0
- /package/dist/assets/{config-hints-BfGoD7-o.js → config-hints-CaB3I7KP.js} +0 -0
- /package/dist/assets/{cytoscape.esm-DdIcNEda.js → cytoscape.esm-j4J9a91l.js} +0 -0
- /package/dist/assets/{defaultLocale-CzXix2iJ.js → defaultLocale-Bmxjp-V_.js} +0 -0
- /package/dist/assets/{dist-D5dwMwKA.js → dist-DwLj1Wg5.js} +0 -0
- /package/dist/assets/{graphlib-BKOe0eFe.js → graphlib-CC0HTn1v.js} +0 -0
- /package/dist/assets/{host-capabilities-CnSVTaot.js → host-capabilities-B107nwS3.js} +0 -0
- /package/dist/assets/{init-OCFb3zgY.js → init-Biz9Rus1.js} +0 -0
- /package/dist/assets/{jszip.min-B2uhSxvV.js → jszip.min-DQvBVV_R.js} +0 -0
- /package/dist/assets/{katex-dBrYsE7B.js → katex-BzT-4KBu.js} +0 -0
- /package/dist/assets/{middleware-CAXxl-af.js → middleware-B--6mAUM.js} +0 -0
- /package/dist/assets/{navigation-history-CzErJuPG.js → navigation-history-CCnxsAKR.js} +0 -0
- /package/dist/assets/{panel-app-CSQmm_7E.js → panel-app-BBTg0tVp.js} +0 -0
- /package/dist/assets/{path-T5eoIRSJ.js → path-4azsBPZv.js} +0 -0
- /package/dist/assets/{rough.esm-DmGXmZEB.js → rough.esm-w1lBArN6.js} +0 -0
- /package/dist/assets/{xlsx-CoYacou7.js → xlsx--SB9KlFl.js} +0 -0
package/src/features/chat/features/conversation/hooks/use-session-conversation-input-state.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { useCallback, useEffect, useMemo, type SetStateAction } from 'react';
|
|
2
2
|
import type { ChatComposerNode } from '@nextclaw/agent-chat-ui';
|
|
3
3
|
import type { NcpDraftAttachment } from '@nextclaw/ncp-react';
|
|
4
|
+
import type { NcpAgentSendEnvelope } from '@nextclaw/ncp';
|
|
4
5
|
|
|
5
6
|
import type { ThinkingLevel } from '@/shared/lib/api';
|
|
6
7
|
import { DEFAULT_SESSION_TYPE } from '@/features/chat/features/session-type/utils/chat-session-type.utils';
|
|
@@ -10,6 +11,7 @@ import {
|
|
|
10
11
|
resolveChatComposerDraftKey,
|
|
11
12
|
useChatComposerDraftStore,
|
|
12
13
|
type ChatComposerDraftSnapshot,
|
|
14
|
+
type ChatComposerSubmission,
|
|
13
15
|
} from '@/features/chat/stores/chat-composer-draft.store';
|
|
14
16
|
import {
|
|
15
17
|
useSessionConversationPreferenceActions,
|
|
@@ -38,6 +40,7 @@ export type SessionConversationInputSnapshot = SessionConversationComposerState
|
|
|
38
40
|
readonly pendingProjectRoot: string | null;
|
|
39
41
|
readonly composerFocusRequestId: number;
|
|
40
42
|
readonly sendError: string | null;
|
|
43
|
+
readonly pendingSubmission?: ChatComposerSubmission | null;
|
|
41
44
|
};
|
|
42
45
|
|
|
43
46
|
type SessionConversationOwnedInputSnapshot = ChatComposerDraftSnapshot;
|
|
@@ -49,7 +52,11 @@ export type SessionConversationInputPatch =
|
|
|
49
52
|
export type SessionConversationInputActions = {
|
|
50
53
|
readonly update: (patch: SessionConversationInputPatch) => void;
|
|
51
54
|
readonly syncComposer: (composer: SessionConversationComposerState) => void;
|
|
52
|
-
readonly
|
|
55
|
+
readonly beginSubmission: (envelope: NcpAgentSendEnvelope, composer: ChatComposerSubmission['composer']) => void;
|
|
56
|
+
readonly acceptSubmission: (messageId: string) => void;
|
|
57
|
+
readonly failSubmission: (messageId: string, status: 'uncertain' | 'rejected', message: string) => void;
|
|
58
|
+
readonly restoreSubmission: (messageId: string) => void;
|
|
59
|
+
readonly discardSubmission: (messageId: string) => void;
|
|
53
60
|
readonly restoreComposer: (
|
|
54
61
|
composer: SessionConversationComposerState & {
|
|
55
62
|
readonly attachments?: readonly NcpDraftAttachment[];
|
|
@@ -176,6 +183,7 @@ function usePersistedConversationInputSnapshot(
|
|
|
176
183
|
const snapshot = useChatComposerDraftStore(
|
|
177
184
|
(state) => state.drafts[draftKey] ?? initialSnapshot,
|
|
178
185
|
);
|
|
186
|
+
const pendingSubmission = useChatComposerDraftStore((state) => state.submissions[draftKey] ?? null);
|
|
179
187
|
|
|
180
188
|
useEffect(() => {
|
|
181
189
|
useChatComposerDraftStore.getState().ensureDraft(draftKey, initialSnapshot);
|
|
@@ -196,7 +204,35 @@ function usePersistedConversationInputSnapshot(
|
|
|
196
204
|
});
|
|
197
205
|
}, [draftKey, initialSnapshot]);
|
|
198
206
|
|
|
199
|
-
|
|
207
|
+
const beginSubmission = useCallback((
|
|
208
|
+
envelope: NcpAgentSendEnvelope,
|
|
209
|
+
composer: ChatComposerSubmission['composer'],
|
|
210
|
+
) => {
|
|
211
|
+
useChatComposerDraftStore.getState().beginSubmission(draftKey, snapshot, {
|
|
212
|
+
envelope, composer, status: 'sending',
|
|
213
|
+
});
|
|
214
|
+
}, [draftKey, snapshot]);
|
|
215
|
+
const acceptSubmission = useCallback((messageId: string) => {
|
|
216
|
+
useChatComposerDraftStore.getState().acceptSubmission(draftKey, messageId);
|
|
217
|
+
}, [draftKey]);
|
|
218
|
+
const failSubmission = useCallback((
|
|
219
|
+
messageId: string,
|
|
220
|
+
status: 'uncertain' | 'rejected',
|
|
221
|
+
message: string,
|
|
222
|
+
) => {
|
|
223
|
+
useChatComposerDraftStore.getState().failSubmission(draftKey, messageId, status, message);
|
|
224
|
+
}, [draftKey]);
|
|
225
|
+
const restoreSubmission = useCallback((messageId: string) => {
|
|
226
|
+
useChatComposerDraftStore.getState().restoreSubmission(draftKey, messageId);
|
|
227
|
+
}, [draftKey]);
|
|
228
|
+
const discardSubmission = useCallback((messageId: string) => {
|
|
229
|
+
useChatComposerDraftStore.getState().discardSubmission(draftKey, messageId);
|
|
230
|
+
}, [draftKey]);
|
|
231
|
+
|
|
232
|
+
return {
|
|
233
|
+
draftKey, snapshot, pendingSubmission, update,
|
|
234
|
+
beginSubmission, acceptSubmission, failSubmission, restoreSubmission, discardSubmission,
|
|
235
|
+
};
|
|
200
236
|
}
|
|
201
237
|
|
|
202
238
|
export const useSessionConversationInputState = (
|
|
@@ -204,7 +240,10 @@ export const useSessionConversationInputState = (
|
|
|
204
240
|
sessionKey: string | null = null,
|
|
205
241
|
) => {
|
|
206
242
|
const pendingProjectRoot = useChatThreadStore((state) => state.snapshot.draftProjectRoot);
|
|
207
|
-
const {
|
|
243
|
+
const {
|
|
244
|
+
draftKey, snapshot, pendingSubmission, update,
|
|
245
|
+
beginSubmission, acceptSubmission, failSubmission, restoreSubmission, discardSubmission,
|
|
246
|
+
} = usePersistedConversationInputSnapshot(
|
|
208
247
|
initialPrompt,
|
|
209
248
|
sessionKey,
|
|
210
249
|
);
|
|
@@ -219,14 +258,6 @@ export const useSessionConversationInputState = (
|
|
|
219
258
|
});
|
|
220
259
|
}, [update]);
|
|
221
260
|
|
|
222
|
-
const resetComposer = useCallback(() => {
|
|
223
|
-
update({
|
|
224
|
-
...EMPTY_COMPOSER_STATE,
|
|
225
|
-
attachments: [],
|
|
226
|
-
sendError: null,
|
|
227
|
-
});
|
|
228
|
-
}, [update]);
|
|
229
|
-
|
|
230
261
|
const restoreComposer = useCallback((
|
|
231
262
|
composer: SessionConversationComposerState & {
|
|
232
263
|
readonly attachments?: readonly NcpDraftAttachment[];
|
|
@@ -309,7 +340,11 @@ export const useSessionConversationInputState = (
|
|
|
309
340
|
const actions = useMemo<SessionConversationInputActions>(() => ({
|
|
310
341
|
update,
|
|
311
342
|
syncComposer,
|
|
312
|
-
|
|
343
|
+
beginSubmission,
|
|
344
|
+
acceptSubmission,
|
|
345
|
+
failSubmission,
|
|
346
|
+
restoreSubmission,
|
|
347
|
+
discardSubmission,
|
|
313
348
|
restoreComposer,
|
|
314
349
|
applyPromptSuggestion,
|
|
315
350
|
requestComposerFocusAtEnd,
|
|
@@ -325,7 +360,11 @@ export const useSessionConversationInputState = (
|
|
|
325
360
|
}), [
|
|
326
361
|
update,
|
|
327
362
|
syncComposer,
|
|
328
|
-
|
|
363
|
+
beginSubmission,
|
|
364
|
+
acceptSubmission,
|
|
365
|
+
failSubmission,
|
|
366
|
+
restoreSubmission,
|
|
367
|
+
discardSubmission,
|
|
329
368
|
restoreComposer,
|
|
330
369
|
applyPromptSuggestion,
|
|
331
370
|
requestComposerFocusAtEnd,
|
|
@@ -344,6 +383,7 @@ export const useSessionConversationInputState = (
|
|
|
344
383
|
inputSnapshot: {
|
|
345
384
|
...snapshot,
|
|
346
385
|
pendingProjectRoot,
|
|
386
|
+
pendingSubmission,
|
|
347
387
|
},
|
|
348
388
|
inputActions: actions,
|
|
349
389
|
};
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { useCallback, useEffect, useRef } from 'react';
|
|
2
|
+
import type { NcpAgentSendEnvelope, NcpRunHandle } from '@nextclaw/ncp';
|
|
3
|
+
import { NcpHttpSendError } from '@nextclaw/ncp-http-agent-client';
|
|
4
|
+
import { fetchNcpSessionMessages } from '@/shared/lib/api';
|
|
5
|
+
import { t } from '@/shared/lib/i18n';
|
|
6
|
+
import type { ChatComposerSubmission } from '@/features/chat/stores/chat-composer-draft.store';
|
|
7
|
+
|
|
8
|
+
async function hasAcceptedSubmission(submission: ChatComposerSubmission): Promise<boolean> {
|
|
9
|
+
const sessionId = submission.envelope.sessionId?.trim();
|
|
10
|
+
if (!sessionId) return false;
|
|
11
|
+
try {
|
|
12
|
+
const response = await fetchNcpSessionMessages(sessionId, { limit: 100 });
|
|
13
|
+
return response.messages.some((message) => message.id === submission.envelope.message.id);
|
|
14
|
+
} catch {
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function useSessionSubmissionRecovery(params: {
|
|
20
|
+
readonly agent: { send: (envelope: NcpAgentSendEnvelope) => Promise<NcpRunHandle | null> };
|
|
21
|
+
readonly submission?: ChatComposerSubmission | null;
|
|
22
|
+
readonly sessionKey: string | null;
|
|
23
|
+
readonly onSessionMaterialized?: (sessionKey: string) => void;
|
|
24
|
+
readonly acceptSubmission: (messageId: string) => void;
|
|
25
|
+
readonly failSubmission: (messageId: string, status: 'uncertain' | 'rejected', message: string) => void;
|
|
26
|
+
readonly restoreSubmission: (messageId: string) => void;
|
|
27
|
+
readonly discardSubmission: (messageId: string) => void;
|
|
28
|
+
readonly setSendError: (message: string | null) => void;
|
|
29
|
+
}) {
|
|
30
|
+
const {
|
|
31
|
+
agent, submission, sessionKey, onSessionMaterialized,
|
|
32
|
+
acceptSubmission, failSubmission, restoreSubmission, discardSubmission, setSendError,
|
|
33
|
+
} = params;
|
|
34
|
+
const retryPendingSubmission = useCallback(async () => {
|
|
35
|
+
if (!submission || submission.status !== 'uncertain') return;
|
|
36
|
+
const { envelope } = submission;
|
|
37
|
+
if (await hasAcceptedSubmission(submission)) {
|
|
38
|
+
acceptSubmission(envelope.message.id);
|
|
39
|
+
if (!sessionKey && envelope.sessionId) onSessionMaterialized?.(envelope.sessionId);
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
if (!envelope.sessionId) {
|
|
43
|
+
setSendError(t('chatSendResultUnknownChild'));
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
try {
|
|
47
|
+
const handle = await agent.send(envelope);
|
|
48
|
+
if (!handle) throw new Error(t('chatSendFailed'));
|
|
49
|
+
acceptSubmission(envelope.message.id);
|
|
50
|
+
if (!sessionKey) onSessionMaterialized?.(handle.sessionId);
|
|
51
|
+
} catch (error) {
|
|
52
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
53
|
+
failSubmission(envelope.message.id,
|
|
54
|
+
error instanceof NcpHttpSendError && error.sendRejected ? 'rejected' : 'uncertain',
|
|
55
|
+
message);
|
|
56
|
+
}
|
|
57
|
+
}, [acceptSubmission, agent, failSubmission, onSessionMaterialized, sessionKey, setSendError, submission]);
|
|
58
|
+
|
|
59
|
+
const checkedSubmissionRef = useRef<string | null>(null);
|
|
60
|
+
useEffect(() => {
|
|
61
|
+
if (!submission || submission.status !== 'uncertain' ||
|
|
62
|
+
checkedSubmissionRef.current === submission.envelope.message.id) return;
|
|
63
|
+
checkedSubmissionRef.current = submission.envelope.message.id;
|
|
64
|
+
void hasAcceptedSubmission(submission).then((accepted) => {
|
|
65
|
+
if (accepted) {
|
|
66
|
+
acceptSubmission(submission.envelope.message.id);
|
|
67
|
+
if (!sessionKey && submission.envelope.sessionId) {
|
|
68
|
+
onSessionMaterialized?.(submission.envelope.sessionId);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
}, [acceptSubmission, onSessionMaterialized, sessionKey, submission]);
|
|
73
|
+
|
|
74
|
+
return {
|
|
75
|
+
retryPendingSubmission,
|
|
76
|
+
restorePendingSubmission: () => {
|
|
77
|
+
if (submission) restoreSubmission(submission.envelope.message.id);
|
|
78
|
+
},
|
|
79
|
+
discardPendingSubmission: () => {
|
|
80
|
+
if (submission?.status === 'rejected') discardSubmission(submission.envelope.message.id);
|
|
81
|
+
},
|
|
82
|
+
};
|
|
83
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { ChatContextWindowIndicator } from '@nextclaw/agent-chat-ui';
|
|
2
|
+
import type { SessionConversationQueuedInput } from '@/features/chat/features/conversation/hooks/use-session-conversation-controller';
|
|
3
|
+
import type { useSessionConversationInputQuery } from '@/features/chat/features/conversation/hooks/use-session-conversation-input-query';
|
|
4
|
+
import type {
|
|
5
|
+
SessionConversationInputActions,
|
|
6
|
+
SessionConversationInputSnapshot,
|
|
7
|
+
} from '@/features/chat/features/conversation/hooks/use-session-conversation-input-state';
|
|
8
|
+
|
|
9
|
+
export type SessionConversationInputController = {
|
|
10
|
+
readonly canEditQueuedInput: boolean;
|
|
11
|
+
readonly canStopGeneration: boolean;
|
|
12
|
+
readonly deleteQueuedInput: (id: string) => void;
|
|
13
|
+
readonly editQueuedInput: (id: string) => void;
|
|
14
|
+
readonly isSending: boolean;
|
|
15
|
+
readonly queuedInputs: readonly SessionConversationQueuedInput[];
|
|
16
|
+
readonly primaryAction: 'continue' | 'send';
|
|
17
|
+
readonly sendDisabled: boolean;
|
|
18
|
+
readonly stopDisabled: boolean;
|
|
19
|
+
readonly send: () => Promise<void> | void;
|
|
20
|
+
readonly sendSteering: () => Promise<void> | void;
|
|
21
|
+
readonly sendPresetMessage: (message: string) => Promise<void> | void;
|
|
22
|
+
readonly retryPendingSubmission: () => Promise<void> | void;
|
|
23
|
+
readonly restorePendingSubmission: () => void;
|
|
24
|
+
readonly discardPendingSubmission: () => void;
|
|
25
|
+
readonly stop: () => Promise<void> | void;
|
|
26
|
+
readonly steerQueuedInput: (id: string) => void;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export type SessionConversationInputProps = {
|
|
30
|
+
readonly contextWindow: ChatContextWindowIndicator | null;
|
|
31
|
+
readonly controller: SessionConversationInputController;
|
|
32
|
+
readonly inputActions: SessionConversationInputActions;
|
|
33
|
+
readonly inputQuery: ReturnType<typeof useSessionConversationInputQuery>;
|
|
34
|
+
readonly inputSnapshot: SessionConversationInputSnapshot;
|
|
35
|
+
readonly onContextCompactingChange?: (sessionId: string, isCompacting: boolean) => void;
|
|
36
|
+
readonly placeholder?: string;
|
|
37
|
+
readonly surface?: 'default' | 'embedded';
|
|
38
|
+
};
|
package/src/features/chat/features/input/utils/__tests__/ncp-chat-input-availability.utils.test.ts
CHANGED
|
@@ -23,7 +23,7 @@ function createSnapshot(overrides: Partial<AvailabilitySnapshot> = {}): Availabi
|
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
describe('ncp-chat-input-availability.utils', () => {
|
|
26
|
-
it('keeps
|
|
26
|
+
it('keeps editing and sending available when runtime readiness is misreported', () => {
|
|
27
27
|
const snapshot = createSnapshot({
|
|
28
28
|
isProviderStateResolved: false,
|
|
29
29
|
modelOptions: [],
|
|
@@ -35,25 +35,7 @@ describe('ncp-chat-input-availability.utils', () => {
|
|
|
35
35
|
expect(isNcpChatComposerDisabled(snapshot)).toBe(false);
|
|
36
36
|
expect(
|
|
37
37
|
isNcpChatSendDisabled({
|
|
38
|
-
snapshot,
|
|
39
38
|
hasSendableDraft: true,
|
|
40
|
-
isRuntimeBlocked: true,
|
|
41
|
-
})
|
|
42
|
-
).toBe(true);
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
it('does not block send only because model options have not loaded yet', () => {
|
|
46
|
-
const snapshot = createSnapshot({
|
|
47
|
-
isProviderStateResolved: false,
|
|
48
|
-
modelOptions: [],
|
|
49
|
-
sessionTypeUnavailable: false,
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
expect(
|
|
53
|
-
isNcpChatSendDisabled({
|
|
54
|
-
snapshot,
|
|
55
|
-
hasSendableDraft: true,
|
|
56
|
-
isRuntimeBlocked: false,
|
|
57
39
|
})
|
|
58
40
|
).toBe(false);
|
|
59
41
|
});
|
|
@@ -81,25 +63,15 @@ describe('ncp-chat-input-availability.utils', () => {
|
|
|
81
63
|
expect(isNcpChatComposerDisabled(snapshot)).toBe(false);
|
|
82
64
|
expect(
|
|
83
65
|
isNcpChatSendDisabled({
|
|
84
|
-
snapshot,
|
|
85
66
|
hasSendableDraft: true,
|
|
86
|
-
isRuntimeBlocked: false,
|
|
87
67
|
})
|
|
88
68
|
).toBe(false);
|
|
89
69
|
});
|
|
90
70
|
|
|
91
71
|
it('blocks send when there is no sendable draft', () => {
|
|
92
|
-
const snapshot = createSnapshot({
|
|
93
|
-
isProviderStateResolved: true,
|
|
94
|
-
modelOptions: [],
|
|
95
|
-
sessionTypeUnavailable: true,
|
|
96
|
-
});
|
|
97
|
-
|
|
98
72
|
expect(
|
|
99
73
|
isNcpChatSendDisabled({
|
|
100
|
-
snapshot,
|
|
101
74
|
hasSendableDraft: false,
|
|
102
|
-
isRuntimeBlocked: false,
|
|
103
75
|
})
|
|
104
76
|
).toBe(true);
|
|
105
77
|
});
|
|
@@ -30,13 +30,6 @@ export function isNcpChatComposerDisabled(
|
|
|
30
30
|
|
|
31
31
|
export function isNcpChatSendDisabled(params: {
|
|
32
32
|
hasSendableDraft: boolean;
|
|
33
|
-
snapshot: ChatInputAvailabilitySnapshot;
|
|
34
|
-
isRuntimeBlocked: boolean;
|
|
35
33
|
}): boolean {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
return (
|
|
39
|
-
isRuntimeBlocked ||
|
|
40
|
-
!hasSendableDraft
|
|
41
|
-
);
|
|
34
|
+
return !params.hasSendableDraft;
|
|
42
35
|
}
|
|
@@ -23,6 +23,8 @@ function ChatMessageListContainer({
|
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
const captures = vi.hoisted(() => ({
|
|
26
|
+
resolveResource: vi.fn(),
|
|
27
|
+
openResource: vi.fn(),
|
|
26
28
|
renders: [] as Array<{
|
|
27
29
|
onInlineTokenClick?: (token: unknown) => void;
|
|
28
30
|
}>,
|
|
@@ -98,6 +100,8 @@ vi.mock("@/shared/lib/i18n", () => ({
|
|
|
98
100
|
}));
|
|
99
101
|
|
|
100
102
|
beforeEach(() => {
|
|
103
|
+
captures.resolveResource.mockReset();
|
|
104
|
+
captures.openResource.mockReset();
|
|
101
105
|
captures.renders = [];
|
|
102
106
|
captures.openFilePreview.mockReset();
|
|
103
107
|
captures.fetchSessionSkills.mockReset();
|
|
@@ -116,6 +120,15 @@ function clickSkill(token: Record<string, unknown>, sessionKey?: string): void {
|
|
|
116
120
|
captures.renders[captures.renders.length - 1]?.onInlineTokenClick?.(token);
|
|
117
121
|
}
|
|
118
122
|
|
|
123
|
+
it("opens a quoted object through the resource opener instead of treating its URI as a local path", () => {
|
|
124
|
+
const page = { uri: "nextclaw://objects/agent/philosopher" };
|
|
125
|
+
captures.resolveResource.mockReturnValue(page);
|
|
126
|
+
clickSkill({ kind: "workspace_excerpt", path: page.uri, excerpt: "Description", label: "Philosopher", startLine: null, endLine: null });
|
|
127
|
+
expect(captures.resolveResource).toHaveBeenCalledWith(page.uri);
|
|
128
|
+
expect(captures.openResource).toHaveBeenCalledWith(page, "default", expect.any(Function));
|
|
129
|
+
expect(captures.openFilePreview).not.toHaveBeenCalled();
|
|
130
|
+
});
|
|
131
|
+
|
|
119
132
|
it("opens a persisted skill path without consulting the session catalog", () => {
|
|
120
133
|
clickSkill({
|
|
121
134
|
kind: "skill", ref: "global:/skills/review", name: "review", source: "global",
|
|
@@ -170,4 +183,4 @@ it("shows an error when a persisted v1 skill is no longer resolvable", async ()
|
|
|
170
183
|
});
|
|
171
184
|
|
|
172
185
|
vi.mock("react-router-dom", async (importOriginal) => ({ ...(await importOriginal<object>()), useNavigate: () => vi.fn() }));
|
|
173
|
-
vi.mock("@/app/components/app-presenter-provider", () => ({ useAppPresenter: () => ({ pageResourceManager: { resolve:
|
|
186
|
+
vi.mock("@/app/components/app-presenter-provider", () => ({ useAppPresenter: () => ({ pageResourceManager: { resolve: captures.resolveResource, open: captures.openResource } }) }));
|
|
@@ -30,8 +30,13 @@ export function useChatInlineTokenActions(params: {
|
|
|
30
30
|
const projectRoot = selectedSession?.projectRoot ?? selectedSession?.workingDir;
|
|
31
31
|
|
|
32
32
|
const handleInlineTokenClick = useCallback((token: ChatInlineTokenViewModel) => {
|
|
33
|
-
|
|
34
|
-
|
|
33
|
+
const resourceUri = (token.kind === CHAT_UI_RESOURCE_TOKEN_KIND || token.kind === CHAT_SYSTEM_OBJECT_TOKEN_KIND) && "key" in token
|
|
34
|
+
? token.key
|
|
35
|
+
: token.kind === CHAT_WORKSPACE_EXCERPT_TOKEN_KIND && "excerpt" in token && token.path.startsWith("nextclaw://")
|
|
36
|
+
? token.path
|
|
37
|
+
: null;
|
|
38
|
+
if (resourceUri) {
|
|
39
|
+
const page = appPresenter.pageResourceManager.resolve(resourceUri);
|
|
35
40
|
if (page) appPresenter.pageResourceManager.open(page, 'default', navigate);
|
|
36
41
|
return;
|
|
37
42
|
}
|
|
@@ -1,11 +1,37 @@
|
|
|
1
1
|
import { describe, expect, it } from 'vitest';
|
|
2
2
|
import {
|
|
3
3
|
CHAT_DRAFT_SESSION_PATH,
|
|
4
|
+
buildSessionPanelUrl,
|
|
5
|
+
parseSessionKeyFromPanelUrl,
|
|
6
|
+
encodeSessionRouteId,
|
|
4
7
|
buildSessionPath,
|
|
5
8
|
parseSessionKeyFromRoute,
|
|
6
9
|
} from '@/features/chat/features/session/utils/chat-session-route.utils';
|
|
7
10
|
|
|
8
11
|
describe('chat session route utils', () => {
|
|
12
|
+
it.each(['ncp-mu2x4zdy-9wzl0otb', 'agent:main:会话/一 %2F', 'sid_literal', 'draft'])(
|
|
13
|
+
'round-trips resource and browser links for %s', (id) => {
|
|
14
|
+
expect(buildSessionPanelUrl(id)).toBe(`nextclaw://sessions/${encodeURIComponent(id)}`);
|
|
15
|
+
expect(parseSessionKeyFromPanelUrl(buildSessionPanelUrl(id))).toBe(id);
|
|
16
|
+
expect(parseSessionKeyFromRoute(buildSessionPath(id).slice('/chat/'.length))).toBe(id);
|
|
17
|
+
expect(parseSessionKeyFromPanelUrl(`nextclaw://chat-session/${encodeSessionRouteId(id)}`)).toBe(id);
|
|
18
|
+
},
|
|
19
|
+
);
|
|
20
|
+
it('keeps ordinary IDs readable in the address bar', () => {
|
|
21
|
+
expect(buildSessionPath('ncp-mu2x4zdy-9wzl0otb')).toBe('/chat/ncp-mu2x4zdy-9wzl0otb');
|
|
22
|
+
});
|
|
23
|
+
it.each(['sessions', 'chat-session', 'objects/chat-session', 'objects/chat-sessions'])(
|
|
24
|
+
'recovers already delivered %s links', (namespace) => {
|
|
25
|
+
expect(parseSessionKeyFromPanelUrl(`nextclaw://${namespace}/ncp-mu2x4zdy-9wzl0otb`)).toBe('ncp-mu2x4zdy-9wzl0otb');
|
|
26
|
+
},
|
|
27
|
+
);
|
|
28
|
+
it.each(['nextclaw://sessions/', 'nextclaw://sessions/a/b', 'nextclaw://sessions/%ZZ',
|
|
29
|
+
'nextclaw://sessions/%20', 'nextclaw://chat-session/sid_%%%','nextclaw://sessions/a?other=b',
|
|
30
|
+
'https://sessions/a', 'nextclaw://user@sessions/a', 'nextclaw://objects/project/a'])(
|
|
31
|
+
'rejects malformed or unrelated session links: %s', (uri) => {
|
|
32
|
+
expect(parseSessionKeyFromPanelUrl(uri)).toBeNull();
|
|
33
|
+
},
|
|
34
|
+
);
|
|
9
35
|
it('keeps the draft route separate from real session keys', () => {
|
|
10
36
|
expect(CHAT_DRAFT_SESSION_PATH).toBe('/chat/draft');
|
|
11
37
|
expect(parseSessionKeyFromRoute('draft')).toBeNull();
|
package/src/features/chat/features/session/utils/chat-session-preference-governance.utils.ts
CHANGED
|
@@ -129,15 +129,17 @@ export function resolveSelectedThinkingLevelValue(params: {
|
|
|
129
129
|
});
|
|
130
130
|
}
|
|
131
131
|
|
|
132
|
-
export function
|
|
132
|
+
export function resolveRecentSessionPreferenceSnapshot(params: {
|
|
133
133
|
sessions: readonly SessionEntryView[];
|
|
134
134
|
selectedSessionKey?: string | null;
|
|
135
135
|
sessionType?: string | null;
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
136
|
+
}): {
|
|
137
|
+
model: string;
|
|
138
|
+
thinking?: ThinkingLevel;
|
|
139
|
+
} | undefined {
|
|
140
|
+
const { sessions, selectedSessionKey, sessionType } = params;
|
|
139
141
|
const targetSessionType = normalizeSessionType(sessionType);
|
|
140
|
-
let bestValue:
|
|
142
|
+
let bestValue: { model: string; thinking?: ThinkingLevel } | undefined;
|
|
141
143
|
let bestTimestamp = Number.NEGATIVE_INFINITY;
|
|
142
144
|
for (const session of sessions) {
|
|
143
145
|
if (session.key === selectedSessionKey) {
|
|
@@ -146,14 +148,18 @@ export function resolveRecentSessionPreferredValue<T>(params: {
|
|
|
146
148
|
if (normalizeSessionType(session.sessionType) !== targetSessionType) {
|
|
147
149
|
continue;
|
|
148
150
|
}
|
|
149
|
-
const
|
|
150
|
-
|
|
151
|
+
const model = session.preferredModel?.trim() || undefined;
|
|
152
|
+
const thinking = session.preferredThinking ?? undefined;
|
|
153
|
+
if (model === undefined) {
|
|
151
154
|
continue;
|
|
152
155
|
}
|
|
153
156
|
const updatedAtTimestamp = Date.parse(session.updatedAt);
|
|
154
157
|
const comparableTimestamp = Number.isFinite(updatedAtTimestamp) ? updatedAtTimestamp : Number.NEGATIVE_INFINITY;
|
|
155
158
|
if (bestValue === undefined || comparableTimestamp > bestTimestamp) {
|
|
156
|
-
bestValue =
|
|
159
|
+
bestValue = {
|
|
160
|
+
model,
|
|
161
|
+
...(thinking ? { thinking } : {}),
|
|
162
|
+
};
|
|
157
163
|
bestTimestamp = comparableTimestamp;
|
|
158
164
|
}
|
|
159
165
|
}
|
|
@@ -1,16 +1,9 @@
|
|
|
1
|
+
import { createSessionResourceUri, parseSessionResourceUri } from '@nextclaw/shared';
|
|
2
|
+
|
|
1
3
|
const SESSION_ROUTE_PREFIX = 'sid_';
|
|
2
4
|
export const CHAT_SESSION_PANEL_KIND = 'chat-session';
|
|
3
|
-
const
|
|
4
|
-
|
|
5
|
-
export function buildSessionPanelUrl(sessionKey: string): string {
|
|
6
|
-
return SESSION_PANEL_PREFIX + encodeSessionRouteId(sessionKey);
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export function parseSessionKeyFromPanelUrl(url: string): string | null {
|
|
10
|
-
return url.startsWith(SESSION_PANEL_PREFIX)
|
|
11
|
-
? decodeSessionRouteId(url.slice(SESSION_PANEL_PREFIX.length))
|
|
12
|
-
: null;
|
|
13
|
-
}
|
|
5
|
+
export const buildSessionPanelUrl = createSessionResourceUri;
|
|
6
|
+
export const parseSessionKeyFromPanelUrl = parseSessionResourceUri;
|
|
14
7
|
export const CHAT_DRAFT_SESSION_PATH = '/chat/draft';
|
|
15
8
|
const DRAFT_SESSION_ROUTE_ID = CHAT_DRAFT_SESSION_PATH.slice('/chat/'.length);
|
|
16
9
|
|
|
@@ -55,5 +48,9 @@ export function parseSessionKeyFromRoute(routeValue?: string): string | null {
|
|
|
55
48
|
}
|
|
56
49
|
|
|
57
50
|
export function buildSessionPath(sessionKey: string): string {
|
|
58
|
-
|
|
51
|
+
// Keep reserved historical route tokens unambiguous; ordinary IDs stay readable.
|
|
52
|
+
const routeId = sessionKey === DRAFT_SESSION_ROUTE_ID || sessionKey.startsWith(SESSION_ROUTE_PREFIX)
|
|
53
|
+
? encodeSessionRouteId(sessionKey)
|
|
54
|
+
: encodeURIComponent(sessionKey);
|
|
55
|
+
return `/chat/${routeId}`;
|
|
59
56
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ReactNode } from "react";
|
|
2
|
-
import { fireEvent, render, screen } from "@testing-library/react";
|
|
3
|
-
import { describe, expect, it, vi } from "vitest";
|
|
2
|
+
import { cleanup, fireEvent, render, screen } from "@testing-library/react";
|
|
3
|
+
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
4
4
|
import { ChatSessionWorkspaceFilePreview } from "@/features/chat/features/workspace/components/chat-session-workspace-file-preview";
|
|
5
5
|
|
|
6
6
|
const onTextExcerptAdd = vi.fn();
|
|
@@ -37,6 +37,18 @@ vi.mock("@nextclaw/agent-chat-ui", () => ({
|
|
|
37
37
|
}));
|
|
38
38
|
|
|
39
39
|
describe("ChatSessionWorkspaceFilePreview selection", () => {
|
|
40
|
+
afterEach(cleanup);
|
|
41
|
+
|
|
42
|
+
it("does not offer an action when no composer callback is connected", () => {
|
|
43
|
+
render(<ChatSessionWorkspaceFilePreview
|
|
44
|
+
file={{ key: "boot", parentSessionKey: null, path: "BOOT.md", label: "BOOT.md", viewMode: "preview" }}
|
|
45
|
+
sessionProjectRoot={null}
|
|
46
|
+
sessionWorkingDir={null}
|
|
47
|
+
onFileOpen={vi.fn()}
|
|
48
|
+
/>);
|
|
49
|
+
expect(screen.queryByRole("button", { name: "select excerpt" })).toBeNull();
|
|
50
|
+
});
|
|
51
|
+
|
|
40
52
|
it("uses the resolved absolute path when a shell-style workspace root cannot be compared in the browser", () => {
|
|
41
53
|
render(
|
|
42
54
|
<ChatSessionWorkspaceFilePreview
|
package/src/features/chat/features/workspace/components/__tests__/session-cron-job-content.test.tsx
CHANGED
|
@@ -8,10 +8,14 @@ import { setLanguage } from "@/shared/lib/i18n";
|
|
|
8
8
|
import { SessionCronJobContent } from "@/features/chat/features/workspace/components/session-cron-job-content";
|
|
9
9
|
|
|
10
10
|
const mocks = vi.hoisted(() => ({
|
|
11
|
+
openResource: vi.fn(),
|
|
11
12
|
deleteJob: vi.fn(),
|
|
12
13
|
runJob: vi.fn(),
|
|
13
14
|
toggleJob: vi.fn(),
|
|
14
15
|
}));
|
|
16
|
+
vi.mock("@/app/components/app-presenter-provider", () => ({ useAppPresenter: () => ({ pageResourceManager: { open: mocks.openResource } }) }));
|
|
17
|
+
vi.mock("react-router-dom", () => ({ useNavigate: () => vi.fn() }));
|
|
18
|
+
vi.mock("@/features/right-panel-resources", () => ({ pageResourceFromSystemObject: (type: string, id: string) => ({ uri: `nextclaw://objects/${type}/${id}` }) }));
|
|
15
19
|
|
|
16
20
|
vi.mock("@/features/cron", () => ({
|
|
17
21
|
CronJobDetailDialog: ({ job, open }: { job: CronJobView | null; open: boolean }) => (
|
|
@@ -73,6 +77,6 @@ describe("SessionCronJobContent", () => {
|
|
|
73
77
|
expect(mocks.runJob).toHaveBeenCalledWith(job);
|
|
74
78
|
|
|
75
79
|
await user.click(screen.getByRole("button", { name: "查看任务详情" }));
|
|
76
|
-
expect(
|
|
80
|
+
expect(mocks.openResource).toHaveBeenCalledWith({ uri: "nextclaw://objects/cron-job/paint-daily" }, "default", expect.any(Function));
|
|
77
81
|
});
|
|
78
82
|
});
|
package/src/features/chat/features/workspace/components/chat-session-workspace-file-preview.tsx
CHANGED
|
@@ -455,7 +455,7 @@ export function ChatSessionWorkspaceFilePreview({
|
|
|
455
455
|
<div className="flex-1 min-h-0 overflow-hidden">
|
|
456
456
|
{file.viewMode === 'diff' ? (
|
|
457
457
|
<WorkspaceDiffBody diffBlock={diffBlock} fileKey={file.key} />
|
|
458
|
-
) : excerptPath && previewText ? (
|
|
458
|
+
) : excerptPath && previewText && onTextExcerptAdd ? (
|
|
459
459
|
<WorkspaceTextSelectionMenu
|
|
460
460
|
fileLabel={file.label?.trim() || excerptPath.split('/').at(-1) || excerptPath}
|
|
461
461
|
filePath={excerptPath}
|
|
@@ -11,9 +11,11 @@ import {
|
|
|
11
11
|
} from "lucide-react";
|
|
12
12
|
|
|
13
13
|
import {
|
|
14
|
-
CronJobDetailDialog,
|
|
15
14
|
useCronJobActions,
|
|
16
15
|
} from "@/features/cron";
|
|
16
|
+
import { useAppPresenter } from "@/app/components/app-presenter-provider";
|
|
17
|
+
import { useNavigate } from "react-router-dom";
|
|
18
|
+
import { pageResourceFromSystemObject } from "@/features/right-panel-resources";
|
|
17
19
|
import type { CronJobView } from "@/shared/lib/api";
|
|
18
20
|
import { Button } from "@/shared/components/ui/button";
|
|
19
21
|
import {
|
|
@@ -227,9 +229,9 @@ export function SessionCronJobContent({
|
|
|
227
229
|
readonly isLoading?: boolean;
|
|
228
230
|
readonly onRetry?: () => void;
|
|
229
231
|
}) {
|
|
230
|
-
const
|
|
232
|
+
const app = useAppPresenter();
|
|
233
|
+
const navigate = useNavigate();
|
|
231
234
|
const cronActions = useCronJobActions();
|
|
232
|
-
const selectedJob = jobs.find((job) => job.id === selectedJobId) ?? null;
|
|
233
235
|
|
|
234
236
|
return (
|
|
235
237
|
<div className="h-full overflow-y-auto custom-scrollbar px-4 py-4">
|
|
@@ -271,29 +273,11 @@ export function SessionCronJobContent({
|
|
|
271
273
|
key={job.id}
|
|
272
274
|
cronActions={cronActions}
|
|
273
275
|
job={job}
|
|
274
|
-
onOpenDetails={(item) =>
|
|
276
|
+
onOpenDetails={(item) => app.pageResourceManager.open(pageResourceFromSystemObject("cron-job", item.id, item.name || item.id), "default", navigate)}
|
|
275
277
|
/>
|
|
276
278
|
))}
|
|
277
279
|
</div>
|
|
278
280
|
)}
|
|
279
|
-
<CronJobDetailDialog
|
|
280
|
-
job={selectedJob}
|
|
281
|
-
open={Boolean(selectedJob)}
|
|
282
|
-
onOpenChange={(open) => {
|
|
283
|
-
if (!open) {
|
|
284
|
-
setSelectedJobId(null);
|
|
285
|
-
}
|
|
286
|
-
}}
|
|
287
|
-
onDelete={(job) => {
|
|
288
|
-
void cronActions.deleteJob(job, () => setSelectedJobId(null));
|
|
289
|
-
}}
|
|
290
|
-
onRun={(job) => {
|
|
291
|
-
void cronActions.runJob(job);
|
|
292
|
-
}}
|
|
293
|
-
onToggle={(job, enabled) => {
|
|
294
|
-
void cronActions.toggleJob(job, enabled);
|
|
295
|
-
}}
|
|
296
|
-
/>
|
|
297
281
|
<cronActions.ConfirmDialog />
|
|
298
282
|
</div>
|
|
299
283
|
);
|
|
@@ -39,3 +39,4 @@ export { ChatSessionWorkspaceFilePreview } from './features/workspace/components
|
|
|
39
39
|
export { createWorkspaceFileTab, createWorkspaceFileViewerTab } from './features/workspace/utils/chat-workspace-file-tab.utils';
|
|
40
40
|
export { WORKSPACE_FILE_PANEL_KIND, resolveFileResourceTarget, createWorkspaceFilePanelTarget, readWorkspaceFilePanelView } from './features/workspace/utils/workspace-file-panel-route.utils';
|
|
41
41
|
export { resolveAlternateWorkspaceFileViewer } from './features/workspace/utils/chat-workspace-file-viewer.utils';
|
|
42
|
+
export { WORKSPACE_TEXT_EXCERPT_MAX_CHARACTERS, type WorkspaceTextExcerpt } from './features/workspace/utils/workspace-text-excerpt.utils';
|