specrails-desktop 2.3.0 → 2.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/client/dist/assets/ActivityFeedPage-BTYWMRwB.js +1 -0
- package/client/dist/assets/AgentsPage-BfOCeHHt.js +86 -0
- package/client/dist/assets/{AnalyticsPage-Dyyz1ht3.js → AnalyticsPage-AbVXKh9v.js} +1 -1
- package/client/dist/assets/{BarChart-CMdLa6Es.js → BarChart-DlshJN3Z.js} +2 -2
- package/client/dist/assets/CodePage-DJCjDG4I.js +2 -0
- package/client/dist/assets/{DesktopAnalyticsPage-CTNwb639.js → DesktopAnalyticsPage-CTqZ9mbB.js} +1 -1
- package/client/dist/assets/DocsDialog-KiJOSRvX.js +11 -0
- package/client/dist/assets/DocsPage-B17CR54A.js +11 -0
- package/client/dist/assets/{ExportDropdown-DuoZcdYN.js → ExportDropdown-BAu6z3b6.js} +1 -1
- package/client/dist/assets/IntegrationsPage-CCG64Q-6.js +3 -0
- package/client/dist/assets/JobDetailPage-BnGJSMiS.js +16 -0
- package/client/dist/assets/JobsPage-B-tn4CIf.js +1 -0
- package/client/dist/assets/{cssMode-Cc6ozl-J.js → cssMode-DzNPAYFh.js} +1 -1
- package/client/dist/assets/dashboard--Ahnvfr3.js +1 -0
- package/client/dist/assets/dashboard-BN1C2pEh.js +1 -0
- package/client/dist/assets/dashboard-BZs_EzAn.js +1 -0
- package/client/dist/assets/dashboard-Bsw44L8_.js +1 -0
- package/client/dist/assets/dashboard-Bw3VECgY.js +1 -0
- package/client/dist/assets/{dashboard-Duo4DDCW.js → dashboard-CuOshSHn.js} +1 -1
- package/client/dist/assets/dashboard-DfouCM3_.js +1 -0
- package/client/dist/assets/dashboard-Pp5hwnZB.js +1 -0
- package/client/dist/assets/{dist-js-H6hyhSuv.js → dist-js-B16c3VyT.js} +1 -1
- package/client/dist/assets/{dist-js-4UEGaKhD.js → dist-js-P2FkJ6fA.js} +1 -1
- package/client/dist/assets/{editor.main-CfXxHimg.js → editor.main-C7Rmw-hR.js} +2 -2
- package/client/dist/assets/{freemarker2-DP7J1gG3.js → freemarker2-Cszs4SVo.js} +1 -1
- package/client/dist/assets/{handlebars-BjRlucw6.js → handlebars-Dp7Lsuym.js} +1 -1
- package/client/dist/assets/{html-OumBQJ-U.js → html-BURidrEm.js} +1 -1
- package/client/dist/assets/{htmlMode-CStc3zXM.js → htmlMode--k5M7GjZ.js} +1 -1
- package/client/dist/assets/index-AfVF6BgE.js +142 -0
- package/client/dist/assets/index-NlH5BbXJ.css +2 -0
- package/client/dist/assets/{integrations-Cublz3m6.js → integrations-2C7MkGT0.js} +1 -1
- package/client/dist/assets/{integrations-HIlUxXVs.js → integrations-BDC670cg.js} +1 -1
- package/client/dist/assets/integrations-BqUmRUef.js +1 -0
- package/client/dist/assets/{integrations-DmQYCUvN.js → integrations-C2jQtv-s.js} +1 -1
- package/client/dist/assets/{integrations-DRdbki5W.js → integrations-CB98NeH5.js} +1 -1
- package/client/dist/assets/{integrations-C3p12Ms6.js → integrations-CX4p_bij.js} +1 -1
- package/client/dist/assets/{integrations-DaC4SzzL.js → integrations-_SuVeQIG.js} +1 -1
- package/client/dist/assets/{integrations-Cr6hH7XR.js → integrations-eQPHAYsE.js} +1 -1
- package/client/dist/assets/{javascript-CMk--e7g.js → javascript-kJQz__44.js} +1 -1
- package/client/dist/assets/jira-C-ATCti0.js +1 -0
- package/client/dist/assets/jira-CmVfRM-b.js +1 -0
- package/client/dist/assets/jira-D7bkKAX8.js +1 -0
- package/client/dist/assets/jira-DKImM1YH.js +1 -0
- package/client/dist/assets/jira-DOw8bkIR.js +1 -0
- package/client/dist/assets/jira-DlA-wGp-.js +1 -0
- package/client/dist/assets/jira-Fob8EGxN.js +1 -0
- package/client/dist/assets/jira-xZA2lixb.js +1 -0
- package/client/dist/assets/jobs-BGkI19S_.js +1 -0
- package/client/dist/assets/jobs-Brp44JDd.js +1 -0
- package/client/dist/assets/jobs-D93lG6If.js +1 -0
- package/client/dist/assets/jobs-DAF8AGy5.js +1 -0
- package/client/dist/assets/jobs-Db3xrsp_.js +1 -0
- package/client/dist/assets/jobs-Do4Ltqdj.js +1 -0
- package/client/dist/assets/jobs-F5PGJwbW.js +1 -0
- package/client/dist/assets/jobs-fYWWxCUV.js +1 -0
- package/client/dist/assets/{jsonMode-C2h3ZcjZ.js → jsonMode-v5JYPpnz.js} +1 -1
- package/client/dist/assets/{lib-Cs5FrUJI.js → lib-rNNmltMb.js} +1 -1
- package/client/dist/assets/{liquid-mI3KJrBE.js → liquid-Dl9I6gWt.js} +1 -1
- package/client/dist/assets/{lspLanguageFeatures-DU09ggWi.js → lspLanguageFeatures-CPlEe0NK.js} +1 -1
- package/client/dist/assets/{mdx-C41VDTR_.js → mdx-Byl7TtzQ.js} +1 -1
- package/client/dist/assets/{monaco.contribution-CPObAXMC.js → monaco.contribution-YMAkHQcQ.js} +2 -2
- package/client/dist/assets/{python-Y27rKQtk.js → python-jWQwT6j2.js} +1 -1
- package/client/dist/assets/{razor-Cd5-q9Bp.js → razor-BWS3sP-E.js} +1 -1
- package/client/dist/assets/setup-C0dzw8j4.js +1 -0
- package/client/dist/assets/setup-C1IA-9YS.js +1 -0
- package/client/dist/assets/setup-CpfjaNut.js +1 -0
- package/client/dist/assets/setup-D3rNZA9A.js +1 -0
- package/client/dist/assets/setup-UD2aanGs.js +1 -0
- package/client/dist/assets/setup-WP6WOYQh.js +1 -0
- package/client/dist/assets/setup-gzLG8T6F.js +1 -0
- package/client/dist/assets/setup-pjgmYHx6.js +1 -0
- package/client/dist/assets/{specs-DaUTrNF9.js → specs-B4GuOzuZ.js} +1 -1
- package/client/dist/assets/{specs-CZ1PsXsC.js → specs-BVLKe2n5.js} +1 -1
- package/client/dist/assets/{specs-k0PyLDVt.js → specs-C62F2CDv.js} +1 -1
- package/client/dist/assets/specs-D-Sb6dre.js +1 -0
- package/client/dist/assets/{specs-B__C8-8a.js → specs-DFSkAeK8.js} +1 -1
- package/client/dist/assets/{specs-BFfu3u-a.js → specs-DfwDeADE.js} +1 -1
- package/client/dist/assets/{specs-D2FzlLn9.js → specs-VK-zXv7x.js} +1 -1
- package/client/dist/assets/{specs-Dyc5hYeE.js → specs-ghyBMnib.js} +1 -1
- package/client/dist/assets/{tsMode-B0y_xEci.js → tsMode-BbOGOuSV.js} +1 -1
- package/client/dist/assets/{typescript-BzK0OgwW.js → typescript-eBtFQJLs.js} +1 -1
- package/client/dist/assets/{useProjectCache-BZWYV-w-.js → useProjectCache-Cid_GxRM.js} +1 -1
- package/client/dist/assets/{workers-rt--R2Qy.js → workers-BvicOoDf.js} +1 -1
- package/client/dist/assets/{xml-eX9QXAmI.js → xml-BJepAPyM.js} +1 -1
- package/client/dist/assets/{yaml-fcsNkpOt.js → yaml-DabgV-eA.js} +1 -1
- package/client/dist/index.html +13 -12
- package/docs/jira-integration-plan.md +321 -0
- package/package.json +1 -1
- package/server/dist/chat-manager.js +19 -7
- package/server/dist/context-scope.js +29 -8
- package/server/dist/db.js +127 -2
- package/server/dist/feature-flags.js +26 -0
- package/server/dist/interactive-job-session.js +363 -0
- package/server/dist/jira/jira-adf.js +113 -0
- package/server/dist/jira/jira-backlog-config.js +58 -0
- package/server/dist/jira/jira-client.js +279 -0
- package/server/dist/jira/jira-credential-store.js +103 -0
- package/server/dist/jira/jira-db.js +341 -0
- package/server/dist/jira/jira-issue-fields.js +428 -0
- package/server/dist/jira/jira-materializer.js +250 -0
- package/server/dist/jira/jira-status-resolver.js +211 -0
- package/server/dist/jira/jira-sync-manager.js +1014 -0
- package/server/dist/jira/types.js +9 -0
- package/server/dist/jira-router.js +304 -0
- package/server/dist/project-registry.js +43 -1
- package/server/dist/project-router-jobs.js +42 -0
- package/server/dist/project-router-tickets.js +49 -1
- package/server/dist/project-router.js +4 -0
- package/server/dist/queue-manager.js +214 -54
- package/server/dist/rails-router.js +27 -1
- package/server/dist/util/stream-display.js +66 -0
- package/client/dist/assets/ActivityFeedPage-3Veccrvk.js +0 -1
- package/client/dist/assets/AgentsPage-2mFPghP4.js +0 -86
- package/client/dist/assets/CodePage-D7Xwjhut.js +0 -2
- package/client/dist/assets/DocsDialog-D8yoyZDD.js +0 -11
- package/client/dist/assets/DocsPage-CeO-fAxy.js +0 -11
- package/client/dist/assets/IntegrationsPage-iIZ0UEzf.js +0 -3
- package/client/dist/assets/JobDetailPage-DgJHAH2m.js +0 -16
- package/client/dist/assets/JobsPage-Bv_RpRAE.js +0 -1
- package/client/dist/assets/dashboard-B4ixDVk8.js +0 -1
- package/client/dist/assets/dashboard-BZBADHSj.js +0 -1
- package/client/dist/assets/dashboard-C1MfeUHs.js +0 -1
- package/client/dist/assets/dashboard-C7SK6xu5.js +0 -1
- package/client/dist/assets/dashboard-CB6Le1yN.js +0 -1
- package/client/dist/assets/dashboard-CoTpMOBM.js +0 -1
- package/client/dist/assets/dashboard-I19DXBxw.js +0 -1
- package/client/dist/assets/index-CGHKpC-N.js +0 -142
- package/client/dist/assets/index-D17R4Cjc.css +0 -2
- package/client/dist/assets/integrations-D28q1kF6.js +0 -1
- package/client/dist/assets/jobs-2N3RXDAM.js +0 -1
- package/client/dist/assets/jobs-2f6Hdc72.js +0 -1
- package/client/dist/assets/jobs-3j3_npyo.js +0 -1
- package/client/dist/assets/jobs-BqEbCCxD.js +0 -1
- package/client/dist/assets/jobs-DPPT6bV6.js +0 -1
- package/client/dist/assets/jobs-DRzjWI9u.js +0 -1
- package/client/dist/assets/jobs-cHYInoau.js +0 -1
- package/client/dist/assets/jobs-vGfzIDQa.js +0 -1
- package/client/dist/assets/setup--FMCsnQS.js +0 -1
- package/client/dist/assets/setup-B19ZpBNi.js +0 -1
- package/client/dist/assets/setup-BZPmkjSN.js +0 -1
- package/client/dist/assets/setup-BqYA02rS.js +0 -1
- package/client/dist/assets/setup-ChKQDHN9.js +0 -1
- package/client/dist/assets/setup-D2n9jMfM.js +0 -1
- package/client/dist/assets/setup-P3r6YP1D.js +0 -1
- package/client/dist/assets/setup-fnfEbwlv.js +0 -1
- package/client/dist/assets/specs-cKEh2LXt.js +0 -1
- /package/client/dist/assets/{abap-Bw6f2wDG.js → abap-s65oMlhi.js} +0 -0
- /package/client/dist/assets/{activity-BdrPln96.js → activity-BqqwnH_h.js} +0 -0
- /package/client/dist/assets/{activity-BEIp_Y1A.js → activity-C8qqEIoP.js} +0 -0
- /package/client/dist/assets/{activity-CpkRS8Sx.js → activity-CZVM4nlJ.js} +0 -0
- /package/client/dist/assets/{activity-DOUVEjJi.js → activity-Cyy07Tgo.js} +0 -0
- /package/client/dist/assets/{activity-DRwkql_y.js → activity-DlbWCa4y.js} +0 -0
- /package/client/dist/assets/{activity-DKCpESPt.js → activity-Dwq0heud.js} +0 -0
- /package/client/dist/assets/{activity-DcDQ7tjw.js → activity-qFTcMyW9.js} +0 -0
- /package/client/dist/assets/{addon-image-3WCl5Vhd.js → addon-image-CpF0L0jM.js} +0 -0
- /package/client/dist/assets/{addon-ligatures-C5OdliKs.js → addon-ligatures-hXysGZrA.js} +0 -0
- /package/client/dist/assets/{addon-webgl-BbX6pSjl.js → addon-webgl-Cn1slavz.js} +0 -0
- /package/client/dist/assets/{addspec-D33ocMxf.js → addspec-B1FTtI2a.js} +0 -0
- /package/client/dist/assets/{addspec-DFswZ0jK.js → addspec-BCT9vm_c.js} +0 -0
- /package/client/dist/assets/{addspec-DVZ15Jp8.js → addspec-DeDOztDr.js} +0 -0
- /package/client/dist/assets/{addspec-Fkv91Opc.js → addspec-DpRgmfmx.js} +0 -0
- /package/client/dist/assets/{addspec-BEeF5-zc.js → addspec-Dw-0Dg-4.js} +0 -0
- /package/client/dist/assets/{addspec-B5yl4Loj.js → addspec-rp496P_F.js} +0 -0
- /package/client/dist/assets/{addspec-DRE-jZv7.js → addspec-v8j6A7CD.js} +0 -0
- /package/client/dist/assets/{agents-DK-Dlc0i.js → agents-23iPejcA.js} +0 -0
- /package/client/dist/assets/{agents-Q6Ldfpxx.js → agents-BDx1RXcl.js} +0 -0
- /package/client/dist/assets/{agents-TeOSy-ax.js → agents-BFr3kUhK.js} +0 -0
- /package/client/dist/assets/{agents-Bm9rPqnt.js → agents-B_1L9xRg.js} +0 -0
- /package/client/dist/assets/{agents-1nCDWRmP.js → agents-BlPnx-mz.js} +0 -0
- /package/client/dist/assets/{agents-iTqjRajS.js → agents-DcxZHzNr.js} +0 -0
- /package/client/dist/assets/{agents-s87sMGzL.js → agents-G3shOewU.js} +0 -0
- /package/client/dist/assets/{agentstudio-B6Wb59E7.js → agentstudio-B-CMAQqy.js} +0 -0
- /package/client/dist/assets/{agentstudio-D3I62TLJ.js → agentstudio-Bk1eZcv4.js} +0 -0
- /package/client/dist/assets/{agentstudio-DuH9TogZ.js → agentstudio-ChxNuGAu.js} +0 -0
- /package/client/dist/assets/{agentstudio-Kw88_dUF.js → agentstudio-DNlme601.js} +0 -0
- /package/client/dist/assets/{agentstudio-BdidyBzZ.js → agentstudio-DpP9caEE.js} +0 -0
- /package/client/dist/assets/{agentstudio-BSnWLR63.js → agentstudio-Y3G0ddJ2.js} +0 -0
- /package/client/dist/assets/{agentstudio-BADhZ41e.js → agentstudio-kk9RB7Se.js} +0 -0
- /package/client/dist/assets/{aiedit-DJMny-D5.js → aiedit-5ETerMK1.js} +0 -0
- /package/client/dist/assets/{aiedit-D2ji6Qy0.js → aiedit-BBCrOpHq.js} +0 -0
- /package/client/dist/assets/{aiedit-DAhZTvtk.js → aiedit-BMtcGYNE.js} +0 -0
- /package/client/dist/assets/{aiedit-DvrcbwGv.js → aiedit-D9ddlgkM.js} +0 -0
- /package/client/dist/assets/{aiedit-WBSjT_C1.js → aiedit-De0SOH6S.js} +0 -0
- /package/client/dist/assets/{aiedit-BWxHGsYA.js → aiedit-DrfzQroF.js} +0 -0
- /package/client/dist/assets/{aiedit-DOcxERkU.js → aiedit-fMltW101.js} +0 -0
- /package/client/dist/assets/{analytics-C9Zc-rkM.js → analytics-BeTyviO8.js} +0 -0
- /package/client/dist/assets/{analytics-CrPCZRJ-.js → analytics-C4eEO260.js} +0 -0
- /package/client/dist/assets/{analytics-CYj0tfj7.js → analytics-C67cIA1b.js} +0 -0
- /package/client/dist/assets/{analytics-C6EzgtdE.js → analytics-CAguvW28.js} +0 -0
- /package/client/dist/assets/{analytics-CVx3YOc0.js → analytics-DBtt8Mgk.js} +0 -0
- /package/client/dist/assets/{analytics-CnY4kNG3.js → analytics-DUPtODxX.js} +0 -0
- /package/client/dist/assets/{analytics-BIdr0YfL.js → analytics-YIpQvPAc.js} +0 -0
- /package/client/dist/assets/{apex-Cw8_REBo.js → apex-BLUBIldB.js} +0 -0
- /package/client/dist/assets/{attachments-DYHGA2Dj.js → attachments-CCWasu-P.js} +0 -0
- /package/client/dist/assets/{attachments-Dd92KpUH.js → attachments-CHaDUfjB.js} +0 -0
- /package/client/dist/assets/{attachments-DzdU6DV6.js → attachments-CVSAbGNl.js} +0 -0
- /package/client/dist/assets/{attachments-Bcf6BG6V.js → attachments-Chg5poG1.js} +0 -0
- /package/client/dist/assets/{attachments-BW4L3l2L.js → attachments-DazTVJbH.js} +0 -0
- /package/client/dist/assets/{attachments-COcrGRFz.js → attachments-Dn-JImAK.js} +0 -0
- /package/client/dist/assets/{attachments-Bke8sCU4.js → attachments-LDA9kp2X.js} +0 -0
- /package/client/dist/assets/{azcli-Cz6HAoOw.js → azcli-DuWxh9mO.js} +0 -0
- /package/client/dist/assets/{bat-CcJ-xyqL.js → bat-UKoTejQm.js} +0 -0
- /package/client/dist/assets/{bicep-z1WDCKYz.js → bicep-4sTT4B3D.js} +0 -0
- /package/client/dist/assets/{browser-DGITz3fC.js → browser-BDd1dbFa.js} +0 -0
- /package/client/dist/assets/{browser-JsAIGCEW.js → browser-BWSgbfdX.js} +0 -0
- /package/client/dist/assets/{browser-M5-rbPlw.js → browser-D2Y_UAKA.js} +0 -0
- /package/client/dist/assets/{browser-BlYF4OOq.js → browser-DH9SGVfM.js} +0 -0
- /package/client/dist/assets/{browser-Bc-YdlVg.js → browser-DWOVYMlg.js} +0 -0
- /package/client/dist/assets/{browser-CT-ReZGt.js → browser-Dxc_VIRK.js} +0 -0
- /package/client/dist/assets/{browser-5ErDlJoR.js → browser-lTQwcDCI.js} +0 -0
- /package/client/dist/assets/{cameligo-BRewOpfa.js → cameligo-CAAryRYO.js} +0 -0
- /package/client/dist/assets/{chat-DwUm6W9z.js → chat-BO9MvVID.js} +0 -0
- /package/client/dist/assets/{chat-BEGuC03z.js → chat-CPgmgZOj.js} +0 -0
- /package/client/dist/assets/{chat-CboQguCi.js → chat-CUrG1eVg.js} +0 -0
- /package/client/dist/assets/{chat-DRCa9pOt.js → chat-CvOOKB2s.js} +0 -0
- /package/client/dist/assets/{chat-BEW60P_u.js → chat-DIh3hr6y.js} +0 -0
- /package/client/dist/assets/{chat-yoXwguQu.js → chat-UVVZqA57.js} +0 -0
- /package/client/dist/assets/{chat-BQNMD0PL.js → chat-mPn3UlMl.js} +0 -0
- /package/client/dist/assets/{clojure-DBjRWN6g.js → clojure-BlMERO1w.js} +0 -0
- /package/client/dist/assets/{clsx-DnqN-uhr.js → clsx-CnH-HMk3.js} +0 -0
- /package/client/dist/assets/{code-zCwBt3Uu.js → code-BwIz8agY.js} +0 -0
- /package/client/dist/assets/{code-g0qFMzyg.js → code-CD7yNSK0.js} +0 -0
- /package/client/dist/assets/{code-DDU0CRS0.js → code-CDFlxUFC.js} +0 -0
- /package/client/dist/assets/{code-L35Loak_.js → code-Cp3Fdng-.js} +0 -0
- /package/client/dist/assets/{code-D1z-YDt-.js → code-D24e1Crx.js} +0 -0
- /package/client/dist/assets/{code-BtsmPQLV.js → code-DtZBQTi9.js} +0 -0
- /package/client/dist/assets/{code-Coa8f2Sh.js → code-nKa0fkm_.js} +0 -0
- /package/client/dist/assets/{coffee-Cfk_XHGR.js → coffee-Cj8D-Wl1.js} +0 -0
- /package/client/dist/assets/{commands-sqrqsxyE.js → commands-B-MVT-2F.js} +0 -0
- /package/client/dist/assets/{commands-UD1NzmwX.js → commands-B0yFTp7e.js} +0 -0
- /package/client/dist/assets/{commands-DLrvnPNg.js → commands-BR1kDkHQ.js} +0 -0
- /package/client/dist/assets/{commands-CJxCry-o.js → commands-Cb21pDlG.js} +0 -0
- /package/client/dist/assets/{commands-CfgY-_of.js → commands-DWgp-8W1.js} +0 -0
- /package/client/dist/assets/{commands-B772IyDa.js → commands-ddsl1V91.js} +0 -0
- /package/client/dist/assets/{commands-BDDp6xFG.js → commands-t4frzhB0.js} +0 -0
- /package/client/dist/assets/{common-Dmm1GhdD.js → common-5ilvMOcH.js} +0 -0
- /package/client/dist/assets/{common-DltqHaAe.js → common-B4sqsKp7.js} +0 -0
- /package/client/dist/assets/{common-GbpxfPG8.js → common-BKpVwUIf.js} +0 -0
- /package/client/dist/assets/{common-DeDELLZJ.js → common-BzEC3kJU.js} +0 -0
- /package/client/dist/assets/{common-DnjcgkPH.js → common-CALKUpYm.js} +0 -0
- /package/client/dist/assets/{common-Dard9UNH.js → common-CTEbWVZS.js} +0 -0
- /package/client/dist/assets/{common-DCr6VzJ7.js → common-DQiza2Xp.js} +0 -0
- /package/client/dist/assets/{cpp-BVob6BaP.js → cpp-BPfKnaj_.js} +0 -0
- /package/client/dist/assets/{csharp-C4fbRuOu.js → csharp-gX-x5uD6.js} +0 -0
- /package/client/dist/assets/{csp-DthFP_vT.js → csp-DKGVt8SM.js} +0 -0
- /package/client/dist/assets/{css-CGMH0hcW.js → css-CPMdnAVq.js} +0 -0
- /package/client/dist/assets/{cypher-Pnf68BRV.js → cypher-ClMDrj9S.js} +0 -0
- /package/client/dist/assets/{dart-PMMOtxZX.js → dart-C4zbzpVv.js} +0 -0
- /package/client/dist/assets/{dockerfile-di1nsJCc.js → dockerfile-D9xw73D1.js} +0 -0
- /package/client/dist/assets/{ecl-D_WVcB5M.js → ecl-gqO8tIR9.js} +0 -0
- /package/client/dist/assets/{editor.api2-XLGzZfbc.js → editor.api2-BPnIxMjz.js} +0 -0
- /package/client/dist/assets/{elixir-OAdJEMOn.js → elixir-DSAhVF3_.js} +0 -0
- /package/client/dist/assets/{explore-D2EFgt8J.js → explore-BE5UmlbD.js} +0 -0
- /package/client/dist/assets/{explore-BV5Xxlsn.js → explore-BmTaI8dX.js} +0 -0
- /package/client/dist/assets/{explore-A8Ltoblq.js → explore-CCwkqoWq.js} +0 -0
- /package/client/dist/assets/{explore-4mFpnrKU.js → explore-CMdEoPDx.js} +0 -0
- /package/client/dist/assets/{explore-C3FSE42C.js → explore-CtdCL4QU.js} +0 -0
- /package/client/dist/assets/{explore-B9A3iN2W.js → explore-DHjxSkqQ.js} +0 -0
- /package/client/dist/assets/{explore-BrBJvfjP.js → explore-__BeALjE.js} +0 -0
- /package/client/dist/assets/{flow9-D3QEZjgn.js → flow9-DeQCSPOd.js} +0 -0
- /package/client/dist/assets/{format-command-CwGuwzGA.js → format-command-2VNoNnMv.js} +0 -0
- /package/client/dist/assets/{fsharp-BF0k_8N8.js → fsharp-CEfaXL-S.js} +0 -0
- /package/client/dist/assets/{go-BAQO5Jsz.js → go-Xp1OkZCh.js} +0 -0
- /package/client/dist/assets/{graphql-hdFVFkiV.js → graphql-BwRXrUwe.js} +0 -0
- /package/client/dist/assets/{hcl-DWnl1o-X.js → hcl-u06DtVFk.js} +0 -0
- /package/client/dist/assets/{ini-CB-6OVu3.js → ini-AmeIpFND.js} +0 -0
- /package/client/dist/assets/{java-d1CmfiHX.js → java-CyDbRQjX.js} +0 -0
- /package/client/dist/assets/{julia-Bgv08lKa.js → julia-BqialFRG.js} +0 -0
- /package/client/dist/assets/{kotlin-u98kaVTf.js → kotlin-Dzz8TWAt.js} +0 -0
- /package/client/dist/assets/{less-CjYwpgg5.js → less-DHRJD3TR.js} +0 -0
- /package/client/dist/assets/{lexon-YTjaAFBB.js → lexon-5Y3QgTmT.js} +0 -0
- /package/client/dist/assets/{lua-BzmkWv27.js → lua-sKvhfPn5.js} +0 -0
- /package/client/dist/assets/{m3-CFwk9fw0.js → m3-DWDVwkFG.js} +0 -0
- /package/client/dist/assets/{markdown-CR5iMpSZ.js → markdown-CD_aSBxW.js} +0 -0
- /package/client/dist/assets/{mips-CcEalc17.js → mips-687T03hg.js} +0 -0
- /package/client/dist/assets/{msdax-BQbkawnr.js → msdax-C1St-dIV.js} +0 -0
- /package/client/dist/assets/{mysql-GTlaaW_P.js → mysql-BG7r8oBS.js} +0 -0
- /package/client/dist/assets/{nav-C2YXcbZS.js → nav-B05EYB0b.js} +0 -0
- /package/client/dist/assets/{nav-D2bOGSEg.js → nav-BNGCq-0y.js} +0 -0
- /package/client/dist/assets/{nav-BEL3MTwK.js → nav-BRInPX8a.js} +0 -0
- /package/client/dist/assets/{nav-CtYwmMgu.js → nav-Bf87DRHD.js} +0 -0
- /package/client/dist/assets/{nav-iH1V5j6o.js → nav-BkVzzFpc.js} +0 -0
- /package/client/dist/assets/{nav-0fwkrgHt.js → nav-BzFLtS1W.js} +0 -0
- /package/client/dist/assets/{nav-ClzOE4mA.js → nav-DBDbQOYn.js} +0 -0
- /package/client/dist/assets/{nav-B_G-TJDW.js → nav-X9sVtUWC.js} +0 -0
- /package/client/dist/assets/{objective-c-Byu1T5if.js → objective-c-Ds1-m05L.js} +0 -0
- /package/client/dist/assets/{pascal-BrfzBfRm.js → pascal-BKK9FpIi.js} +0 -0
- /package/client/dist/assets/{pascaligo-BXXKFUeo.js → pascaligo-SRS3nwtO.js} +0 -0
- /package/client/dist/assets/{perl-B3OikKq-.js → perl-B2hTOlrF.js} +0 -0
- /package/client/dist/assets/{pgsql-CTsa0Acc.js → pgsql-DIQJYNpL.js} +0 -0
- /package/client/dist/assets/{php-DiQh3FUW.js → php-BEaVe8X2.js} +0 -0
- /package/client/dist/assets/{pla-92uH8Fzm.js → pla-oPLHpZ-Q.js} +0 -0
- /package/client/dist/assets/{postiats-BbeWkKUr.js → postiats-D_vzrAzD.js} +0 -0
- /package/client/dist/assets/{powerquery-DgDMzpsm.js → powerquery-BKG6w-FH.js} +0 -0
- /package/client/dist/assets/{powershell-BfdUUzaG.js → powershell-B3dLhDt4.js} +0 -0
- /package/client/dist/assets/{protobuf-BojW2ftW.js → protobuf-DC8SGjcl.js} +0 -0
- /package/client/dist/assets/{pug-BxqTg3IU.js → pug-D5E-4fI0.js} +0 -0
- /package/client/dist/assets/{qsharp-BX_A-MW9.js → qsharp-6vJAWv0x.js} +0 -0
- /package/client/dist/assets/{r-D9BMnxvJ.js → r-CDwsEcbM.js} +0 -0
- /package/client/dist/assets/{redis-5cJqEQJJ.js → redis-CuQbbESS.js} +0 -0
- /package/client/dist/assets/{redshift-d8BBqiwb.js → redshift-B9e1k-qI.js} +0 -0
- /package/client/dist/assets/{restructuredtext-C8a6yIcZ.js → restructuredtext-BiJ5IwaU.js} +0 -0
- /package/client/dist/assets/{ruby-egeh-6KX.js → ruby-B0UAHY9b.js} +0 -0
- /package/client/dist/assets/{rust-a3r9IInB.js → rust-Dg_spmFr.js} +0 -0
- /package/client/dist/assets/{sb-y8iRIDei.js → sb-DjU66I8Q.js} +0 -0
- /package/client/dist/assets/{scala-BPDK2AmK.js → scala-qvStIdfG.js} +0 -0
- /package/client/dist/assets/{scheme-BIWUEoOs.js → scheme-FstEk5Rh.js} +0 -0
- /package/client/dist/assets/{scss-CA-PSzwg.js → scss-w0U3rQLK.js} +0 -0
- /package/client/dist/assets/{settings-CTcwN9RE.js → settings-5tzo0Rn3.js} +0 -0
- /package/client/dist/assets/{settings-D_dujJZI.js → settings-BDAW3trC.js} +0 -0
- /package/client/dist/assets/{settings-Bg0A3zoS.js → settings-BEWv3VEu.js} +0 -0
- /package/client/dist/assets/{settings-BgPqg2nv.js → settings-BORg56um.js} +0 -0
- /package/client/dist/assets/{settings-BSze3_9q.js → settings-D3LurcR5.js} +0 -0
- /package/client/dist/assets/{settings-CSJ0ahZ8.js → settings-DcqWIEM6.js} +0 -0
- /package/client/dist/assets/{settings-DYIV89nV.js → settings-Dfz8QbZS.js} +0 -0
- /package/client/dist/assets/{settings-DDcfx_ca.js → settings-yMubjqYw.js} +0 -0
- /package/client/dist/assets/{shell--LiT1Bja.js → shell-DJ78wREd.js} +0 -0
- /package/client/dist/assets/{solidity-DdqZccZg.js → solidity-1aGIVsdX.js} +0 -0
- /package/client/dist/assets/{sophia-S6-YxNG_.js → sophia-40LqcGjB.js} +0 -0
- /package/client/dist/assets/{sparql-BSf5kMp2.js → sparql-Cz5dqG_g.js} +0 -0
- /package/client/dist/assets/{sql-D7KgjR8G.js → sql-64f62Ni4.js} +0 -0
- /package/client/dist/assets/{st-BnoDa-Ml.js → st-gJe2yG8J.js} +0 -0
- /package/client/dist/assets/{swift-DEUHTkUX.js → swift-C6ME22mv.js} +0 -0
- /package/client/dist/assets/{systemverilog-Tqb_KPnW.js → systemverilog-CEWz259w.js} +0 -0
- /package/client/dist/assets/{tcl-BmBFS2qq.js → tcl-CcLVIi3m.js} +0 -0
- /package/client/dist/assets/{terminal-Bje4ziIa.js → terminal-BYtreaaF.js} +0 -0
- /package/client/dist/assets/{terminal-CSONJOex.js → terminal-C0xx0SjA.js} +0 -0
- /package/client/dist/assets/{terminal-DeWzh6ys.js → terminal-CPpK58RC.js} +0 -0
- /package/client/dist/assets/{terminal-C2WYcFHF.js → terminal-CdxkpafL.js} +0 -0
- /package/client/dist/assets/{terminal-DEqzGtcr.js → terminal-Ciia0wh2.js} +0 -0
- /package/client/dist/assets/{terminal-80yDMgMF.js → terminal-DHIkiWcs.js} +0 -0
- /package/client/dist/assets/{terminal-lkZYR4wJ.js → terminal-DY42QANg.js} +0 -0
- /package/client/dist/assets/{terminal-YOlsJCQj.js → terminal-DoxtVdma.js} +0 -0
- /package/client/dist/assets/{tickets-DYvafSaY.js → tickets-0rM0lIXd.js} +0 -0
- /package/client/dist/assets/{tickets-DNOANUXr.js → tickets-1UIGf_oA.js} +0 -0
- /package/client/dist/assets/{tickets-DlpC_iTg.js → tickets-9kdPXInd.js} +0 -0
- /package/client/dist/assets/{tickets-CF2PYelu.js → tickets-C6pwZwt4.js} +0 -0
- /package/client/dist/assets/{tickets-CB7N30gm.js → tickets-DAjtxAVb.js} +0 -0
- /package/client/dist/assets/{tickets-DU1aqsbr.js → tickets-DNmXcAwu.js} +0 -0
- /package/client/dist/assets/{tickets-clefmXLv.js → tickets-n23kDqJT.js} +0 -0
- /package/client/dist/assets/{tickets-DucYgtdl.js → tickets-tGx5AR5b.js} +0 -0
- /package/client/dist/assets/{twig-BQV8igWC.js → twig-DvsO-WjW.js} +0 -0
- /package/client/dist/assets/{typespec-DlFroUGY.js → typespec-Brkt3IAA.js} +0 -0
- /package/client/dist/assets/{vb-BlrJpIMX.js → vb-r121Uzxt.js} +0 -0
- /package/client/dist/assets/{wgsl-BWgIc6FZ.js → wgsl-BRX8uYh4.js} +0 -0
|
@@ -14,6 +14,7 @@ const tree_kill_1 = __importDefault(require("tree-kill"));
|
|
|
14
14
|
const types_1 = require("./types");
|
|
15
15
|
const command_resolver_1 = require("./command-resolver");
|
|
16
16
|
const cli_prompt_1 = require("./util/cli-prompt");
|
|
17
|
+
const stream_display_1 = require("./util/stream-display");
|
|
17
18
|
const hooks_1 = require("./hooks");
|
|
18
19
|
const ai_invocations_1 = require("./ai-invocations");
|
|
19
20
|
const feature_flags_1 = require("./feature-flags");
|
|
@@ -23,6 +24,7 @@ const crypto_1 = require("crypto");
|
|
|
23
24
|
const providers_1 = require("./providers");
|
|
24
25
|
const codex_otel_bridge_1 = require("./codex-otel-bridge");
|
|
25
26
|
const db_1 = require("./db");
|
|
27
|
+
const interactive_job_session_1 = require("./interactive-job-session");
|
|
26
28
|
const attachment_manager_1 = require("./attachment-manager");
|
|
27
29
|
const ticket_store_1 = require("./ticket-store");
|
|
28
30
|
const binary_probe_1 = require("./binary-probe");
|
|
@@ -104,59 +106,6 @@ class JobAlreadyTerminalError extends Error {
|
|
|
104
106
|
}
|
|
105
107
|
exports.JobAlreadyTerminalError = JobAlreadyTerminalError;
|
|
106
108
|
// ─── Helpers ──────────────────────────────────────────────────────────────────
|
|
107
|
-
function extractDisplayText(event) {
|
|
108
|
-
const type = event.type;
|
|
109
|
-
// ── Claude `--output-format stream-json` ───────────────────────────────
|
|
110
|
-
if (type === 'assistant') {
|
|
111
|
-
const content = event.message;
|
|
112
|
-
const texts = (content?.content ?? [])
|
|
113
|
-
.filter((c) => c.type === 'text')
|
|
114
|
-
.map((c) => c.text ?? '');
|
|
115
|
-
return texts.join('') || null;
|
|
116
|
-
}
|
|
117
|
-
if (type === 'tool_use') {
|
|
118
|
-
const name = event.name;
|
|
119
|
-
const input = JSON.stringify(event.input ?? {});
|
|
120
|
-
return `[tool: ${name}] ${input.slice(0, 120)}`;
|
|
121
|
-
}
|
|
122
|
-
if (type === 'tool_result' || type === 'system_prompt' || type === 'user' || type === 'system' || type === 'result') {
|
|
123
|
-
return null;
|
|
124
|
-
}
|
|
125
|
-
// ── Codex `exec --json` event types ───────────────────────────────────
|
|
126
|
-
// Codex shape differs from claude: items are nested under `item` with a
|
|
127
|
-
// discriminator at `item.type`. Without explicit handling the Job Detail
|
|
128
|
-
// log shows only the spawn preamble and exit notice — exactly the
|
|
129
|
-
// "2 / 2 lines" symptom that masks 200k+ tokens of real work.
|
|
130
|
-
if (type === 'item.completed' || type === 'item.started') {
|
|
131
|
-
const item = event.item;
|
|
132
|
-
if (!item)
|
|
133
|
-
return null;
|
|
134
|
-
const itemType = item.type;
|
|
135
|
-
if (itemType === 'agent_message') {
|
|
136
|
-
const text = item.text?.trim();
|
|
137
|
-
return text && text.length > 0 ? text : null;
|
|
138
|
-
}
|
|
139
|
-
if (itemType === 'command_execution') {
|
|
140
|
-
// Only surface the completed line so the log isn't doubled with the
|
|
141
|
-
// matching `item.started` placeholder.
|
|
142
|
-
if (type !== 'item.completed')
|
|
143
|
-
return null;
|
|
144
|
-
const cmd = item.command ?? '';
|
|
145
|
-
const exitCode = item.exit_code;
|
|
146
|
-
const exitStr = typeof exitCode === 'number' ? ` → exit ${exitCode}` : '';
|
|
147
|
-
return `[exec]${exitStr} ${cmd.slice(0, 200)}`;
|
|
148
|
-
}
|
|
149
|
-
if (itemType === 'agent_reasoning') {
|
|
150
|
-
const text = item.text?.trim();
|
|
151
|
-
return text && text.length > 0 ? `[reasoning] ${text.slice(0, 200)}` : null;
|
|
152
|
-
}
|
|
153
|
-
return null;
|
|
154
|
-
}
|
|
155
|
-
if (type === 'thread.started' || type === 'turn.started' || type === 'turn.completed') {
|
|
156
|
-
return null;
|
|
157
|
-
}
|
|
158
|
-
return null;
|
|
159
|
-
}
|
|
160
109
|
const TERMINAL_STATUSES = new Set(['completed', 'failed', 'canceled', 'zombie_terminated', 'skipped']);
|
|
161
110
|
/** Match an Ultracode rail command: `/specrails:ultracode #5 …` (or `/sr:…`). */
|
|
162
111
|
exports.ULTRACODE_COMMAND_RE = /^\/(specrails|sr):ultracode\b/;
|
|
@@ -207,6 +156,12 @@ class QueueManager {
|
|
|
207
156
|
/** Pre-spawn working-tree snapshot refs keyed by jobId — read at exit time
|
|
208
157
|
* by the Code-Explorer provenance hook. Cleared on job exit. */
|
|
209
158
|
_snapshotRefs;
|
|
159
|
+
/** Pending per-job interactive flag keyed by jobId — read at spawn time.
|
|
160
|
+
* In-memory only (mirrors _jobModelSelection). */
|
|
161
|
+
_jobInteractiveSelection;
|
|
162
|
+
/** Live interactive job sessions keyed by jobId (the resident persistent-stdin
|
|
163
|
+
* child + per-turn accounting). Present only while an interactive job runs. */
|
|
164
|
+
_interactiveSessions;
|
|
210
165
|
constructor(broadcast, db, commands, cwd, options) {
|
|
211
166
|
this._queue = [];
|
|
212
167
|
this._jobs = new Map();
|
|
@@ -235,6 +190,8 @@ class QueueManager {
|
|
|
235
190
|
this._jobProviderSelection = new Map();
|
|
236
191
|
this._jobModelSelection = new Map();
|
|
237
192
|
this._snapshotRefs = new Map();
|
|
193
|
+
this._jobInteractiveSelection = new Map();
|
|
194
|
+
this._interactiveSessions = new Map();
|
|
238
195
|
const envTimeout = process.env.WM_ZOMBIE_TIMEOUT_MS !== undefined
|
|
239
196
|
? parseInt(process.env.WM_ZOMBIE_TIMEOUT_MS, 10)
|
|
240
197
|
: null;
|
|
@@ -293,6 +250,15 @@ class QueueManager {
|
|
|
293
250
|
}
|
|
294
251
|
this._activeProcess = null;
|
|
295
252
|
this._activeJobId = null;
|
|
253
|
+
// Tear down any resident interactive sessions (SIGTERM their children) so
|
|
254
|
+
// teardown orphans no persistent claude process. dispose() does not settle.
|
|
255
|
+
for (const session of this._interactiveSessions.values()) {
|
|
256
|
+
try {
|
|
257
|
+
session.dispose();
|
|
258
|
+
}
|
|
259
|
+
catch { /* best-effort */ }
|
|
260
|
+
}
|
|
261
|
+
this._interactiveSessions.clear();
|
|
296
262
|
// Release any per-job provenance snapshots so teardown leaves no map entries.
|
|
297
263
|
this._snapshotRefs.clear();
|
|
298
264
|
// Drop the DB reference last so any in-flight 'close' callback sees null
|
|
@@ -357,6 +323,11 @@ class QueueManager {
|
|
|
357
323
|
if (resolvedOpts?.model) {
|
|
358
324
|
this._jobModelSelection.set(id, resolvedOpts.model);
|
|
359
325
|
}
|
|
326
|
+
// Record per-job interactive flag (ultracode + claude only — enforced at
|
|
327
|
+
// spawn time against the resolved adapter's persistent-stdin capability).
|
|
328
|
+
if (resolvedOpts?.interactive) {
|
|
329
|
+
this._jobInteractiveSelection.set(id, true);
|
|
330
|
+
}
|
|
360
331
|
// Insert at the correct position based on priority (higher priority first, FIFO within same level)
|
|
361
332
|
const weight = types_1.PRIORITY_WEIGHT[priority];
|
|
362
333
|
let insertIdx = this._queue.length;
|
|
@@ -395,6 +366,7 @@ class QueueManager {
|
|
|
395
366
|
this._jobProviderSelection.delete(jobId);
|
|
396
367
|
this._jobModelSelection.delete(jobId);
|
|
397
368
|
this._jobProfileSelection.delete(jobId);
|
|
369
|
+
this._jobInteractiveSelection.delete(jobId);
|
|
398
370
|
this._skipDependents(jobId, `Parent job ${jobId} was canceled`);
|
|
399
371
|
this._recomputePositions();
|
|
400
372
|
this._persistJob(job);
|
|
@@ -415,6 +387,15 @@ class QueueManager {
|
|
|
415
387
|
return 'canceled';
|
|
416
388
|
}
|
|
417
389
|
// job.status === 'running'
|
|
390
|
+
// Interactive jobs own a resident child via the session (not _activeProcess),
|
|
391
|
+
// so route their cancel through the session: SIGTERM → settle sees the
|
|
392
|
+
// canceling flag and stamps 'canceled'.
|
|
393
|
+
const interactiveSession = this._interactiveSessions.get(jobId);
|
|
394
|
+
if (interactiveSession) {
|
|
395
|
+
this._cancelingJobs.add(jobId);
|
|
396
|
+
interactiveSession.finalize();
|
|
397
|
+
return 'canceling';
|
|
398
|
+
}
|
|
418
399
|
this._kill(jobId);
|
|
419
400
|
return 'canceling';
|
|
420
401
|
}
|
|
@@ -490,6 +471,29 @@ class QueueManager {
|
|
|
490
471
|
getLogBuffer() {
|
|
491
472
|
return [...this._logBuffer];
|
|
492
473
|
}
|
|
474
|
+
/** True while an interactive ultracode session is resident for this job. */
|
|
475
|
+
isInteractiveJob(jobId) {
|
|
476
|
+
return this._interactiveSessions.has(jobId);
|
|
477
|
+
}
|
|
478
|
+
/** Feed one more user prompt to a running interactive job (queued behind the
|
|
479
|
+
* active turn). Returns false when the job isn't an active interactive
|
|
480
|
+
* session (unknown / already finalized / not interactive). */
|
|
481
|
+
sendInteractiveTurn(jobId, text) {
|
|
482
|
+
const session = this._interactiveSessions.get(jobId);
|
|
483
|
+
if (!session)
|
|
484
|
+
return false;
|
|
485
|
+
return session.send(text);
|
|
486
|
+
}
|
|
487
|
+
/** User-initiated finalize for an interactive job: SIGTERM the resident child;
|
|
488
|
+
* the settle path stamps the summed totals + 'completed' status. Returns false
|
|
489
|
+
* when the job isn't an active interactive session. */
|
|
490
|
+
finalizeInteractive(jobId) {
|
|
491
|
+
const session = this._interactiveSessions.get(jobId);
|
|
492
|
+
if (!session)
|
|
493
|
+
return false;
|
|
494
|
+
session.finalize();
|
|
495
|
+
return true;
|
|
496
|
+
}
|
|
493
497
|
// ─── Private methods ────────────────────────────────────────────────────────
|
|
494
498
|
phasesForCommand(command) {
|
|
495
499
|
return this._phasesForCommand(command);
|
|
@@ -630,6 +634,143 @@ class QueueManager {
|
|
|
630
634
|
}
|
|
631
635
|
return this._adapter;
|
|
632
636
|
}
|
|
637
|
+
/**
|
|
638
|
+
* Spawn an interactive ultracode session. The job row is created with the
|
|
639
|
+
* `interactive` flag set; the resident child runs the first turn (the
|
|
640
|
+
* ultracode prompt) and stays alive for follow-up turns until finalize/crash.
|
|
641
|
+
* No zombie timer is armed (the child idles between turns by design) and
|
|
642
|
+
* `_activeProcess` is left null — the session owns the child; the active SLOT
|
|
643
|
+
* (`_activeJobId`, reserved by _drainQueue) is held until settle.
|
|
644
|
+
*/
|
|
645
|
+
_startInteractiveJob(jobId, job, adapter, spec, firstPrompt) {
|
|
646
|
+
if (this._db) {
|
|
647
|
+
try {
|
|
648
|
+
(0, db_1.createJob)(this._db, {
|
|
649
|
+
id: jobId,
|
|
650
|
+
command: job.command,
|
|
651
|
+
started_at: job.startedAt,
|
|
652
|
+
priority: job.priority,
|
|
653
|
+
depends_on_job_id: job.dependsOnJobId,
|
|
654
|
+
pipeline_id: job.pipelineId,
|
|
655
|
+
interactive: true,
|
|
656
|
+
});
|
|
657
|
+
}
|
|
658
|
+
catch (err) {
|
|
659
|
+
console.error('[queue-manager] createJob (interactive) failed:', err);
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
const session = new interactive_job_session_1.InteractiveJobSession({
|
|
663
|
+
jobId,
|
|
664
|
+
projectId: this._projectId ?? '',
|
|
665
|
+
db: this._db,
|
|
666
|
+
adapter,
|
|
667
|
+
broadcast: this._broadcast,
|
|
668
|
+
onSettle: (info) => this._settleInteractiveJob(jobId, info),
|
|
669
|
+
});
|
|
670
|
+
this._interactiveSessions.set(jobId, session);
|
|
671
|
+
session.start(spec, firstPrompt);
|
|
672
|
+
this._broadcastQueueState();
|
|
673
|
+
}
|
|
674
|
+
/**
|
|
675
|
+
* Terminal bookkeeping for an interactive job (called once by the session's
|
|
676
|
+
* onSettle). Releases the active slot, stamps the job's terminal status +
|
|
677
|
+
* finished_at (token/cost totals were already accumulated per turn), writes a
|
|
678
|
+
* single ai_invocations row with the summed usage, fires the rail/ticket
|
|
679
|
+
* completion callback, and drains the queue.
|
|
680
|
+
*/
|
|
681
|
+
_settleInteractiveJob(jobId, info) {
|
|
682
|
+
this._interactiveSessions.delete(jobId);
|
|
683
|
+
if (this._activeJobId === jobId) {
|
|
684
|
+
this._activeProcess = null;
|
|
685
|
+
this._activeJobId = null;
|
|
686
|
+
}
|
|
687
|
+
// Interactive jobs skip provenance, but a defensive delete keeps the map
|
|
688
|
+
// clean if a snapshot was ever recorded for this id.
|
|
689
|
+
this._snapshotRefs.delete(jobId);
|
|
690
|
+
if (this._disposed)
|
|
691
|
+
return;
|
|
692
|
+
const job = this._jobs.get(jobId);
|
|
693
|
+
if (!job) {
|
|
694
|
+
this._drainQueue();
|
|
695
|
+
return;
|
|
696
|
+
}
|
|
697
|
+
const wasCanceling = this._cancelingJobs.has(jobId);
|
|
698
|
+
this._cancelingJobs.delete(jobId);
|
|
699
|
+
const finalStatus = wasCanceling
|
|
700
|
+
? 'canceled'
|
|
701
|
+
: info.reason === 'finalized'
|
|
702
|
+
? 'completed'
|
|
703
|
+
: 'failed';
|
|
704
|
+
job.status = finalStatus;
|
|
705
|
+
job.finishedAt = new Date().toISOString();
|
|
706
|
+
job.exitCode = info.reason === 'finalized' ? 0 : 1;
|
|
707
|
+
const totals = info.totals;
|
|
708
|
+
if (this._db) {
|
|
709
|
+
try {
|
|
710
|
+
(0, db_1.finalizeInteractiveJob)(this._db, jobId, finalStatus);
|
|
711
|
+
}
|
|
712
|
+
catch (err) {
|
|
713
|
+
console.error('[queue-manager] finalizeInteractiveJob failed:', err);
|
|
714
|
+
}
|
|
715
|
+
if (this._projectId) {
|
|
716
|
+
try {
|
|
717
|
+
const invStatus = finalStatus === 'completed'
|
|
718
|
+
? 'success'
|
|
719
|
+
: finalStatus === 'canceled'
|
|
720
|
+
? 'aborted'
|
|
721
|
+
: 'failed';
|
|
722
|
+
const ticketIds = this._extractTicketIds(job.command);
|
|
723
|
+
const durationMs = job.startedAt
|
|
724
|
+
? new Date(job.finishedAt).getTime() - new Date(job.startedAt).getTime()
|
|
725
|
+
: undefined;
|
|
726
|
+
(0, ai_invocations_1.recordInvocation)(this._db, {
|
|
727
|
+
id: (0, crypto_1.randomUUID)(),
|
|
728
|
+
project_id: this._projectId,
|
|
729
|
+
provider: 'claude',
|
|
730
|
+
surface: 'job',
|
|
731
|
+
surface_ref_id: jobId,
|
|
732
|
+
ticket_id: ticketIds[0] ?? null,
|
|
733
|
+
status: invStatus,
|
|
734
|
+
started_at: job.startedAt ?? new Date().toISOString(),
|
|
735
|
+
finished_at: job.finishedAt,
|
|
736
|
+
total_cost_usd_estimated: false,
|
|
737
|
+
tokens_in: totals.tokens_in,
|
|
738
|
+
tokens_out: totals.tokens_out,
|
|
739
|
+
tokens_cache_read: totals.tokens_cache_read,
|
|
740
|
+
tokens_cache_create: totals.tokens_cache_create,
|
|
741
|
+
total_cost_usd: totals.total_cost_usd,
|
|
742
|
+
num_turns: totals.num_turns,
|
|
743
|
+
model: info.model ?? undefined,
|
|
744
|
+
session_id: info.sessionId ?? undefined,
|
|
745
|
+
duration_ms: durationMs,
|
|
746
|
+
});
|
|
747
|
+
this._broadcast({ type: 'spending.invalidated', projectId: this._projectId });
|
|
748
|
+
}
|
|
749
|
+
catch (err) {
|
|
750
|
+
console.error('[queue-manager] recordInvocation (interactive) failed:', err);
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
}
|
|
754
|
+
this._persistJob(job);
|
|
755
|
+
this._broadcast({
|
|
756
|
+
type: 'job.finalized',
|
|
757
|
+
projectId: this._projectId ?? '',
|
|
758
|
+
jobId,
|
|
759
|
+
status: finalStatus,
|
|
760
|
+
totals,
|
|
761
|
+
timestamp: new Date().toISOString(),
|
|
762
|
+
});
|
|
763
|
+
this._broadcastQueueState();
|
|
764
|
+
if (this._onJobFinished) {
|
|
765
|
+
try {
|
|
766
|
+
this._onJobFinished(jobId, finalStatus, totals.total_cost_usd);
|
|
767
|
+
}
|
|
768
|
+
catch (err) {
|
|
769
|
+
console.error(`[QueueManager] onJobFinished failed for ${jobId}: ${err.message}`);
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
this._drainQueue();
|
|
773
|
+
}
|
|
633
774
|
async _startJob(jobId) {
|
|
634
775
|
const job = this._jobs.get(jobId);
|
|
635
776
|
if (!job) {
|
|
@@ -859,6 +1000,25 @@ class QueueManager {
|
|
|
859
1000
|
};
|
|
860
1001
|
}
|
|
861
1002
|
}
|
|
1003
|
+
// ─── Interactive ultracode branch ──────────────────────────────────────
|
|
1004
|
+
// When the launch requested interactive mode AND the command is ultracode
|
|
1005
|
+
// AND the adapter supports persistent stdin (claude), hand off to a resident
|
|
1006
|
+
// session instead of the one-shot spawn below. The session keeps the child
|
|
1007
|
+
// alive across turns and settles only on finalize/crash. Code-Explorer
|
|
1008
|
+
// provenance is intentionally skipped for interactive jobs (v1 — deferred).
|
|
1009
|
+
const wantsInteractive = this._jobInteractiveSelection.get(jobId) === true;
|
|
1010
|
+
this._jobInteractiveSelection.delete(jobId);
|
|
1011
|
+
if (wantsInteractive && isUltracode && adapter.capabilities.persistentStdin) {
|
|
1012
|
+
const interactiveArgs = adapter.buildArgs('chat-stream', {
|
|
1013
|
+
// chat-stream feeds the prompt over stdin per-turn, so the argv `prompt`
|
|
1014
|
+
// is unused — pass empty to satisfy the shared SpawnOptions shape.
|
|
1015
|
+
prompt: '',
|
|
1016
|
+
systemPrompt: systemAppend || undefined,
|
|
1017
|
+
model: railModel,
|
|
1018
|
+
});
|
|
1019
|
+
this._startInteractiveJob(jobId, job, adapter, { binary, args: interactiveArgs, cwd: this._cwd, env: spawnEnv }, railPrompt);
|
|
1020
|
+
return;
|
|
1021
|
+
}
|
|
862
1022
|
// Code-Explorer pre-spawn snapshot. Captures the working-tree state via
|
|
863
1023
|
// `git stash create --include-untracked` so the post-exit hook can diff
|
|
864
1024
|
// against it. Gated by SPECRAILS_CODE_EXPLORER — when off, no-op.
|
|
@@ -996,7 +1156,7 @@ class QueueManager {
|
|
|
996
1156
|
if (eventType === 'result') {
|
|
997
1157
|
lastResultEvent = parsed;
|
|
998
1158
|
}
|
|
999
|
-
const displayText = extractDisplayText(parsed);
|
|
1159
|
+
const displayText = (0, stream_display_1.extractDisplayText)(parsed);
|
|
1000
1160
|
if (displayText !== null) {
|
|
1001
1161
|
if (this._db) {
|
|
1002
1162
|
(0, db_1.appendEvent)(this._db, jobId, eventSeq++, {
|
|
@@ -5,6 +5,7 @@ const express_1 = require("express");
|
|
|
5
5
|
const rails_store_1 = require("./rails-store");
|
|
6
6
|
const queue_manager_1 = require("./queue-manager");
|
|
7
7
|
const provider_selection_1 = require("./provider-selection");
|
|
8
|
+
const feature_flags_1 = require("./feature-flags");
|
|
8
9
|
const VALID_MODES = new Set(['implement', 'batch-implement', 'ultracode']);
|
|
9
10
|
// Models the ultracode picker exposes (Claude aliases). Mirrors the client
|
|
10
11
|
// RailModelSelector options and the project-router orchestrator-model allow-list.
|
|
@@ -189,7 +190,7 @@ function createRailsRouter() {
|
|
|
189
190
|
res.status(400).json({ error: 'Invalid rail index' });
|
|
190
191
|
return;
|
|
191
192
|
}
|
|
192
|
-
const { mode = 'implement', profileName, aiEngine, model } = req.body ?? {};
|
|
193
|
+
const { mode = 'implement', profileName, aiEngine, model, interactive } = req.body ?? {};
|
|
193
194
|
if (!VALID_MODES.has(mode)) {
|
|
194
195
|
res.status(400).json({ error: 'mode must be "implement", "batch-implement" or "ultracode"' });
|
|
195
196
|
return;
|
|
@@ -202,6 +203,18 @@ function createRailsRouter() {
|
|
|
202
203
|
return;
|
|
203
204
|
}
|
|
204
205
|
}
|
|
206
|
+
// Interactive toggle: only valid for ultracode (Claude-only) and only when
|
|
207
|
+
// the feature is enabled. Reject loudly so the client never silently drops it.
|
|
208
|
+
if (interactive === true) {
|
|
209
|
+
if (mode !== 'ultracode') {
|
|
210
|
+
res.status(400).json({ error: 'interactive mode is only available for ultracode rails' });
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
if (!(0, feature_flags_1.isInteractiveJobsEnabled)()) {
|
|
214
|
+
res.status(403).json({ error: 'Interactive jobs are disabled on this server' });
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
205
218
|
const c = ctx(req);
|
|
206
219
|
const rail = (0, rails_store_1.getRail)(c.db, railIndex);
|
|
207
220
|
if (rail.ticketIds.length === 0) {
|
|
@@ -267,9 +280,16 @@ function createRailsRouter() {
|
|
|
267
280
|
profileName: null,
|
|
268
281
|
provider: 'claude',
|
|
269
282
|
...(ultracodeModel ? { model: ultracodeModel } : {}),
|
|
283
|
+
...(interactive === true ? { interactive: true } : {}),
|
|
270
284
|
});
|
|
271
285
|
jobIds.push(job.id);
|
|
272
286
|
c.railJobs.set(job.id, { railIndex, mode, ticketIds: [ticketId] });
|
|
287
|
+
// Jira write-back: push In Progress for any Jira-linked ticket (inert
|
|
288
|
+
// for non-Jira projects). Best-effort — never blocks the launch.
|
|
289
|
+
try {
|
|
290
|
+
c.jiraSyncManager.onRailLaunch([ticketId], job.id);
|
|
291
|
+
}
|
|
292
|
+
catch { /* non-fatal */ }
|
|
273
293
|
}
|
|
274
294
|
jobId = jobIds[0];
|
|
275
295
|
const startMsg = {
|
|
@@ -291,6 +311,12 @@ function createRailsRouter() {
|
|
|
291
311
|
const job = c.queueManager.enqueue(command, 'normal', { profileName: resolvedProfile, provider: railProvider });
|
|
292
312
|
jobId = job.id;
|
|
293
313
|
c.railJobs.set(jobId, { railIndex, mode, ticketIds: [...rail.ticketIds] });
|
|
314
|
+
// Jira write-back: push In Progress for any Jira-linked ticket (inert for
|
|
315
|
+
// non-Jira projects). Best-effort — never blocks the launch.
|
|
316
|
+
try {
|
|
317
|
+
c.jiraSyncManager.onRailLaunch([...rail.ticketIds], jobId);
|
|
318
|
+
}
|
|
319
|
+
catch { /* non-fatal */ }
|
|
294
320
|
const startMsg = {
|
|
295
321
|
type: 'rail.job_started',
|
|
296
322
|
projectId: c.project.id,
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Shared stream-frame → human-readable display-text extraction.
|
|
3
|
+
//
|
|
4
|
+
// Extracted from queue-manager so the interactive-job session transport can
|
|
5
|
+
// render the SAME log lines QueueManager's one-shot spawn does, without a
|
|
6
|
+
// circular import between the two modules.
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.extractDisplayText = extractDisplayText;
|
|
9
|
+
/**
|
|
10
|
+
* Map a parsed provider stream-json frame to the single display line the Job
|
|
11
|
+
* Detail log shows (or null when the frame carries no user-facing text).
|
|
12
|
+
* Handles both Claude `--output-format stream-json` and Codex `exec --json`.
|
|
13
|
+
*/
|
|
14
|
+
function extractDisplayText(event) {
|
|
15
|
+
const type = event.type;
|
|
16
|
+
// ── Claude `--output-format stream-json` ───────────────────────────────
|
|
17
|
+
if (type === 'assistant') {
|
|
18
|
+
const content = event.message;
|
|
19
|
+
const texts = (content?.content ?? [])
|
|
20
|
+
.filter((c) => c.type === 'text')
|
|
21
|
+
.map((c) => c.text ?? '');
|
|
22
|
+
return texts.join('') || null;
|
|
23
|
+
}
|
|
24
|
+
if (type === 'tool_use') {
|
|
25
|
+
const name = event.name;
|
|
26
|
+
const input = JSON.stringify(event.input ?? {});
|
|
27
|
+
return `[tool: ${name}] ${input.slice(0, 120)}`;
|
|
28
|
+
}
|
|
29
|
+
if (type === 'tool_result' || type === 'system_prompt' || type === 'user' || type === 'system' || type === 'result') {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
// ── Codex `exec --json` event types ───────────────────────────────────
|
|
33
|
+
// Codex shape differs from claude: items are nested under `item` with a
|
|
34
|
+
// discriminator at `item.type`. Without explicit handling the Job Detail
|
|
35
|
+
// log shows only the spawn preamble and exit notice — exactly the
|
|
36
|
+
// "2 / 2 lines" symptom that masks 200k+ tokens of real work.
|
|
37
|
+
if (type === 'item.completed' || type === 'item.started') {
|
|
38
|
+
const item = event.item;
|
|
39
|
+
if (!item)
|
|
40
|
+
return null;
|
|
41
|
+
const itemType = item.type;
|
|
42
|
+
if (itemType === 'agent_message') {
|
|
43
|
+
const text = item.text?.trim();
|
|
44
|
+
return text && text.length > 0 ? text : null;
|
|
45
|
+
}
|
|
46
|
+
if (itemType === 'command_execution') {
|
|
47
|
+
// Only surface the completed line so the log isn't doubled with the
|
|
48
|
+
// matching `item.started` placeholder.
|
|
49
|
+
if (type !== 'item.completed')
|
|
50
|
+
return null;
|
|
51
|
+
const cmd = item.command ?? '';
|
|
52
|
+
const exitCode = item.exit_code;
|
|
53
|
+
const exitStr = typeof exitCode === 'number' ? ` → exit ${exitCode}` : '';
|
|
54
|
+
return `[exec]${exitStr} ${cmd.slice(0, 200)}`;
|
|
55
|
+
}
|
|
56
|
+
if (itemType === 'agent_reasoning') {
|
|
57
|
+
const text = item.text?.trim();
|
|
58
|
+
return text && text.length > 0 ? `[reasoning] ${text.slice(0, 200)}` : null;
|
|
59
|
+
}
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
if (type === 'thread.started' || type === 'turn.started' || type === 'turn.completed') {
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{r as e}from"./chunk-CilyBKbf.js";import{Ct as t,Jt as n,M as r,Mt as i,Nt as a,Pt as o,nn as s,ot as c,q as l,st as u,vt as d,xt as f,yt as p}from"./index-CGHKpC-N.js";var m=p(`ban`,[[`circle`,{cx:`12`,cy:`12`,r:`10`,key:`1mglay`}],[`path`,{d:`M4.929 4.929 19.07 19.071`,key:`196cmz`}]]),h=e(s(),1);function g(e){let t=new Set;return e.filter(e=>{let n=`${e.type}:${e.jobId}`;return t.has(n)?!1:(t.add(n),!0)})}function _({activeProjectId:e,limit:n=50}){let[r,a]=(0,h.useState)([]),[s,c]=(0,h.useState)(!1),[l,u]=(0,h.useState)(!0),d=(0,h.useRef)(e);(0,h.useEffect)(()=>{d.current=e},[e]);let{registerHandler:f,unregisterHandler:p}=i();(0,h.useEffect)(()=>{if(!e){a([]),u(!0);return}let t=!1;c(!0),a([]),u(!0);async function r(){let e=o();try{let r=await fetch(`${e}/activity?limit=${n}`);if(!r.ok||t)return;let i=await r.json();if(t)return;a(i),u(i.length===n)}catch{}finally{t||c(!1)}}return r(),()=>{t=!0}},[e,n]);let m=(0,h.useCallback)(async()=>{if(s||!l)return;c(!0);let e=o();try{a(t=>{let r=t[t.length-1];if(!r)return t;let i=encodeURIComponent(r.timestamp);return fetch(`${e}/activity?limit=${n}&before=${i}`).then(e=>e.json()).then(e=>{a(t=>g([...t,...e])),u(e.length===n),c(!1)}).catch(()=>c(!1)),t})}catch{c(!1)}},[s,l,n]),_=(0,h.useCallback)(e=>{let n=e,r=d.current;if(!(!n||typeof n.type!=`string`)&&!(n.projectId&&n.projectId!==r)){if(n.type===`queue`&&Array.isArray(n.jobs)){let e=[];for(let t of n.jobs){let n=t.status===`completed`?`job_completed`:t.status===`failed`?`job_failed`:t.status===`canceled`?`job_canceled`:`job_started`;e.push({id:`${n}:${t.id}`,type:n,jobId:t.id,jobCommand:t.command??``,timestamp:t.startedAt??new Date().toISOString(),summary:`${n.replace(`_`,` `)}: ${t.command??``}`,costUsd:null})}e.length>0&&a(t=>g([...e,...t]))}if(n.type===`phase`&&n.phase&&n.state&&n.timestamp){let e={id:`phase:${n.phase}:${n.state}:${n.timestamp}`,type:`job_started`,jobId:`phase-${n.phase}`,jobCommand:t.t(`activity:feed.phaseCommand`,{phase:n.phase,state:n.state}),timestamp:n.timestamp,summary:`Phase ${n.phase} is ${n.state}`,costUsd:null};a(t=>g([e,...t]))}}},[]);return(0,h.useLayoutEffect)(()=>(f(`activity`,_),()=>p(`activity`)),[_,f,p]),{items:r,loading:s,hasMore:l,loadMore:m}}var v=a();function y(e,t){let n=Date.now()-new Date(e).getTime(),r=Math.floor(n/1e3);if(r<60)return t(`feed.relativeTime.seconds`,{value:r});let i=Math.floor(r/60);if(i<60)return t(`feed.relativeTime.minutes`,{value:i});let a=Math.floor(i/60);return a<24?t(`feed.relativeTime.hours`,{value:a}):t(`feed.relativeTime.days`,{value:Math.floor(a/24)})}function b({type:e}){switch(e){case`job_completed`:return(0,v.jsx)(u,{className:`w-4 h-4 text-green-500 flex-shrink-0`});case`job_failed`:return(0,v.jsx)(c,{className:`w-4 h-4 text-red-500 flex-shrink-0`});case`job_canceled`:return(0,v.jsx)(m,{className:`w-4 h-4 text-muted-foreground flex-shrink-0`});default:return(0,v.jsx)(r,{className:`w-4 h-4 text-blue-500 flex-shrink-0`})}}function x(e,t){switch(e){case`job_completed`:return t(`common:status.completed`);case`job_failed`:return t(`common:status.failed`);case`job_canceled`:return t(`common:status.canceled`);default:return t(`feed.typeStarted`)}}function S(e){switch(e){case`job_completed`:return`text-green-500`;case`job_failed`:return`text-red-500`;case`job_canceled`:return`text-muted-foreground`;default:return`text-blue-500`}}function C(){let{t:e}=n(`activity`),{activeProjectId:t}=f(),{items:r,loading:i,hasMore:a,loadMore:o}=_({activeProjectId:t}),s=(0,h.useRef)(null);return(0,h.useEffect)(()=>{let e=s.current;if(!e)return;let t=new IntersectionObserver(e=>{e[0].isIntersecting&&a&&!i&&o()},{threshold:.1});return t.observe(e),()=>t.disconnect()},[a,i,o]),(0,v.jsxs)(`div`,{className:`flex flex-col h-full overflow-hidden`,children:[(0,v.jsxs)(`div`,{className:`flex items-center gap-2 px-4 py-3 border-b border-border bg-background/50`,children:[(0,v.jsx)(d,{className:`w-4 h-4 text-muted-foreground`}),(0,v.jsx)(`h1`,{className:`text-sm font-medium`,children:e(`feed.title`)})]}),(0,v.jsxs)(`div`,{className:`flex-1 overflow-y-auto`,children:[i&&r.length===0?(0,v.jsx)(`div`,{className:`flex items-center justify-center h-32`,children:(0,v.jsx)(l,{className:`w-4 h-4 animate-spin text-muted-foreground`})}):r.length===0?(0,v.jsxs)(`div`,{className:`flex flex-col items-center justify-center h-48 gap-2 text-muted-foreground`,children:[(0,v.jsx)(d,{className:`w-8 h-8 opacity-40`}),(0,v.jsx)(`p`,{className:`text-sm`,children:e(`feed.emptyTitle`)}),(0,v.jsx)(`p`,{className:`text-xs opacity-70`,children:e(`feed.emptyHint`)})]}):(0,v.jsx)(`ul`,{className:`divide-y divide-border/50`,children:r.map(t=>(0,v.jsxs)(`li`,{className:`flex items-center gap-3 px-4 py-2.5 hover:bg-accent/30 transition-colors`,children:[(0,v.jsx)(b,{type:t.type}),(0,v.jsxs)(`div`,{className:`flex-1 min-w-0`,children:[(0,v.jsx)(`p`,{className:`text-xs text-foreground truncate`,title:t.jobCommand,children:t.jobCommand}),(0,v.jsxs)(`div`,{className:`flex items-center gap-2 mt-0.5`,children:[(0,v.jsx)(`span`,{className:`text-xs font-medium ${S(t.type)}`,children:x(t.type,e)}),t.costUsd!=null&&(0,v.jsxs)(`span`,{className:`text-xs text-muted-foreground`,children:[`$`,t.costUsd.toFixed(4)]})]})]}),(0,v.jsx)(`span`,{className:`text-xs text-muted-foreground flex-shrink-0 tabular-nums`,children:y(t.timestamp,e)})]},`${t.type}:${t.jobId}`))}),(0,v.jsx)(`div`,{ref:s,className:`h-1`}),i&&r.length>0&&(0,v.jsx)(`div`,{className:`flex justify-center py-3`,children:(0,v.jsx)(l,{className:`w-4 h-4 animate-spin text-muted-foreground`})}),!a&&r.length>0&&(0,v.jsx)(`p`,{className:`text-center text-xs text-muted-foreground py-3`,children:e(`feed.allLoaded`)})]})]})}export{C as default};
|