@nextclaw/ui 0.26.5 → 0.27.1
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 +82 -0
- package/dist/.vite/manifest.json +1342 -1227
- package/dist/assets/{abnfDiagram-VRR7QNED-Dcw10Yt1.js → abnfDiagram-VRR7QNED-BT0_ycaq.js} +1 -1
- package/dist/assets/account-panel-BVNV8XqM.js +1 -0
- package/dist/assets/agents-CfpN8PQc.js +1 -0
- package/dist/assets/agents-E4nu-17c.js +1 -0
- package/dist/assets/{aiden0z-pptx-renderer.es--oNqetPA.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-2DwHRRle.js +28 -0
- package/dist/assets/app-presenter-provider-D3BuuOyZ.css +1 -0
- package/dist/assets/appearance-settings-page-Cn9w3F-K.js +1 -0
- package/dist/assets/apps-YFlJirpx.js +1 -0
- package/dist/assets/{arc-DBRedCax.js → arc-cmSdpq1Z.js} +1 -1
- package/dist/assets/architecture-TIHT7OUA-BImoGh10.js +1 -0
- package/dist/assets/{architectureDiagram-ZJ3FMSHR-Dufhtuv-.js → architectureDiagram-ZJ3FMSHR-aYglVeoS.js} +1 -1
- package/dist/assets/{blockDiagram-677ZJIJ3-BUk0vtJ7.js → blockDiagram-677ZJIJ3-Di_PBl5q.js} +1 -1
- package/dist/assets/{book-open-Bcnn2_uV.js → book-open-i_BjUBqL.js} +1 -1
- package/dist/assets/{c4Diagram-LMCZKHZV-CxDcVE9p.js → c4Diagram-LMCZKHZV-CfuxybOL.js} +1 -1
- package/dist/assets/{card-Cqs73hGI.js → card-DokH7OBp.js} +1 -1
- package/dist/assets/channel-BDQry0ob.js +1 -0
- package/dist/assets/channels-list-page-B7G9lHUm.js +8 -0
- package/dist/assets/chunk-2Q5K7J3B-DkgSFfIy.js +1 -0
- package/dist/assets/{chunk-32BRIVSS-DSF3KElA.js → chunk-32BRIVSS-CCGc4qg4.js} +1 -1
- package/dist/assets/{chunk-52WLFC77-Costxzr3.js → chunk-52WLFC77-aJoxU2Ow.js} +1 -1
- package/dist/assets/{chunk-5FCAYU7R-rhqzGGZo.js → chunk-5FCAYU7R-CGwtZSax.js} +1 -1
- package/dist/assets/{chunk-5HE753X5-BsEsmIao.js → chunk-5HE753X5-DqaMSMeS.js} +1 -1
- package/dist/assets/{chunk-5JV3BV7I-Dqw_DCoN.js → chunk-5JV3BV7I-DnabINcd.js} +1 -1
- package/dist/assets/{chunk-5TONJI2A-Cft82fp8.js → chunk-5TONJI2A-BhpKv1k2.js} +1 -1
- package/dist/assets/{chunk-5VM5RSS4-DqNHn9Dl.js → chunk-5VM5RSS4-DvkRPit_.js} +1 -1
- package/dist/assets/{chunk-7BUUIJ7U-A5SBEMYY.js → chunk-7BUUIJ7U-CgDQOLnC.js} +1 -1
- package/dist/assets/{chunk-BIQX33UG-1Ng3mTrH.js → chunk-BIQX33UG-9FEv5b7T.js} +1 -1
- package/dist/assets/{chunk-C7G6YPKG-DRJEy8ZI.js → chunk-C7G6YPKG-CNGFAFYL.js} +1 -1
- package/dist/assets/{chunk-CQNSW5MT-Bydv_J3J.js → chunk-CQNSW5MT-DovTZx0M.js} +1 -1
- package/dist/assets/{chunk-CYSBUYHQ-HkMIg12u.js → chunk-CYSBUYHQ-DpLEgYa1.js} +1 -1
- package/dist/assets/{chunk-EMLP6XTP-C5ndDvm3.js → chunk-EMLP6XTP-D4NuN01W.js} +1 -1
- package/dist/assets/{chunk-EX3LRPZG-DzeloZRo.js → chunk-EX3LRPZG-D8Jf4kc2.js} +1 -1
- package/dist/assets/{chunk-FWX5IMBZ-n_2_CLTQ.js → chunk-FWX5IMBZ-BdHymAs0.js} +2 -2
- package/dist/assets/{chunk-HOUHSVGY-kx_slvu3.js → chunk-HOUHSVGY-Dd_Ycn9Z.js} +1 -1
- package/dist/assets/{chunk-ICXQ74PX-sQLMURqL.js → chunk-ICXQ74PX-BRPUu3ff.js} +1 -1
- package/dist/assets/{chunk-JG7HCLWE-CMUn5Elc.js → chunk-JG7HCLWE-DnCasQja.js} +1 -1
- package/dist/assets/{chunk-JWPE2WC7-Cra3s-Uk.js → chunk-JWPE2WC7-C3CkbEj1.js} +1 -1
- package/dist/assets/{chunk-MOJQB5TN-umcrg5Bi.js → chunk-MOJQB5TN-Pi--K4-1.js} +1 -1
- package/dist/assets/{chunk-MOZMSUNE-BnljD1ig.js → chunk-MOZMSUNE-3VTspvlh.js} +1 -1
- package/dist/assets/{chunk-OGEWGWER-BXx5pQjU.js → chunk-OGEWGWER-BetLLyJt.js} +1 -1
- package/dist/assets/{chunk-OSBZ3O6U-D-1qfdWu.js → chunk-OSBZ3O6U-D1VcupAj.js} +1 -1
- package/dist/assets/{chunk-PUDLZKDR-DLzX78LC.js → chunk-PUDLZKDR-Cy4G8SjV.js} +1 -1
- package/dist/assets/{chunk-Q4XR5HBZ-DTK-rtW6.js → chunk-Q4XR5HBZ-UYxXzi7_.js} +1 -1
- package/dist/assets/{chunk-QBLGF6JB-CsFeIGfr.js → chunk-QBLGF6JB-CHiGeRY1.js} +1 -1
- package/dist/assets/{chunk-R7FJI6CG-4xNYUeng.js → chunk-R7FJI6CG-C5kVJus8.js} +1 -1
- package/dist/assets/{chunk-RYQCIY6F-DJiHiTE5.js → chunk-RYQCIY6F-C6cuuEBn.js} +1 -1
- package/dist/assets/{chunk-U6XO7XAA-BVYkauHz.js → chunk-U6XO7XAA-CM0EK7Y0.js} +1 -1
- package/dist/assets/{chunk-V7JOEXUC-BsazE8cS.js → chunk-V7JOEXUC-DWJZIsME.js} +1 -1
- package/dist/assets/chunk-VAUOI2AC-CsTIB8qD.js +1 -0
- package/dist/assets/{chunk-VR4S4FIN-7RoZQffO.js → chunk-VR4S4FIN-CY5KYeEi.js} +1 -1
- package/dist/assets/{chunk-WYO6CB5R-DEuS6N1R.js → chunk-WYO6CB5R-B30N3ZP8.js} +3 -3
- package/dist/assets/chunk-XXDRQBXY-DK6dz0Q3.js +1 -0
- package/dist/assets/{chunk-YOTPTUD7-9KBrosZL.js → chunk-YOTPTUD7-CBu82JpO.js} +1 -1
- package/dist/assets/{chunk-ZGVPDNZ5-IYgN9f5A.js → chunk-ZGVPDNZ5-BN5NX5qA.js} +1 -1
- package/dist/assets/{chunk-ZIRB5QZD-BUo0-zcp.js → chunk-ZIRB5QZD-DcDXK29L.js} +1 -1
- package/dist/assets/{circle-dashed-EY1ScSMe.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-CH7w6yRV.js → client-CUJUci3r.js} +1 -1
- package/dist/assets/config-split-page-hY1xug28.js +1 -0
- package/dist/assets/confirm-dialog-B-ejV666.js +1 -0
- package/dist/assets/{app-presenter-provider-jNGlmBLe.css → context-menu-DEcVZfaU.css} +1 -1
- package/dist/assets/context-menu-dGVv8klA.js +211 -0
- package/dist/assets/{cose-bilkent-JH36ORCC-DhqbC1fR.js → cose-bilkent-JH36ORCC-CmeJVoTw.js} +1 -1
- package/dist/assets/{createLucideIcon-Cfo2ySi5.js → createLucideIcon-reFMl-W-.js} +1 -1
- package/dist/assets/cron-CH5c55CR.js +1 -0
- package/dist/assets/cynefin-VYW2F7L2-DKbotNWS.js +1 -0
- package/dist/assets/{cynefinDiagram-TSTJHNR4-C-TBRi5V.js → cynefinDiagram-TSTJHNR4-DGOUMgPP.js} +1 -1
- package/dist/assets/{dagre-CrgsRasE.js → dagre-CMxSkbJJ.js} +1 -1
- package/dist/assets/{dagre-VKFMJZFB-BmafJymp.js → dagre-VKFMJZFB-3YUBEXwo.js} +1 -1
- package/dist/assets/{desktop-capabilities-page-BDYITStl.js → desktop-capabilities-page-CYJTQ3nC.js} +1 -1
- package/dist/assets/desktop-update-config-guKAozXO.js +1 -0
- package/dist/assets/{diagram-FQU43EPY-BoOMwa6D.js → diagram-FQU43EPY-Br1g--ww.js} +1 -1
- package/dist/assets/{diagram-G47NLZAW-Le7N6Uym.js → diagram-G47NLZAW-D1wJCBgr.js} +1 -1
- package/dist/assets/{diagram-NH7WQ7WH-Fbpj3-MO.js → diagram-NH7WQ7WH-Cgg2auLH.js} +1 -1
- package/dist/assets/{diagram-OA4YK3LP-D3QuGGuu.js → diagram-OA4YK3LP-R-wHiWqh.js} +1 -1
- package/dist/assets/{diagram-WEI45ONY-Cxu1uiN6.js → diagram-WEI45ONY-CsNnKV0P.js} +1 -1
- package/dist/assets/dialog-DLOwdjT1.js +1 -0
- package/dist/assets/dist-ZaFFmAGl.js +41 -0
- package/dist/assets/doc-browser-ClDUWo9V.js +1 -0
- package/dist/assets/doc-browser-context-CTmOmuqa.js +1 -0
- package/dist/assets/{docx-preview-CkU2psnd.js → docx-preview-kPn_EtAr.js} +1 -1
- package/dist/assets/{download-BoaKzDJk.js → download-DovI3Yvf.js} +1 -1
- package/dist/assets/{ebnfDiagram-CCIWWBDH-CCAjuQM6.js → ebnfDiagram-CCIWWBDH-DCyhIPdi.js} +1 -1
- package/dist/assets/{erDiagram-Q63AITRT-BuzUAq-d.js → erDiagram-Q63AITRT-D0ZJYAUf.js} +1 -1
- package/dist/assets/eventmodeling-45OFAUF4-SIhbIFIw.js +1 -0
- package/dist/assets/extensions-BZ3qrM8M.js +1 -0
- package/dist/assets/external-link-DUD3AbsF.js +1 -0
- package/dist/assets/flowDiagram-23GEKE2U-DdAjkU7I.js +1 -0
- package/dist/assets/{form-actions-D9JWSFQu.js → form-actions-B8VniHts.js} +1 -1
- package/dist/assets/{ganttDiagram-NO4QXBWP-cJmWVY8F.js → ganttDiagram-NO4QXBWP-CiXDcXZD.js} +1 -1
- package/dist/assets/gitGraph-TEB2WS4Q-DnMNpESZ.js +1 -0
- package/dist/assets/{gitGraphDiagram-IHSO6WYX-F58o-vtP.js → gitGraphDiagram-IHSO6WYX-BSiIV48S.js} +1 -1
- package/dist/assets/{i18n-Bm3Ov7Fy.js → i18n-IGQbjBqS.js} +2 -2
- package/dist/assets/inbox-BjBZIbgx.js +1 -0
- package/dist/assets/inbox-ClAG7SI_.js +1 -0
- package/dist/assets/info-DKCQHKI2-BSm-69p_.js +1 -0
- package/dist/assets/{infoDiagram-FWYZ7A6U-Gt59b83C.js → infoDiagram-FWYZ7A6U-CCIgBCVq.js} +1 -1
- package/dist/assets/{ishikawaDiagram-FXEZZL3T-1u4IAj1I.js → ishikawaDiagram-FXEZZL3T-nQ_baN5u.js} +1 -1
- package/dist/assets/{journeyDiagram-5HDEW3XC-CCQsfV-5.js → journeyDiagram-5HDEW3XC-ABueIPzj.js} +1 -1
- package/dist/assets/{kanban-definition-HUTT4EX6-vlB6O_Zn.js → kanban-definition-HUTT4EX6-8FKS3fmQ.js} +1 -1
- package/dist/assets/katex-DPgHtix3.js +1 -0
- package/dist/assets/keyboard-shortcuts-settings-page-BqfbbKir.js +1 -0
- package/dist/assets/{line-D_bHubTL.js → line-Biw8iEUz.js} +1 -1
- package/dist/assets/{linear-ChlwuS5y.js → linear-D7CWUHTF.js} +1 -1
- package/dist/assets/login-page-BxSMwUsc.js +1 -0
- package/dist/assets/{login-page-C-DvcG3L.js → login-page-DYaozpzz.js} +1 -1
- package/dist/assets/main-CWYF9QU_.js +2 -0
- package/dist/assets/main-D_zmSVS1.css +1 -0
- package/dist/assets/main-i18n-catalog.config-itg3Gvzp.js +1 -0
- package/dist/assets/{map-oGHTsIu8.js → map-CDu47gTf.js} +1 -1
- package/dist/assets/marketplace-CnQ5USfr.js +1 -0
- package/dist/assets/mcp-marketplace-page-Dor6H9IC.js +1 -0
- package/dist/assets/{mermaid-parser.core-CuRe1ZG4.js → mermaid-parser.core-Cc9wjl82.js} +2 -2
- package/dist/assets/{mermaid.core-u4YCFKRf.js → mermaid.core-GWlaVWz1.js} +3 -3
- package/dist/assets/{mindmap-definition-LN4V7U3C-DeJAQYTu.js → mindmap-definition-LN4V7U3C-oqnKsz-R.js} +1 -1
- package/dist/assets/model-config-page-Cduyz2Hy.js +1 -0
- package/dist/assets/{navigation-link-CjxNC8aT.js → navigation-link-D-JSWFxj.js} +2 -2
- package/dist/assets/{ordinal-C6JFfkKN.js → ordinal-DImbxqBz.js} +1 -1
- package/dist/assets/packet-7NZHBO7P-1YQvC6mT.js +1 -0
- package/dist/assets/panel-app-BBTg0tVp.js +1 -0
- package/dist/assets/panel-app-i18n-catalog.config-BfLHr1tc.js +1 -0
- package/dist/assets/panel-apps-C-izvtu9.js +1 -0
- package/dist/assets/panelStandalone-XRlWxbRS.css +1 -0
- package/dist/assets/panelStandalone-oHxbXvYt.js +2 -0
- package/dist/assets/{pegDiagram-2B236MQR-nVMkxShH.js → pegDiagram-2B236MQR-DYAB8CEz.js} +1 -1
- package/dist/assets/pie-RZYD4A2V-BGoNOSwu.js +1 -0
- package/dist/assets/{pieDiagram-ENE6RG2P-8aUH44QZ.js → pieDiagram-ENE6RG2P-DGsH0Kk5.js} +1 -1
- package/dist/assets/plus-DUdl68Eo.js +1 -0
- package/dist/assets/privacy-settings-page-DG9E8N-F.js +1 -0
- package/dist/assets/projects-CzBaTOTL.js +1 -0
- package/dist/assets/provider-models-COzjYl29.js +1 -0
- package/dist/assets/provider-scoped-model-input-Cvy74uj8.js +1 -0
- package/dist/assets/providers-config-page-7rCwVnhh.js +1 -0
- package/dist/assets/puzzle-C5Wfpjk_.js +1 -0
- package/dist/assets/pwa-CAg_9zFs.js +1 -0
- package/dist/assets/{quadrantDiagram-ABIIQ3AL-EY8hpFv8.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-CNhcIeji.js → railroadDiagram-RFXS5EU6-B3yJ2yxE.js} +1 -1
- package/dist/assets/{refresh-cw-BlXDrVP0.js → refresh-cw-OhwaPDn1.js} +1 -1
- package/dist/assets/remote-DvCdHjzA.js +1 -0
- package/dist/assets/{requirementDiagram-TGXJPOKE-D8Dcs-Rt.js → requirementDiagram-TGXJPOKE-DtEyoEXG.js} +1 -1
- package/dist/assets/{rotate-cw-ei6rPD6z.js → rotate-cw-aBponvp7.js} +1 -1
- package/dist/assets/runtime-config-page-BF1wxvzR.js +1 -0
- package/dist/assets/{sankeyDiagram-HTMAVEWB-HTrb6aa-.js → sankeyDiagram-HTMAVEWB-h9AYS2UB.js} +1 -1
- package/dist/assets/{save-DdF-bXgC.js → save-394QCMXn.js} +1 -1
- package/dist/assets/search-BG2qAlNZ.js +1 -0
- package/dist/assets/search-config-page-D4LeiB9y.js +1 -0
- package/dist/assets/secrets-config-page-BzGcr5Vw.js +3 -0
- package/dist/assets/security-config-vD_V0BQF.js +1 -0
- package/dist/assets/select-xUXYV0Gr.js +1 -0
- package/dist/assets/{sequenceDiagram-DBY2YBRQ-6f_4X16Y.js → sequenceDiagram-DBY2YBRQ-D-uxCkob.js} +1 -1
- package/dist/assets/service-apps-panel-D3wwPRzV.js +1 -0
- package/dist/assets/{settings-2-CrNhfInU.js → settings-2-CWOGRRaA.js} +1 -1
- package/dist/assets/{sizeCapture-X5ZJPWSS-Ck9rsuwL.js → sizeCapture-X5ZJPWSS-DBzZytQo.js} +1 -1
- package/dist/assets/{src-C8AUg09O.js → src-zrGbZsfc.js} +1 -1
- package/dist/assets/{stateDiagram-2N3HPSRC-Cm33MLHu.js → stateDiagram-2N3HPSRC-DyDy7AHq.js} +1 -1
- package/dist/assets/stateDiagram-v2-6OUMAXLB-CtkpO6aA.js +1 -0
- package/dist/assets/{status-dot-C3SRFEta.js → status-dot-CYifnSnt.js} +1 -1
- package/dist/assets/{swimlanes-5IMT3BWC-B107vmvM.js → swimlanes-5IMT3BWC-BzOduS38.js} +2 -2
- package/dist/assets/swimlanesDiagram-G3AALYLV-BSdi6mvi.js +8 -0
- package/dist/assets/tag-chip-CjM6lyeh.js +1 -0
- package/dist/assets/theme-provider-BToFZGZG.js +1 -0
- package/dist/assets/{timeline-definition-FHXFAJF6-CJEoAj33.js → timeline-definition-FHXFAJF6-CmgnEF2t.js} +1 -1
- package/dist/assets/trash-2-DvJ6duOW.js +1 -0
- 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-BYDjFlpt.js → use-desktop-capabilities-B-u6ojjW.js} +1 -1
- package/dist/assets/use-viewport-layout-IKKGpjzF.js +1 -0
- package/dist/assets/{vennDiagram-L72KCM5P-DzsUHk5I.js → vennDiagram-L72KCM5P-DwS7D2kg.js} +1 -1
- package/dist/assets/wardley-OPB4EBWU-Dqxe7zN6.js +1 -0
- package/dist/assets/{wardleyDiagram-EHGQE667-1NfFs5ua.js → wardleyDiagram-EHGQE667-B4X8OOL4.js} +1 -1
- package/dist/assets/x-E9VB4HQx.js +1 -0
- package/dist/assets/{xychartDiagram-FW5EYKEG-Ci8AI3Qo.js → xychartDiagram-FW5EYKEG-BjRQ_0nx.js} +1 -1
- package/dist/index.html +44 -106
- package/dist/panel-standalone.html +19 -13
- package/index.html +15 -66
- package/package.json +5 -5
- package/src/app/styles/design-system.css +85 -1
- package/src/app/styles/island-theme.css +8 -6
- package/src/features/agents/components/__tests__/agents-page.test.tsx +8 -5
- package/src/features/agents/components/agent-details-dialog.tsx +24 -18
- package/src/features/agents/components/agents-page.tsx +27 -38
- package/src/features/app-data/components/app-retained-data-section.tsx +4 -4
- package/src/features/apps/components/__tests__/app-marketplace-catalog.test.tsx +2 -2
- package/src/features/apps/components/__tests__/app-packages-panel.test.tsx +94 -23
- package/src/features/apps/components/__tests__/apps-panel.test.tsx +5 -3
- package/src/features/apps/components/app-document-access-section.tsx +17 -14
- package/src/features/apps/components/app-marketplace-catalog.tsx +69 -42
- package/src/features/apps/components/app-marketplace-cover.tsx +5 -2
- package/src/features/apps/components/app-marketplace-detail.tsx +20 -8
- package/src/features/apps/components/app-marketplace-operation.tsx +8 -3
- package/src/features/apps/components/app-marketplace-panel.tsx +168 -0
- package/src/features/apps/components/app-package-card.tsx +224 -147
- package/src/features/apps/components/app-package-details-dialog.tsx +103 -0
- package/src/features/apps/components/app-packages-panel.tsx +162 -147
- package/src/features/apps/components/apps-panel.tsx +43 -12
- package/src/features/chat/components/conversation/chat-conversation-header-section.tsx +1 -1
- package/src/features/chat/components/conversation/chat-conversation-header.tsx +1 -1
- package/src/features/chat/components/layout/chat-sidebar-toolbar.tsx +2 -2
- package/src/features/chat/components/layout/chat-sidebar-utility-menu.tsx +9 -7
- 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/floating-session-conversation.tsx +2 -3
- package/src/features/chat/features/conversation/components/session-conversation-area.tsx +9 -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 +86 -10
- package/src/features/chat/features/conversation/hooks/__tests__/use-session-conversation-input-state.test.tsx +44 -1
- package/src/features/chat/features/conversation/hooks/use-session-conversation-controller.ts +85 -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/message/utils/chat-message-execution-summary.utils.ts +3 -0
- package/src/features/chat/features/message/utils/chat-message-texts.utils.ts +1 -0
- package/src/features/chat/features/message/utils/chat-message-trigger-details.utils.ts +3 -0
- package/src/features/chat/features/session/components/chat-sidebar-project-groups.tsx +1 -1
- package/src/features/chat/features/session/components/session-header/chat-session-metadata-dialog.tsx +1 -1
- package/src/features/chat/features/session/components/session-header/chat-session-project-badge.tsx +2 -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/welcome/components/__tests__/chat-welcome.test.tsx +31 -6
- package/src/features/chat/features/welcome/components/chat-conversation-welcome.tsx +13 -1
- package/src/features/chat/features/welcome/components/chat-welcome-agent-picker.tsx +1 -1
- package/src/features/chat/features/welcome/components/chat-welcome-project-picker.tsx +1 -1
- package/src/features/chat/features/welcome/components/chat-welcome-prompt-suggestions.tsx +56 -13
- package/src/features/chat/features/welcome/components/chat-welcome-session-type-picker.tsx +3 -3
- package/src/features/chat/features/welcome/components/chat-welcome.tsx +14 -4
- package/src/features/chat/features/welcome/utils/__tests__/chat-welcome-continuation.utils.test.ts +40 -0
- package/src/features/chat/features/welcome/utils/chat-welcome-continuation.utils.ts +21 -0
- 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-directory-browser.tsx +1 -1
- package/src/features/chat/features/workspace/components/chat-session-workspace-file-breadcrumbs.tsx +3 -7
- package/src/features/chat/features/workspace/components/chat-session-workspace-file-preview.tsx +6 -5
- package/src/features/chat/features/workspace/components/chat-session-workspace-panel-content.tsx +27 -27
- package/src/features/chat/features/workspace/components/overview/chat-session-continuous-attention.tsx +11 -11
- package/src/features/chat/features/workspace/components/overview/chat-session-token-usage.tsx +15 -15
- package/src/features/chat/features/workspace/components/project-files/workspace-directory-tree.tsx +2 -2
- package/src/features/chat/features/workspace/components/project-files/workspace-new-folder-tree-item.tsx +1 -1
- package/src/features/chat/features/workspace/components/project-files/workspace-project-files-toolbar.tsx +2 -2
- package/src/features/chat/features/workspace/components/session-cron-job-content.tsx +13 -26
- 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/components/cron-job-row.tsx +5 -4
- package/src/features/cron/index.ts +1 -0
- package/src/features/desktop-capabilities/components/desktop-authorization-dialog.tsx +5 -5
- package/src/features/inbox/components/inbox-reader-dialog.test.tsx +46 -6
- package/src/features/inbox/components/inbox-reader-dialog.tsx +38 -29
- package/src/features/inbox/managers/inbox.manager.test.ts +28 -0
- package/src/features/inbox/managers/inbox.manager.ts +18 -4
- package/src/features/inbox/pages/inbox-page.test.ts +4 -2
- package/src/features/inbox/pages/inbox-page.tsx +14 -10
- 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/components/panel-app-list-item.tsx +4 -3
- package/src/features/panel-apps/components/panel-app-service-action-authorization-dialog.tsx +2 -2
- package/src/features/panel-apps/index.ts +1 -0
- package/src/features/panel-apps/utils/panel-app-doc-browser.utils.tsx +5 -24
- package/src/features/projects/components/work/project-work-item-drawer.tsx +7 -10
- package/src/features/projects/components/work/project-work-items.tsx +1 -1
- 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/pwa/managers/__tests__/pwa-shell-theme.manager.test.ts +3 -3
- package/src/features/pwa/managers/pwa-shell-theme.manager.ts +8 -3
- package/src/features/right-panel-resources/components/__tests__/page-resource-icon.test.tsx +13 -2
- 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 +16 -8
- 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/index.ts +3 -0
- 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 +17 -0
- package/src/features/right-panel-resources/utils/right-panel-resource-uri.utils.ts +3 -2
- package/src/features/service-apps/components/service-action-row.tsx +4 -3
- package/src/features/service-apps/components/service-app-delete-dialog.tsx +2 -2
- package/src/features/service-apps/components/service-app-list-item.tsx +5 -4
- package/src/features/service-apps/components/service-apps-panel.tsx +5 -2
- package/src/features/settings/components/config/provider-model-suggestions-panel.tsx +1 -1
- package/src/features/settings/pages/providers-config-page.tsx +3 -2
- package/src/index.css +42 -8
- 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/doc-browser-tab-strip.tsx +2 -2
- 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/path-picker/server-path-picker-dialog.tsx +5 -3
- package/src/shared/components/ui/__tests__/dialog.test.tsx +37 -1
- package/src/shared/components/ui/actions/action-feedback.ts +1 -8
- package/src/shared/components/ui/actions/icon-action-button.tsx +1 -1
- package/src/shared/components/ui/confirm-dialog.tsx +1 -2
- package/src/shared/components/ui/context-menu/context-menu-items.tsx +2 -2
- package/src/shared/components/ui/dialog.tsx +29 -7
- package/src/shared/components/ui/popover.tsx +14 -3
- package/src/shared/components/ui/skeleton.tsx +16 -2
- package/src/shared/components/ui/tab-strip/compact-tab-strip.tsx +2 -2
- package/src/shared/components/ui/tooltip.tsx +2 -1
- package/src/shared/components/workbench/__tests__/workbench-surface.test.tsx +21 -0
- package/src/shared/components/workbench/workbench-surface-toolbar.tsx +4 -0
- package/src/shared/components/workbench/workbench-surface.tsx +4 -1
- package/src/shared/lib/i18n/locales/en-US/chat.json +21 -7
- package/src/shared/lib/i18n/locales/en-US/core.json +5 -1
- package/src/shared/lib/i18n/locales/en-US/doc-browser.json +10 -5
- package/src/shared/lib/i18n/locales/en-US/inbox.json +1 -0
- package/src/shared/lib/i18n/locales/zh-CN/chat.json +21 -7
- package/src/shared/lib/i18n/locales/zh-CN/core.json +5 -1
- package/src/shared/lib/i18n/locales/zh-CN/doc-browser.json +11 -6
- package/src/shared/lib/i18n/locales/zh-CN/inbox.json +1 -0
- package/src/shared/lib/theme/index.test.ts +28 -1
- package/src/shared/lib/theme/index.ts +14 -3
- 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-BAH7FW6z.js +0 -1
- package/dist/assets/api-DjiZvIa0.js +0 -20
- package/dist/assets/app-presenter-provider-CCRFsFYr.js +0 -232
- package/dist/assets/appearance-settings-page-CdP86QJ7.js +0 -1
- package/dist/assets/architecture-TIHT7OUA-CvnC-LeA.js +0 -1
- package/dist/assets/channel-CpMstUPF.js +0 -1
- package/dist/assets/channels-list-page-5qGagKuE.js +0 -8
- package/dist/assets/chunk-2Q5K7J3B-Djp3VF0s.js +0 -1
- package/dist/assets/chunk-VAUOI2AC-BrbiIC1Q.js +0 -1
- package/dist/assets/chunk-XXDRQBXY-Cx9N40wF.js +0 -1
- package/dist/assets/classDiagram-OUVF2IWQ-DFN1v3PQ.js +0 -1
- package/dist/assets/classDiagram-v2-EOCWNBFH-DRvglADa.js +0 -1
- package/dist/assets/config-split-page-CuEGQL8Z.js +0 -1
- package/dist/assets/confirm-dialog-CxfecBzO.js +0 -1
- package/dist/assets/context-menu-BsCj2fRs.js +0 -1
- package/dist/assets/cynefin-VYW2F7L2-DXUGnpJH.js +0 -1
- package/dist/assets/desktop-update-config-e-zhkJuS.js +0 -1
- package/dist/assets/dialog-QjQoKbIV.js +0 -5
- package/dist/assets/doc-browser-CLEdkH9z.js +0 -1
- package/dist/assets/doc-browser-context-DwgG6wrz.js +0 -1
- package/dist/assets/es2015-Bp6cuSGh.js +0 -41
- package/dist/assets/eventmodeling-45OFAUF4-ZBfVS3ZC.js +0 -1
- package/dist/assets/extensions-CgShSIkd.js +0 -1
- package/dist/assets/eye-kisejBFH.js +0 -1
- package/dist/assets/flowDiagram-23GEKE2U-CqdsKk6x.js +0 -1
- package/dist/assets/gitGraph-TEB2WS4Q-fHYFd9Es.js +0 -1
- package/dist/assets/info-DKCQHKI2-CSaOL_bb.js +0 -1
- package/dist/assets/katex-B4FQSo9k.js +0 -1
- package/dist/assets/keyboard-shortcuts-settings-page-DZ8A1iLg.js +0 -1
- package/dist/assets/loader-circle-Bd1fTm-x.js +0 -1
- package/dist/assets/login-page-D99JjH9F.js +0 -1
- package/dist/assets/main-Bt5r6b21.js +0 -2
- package/dist/assets/main-DXd_aKJV.css +0 -1
- package/dist/assets/main-i18n-catalog.config-D0Ll36J_.js +0 -1
- package/dist/assets/mcp-marketplace-page-DUoGfSmY.js +0 -1
- package/dist/assets/model-config-page-9NNf-mzK.js +0 -1
- package/dist/assets/packet-7NZHBO7P-D-YFTczs.js +0 -1
- package/dist/assets/panel-app-BYfQu_TS.js +0 -1
- package/dist/assets/panel-app-i18n-catalog.config-Ddf2Kv8A.js +0 -1
- package/dist/assets/panelStandalone-BRg7B1EI.css +0 -1
- package/dist/assets/panelStandalone-BaUzY8Wy.js +0 -2
- package/dist/assets/pie-RZYD4A2V-VEnYu9s5.js +0 -1
- package/dist/assets/privacy-settings-page-CVMBFuak.js +0 -1
- package/dist/assets/projects-BEsU3box.js +0 -1
- package/dist/assets/provider-models-Dm-pmWAA.js +0 -1
- package/dist/assets/provider-scoped-model-input-CzrXg4cX.js +0 -1
- package/dist/assets/providers-config-page-839uUADZ.js +0 -1
- package/dist/assets/puzzle-BGvD2DPZ.js +0 -1
- package/dist/assets/pwa-DNNK_8E9.js +0 -1
- package/dist/assets/radar-I7S5WNFK-BFNIekC1.js +0 -1
- package/dist/assets/railroad-3IZDKUUU-lVqJ3Hak.js +0 -1
- package/dist/assets/railroad-abnf-AHOZXSZD-DYaefdFC.js +0 -1
- package/dist/assets/railroad-ebnf-EBAXGLYW-CTAk6lVq.js +0 -1
- package/dist/assets/railroad-peg-LSFZ7HO6-Cob294tg.js +0 -1
- package/dist/assets/remote-B5qIuUbT.js +0 -1
- package/dist/assets/runtime-config-page-Bf-4JYxQ.js +0 -1
- package/dist/assets/search-config-page-C0qA3j-T.js +0 -1
- package/dist/assets/secrets-config-page-DxfZWpnk.js +0 -3
- package/dist/assets/security-config-CItfIQZ4.js +0 -1
- package/dist/assets/select-CWyjnar7.js +0 -1
- package/dist/assets/service-apps-panel-D3SOkRVv.js +0 -1
- package/dist/assets/stateDiagram-v2-6OUMAXLB-BrNv-raG.js +0 -1
- package/dist/assets/swimlanesDiagram-G3AALYLV-ntcxaPXp.js +0 -8
- package/dist/assets/tag-chip-BIuavK2K.js +0 -1
- package/dist/assets/theme-provider-CWUz4yO9.js +0 -1
- package/dist/assets/trash-2-hAbJh9VZ.js +0 -1
- package/dist/assets/treeView-QDETBFTQ-DbFmr-gw.js +0 -1
- package/dist/assets/treemap-6X3UGDF4-C8aY96pi.js +0 -1
- package/dist/assets/use-config-evzage09.js +0 -1
- package/dist/assets/use-viewport-layout-D_9XWGDV.js +0 -1
- package/dist/assets/wardley-OPB4EBWU-D8d6DbbJ.js +0 -1
- package/dist/assets/x-ChPbNv39.js +0 -1
- package/src/features/apps/components/app-marketplace-dialog.tsx +0 -168
- /package/dist/assets/{array-BV9OtnO8.js → array-DsNX3jRj.js} +0 -0
- /package/dist/assets/{chunk-KEIR6QF5-Cx-8EJ4_.js → chunk-KEIR6QF5-BOAXXeyv.js} +0 -0
- /package/dist/assets/{chunk-Y2CYZVJY-Dy1ufvjf.js → chunk-Y2CYZVJY-CHjSjwoV.js} +0 -0
- /package/dist/assets/{config-hints-DbmiyTKg.js → config-hints-CaB3I7KP.js} +0 -0
- /package/dist/assets/{cytoscape.esm-CSCjuT4Z.js → cytoscape.esm-j4J9a91l.js} +0 -0
- /package/dist/assets/{defaultLocale-DWTiNsbT.js → defaultLocale-Bmxjp-V_.js} +0 -0
- /package/dist/assets/{dist-BVCSkfWY.js → dist-DwLj1Wg5.js} +0 -0
- /package/dist/assets/{graphlib-B1yb1Wl8.js → graphlib-CC0HTn1v.js} +0 -0
- /package/dist/assets/{host-capabilities-DuIFVsvM.js → host-capabilities-B107nwS3.js} +0 -0
- /package/dist/assets/{init-BF6GH5oe.js → init-Biz9Rus1.js} +0 -0
- /package/dist/assets/{jszip.min-D12teKzP.js → jszip.min-DQvBVV_R.js} +0 -0
- /package/dist/assets/{katex-CsAM73R9.js → katex-BzT-4KBu.js} +0 -0
- /package/dist/assets/{navigation-history-CzErJuPG.js → navigation-history-CCnxsAKR.js} +0 -0
- /package/dist/assets/{path-C56XkznJ.js → path-4azsBPZv.js} +0 -0
- /package/dist/assets/{preload-helper-ca-nBW7U.js → preload-helper-DWTEM3RW.js} +0 -0
- /package/dist/assets/{rough.esm-CGfeEbtE.js → rough.esm-w1lBArN6.js} +0 -0
- /package/dist/assets/{xlsx-sds5nUpL.js → xlsx--SB9KlFl.js} +0 -0
package/src/features/chat/features/conversation/hooks/use-session-conversation-controller.ts
CHANGED
|
@@ -5,12 +5,14 @@ import type {
|
|
|
5
5
|
UiNcpSessionQueuedInputView,
|
|
6
6
|
} from '@nextclaw/client-sdk';
|
|
7
7
|
import type { NcpAgentSendEnvelope, NcpRunHandle } from '@nextclaw/ncp';
|
|
8
|
+
import { NcpHttpSendError } from '@nextclaw/ncp-http-agent-client';
|
|
8
9
|
|
|
9
10
|
import {
|
|
10
11
|
createChatComposerNodesFromDraft,
|
|
11
12
|
deriveNcpMessagePartsFromComposer,
|
|
12
13
|
} from '@/features/chat/features/input/utils/chat-composer-state.utils';
|
|
13
14
|
import { isNcpChatSendDisabled } from '@/features/chat/features/input/utils/ncp-chat-input-availability.utils';
|
|
15
|
+
import { t } from '@/shared/lib/i18n';
|
|
14
16
|
import { buildChatRunMetadata } from '@/features/chat/features/session/utils/chat-run-metadata.utils';
|
|
15
17
|
import { createNcpSessionId } from '@/features/chat/features/session/utils/ncp-session-adapter.utils';
|
|
16
18
|
import type { SessionQueuedInputAttachmentPreview } from '@/features/chat/features/conversation/utils/session-queued-input.utils';
|
|
@@ -25,6 +27,7 @@ import {
|
|
|
25
27
|
useSessionConversationRecoveryActions,
|
|
26
28
|
type SessionConversationRecoveryAgent,
|
|
27
29
|
} from './use-session-conversation-recovery-actions';
|
|
30
|
+
import { useSessionSubmissionRecovery } from './use-session-submission-recovery';
|
|
28
31
|
|
|
29
32
|
type SessionConversationInputQuery = ReturnType<typeof useSessionConversationInputQuery>;
|
|
30
33
|
type ComposerDraftSnapshot = Pick<
|
|
@@ -80,8 +83,12 @@ type UseSessionConversationControllerParams = {
|
|
|
80
83
|
readonly selectedAgentId: string;
|
|
81
84
|
readonly sessionKey: string | null;
|
|
82
85
|
readonly onSessionMaterialized?: (sessionKey: string) => void;
|
|
83
|
-
readonly resetComposer: () => void;
|
|
84
86
|
readonly restoreComposer: (snapshot: ComposerDraftSnapshot) => void;
|
|
87
|
+
readonly beginSubmission: (envelope: NcpAgentSendEnvelope, composer: ComposerDraftSnapshot) => void;
|
|
88
|
+
readonly acceptSubmission: (messageId: string) => void;
|
|
89
|
+
readonly failSubmission: (messageId: string, status: 'uncertain' | 'rejected', message: string) => void;
|
|
90
|
+
readonly restoreSubmission: (messageId: string) => void;
|
|
91
|
+
readonly discardSubmission: (messageId: string) => void;
|
|
85
92
|
readonly setSendError: (message: string | null) => void;
|
|
86
93
|
};
|
|
87
94
|
|
|
@@ -90,7 +97,6 @@ type BuildSubmissionDraftParams = {
|
|
|
90
97
|
readonly composerSnapshot?: ComposerDraftSnapshot;
|
|
91
98
|
readonly inputSnapshot: SessionConversationInputSnapshot;
|
|
92
99
|
readonly inputQuery: SessionConversationInputQuery;
|
|
93
|
-
readonly isRuntimeBlocked: boolean;
|
|
94
100
|
readonly materializationContext?: SessionConversationMaterializationContext | null;
|
|
95
101
|
readonly selectedAgentId: string;
|
|
96
102
|
readonly sessionKey: string | null;
|
|
@@ -111,21 +117,12 @@ const resolveModelForSend = (value: string | null | undefined): string | undefin
|
|
|
111
117
|
return trimmed || undefined;
|
|
112
118
|
};
|
|
113
119
|
|
|
114
|
-
function buildInputAvailabilitySnapshot(inputQuery: SessionConversationInputQuery) {
|
|
115
|
-
return {
|
|
116
|
-
isProviderStateResolved: inputQuery.isProviderStateResolved,
|
|
117
|
-
modelOptions: inputQuery.modelOptions,
|
|
118
|
-
sessionTypeUnavailable: inputQuery.sessionTypeState.sessionTypeUnavailable,
|
|
119
|
-
};
|
|
120
|
-
}
|
|
121
|
-
|
|
122
120
|
function buildSubmissionDraft(params: BuildSubmissionDraftParams): SubmissionDraft | null {
|
|
123
121
|
const {
|
|
124
122
|
agentIsSending,
|
|
125
123
|
composerSnapshot: requestedComposerSnapshot,
|
|
126
124
|
inputQuery,
|
|
127
125
|
inputSnapshot,
|
|
128
|
-
isRuntimeBlocked,
|
|
129
126
|
materializationContext,
|
|
130
127
|
selectedAgentId,
|
|
131
128
|
sessionKey,
|
|
@@ -142,10 +139,9 @@ function buildSubmissionDraft(params: BuildSubmissionDraftParams): SubmissionDra
|
|
|
142
139
|
composerSnapshot.attachments,
|
|
143
140
|
);
|
|
144
141
|
if (
|
|
142
|
+
inputSnapshot.pendingSubmission ||
|
|
145
143
|
isNcpChatSendDisabled({
|
|
146
|
-
snapshot: buildInputAvailabilitySnapshot(inputQuery),
|
|
147
144
|
hasSendableDraft: hasSendableMessagePart(currentParts),
|
|
148
|
-
isRuntimeBlocked,
|
|
149
145
|
}) ||
|
|
150
146
|
agentIsSending
|
|
151
147
|
) {
|
|
@@ -197,6 +193,7 @@ function buildSubmissionEnvelope(
|
|
|
197
193
|
): NcpAgentSendEnvelope | null {
|
|
198
194
|
const envelope = buildNcpRequestEnvelope({
|
|
199
195
|
sessionId: sessionKey ?? undefined,
|
|
196
|
+
messageId: `user-${crypto.randomUUID()}`,
|
|
200
197
|
text: draft.composerSnapshot.text.trim(),
|
|
201
198
|
attachments: [...draft.composerSnapshot.attachments],
|
|
202
199
|
parts: deriveNcpMessagePartsFromComposer(
|
|
@@ -205,7 +202,7 @@ function buildSubmissionEnvelope(
|
|
|
205
202
|
),
|
|
206
203
|
metadata: draft.metadata,
|
|
207
204
|
});
|
|
208
|
-
return envelope ? { ...envelope, delivery } : null;
|
|
205
|
+
return envelope ? { ...envelope, delivery, idempotencyKey: envelope.message.id } : null;
|
|
209
206
|
}
|
|
210
207
|
|
|
211
208
|
function useSubmissionDraftRunner(params: {
|
|
@@ -213,8 +210,9 @@ function useSubmissionDraftRunner(params: {
|
|
|
213
210
|
readonly clearSubmittingInput: (input: SubmittingQueuedInput) => void;
|
|
214
211
|
readonly materializationContext?: SessionConversationMaterializationContext | null;
|
|
215
212
|
readonly onSessionMaterialized?: (sessionKey: string) => void;
|
|
216
|
-
readonly
|
|
217
|
-
readonly
|
|
213
|
+
readonly beginSubmission: (envelope: NcpAgentSendEnvelope, composer: ComposerDraftSnapshot) => void;
|
|
214
|
+
readonly acceptSubmission: (messageId: string) => void;
|
|
215
|
+
readonly failSubmission: (messageId: string, status: 'uncertain' | 'rejected', message: string) => void;
|
|
218
216
|
readonly runQueue: SessionRunQueue;
|
|
219
217
|
readonly sessionKey: string | null;
|
|
220
218
|
readonly setSendError: (message: string | null) => void;
|
|
@@ -225,8 +223,9 @@ function useSubmissionDraftRunner(params: {
|
|
|
225
223
|
clearSubmittingInput,
|
|
226
224
|
materializationContext,
|
|
227
225
|
onSessionMaterialized,
|
|
228
|
-
|
|
229
|
-
|
|
226
|
+
beginSubmission,
|
|
227
|
+
acceptSubmission,
|
|
228
|
+
failSubmission,
|
|
230
229
|
runQueue,
|
|
231
230
|
sessionKey,
|
|
232
231
|
setSendError,
|
|
@@ -244,10 +243,16 @@ function useSubmissionDraftRunner(params: {
|
|
|
244
243
|
const queuedSubmission = agent.isRunning && delivery === 'queue'
|
|
245
244
|
? stageSubmittingInput(envelope)
|
|
246
245
|
: null;
|
|
247
|
-
if (composerBehavior === 'reset-and-restore')
|
|
246
|
+
if (composerBehavior === 'reset-and-restore') beginSubmission(envelope, draft.composerSnapshot);
|
|
248
247
|
setSendError(null);
|
|
248
|
+
let definitelyRejected = false;
|
|
249
249
|
try {
|
|
250
250
|
const handle = await agent.send(envelope);
|
|
251
|
+
if (!handle) {
|
|
252
|
+
definitelyRejected = true;
|
|
253
|
+
throw new Error(t('chatSendFailed'));
|
|
254
|
+
}
|
|
255
|
+
if (composerBehavior === 'reset-and-restore') acceptSubmission(envelope.message.id);
|
|
251
256
|
if (handle?.delivery === 'steered') {
|
|
252
257
|
await runQueue.refreshPendingInputs().catch(() => undefined);
|
|
253
258
|
} else if (handle?.delivery === 'queued') {
|
|
@@ -261,8 +266,12 @@ function useSubmissionDraftRunner(params: {
|
|
|
261
266
|
}
|
|
262
267
|
} catch (error) {
|
|
263
268
|
if (queuedSubmission) clearSubmittingInput(queuedSubmission);
|
|
264
|
-
|
|
265
|
-
|
|
269
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
270
|
+
if (composerBehavior === 'reset-and-restore') {
|
|
271
|
+
failSubmission(envelope.message.id,
|
|
272
|
+
definitelyRejected || (error instanceof NcpHttpSendError && error.sendRejected) ? 'rejected' : 'uncertain',
|
|
273
|
+
message);
|
|
274
|
+
} else setSendError(message);
|
|
266
275
|
throw error;
|
|
267
276
|
}
|
|
268
277
|
}, [
|
|
@@ -270,8 +279,9 @@ function useSubmissionDraftRunner(params: {
|
|
|
270
279
|
clearSubmittingInput,
|
|
271
280
|
materializationContext,
|
|
272
281
|
onSessionMaterialized,
|
|
273
|
-
|
|
274
|
-
|
|
282
|
+
beginSubmission,
|
|
283
|
+
acceptSubmission,
|
|
284
|
+
failSubmission,
|
|
275
285
|
runQueue,
|
|
276
286
|
sessionKey,
|
|
277
287
|
setSendError,
|
|
@@ -283,7 +293,6 @@ function useSteeringSubmission(params: {
|
|
|
283
293
|
readonly agent: SessionConversationAgent;
|
|
284
294
|
readonly inputSnapshot: SessionConversationInputSnapshot;
|
|
285
295
|
readonly inputQuery: SessionConversationInputQuery;
|
|
286
|
-
readonly isRuntimeBlocked: boolean;
|
|
287
296
|
readonly materializationContext?: SessionConversationMaterializationContext | null;
|
|
288
297
|
readonly selectedAgentId: string;
|
|
289
298
|
readonly sessionKey: string | null;
|
|
@@ -297,7 +306,6 @@ function useSteeringSubmission(params: {
|
|
|
297
306
|
agent,
|
|
298
307
|
inputQuery,
|
|
299
308
|
inputSnapshot,
|
|
300
|
-
isRuntimeBlocked,
|
|
301
309
|
materializationContext,
|
|
302
310
|
selectedAgentId,
|
|
303
311
|
sessionKey,
|
|
@@ -308,7 +316,6 @@ function useSteeringSubmission(params: {
|
|
|
308
316
|
agentIsSending: agent.isSending,
|
|
309
317
|
inputSnapshot,
|
|
310
318
|
inputQuery,
|
|
311
|
-
isRuntimeBlocked,
|
|
312
319
|
materializationContext,
|
|
313
320
|
selectedAgentId,
|
|
314
321
|
sessionKey,
|
|
@@ -318,7 +325,6 @@ function useSteeringSubmission(params: {
|
|
|
318
325
|
agent.isSending,
|
|
319
326
|
inputQuery,
|
|
320
327
|
inputSnapshot,
|
|
321
|
-
isRuntimeBlocked,
|
|
322
328
|
materializationContext,
|
|
323
329
|
selectedAgentId,
|
|
324
330
|
sessionKey,
|
|
@@ -331,7 +337,6 @@ function usePrimarySubmission(params: {
|
|
|
331
337
|
readonly continueRun: () => Promise<void>;
|
|
332
338
|
readonly inputSnapshot: SessionConversationInputSnapshot;
|
|
333
339
|
readonly inputQuery: SessionConversationInputQuery;
|
|
334
|
-
readonly isRuntimeBlocked: boolean;
|
|
335
340
|
readonly materializationContext?: SessionConversationMaterializationContext | null;
|
|
336
341
|
readonly primaryAction: 'continue' | 'send';
|
|
337
342
|
readonly selectedAgentId: string;
|
|
@@ -346,7 +351,6 @@ function usePrimarySubmission(params: {
|
|
|
346
351
|
continueRun,
|
|
347
352
|
inputQuery,
|
|
348
353
|
inputSnapshot,
|
|
349
|
-
isRuntimeBlocked,
|
|
350
354
|
materializationContext,
|
|
351
355
|
primaryAction,
|
|
352
356
|
selectedAgentId,
|
|
@@ -359,7 +363,6 @@ function usePrimarySubmission(params: {
|
|
|
359
363
|
agentIsSending: agent.isSending,
|
|
360
364
|
inputSnapshot,
|
|
361
365
|
inputQuery,
|
|
362
|
-
isRuntimeBlocked,
|
|
363
366
|
materializationContext,
|
|
364
367
|
selectedAgentId,
|
|
365
368
|
sessionKey,
|
|
@@ -370,7 +373,6 @@ function usePrimarySubmission(params: {
|
|
|
370
373
|
continueRun,
|
|
371
374
|
inputQuery,
|
|
372
375
|
inputSnapshot,
|
|
373
|
-
isRuntimeBlocked,
|
|
374
376
|
materializationContext,
|
|
375
377
|
primaryAction,
|
|
376
378
|
selectedAgentId,
|
|
@@ -379,6 +381,32 @@ function usePrimarySubmission(params: {
|
|
|
379
381
|
]);
|
|
380
382
|
}
|
|
381
383
|
|
|
384
|
+
function usePresetSubmission(params: {
|
|
385
|
+
readonly agent: SessionConversationAgent;
|
|
386
|
+
readonly inputSnapshot: SessionConversationInputSnapshot;
|
|
387
|
+
readonly inputQuery: SessionConversationInputQuery;
|
|
388
|
+
readonly materializationContext?: SessionConversationMaterializationContext | null;
|
|
389
|
+
readonly selectedAgentId: string;
|
|
390
|
+
readonly sessionKey: string | null;
|
|
391
|
+
readonly submitDraft: (draft: SubmissionDraft, behavior: SubmissionComposerBehavior) => Promise<void>;
|
|
392
|
+
}) {
|
|
393
|
+
const { agent, inputSnapshot, inputQuery, materializationContext, selectedAgentId, sessionKey, submitDraft } = params;
|
|
394
|
+
return useCallback(async (message: string) => {
|
|
395
|
+
const text = message.trim();
|
|
396
|
+
if (!text) return;
|
|
397
|
+
const draft = buildSubmissionDraft({
|
|
398
|
+
agentIsSending: agent.isSending,
|
|
399
|
+
composerSnapshot: {
|
|
400
|
+
text,
|
|
401
|
+
nodes: createChatComposerNodesFromDraft(text),
|
|
402
|
+
selectedSkills: [], skillRecords: [], attachments: [],
|
|
403
|
+
},
|
|
404
|
+
inputSnapshot, inputQuery, materializationContext, selectedAgentId, sessionKey,
|
|
405
|
+
});
|
|
406
|
+
if (draft) await submitDraft(draft, 'preserve');
|
|
407
|
+
}, [agent.isSending, inputQuery, inputSnapshot, materializationContext, selectedAgentId, sessionKey, submitDraft]);
|
|
408
|
+
}
|
|
409
|
+
|
|
382
410
|
export function useSessionConversationController(params: UseSessionConversationControllerParams) {
|
|
383
411
|
const {
|
|
384
412
|
agent,
|
|
@@ -390,8 +418,12 @@ export function useSessionConversationController(params: UseSessionConversationC
|
|
|
390
418
|
selectedAgentId,
|
|
391
419
|
sessionKey,
|
|
392
420
|
onSessionMaterialized,
|
|
393
|
-
resetComposer,
|
|
394
421
|
restoreComposer,
|
|
422
|
+
beginSubmission,
|
|
423
|
+
acceptSubmission,
|
|
424
|
+
failSubmission,
|
|
425
|
+
restoreSubmission,
|
|
426
|
+
discardSubmission,
|
|
395
427
|
setSendError,
|
|
396
428
|
} = params;
|
|
397
429
|
const {
|
|
@@ -421,12 +453,10 @@ export function useSessionConversationController(params: UseSessionConversationC
|
|
|
421
453
|
);
|
|
422
454
|
const primaryAction: 'continue' | 'send' =
|
|
423
455
|
canContinue && !hasSendableDraft ? 'continue' : 'send';
|
|
424
|
-
const sendDisabled = primaryAction === 'continue'
|
|
456
|
+
const sendDisabled = inputSnapshot.pendingSubmission ? true : primaryAction === 'continue'
|
|
425
457
|
? false
|
|
426
458
|
: isNcpChatSendDisabled({
|
|
427
|
-
snapshot: buildInputAvailabilitySnapshot(inputQuery),
|
|
428
459
|
hasSendableDraft,
|
|
429
|
-
isRuntimeBlocked,
|
|
430
460
|
}) || agent.isSending;
|
|
431
461
|
|
|
432
462
|
const { continueRun, editMessage } = useSessionConversationRecoveryActions({
|
|
@@ -440,8 +470,9 @@ export function useSessionConversationController(params: UseSessionConversationC
|
|
|
440
470
|
clearSubmittingInput,
|
|
441
471
|
materializationContext,
|
|
442
472
|
onSessionMaterialized,
|
|
443
|
-
|
|
444
|
-
|
|
473
|
+
beginSubmission,
|
|
474
|
+
acceptSubmission,
|
|
475
|
+
failSubmission,
|
|
445
476
|
runQueue,
|
|
446
477
|
sessionKey,
|
|
447
478
|
setSendError,
|
|
@@ -453,7 +484,6 @@ export function useSessionConversationController(params: UseSessionConversationC
|
|
|
453
484
|
continueRun,
|
|
454
485
|
inputQuery,
|
|
455
486
|
inputSnapshot,
|
|
456
|
-
isRuntimeBlocked,
|
|
457
487
|
materializationContext,
|
|
458
488
|
primaryAction,
|
|
459
489
|
selectedAgentId,
|
|
@@ -465,52 +495,33 @@ export function useSessionConversationController(params: UseSessionConversationC
|
|
|
465
495
|
agent,
|
|
466
496
|
inputQuery,
|
|
467
497
|
inputSnapshot,
|
|
468
|
-
isRuntimeBlocked,
|
|
469
498
|
materializationContext,
|
|
470
499
|
selectedAgentId,
|
|
471
500
|
sessionKey,
|
|
472
501
|
submitDraft,
|
|
473
502
|
});
|
|
474
503
|
|
|
475
|
-
const sendPresetMessage =
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
}
|
|
480
|
-
const draft = buildSubmissionDraft({
|
|
481
|
-
agentIsSending: agent.isSending,
|
|
482
|
-
composerSnapshot: {
|
|
483
|
-
text,
|
|
484
|
-
nodes: createChatComposerNodesFromDraft(text),
|
|
485
|
-
selectedSkills: [],
|
|
486
|
-
skillRecords: [],
|
|
487
|
-
attachments: [],
|
|
488
|
-
},
|
|
489
|
-
inputSnapshot,
|
|
490
|
-
inputQuery,
|
|
491
|
-
isRuntimeBlocked,
|
|
492
|
-
materializationContext,
|
|
493
|
-
selectedAgentId,
|
|
494
|
-
sessionKey,
|
|
495
|
-
});
|
|
496
|
-
if (draft) {
|
|
497
|
-
await submitDraft(draft, 'preserve');
|
|
498
|
-
}
|
|
499
|
-
}, [
|
|
500
|
-
agent.isSending,
|
|
501
|
-
inputQuery,
|
|
502
|
-
inputSnapshot,
|
|
503
|
-
isRuntimeBlocked,
|
|
504
|
-
materializationContext,
|
|
505
|
-
selectedAgentId,
|
|
506
|
-
sessionKey,
|
|
507
|
-
submitDraft,
|
|
508
|
-
]);
|
|
504
|
+
const sendPresetMessage = usePresetSubmission({
|
|
505
|
+
agent, inputSnapshot, inputQuery, materializationContext,
|
|
506
|
+
selectedAgentId, sessionKey, submitDraft,
|
|
507
|
+
});
|
|
509
508
|
|
|
510
509
|
const stop = useCallback(async () => {
|
|
511
510
|
await agent.abort();
|
|
512
511
|
}, [agent]);
|
|
513
512
|
|
|
513
|
+
const submissionRecovery = useSessionSubmissionRecovery({
|
|
514
|
+
agent,
|
|
515
|
+
submission: inputSnapshot.pendingSubmission,
|
|
516
|
+
sessionKey,
|
|
517
|
+
onSessionMaterialized,
|
|
518
|
+
acceptSubmission,
|
|
519
|
+
failSubmission,
|
|
520
|
+
restoreSubmission,
|
|
521
|
+
discardSubmission,
|
|
522
|
+
setSendError,
|
|
523
|
+
});
|
|
524
|
+
|
|
514
525
|
return {
|
|
515
526
|
canContinue,
|
|
516
527
|
canStopGeneration: agent.isRunning,
|
|
@@ -525,6 +536,7 @@ export function useSessionConversationController(params: UseSessionConversationC
|
|
|
525
536
|
send,
|
|
526
537
|
sendSteering,
|
|
527
538
|
sendPresetMessage,
|
|
539
|
+
...submissionRecovery,
|
|
528
540
|
sendDisabled,
|
|
529
541
|
primaryAction,
|
|
530
542
|
stop,
|
package/src/features/chat/features/conversation/hooks/use-session-conversation-input-query.ts
CHANGED
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
filterNcpChatModelOptionsBySessionType,
|
|
13
13
|
} from '@/features/chat/features/ncp/utils/ncp-chat-query-derived.utils';
|
|
14
14
|
import { adaptNcpSessionSummaries } from '@/features/chat/features/session/utils/ncp-session-adapter.utils';
|
|
15
|
-
import {
|
|
15
|
+
import { resolveRecentSessionPreferenceSnapshot } from '@/features/chat/features/session/utils/chat-session-preference-governance.utils';
|
|
16
16
|
import { useChatSessionTypeState } from '@/features/chat/features/session-type/hooks/use-chat-session-type-state';
|
|
17
17
|
import { chatRecentModelsManager } from '@/features/chat/managers/chat-recent-models.manager';
|
|
18
18
|
import { useChatQueryStore } from '@/features/chat/stores/ncp-chat-query.store';
|
|
@@ -112,27 +112,17 @@ export function useSessionConversationInputQuery(params: UseSessionConversationI
|
|
|
112
112
|
const recentSessionTypeModel = chatRecentModelsManager
|
|
113
113
|
.read({ namespace: sessionTypeState.selectedSessionType })
|
|
114
114
|
.find((value) => availableModelValueSet.has(value));
|
|
115
|
-
const
|
|
115
|
+
const recentSessionPreferences = useMemo(
|
|
116
116
|
() =>
|
|
117
|
-
|
|
118
|
-
resolveRecentSessionPreferredValue<string>({
|
|
117
|
+
resolveRecentSessionPreferenceSnapshot({
|
|
119
118
|
sessions,
|
|
120
119
|
selectedSessionKey,
|
|
121
120
|
sessionType: sessionTypeState.selectedSessionType,
|
|
122
|
-
readPreference: (session) => session.preferredModel?.trim() || undefined,
|
|
123
|
-
}),
|
|
124
|
-
[recentSessionTypeModel, selectedSessionKey, sessionTypeState.selectedSessionType, sessions],
|
|
125
|
-
);
|
|
126
|
-
const fallbackPreferredThinking = useMemo(
|
|
127
|
-
() =>
|
|
128
|
-
resolveRecentSessionPreferredValue({
|
|
129
|
-
sessions,
|
|
130
|
-
selectedSessionKey,
|
|
131
|
-
sessionType: sessionTypeState.selectedSessionType,
|
|
132
|
-
readPreference: (session) => session.preferredThinking ?? undefined,
|
|
133
121
|
}),
|
|
134
122
|
[selectedSessionKey, sessionTypeState.selectedSessionType, sessions],
|
|
135
123
|
);
|
|
124
|
+
const fallbackPreferredModel = recentSessionPreferences?.model ?? recentSessionTypeModel;
|
|
125
|
+
const fallbackPreferredThinking = recentSessionPreferences?.thinking;
|
|
136
126
|
|
|
137
127
|
const defaultProjectRoot = normalizeSessionProjectRootValue(
|
|
138
128
|
config?.agents.defaults.workspace,
|
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
|
+
};
|