specrails-desktop 2.29.0 → 2.29.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/client/dist/assets/ActivityFeedPage-ClpD5CFj.js +1 -0
- package/client/dist/assets/AgentBrowserCapture-CSPs9Ofc.js +1 -0
- package/client/dist/assets/AgentModeCodePane-DwcyklA5.js +2 -0
- package/client/dist/assets/AgentModeJobsPane-C69bqlMa.js +1 -0
- package/client/dist/assets/AgentsPage-pRiRr9-W.js +86 -0
- package/client/dist/assets/AnalyticsPage-C14exKsC.js +1 -0
- package/client/dist/assets/BarChart-nBOMNfiy.js +33 -0
- package/client/dist/assets/CodePage-CK76JKm9.js +2 -0
- package/client/dist/assets/DesktopAnalyticsPage-Cnv0f3XQ.js +1 -0
- package/client/dist/assets/DocsDialog-CHUm_Ym0.js +11 -0
- package/client/dist/assets/DocsPage-COI-oDok.js +11 -0
- package/client/dist/assets/ExportDropdown-BrtfWzEG.js +1 -0
- package/client/dist/assets/IntegrationsPage-Bs00_tl4.js +1 -0
- package/client/dist/assets/InteractiveJobComposer-CypM7R1F.js +19 -0
- package/client/dist/assets/JobDetailModal-B_W0H9dw.js +1 -0
- package/client/dist/assets/JobDetailPage-CeeXOoKS.js +1 -0
- package/client/dist/assets/JobsPage-CwhJG9jw.js +1 -0
- package/client/dist/assets/LoopBuilderPage-C51t1WOM.js +7 -0
- package/client/dist/assets/LoopPreviewModal-Y2HgtIJu.js +1 -0
- package/client/dist/assets/LoopsPage-Bvn1Kw5V.js +1 -0
- package/client/dist/assets/MinimizedChatsContext-DiFvZDPW.js +1 -0
- package/client/dist/assets/PluginsPage-BGPRJpdf.js +2 -0
- package/client/dist/assets/ProjectSettingsDialog-D_GTyGLc.js +1 -0
- package/client/dist/assets/TemplatePreviewModal-szwBhd7h.js +1 -0
- package/client/dist/assets/TicketDetailModal-9UEyK974.js +14 -0
- package/client/dist/assets/Trans-B_vKZ-Hb.js +1 -0
- package/client/dist/assets/activity-DiyjsgQV.js +1 -0
- package/client/dist/assets/addon-image-BRmmRHgQ.js +1 -0
- package/client/dist/assets/addon-ligatures-qIZUPvRV.js +2 -0
- package/client/dist/assets/{addon-webgl-DMbGeI_u.js → addon-webgl-C2d7lriQ.js} +3 -3
- package/client/dist/assets/addspec-Rw8uVBC1.js +1 -0
- package/client/dist/assets/agent-4rmXoo_p.js +1 -0
- package/client/dist/assets/agent-BxZuNGih.js +1 -0
- package/client/dist/assets/agent-C3uXOYv_.js +1 -0
- package/client/dist/assets/agent-CA8Y4wbw.js +1 -0
- package/client/dist/assets/agent-CASKrhG12.js +1 -0
- package/client/dist/assets/agent-Cv-jud5n2.js +1 -0
- package/client/dist/assets/agent-DitUxYh2.js +1 -0
- package/client/dist/assets/agent-Doow4X7o.js +1 -0
- package/client/dist/assets/agents-DhG7mg6-.js +1 -0
- package/client/dist/assets/agentstudio-BIUe1Im2.js +1 -0
- package/client/dist/assets/aiedit-iIjz2_Qk.js +1 -0
- package/client/dist/assets/analytics-DZ8Aoq3I.js +1 -0
- package/client/dist/assets/api-B2M7CtDw.js +1 -0
- package/client/dist/assets/arrow-left-CpIR4j7G.js +1 -0
- package/client/dist/assets/arrow-up-right-9DoMn7fD.js +1 -0
- package/client/dist/assets/attachments-B53PG733.js +1 -0
- package/client/dist/assets/brain-DI9lHkKY.js +1 -0
- package/client/dist/assets/browser-CXUcnTMI.js +1 -0
- package/client/dist/assets/button-BUIIBQPT.js +1 -0
- package/client/dist/assets/chat-BGD7MXAy.js +1 -0
- package/client/dist/assets/chevron-right-CViMxucY.js +1 -0
- package/client/dist/assets/chunk-KS7C4IRE-Cx5sqopX.js +3 -0
- package/client/dist/assets/circle-x-CMYsN4ZH.js +1 -0
- package/client/dist/assets/code-BDXEM4ml.js +1 -0
- package/client/dist/assets/commands-DyUZQ1FI.js +1 -0
- package/client/dist/assets/common-CD1QHriA2.js +1 -0
- package/client/dist/assets/common-CwwPaRxx.js +1 -0
- package/client/dist/assets/common-DVQuhs-m.js +1 -0
- package/client/dist/assets/common-Dg2jaX7d.js +1 -0
- package/client/dist/assets/common-DuBwj6tK.js +1 -0
- package/client/dist/assets/common-MRj9MHcc.js +1 -0
- package/client/dist/assets/common-O4ZpnMLp.js +1 -0
- package/client/dist/assets/common-fyeF0v7C2.js +1 -0
- package/client/dist/assets/createLucideIcon-Bjbbp_KS.js +1 -0
- package/client/dist/assets/{css.worker-Wv5dxAWO.js → css.worker-yKcq13f2.js} +13 -13
- package/client/dist/assets/{cssMode-DBHbkBvI.js → cssMode-BM4z9OX0.js} +1 -1
- package/client/dist/assets/dashboard-B_NkSHYm.js +1 -0
- package/client/dist/assets/dashboard-ClBb_3pq.js +1 -0
- package/client/dist/assets/dashboard-CpCmJvMB.js +1 -0
- package/client/dist/assets/dashboard-Czohu35O2.js +1 -0
- package/client/dist/assets/dashboard-DcjbD0UK.js +1 -0
- package/client/dist/assets/dashboard-Dvx5F3we.js +1 -0
- package/client/dist/assets/dashboard-R1bOPjBh2.js +1 -0
- package/client/dist/assets/dashboard-owcDucDi.js +1 -0
- package/client/dist/assets/dialog-CzIekCw0.js +45 -0
- package/client/dist/assets/dist-Cez5CRkX.js +1 -0
- package/client/dist/assets/dist-bVqfYmby.js +1 -0
- package/client/dist/assets/{dist-js-UjXbEWhN.js → dist-js-CcBCbb32.js} +1 -1
- package/client/dist/assets/{dist-js-BTAcxhPb.js → dist-js-VwztRkGj.js} +1 -1
- package/client/dist/assets/download-CFHyyHcw.js +1 -0
- package/client/dist/assets/editor.api2-4ndOupAA.js +872 -0
- package/client/dist/assets/{editor.main-C9J2ikJK.js → editor.main-DxrmGfoq.js} +2 -2
- package/client/dist/assets/editor.worker-tytyn86m.js +26 -0
- package/client/dist/assets/explore-DgBACn39.js +1 -0
- package/client/dist/assets/external-link-BcU5EWZp.js +1 -0
- package/client/dist/assets/file-text-CFT-xXKN.js +1 -0
- package/client/dist/assets/formatDistanceToNow-ByHIauTQ.js +1 -0
- package/client/dist/assets/{freemarker2-J5iIIIK-.js → freemarker2-CELlTDJ2.js} +1 -1
- package/client/dist/assets/getTimezoneOffsetInMilliseconds-BxHAksaU.js +1 -0
- package/client/dist/assets/git-branch-BRM0F5GN.js +1 -0
- package/client/dist/assets/{handlebars-DSw1l_tw.js → handlebars-NEjHJ7o_.js} +1 -1
- package/client/dist/assets/{html-h2-wE1Lj.js → html-CA10zN5A.js} +1 -1
- package/client/dist/assets/{html.worker-CQP8QQsS.js → html.worker-DSJ9zmd7.js} +12 -12
- package/client/dist/assets/{htmlMode-Cc_ij7lW.js → htmlMode-89rPYiyq.js} +1 -1
- package/client/dist/assets/i18n-CgaRxpII.js +2 -0
- package/client/dist/assets/index-BflYQpWm.css +2 -0
- package/client/dist/assets/index-C1_-BTXy.js +72 -0
- package/client/dist/assets/integrations-mB-7zoyT.js +1 -0
- package/client/dist/assets/{javascript-C1q3xv6N.js → javascript-B1gDmwzS.js} +1 -1
- package/client/dist/assets/jira-CmKWERE0.js +1 -0
- package/client/dist/assets/jira-api-BgFIr8eD.js +1 -0
- package/client/dist/assets/job-time-BCL7wee9.js +1 -0
- package/client/dist/assets/jobs-B-sDHEay2.js +1 -0
- package/client/dist/assets/jobs-BCtGfgUA.js +1 -0
- package/client/dist/assets/jobs-BHR_EnDI.js +1 -0
- package/client/dist/assets/jobs-BMbZJjJJ.js +1 -0
- package/client/dist/assets/jobs-CVFD8rar.js +1 -0
- package/client/dist/assets/jobs-DoSaFzAa.js +1 -0
- package/client/dist/assets/jobs-DzSIR8V62.js +1 -0
- package/client/dist/assets/jobs-lk1_Dq1U.js +1 -0
- package/client/dist/assets/json.worker-Oa9UrkKE.js +58 -0
- package/client/dist/assets/{jsonMode-CeaCdEhr.js → jsonMode-xHLMfzhF.js} +1 -1
- package/client/dist/assets/jsx-runtime-zu2_FqZY.js +1 -0
- package/client/dist/assets/lib-C7Mhm-gT.js +7 -0
- package/client/dist/assets/lib-CGdyxIWg.js +29 -0
- package/client/dist/assets/{liquid-eFsVK0V-.js → liquid-BY6hCUXG.js} +1 -1
- package/client/dist/assets/loader-circle-DcygOQpC.js +1 -0
- package/client/dist/assets/loops-BzfXWEwO.js +1 -0
- package/client/dist/assets/{lspLanguageFeatures-DT3-bbhn.js → lspLanguageFeatures-ira2aEJh.js} +1 -1
- package/client/dist/assets/mcp-uDkXYu4L.js +1 -0
- package/client/dist/assets/{mdx-Fuwnh1cX.js → mdx-BNx0xr3N.js} +1 -1
- package/client/dist/assets/monaco.contribution-Bt92R3Vw.js +2 -0
- package/client/dist/assets/nav-myFaXRHD.js +1 -0
- package/client/dist/assets/pencil-C9RkrIPZ.js +1 -0
- package/client/dist/assets/play-DNlrawbS.js +1 -0
- package/client/dist/assets/plus-CsnjfkmX.js +1 -0
- package/client/dist/assets/preload-helper-Czpn1I53.js +1 -0
- package/client/dist/assets/{python-BgoEs6Cj.js → python-DLdbtmNw.js} +1 -1
- package/client/dist/assets/{razor-CM1sPMMq.js → razor-B9gdhAbR.js} +1 -1
- package/client/dist/assets/react-dom-DiWzBDP9.js +1 -0
- package/client/dist/assets/rolldown-runtime-CNC7AqOf.js +1 -0
- package/client/dist/assets/save-28sIlCdr.js +1 -0
- package/client/dist/assets/search-Cq_gE3Ik.js +1 -0
- package/client/dist/assets/settings-B0ypw9uw.js +1 -0
- package/client/dist/assets/{settings-Bp24JHlv2.js → settings-B9ilOSYO.js} +1 -1
- package/client/dist/assets/{settings-Bx2ObkTR2.js → settings-BqlWHRHA.js} +1 -1
- package/client/dist/assets/{settings-C_T0-j9d.js → settings-D8dlqt4d.js} +1 -1
- package/client/dist/assets/{settings-DhaFKpcw2.js → settings-DAZqjX2a2.js} +1 -1
- package/client/dist/assets/{settings-B_v3zgJf.js → settings-DRh39v1S2.js} +1 -1
- package/client/dist/assets/{settings-BemR_e3F.js → settings-Mj1OJbfd2.js} +1 -1
- package/client/dist/assets/{settings-BvIwQ3A1.js → settings-lRReaSYm.js} +1 -1
- package/client/dist/assets/setup-CmK87LuS.js +1 -0
- package/client/dist/assets/sparkles-DrY8hb0X.js +1 -0
- package/client/dist/assets/specs-DII0C8gw.js +1 -0
- package/client/dist/assets/spending-C4p06nen.js +1 -0
- package/client/dist/assets/terminal-BFRZnMPP.js +1 -0
- package/client/dist/assets/tickets-B8BuAaj5.js +1 -0
- package/client/dist/assets/tickets-B_yh4qQk.js +1 -0
- package/client/dist/assets/tickets-Bs37scwY2.js +1 -0
- package/client/dist/assets/tickets-CFk2n2Or.js +1 -0
- package/client/dist/assets/tickets-DQp7JS2R2.js +1 -0
- package/client/dist/assets/tickets-D_yDquEw.js +1 -0
- package/client/dist/assets/tickets-DpmdE8tv2.js +1 -0
- package/client/dist/assets/tickets-pAUJkDTu.js +1 -0
- package/client/dist/assets/trash-2-BOU3WdZZ.js +1 -0
- package/client/dist/assets/triangle-alert-H9T4jAmh.js +1 -0
- package/client/dist/assets/{ts.worker-METxwbDZ.js → ts.worker-BtjBFNHX.js} +48 -33
- package/client/dist/assets/{tsMode-BmT8WogI.js → tsMode-DEjSThU9.js} +1 -1
- package/client/dist/assets/{typescript-CQrQPsoW.js → typescript-CRRnD2Ts.js} +1 -1
- package/client/dist/assets/upload-DYMjAQ6M.js +1 -0
- package/client/dist/assets/useBrowserCaptureSession-2OqX0vap.js +1 -0
- package/client/dist/assets/useDesktop-X8YB9xzv.js +1 -0
- package/client/dist/assets/useSharedWebSocket-DaPh7QBL.js +1 -0
- package/client/dist/assets/utils-BC4DHlz2.js +1 -0
- package/client/dist/assets/value-s-gzBeyF.js +1 -0
- package/client/dist/assets/{workers-U0UXyLUf.js → workers-uOo7WLaa.js} +1 -1
- package/client/dist/assets/x-CBMI9ejn.js +1 -0
- package/client/dist/assets/{xml-WRxJs8_I.js → xml-EDREH2X7.js} +1 -1
- package/client/dist/assets/{yaml-CjpSTjJU.js → yaml-BjaDVX1E.js} +1 -1
- package/client/dist/assets/zap-CHo3aCD1.js +1 -0
- package/client/dist/index.html +73 -32
- package/docs/guide/en/integrations/5-mcp-server.md +2 -2
- package/docs/internals/safe-pr-review-flow.md +190 -132
- package/docs/mcp.md +15 -5
- package/package.json +11 -7
- package/server/dist/active-pr-continuation.js +16 -1
- package/server/dist/agent-chat-manager.js +360 -181
- package/server/dist/agent-cwd-manager.js +52 -8
- package/server/dist/agent-generator.js +90 -48
- package/server/dist/agent-mcp-config.js +69 -36
- package/server/dist/agent-operator-prompt.js +3 -2
- package/server/dist/agent-refine-manager.js +47 -6
- package/server/dist/agent-tier.js +13 -11
- package/server/dist/artifact-registry.js +33 -2
- package/server/dist/auth.js +5 -4
- package/server/dist/browser-capture-manager.js +92 -29
- package/server/dist/chat-manager.js +302 -46
- package/server/dist/contract-refine-runner.js +19 -6
- package/server/dist/db.js +665 -8
- package/server/dist/desktop-router.js +1 -2
- package/server/dist/headroom-manager.js +1310 -121
- package/server/dist/headroom-routing.js +120 -2
- package/server/dist/index.js +48 -13
- package/server/dist/interactive-job-session.js +237 -82
- package/server/dist/jira/jira-adf.js +10 -0
- package/server/dist/jira/jira-db.js +15 -3
- package/server/dist/jira/jira-sync-manager.js +182 -13
- package/server/dist/job-listing.js +140 -0
- package/server/dist/job-spawn-idempotency.js +67 -0
- package/server/dist/loop-run-manager.js +508 -98
- package/server/dist/loop-runs-store.js +266 -13
- package/server/dist/mcp/agent-capability.js +71 -0
- package/server/dist/mcp/guide.js +5 -2
- package/server/dist/mcp/mcp-server.js +5 -10
- package/server/dist/mcp/mcp-token.js +5 -5
- package/server/dist/mcp/tools/jobs.js +20 -13
- package/server/dist/mcp/tools/types.js +20 -42
- package/server/dist/mobile/mobile-router.js +1 -1
- package/server/dist/pr-lifecycle.js +77 -0
- package/server/dist/pr-publisher.js +94 -27
- package/server/dist/process-admission.js +82 -0
- package/server/dist/project-registry.js +572 -174
- package/server/dist/project-router-git.js +13 -2
- package/server/dist/project-router-jobs.js +111 -55
- package/server/dist/project-router-tickets.js +32 -2
- package/server/dist/providers/claude-adapter.js +21 -13
- package/server/dist/queue-manager.js +2332 -623
- package/server/dist/rail-isolated-launch.js +1141 -280
- package/server/dist/rail-isolation.js +4 -2
- package/server/dist/rail-pr-decision.js +756 -270
- package/server/dist/rail-pr-delivery.js +2 -1
- package/server/dist/rail-pr-store.js +317 -18
- package/server/dist/rail-pr-ticket-effects.js +328 -0
- package/server/dist/rail-worktree-release.js +28 -6
- package/server/dist/rails-router.js +149 -112
- package/server/dist/rails-store.js +106 -3
- package/server/dist/ticket-store.js +23 -1
- package/server/dist/transient-children.js +13 -0
- package/server/dist/util/cli-prompt.js +42 -8
- package/server/dist/util/secure-token-file.js +84 -0
- package/server/dist/worktree-manager.js +70 -21
- package/client/dist/assets/ActivityFeedPage-Be-6L0Ld.js +0 -1
- package/client/dist/assets/AgentBrowserCapture-CpZ-dd8O.js +0 -1
- package/client/dist/assets/AgentIntegrationsModal-DO1pN_Ez.js +0 -1
- package/client/dist/assets/AgentModeCodePane-DLltTOqp.js +0 -2
- package/client/dist/assets/AgentModeJobsPane-Dp5YvmW0.js +0 -1
- package/client/dist/assets/AgentsPage-ehHuVUds.js +0 -86
- package/client/dist/assets/AnalyticsPage-C4Ik95FX.js +0 -1
- package/client/dist/assets/BarChart-DVZgrhJd.js +0 -33
- package/client/dist/assets/CodePage-D4OCMfxL.js +0 -2
- package/client/dist/assets/DesktopAnalyticsPage-2Xf-52x2.js +0 -1
- package/client/dist/assets/DocsDialog-CHihLjWd.js +0 -11
- package/client/dist/assets/DocsPage-1vEk7XbH.js +0 -11
- package/client/dist/assets/ExportDropdown-DLHFQxVn.js +0 -1
- package/client/dist/assets/IntegrationsPage-CCb2YuyJ.js +0 -1
- package/client/dist/assets/InteractiveJobComposer-CxJJEnjw.js +0 -19
- package/client/dist/assets/JobDetailModal-CJI7qRkm.js +0 -1
- package/client/dist/assets/JobDetailPage-DwA9bbwx.js +0 -1
- package/client/dist/assets/JobsPage-BDIyFfd5.js +0 -1
- package/client/dist/assets/LoopBuilderPage-CpBaW59t.js +0 -7
- package/client/dist/assets/LoopPreviewModal-CwpKcv0Y.js +0 -1
- package/client/dist/assets/LoopsPage-BO0Pa8oz.js +0 -1
- package/client/dist/assets/PluginsPage-BBGTBpGh.js +0 -2
- package/client/dist/assets/ProjectSettingsDialog-M9zGQo0l.js +0 -1
- package/client/dist/assets/TemplatePreviewModal-eBI0zL5P.js +0 -1
- package/client/dist/assets/activity-Dbl71S-E.js +0 -1
- package/client/dist/assets/addon-image-CwoZj17F.js +0 -1
- package/client/dist/assets/addon-ligatures-CWDrED80.js +0 -2
- package/client/dist/assets/addspec-DrXqP8ip.js +0 -1
- package/client/dist/assets/agent-BEXYxDbs.js +0 -1
- package/client/dist/assets/agent-BoXSzaBk2.js +0 -1
- package/client/dist/assets/agent-C2-rROL52.js +0 -1
- package/client/dist/assets/agent-CeRTdGT12.js +0 -1
- package/client/dist/assets/agent-DZ8zTrQT.js +0 -1
- package/client/dist/assets/agent-DqyzT33X.js +0 -1
- package/client/dist/assets/agent-fQI_6tsA.js +0 -1
- package/client/dist/assets/agent-tJdAobaM.js +0 -1
- package/client/dist/assets/agents-CGDn_3kB.js +0 -1
- package/client/dist/assets/agentstudio-Dxe_94PK.js +0 -1
- package/client/dist/assets/aiedit-DrfHQnlz.js +0 -1
- package/client/dist/assets/analytics-CxDYcBl9.js +0 -1
- package/client/dist/assets/attachments-DvxQbBTC.js +0 -1
- package/client/dist/assets/brain-DecvjjPU.js +0 -1
- package/client/dist/assets/browser-DM8G151q.js +0 -1
- package/client/dist/assets/chat-0dg5hOo_.js +0 -1
- package/client/dist/assets/chunk-BNv3lrIs.js +0 -1
- package/client/dist/assets/code-B62fClk-.js +0 -1
- package/client/dist/assets/commands-DCJ-R9E4.js +0 -1
- package/client/dist/assets/common-BfQD173j.js +0 -1
- package/client/dist/assets/common-CF8iGXrG.js +0 -1
- package/client/dist/assets/common-Cfmwcrl52.js +0 -1
- package/client/dist/assets/common-D2cimsul.js +0 -1
- package/client/dist/assets/common-DH7fjyL1.js +0 -1
- package/client/dist/assets/common-DXrmj6WD.js +0 -1
- package/client/dist/assets/common-DZbXlmq72.js +0 -1
- package/client/dist/assets/common-DtXmzX2o2.js +0 -1
- package/client/dist/assets/dashboard-5C2FOZQX.js +0 -1
- package/client/dist/assets/dashboard-B6iQ-IL_.js +0 -1
- package/client/dist/assets/dashboard-BFfnCtq52.js +0 -1
- package/client/dist/assets/dashboard-BIC8KtRf2.js +0 -1
- package/client/dist/assets/dashboard-CEgg9NAr.js +0 -1
- package/client/dist/assets/dashboard-CiOyDh9L.js +0 -1
- package/client/dist/assets/dashboard-D6x5OnNj2.js +0 -1
- package/client/dist/assets/dashboard-DBuLfWo9.js +0 -1
- package/client/dist/assets/editor.api2-C3B0tp2x.js +0 -872
- package/client/dist/assets/editor.worker-Bd9IXS8d.js +0 -26
- package/client/dist/assets/explore-_XyU5e7R.js +0 -1
- package/client/dist/assets/index-BVbgKXUu.css +0 -2
- package/client/dist/assets/index-OBDI7bHm.js +0 -158
- package/client/dist/assets/integrations-By80EBkf.js +0 -1
- package/client/dist/assets/jira-DeIjwCK3.js +0 -1
- package/client/dist/assets/jobs-BFIdeDTw.js +0 -1
- package/client/dist/assets/jobs-BJ-Gcao22.js +0 -1
- package/client/dist/assets/jobs-DAGiPVIS2.js +0 -1
- package/client/dist/assets/jobs-DAU8C_tZ.js +0 -1
- package/client/dist/assets/jobs-Da0GaaSc.js +0 -1
- package/client/dist/assets/jobs-DrYmsKy5.js +0 -1
- package/client/dist/assets/jobs-P3unxtxo2.js +0 -1
- package/client/dist/assets/jobs-p360zdf1.js +0 -1
- package/client/dist/assets/json.worker-DzV-CpCQ.js +0 -58
- package/client/dist/assets/lib-C5ZxrPSR.js +0 -7
- package/client/dist/assets/loops-CO6q75W8.js +0 -1
- package/client/dist/assets/mcp-HwBbQDk0.js +0 -1
- package/client/dist/assets/monaco.contribution-Desq7oq4.js +0 -2
- package/client/dist/assets/nav-BTg8s-cD.js +0 -1
- package/client/dist/assets/preload-helper-DSXbuxSR.js +0 -1
- package/client/dist/assets/settings-BYCMtxOz.js +0 -1
- package/client/dist/assets/setup-D2CmgAro.js +0 -1
- package/client/dist/assets/specs-PGIOzMtc.js +0 -1
- package/client/dist/assets/terminal-CFt56A5f.js +0 -1
- package/client/dist/assets/tickets-BHv3ewvq.js +0 -1
- package/client/dist/assets/tickets-BIxU86j12.js +0 -1
- package/client/dist/assets/tickets-C2BhwzwR.js +0 -1
- package/client/dist/assets/tickets-D1IeX2EW.js +0 -1
- package/client/dist/assets/tickets-DZut8Ryt.js +0 -1
- package/client/dist/assets/tickets-LfK6LzKl2.js +0 -1
- package/client/dist/assets/tickets-dQfsc7Ph.js +0 -1
- package/client/dist/assets/tickets-sVun0I6v.js +0 -1
- package/client/dist/assets/upload-lgjKJgrl.js +0 -1
- package/client/dist/assets/value-Bc0_jlJA.js +0 -1
- /package/client/dist/assets/{abap-D0E4FfVW.js → abap-08VXUWAP.js} +0 -0
- /package/client/dist/assets/{activity-BbWiDfn-2.js → activity-B-rp4h_v.js} +0 -0
- /package/client/dist/assets/{activity-DvECTYGt.js → activity-C6kJpm9q2.js} +0 -0
- /package/client/dist/assets/{activity-D3Ic-HTS.js → activity-CGx4kb_j.js} +0 -0
- /package/client/dist/assets/{activity-BZZlEG3a.js → activity-CnoX2bH7.js} +0 -0
- /package/client/dist/assets/{activity-DtzRy92x.js → activity-DAyekdlt2.js} +0 -0
- /package/client/dist/assets/{activity-FleOlK0l2.js → activity-DCxtpT7j.js} +0 -0
- /package/client/dist/assets/{activity-DFbvNqhE2.js → activity-JzwRaWPD.js} +0 -0
- /package/client/dist/assets/{addspec-CFxGvmJR2.js → addspec-BXjvkh5q.js} +0 -0
- /package/client/dist/assets/{addspec-NBbcTbLc.js → addspec-C4bwrmpi.js} +0 -0
- /package/client/dist/assets/{addspec-BKrH2Ucz.js → addspec-CArHXUDM.js} +0 -0
- /package/client/dist/assets/{addspec-CR8MB5Fr2.js → addspec-DTKJcXiR.js} +0 -0
- /package/client/dist/assets/{addspec-B_LQMHW3.js → addspec-DbNBbrha2.js} +0 -0
- /package/client/dist/assets/{addspec-DaA-CbTt.js → addspec-htHGZHOe2.js} +0 -0
- /package/client/dist/assets/{addspec-Bw_YQwo62.js → addspec-lr_LP6jk.js} +0 -0
- /package/client/dist/assets/{agents-BHgn--3j.js → agents-6ZOJXWVk2.js} +0 -0
- /package/client/dist/assets/{agents-VsyFhGOS2.js → agents-BZ0XQKjg.js} +0 -0
- /package/client/dist/assets/{agents-HFCqQH0Z.js → agents-BqWklnHR.js} +0 -0
- /package/client/dist/assets/{agents-B_qGaB0F.js → agents-Bz-thHkB2.js} +0 -0
- /package/client/dist/assets/{agents-CP8_ezYG.js → agents-CJclElx6.js} +0 -0
- /package/client/dist/assets/{agents-B9pFSJQI2.js → agents-D_l9L0VA.js} +0 -0
- /package/client/dist/assets/{agents-CV-_xBvX2.js → agents-u_C0jPB5.js} +0 -0
- /package/client/dist/assets/{agentstudio-BEp7Sb46.js → agentstudio-BF19hbXj.js} +0 -0
- /package/client/dist/assets/{agentstudio-Br3WD7Xs.js → agentstudio-BLGvxWBx2.js} +0 -0
- /package/client/dist/assets/{agentstudio-BOjG6tgJ.js → agentstudio-D9UKiWTj2.js} +0 -0
- /package/client/dist/assets/{agentstudio-D2A5peWV2.js → agentstudio-Drs37nIM.js} +0 -0
- /package/client/dist/assets/{agentstudio-CuTt3ZGe2.js → agentstudio-nEnKkcXM.js} +0 -0
- /package/client/dist/assets/{agentstudio-RsxnZtUA.js → agentstudio-pyFcSBKy.js} +0 -0
- /package/client/dist/assets/{agentstudio-RfZavULt2.js → agentstudio-zfTzQh3U.js} +0 -0
- /package/client/dist/assets/{aiedit-DnBzjlVz2.js → aiedit-B0KUbpB6.js} +0 -0
- /package/client/dist/assets/{aiedit-D0Syl-mC.js → aiedit-BoG24nlg2.js} +0 -0
- /package/client/dist/assets/{aiedit-CcugGPbS.js → aiedit-CjlSRQVP.js} +0 -0
- /package/client/dist/assets/{aiedit-DrIjSojo.js → aiedit-DCjA7jLJ.js} +0 -0
- /package/client/dist/assets/{aiedit-CV520D4W2.js → aiedit-DNXxq_Dr.js} +0 -0
- /package/client/dist/assets/{aiedit-26p5A_HY2.js → aiedit-DQ-0_pvE.js} +0 -0
- /package/client/dist/assets/{aiedit-a-Z-g5iC.js → aiedit-olnv3QSt2.js} +0 -0
- /package/client/dist/assets/{analytics-DEe5BMz8.js → analytics-BC7mwR4s.js} +0 -0
- /package/client/dist/assets/{analytics-4HvXb0Vn2.js → analytics-BiNg8edP.js} +0 -0
- /package/client/dist/assets/{analytics-CpSTNfui.js → analytics-C0s_T2GN.js} +0 -0
- /package/client/dist/assets/{analytics-4-eskbtX.js → analytics-CdsAPAwZ2.js} +0 -0
- /package/client/dist/assets/{analytics-Bpe41fnX2.js → analytics-Cr1_q-lC.js} +0 -0
- /package/client/dist/assets/{analytics-DcOITHla2.js → analytics-IEsKZvpW2.js} +0 -0
- /package/client/dist/assets/{analytics-Bd9rHGjV.js → analytics-SRPf84OT.js} +0 -0
- /package/client/dist/assets/{apex-D_X_8J4d.js → apex-BWPQTe0t.js} +0 -0
- /package/client/dist/assets/{atom-one-dark-BMDPFwRZ.js → atom-one-dark-qiGhVQxg.js} +0 -0
- /package/client/dist/assets/{attachments-CgOQ9K-6.js → attachments-D0wXXt9T2.js} +0 -0
- /package/client/dist/assets/{attachments-DlEQu56g2.js → attachments-DenIjuVI.js} +0 -0
- /package/client/dist/assets/{attachments-CA2f3qL3.js → attachments-DhO7LPfy.js} +0 -0
- /package/client/dist/assets/{attachments-D2jwJXQ42.js → attachments-DoH5w0x4.js} +0 -0
- /package/client/dist/assets/{attachments-CHDbhKeH.js → attachments-Q9yNtiEM.js} +0 -0
- /package/client/dist/assets/{attachments-CKAY5aYG2.js → attachments-V_WZAYXx2.js} +0 -0
- /package/client/dist/assets/{attachments-jVdKzAXn.js → attachments-eaeScpjM.js} +0 -0
- /package/client/dist/assets/{auth-DpZq5p1e.js → auth-D_5bQv5W.js} +0 -0
- /package/client/dist/assets/{azcli-PZLnZ3jH.js → azcli-Bc_sGQ0U.js} +0 -0
- /package/client/dist/assets/{bat-KlBOxpO4.js → bat-i0X4ZdIN.js} +0 -0
- /package/client/dist/assets/{bicep-CgG9oF3V.js → bicep-B5-_aFwp.js} +0 -0
- /package/client/dist/assets/{browser-Cl-FwPXs.js → browser-C25DkQiO.js} +0 -0
- /package/client/dist/assets/{browser-JsiohNmW.js → browser-CiJ7-L32.js} +0 -0
- /package/client/dist/assets/{browser-BbJ_q_OT2.js → browser-CvgDySd9.js} +0 -0
- /package/client/dist/assets/{browser-BQFDxrRq.js → browser-CyR1Kp3m2.js} +0 -0
- /package/client/dist/assets/{browser-Do2jf8_N.js → browser-DwZljcRh2.js} +0 -0
- /package/client/dist/assets/{browser-C4VJ5CW12.js → browser-DxP-alBK.js} +0 -0
- /package/client/dist/assets/{browser-kA31eYhu2.js → browser-rRCwi7Y7.js} +0 -0
- /package/client/dist/assets/{cameligo-6R45j6Ph.js → cameligo-DMUM7wLl.js} +0 -0
- /package/client/dist/assets/{chat-BalviUAD.js → chat-2rIB8HhT.js} +0 -0
- /package/client/dist/assets/{chat-Ds8GvCnv.js → chat-BR8oe53x2.js} +0 -0
- /package/client/dist/assets/{chat-D5xEtsf3.js → chat-Bua03tty.js} +0 -0
- /package/client/dist/assets/{chat-SaG-ng1x2.js → chat-CZpAQan1.js} +0 -0
- /package/client/dist/assets/{chat-CJddjN3D2.js → chat-CdY5SGvS.js} +0 -0
- /package/client/dist/assets/{chat-n43nZGvn.js → chat-DZyu3ImY2.js} +0 -0
- /package/client/dist/assets/{chat-BMWD_Rx12.js → chat-D_I7nU5K.js} +0 -0
- /package/client/dist/assets/{clojure-CLAAMO7J.js → clojure-Cm7r79vr.js} +0 -0
- /package/client/dist/assets/{clsx-CNmW0Nip.js → clsx-CjueKrWZ.js} +0 -0
- /package/client/dist/assets/{code-C9U6M5-e2.js → code-76gS0IdL.js} +0 -0
- /package/client/dist/assets/{code-BotxM43N2.js → code-C1VwxlML.js} +0 -0
- /package/client/dist/assets/{code-HDK4P6Rx.js → code-CnMZyJpr.js} +0 -0
- /package/client/dist/assets/{code-DUe1Bouz.js → code-D20ef9Cf2.js} +0 -0
- /package/client/dist/assets/{code-Bit_z2Xd2.js → code-DdOXaWRY.js} +0 -0
- /package/client/dist/assets/{code-F_KjccGf.js → code-Duohuf9l.js} +0 -0
- /package/client/dist/assets/{code-CIPmDEd0.js → code-geHmknB92.js} +0 -0
- /package/client/dist/assets/{coffee-AruSygo-.js → coffee-Ba7i2nA0.js} +0 -0
- /package/client/dist/assets/{commands-BFQZc9AG.js → commands-B9RZO4qS.js} +0 -0
- /package/client/dist/assets/{commands-BMkC5-ki.js → commands-BEwbAjtD2.js} +0 -0
- /package/client/dist/assets/{commands-KBbhsnw8.js → commands-Bbxu8kLU.js} +0 -0
- /package/client/dist/assets/{commands-CzFSoIiq2.js → commands-CDU3qv68.js} +0 -0
- /package/client/dist/assets/{commands-CWX9WmDX2.js → commands-CzezgtQj.js} +0 -0
- /package/client/dist/assets/{commands-BllkJauO.js → commands-DTQBF_q52.js} +0 -0
- /package/client/dist/assets/{commands-cKTaLwwV2.js → commands-hOtKuOXc.js} +0 -0
- /package/client/dist/assets/{cpp-DEE5r4Pw.js → cpp-C7h46wYY.js} +0 -0
- /package/client/dist/assets/{csharp-BVXJUvbK.js → csharp-BKxtCVv1.js} +0 -0
- /package/client/dist/assets/{csp-cXOF0JoV.js → csp-bTuwJoIa.js} +0 -0
- /package/client/dist/assets/{css-C_zQuAoy.js → css-DIMkf-bt.js} +0 -0
- /package/client/dist/assets/{cypher-t95m_Q-O.js → cypher-CVaqCwHa.js} +0 -0
- /package/client/dist/assets/{dart-B4r1Tg-e.js → dart-onAF5SnQ.js} +0 -0
- /package/client/dist/assets/{dockerfile-6mt7zHQw.js → dockerfile-DZFCIeNp.js} +0 -0
- /package/client/dist/assets/{ecl-DEY_Fz_Q.js → ecl-D05T4iGw.js} +0 -0
- /package/client/dist/assets/{elixir-R6-q1c5t.js → elixir-6RTg0lbw.js} +0 -0
- /package/client/dist/assets/{explore-CAc8Qzu32.js → explore-BG99VGpL.js} +0 -0
- /package/client/dist/assets/{explore-BO_OinBD.js → explore-C0TjprJW2.js} +0 -0
- /package/client/dist/assets/{explore-Bhy7WWXv.js → explore-C2dgEo7q.js} +0 -0
- /package/client/dist/assets/{explore-ELbrSZyQ2.js → explore-C8NDHbob.js} +0 -0
- /package/client/dist/assets/{explore-DW_YTkQh.js → explore-CWWgzQGR.js} +0 -0
- /package/client/dist/assets/{explore-DCZL9gRN2.js → explore-CcQXpdtS.js} +0 -0
- /package/client/dist/assets/{explore-BEpIs343.js → explore-DsXAgnmJ2.js} +0 -0
- /package/client/dist/assets/{flow9-CNQvHBOt.js → flow9-C5_-GSwl.js} +0 -0
- /package/client/dist/assets/{format-command-Db1viey1.js → format-command-Dfa1o2d-.js} +0 -0
- /package/client/dist/assets/{fsharp-vPZkFXwv.js → fsharp-C8Ef5oNN.js} +0 -0
- /package/client/dist/assets/{go-KUzBMYJ_.js → go-C-y9NEjX.js} +0 -0
- /package/client/dist/assets/{graphql-C3W0rCsD.js → graphql-fmXr3nnJ.js} +0 -0
- /package/client/dist/assets/{hcl-BOOMFSNX.js → hcl-CpzslTdj.js} +0 -0
- /package/client/dist/assets/{ini-CFat1WJr.js → ini-sBoK_t0W.js} +0 -0
- /package/client/dist/assets/{integrations-CG2dp3Kd.js → integrations-CH0zy1Mw2.js} +0 -0
- /package/client/dist/assets/{integrations-CUNe3t9l2.js → integrations-CIAjhd7L.js} +0 -0
- /package/client/dist/assets/{integrations-CWjh5VRk.js → integrations-CZdwOe8A.js} +0 -0
- /package/client/dist/assets/{integrations-RJfzXkPx2.js → integrations-Ct7omMld.js} +0 -0
- /package/client/dist/assets/{integrations-CAjq5tdW2.js → integrations-D6MSxy3-.js} +0 -0
- /package/client/dist/assets/{integrations-JOHSCvB3.js → integrations-DbZa-Zyc.js} +0 -0
- /package/client/dist/assets/{integrations-CP_aiV_8.js → integrations-b8pH-vfl2.js} +0 -0
- /package/client/dist/assets/{java-Dee-CNAM.js → java-BEtHBSE6.js} +0 -0
- /package/client/dist/assets/{jira-CQ7mrZde.js → jira-BySfUuQZ.js} +0 -0
- /package/client/dist/assets/{jira-DIRkZk9U.js → jira-Byw2C0F8.js} +0 -0
- /package/client/dist/assets/{jira-C5UjxHE4.js → jira-CNeYi06w2.js} +0 -0
- /package/client/dist/assets/{jira-ZdKb-50F2.js → jira-D11gPhxz.js} +0 -0
- /package/client/dist/assets/{jira-DTYu3hJi2.js → jira-D38Gj7AT.js} +0 -0
- /package/client/dist/assets/{jira-B5wszJ1-2.js → jira-gAvOyije.js} +0 -0
- /package/client/dist/assets/{jira-DtZpokjJ.js → jira-pRaL7JQo2.js} +0 -0
- /package/client/dist/assets/{julia-CGNlLYuU.js → julia-Bri6UV-V.js} +0 -0
- /package/client/dist/assets/{kotlin-CY7lhknJ.js → kotlin-BOotOW0E.js} +0 -0
- /package/client/dist/assets/{less-D0KN7hfJ.js → less-B9JPFI3C.js} +0 -0
- /package/client/dist/assets/{lexon-CuRJufPs.js → lexon-CfSJPG6W.js} +0 -0
- /package/client/dist/assets/{loops-DKzYFcq6.js → loops-CPpgMapU.js} +0 -0
- /package/client/dist/assets/{loops-Du-bNVpc2.js → loops-CWWbKuVL.js} +0 -0
- /package/client/dist/assets/{loops-DDs4KPu_.js → loops-Crc9It8o2.js} +0 -0
- /package/client/dist/assets/{loops-Bi4ywYGn.js → loops-DH2hZcbK2.js} +0 -0
- /package/client/dist/assets/{loops-DvGbSfxw2.js → loops-DS5TmvIU2.js} +0 -0
- /package/client/dist/assets/{loops-D3wdUkZV.js → loops-P2f0cN8-.js} +0 -0
- /package/client/dist/assets/{loops-BjK8lmoZ2.js → loops-fJV-9hH7.js} +0 -0
- /package/client/dist/assets/{lua-DHvH62Zf.js → lua-CsQS60Ue.js} +0 -0
- /package/client/dist/assets/{m3-tlthQ8Fo.js → m3-D-oSqn_W.js} +0 -0
- /package/client/dist/assets/{markdown-Dbx1LgUZ.js → markdown-Cimd5fb3.js} +0 -0
- /package/client/dist/assets/{mcp-DfmzoT5t.js → mcp-Czd_iyp02.js} +0 -0
- /package/client/dist/assets/{mcp-BG-OCJca2.js → mcp-D2pc5GGx.js} +0 -0
- /package/client/dist/assets/{mcp-CrWdq5db.js → mcp-D4ZjtIx32.js} +0 -0
- /package/client/dist/assets/{mcp-CbJ04oFS2.js → mcp-DIfBUv2D2.js} +0 -0
- /package/client/dist/assets/{mcp-Dd844F5_.js → mcp-DsTwmjST.js} +0 -0
- /package/client/dist/assets/{mcp-zSJ2TsJj.js → mcp-SMkn8boG.js} +0 -0
- /package/client/dist/assets/{mcp-DyULurYS2.js → mcp-fSfiVYAc.js} +0 -0
- /package/client/dist/assets/{mips-D_O3IUz_.js → mips-CIPQ_RoX.js} +0 -0
- /package/client/dist/assets/{msdax-C_ZmCnRt.js → msdax-DauUninz.js} +0 -0
- /package/client/dist/assets/{mysql-C-dCEYSX.js → mysql-SOo6toE5.js} +0 -0
- /package/client/dist/assets/{nav-DUuw9VIU2.js → nav-BRJBxaGt2.js} +0 -0
- /package/client/dist/assets/{nav-D0Erv9ZJ2.js → nav-CAGKv3_F.js} +0 -0
- /package/client/dist/assets/{nav-BY_4EWRv.js → nav-CNskRJKQ2.js} +0 -0
- /package/client/dist/assets/{nav-CVXtv0wX2.js → nav-DY93irBL.js} +0 -0
- /package/client/dist/assets/{nav-B2_ToNqS.js → nav-DhjvYgqt.js} +0 -0
- /package/client/dist/assets/{nav-S4HM94vW.js → nav-Gb-r4wop.js} +0 -0
- /package/client/dist/assets/{nav-BAMkVEId.js → nav-TvumAFD22.js} +0 -0
- /package/client/dist/assets/{objective-c-DZY9Aqxd.js → objective-c-FvmIjYaQ.js} +0 -0
- /package/client/dist/assets/{pascal-BVHLXoor.js → pascal-DrH0SRf2.js} +0 -0
- /package/client/dist/assets/{pascaligo-XdG_6u3k.js → pascaligo-D-ptJ9y-.js} +0 -0
- /package/client/dist/assets/{perl-b9QV0BcD.js → perl-oz_6vUea.js} +0 -0
- /package/client/dist/assets/{pgsql-Du5FDOgT.js → pgsql-DTj74zXo.js} +0 -0
- /package/client/dist/assets/{php-WJD0z2Z_.js → php-nr791fC2.js} +0 -0
- /package/client/dist/assets/{pla-CbciTf2w.js → pla-CopQ2nXW.js} +0 -0
- /package/client/dist/assets/{postiats-C1QxmvVq.js → postiats-43DmfD33.js} +0 -0
- /package/client/dist/assets/{powerquery-BEYDhPLZ.js → powerquery-D3hlyOfw.js} +0 -0
- /package/client/dist/assets/{powershell-CfaYw4XL.js → powershell-DmHpPYUd.js} +0 -0
- /package/client/dist/assets/{protobuf-pwZEDOYa.js → protobuf-C531GsRP.js} +0 -0
- /package/client/dist/assets/{pug-5ftqSPVe.js → pug-Z5eAx3Zn.js} +0 -0
- /package/client/dist/assets/{qsharp-uI6qZMq4.js → qsharp-DkqhCAOL.js} +0 -0
- /package/client/dist/assets/{r-BK54P1EG.js → r-BwWrilGY.js} +0 -0
- /package/client/dist/assets/{redis-DI0yd7kN.js → redis-ClamHrr6.js} +0 -0
- /package/client/dist/assets/{redshift-Dov26eyI.js → redshift-DT7zqm-g.js} +0 -0
- /package/client/dist/assets/{restructuredtext-QqJ_1dC-.js → restructuredtext-BYgofb2h.js} +0 -0
- /package/client/dist/assets/{ruby-5WjveeVb.js → ruby-DezsRK8O.js} +0 -0
- /package/client/dist/assets/{rust-BzVSfqFH.js → rust-DdL9SqIa.js} +0 -0
- /package/client/dist/assets/{sb-DMIUfT-3.js → sb-CcwsVR0C.js} +0 -0
- /package/client/dist/assets/{scala-CSKA7lqt.js → scala-DHpiXF5c.js} +0 -0
- /package/client/dist/assets/{scheme-CojOP2Qc.js → scheme-BeGwcela.js} +0 -0
- /package/client/dist/assets/{scss-DoBZGJG6.js → scss-gp-XZpBa.js} +0 -0
- /package/client/dist/assets/{setup-JeBwoXoM.js → setup-CGZjy2IF2.js} +0 -0
- /package/client/dist/assets/{setup-1vN48B-m2.js → setup-CXa0Sx16.js} +0 -0
- /package/client/dist/assets/{setup-BmJ0Kx16.js → setup-D2ktKKMF2.js} +0 -0
- /package/client/dist/assets/{setup-T_ApeQDV2.js → setup-DG2H7ha5.js} +0 -0
- /package/client/dist/assets/{setup-DQWsu2TR.js → setup-DK5bHDUq2.js} +0 -0
- /package/client/dist/assets/{setup-q0wRHUp1.js → setup-DrWlIQTZ.js} +0 -0
- /package/client/dist/assets/{setup-mXnzww4f.js → setup-rzHUVgAu.js} +0 -0
- /package/client/dist/assets/{shell-YOaE4udl.js → shell-CC2rA5mh.js} +0 -0
- /package/client/dist/assets/{solidity-l3jSyVLu.js → solidity-BEEn4gHE.js} +0 -0
- /package/client/dist/assets/{sophia-BhSGTaQJ.js → sophia-CRfGWb83.js} +0 -0
- /package/client/dist/assets/{sparql-qhk6QD9w.js → sparql-D_Lu-MrJ.js} +0 -0
- /package/client/dist/assets/{specs-BGRKhM8t.js → specs-BcyxaCwf2.js} +0 -0
- /package/client/dist/assets/{specs-GkiL-snY.js → specs-C1q9geAi.js} +0 -0
- /package/client/dist/assets/{specs-DbtIzV8a.js → specs-CLZKysq-2.js} +0 -0
- /package/client/dist/assets/{specs-Ce5y2iFc2.js → specs-DZMS9o54.js} +0 -0
- /package/client/dist/assets/{specs-CT8exGOy2.js → specs-Dm6zUI-R.js} +0 -0
- /package/client/dist/assets/{specs-C6J2zrLM.js → specs-V3TvhKLX.js} +0 -0
- /package/client/dist/assets/{specs-DZDoZsDq.js → specs-dV3Mq5Mu2.js} +0 -0
- /package/client/dist/assets/{sql-DoO3y21-.js → sql-NEE52Syq.js} +0 -0
- /package/client/dist/assets/{st-ChZAY8oG.js → st-DbInun42.js} +0 -0
- /package/client/dist/assets/{swift-D290Tr7_.js → swift-Bxkupp3x.js} +0 -0
- /package/client/dist/assets/{systemverilog-DsxzgJ-o.js → systemverilog-Bz4Y3fRF.js} +0 -0
- /package/client/dist/assets/{tcl-BKDUHAAR.js → tcl-DISqw1ZD.js} +0 -0
- /package/client/dist/assets/{terminal-BTpE7iki.js → terminal-BZiIu3rf.js} +0 -0
- /package/client/dist/assets/{terminal-DEyt0prF.js → terminal-C2NAd7BW2.js} +0 -0
- /package/client/dist/assets/{terminal-a6Uq8B0p.js → terminal-IahE4LW92.js} +0 -0
- /package/client/dist/assets/{terminal-DDk_bTw0.js → terminal-QpXZU2Bn2.js} +0 -0
- /package/client/dist/assets/{terminal-BNSg2lR7.js → terminal-ScjyXNxQ.js} +0 -0
- /package/client/dist/assets/{terminal-Cvabyzm42.js → terminal-d7GadXbN.js} +0 -0
- /package/client/dist/assets/{terminal-D0z12_sJ2.js → terminal-tITa81iz.js} +0 -0
- /package/client/dist/assets/{twig-UpZQaM8G.js → twig-De2hgUGE.js} +0 -0
- /package/client/dist/assets/{typespec-DzaKvN8i.js → typespec-B8J7ngcE.js} +0 -0
- /package/client/dist/assets/{vb-CZpbb7tk.js → vb-DV3o63ZY.js} +0 -0
- /package/client/dist/assets/{wgsl-CNt3OIvl.js → wgsl-DpFanUEy.js} +0 -0
|
@@ -54,6 +54,18 @@ class ChatManager {
|
|
|
54
54
|
_buffers;
|
|
55
55
|
_emittedProposals;
|
|
56
56
|
_abortingConversations;
|
|
57
|
+
/** Permanent lifecycle gate. Project contexts are not reusable after their
|
|
58
|
+
* DB is closed, so every public/asynchronous entry point must fail closed
|
|
59
|
+
* once shutdown starts. */
|
|
60
|
+
_disposed = false;
|
|
61
|
+
_resolveDisposed;
|
|
62
|
+
_disposedSignal = new Promise((resolve) => {
|
|
63
|
+
this._resolveDisposed = resolve;
|
|
64
|
+
});
|
|
65
|
+
/** Active turn promises otherwise settle only when their child emits
|
|
66
|
+
* `close`. Shutdown must also settle them when a mocked/wedged child never
|
|
67
|
+
* closes, while late child callbacks become harmless no-ops. */
|
|
68
|
+
_pendingTurnCancellations = new Set();
|
|
57
69
|
_specDraftStates;
|
|
58
70
|
/** Per-conversation live-strip state for `\`\`\`spec-draft` fenced blocks. */
|
|
59
71
|
_streamFilters;
|
|
@@ -65,6 +77,9 @@ class ChatManager {
|
|
|
65
77
|
/** Persistent-stdin Explore transport (big bet #3, flag-gated default OFF).
|
|
66
78
|
* Holds long-lived claude children that survive between turns. */
|
|
67
79
|
_stdinSessions = new explore_stdin_session_1.ExploreStdinSessions();
|
|
80
|
+
/** Mirror the transport's resident child handles so ChatManager can enforce
|
|
81
|
+
* its stronger process-group escalation for parked sessions too. */
|
|
82
|
+
_persistentProcesses = new Map();
|
|
68
83
|
/** MED-1: per-conversation cumulative usage snapshot for the persistent-stdin
|
|
69
84
|
* transport. One long-lived child serves every turn, so claude's `result`
|
|
70
85
|
* event reports SESSION-CUMULATIVE cost/tokens/num_turns. We diff each turn
|
|
@@ -76,6 +91,10 @@ class ChatManager {
|
|
|
76
91
|
* tree-kill any in-flight one instead of orphaning it (BUG-CHAT-02). Each
|
|
77
92
|
* entry self-removes on its own `'close'`. */
|
|
78
93
|
_auxProcesses = new Set();
|
|
94
|
+
/** Readline listeners owned by auxiliary children. Closing them at shutdown
|
|
95
|
+
* prevents buffered title output from running after the project DB closes. */
|
|
96
|
+
_auxReaders = new Map();
|
|
97
|
+
_terminationTimers = new Map();
|
|
79
98
|
_cwd;
|
|
80
99
|
_projectName;
|
|
81
100
|
_adapter;
|
|
@@ -102,6 +121,85 @@ class ChatManager {
|
|
|
102
121
|
get provider() {
|
|
103
122
|
return this._adapter.id;
|
|
104
123
|
}
|
|
124
|
+
async _awaitWhileLive(work) {
|
|
125
|
+
if (this._disposed)
|
|
126
|
+
return { disposed: true };
|
|
127
|
+
return Promise.race([
|
|
128
|
+
work.then((value) => ({ disposed: false, value })),
|
|
129
|
+
this._disposedSignal.then(() => ({ disposed: true })),
|
|
130
|
+
]);
|
|
131
|
+
}
|
|
132
|
+
/** POSIX children get a dedicated process group so escalation can still
|
|
133
|
+
* address descendants after the root CLI has already exited/reparented them.
|
|
134
|
+
* Windows uses taskkill /T /F through tree-kill instead. */
|
|
135
|
+
_spawnOwned(binary, args, options = {}) {
|
|
136
|
+
if (process.platform === 'win32')
|
|
137
|
+
return (0, cli_prompt_1.spawnAiCli)(binary, args, options);
|
|
138
|
+
return (0, cli_prompt_1.spawnAiCli)(binary, args, { ...options, detached: true });
|
|
139
|
+
}
|
|
140
|
+
/** Terminate the complete CLI/MCP subtree, escalating when SIGTERM is
|
|
141
|
+
* ignored. Do NOT cancel escalation when the root closes: descendants remain
|
|
142
|
+
* in the dedicated POSIX process group even after their parent exits. */
|
|
143
|
+
_terminate(child) {
|
|
144
|
+
if (this._terminationTimers.has(child))
|
|
145
|
+
return;
|
|
146
|
+
try {
|
|
147
|
+
if (!child.pid) {
|
|
148
|
+
child.kill('SIGTERM');
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
const pid = child.pid;
|
|
152
|
+
(0, tree_kill_1.default)(pid, 'SIGTERM');
|
|
153
|
+
const timer = setTimeout(() => {
|
|
154
|
+
this._terminationTimers.delete(child);
|
|
155
|
+
if (process.platform !== 'win32') {
|
|
156
|
+
// Negative PID targets the process GROUP. It remains addressable when
|
|
157
|
+
// the root has exited but an MCP descendant ignored SIGTERM.
|
|
158
|
+
try {
|
|
159
|
+
process.kill(-pid, 'SIGKILL');
|
|
160
|
+
}
|
|
161
|
+
catch { /* group already gone */ }
|
|
162
|
+
}
|
|
163
|
+
else {
|
|
164
|
+
try {
|
|
165
|
+
(0, tree_kill_1.default)(pid, 'SIGKILL', () => { });
|
|
166
|
+
}
|
|
167
|
+
catch { /* gone */ }
|
|
168
|
+
}
|
|
169
|
+
}, 2000);
|
|
170
|
+
timer.unref?.();
|
|
171
|
+
this._terminationTimers.set(child, timer);
|
|
172
|
+
}
|
|
173
|
+
catch {
|
|
174
|
+
/* already gone */
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
_closeChildIo(child) {
|
|
178
|
+
try {
|
|
179
|
+
child.stdin?.destroy();
|
|
180
|
+
}
|
|
181
|
+
catch { /* best-effort */ }
|
|
182
|
+
try {
|
|
183
|
+
child.stdout?.destroy();
|
|
184
|
+
}
|
|
185
|
+
catch { /* best-effort */ }
|
|
186
|
+
try {
|
|
187
|
+
child.stderr?.destroy();
|
|
188
|
+
}
|
|
189
|
+
catch { /* best-effort */ }
|
|
190
|
+
}
|
|
191
|
+
_trackPersistentProcess(conversationId, child) {
|
|
192
|
+
if (this._persistentProcesses.get(conversationId) === child)
|
|
193
|
+
return;
|
|
194
|
+
this._persistentProcesses.set(conversationId, child);
|
|
195
|
+
const drop = () => {
|
|
196
|
+
if (this._persistentProcesses.get(conversationId) === child) {
|
|
197
|
+
this._persistentProcesses.delete(conversationId);
|
|
198
|
+
}
|
|
199
|
+
};
|
|
200
|
+
child.once('close', drop);
|
|
201
|
+
child.once('error', drop);
|
|
202
|
+
}
|
|
105
203
|
/**
|
|
106
204
|
* Resolve the adapter for a conversation. A conversation may carry its own
|
|
107
205
|
* `provider` (set at creation from the Add Spec AI Engine selector); when
|
|
@@ -142,6 +240,8 @@ class ChatManager {
|
|
|
142
240
|
}
|
|
143
241
|
}
|
|
144
242
|
_startIdleTimer(conversationId) {
|
|
243
|
+
if (this._disposed)
|
|
244
|
+
return;
|
|
145
245
|
const life = this._exploreLifecycle.get(conversationId);
|
|
146
246
|
if (!life)
|
|
147
247
|
return;
|
|
@@ -151,13 +251,11 @@ class ChatManager {
|
|
|
151
251
|
return;
|
|
152
252
|
this._clearIdleTimer(conversationId);
|
|
153
253
|
life.idleTimer = setTimeout(() => {
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
catch { /* best-effort */ }
|
|
160
|
-
}
|
|
254
|
+
if (this._disposed)
|
|
255
|
+
return;
|
|
256
|
+
const child = this._activeProcesses.get(conversationId) ?? this._persistentProcesses.get(conversationId);
|
|
257
|
+
if (child)
|
|
258
|
+
this._terminate(child);
|
|
161
259
|
// Persistent-stdin children live OUTSIDE _activeProcesses between turns —
|
|
162
260
|
// idle-kill must reach them too (the next turn re-spawns with --resume).
|
|
163
261
|
this._stdinSessions.kill(conversationId);
|
|
@@ -169,6 +267,8 @@ class ChatManager {
|
|
|
169
267
|
* the timer starts when the turn completes.
|
|
170
268
|
*/
|
|
171
269
|
notifyMinimized(conversationId) {
|
|
270
|
+
if (this._disposed)
|
|
271
|
+
return;
|
|
172
272
|
const life = this._getOrCreateExploreLifecycle(conversationId);
|
|
173
273
|
life.isMinimized = true;
|
|
174
274
|
life.lastActivityAt = Date.now();
|
|
@@ -177,6 +277,8 @@ class ChatManager {
|
|
|
177
277
|
/** Mark an Explore conversation as restored (un-minimized). Cancels the
|
|
178
278
|
* pending idle-kill timer if any. */
|
|
179
279
|
notifyRestored(conversationId) {
|
|
280
|
+
if (this._disposed)
|
|
281
|
+
return;
|
|
180
282
|
const life = this._exploreLifecycle.get(conversationId);
|
|
181
283
|
if (!life)
|
|
182
284
|
return;
|
|
@@ -208,6 +310,8 @@ class ChatManager {
|
|
|
208
310
|
return oldest?.id ?? null;
|
|
209
311
|
}
|
|
210
312
|
_drainExploreQueue() {
|
|
313
|
+
if (this._disposed)
|
|
314
|
+
return;
|
|
211
315
|
// A released waiter does NOT flip its `isStreaming` flag synchronously — it
|
|
212
316
|
// does so only when its awaiting sendMessage continuation runs as a later
|
|
213
317
|
// microtask. So `_countStreamingExplore()` stays stale across this fully
|
|
@@ -224,6 +328,8 @@ class ChatManager {
|
|
|
224
328
|
}
|
|
225
329
|
}
|
|
226
330
|
async _waitForExploreSlot(conversationId) {
|
|
331
|
+
if (this._disposed)
|
|
332
|
+
return 'disposed';
|
|
227
333
|
if (this._countStreamingExplore() < exports.EXPLORE_MAX_CONCURRENCY)
|
|
228
334
|
return 'ok';
|
|
229
335
|
// M14: a streaming slot is freed only when a STREAMING turn ends. The old code
|
|
@@ -235,13 +341,9 @@ class ChatManager {
|
|
|
235
341
|
// stray child) but only grant the slot if the streaming count actually dropped.
|
|
236
342
|
const victim = this._findIdleExploreVictim(conversationId);
|
|
237
343
|
if (victim) {
|
|
238
|
-
const child = this._activeProcesses.get(victim);
|
|
239
|
-
if (child
|
|
240
|
-
|
|
241
|
-
(0, tree_kill_1.default)(child.pid, 'SIGTERM');
|
|
242
|
-
}
|
|
243
|
-
catch { /* best-effort */ }
|
|
244
|
-
}
|
|
344
|
+
const child = this._activeProcesses.get(victim) ?? this._persistentProcesses.get(victim);
|
|
345
|
+
if (child)
|
|
346
|
+
this._terminate(child);
|
|
245
347
|
// Reclaim the slot from a persistent-stdin child parked between turns.
|
|
246
348
|
this._stdinSessions.kill(victim);
|
|
247
349
|
this._clearIdleTimer(victim);
|
|
@@ -262,7 +364,7 @@ class ChatManager {
|
|
|
262
364
|
enqueuedAt: Date.now(),
|
|
263
365
|
timeoutTimer,
|
|
264
366
|
onSlot: () => resolve('ok'),
|
|
265
|
-
onTimeout: () => resolve('busy'),
|
|
367
|
+
onTimeout: () => resolve(this._disposed ? 'disposed' : 'busy'),
|
|
266
368
|
});
|
|
267
369
|
});
|
|
268
370
|
}
|
|
@@ -339,6 +441,8 @@ class ChatManager {
|
|
|
339
441
|
}
|
|
340
442
|
/** Drop the per-conversation draft state (used on conversation deletion). */
|
|
341
443
|
forgetSpecDraft(conversationId) {
|
|
444
|
+
if (this._disposed)
|
|
445
|
+
return;
|
|
342
446
|
this._specDraftStates.delete(conversationId);
|
|
343
447
|
}
|
|
344
448
|
/** Snapshot of the current spec-draft state for a conversation, or null
|
|
@@ -346,6 +450,8 @@ class ChatManager {
|
|
|
346
450
|
* a refresh / minimize cycle so updates Claude pushed while no shell
|
|
347
451
|
* was subscribed don't get lost. */
|
|
348
452
|
getSpecDraftState(conversationId) {
|
|
453
|
+
if (this._disposed)
|
|
454
|
+
return null;
|
|
349
455
|
return this._specDraftStates.get(conversationId) ?? null;
|
|
350
456
|
}
|
|
351
457
|
/**
|
|
@@ -454,9 +560,11 @@ class ChatManager {
|
|
|
454
560
|
return `${scopedBase}\n\n${prefix}`;
|
|
455
561
|
}
|
|
456
562
|
isActive(conversationId) {
|
|
457
|
-
return this._activeProcesses.has(conversationId);
|
|
563
|
+
return !this._disposed && this._activeProcesses.has(conversationId);
|
|
458
564
|
}
|
|
459
565
|
async sendMessage(conversationId, userText, options) {
|
|
566
|
+
if (this._disposed)
|
|
567
|
+
return;
|
|
460
568
|
if (this._activeProcesses.has(conversationId) || this._reservedTurns.has(conversationId)) {
|
|
461
569
|
console.warn(`[ChatManager] conversation ${conversationId} already has an active or pending stream`);
|
|
462
570
|
return;
|
|
@@ -487,6 +595,8 @@ class ChatManager {
|
|
|
487
595
|
// Explore: enforce per-project concurrency cap before doing any work.
|
|
488
596
|
if (conversation.kind === 'explore') {
|
|
489
597
|
const slot = await this._waitForExploreSlot(conversationId);
|
|
598
|
+
if (this._disposed || slot === 'disposed')
|
|
599
|
+
return;
|
|
490
600
|
if (slot === 'busy') {
|
|
491
601
|
this._broadcast({
|
|
492
602
|
type: 'chat_error',
|
|
@@ -514,7 +624,10 @@ class ChatManager {
|
|
|
514
624
|
let hasAttachments = false;
|
|
515
625
|
if (options?.attachments && options.attachments.ids.length > 0) {
|
|
516
626
|
try {
|
|
517
|
-
const
|
|
627
|
+
const attachmentResult = await this._awaitWhileLive(attachment_manager_1.attachmentManager.getClaudeArgs(options.attachments.slug, options.attachments.ticketKey, options.attachments.ids));
|
|
628
|
+
if (attachmentResult.disposed)
|
|
629
|
+
return;
|
|
630
|
+
const { textBlocks } = attachmentResult.value;
|
|
518
631
|
if (textBlocks.length > 0) {
|
|
519
632
|
resolvedText = `${resolvedText}\n\n## Attached Resources\n\n${textBlocks.join('\n\n')}`;
|
|
520
633
|
hasAttachments = true;
|
|
@@ -523,6 +636,10 @@ class ChatManager {
|
|
|
523
636
|
catch (err) {
|
|
524
637
|
console.error(`[chat-manager] attachment extraction failed (${conversationId}):`, err);
|
|
525
638
|
}
|
|
639
|
+
// Project removal may close the DB while attachment extraction is in
|
|
640
|
+
// flight. Never continue into context reads or a new spawn afterwards.
|
|
641
|
+
if (this._disposed)
|
|
642
|
+
return;
|
|
526
643
|
}
|
|
527
644
|
// Build spawn args via the resolved adapter. System prompt placement
|
|
528
645
|
// (--system-prompt flag vs prompt-fold) and resume vs fresh-turn are both
|
|
@@ -640,7 +757,7 @@ class ChatManager {
|
|
|
640
757
|
lightweight, conversationScope,
|
|
641
758
|
});
|
|
642
759
|
}
|
|
643
|
-
const child =
|
|
760
|
+
const child = this._spawnOwned(binary, args, {
|
|
644
761
|
env: spawnEnv,
|
|
645
762
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
646
763
|
cwd: spawnCwd,
|
|
@@ -648,6 +765,8 @@ class ChatManager {
|
|
|
648
765
|
let stderrBuf = '';
|
|
649
766
|
// Drain stderr so the pipe buffer never fills up (child process would block otherwise)
|
|
650
767
|
child.stderr?.on('data', (chunk) => {
|
|
768
|
+
if (this._disposed)
|
|
769
|
+
return;
|
|
651
770
|
const text = chunk.toString();
|
|
652
771
|
stderrBuf += text;
|
|
653
772
|
console.error(`[chat-manager] ${binary} stderr (${conversationId}):`, text.trim());
|
|
@@ -659,6 +778,8 @@ class ChatManager {
|
|
|
659
778
|
// Surface ENOENT (e.g. claude not on PATH) instead of crashing the app.
|
|
660
779
|
/* c8 ignore start -- spawn-failure path; exercised manually, not in CI */
|
|
661
780
|
child.on('error', (err) => {
|
|
781
|
+
if (this._disposed)
|
|
782
|
+
return;
|
|
662
783
|
console.error(`[chat-manager] spawn failed for ${conversationId}: ${err.message}`);
|
|
663
784
|
this._activeProcesses.delete(conversationId);
|
|
664
785
|
this._buffers.delete(conversationId);
|
|
@@ -684,6 +805,8 @@ class ChatManager {
|
|
|
684
805
|
const turnStartedAt = new Date().toISOString();
|
|
685
806
|
const stdoutReader = (0, readline_1.createInterface)({ input: child.stdout, crlfDelay: Infinity });
|
|
686
807
|
const emitDelta = (newText) => {
|
|
808
|
+
if (this._disposed)
|
|
809
|
+
return;
|
|
687
810
|
const prev = this._buffers.get(conversationId) ?? '';
|
|
688
811
|
const updated = prev + newText;
|
|
689
812
|
this._buffers.set(conversationId, updated);
|
|
@@ -718,6 +841,8 @@ class ChatManager {
|
|
|
718
841
|
}
|
|
719
842
|
};
|
|
720
843
|
const readerHandler = (line) => {
|
|
844
|
+
if (this._disposed)
|
|
845
|
+
return;
|
|
721
846
|
const ev = adapter.parseStreamLine(line);
|
|
722
847
|
if (!ev)
|
|
723
848
|
return;
|
|
@@ -760,7 +885,42 @@ class ChatManager {
|
|
|
760
885
|
let currentChild = child;
|
|
761
886
|
void currentChild; // keep reference live for crash respawn
|
|
762
887
|
return new Promise((resolve) => {
|
|
888
|
+
let settled = false;
|
|
889
|
+
const readers = new Set([stdoutReader]);
|
|
890
|
+
const closeChildren = new Set([child]);
|
|
891
|
+
const complete = () => {
|
|
892
|
+
if (settled)
|
|
893
|
+
return;
|
|
894
|
+
settled = true;
|
|
895
|
+
this._pendingTurnCancellations.delete(cancelForShutdown);
|
|
896
|
+
resolve();
|
|
897
|
+
};
|
|
898
|
+
const cancelForShutdown = () => {
|
|
899
|
+
if (settled)
|
|
900
|
+
return;
|
|
901
|
+
for (const reader of readers) {
|
|
902
|
+
try {
|
|
903
|
+
reader.close();
|
|
904
|
+
}
|
|
905
|
+
catch { /* best-effort */ }
|
|
906
|
+
}
|
|
907
|
+
for (const ownedChild of closeChildren) {
|
|
908
|
+
ownedChild.removeListener('close', onClose);
|
|
909
|
+
}
|
|
910
|
+
this._activeProcesses.delete(conversationId);
|
|
911
|
+
this._buffers.delete(conversationId);
|
|
912
|
+
this._emittedProposals.delete(conversationId);
|
|
913
|
+
this._abortingConversations.delete(conversationId);
|
|
914
|
+
this._streamFilters.delete(conversationId);
|
|
915
|
+
complete();
|
|
916
|
+
};
|
|
763
917
|
const onClose = (code) => {
|
|
918
|
+
if (settled)
|
|
919
|
+
return;
|
|
920
|
+
if (this._disposed) {
|
|
921
|
+
cancelForShutdown();
|
|
922
|
+
return;
|
|
923
|
+
}
|
|
764
924
|
console.log(`[chat-manager] ${adapter.id} exited code=${code} conv=${conversationId}`);
|
|
765
925
|
const fullText = this._buffers.get(conversationId) ?? '';
|
|
766
926
|
const wasAborting = this._abortingConversations.has(conversationId);
|
|
@@ -797,12 +957,13 @@ class ChatManager {
|
|
|
797
957
|
: args;
|
|
798
958
|
console.warn(`[chat-manager] explore crash respawn for ${conversationId}`);
|
|
799
959
|
try {
|
|
800
|
-
const newChild =
|
|
960
|
+
const newChild = this._spawnOwned(binary, respawnArgs, {
|
|
801
961
|
env: process.env,
|
|
802
962
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
803
963
|
cwd: spawnCwd,
|
|
804
964
|
});
|
|
805
965
|
currentChild = newChild;
|
|
966
|
+
closeChildren.add(newChild);
|
|
806
967
|
args = respawnArgs;
|
|
807
968
|
// MED-2: the crashed spawn already burned tokens (tool-call rounds
|
|
808
969
|
// before the crash). Its usage was aggregated into adapterEvents by
|
|
@@ -829,6 +990,8 @@ class ChatManager {
|
|
|
829
990
|
adapterEvents.length = 0;
|
|
830
991
|
this._activeProcesses.set(conversationId, newChild);
|
|
831
992
|
newChild.stderr?.on('data', (chunk) => {
|
|
993
|
+
if (this._disposed)
|
|
994
|
+
return;
|
|
832
995
|
const text = chunk.toString();
|
|
833
996
|
stderrBuf += text;
|
|
834
997
|
console.error(`[chat-manager] ${binary} stderr (${conversationId}):`, text.trim());
|
|
@@ -840,6 +1003,10 @@ class ChatManager {
|
|
|
840
1003
|
// event and crash the entire app. Mirror the original handler.
|
|
841
1004
|
/* c8 ignore start -- respawn spawn-failure path; exercised manually, not in CI */
|
|
842
1005
|
newChild.on('error', (err) => {
|
|
1006
|
+
if (this._disposed) {
|
|
1007
|
+
cancelForShutdown();
|
|
1008
|
+
return;
|
|
1009
|
+
}
|
|
843
1010
|
console.error(`[chat-manager] explore crash-respawn spawn failed for ${conversationId}: ${err.message}`);
|
|
844
1011
|
// MED-2: the respawn never streamed a result event, so the normal
|
|
845
1012
|
// close-path recording is bypassed. Record whatever usage the
|
|
@@ -873,10 +1040,11 @@ class ChatManager {
|
|
|
873
1040
|
error: `Failed to launch ${binary}: ${err.message}`,
|
|
874
1041
|
timestamp: new Date().toISOString(),
|
|
875
1042
|
});
|
|
876
|
-
|
|
1043
|
+
complete();
|
|
877
1044
|
});
|
|
878
1045
|
/* c8 ignore stop */
|
|
879
1046
|
const newReader = (0, readline_1.createInterface)({ input: newChild.stdout, crlfDelay: Infinity });
|
|
1047
|
+
readers.add(newReader);
|
|
880
1048
|
newReader.on('line', readerHandler);
|
|
881
1049
|
newChild.on('close', onClose);
|
|
882
1050
|
return;
|
|
@@ -925,7 +1093,7 @@ class ChatManager {
|
|
|
925
1093
|
});
|
|
926
1094
|
if (wasAborting) {
|
|
927
1095
|
// abort already emitted chat_error
|
|
928
|
-
|
|
1096
|
+
complete();
|
|
929
1097
|
return;
|
|
930
1098
|
}
|
|
931
1099
|
if (code === 0) {
|
|
@@ -986,8 +1154,9 @@ class ChatManager {
|
|
|
986
1154
|
timestamp: new Date().toISOString(),
|
|
987
1155
|
});
|
|
988
1156
|
}
|
|
989
|
-
|
|
1157
|
+
complete();
|
|
990
1158
|
};
|
|
1159
|
+
this._pendingTurnCancellations.add(cancelForShutdown);
|
|
991
1160
|
child.on('close', onClose);
|
|
992
1161
|
});
|
|
993
1162
|
}
|
|
@@ -1009,6 +1178,8 @@ class ChatManager {
|
|
|
1009
1178
|
* `--resume`. Only reached when the flag is on; the legacy path is untouched.
|
|
1010
1179
|
*/
|
|
1011
1180
|
async _streamPersistentExploreTurn(p) {
|
|
1181
|
+
if (this._disposed)
|
|
1182
|
+
return;
|
|
1012
1183
|
const { conversationId, conversation, adapter, binary, model, systemPrompt, scopeFlags, spawnCwd, promptForAdapter, isFirstTurn, userText, lightweight, conversationScope, } = p;
|
|
1013
1184
|
const sessionArgs = adapter.buildArgs('chat-stream', {
|
|
1014
1185
|
prompt: '',
|
|
@@ -1019,8 +1190,9 @@ class ChatManager {
|
|
|
1019
1190
|
loadUserEnv: adapter.id === 'claude' && !!conversationScope?.userMcp,
|
|
1020
1191
|
});
|
|
1021
1192
|
const { child, isNew } = this._stdinSessions.getOrSpawn(conversationId, {
|
|
1022
|
-
binary, args: sessionArgs, cwd: spawnCwd, env: process.env,
|
|
1193
|
+
binary, args: sessionArgs, cwd: spawnCwd, env: process.env, spawn: this._spawnOwned.bind(this),
|
|
1023
1194
|
});
|
|
1195
|
+
this._trackPersistentProcess(conversationId, child);
|
|
1024
1196
|
// MED-1: a fresh child restarts claude's session-cumulative counters at 0,
|
|
1025
1197
|
// so drop any stale baseline. The next turn diffs against zero.
|
|
1026
1198
|
if (isNew)
|
|
@@ -1034,6 +1206,8 @@ class ChatManager {
|
|
|
1034
1206
|
let stderrBuf = '';
|
|
1035
1207
|
const turnStartedAt = new Date().toISOString();
|
|
1036
1208
|
const emitDelta = (newText) => {
|
|
1209
|
+
if (this._disposed)
|
|
1210
|
+
return;
|
|
1037
1211
|
const prev = this._buffers.get(conversationId) ?? '';
|
|
1038
1212
|
this._buffers.set(conversationId, prev + newText);
|
|
1039
1213
|
const filter = this._streamFilters.get(conversationId);
|
|
@@ -1063,6 +1237,8 @@ class ChatManager {
|
|
|
1063
1237
|
}
|
|
1064
1238
|
};
|
|
1065
1239
|
const recordInv = (status) => {
|
|
1240
|
+
if (this._disposed)
|
|
1241
|
+
return;
|
|
1066
1242
|
if (!this._projectId)
|
|
1067
1243
|
return;
|
|
1068
1244
|
try {
|
|
@@ -1134,6 +1310,8 @@ class ChatManager {
|
|
|
1134
1310
|
this._streamFilters.delete(conversationId);
|
|
1135
1311
|
};
|
|
1136
1312
|
const markStreamingEnded = (success) => {
|
|
1313
|
+
if (this._disposed)
|
|
1314
|
+
return;
|
|
1137
1315
|
const life = this._exploreLifecycle.get(conversationId);
|
|
1138
1316
|
if (life) {
|
|
1139
1317
|
life.isStreaming = false;
|
|
@@ -1147,6 +1325,19 @@ class ChatManager {
|
|
|
1147
1325
|
};
|
|
1148
1326
|
return new Promise((resolve) => {
|
|
1149
1327
|
let settled = false;
|
|
1328
|
+
const complete = () => {
|
|
1329
|
+
this._pendingTurnCancellations.delete(cancelForShutdown);
|
|
1330
|
+
resolve();
|
|
1331
|
+
};
|
|
1332
|
+
const cancelForShutdown = () => {
|
|
1333
|
+
if (settled)
|
|
1334
|
+
return;
|
|
1335
|
+
settled = true;
|
|
1336
|
+
this._stdinSessions.clearHandlers(conversationId);
|
|
1337
|
+
cleanupTurnState();
|
|
1338
|
+
this._abortingConversations.delete(conversationId);
|
|
1339
|
+
complete();
|
|
1340
|
+
};
|
|
1150
1341
|
// LOW-7: the persistent transport ends the turn on the `result` event even
|
|
1151
1342
|
// when that event reports a failure (is_error / an `error_*` subtype, e.g.
|
|
1152
1343
|
// error_max_turns). Recording those as status='success' misreports the
|
|
@@ -1156,6 +1347,10 @@ class ChatManager {
|
|
|
1156
1347
|
const finishTurn = () => {
|
|
1157
1348
|
if (settled)
|
|
1158
1349
|
return;
|
|
1350
|
+
if (this._disposed) {
|
|
1351
|
+
cancelForShutdown();
|
|
1352
|
+
return;
|
|
1353
|
+
}
|
|
1159
1354
|
settled = true;
|
|
1160
1355
|
this._stdinSessions.clearHandlers(conversationId);
|
|
1161
1356
|
const fullText = this._buffers.get(conversationId) ?? '';
|
|
@@ -1168,7 +1363,7 @@ class ChatManager {
|
|
|
1168
1363
|
// user-cancelled — do NOT persist the partial assistant message, update
|
|
1169
1364
|
// the session, or broadcast chat_done (mirrors the legacy close handler).
|
|
1170
1365
|
if (wasAborting) {
|
|
1171
|
-
|
|
1366
|
+
complete();
|
|
1172
1367
|
return;
|
|
1173
1368
|
}
|
|
1174
1369
|
const parsed = (0, spec_draft_parser_1.parseSpecDraftBlocks)(fullText);
|
|
@@ -1202,7 +1397,7 @@ class ChatManager {
|
|
|
1202
1397
|
if (isFirstTurn && fullText && !lightweight) {
|
|
1203
1398
|
this._autoTitle(conversationId, userText, fullText);
|
|
1204
1399
|
}
|
|
1205
|
-
|
|
1400
|
+
complete();
|
|
1206
1401
|
};
|
|
1207
1402
|
const onClose = (code) => {
|
|
1208
1403
|
// The persistent child died (crash / idle-kill / shutdown). If the turn
|
|
@@ -1211,6 +1406,10 @@ class ChatManager {
|
|
|
1211
1406
|
// `--resume`, so no persisted state is lost.
|
|
1212
1407
|
if (settled)
|
|
1213
1408
|
return;
|
|
1409
|
+
if (this._disposed) {
|
|
1410
|
+
cancelForShutdown();
|
|
1411
|
+
return;
|
|
1412
|
+
}
|
|
1214
1413
|
settled = true;
|
|
1215
1414
|
this._stdinSessions.clearHandlers(conversationId);
|
|
1216
1415
|
const wasAborting = this._abortingConversations.has(conversationId);
|
|
@@ -1219,7 +1418,7 @@ class ChatManager {
|
|
|
1219
1418
|
markStreamingEnded(false);
|
|
1220
1419
|
recordInv(wasAborting ? 'aborted' : 'failed');
|
|
1221
1420
|
if (wasAborting) {
|
|
1222
|
-
|
|
1421
|
+
complete();
|
|
1223
1422
|
return;
|
|
1224
1423
|
}
|
|
1225
1424
|
const stderrTail = stderrBuf.trim().slice(-500);
|
|
@@ -1231,9 +1430,11 @@ class ChatManager {
|
|
|
1231
1430
|
: `Process exited with code ${code ?? 'unknown'}`,
|
|
1232
1431
|
timestamp: new Date().toISOString(),
|
|
1233
1432
|
});
|
|
1234
|
-
|
|
1433
|
+
complete();
|
|
1235
1434
|
};
|
|
1236
1435
|
const onLine = (line) => {
|
|
1436
|
+
if (this._disposed || settled)
|
|
1437
|
+
return;
|
|
1237
1438
|
const ev = adapter.parseStreamLine(line);
|
|
1238
1439
|
if (!ev)
|
|
1239
1440
|
return;
|
|
@@ -1264,11 +1465,14 @@ class ChatManager {
|
|
|
1264
1465
|
this._stdinSessions.setHandlers(conversationId, {
|
|
1265
1466
|
onLine,
|
|
1266
1467
|
onStderr: (s) => {
|
|
1468
|
+
if (this._disposed || settled)
|
|
1469
|
+
return;
|
|
1267
1470
|
stderrBuf += s;
|
|
1268
1471
|
console.error(`[chat-manager] ${binary} stderr (${conversationId}):`, s.trim());
|
|
1269
1472
|
},
|
|
1270
1473
|
onClose,
|
|
1271
1474
|
});
|
|
1475
|
+
this._pendingTurnCancellations.add(cancelForShutdown);
|
|
1272
1476
|
if (!this._stdinSessions.writeTurn(conversationId, promptForAdapter)) {
|
|
1273
1477
|
// stdin already gone (child died between spawn and write) — fail the turn.
|
|
1274
1478
|
onClose(null);
|
|
@@ -1276,11 +1480,13 @@ class ChatManager {
|
|
|
1276
1480
|
});
|
|
1277
1481
|
}
|
|
1278
1482
|
abort(conversationId) {
|
|
1483
|
+
if (this._disposed)
|
|
1484
|
+
return;
|
|
1279
1485
|
const child = this._activeProcesses.get(conversationId);
|
|
1280
1486
|
if (!child || !child.pid)
|
|
1281
1487
|
return;
|
|
1282
1488
|
this._abortingConversations.add(conversationId);
|
|
1283
|
-
|
|
1489
|
+
this._terminate(child);
|
|
1284
1490
|
this._broadcast({
|
|
1285
1491
|
type: 'chat_error',
|
|
1286
1492
|
conversationId,
|
|
@@ -1296,12 +1502,20 @@ class ChatManager {
|
|
|
1296
1502
|
* armed timers) don't accumulate for the lifetime of the project.
|
|
1297
1503
|
*/
|
|
1298
1504
|
forgetExploreLifecycle(conversationId) {
|
|
1505
|
+
if (this._disposed)
|
|
1506
|
+
return;
|
|
1299
1507
|
this._clearIdleTimer(conversationId);
|
|
1300
1508
|
const idx = this._exploreQueue.findIndex((q) => q.conversationId === conversationId);
|
|
1301
1509
|
if (idx >= 0) {
|
|
1302
1510
|
clearTimeout(this._exploreQueue[idx].timeoutTimer);
|
|
1303
1511
|
this._exploreQueue.splice(idx, 1);
|
|
1304
1512
|
}
|
|
1513
|
+
const persistentChild = this._persistentProcesses.get(conversationId);
|
|
1514
|
+
if (persistentChild) {
|
|
1515
|
+
this._terminate(persistentChild);
|
|
1516
|
+
this._closeChildIo(persistentChild);
|
|
1517
|
+
this._persistentProcesses.delete(conversationId);
|
|
1518
|
+
}
|
|
1305
1519
|
this._stdinSessions.kill(conversationId);
|
|
1306
1520
|
this._stdinCumulative.delete(conversationId);
|
|
1307
1521
|
this._exploreLifecycle.delete(conversationId);
|
|
@@ -1314,42 +1528,62 @@ class ChatManager {
|
|
|
1314
1528
|
* app exits and keep consuming API quota/CPU. Idempotent.
|
|
1315
1529
|
*/
|
|
1316
1530
|
shutdown() {
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1531
|
+
if (this._disposed)
|
|
1532
|
+
return;
|
|
1533
|
+
this._disposed = true;
|
|
1534
|
+
this._resolveDisposed();
|
|
1535
|
+
// Snapshot before cancellation callbacks remove ownership from the maps.
|
|
1536
|
+
const ownedChildren = new Set([
|
|
1537
|
+
...this._activeProcesses.values(),
|
|
1538
|
+
...this._persistentProcesses.values(),
|
|
1539
|
+
]);
|
|
1540
|
+
const auxChildren = Array.from(this._auxProcesses);
|
|
1541
|
+
// Settle every queued capacity waiter and every spawned-turn promise now;
|
|
1542
|
+
// do not rely on a killed/wedged child eventually emitting `close`.
|
|
1543
|
+
for (const q of this._exploreQueue) {
|
|
1544
|
+
clearTimeout(q.timeoutTimer);
|
|
1545
|
+
q.onTimeout();
|
|
1546
|
+
}
|
|
1547
|
+
this._exploreQueue = [];
|
|
1548
|
+
for (const cancel of Array.from(this._pendingTurnCancellations))
|
|
1549
|
+
cancel();
|
|
1550
|
+
this._pendingTurnCancellations.clear();
|
|
1551
|
+
for (const child of ownedChildren) {
|
|
1552
|
+
// ChatManager's process-group timer remains authoritative even for
|
|
1553
|
+
// persistent children: the transport's legacy root-PID escalation cannot
|
|
1554
|
+
// reach a resistant MCP after the root exits.
|
|
1555
|
+
this._terminate(child);
|
|
1556
|
+
this._closeChildIo(child);
|
|
1324
1557
|
}
|
|
1325
1558
|
// Persistent-stdin children outlive individual turns — tear them down too.
|
|
1326
1559
|
this._stdinSessions.killAll();
|
|
1560
|
+
this._persistentProcesses.clear();
|
|
1327
1561
|
this._stdinCumulative.clear();
|
|
1328
1562
|
// Fire-and-forget auxiliary children (auto-title) are not keyed by
|
|
1329
1563
|
// conversation; tree-kill any in-flight one so it isn't orphaned on
|
|
1330
1564
|
// shutdown / project removal (BUG-CHAT-02).
|
|
1331
|
-
for (const child of
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
}
|
|
1336
|
-
catch { /* best-effort */ }
|
|
1565
|
+
for (const child of auxChildren) {
|
|
1566
|
+
const reader = this._auxReaders.get(child);
|
|
1567
|
+
try {
|
|
1568
|
+
reader?.close();
|
|
1337
1569
|
}
|
|
1570
|
+
catch { /* best-effort */ }
|
|
1571
|
+
this._terminate(child);
|
|
1572
|
+
this._closeChildIo(child);
|
|
1338
1573
|
}
|
|
1574
|
+
this._auxReaders.clear();
|
|
1339
1575
|
this._auxProcesses.clear();
|
|
1340
1576
|
for (const id of this._exploreLifecycle.keys()) {
|
|
1341
1577
|
this._clearIdleTimer(id);
|
|
1342
1578
|
}
|
|
1343
|
-
for (const q of this._exploreQueue) {
|
|
1344
|
-
clearTimeout(q.timeoutTimer);
|
|
1345
|
-
}
|
|
1346
|
-
this._exploreQueue = [];
|
|
1347
1579
|
this._activeProcesses.clear();
|
|
1580
|
+
this._reservedTurns.clear();
|
|
1348
1581
|
this._buffers.clear();
|
|
1349
1582
|
this._emittedProposals.clear();
|
|
1350
1583
|
this._abortingConversations.clear();
|
|
1351
1584
|
this._streamFilters.clear();
|
|
1352
1585
|
this._exploreLifecycle.clear();
|
|
1586
|
+
this._specDraftStates.clear();
|
|
1353
1587
|
}
|
|
1354
1588
|
/**
|
|
1355
1589
|
* Record an ai_invocations row for a chat turn (explore or sidebar).
|
|
@@ -1368,6 +1602,8 @@ class ChatManager {
|
|
|
1368
1602
|
* native cost — so kill/crash paths still record a priced row.
|
|
1369
1603
|
*/
|
|
1370
1604
|
_recordChatInvocation(opts) {
|
|
1605
|
+
if (this._disposed)
|
|
1606
|
+
return;
|
|
1371
1607
|
if (!this._projectId)
|
|
1372
1608
|
return;
|
|
1373
1609
|
if (opts.kind !== 'explore' && opts.kind !== 'sidebar')
|
|
@@ -1397,6 +1633,8 @@ class ChatManager {
|
|
|
1397
1633
|
}
|
|
1398
1634
|
}
|
|
1399
1635
|
_autoTitle(conversationId, firstUserMsg, firstResponse) {
|
|
1636
|
+
if (this._disposed)
|
|
1637
|
+
return;
|
|
1400
1638
|
try {
|
|
1401
1639
|
// Title generation runs on the conversation's own provider.
|
|
1402
1640
|
const conv = (0, db_1.getConversation)(this._db, conversationId);
|
|
@@ -1407,7 +1645,7 @@ class ChatManager {
|
|
|
1407
1645
|
prompt: titlePrompt,
|
|
1408
1646
|
model: adapter.defaultModel(),
|
|
1409
1647
|
});
|
|
1410
|
-
const child =
|
|
1648
|
+
const child = this._spawnOwned(adapter.binary, args, {
|
|
1411
1649
|
env: process.env,
|
|
1412
1650
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
1413
1651
|
cwd: this._cwd,
|
|
@@ -1424,7 +1662,10 @@ class ChatManager {
|
|
|
1424
1662
|
const titleEvents = [];
|
|
1425
1663
|
const titleStartedAt = new Date().toISOString();
|
|
1426
1664
|
const reader = (0, readline_1.createInterface)({ input: child.stdout, crlfDelay: Infinity });
|
|
1665
|
+
this._auxReaders.set(child, reader);
|
|
1427
1666
|
reader.on('line', (line) => {
|
|
1667
|
+
if (this._disposed)
|
|
1668
|
+
return;
|
|
1428
1669
|
const ev = adapter.parseStreamLine(line);
|
|
1429
1670
|
if (!ev)
|
|
1430
1671
|
return;
|
|
@@ -1436,8 +1677,23 @@ class ChatManager {
|
|
|
1436
1677
|
titleText = trimmed;
|
|
1437
1678
|
}
|
|
1438
1679
|
});
|
|
1680
|
+
child.on('error', () => {
|
|
1681
|
+
this._auxProcesses.delete(child);
|
|
1682
|
+
this._auxReaders.delete(child);
|
|
1683
|
+
try {
|
|
1684
|
+
reader.close();
|
|
1685
|
+
}
|
|
1686
|
+
catch { /* best-effort */ }
|
|
1687
|
+
});
|
|
1439
1688
|
child.on('close', (code) => {
|
|
1440
1689
|
this._auxProcesses.delete(child);
|
|
1690
|
+
this._auxReaders.delete(child);
|
|
1691
|
+
try {
|
|
1692
|
+
reader.close();
|
|
1693
|
+
}
|
|
1694
|
+
catch { /* best-effort */ }
|
|
1695
|
+
if (this._disposed)
|
|
1696
|
+
return;
|
|
1441
1697
|
this._recordChatInvocation({
|
|
1442
1698
|
conversationId,
|
|
1443
1699
|
kind: conv?.kind,
|