@band-app/server 0.16.9 → 0.17.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/dist/client/assets/DockviewBrowserContainer-B_oEene2.js +5 -0
- package/dist/client/assets/DockviewTerminalContainer-CfQMvR_k.js +2 -0
- package/dist/client/assets/TerminalPanel-DxZK0ClB.js +5 -0
- package/dist/client/assets/{_basePickBy-uVqvgsJc.js → _basePickBy-Ct-e0Qqq.js} +1 -1
- package/dist/client/assets/{_baseUniq-7i7L1uNE.js → _baseUniq-CxKOXF1k.js} +1 -1
- package/dist/client/assets/arc-CKSDLbJ_.js +1 -0
- package/dist/client/assets/architectureDiagram-VXUJARFQ-DX7YfptV.js +36 -0
- package/dist/client/assets/{blockDiagram-VD42YOAC-CXQSSz3O.js → blockDiagram-VD42YOAC-CsuIx-c9.js} +5 -5
- package/dist/client/assets/{c4Diagram-YG6GDRKO-DplRXCR2.js → c4Diagram-YG6GDRKO-DychwT1W.js} +3 -3
- package/dist/client/assets/channel-B-u6m7I1.js +1 -0
- package/dist/client/assets/chunk-4BX2VUAB-loz8MPPD.js +1 -0
- package/dist/client/assets/chunk-55IACEB6-D29ChrqC.js +1 -0
- package/dist/client/assets/{chunk-B4BG7PRW-DlN9tUxh.js → chunk-B4BG7PRW-DKCONMEK.js} +6 -6
- package/dist/client/assets/{chunk-DI55MBZ5-a11zyhq4.js → chunk-DI55MBZ5-D5zzjeE8.js} +1 -1
- package/dist/client/assets/{chunk-FMBD7UC4-aGGVV1yn.js → chunk-FMBD7UC4-D1xESdhD.js} +1 -1
- package/dist/client/assets/chunk-QN33PNHL-DXisPMUT.js +1 -0
- package/dist/client/assets/chunk-QZHKN3VN-Ch8ZVx4Y.js +1 -0
- package/dist/client/assets/chunk-TZMSLE5B-GuM5n4Rs.js +1 -0
- package/dist/client/assets/classDiagram-2ON5EDUG-ZLOOfEOW.js +1 -0
- package/dist/client/assets/classDiagram-v2-WZHVMYZB-ZLOOfEOW.js +1 -0
- package/dist/client/assets/clone-CDLv4lRU.js +1 -0
- package/dist/client/assets/cose-bilkent-S5V4N54A-Cf0f3nH9.js +1 -0
- package/dist/client/assets/dagre-6UL2VRFP-BEjucV14.js +4 -0
- package/dist/client/assets/diagram-PSM6KHXK-4UTMLb3J.js +24 -0
- package/dist/client/assets/diagram-QEK2KX5R-B9rhi9zE.js +43 -0
- package/dist/client/assets/diagram-S2PKOQOG-CS7F4WJO.js +24 -0
- package/dist/client/assets/{erDiagram-Q2GNP2WA-kUd-gmjz.js → erDiagram-Q2GNP2WA-D-EqIR9o.js} +4 -4
- package/dist/client/assets/{flowDiagram-NV44I4VS-CHbLqCKB.js → flowDiagram-NV44I4VS-_GH1A_sS.js} +5 -5
- package/dist/client/assets/ganttDiagram-JELNMOA3-Dtb6N1ze.js +267 -0
- package/dist/client/assets/gitGraphDiagram-V2S2FVAM-B_QsP5ak.js +65 -0
- package/dist/client/assets/{graph-CSi_akmB.js → graph-H6OCDpse.js} +1 -1
- package/dist/client/assets/highlighted-body-B3W2YXNL-Pz2rshlt.js +1 -0
- package/dist/client/assets/index-B-KsZlI_.js +1 -0
- package/dist/client/assets/{index-udv0M-ix.js → index-BCbe81ki.js} +2 -2
- package/dist/client/assets/index-BOdifnXB.js +1 -0
- package/dist/client/assets/{index-BPf6S9f1.js → index-BQW7Zpk7.js} +1 -1
- package/dist/client/assets/index-BX_7-t5E.js +1 -0
- package/dist/client/assets/{index-B0ZcEU4c.js → index-BktK8Iwc.js} +1 -1
- package/dist/client/assets/{index-C-6dsPog.js → index-BtEs1oEp.js} +1 -1
- package/dist/client/assets/{index-T_1b5WRg.js → index-BtajlvkF.js} +1 -1
- package/dist/client/assets/{index-CNQHGhCu.js → index-Bx3rRbZG.js} +1 -1
- package/dist/client/assets/{index-DfHcm4JM.js → index-C6MgAn1q.js} +1 -1
- package/dist/client/assets/{index-C4ee_PQ0.js → index-CzCjpAqZ.js} +5 -5
- package/dist/client/assets/{index-oolizINO.js → index-DQAckahj.js} +1 -1
- package/dist/client/assets/index-DaRnNd02.js +7 -0
- package/dist/client/assets/{index-BJP1qdPz.js → index-Im7rGMYn.js} +1 -1
- package/dist/client/assets/{index-CA1NuCd_.js → index-WmGuuT8Z.js} +1 -1
- package/dist/client/assets/{index-C-3PAt1d.js → index-aTt3zXBv.js} +1 -1
- package/dist/client/assets/{index-5X7JRvnK.js → index-nPplcWzt.js} +1 -1
- package/dist/client/assets/{index-spwNnd85.js → index-vaGaAlmP.js} +1 -1
- package/dist/client/assets/infoDiagram-HS3SLOUP-Dp2iuUeA.js +2 -0
- package/dist/client/assets/{journeyDiagram-XKPGCS4Q-DIY8FE8Z.js → journeyDiagram-XKPGCS4Q-BaVzrE3V.js} +3 -3
- package/dist/client/assets/{kanban-definition-3W4ZIXB7-Cd_JJ8FN.js → kanban-definition-3W4ZIXB7-DdbWsnm7.js} +8 -8
- package/dist/client/assets/{layout-Bhb5FQCr.js → layout-vxWf40Ht.js} +1 -1
- package/dist/client/assets/{linear-Cmk2RyH_.js → linear-BstrgKy8.js} +1 -1
- package/dist/client/assets/{main-BlRcPsmZ.js → main-DRq9Axai.js} +227 -226
- package/dist/client/assets/main-evBJruhw.css +1 -0
- package/dist/client/assets/{mindmap-definition-VGOIOE7T-B-WhBVeY.js → mindmap-definition-VGOIOE7T-CAEEMYhK.js} +3 -3
- package/dist/client/assets/pieDiagram-ADFJNKIX-DCNv4UlO.js +30 -0
- package/dist/client/assets/{quadrantDiagram-AYHSOK5B-DHBoMUCQ.js → quadrantDiagram-AYHSOK5B-BeP4t0hp.js} +2 -2
- package/dist/client/assets/{requirementDiagram-UZGBJVZJ-DjS5RONh.js → requirementDiagram-UZGBJVZJ-CAdiLb_M.js} +2 -2
- package/dist/client/assets/sankeyDiagram-TZEHDZUN-DW9xKT5Y.js +10 -0
- package/dist/client/assets/{sequenceDiagram-WL72ISMW-CzqbRfb_.js → sequenceDiagram-WL72ISMW-D9y8fK_R.js} +1 -1
- package/dist/client/assets/{square-terminal-CNHJa6OY.js → square-terminal-VjG9-RoZ.js} +1 -1
- package/dist/client/assets/stateDiagram-FKZM4ZOC-QYuyBeVm.js +1 -0
- package/dist/client/assets/stateDiagram-v2-4FDKWEC3-VVONI0Hb.js +1 -0
- package/dist/client/assets/{timeline-definition-IT6M3QCI-CNKMKDwq.js → timeline-definition-IT6M3QCI-Ci_SXZdO.js} +4 -4
- package/dist/client/assets/{treemap-GDKQZRPO-DCEPrZh7.js → treemap-GDKQZRPO-fDacl-jS.js} +1 -1
- package/dist/client/assets/workspace._workspaceId-C9BVWo6-.js +2 -0
- package/dist/client/assets/workspace._workspaceId-CMlw9wn8.js +1 -0
- package/dist/client/assets/{xychartDiagram-PRI3JC2R-Cr18I3A3.js → xychartDiagram-PRI3JC2R-rRpBADcB.js} +4 -4
- package/dist/migrations/20260525163504_add_projects_has_origin/migration.sql +1 -0
- package/dist/migrations/20260525163504_add_projects_has_origin/snapshot.json +866 -0
- package/dist/openapi.json +414 -4
- package/dist/server/assets/{DockviewBrowserContainer-Bm7ARaqd.js → DockviewBrowserContainer-BAe7TLKD.js} +42 -22
- package/dist/server/assets/{DockviewTerminalContainer-BbMZgBJ8.js → DockviewTerminalContainer-CC7i0yMZ.js} +44 -24
- package/dist/server/assets/{TerminalPanel-BmhYCf33.js → TerminalPanel-gBh8VBn0.js} +1 -1
- package/dist/server/assets/{_basePickBy-C7CNOUDi.js → _basePickBy-CTks6QXq.js} +2 -2
- package/dist/server/assets/{_baseUniq-DeF47vVO.js → _baseUniq-BJI4qneQ.js} +1 -1
- package/dist/server/assets/_tanstack-start-manifest_v-CfuSyuIp.js +4 -0
- package/dist/server/assets/{arc-P5FY7IYH.js → arc-Fdc_l0PB.js} +1 -1
- package/dist/server/assets/{architecture-7HQA4BMR-LvprLHYS.js → architecture-7HQA4BMR-CfPXboDr.js} +6 -6
- package/dist/server/assets/{architectureDiagram-VXUJARFQ-Br4iiUzH.js → architectureDiagram-VXUJARFQ-D6UEkzy_.js} +6 -6
- package/dist/server/assets/{blockDiagram-VD42YOAC-BahODDhX.js → blockDiagram-VD42YOAC-BvasIENt.js} +6 -6
- package/dist/server/assets/{c4Diagram-YG6GDRKO-CQcZX6cr.js → c4Diagram-YG6GDRKO-MW5H9zoJ.js} +2 -2
- package/dist/server/assets/{channel-BmAB_ZKU.js → channel-XhTiPor2.js} +1 -1
- package/dist/server/assets/{chunk-4BX2VUAB-YUvszr4w.js → chunk-4BX2VUAB-C6POw9HJ.js} +1 -1
- package/dist/server/assets/{chunk-55IACEB6-BUgBPiJd.js → chunk-55IACEB6-BZ0x-UQb.js} +1 -1
- package/dist/server/assets/{chunk-B4BG7PRW-BxuWeZlV.js → chunk-B4BG7PRW-BAYqNQHL.js} +4 -4
- package/dist/server/assets/{chunk-DI55MBZ5-DuGkdvte.js → chunk-DI55MBZ5-DbsR50vR.js} +3 -3
- package/dist/server/assets/{chunk-FMBD7UC4-qY-BVG34.js → chunk-FMBD7UC4-D_KXTL87.js} +1 -1
- package/dist/server/assets/{chunk-QN33PNHL-BM_oi8-e.js → chunk-QN33PNHL-RXXHu7T0.js} +1 -1
- package/dist/server/assets/{chunk-QZHKN3VN-BL6_-at8.js → chunk-QZHKN3VN-5QE6weTd.js} +1 -1
- package/dist/server/assets/{chunk-TZMSLE5B-38NhX5at.js → chunk-TZMSLE5B-HlRXkCDZ.js} +1 -1
- package/dist/server/assets/{classDiagram-v2-WZHVMYZB-CwIsZ53p.js → classDiagram-2ON5EDUG-B90fR_EV.js} +5 -5
- package/dist/server/assets/{classDiagram-2ON5EDUG-CwIsZ53p.js → classDiagram-v2-WZHVMYZB-B90fR_EV.js} +5 -5
- package/dist/server/assets/{clone-BXHuGM8i.js → clone-Bjcb6OQr.js} +1 -1
- package/dist/server/assets/{cose-bilkent-S5V4N54A-D1CdgGvI.js → cose-bilkent-S5V4N54A-BgnWrjAl.js} +1 -1
- package/dist/server/assets/{dagre-6UL2VRFP-UMvdMLG3.js → dagre-6UL2VRFP-LfRXD26Q.js} +6 -6
- package/dist/server/assets/{diagram-PSM6KHXK-DtOD93m7.js → diagram-PSM6KHXK-DLrJ9Eja.js} +7 -7
- package/dist/server/assets/{diagram-QEK2KX5R-DViyYq-y.js → diagram-QEK2KX5R-atbHIh96.js} +6 -6
- package/dist/server/assets/{diagram-S2PKOQOG-C42mRVEn.js → diagram-S2PKOQOG-BnxctnIJ.js} +6 -6
- package/dist/server/assets/{erDiagram-Q2GNP2WA-D14z9IvB.js → erDiagram-Q2GNP2WA-Ct1zXovC.js} +4 -4
- package/dist/server/assets/{flowDiagram-NV44I4VS-BYBNOZwM.js → flowDiagram-NV44I4VS-DtWHb6Ay.js} +5 -5
- package/dist/server/assets/{ganttDiagram-JELNMOA3-CaG3uoK-.js → ganttDiagram-JELNMOA3-CySyldy4.js} +2 -2
- package/dist/server/assets/{gitGraph-G5XIXVHT-Dsx3dV0R.js → gitGraph-G5XIXVHT-DFo7FJzL.js} +6 -6
- package/dist/server/assets/{gitGraphDiagram-V2S2FVAM-CrSfx7b3.js → gitGraphDiagram-V2S2FVAM-DvT5EUG7.js} +7 -7
- package/dist/server/assets/{graph-gBFInK6H.js → graph-B5XlkLf_.js} +2 -2
- package/dist/server/assets/{highlighted-body-B3W2YXNL-DjTWk17l.js → highlighted-body-B3W2YXNL-CLJWhRU_.js} +1 -1
- package/dist/server/assets/{index-C3N_Nx6h.js → index--4MijjkY.js} +2 -2
- package/dist/server/assets/{index-C245EJn1.js → index-4SOjxyuO.js} +2 -2
- package/dist/server/assets/{index-3wtbr7va.js → index-BQ5LDgRA.js} +3 -3
- package/dist/server/assets/{index-CD97pPmc.js → index-BanzNq86.js} +1 -1
- package/dist/server/assets/{index-2gWBdIrR.js → index-BvJzvUfR.js} +2 -2
- package/dist/server/assets/{index-B84Urg23.js → index-C2GzB22l.js} +2 -2
- package/dist/server/assets/{index-QxgXX0fb.js → index-CAJcSCqE.js} +2 -2
- package/dist/server/assets/{index-Bs6a6-xI.js → index-CLUle2oh.js} +5 -5
- package/dist/server/assets/{index-5N2Gh0ba.js → index-CMO4FLK_.js} +2 -2
- package/dist/server/assets/{index-6Zof9vm8.js → index-CXMNOcuN.js} +1 -1
- package/dist/server/assets/{index-Dv-16VYI.js → index-CXmMBSCL.js} +2 -2
- package/dist/server/assets/{index-DXgP0Lsu.js → index-CdgmRfZg.js} +2 -2
- package/dist/server/assets/{index-CwQ5qWPC.js → index-DJ8A5E65.js} +5 -5
- package/dist/server/assets/{index-DZZ6NiTf.js → index-DjySh3G7.js} +3 -3
- package/dist/server/assets/{index-Bd5jTryJ.js → index-DuXjusjn.js} +2 -2
- package/dist/server/assets/{index-DsGPaWHg.js → index-QiPzMfSX.js} +2 -2
- package/dist/server/assets/{index-Bw42FDwO.js → index-SuLB6TaE.js} +2 -2
- package/dist/server/assets/{index-egmIrLx2.js → index-bmq-aMYV.js} +4 -4
- package/dist/server/assets/{info-VBDWY6EO-CueOsYFZ.js → info-VBDWY6EO-CW57QiJi.js} +6 -6
- package/dist/server/assets/{infoDiagram-HS3SLOUP-CeyMzohL.js → infoDiagram-HS3SLOUP-D_Zdx-MM.js} +5 -5
- package/dist/server/assets/{journeyDiagram-XKPGCS4Q-ANqeM_TM.js → journeyDiagram-XKPGCS4Q-BcO9qzr2.js} +4 -4
- package/dist/server/assets/{kanban-definition-3W4ZIXB7-B0RkH45q.js → kanban-definition-3W4ZIXB7-BatZ7RKG.js} +2 -2
- package/dist/server/assets/{layout-JjP5jdu6.js → layout-Cwuj9CwZ.js} +4 -4
- package/dist/server/assets/{linear-BJgoq5J4.js → linear-CP3xC85V.js} +1 -1
- package/dist/server/assets/{mermaid-3ZIDBTTL-CFPuUseQ.js → mermaid-3ZIDBTTL-BZm8jQDo.js} +1 -1
- package/dist/server/assets/{mermaid-parser.core-CKKZ1VFr.js → mermaid-parser.core-Cx17C8XR.js} +11 -11
- package/dist/server/assets/{mindmap-definition-VGOIOE7T-DlEXF5z8.js → mindmap-definition-VGOIOE7T-CpzqFomk.js} +3 -3
- package/dist/server/assets/{packet-DYOGHKS2-CvyxHTRM.js → packet-DYOGHKS2-x3ihoqUO.js} +6 -6
- package/dist/server/assets/{pie-VRWISCQL-DfpVZlpC.js → pie-VRWISCQL-DsMBDe8r.js} +6 -6
- package/dist/server/assets/{pieDiagram-ADFJNKIX-CWkrHsNk.js → pieDiagram-ADFJNKIX-DI4Hh6KE.js} +7 -7
- package/dist/server/assets/{quadrantDiagram-AYHSOK5B-C25p2xz7.js → quadrantDiagram-AYHSOK5B-Cqc_vrUG.js} +2 -2
- package/dist/server/assets/{radar-ZZBFDIW7-DWqPsDMi.js → radar-ZZBFDIW7-CqwCJm3D.js} +6 -6
- package/dist/server/assets/{requirementDiagram-UZGBJVZJ-ACRVXQGO.js → requirementDiagram-UZGBJVZJ-96ab-40P.js} +3 -3
- package/dist/server/assets/{router-GhGSLKfP.js → router-CYNdQEN4.js} +1116 -579
- package/dist/server/assets/{sankeyDiagram-TZEHDZUN-uzNSHudY.js → sankeyDiagram-TZEHDZUN-Bux2-BQd.js} +1 -1
- package/dist/server/assets/{sequenceDiagram-WL72ISMW-C_wFtq8b.js → sequenceDiagram-WL72ISMW-CFKyfvmC.js} +3 -3
- package/dist/server/assets/{square-terminal-cghvb5Il.js → square-terminal-gVSeBp7-.js} +1 -1
- package/dist/server/assets/{stateDiagram-FKZM4ZOC-B9MGwsuS.js → stateDiagram-FKZM4ZOC-DGZQd18J.js} +8 -8
- package/dist/server/assets/{stateDiagram-v2-4FDKWEC3-CLHd8oUa.js → stateDiagram-v2-4FDKWEC3-DJXeLDOB.js} +4 -4
- package/dist/server/assets/{timeline-definition-IT6M3QCI-CqKot5RT.js → timeline-definition-IT6M3QCI-DzTJZPN5.js} +2 -2
- package/dist/server/assets/{treemap-GDKQZRPO-mMRojqRQ.js → treemap-GDKQZRPO-CD9jkQrA.js} +6 -6
- package/dist/server/assets/workspace._workspaceId-ClAAZ5aq.js +23 -0
- package/dist/server/assets/{workspace._workspaceId-DwsRTXCg.js → workspace._workspaceId-DT6Kz8RH.js} +125 -97
- package/dist/server/assets/{xychartDiagram-PRI3JC2R-j8PckQEj.js → xychartDiagram-PRI3JC2R-ByA0_p8p.js} +2 -2
- package/dist/server/server.js +2 -2
- package/dist/start-server.mjs +489 -242
- package/package.json +4 -4
- package/dist/client/assets/DockviewBrowserContainer-CCBAkU1p.js +0 -5
- package/dist/client/assets/DockviewTerminalContainer-B9hdDoMz.js +0 -2
- package/dist/client/assets/TerminalPanel-BKfWmj6W.js +0 -5
- package/dist/client/assets/arc-DiYEQGs3.js +0 -1
- package/dist/client/assets/architectureDiagram-VXUJARFQ-C5z8L1iK.js +0 -36
- package/dist/client/assets/channel-BnMJuhcI.js +0 -1
- package/dist/client/assets/chunk-4BX2VUAB-B4Mk_d7A.js +0 -1
- package/dist/client/assets/chunk-55IACEB6-B0hf8Eje.js +0 -1
- package/dist/client/assets/chunk-QN33PNHL-Dit4S-yJ.js +0 -1
- package/dist/client/assets/chunk-QZHKN3VN-L-h1VSi0.js +0 -1
- package/dist/client/assets/chunk-TZMSLE5B-DpK-hWaC.js +0 -1
- package/dist/client/assets/classDiagram-2ON5EDUG-D89oCSXI.js +0 -1
- package/dist/client/assets/classDiagram-v2-WZHVMYZB-D89oCSXI.js +0 -1
- package/dist/client/assets/clone-X7FA7kE2.js +0 -1
- package/dist/client/assets/cose-bilkent-S5V4N54A-CzoIK-3W.js +0 -1
- package/dist/client/assets/dagre-6UL2VRFP-BhfXeb7k.js +0 -4
- package/dist/client/assets/diagram-PSM6KHXK-BwFVwR1b.js +0 -24
- package/dist/client/assets/diagram-QEK2KX5R-BO-CEopy.js +0 -43
- package/dist/client/assets/diagram-S2PKOQOG-BxiH83lN.js +0 -24
- package/dist/client/assets/ganttDiagram-JELNMOA3-B7gBcAFl.js +0 -267
- package/dist/client/assets/gitGraphDiagram-V2S2FVAM-gca_jqKQ.js +0 -65
- package/dist/client/assets/highlighted-body-B3W2YXNL-C2a-lsk8.js +0 -1
- package/dist/client/assets/index-2F-slvqo.js +0 -1
- package/dist/client/assets/index-C4PISrIW.js +0 -1
- package/dist/client/assets/index-CiKTedrx.js +0 -1
- package/dist/client/assets/index-DNrK0iIn.js +0 -7
- package/dist/client/assets/infoDiagram-HS3SLOUP-BK3MmhkJ.js +0 -2
- package/dist/client/assets/main-BLOY6Nam.css +0 -1
- package/dist/client/assets/pieDiagram-ADFJNKIX-CYoHsaM9.js +0 -30
- package/dist/client/assets/sankeyDiagram-TZEHDZUN-DmhEbBY-.js +0 -10
- package/dist/client/assets/stateDiagram-FKZM4ZOC-CafvdTb3.js +0 -1
- package/dist/client/assets/stateDiagram-v2-4FDKWEC3-BkKHK-CQ.js +0 -1
- package/dist/client/assets/useSessionListContext-xer-Wcmf.js +0 -1
- package/dist/client/assets/workspace._workspaceId-CgG1n_1x.js +0 -1
- package/dist/client/assets/workspace._workspaceId.changes-BKX7lUhX.js +0 -1
- package/dist/client/assets/workspace._workspaceId.code-BcnxRdZi.js +0 -1
- package/dist/client/assets/workspace._workspaceId.code._-BbOt6tOD.js +0 -1
- package/dist/client/assets/workspace._workspaceId.code.index-DC2535x-.js +0 -1
- package/dist/client/assets/workspace._workspaceId.index-CNjq1nDf.js +0 -1
- package/dist/client/assets/workspace._workspaceId.terminal-DhYn8I5t.js +0 -2
- package/dist/server/assets/_tanstack-start-manifest_v-BNCQ-izx.js +0 -4
- package/dist/server/assets/useSessionListContext-D_vX6E2e.js +0 -23
- package/dist/server/assets/workspace._workspaceId.changes-C6vwSbUh.js +0 -38
- package/dist/server/assets/workspace._workspaceId.code-Cuj0zH98.js +0 -12
- package/dist/server/assets/workspace._workspaceId.code._-BJdg1-Gs.js +0 -44
- package/dist/server/assets/workspace._workspaceId.code.index-CE_CMD_I.js +0 -36
- package/dist/server/assets/workspace._workspaceId.index-BPhXMwl8.js +0 -112
- package/dist/server/assets/workspace._workspaceId.terminal-BdVDaWNH.js +0 -24
package/dist/start-server.mjs
CHANGED
|
@@ -6501,11 +6501,11 @@ var require_tools = __commonJS({
|
|
|
6501
6501
|
}
|
|
6502
6502
|
}
|
|
6503
6503
|
}
|
|
6504
|
-
function buildFormatters(level, bindings,
|
|
6504
|
+
function buildFormatters(level, bindings, log31) {
|
|
6505
6505
|
return {
|
|
6506
6506
|
level,
|
|
6507
6507
|
bindings,
|
|
6508
|
-
log:
|
|
6508
|
+
log: log31
|
|
6509
6509
|
};
|
|
6510
6510
|
}
|
|
6511
6511
|
function normalizeDestFileDescriptor(destination) {
|
|
@@ -6888,11 +6888,11 @@ var require_proto = __commonJS({
|
|
|
6888
6888
|
}
|
|
6889
6889
|
} else instance[serializersSym] = serializers;
|
|
6890
6890
|
if (options2.hasOwnProperty("formatters")) {
|
|
6891
|
-
const { level, bindings: chindings, log:
|
|
6891
|
+
const { level, bindings: chindings, log: log31 } = options2.formatters;
|
|
6892
6892
|
instance[formattersSym] = buildFormatters(
|
|
6893
6893
|
level || formatters.level,
|
|
6894
6894
|
chindings || resetChildingsFormatter,
|
|
6895
|
-
|
|
6895
|
+
log31 || formatters.log
|
|
6896
6896
|
);
|
|
6897
6897
|
} else {
|
|
6898
6898
|
instance[formattersSym] = buildFormatters(
|
|
@@ -86574,11 +86574,11 @@ var require_core = __commonJS({
|
|
|
86574
86574
|
Ajv2.ValidationError = validation_error_1.default;
|
|
86575
86575
|
Ajv2.MissingRefError = ref_error_1.default;
|
|
86576
86576
|
exports.default = Ajv2;
|
|
86577
|
-
function checkOptions(checkOpts, options2, msg,
|
|
86577
|
+
function checkOptions(checkOpts, options2, msg, log31 = "error") {
|
|
86578
86578
|
for (const key in checkOpts) {
|
|
86579
86579
|
const opt = key;
|
|
86580
86580
|
if (opt in options2)
|
|
86581
|
-
this.logger[
|
|
86581
|
+
this.logger[log31](`${msg}: option ${key}. ${checkOpts[opt]}`);
|
|
86582
86582
|
}
|
|
86583
86583
|
}
|
|
86584
86584
|
function getSchEnv(keyRef) {
|
|
@@ -106688,6 +106688,9 @@ var import_react15 = __toESM(require_react(), 1);
|
|
|
106688
106688
|
// src/dashboard/hooks/use-label-filter.ts
|
|
106689
106689
|
var import_react16 = __toESM(require_react(), 1);
|
|
106690
106690
|
|
|
106691
|
+
// src/dashboard/hooks/use-projects.ts
|
|
106692
|
+
var EMPTY_PROJECTS = Object.freeze([]);
|
|
106693
|
+
|
|
106691
106694
|
// src/dashboard/hooks/use-status.ts
|
|
106692
106695
|
var import_react17 = __toESM(require_react(), 1);
|
|
106693
106696
|
|
|
@@ -106849,6 +106852,11 @@ var WorkspaceCard = (0, import_react20.memo)(function WorkspaceCard2({
|
|
|
106849
106852
|
// "currently-active link in a list of related links".
|
|
106850
106853
|
"data-active": isActive || void 0,
|
|
106851
106854
|
"aria-current": isActive ? "page" : void 0,
|
|
106855
|
+
// Stable test hook keyed by workspaceId so integration tests can right-
|
|
106856
|
+
// click the specific card (issue #508). Branches with `/` in them are
|
|
106857
|
+
// collapsed to `-` by `toWorkspaceId` so the attribute value matches
|
|
106858
|
+
// the canonical workspace id used everywhere else in the UI.
|
|
106859
|
+
"data-testid": `project-list__workspace-card--${workspaceId}`,
|
|
106852
106860
|
onClick: (e2) => {
|
|
106853
106861
|
e2.stopPropagation();
|
|
106854
106862
|
handleClick();
|
|
@@ -116453,7 +116461,15 @@ var projects = sqliteTable("projects", {
|
|
|
116453
116461
|
// branches, PR/CI features) and plain folders (single implicit workspace,
|
|
116454
116462
|
// no isolation, git features disabled). Defaults to "git" so existing
|
|
116455
116463
|
// rows keep their behavior unchanged after migration.
|
|
116456
|
-
kind: text2("kind", { enum: ["git", "plain"] }).notNull().default("git")
|
|
116464
|
+
kind: text2("kind", { enum: ["git", "plain"] }).notNull().default("git"),
|
|
116465
|
+
// Whether the project's git repo has an `origin` remote we can use for
|
|
116466
|
+
// CI / PR queries. Populated by `syncWorktrees` (see `sync-state.ts`) at
|
|
116467
|
+
// the CI tick cadence — `null` means "not yet probed" and is treated as
|
|
116468
|
+
// `true` (best-effort) so the first poll after a fresh boot still issues
|
|
116469
|
+
// the CI query before sync has had a chance to write the real value.
|
|
116470
|
+
// Defaults to 1 (true) so existing rows behave the same after migration.
|
|
116471
|
+
// See issue #458.
|
|
116472
|
+
hasOrigin: integer2("has_origin", { mode: "boolean" }).notNull().default(true)
|
|
116457
116473
|
});
|
|
116458
116474
|
var worktrees = sqliteTable("worktrees", {
|
|
116459
116475
|
id: integer2("id").primaryKey({ autoIncrement: true }),
|
|
@@ -116589,10 +116605,15 @@ function loadState() {
|
|
|
116589
116605
|
defaultBranch: row.defaultBranch,
|
|
116590
116606
|
label: row.label ?? void 0,
|
|
116591
116607
|
kind: row.kind ?? "git",
|
|
116608
|
+
hasOrigin: row.hasOrigin,
|
|
116592
116609
|
worktrees: wtByProject.get(row.name) ?? []
|
|
116593
116610
|
}))
|
|
116594
116611
|
};
|
|
116595
116612
|
}
|
|
116613
|
+
function setProjectHasOrigin(name3, hasOrigin) {
|
|
116614
|
+
const db2 = getDb();
|
|
116615
|
+
db2.update(projects).set({ hasOrigin }).where(eq2(projects.name, name3)).run();
|
|
116616
|
+
}
|
|
116596
116617
|
function saveState(state2) {
|
|
116597
116618
|
const db2 = getDb();
|
|
116598
116619
|
db2.transaction((tx) => {
|
|
@@ -116606,7 +116627,11 @@ function saveState(state2) {
|
|
|
116606
116627
|
defaultBranch: project.defaultBranch,
|
|
116607
116628
|
label: project.label ?? null,
|
|
116608
116629
|
sortOrder: i2,
|
|
116609
|
-
kind: project.kind
|
|
116630
|
+
kind: project.kind,
|
|
116631
|
+
// Default to true for any caller that hasn't probed yet (e.g.
|
|
116632
|
+
// `projects.add` creating a brand-new row before the first
|
|
116633
|
+
// sync tick has run). The real value lands at the next sync.
|
|
116634
|
+
hasOrigin: project.hasOrigin ?? true
|
|
116610
116635
|
}).run();
|
|
116611
116636
|
for (const wt of project.worktrees) {
|
|
116612
116637
|
tx.insert(worktrees).values({
|
|
@@ -116870,9 +116895,9 @@ async function getOrCreateAgent(chatId, worktreePath, agentId) {
|
|
|
116870
116895
|
return existing.agent;
|
|
116871
116896
|
}
|
|
116872
116897
|
const defId = resolveAgentDefId(agentId);
|
|
116873
|
-
const
|
|
116874
|
-
if (
|
|
116875
|
-
return
|
|
116898
|
+
const inFlight2 = pending.get(chatId);
|
|
116899
|
+
if (inFlight2 && inFlight2.agentDefId === defId) {
|
|
116900
|
+
return inFlight2.promise;
|
|
116876
116901
|
}
|
|
116877
116902
|
const config2 = getAgentConfig(worktreePath, agentId);
|
|
116878
116903
|
log8.info({ chatId, type: config2.type, defId, cwd: worktreePath }, "creating agent");
|
|
@@ -117166,15 +117191,30 @@ function removeChatFromLayout(workspaceId, chatId) {
|
|
|
117166
117191
|
manager.removePanel(workspaceId, chatId);
|
|
117167
117192
|
}
|
|
117168
117193
|
|
|
117194
|
+
// src/lib/branch-status-poller.ts
|
|
117195
|
+
init_src();
|
|
117196
|
+
|
|
117169
117197
|
// src/lib/git.ts
|
|
117198
|
+
init_src();
|
|
117170
117199
|
import { execFile as execFile2 } from "node:child_process";
|
|
117171
117200
|
import { readFile, stat as stat3 } from "node:fs/promises";
|
|
117172
117201
|
import { join as join13 } from "node:path";
|
|
117202
|
+
var log9 = createLogger("git");
|
|
117173
117203
|
function parseGitRemoteUrl(url) {
|
|
117174
117204
|
const sshMatch = url.match(/^[\w.-]+@([^:]+):([^/]+)\/(.+?)(?:\.git)?$/);
|
|
117175
117205
|
if (sshMatch) {
|
|
117176
117206
|
return { host: sshMatch[1], owner: sshMatch[2], repo: sshMatch[3] };
|
|
117177
117207
|
}
|
|
117208
|
+
const sshSchemeMatch = url.match(
|
|
117209
|
+
/^ssh:\/\/(?:[\w.-]+@)?([^/:]+)(?::\d+)?\/([^/]+)\/(.+?)(?:\.git)?$/
|
|
117210
|
+
);
|
|
117211
|
+
if (sshSchemeMatch) {
|
|
117212
|
+
return {
|
|
117213
|
+
host: sshSchemeMatch[1],
|
|
117214
|
+
owner: sshSchemeMatch[2],
|
|
117215
|
+
repo: sshSchemeMatch[3]
|
|
117216
|
+
};
|
|
117217
|
+
}
|
|
117178
117218
|
const httpsMatch = url.match(/^https?:\/\/([^/]+)\/([^/]+)\/(.+?)(?:\.git)?$/);
|
|
117179
117219
|
if (httpsMatch) {
|
|
117180
117220
|
return { host: httpsMatch[1], owner: httpsMatch[2], repo: httpsMatch[3] };
|
|
@@ -117186,13 +117226,14 @@ async function getRepoInfo(worktreePath) {
|
|
|
117186
117226
|
const remoteUrl = (await execGit(["remote", "get-url", "origin"], worktreePath)).trim();
|
|
117187
117227
|
const parsed = parseGitRemoteUrl(remoteUrl);
|
|
117188
117228
|
if (!parsed) {
|
|
117189
|
-
|
|
117229
|
+
log9.debug('getRepoInfo: failed to parse remote URL "%s" for %s', remoteUrl, worktreePath);
|
|
117190
117230
|
}
|
|
117191
117231
|
return parsed;
|
|
117192
117232
|
} catch (err) {
|
|
117193
|
-
|
|
117194
|
-
|
|
117195
|
-
|
|
117233
|
+
log9.debug(
|
|
117234
|
+
"getRepoInfo: failed for %s: %s",
|
|
117235
|
+
worktreePath,
|
|
117236
|
+
err instanceof Error ? err.message : String(err)
|
|
117196
117237
|
);
|
|
117197
117238
|
return null;
|
|
117198
117239
|
}
|
|
@@ -117479,6 +117520,10 @@ async function reconcileOneProject(project) {
|
|
|
117479
117520
|
pinned: pinnedByBranch.get(wt.branch) ?? false
|
|
117480
117521
|
}));
|
|
117481
117522
|
} catch {
|
|
117523
|
+
if (project.hasOrigin) {
|
|
117524
|
+
setProjectHasOrigin(project.name, false);
|
|
117525
|
+
project.hasOrigin = false;
|
|
117526
|
+
}
|
|
117482
117527
|
return false;
|
|
117483
117528
|
}
|
|
117484
117529
|
const existingSet = new Set(project.worktrees.map((wt) => `${wt.branch}\0${wt.path}`));
|
|
@@ -117492,10 +117537,19 @@ async function reconcileOneProject(project) {
|
|
|
117492
117537
|
project.defaultBranch = remoteBranch;
|
|
117493
117538
|
mutated = true;
|
|
117494
117539
|
}
|
|
117540
|
+
const hasOrigin = await getRepoInfo(project.path) !== null;
|
|
117541
|
+
if (hasOrigin !== project.hasOrigin) {
|
|
117542
|
+
try {
|
|
117543
|
+
setProjectHasOrigin(project.name, hasOrigin);
|
|
117544
|
+
project.hasOrigin = hasOrigin;
|
|
117545
|
+
} catch {
|
|
117546
|
+
}
|
|
117547
|
+
}
|
|
117495
117548
|
return mutated;
|
|
117496
117549
|
}
|
|
117497
117550
|
|
|
117498
117551
|
// src/lib/branch-status-poller.ts
|
|
117552
|
+
var log10 = createLogger("branch-status-poller");
|
|
117499
117553
|
var INTERVALS = {
|
|
117500
117554
|
// 5 s git / 30 s CI — the original cadence, used when the user is actively looking at the UI on AC power.
|
|
117501
117555
|
active: { pollMs: 5e3, ciTicks: 6 },
|
|
@@ -117507,7 +117561,6 @@ var INTERVALS = {
|
|
|
117507
117561
|
var pollerTimer = null;
|
|
117508
117562
|
var tickCount = 0;
|
|
117509
117563
|
var currentActivity = "active";
|
|
117510
|
-
var repoInfoCache = /* @__PURE__ */ new Map();
|
|
117511
117564
|
function getWorkspaces() {
|
|
117512
117565
|
const state2 = loadState();
|
|
117513
117566
|
const workspaces = [];
|
|
@@ -117520,7 +117573,8 @@ function getWorkspaces() {
|
|
|
117520
117573
|
branch: wt.branch,
|
|
117521
117574
|
defaultBranch: project.defaultBranch,
|
|
117522
117575
|
worktreePath: wt.path,
|
|
117523
|
-
projectPath: project.path
|
|
117576
|
+
projectPath: project.path,
|
|
117577
|
+
hasOrigin: project.hasOrigin
|
|
117524
117578
|
});
|
|
117525
117579
|
}
|
|
117526
117580
|
}
|
|
@@ -117571,30 +117625,29 @@ async function getGitStatus(worktreePath) {
|
|
|
117571
117625
|
}
|
|
117572
117626
|
return status;
|
|
117573
117627
|
}
|
|
117574
|
-
async function resolveRepoInfo(projectPath) {
|
|
117575
|
-
const cached2 = repoInfoCache.get(projectPath);
|
|
117576
|
-
if (cached2 !== void 0) return cached2;
|
|
117577
|
-
const info = await getRepoInfo(projectPath);
|
|
117578
|
-
if (info) {
|
|
117579
|
-
repoInfoCache.set(projectPath, info);
|
|
117580
|
-
}
|
|
117581
|
-
return info;
|
|
117582
|
-
}
|
|
117583
117628
|
async function getBatchedCIStatuses(workspaces) {
|
|
117584
|
-
|
|
117585
|
-
const
|
|
117586
|
-
await Promise.
|
|
117587
|
-
|
|
117588
|
-
|
|
117589
|
-
if (repoInfo) {
|
|
117590
|
-
resolved.push({ ws, repoInfo, alias: `ws_${index3}` });
|
|
117591
|
-
} else {
|
|
117592
|
-
console.error(
|
|
117593
|
-
`CI poll: failed to resolve repo info for ${ws.workspaceId} (${ws.projectPath})`
|
|
117594
|
-
);
|
|
117595
|
-
}
|
|
117629
|
+
const uniqueProjectPaths = [...new Set(workspaces.map((ws) => ws.projectPath))];
|
|
117630
|
+
const repoInfoByPath = /* @__PURE__ */ new Map();
|
|
117631
|
+
await Promise.all(
|
|
117632
|
+
uniqueProjectPaths.map(async (path3) => {
|
|
117633
|
+
repoInfoByPath.set(path3, await getRepoInfo(path3));
|
|
117596
117634
|
})
|
|
117597
117635
|
);
|
|
117636
|
+
for (const path3 of uniqueProjectPaths) {
|
|
117637
|
+
if (repoInfoByPath.get(path3) === null) {
|
|
117638
|
+
log10.warn(
|
|
117639
|
+
"CI poll: getRepoInfo returned null for %s despite hasOrigin=true; will reconcile on next sync tick",
|
|
117640
|
+
path3
|
|
117641
|
+
);
|
|
117642
|
+
}
|
|
117643
|
+
}
|
|
117644
|
+
const resolved = [];
|
|
117645
|
+
for (const [index3, ws] of workspaces.entries()) {
|
|
117646
|
+
const repoInfo = repoInfoByPath.get(ws.projectPath);
|
|
117647
|
+
if (repoInfo) {
|
|
117648
|
+
resolved.push({ ws, repoInfo, alias: `ws_${index3}` });
|
|
117649
|
+
}
|
|
117650
|
+
}
|
|
117598
117651
|
if (resolved.length === 0) {
|
|
117599
117652
|
const results = /* @__PURE__ */ new Map();
|
|
117600
117653
|
for (const ws of workspaces) {
|
|
@@ -117676,7 +117729,10 @@ async function pollTick() {
|
|
|
117676
117729
|
const db2 = getDb();
|
|
117677
117730
|
let ciStatuses = /* @__PURE__ */ new Map();
|
|
117678
117731
|
if (isCITick) {
|
|
117679
|
-
|
|
117732
|
+
const ciWorkspaces = workspaces.filter((w2) => w2.hasOrigin);
|
|
117733
|
+
if (ciWorkspaces.length > 0) {
|
|
117734
|
+
ciStatuses = await getBatchedCIStatuses(ciWorkspaces);
|
|
117735
|
+
}
|
|
117680
117736
|
}
|
|
117681
117737
|
await Promise.allSettled(
|
|
117682
117738
|
workspaces.map(async (ws) => {
|
|
@@ -117880,7 +117936,7 @@ function subscribe(listener) {
|
|
|
117880
117936
|
}
|
|
117881
117937
|
|
|
117882
117938
|
// src/lib/chat-manager.ts
|
|
117883
|
-
var
|
|
117939
|
+
var log11 = createLogger("chat-manager");
|
|
117884
117940
|
var PANEL_TYPE = "chat";
|
|
117885
117941
|
var chatSessions = /* @__PURE__ */ new Map();
|
|
117886
117942
|
var workspaceChats = /* @__PURE__ */ new Map();
|
|
@@ -117951,7 +118007,7 @@ function createChat(workspaceId, options2) {
|
|
|
117951
118007
|
addToIndex(session);
|
|
117952
118008
|
addChatToLayout(workspaceId, session.id, { title: session.name });
|
|
117953
118009
|
emit({ kind: "chat-created", workspaceId, chatId: session.id });
|
|
117954
|
-
|
|
118010
|
+
log11.info({ chatId: session.id, workspaceId, agent: session.agent }, "chat pane created");
|
|
117955
118011
|
return session;
|
|
117956
118012
|
}
|
|
117957
118013
|
function getChat(chatId) {
|
|
@@ -117980,7 +118036,7 @@ function updateChat(chatId, updates) {
|
|
|
117980
118036
|
state: serializeState(session),
|
|
117981
118037
|
updatedAt: Date.now()
|
|
117982
118038
|
});
|
|
117983
|
-
|
|
118039
|
+
log11.info({ chatId, updates }, "chat pane updated");
|
|
117984
118040
|
return session;
|
|
117985
118041
|
}
|
|
117986
118042
|
function updateChatStatus(chatId, status) {
|
|
@@ -118032,7 +118088,7 @@ function removeChat(chatId) {
|
|
|
118032
118088
|
removeChatFromLayout(session.workspaceId, chatId);
|
|
118033
118089
|
removeFromIndex(chatId);
|
|
118034
118090
|
emit({ kind: "chat-removed", workspaceId: session.workspaceId, chatId });
|
|
118035
|
-
|
|
118091
|
+
log11.info({ chatId, workspaceId: session.workspaceId }, "chat pane removed");
|
|
118036
118092
|
return true;
|
|
118037
118093
|
}
|
|
118038
118094
|
function removeWorkspaceChats(workspaceId) {
|
|
@@ -118044,7 +118100,7 @@ function removeWorkspaceChats(workspaceId) {
|
|
|
118044
118100
|
}
|
|
118045
118101
|
deletePanelStatesForWorkspace(workspaceId, PANEL_TYPE);
|
|
118046
118102
|
workspaceChats.delete(workspaceId);
|
|
118047
|
-
|
|
118103
|
+
log11.info({ workspaceId }, "all chat panes removed for workspace");
|
|
118048
118104
|
}
|
|
118049
118105
|
function loadChatsFromDb() {
|
|
118050
118106
|
_initialized = true;
|
|
@@ -118072,7 +118128,7 @@ function loadChatsFromDb() {
|
|
|
118072
118128
|
addToIndex(session);
|
|
118073
118129
|
}
|
|
118074
118130
|
if (rows.length > 0) {
|
|
118075
|
-
|
|
118131
|
+
log11.info({ count: rows.length }, "loaded chat panes from database");
|
|
118076
118132
|
}
|
|
118077
118133
|
return rows.length;
|
|
118078
118134
|
}
|
|
@@ -118090,6 +118146,67 @@ function getOrCreateDefaultChat(workspaceId) {
|
|
|
118090
118146
|
return createChat(workspaceId, { name: "Chat" });
|
|
118091
118147
|
}
|
|
118092
118148
|
|
|
118149
|
+
// src/lib/jsonl-message-to-events.ts
|
|
118150
|
+
function stripFileSharingHint(text3) {
|
|
118151
|
+
return text3.replace(/\n\n\[File sharing:[\s\S]*?\]\s*$/, "");
|
|
118152
|
+
}
|
|
118153
|
+
function jsonlMessageToEvents(msg, startId) {
|
|
118154
|
+
const events = [];
|
|
118155
|
+
let id = startId;
|
|
118156
|
+
if (msg.role === "user") {
|
|
118157
|
+
let textBuf = "";
|
|
118158
|
+
let hasText = false;
|
|
118159
|
+
for (const part of msg.content) {
|
|
118160
|
+
if (part.type === "text") {
|
|
118161
|
+
hasText = true;
|
|
118162
|
+
textBuf += part.text;
|
|
118163
|
+
} else if (part.type === "tool_result") {
|
|
118164
|
+
events.push({
|
|
118165
|
+
type: "tool-output-available",
|
|
118166
|
+
toolCallId: part.toolCallId,
|
|
118167
|
+
output: part.output,
|
|
118168
|
+
isError: part.isError,
|
|
118169
|
+
eventId: id++
|
|
118170
|
+
});
|
|
118171
|
+
}
|
|
118172
|
+
}
|
|
118173
|
+
if (hasText) {
|
|
118174
|
+
events.push({
|
|
118175
|
+
type: "user-message",
|
|
118176
|
+
text: stripFileSharingHint(textBuf),
|
|
118177
|
+
eventId: id++
|
|
118178
|
+
});
|
|
118179
|
+
}
|
|
118180
|
+
return events;
|
|
118181
|
+
}
|
|
118182
|
+
for (const part of msg.content) {
|
|
118183
|
+
if (part.type === "text") {
|
|
118184
|
+
const textPartId = `${msg.id}-text-${id}`;
|
|
118185
|
+
events.push({ type: "text-start", id: textPartId, eventId: id++ });
|
|
118186
|
+
events.push({ type: "text-delta", id: textPartId, delta: part.text, eventId: id++ });
|
|
118187
|
+
events.push({ type: "text-end", id: textPartId, eventId: id++ });
|
|
118188
|
+
} else if (part.type === "tool_use") {
|
|
118189
|
+
events.push({
|
|
118190
|
+
type: "tool-input-available",
|
|
118191
|
+
toolCallId: part.toolCallId,
|
|
118192
|
+
toolName: part.toolName,
|
|
118193
|
+
displayTitle: part.displayTitle,
|
|
118194
|
+
input: part.input,
|
|
118195
|
+
eventId: id++
|
|
118196
|
+
});
|
|
118197
|
+
} else if (part.type === "tool_result") {
|
|
118198
|
+
events.push({
|
|
118199
|
+
type: "tool-output-available",
|
|
118200
|
+
toolCallId: part.toolCallId,
|
|
118201
|
+
output: part.output,
|
|
118202
|
+
isError: part.isError,
|
|
118203
|
+
eventId: id++
|
|
118204
|
+
});
|
|
118205
|
+
}
|
|
118206
|
+
}
|
|
118207
|
+
return events;
|
|
118208
|
+
}
|
|
118209
|
+
|
|
118093
118210
|
// src/lib/queued-message-store.ts
|
|
118094
118211
|
import { randomUUID } from "node:crypto";
|
|
118095
118212
|
function toWireQueuedMessages(messages) {
|
|
@@ -118265,7 +118382,7 @@ function hasPendingInputForWorkspace(workspaceId) {
|
|
|
118265
118382
|
|
|
118266
118383
|
// src/lib/task-store.ts
|
|
118267
118384
|
init_src();
|
|
118268
|
-
var
|
|
118385
|
+
var log12 = createLogger("task-store");
|
|
118269
118386
|
function generateTaskId() {
|
|
118270
118387
|
return `tsk_${Date.now()}`;
|
|
118271
118388
|
}
|
|
@@ -118338,7 +118455,7 @@ function cleanupStaleTasks() {
|
|
|
118338
118455
|
const result = db2.update(tasks).set({ status: "failed", completedAt: now }).where(eq2(tasks.status, "running")).run();
|
|
118339
118456
|
const count3 = result.changes;
|
|
118340
118457
|
if (count3 > 0) {
|
|
118341
|
-
|
|
118458
|
+
log12.info({ count: count3 }, "cleaned up stale tasks on startup");
|
|
118342
118459
|
}
|
|
118343
118460
|
return count3;
|
|
118344
118461
|
}
|
|
@@ -118375,7 +118492,7 @@ function pruneOldTasks(retentionMs = TASK_RETENTION_MS) {
|
|
|
118375
118492
|
const cutoff = Date.now() - retentionMs;
|
|
118376
118493
|
const count3 = deleteTasksOlderThan(cutoff);
|
|
118377
118494
|
if (count3 > 0) {
|
|
118378
|
-
|
|
118495
|
+
log12.info({ count: count3, retentionMs }, "pruned tasks older than retention window");
|
|
118379
118496
|
}
|
|
118380
118497
|
return count3;
|
|
118381
118498
|
}
|
|
@@ -118386,13 +118503,13 @@ function startTaskPruneScheduler(options2 = {}) {
|
|
|
118386
118503
|
try {
|
|
118387
118504
|
pruneOldTasks(retentionMs);
|
|
118388
118505
|
} catch (err) {
|
|
118389
|
-
|
|
118506
|
+
log12.error({ err }, "initial task prune on boot failed");
|
|
118390
118507
|
}
|
|
118391
118508
|
const timer = setInterval(() => {
|
|
118392
118509
|
try {
|
|
118393
118510
|
pruneOldTasks(retentionMs);
|
|
118394
118511
|
} catch (err) {
|
|
118395
|
-
|
|
118512
|
+
log12.error({ err }, "scheduled task prune failed");
|
|
118396
118513
|
}
|
|
118397
118514
|
}, intervalMs);
|
|
118398
118515
|
timer.unref();
|
|
@@ -118447,7 +118564,7 @@ function resolveWorkspace(workspaceId) {
|
|
|
118447
118564
|
}
|
|
118448
118565
|
|
|
118449
118566
|
// src/lib/task-runner.ts
|
|
118450
|
-
var
|
|
118567
|
+
var log13 = createLogger("task-runner");
|
|
118451
118568
|
function listFiles(dir) {
|
|
118452
118569
|
try {
|
|
118453
118570
|
return new Set(readdirSync6(dir));
|
|
@@ -118506,7 +118623,7 @@ function persistTask(task) {
|
|
|
118506
118623
|
chatId: task.chatId
|
|
118507
118624
|
});
|
|
118508
118625
|
} catch (err) {
|
|
118509
|
-
|
|
118626
|
+
log13.warn({ err, taskId: task.taskRecordId }, "failed to persist task");
|
|
118510
118627
|
}
|
|
118511
118628
|
}
|
|
118512
118629
|
function broadcast(chatId, chunk) {
|
|
@@ -118530,7 +118647,7 @@ function broadcast(chatId, chunk) {
|
|
|
118530
118647
|
}
|
|
118531
118648
|
const subs = listeners2.get(chatId);
|
|
118532
118649
|
if (!subs || subs.size === 0) {
|
|
118533
|
-
|
|
118650
|
+
log13.warn({ chatId, chunkType: chunk.type }, "broadcast: no listeners");
|
|
118534
118651
|
return;
|
|
118535
118652
|
}
|
|
118536
118653
|
for (const listener of subs) {
|
|
@@ -118596,7 +118713,7 @@ function submitTask(options2) {
|
|
|
118596
118713
|
});
|
|
118597
118714
|
}
|
|
118598
118715
|
runTask(chatId, task).catch((err) => {
|
|
118599
|
-
|
|
118716
|
+
log13.error({ chatId, err }, "task execution failed");
|
|
118600
118717
|
if (task.status === "running") {
|
|
118601
118718
|
task.status = "failed";
|
|
118602
118719
|
task.completedAt = Date.now();
|
|
@@ -118638,7 +118755,7 @@ function abortTask(chatId) {
|
|
|
118638
118755
|
updateChatStatus(chatId, "idle");
|
|
118639
118756
|
const updated = upsertWorkspaceStatus(task.workspaceId, { status: "waiting" });
|
|
118640
118757
|
emit({ kind: "update", status: updated });
|
|
118641
|
-
|
|
118758
|
+
log13.info({ chatId }, "task aborted by user");
|
|
118642
118759
|
return true;
|
|
118643
118760
|
}
|
|
118644
118761
|
function cancelTask(taskId) {
|
|
@@ -118663,7 +118780,7 @@ function cancelTask(taskId) {
|
|
|
118663
118780
|
updateChatStatus(chatId, "idle");
|
|
118664
118781
|
const updated = upsertWorkspaceStatus(task.workspaceId, { status: "waiting" });
|
|
118665
118782
|
emit({ kind: "update", status: updated });
|
|
118666
|
-
|
|
118783
|
+
log13.info({ chatId, taskId }, "task cancelled (was running in-memory)");
|
|
118667
118784
|
return { cancelled: true, workspaceId: task.workspaceId };
|
|
118668
118785
|
}
|
|
118669
118786
|
}
|
|
@@ -118671,7 +118788,7 @@ function cancelTask(taskId) {
|
|
|
118671
118788
|
if (record2) {
|
|
118672
118789
|
const updated = upsertWorkspaceStatus(record2.workspaceId, { status: "waiting" });
|
|
118673
118790
|
emit({ kind: "update", status: updated });
|
|
118674
|
-
|
|
118791
|
+
log13.info({ taskId, workspaceId: record2.workspaceId }, "orphaned task cancelled");
|
|
118675
118792
|
return { cancelled: true, workspaceId: record2.workspaceId };
|
|
118676
118793
|
}
|
|
118677
118794
|
return { cancelled: false };
|
|
@@ -118691,7 +118808,7 @@ async function runTask(chatId, task) {
|
|
|
118691
118808
|
const taskAgentId = task.codingAgentId;
|
|
118692
118809
|
const resolvedAgentId = taskAgentId ?? chatSession?.agent;
|
|
118693
118810
|
const needsReplace = taskAgentId && taskAgentId !== chatSession?.agent;
|
|
118694
|
-
|
|
118811
|
+
log13.info(
|
|
118695
118812
|
{ chatId, taskAgentId, chatAgent: chatSession?.agent, resolvedAgentId, needsReplace },
|
|
118696
118813
|
"resolving agent for task"
|
|
118697
118814
|
);
|
|
@@ -118740,7 +118857,7 @@ async function runTask(chatId, task) {
|
|
|
118740
118857
|
[File sharing: to send a file to the user, write or copy it to ${sharedDir}/ and it will appear as a downloadable file card in the chat.]`;
|
|
118741
118858
|
const effectivePrompt = task.sessionId ? task.agentPrompt : task.agentPrompt + fileSharingHint;
|
|
118742
118859
|
for await (const event of agent.runSession(effectivePrompt, task.sessionId, sessionOptions)) {
|
|
118743
|
-
|
|
118860
|
+
log13.info({ chatId, eventType: event.type }, "task event");
|
|
118744
118861
|
switch (event.type) {
|
|
118745
118862
|
case "session-start": {
|
|
118746
118863
|
task.sessionId = event.sessionId;
|
|
@@ -118940,7 +119057,7 @@ async function runTask(chatId, task) {
|
|
|
118940
119057
|
break;
|
|
118941
119058
|
}
|
|
118942
119059
|
case "session-id-resolved": {
|
|
118943
|
-
|
|
119060
|
+
log13.info(
|
|
118944
119061
|
{ chatId, previous: event.previousSessionId, resolved: event.resolvedSessionId },
|
|
118945
119062
|
"session ID resolved"
|
|
118946
119063
|
);
|
|
@@ -119035,7 +119152,7 @@ ${queued.text}`;
|
|
|
119035
119152
|
});
|
|
119036
119153
|
autoStarted = true;
|
|
119037
119154
|
} catch (err) {
|
|
119038
|
-
|
|
119155
|
+
log13.warn({ chatId, err }, "failed to auto-start queued task");
|
|
119039
119156
|
}
|
|
119040
119157
|
}
|
|
119041
119158
|
}
|
|
@@ -119188,7 +119305,7 @@ function openSseStream(res) {
|
|
|
119188
119305
|
}
|
|
119189
119306
|
|
|
119190
119307
|
// src/api/chat-events.ts
|
|
119191
|
-
var
|
|
119308
|
+
var log14 = createLogger("chat-events");
|
|
119192
119309
|
async function handleChatEvents(req, res, chatId) {
|
|
119193
119310
|
const url = new URL(req.url, `http://${req.headers.host}`);
|
|
119194
119311
|
const lastEventIdHeader = req.headers["last-event-id"];
|
|
@@ -119268,7 +119385,7 @@ async function handleChatEvents(req, res, chatId) {
|
|
|
119268
119385
|
chatWorkspaceId: chat?.workspaceId ?? explicitWorkspaceId,
|
|
119269
119386
|
agentTypeHint: chat?.agent
|
|
119270
119387
|
}).catch((err) => {
|
|
119271
|
-
|
|
119388
|
+
log14.warn({ chatId, err }, "replay phase failed; continuing to live tail");
|
|
119272
119389
|
});
|
|
119273
119390
|
try {
|
|
119274
119391
|
while (!res.destroyed && !writer.closed) {
|
|
@@ -119327,7 +119444,7 @@ async function replayPast(opts) {
|
|
|
119327
119444
|
}
|
|
119328
119445
|
}
|
|
119329
119446
|
} catch (err) {
|
|
119330
|
-
|
|
119447
|
+
log14.warn({ chatId, sessionId, err }, "JSONL backfill failed; falling through to buffer");
|
|
119331
119448
|
}
|
|
119332
119449
|
}
|
|
119333
119450
|
if (!jsonlEmittedAny && buf) {
|
|
@@ -119361,7 +119478,7 @@ async function replayPast(opts) {
|
|
|
119361
119478
|
}
|
|
119362
119479
|
}
|
|
119363
119480
|
} catch (err) {
|
|
119364
|
-
|
|
119481
|
+
log14.warn({ chatId, sessionId, err }, "JSONL backfill failed; falling through to buffer");
|
|
119365
119482
|
}
|
|
119366
119483
|
}
|
|
119367
119484
|
if (buf) {
|
|
@@ -119374,50 +119491,6 @@ async function replayPast(opts) {
|
|
|
119374
119491
|
}
|
|
119375
119492
|
}
|
|
119376
119493
|
}
|
|
119377
|
-
function stripFileSharingHint(text3) {
|
|
119378
|
-
return text3.replace(/\n\n\[File sharing:[\s\S]*?\]\s*$/, "");
|
|
119379
|
-
}
|
|
119380
|
-
function jsonlMessageToEvents(msg, startId) {
|
|
119381
|
-
const events = [];
|
|
119382
|
-
let id = startId;
|
|
119383
|
-
if (msg.role === "user") {
|
|
119384
|
-
const textPart = msg.content.find(
|
|
119385
|
-
(p6) => p6.type === "text"
|
|
119386
|
-
);
|
|
119387
|
-
events.push({
|
|
119388
|
-
type: "user-message",
|
|
119389
|
-
text: stripFileSharingHint(textPart?.text ?? ""),
|
|
119390
|
-
eventId: id++
|
|
119391
|
-
});
|
|
119392
|
-
return events;
|
|
119393
|
-
}
|
|
119394
|
-
for (const part of msg.content) {
|
|
119395
|
-
if (part.type === "text") {
|
|
119396
|
-
const textPartId = `${msg.id}-text-${id}`;
|
|
119397
|
-
events.push({ type: "text-start", id: textPartId, eventId: id++ });
|
|
119398
|
-
events.push({ type: "text-delta", id: textPartId, delta: part.text, eventId: id++ });
|
|
119399
|
-
events.push({ type: "text-end", id: textPartId, eventId: id++ });
|
|
119400
|
-
} else if (part.type === "tool_use") {
|
|
119401
|
-
events.push({
|
|
119402
|
-
type: "tool-input-available",
|
|
119403
|
-
toolCallId: part.toolCallId,
|
|
119404
|
-
toolName: part.toolName,
|
|
119405
|
-
displayTitle: part.displayTitle,
|
|
119406
|
-
input: part.input,
|
|
119407
|
-
eventId: id++
|
|
119408
|
-
});
|
|
119409
|
-
} else if (part.type === "tool_result") {
|
|
119410
|
-
events.push({
|
|
119411
|
-
type: "tool-output-available",
|
|
119412
|
-
toolCallId: part.toolCallId,
|
|
119413
|
-
output: part.output,
|
|
119414
|
-
isError: part.isError,
|
|
119415
|
-
eventId: id++
|
|
119416
|
-
});
|
|
119417
|
-
}
|
|
119418
|
-
}
|
|
119419
|
-
return events;
|
|
119420
|
-
}
|
|
119421
119494
|
function chunkToChatEvent(chunk, _sessionId) {
|
|
119422
119495
|
const c2 = chunk;
|
|
119423
119496
|
switch (c2.type) {
|
|
@@ -119547,7 +119620,7 @@ async function saveUploadedFiles(fileParts) {
|
|
|
119547
119620
|
}
|
|
119548
119621
|
|
|
119549
119622
|
// src/api/chat-submit.ts
|
|
119550
|
-
var
|
|
119623
|
+
var log15 = createLogger("chat-submit");
|
|
119551
119624
|
function readBody(req) {
|
|
119552
119625
|
return new Promise((resolve7, reject) => {
|
|
119553
119626
|
const chunks = [];
|
|
@@ -119584,7 +119657,7 @@ async function handleChatSubmit(req, res, chatId) {
|
|
|
119584
119657
|
if (files && files.length > 0) {
|
|
119585
119658
|
savedFiles = await saveUploadedFilesDetailed(files);
|
|
119586
119659
|
if (savedFiles.length !== files.length) {
|
|
119587
|
-
|
|
119660
|
+
log15.warn(
|
|
119588
119661
|
{ chatId, submitted: files.length, saved: savedFiles.length },
|
|
119589
119662
|
"chat-submit: some file uploads were dropped (malformed data URL?)"
|
|
119590
119663
|
);
|
|
@@ -119615,7 +119688,7 @@ ${text3}`;
|
|
|
119615
119688
|
model,
|
|
119616
119689
|
codingAgentId
|
|
119617
119690
|
});
|
|
119618
|
-
|
|
119691
|
+
log15.info({ chatId, workspaceId }, "chat-submit: task started");
|
|
119619
119692
|
sendJson(res, 200, { ok: true, queued: false });
|
|
119620
119693
|
} catch (err) {
|
|
119621
119694
|
if (err instanceof TaskConflictError) {
|
|
@@ -119630,7 +119703,7 @@ ${text3}`;
|
|
|
119630
119703
|
}))
|
|
119631
119704
|
}
|
|
119632
119705
|
});
|
|
119633
|
-
|
|
119706
|
+
log15.info({ chatId, workspaceId }, "chat-submit: task busy, message queued");
|
|
119634
119707
|
sendJson(res, 200, { ok: true, queued: true });
|
|
119635
119708
|
return;
|
|
119636
119709
|
}
|
|
@@ -119638,7 +119711,7 @@ ${text3}`;
|
|
|
119638
119711
|
sendJson(res, 404, { error: err.message });
|
|
119639
119712
|
return;
|
|
119640
119713
|
}
|
|
119641
|
-
|
|
119714
|
+
log15.error({ chatId, err }, "chat-submit: unexpected error");
|
|
119642
119715
|
sendJson(res, 500, { error: "Internal server error" });
|
|
119643
119716
|
}
|
|
119644
119717
|
}
|
|
@@ -119672,7 +119745,7 @@ function removeBrowserFromLayout(workspaceId, browserId) {
|
|
|
119672
119745
|
}
|
|
119673
119746
|
|
|
119674
119747
|
// src/lib/browser-manager.ts
|
|
119675
|
-
var
|
|
119748
|
+
var log16 = createLogger("browser-manager");
|
|
119676
119749
|
var PANEL_TYPE2 = "browser";
|
|
119677
119750
|
var browserTabs = /* @__PURE__ */ new Map();
|
|
119678
119751
|
var workspaceBrowsers = /* @__PURE__ */ new Map();
|
|
@@ -119733,7 +119806,7 @@ function createBrowser(workspaceId, options2) {
|
|
|
119733
119806
|
title: tab.name,
|
|
119734
119807
|
initialUrl: tab.url || void 0
|
|
119735
119808
|
});
|
|
119736
|
-
|
|
119809
|
+
log16.info({ browserId: tab.id, workspaceId, url: tab.url }, "browser tab created");
|
|
119737
119810
|
return tab;
|
|
119738
119811
|
}
|
|
119739
119812
|
function getBrowser(browserId) {
|
|
@@ -119760,7 +119833,7 @@ function updateBrowser(browserId, updates) {
|
|
|
119760
119833
|
state: serializeState2(tab),
|
|
119761
119834
|
updatedAt: Date.now()
|
|
119762
119835
|
});
|
|
119763
|
-
|
|
119836
|
+
log16.info({ browserId, updates }, "browser tab updated");
|
|
119764
119837
|
return tab;
|
|
119765
119838
|
}
|
|
119766
119839
|
function updateBrowserUrl(browserId, url) {
|
|
@@ -119777,7 +119850,7 @@ function removeBrowser(browserId) {
|
|
|
119777
119850
|
if (!tab) return false;
|
|
119778
119851
|
deletePanelState(browserId);
|
|
119779
119852
|
removeFromIndex2(browserId);
|
|
119780
|
-
|
|
119853
|
+
log16.info({ browserId, workspaceId: tab.workspaceId }, "browser tab removed");
|
|
119781
119854
|
return true;
|
|
119782
119855
|
}
|
|
119783
119856
|
function removeWorkspaceBrowsers(workspaceId) {
|
|
@@ -119788,7 +119861,7 @@ function removeWorkspaceBrowsers(workspaceId) {
|
|
|
119788
119861
|
}
|
|
119789
119862
|
deletePanelStatesForWorkspace(workspaceId, PANEL_TYPE2);
|
|
119790
119863
|
workspaceBrowsers.delete(workspaceId);
|
|
119791
|
-
|
|
119864
|
+
log16.info({ workspaceId }, "all browser tabs removed for workspace");
|
|
119792
119865
|
}
|
|
119793
119866
|
function loadBrowsersFromDb() {
|
|
119794
119867
|
_initialized2 = true;
|
|
@@ -119807,13 +119880,13 @@ function loadBrowsersFromDb() {
|
|
|
119807
119880
|
addToIndex2(tab);
|
|
119808
119881
|
}
|
|
119809
119882
|
if (rows.length > 0) {
|
|
119810
|
-
|
|
119883
|
+
log16.info({ count: rows.length }, "loaded browser tabs from database");
|
|
119811
119884
|
}
|
|
119812
119885
|
return rows.length;
|
|
119813
119886
|
}
|
|
119814
119887
|
|
|
119815
119888
|
// src/lib/browser-host.ts
|
|
119816
|
-
var
|
|
119889
|
+
var log17 = createLogger("browser-host");
|
|
119817
119890
|
var DESKTOP_CDP_HOST = "127.0.0.1";
|
|
119818
119891
|
var DESKTOP_CDP_PORT = 9223;
|
|
119819
119892
|
var globalAny = globalThis;
|
|
@@ -119864,7 +119937,7 @@ async function ensureCdpTargetId(bandTabId) {
|
|
|
119864
119937
|
reject: rejectFn,
|
|
119865
119938
|
timeoutId
|
|
119866
119939
|
});
|
|
119867
|
-
|
|
119940
|
+
log17.info(
|
|
119868
119941
|
"ensureCdpTargetId emitting ensureView for %s (url=%s, listeners=%d)",
|
|
119869
119942
|
bandTabId,
|
|
119870
119943
|
tab.url,
|
|
@@ -119878,13 +119951,13 @@ async function ensureCdpTargetId(bandTabId) {
|
|
|
119878
119951
|
url: tab.url
|
|
119879
119952
|
});
|
|
119880
119953
|
} catch (err) {
|
|
119881
|
-
|
|
119954
|
+
log17.warn("ensureView listener threw: %s", err instanceof Error ? err.message : err);
|
|
119882
119955
|
}
|
|
119883
119956
|
}
|
|
119884
119957
|
return promise;
|
|
119885
119958
|
}
|
|
119886
119959
|
function resolveTargetReady(bandTabId, cdpTargetId) {
|
|
119887
|
-
|
|
119960
|
+
log17.info("resolveTargetReady %s \u2192 %s", bandTabId, cdpTargetId);
|
|
119888
119961
|
targetIdByBandTabId.set(bandTabId, cdpTargetId);
|
|
119889
119962
|
const pending2 = pendingEnsures.get(bandTabId);
|
|
119890
119963
|
if (pending2) {
|
|
@@ -119894,7 +119967,7 @@ function resolveTargetReady(bandTabId, cdpTargetId) {
|
|
|
119894
119967
|
}
|
|
119895
119968
|
}
|
|
119896
119969
|
function markTargetDestroyed(bandTabId) {
|
|
119897
|
-
|
|
119970
|
+
log17.info("markTargetDestroyed %s", bandTabId);
|
|
119898
119971
|
targetIdByBandTabId.delete(bandTabId);
|
|
119899
119972
|
const pending2 = pendingEnsures.get(bandTabId);
|
|
119900
119973
|
if (pending2) {
|
|
@@ -119905,10 +119978,10 @@ function markTargetDestroyed(bandTabId) {
|
|
|
119905
119978
|
}
|
|
119906
119979
|
function onEnsureView(listener) {
|
|
119907
119980
|
ensureListeners.add(listener);
|
|
119908
|
-
|
|
119981
|
+
log17.info("onEnsureView subscriber added (total=%d)", ensureListeners.size);
|
|
119909
119982
|
return () => {
|
|
119910
119983
|
ensureListeners.delete(listener);
|
|
119911
|
-
|
|
119984
|
+
log17.info("onEnsureView subscriber removed (total=%d)", ensureListeners.size);
|
|
119912
119985
|
if (ensureListeners.size === 0) {
|
|
119913
119986
|
for (const [bandTabId, pending2] of pendingEnsures) {
|
|
119914
119987
|
clearTimeout(pending2.timeoutId);
|
|
@@ -119925,7 +119998,7 @@ function isDesktopHostConnected() {
|
|
|
119925
119998
|
|
|
119926
119999
|
// src/lib/cdp-proxy.ts
|
|
119927
120000
|
init_src();
|
|
119928
|
-
var
|
|
120001
|
+
var log18 = createLogger("cdp-proxy");
|
|
119929
120002
|
async function handleCdpConnection(ws, req) {
|
|
119930
120003
|
const url = new URL(req.url ?? "", `http://${req.headers.host}`);
|
|
119931
120004
|
const bandTabId = url.searchParams.get("bandTabId");
|
|
@@ -119948,17 +120021,17 @@ async function handleCdpConnection(ws, req) {
|
|
|
119948
120021
|
cdpTargetId = await ensureCdpTargetId(bandTabId);
|
|
119949
120022
|
} catch (err) {
|
|
119950
120023
|
const message = err instanceof Error ? err.message : String(err);
|
|
119951
|
-
|
|
120024
|
+
log18.debug("ensureCdpTargetId failed for %s: %s", bandTabId, message);
|
|
119952
120025
|
if (ws.readyState === ws.OPEN) {
|
|
119953
120026
|
ws.close(4001, message.slice(0, 123));
|
|
119954
120027
|
}
|
|
119955
120028
|
return;
|
|
119956
120029
|
}
|
|
119957
120030
|
const upstreamUrl = `ws://${DESKTOP_CDP_HOST}:${DESKTOP_CDP_PORT}/devtools/page/${encodeURIComponent(cdpTargetId)}`;
|
|
119958
|
-
|
|
120031
|
+
log18.info("CDP proxy connecting bandTabId=%s upstream=%s", bandTabId, upstreamUrl);
|
|
119959
120032
|
upstream = new wrapper_default(upstreamUrl);
|
|
119960
120033
|
upstream.on("open", () => {
|
|
119961
|
-
|
|
120034
|
+
log18.info("CDP upstream open bandTabId=%s pending=%d", bandTabId, pending2.length);
|
|
119962
120035
|
for (const msg of pending2) {
|
|
119963
120036
|
upstream?.send(msg);
|
|
119964
120037
|
}
|
|
@@ -119970,20 +120043,20 @@ async function handleCdpConnection(ws, req) {
|
|
|
119970
120043
|
}
|
|
119971
120044
|
});
|
|
119972
120045
|
upstream.on("error", (err) => {
|
|
119973
|
-
|
|
120046
|
+
log18.warn("CDP upstream error bandTabId=%s: %s", bandTabId, err.message);
|
|
119974
120047
|
markTargetDestroyed(bandTabId);
|
|
119975
120048
|
if (ws.readyState === ws.OPEN) {
|
|
119976
120049
|
ws.close(4001, `Desktop CDP error: ${err.message}`.slice(0, 123));
|
|
119977
120050
|
}
|
|
119978
120051
|
});
|
|
119979
120052
|
upstream.on("close", (code) => {
|
|
119980
|
-
|
|
120053
|
+
log18.info("CDP upstream closed bandTabId=%s code=%d", bandTabId, code);
|
|
119981
120054
|
if (ws.readyState === ws.OPEN) {
|
|
119982
120055
|
ws.close(1e3, "Upstream closed");
|
|
119983
120056
|
}
|
|
119984
120057
|
});
|
|
119985
120058
|
ws.on("close", () => {
|
|
119986
|
-
|
|
120059
|
+
log18.debug("CDP client closed bandTabId=%s", bandTabId);
|
|
119987
120060
|
if (upstream && (upstream.readyState === wrapper_default.OPEN || upstream.readyState === wrapper_default.CONNECTING)) {
|
|
119988
120061
|
try {
|
|
119989
120062
|
upstream.close();
|
|
@@ -119992,7 +120065,7 @@ async function handleCdpConnection(ws, req) {
|
|
|
119992
120065
|
}
|
|
119993
120066
|
});
|
|
119994
120067
|
ws.on("error", (err) => {
|
|
119995
|
-
|
|
120068
|
+
log18.debug("CDP client error bandTabId=%s: %s", bandTabId, err.message);
|
|
119996
120069
|
try {
|
|
119997
120070
|
upstream?.close();
|
|
119998
120071
|
} catch {
|
|
@@ -120002,7 +120075,7 @@ async function handleCdpConnection(ws, req) {
|
|
|
120002
120075
|
|
|
120003
120076
|
// src/lib/cdp-targets.ts
|
|
120004
120077
|
init_src();
|
|
120005
|
-
var
|
|
120078
|
+
var log19 = createLogger("cdp-targets");
|
|
120006
120079
|
var CdpUnreachableError = class extends Error {
|
|
120007
120080
|
constructor(message) {
|
|
120008
120081
|
super(message);
|
|
@@ -120058,7 +120131,7 @@ async function captureSnapshot(bandTabId) {
|
|
|
120058
120131
|
});
|
|
120059
120132
|
ws.on("error", (err) => {
|
|
120060
120133
|
clearTimeout(timeout);
|
|
120061
|
-
|
|
120134
|
+
log19.debug("captureSnapshot ws error for tab %s: %s", bandTabId, err.message);
|
|
120062
120135
|
markTargetDestroyed(bandTabId);
|
|
120063
120136
|
settle(new CdpUnreachableError(err.message));
|
|
120064
120137
|
});
|
|
@@ -120778,7 +120851,7 @@ function rowToDefinition(row) {
|
|
|
120778
120851
|
}
|
|
120779
120852
|
|
|
120780
120853
|
// src/lib/cronjob-scheduler.ts
|
|
120781
|
-
var
|
|
120854
|
+
var log20 = createLogger("cronjob-scheduler");
|
|
120782
120855
|
var SCHEDULER_KEY = Symbol.for("band.cronjob-scheduler");
|
|
120783
120856
|
var g14 = globalThis;
|
|
120784
120857
|
if (!g14[SCHEDULER_KEY]) {
|
|
@@ -120798,16 +120871,16 @@ function scheduleJob(job, fileKey) {
|
|
|
120798
120871
|
try {
|
|
120799
120872
|
const cronInstance = new E2(job.cronExpression, () => {
|
|
120800
120873
|
executeCronjob(job, fileKey).catch((err) => {
|
|
120801
|
-
|
|
120874
|
+
log20.error({ jobId: job.id, err }, "unhandled error in cronjob execution");
|
|
120802
120875
|
});
|
|
120803
120876
|
});
|
|
120804
120877
|
state.jobs.set(job.id, cronInstance);
|
|
120805
|
-
|
|
120878
|
+
log20.info(
|
|
120806
120879
|
{ jobId: job.id, name: job.name, cron: job.cronExpression, scope: job.scope },
|
|
120807
120880
|
"scheduled cronjob"
|
|
120808
120881
|
);
|
|
120809
120882
|
} catch (err) {
|
|
120810
|
-
|
|
120883
|
+
log20.error(
|
|
120811
120884
|
{ jobId: job.id, cronExpression: job.cronExpression, err },
|
|
120812
120885
|
"invalid cron expression, skipping job"
|
|
120813
120886
|
);
|
|
@@ -120821,24 +120894,24 @@ async function executeCronjob(job, fileKey) {
|
|
|
120821
120894
|
const appState = loadState();
|
|
120822
120895
|
const project = appState.projects.find((p6) => p6.name === fileKey);
|
|
120823
120896
|
if (!project) {
|
|
120824
|
-
|
|
120897
|
+
log20.warn({ jobId: job.id, fileKey }, "project not found for cronjob, skipping");
|
|
120825
120898
|
updateLastRun(job.id, "failed");
|
|
120826
120899
|
return;
|
|
120827
120900
|
}
|
|
120828
120901
|
workspaceId = toWorkspaceId(project.name, project.defaultBranch);
|
|
120829
120902
|
}
|
|
120830
|
-
|
|
120903
|
+
log20.info({ jobId: job.id, name: job.name, workspaceId }, "executing cronjob");
|
|
120831
120904
|
try {
|
|
120832
120905
|
const chat = getOrCreateDefaultChat(workspaceId);
|
|
120833
120906
|
submitTask({ workspaceId, chatId: chat.id, prompt: job.prompt });
|
|
120834
120907
|
updateLastRun(job.id, "completed");
|
|
120835
120908
|
} catch (err) {
|
|
120836
120909
|
if (err instanceof TaskConflictError) {
|
|
120837
|
-
|
|
120910
|
+
log20.info({ jobId: job.id, workspaceId }, "task already running, skipping cronjob execution");
|
|
120838
120911
|
updateLastRun(job.id, "skipped");
|
|
120839
120912
|
return;
|
|
120840
120913
|
}
|
|
120841
|
-
|
|
120914
|
+
log20.error({ jobId: job.id, err }, "cronjob execution failed");
|
|
120842
120915
|
updateLastRun(job.id, "failed");
|
|
120843
120916
|
}
|
|
120844
120917
|
}
|
|
@@ -120847,7 +120920,7 @@ function updateLastRun(jobId, status) {
|
|
|
120847
120920
|
const db2 = getDb();
|
|
120848
120921
|
db2.update(cronjobs).set({ lastRunAt: (/* @__PURE__ */ new Date()).toISOString(), lastRunStatus: status }).where(eq2(cronjobs.id, jobId)).run();
|
|
120849
120922
|
} catch (err) {
|
|
120850
|
-
|
|
120923
|
+
log20.warn({ jobId, err }, "failed to update lastRun on cronjob");
|
|
120851
120924
|
}
|
|
120852
120925
|
}
|
|
120853
120926
|
function loadAndScheduleAll() {
|
|
@@ -120858,13 +120931,13 @@ function loadAndScheduleAll() {
|
|
|
120858
120931
|
for (const job of listAllCronjobs()) {
|
|
120859
120932
|
scheduleJob(job, job.fileKey);
|
|
120860
120933
|
}
|
|
120861
|
-
|
|
120934
|
+
log20.info({ count: state.jobs.size }, "loaded cronjob schedules");
|
|
120862
120935
|
}
|
|
120863
120936
|
function startCronjobScheduler() {
|
|
120864
120937
|
if (state.started) return;
|
|
120865
120938
|
state.started = true;
|
|
120866
120939
|
loadAndScheduleAll();
|
|
120867
|
-
|
|
120940
|
+
log20.info("cronjob scheduler started");
|
|
120868
120941
|
}
|
|
120869
120942
|
function stopCronjobScheduler() {
|
|
120870
120943
|
for (const [, cron] of state.jobs) {
|
|
@@ -120872,7 +120945,7 @@ function stopCronjobScheduler() {
|
|
|
120872
120945
|
}
|
|
120873
120946
|
state.jobs.clear();
|
|
120874
120947
|
state.started = false;
|
|
120875
|
-
|
|
120948
|
+
log20.info("cronjob scheduler stopped");
|
|
120876
120949
|
}
|
|
120877
120950
|
function reloadSchedules() {
|
|
120878
120951
|
if (!state.started) return;
|
|
@@ -120885,7 +120958,7 @@ function stopJobsForKey(key) {
|
|
|
120885
120958
|
if (cron) {
|
|
120886
120959
|
cron.stop();
|
|
120887
120960
|
state.jobs.delete(job.id);
|
|
120888
|
-
|
|
120961
|
+
log20.info({ jobId: job.id, key }, "stopped cronjob");
|
|
120889
120962
|
}
|
|
120890
120963
|
}
|
|
120891
120964
|
}
|
|
@@ -120951,7 +121024,7 @@ async function checkPrereqs() {
|
|
|
120951
121024
|
|
|
120952
121025
|
// src/lib/lsp-manager.ts
|
|
120953
121026
|
var __dirname2 = dirname2(fileURLToPath(import.meta.url));
|
|
120954
|
-
var
|
|
121027
|
+
var log21 = createLogger("lsp");
|
|
120955
121028
|
var LANG_SERVER_CONFIG = {
|
|
120956
121029
|
typescript: { command: "typescript-language-server", args: ["--stdio"] }
|
|
120957
121030
|
};
|
|
@@ -120979,7 +121052,7 @@ async function getOrSpawnServer(workspaceId, lang) {
|
|
|
120979
121052
|
const workspaceBin = join17(cwd, "node_modules/.bin");
|
|
120980
121053
|
const pathSep = process.platform === "win32" ? ";" : ":";
|
|
120981
121054
|
const combinedPath = [bundledBin, appBin, workspaceBin, resolvedPath].join(pathSep);
|
|
120982
|
-
|
|
121055
|
+
log21.debug("Spawning %s language server in %s for workspace %s", lang, cwd, workspaceId);
|
|
120983
121056
|
const child = spawn6(config2.command, config2.args, {
|
|
120984
121057
|
cwd,
|
|
120985
121058
|
stdio: ["pipe", "pipe", "pipe"],
|
|
@@ -121007,15 +121080,15 @@ async function getOrSpawnServer(workspaceId, lang) {
|
|
|
121007
121080
|
}
|
|
121008
121081
|
ids.add(serverId);
|
|
121009
121082
|
child.on("exit", (code) => {
|
|
121010
|
-
|
|
121083
|
+
log21.debug("Language server exited: %s (code %s)", serverId, String(code));
|
|
121011
121084
|
removeSession();
|
|
121012
121085
|
});
|
|
121013
121086
|
child.on("error", (err) => {
|
|
121014
|
-
|
|
121087
|
+
log21.error("Language server error: %s \u2014 %s", serverId, err.message);
|
|
121015
121088
|
removeSession();
|
|
121016
121089
|
});
|
|
121017
121090
|
child.stderr?.on("data", (chunk) => {
|
|
121018
|
-
|
|
121091
|
+
log21.debug("LSP stderr [%s]: %s", serverId, chunk.toString().trimEnd());
|
|
121019
121092
|
});
|
|
121020
121093
|
await new Promise((resolve7, reject) => {
|
|
121021
121094
|
child.once("spawn", resolve7);
|
|
@@ -121045,7 +121118,7 @@ function killAllServers() {
|
|
|
121045
121118
|
|
|
121046
121119
|
// src/lib/lsp-proxy.ts
|
|
121047
121120
|
init_src();
|
|
121048
|
-
var
|
|
121121
|
+
var log22 = createLogger("lsp-proxy");
|
|
121049
121122
|
function frameMessage(json2) {
|
|
121050
121123
|
const body = Buffer.from(json2, "utf-8");
|
|
121051
121124
|
const header = `Content-Length: ${body.byteLength}\r
|
|
@@ -121063,7 +121136,7 @@ function createFrameParser(onMessage) {
|
|
|
121063
121136
|
const headerStr = buffer.subarray(0, separatorIdx).toString("ascii");
|
|
121064
121137
|
const match = headerStr.match(/Content-Length:\s*(\d+)/i);
|
|
121065
121138
|
if (!match) {
|
|
121066
|
-
|
|
121139
|
+
log22.warn("Malformed LSP header: %s", headerStr);
|
|
121067
121140
|
buffer = buffer.subarray(separatorIdx + 4);
|
|
121068
121141
|
continue;
|
|
121069
121142
|
}
|
|
@@ -121096,7 +121169,7 @@ async function handleLspConnection(ws, req) {
|
|
|
121096
121169
|
session = await getOrSpawnServer(workspaceId, lang);
|
|
121097
121170
|
} catch (err) {
|
|
121098
121171
|
const message = err instanceof Error ? err.message : String(err);
|
|
121099
|
-
|
|
121172
|
+
log22.error(
|
|
121100
121173
|
"Failed to spawn %s language server for workspace %s: %s",
|
|
121101
121174
|
lang,
|
|
121102
121175
|
workspaceId,
|
|
@@ -121110,12 +121183,12 @@ async function handleLspConnection(ws, req) {
|
|
|
121110
121183
|
ws.close(4002, "Language server stdio not available");
|
|
121111
121184
|
return;
|
|
121112
121185
|
}
|
|
121113
|
-
|
|
121186
|
+
log22.debug("LSP client connected: %s/%s", workspaceId, lang);
|
|
121114
121187
|
const pendingRequests = /* @__PURE__ */ new Map();
|
|
121115
121188
|
const retriedIds = /* @__PURE__ */ new Set();
|
|
121116
121189
|
const RETRY_DELAY_MS = 2e3;
|
|
121117
121190
|
const parseFrame = createFrameParser((json2) => {
|
|
121118
|
-
|
|
121191
|
+
log22.debug(
|
|
121119
121192
|
"LSP stdout [%s/%s]: %s",
|
|
121120
121193
|
workspaceId,
|
|
121121
121194
|
lang,
|
|
@@ -121127,7 +121200,7 @@ async function handleLspConnection(ws, req) {
|
|
|
121127
121200
|
const originalRequest = pendingRequests.get(msg.id);
|
|
121128
121201
|
retriedIds.add(msg.id);
|
|
121129
121202
|
pendingRequests.delete(msg.id);
|
|
121130
|
-
|
|
121203
|
+
log22.debug(
|
|
121131
121204
|
"LSP retrying request %d after 'No Project' error [%s/%s]",
|
|
121132
121205
|
msg.id,
|
|
121133
121206
|
workspaceId,
|
|
@@ -121149,14 +121222,14 @@ async function handleLspConnection(ws, req) {
|
|
|
121149
121222
|
const onStdoutData = (chunk) => parseFrame(chunk);
|
|
121150
121223
|
lspProcess.stdout.on("data", onStdoutData);
|
|
121151
121224
|
const onExit = (code) => {
|
|
121152
|
-
|
|
121225
|
+
log22.debug("LSP server exited (code %s), closing WebSocket", String(code));
|
|
121153
121226
|
if (ws.readyState === ws.OPEN) {
|
|
121154
121227
|
ws.close(1e3, "Language server exited");
|
|
121155
121228
|
}
|
|
121156
121229
|
};
|
|
121157
121230
|
lspProcess.on("exit", onExit);
|
|
121158
121231
|
function forwardToStdin(json2) {
|
|
121159
|
-
|
|
121232
|
+
log22.debug(
|
|
121160
121233
|
"LSP stdin [%s/%s]: %s",
|
|
121161
121234
|
workspaceId,
|
|
121162
121235
|
lang,
|
|
@@ -121183,7 +121256,7 @@ async function handleLspConnection(ws, req) {
|
|
|
121183
121256
|
ws.on("close", () => {
|
|
121184
121257
|
lspProcess.stdout?.off("data", onStdoutData);
|
|
121185
121258
|
lspProcess.off("exit", onExit);
|
|
121186
|
-
|
|
121259
|
+
log22.debug("LSP client disconnected: %s/%s (server kept alive)", workspaceId, lang);
|
|
121187
121260
|
});
|
|
121188
121261
|
}
|
|
121189
121262
|
|
|
@@ -121712,7 +121785,7 @@ async function installHooks() {
|
|
|
121712
121785
|
}
|
|
121713
121786
|
|
|
121714
121787
|
// src/lib/setup.ts
|
|
121715
|
-
var
|
|
121788
|
+
var log23 = createLogger("setup");
|
|
121716
121789
|
var AGENT_CHECKS = [
|
|
121717
121790
|
{ id: "claude-code", type: "claude-code", label: "Claude Code", binary: "claude" },
|
|
121718
121791
|
{ id: "codex", type: "codex", label: "Codex", binary: "codex" },
|
|
@@ -121729,7 +121802,7 @@ async function runFirstTimeSetup() {
|
|
|
121729
121802
|
]);
|
|
121730
121803
|
for (const r6 of results) {
|
|
121731
121804
|
if (r6.status === "rejected") {
|
|
121732
|
-
|
|
121805
|
+
log23.warn(
|
|
121733
121806
|
"Setup step failed: %s",
|
|
121734
121807
|
r6.reason instanceof Error ? r6.reason.message : String(r6.reason)
|
|
121735
121808
|
);
|
|
@@ -121744,7 +121817,7 @@ async function ensureProjectStateInSync() {
|
|
|
121744
121817
|
try {
|
|
121745
121818
|
await syncWorktrees();
|
|
121746
121819
|
} catch (err) {
|
|
121747
|
-
|
|
121820
|
+
log23.warn(
|
|
121748
121821
|
"Failed to sync project state at boot: %s",
|
|
121749
121822
|
err instanceof Error ? err.message : String(err)
|
|
121750
121823
|
);
|
|
@@ -121755,22 +121828,22 @@ async function ensureCliInstalled() {
|
|
|
121755
121828
|
try {
|
|
121756
121829
|
cliStatus = await checkCli();
|
|
121757
121830
|
} catch (err) {
|
|
121758
|
-
|
|
121831
|
+
log23.warn("Could not check CLI status: %s", err instanceof Error ? err.message : String(err));
|
|
121759
121832
|
return;
|
|
121760
121833
|
}
|
|
121761
121834
|
if (cliStatus === "Installed") {
|
|
121762
121835
|
return;
|
|
121763
121836
|
}
|
|
121764
121837
|
if (cliStatus !== "NotInstalled") {
|
|
121765
|
-
|
|
121838
|
+
log23.warn("CLI not auto-installed (status: %s)", cliStatus);
|
|
121766
121839
|
return;
|
|
121767
121840
|
}
|
|
121768
|
-
|
|
121841
|
+
log23.info("Installing band CLI...");
|
|
121769
121842
|
try {
|
|
121770
121843
|
await installCli();
|
|
121771
|
-
|
|
121844
|
+
log23.info("CLI installed to /usr/local/bin/band");
|
|
121772
121845
|
} catch (err) {
|
|
121773
|
-
|
|
121846
|
+
log23.warn("CLI installation failed: %s", err instanceof Error ? err.message : String(err));
|
|
121774
121847
|
}
|
|
121775
121848
|
}
|
|
121776
121849
|
async function ensureDefaultCodingAgents() {
|
|
@@ -121779,17 +121852,17 @@ async function ensureDefaultCodingAgents() {
|
|
|
121779
121852
|
if (Array.isArray(existing) && existing.length > 0) {
|
|
121780
121853
|
return;
|
|
121781
121854
|
}
|
|
121782
|
-
|
|
121855
|
+
log23.info("Detecting installed coding agents...");
|
|
121783
121856
|
const detected = [];
|
|
121784
121857
|
for (const check2 of AGENT_CHECKS) {
|
|
121785
121858
|
const path3 = await whichBinary(check2.binary);
|
|
121786
121859
|
if (path3) {
|
|
121787
|
-
|
|
121860
|
+
log23.info("Detected coding agent: %s (%s)", check2.id, path3);
|
|
121788
121861
|
detected.push({ id: check2.id, type: check2.type, label: check2.label });
|
|
121789
121862
|
}
|
|
121790
121863
|
}
|
|
121791
121864
|
if (detected.length === 0) {
|
|
121792
|
-
|
|
121865
|
+
log23.info("No coding agent CLIs detected on PATH");
|
|
121793
121866
|
return;
|
|
121794
121867
|
}
|
|
121795
121868
|
const current = loadSettings();
|
|
@@ -121798,7 +121871,7 @@ async function ensureDefaultCodingAgents() {
|
|
|
121798
121871
|
current.defaultCodingAgent = detected[0].id;
|
|
121799
121872
|
}
|
|
121800
121873
|
saveSettings(current);
|
|
121801
|
-
|
|
121874
|
+
log23.info("Enabled %d coding agent(s); default = %s", detected.length, current.defaultCodingAgent);
|
|
121802
121875
|
}
|
|
121803
121876
|
function ensureNotificationDefaults() {
|
|
121804
121877
|
const settings = loadSettings();
|
|
@@ -121810,7 +121883,7 @@ function ensureNotificationDefaults() {
|
|
|
121810
121883
|
...settings,
|
|
121811
121884
|
notifications: { ...notifications, soundOnNeedsAttention: true }
|
|
121812
121885
|
});
|
|
121813
|
-
|
|
121886
|
+
log23.info("Set default notifications.soundOnNeedsAttention = true");
|
|
121814
121887
|
}
|
|
121815
121888
|
async function ensureClaudeHooks() {
|
|
121816
121889
|
try {
|
|
@@ -121819,9 +121892,9 @@ async function ensureClaudeHooks() {
|
|
|
121819
121892
|
return;
|
|
121820
121893
|
}
|
|
121821
121894
|
await installHooks();
|
|
121822
|
-
|
|
121895
|
+
log23.info("Installed Claude Code hooks");
|
|
121823
121896
|
} catch (err) {
|
|
121824
|
-
|
|
121897
|
+
log23.warn(
|
|
121825
121898
|
"Failed to install Claude Code hooks: %s",
|
|
121826
121899
|
err instanceof Error ? err.message : String(err)
|
|
121827
121900
|
);
|
|
@@ -121829,11 +121902,11 @@ async function ensureClaudeHooks() {
|
|
|
121829
121902
|
}
|
|
121830
121903
|
async function ensureSkillsInstalled() {
|
|
121831
121904
|
try {
|
|
121832
|
-
const result = await installSkills({ log:
|
|
121905
|
+
const result = await installSkills({ log: log23 });
|
|
121833
121906
|
const wrote = result.written.length + result.updated.length;
|
|
121834
121907
|
const linkChange = result.linked.length;
|
|
121835
121908
|
if (wrote > 0 || linkChange > 0 || result.conflicts.length > 0) {
|
|
121836
|
-
|
|
121909
|
+
log23.info(
|
|
121837
121910
|
"Synced CLI skills (shared: %d written, %d updated, %d unchanged; symlinks: %d created, %d already-linked, %d conflicts, %d skipped)",
|
|
121838
121911
|
result.written.length,
|
|
121839
121912
|
result.updated.length,
|
|
@@ -121845,7 +121918,7 @@ async function ensureSkillsInstalled() {
|
|
|
121845
121918
|
);
|
|
121846
121919
|
}
|
|
121847
121920
|
} catch (err) {
|
|
121848
|
-
|
|
121921
|
+
log23.warn("Failed to sync CLI skills: %s", err instanceof Error ? err.message : String(err));
|
|
121849
121922
|
}
|
|
121850
121923
|
}
|
|
121851
121924
|
|
|
@@ -121879,7 +121952,7 @@ function removeTerminalFromLayout(workspaceId, terminalId) {
|
|
|
121879
121952
|
}
|
|
121880
121953
|
|
|
121881
121954
|
// src/lib/terminal-manager.ts
|
|
121882
|
-
var
|
|
121955
|
+
var log24 = createLogger("terminal");
|
|
121883
121956
|
var MAX_SCROLLBACK_SIZE = 1e5;
|
|
121884
121957
|
var terminals = /* @__PURE__ */ new Map();
|
|
121885
121958
|
var workspaceTerminals = /* @__PURE__ */ new Map();
|
|
@@ -121910,11 +121983,11 @@ async function spawnTerminal(workspaceId, terminalId, options2) {
|
|
|
121910
121983
|
if (options2?.cwd) {
|
|
121911
121984
|
const resolved = join21(workspaceRoot, options2.cwd);
|
|
121912
121985
|
if (!resolved.startsWith(workspaceRoot)) {
|
|
121913
|
-
|
|
121986
|
+
log24.warn("Ignoring cwd %s \u2014 resolves outside workspace root %s", options2.cwd, workspaceRoot);
|
|
121914
121987
|
} else if (existsSync7(resolved)) {
|
|
121915
121988
|
cwd = resolved;
|
|
121916
121989
|
} else {
|
|
121917
|
-
|
|
121990
|
+
log24.warn("Ignoring cwd %s \u2014 directory does not exist", options2.cwd);
|
|
121918
121991
|
}
|
|
121919
121992
|
}
|
|
121920
121993
|
if (!existsSync7(cwd)) {
|
|
@@ -121923,7 +121996,7 @@ async function spawnTerminal(workspaceId, terminalId, options2) {
|
|
|
121923
121996
|
if (!existsSync7(shell)) {
|
|
121924
121997
|
throw new Error(`Shell not found: ${shell}`);
|
|
121925
121998
|
}
|
|
121926
|
-
|
|
121999
|
+
log24.debug(
|
|
121927
122000
|
"Spawning shell %s in %s for terminal %s (PATH=%s)",
|
|
121928
122001
|
shell,
|
|
121929
122002
|
cwd,
|
|
@@ -121942,7 +122015,7 @@ async function spawnTerminal(workspaceId, terminalId, options2) {
|
|
|
121942
122015
|
});
|
|
121943
122016
|
} catch (err) {
|
|
121944
122017
|
const msg = err instanceof Error ? err.message : String(err);
|
|
121945
|
-
|
|
122018
|
+
log24.error("pty.spawn failed: %s (shell=%s, cwd=%s)", msg, shell, cwd);
|
|
121946
122019
|
throw err;
|
|
121947
122020
|
}
|
|
121948
122021
|
const session = { pty: ptyProcess, scrollback: "", workspaceId };
|
|
@@ -121978,7 +122051,7 @@ async function spawnTerminal(workspaceId, terminalId, options2) {
|
|
|
121978
122051
|
}
|
|
121979
122052
|
});
|
|
121980
122053
|
ptyProcess.onExit(() => {
|
|
121981
|
-
|
|
122054
|
+
log24.debug("Terminal exited: %s (workspace %s)", terminalId, workspaceId);
|
|
121982
122055
|
terminals.delete(terminalId);
|
|
121983
122056
|
outputListeners.delete(terminalId);
|
|
121984
122057
|
const set = workspaceTerminals.get(workspaceId);
|
|
@@ -122086,7 +122159,7 @@ function killAllTerminals() {
|
|
|
122086
122159
|
|
|
122087
122160
|
// src/lib/terminal-ws.ts
|
|
122088
122161
|
init_src();
|
|
122089
|
-
var
|
|
122162
|
+
var log25 = createLogger("terminal-ws");
|
|
122090
122163
|
var MAX_CLOSE_REASON_BYTES = 123;
|
|
122091
122164
|
function clampCloseReason(reason) {
|
|
122092
122165
|
const enc = new TextEncoder();
|
|
@@ -122150,7 +122223,7 @@ async function handleTerminalConnection(ws, req) {
|
|
|
122150
122223
|
session = await spawnTerminal(workspaceId, terminalId, spawnOpts);
|
|
122151
122224
|
} catch (err) {
|
|
122152
122225
|
const msg = err instanceof Error ? err.message : String(err);
|
|
122153
|
-
|
|
122226
|
+
log25.error("Failed to spawn terminal %s for workspace %s: %s", terminalId, workspaceId, msg);
|
|
122154
122227
|
safeClose(ws, 4001, msg);
|
|
122155
122228
|
return;
|
|
122156
122229
|
}
|
|
@@ -122164,7 +122237,7 @@ async function handleTerminalConnection(ws, req) {
|
|
|
122164
122237
|
});
|
|
122165
122238
|
}
|
|
122166
122239
|
function attachSession(ws, terminalId, workspaceId, session, isNew) {
|
|
122167
|
-
|
|
122240
|
+
log25.debug(
|
|
122168
122241
|
"Terminal %s: %s (workspace %s)",
|
|
122169
122242
|
isNew ? "connected" : "reconnected",
|
|
122170
122243
|
terminalId,
|
|
@@ -122193,7 +122266,7 @@ function attachSession(ws, terminalId, workspaceId, session, isNew) {
|
|
|
122193
122266
|
}, 3e3);
|
|
122194
122267
|
const exitDisposable = session.pty.onExit(({ exitCode }) => {
|
|
122195
122268
|
clearInterval(processInterval);
|
|
122196
|
-
|
|
122269
|
+
log25.debug("PTY exited with code %d for terminal %s", exitCode, terminalId);
|
|
122197
122270
|
if (ws.readyState === ws.OPEN) {
|
|
122198
122271
|
ws.close(1e3, "Terminal exited");
|
|
122199
122272
|
}
|
|
@@ -122205,7 +122278,7 @@ function attachSession(ws, terminalId, workspaceId, session, isNew) {
|
|
|
122205
122278
|
clearInterval(processInterval);
|
|
122206
122279
|
dataDisposable.dispose();
|
|
122207
122280
|
exitDisposable.dispose();
|
|
122208
|
-
|
|
122281
|
+
log25.debug("Terminal disconnected: %s (PTY kept alive)", terminalId);
|
|
122209
122282
|
});
|
|
122210
122283
|
}
|
|
122211
122284
|
function handleMessage(ws, terminalId, session, message) {
|
|
@@ -122243,7 +122316,7 @@ function getToken() {
|
|
|
122243
122316
|
}
|
|
122244
122317
|
|
|
122245
122318
|
// src/lib/tunnel.ts
|
|
122246
|
-
var
|
|
122319
|
+
var log26 = createLogger("tunnel");
|
|
122247
122320
|
var tunnelProcess = null;
|
|
122248
122321
|
var tunnelUrl = null;
|
|
122249
122322
|
var startInProgress = null;
|
|
@@ -122257,7 +122330,7 @@ function appendToken(baseUrl, token) {
|
|
|
122257
122330
|
}
|
|
122258
122331
|
function spawnTunnel(options2, resolvedPath) {
|
|
122259
122332
|
const args = ["tunnel", "--config", "/dev/null", "--url", `http://localhost:${options2.port}`];
|
|
122260
|
-
|
|
122333
|
+
log26.debug("spawning cloudflared %s", args.join(" "));
|
|
122261
122334
|
return new Promise((resolve7, reject) => {
|
|
122262
122335
|
const child = spawn7("cloudflared", args, {
|
|
122263
122336
|
env: { ...process.env, PATH: resolvedPath },
|
|
@@ -122271,12 +122344,12 @@ function spawnTunnel(options2, resolvedPath) {
|
|
|
122271
122344
|
for (const line2 of text3.split("\n")) {
|
|
122272
122345
|
const trimmed = line2.trim();
|
|
122273
122346
|
if (!trimmed) continue;
|
|
122274
|
-
|
|
122347
|
+
log26.debug("output: %s", trimmed);
|
|
122275
122348
|
const url = extractUrl(trimmed);
|
|
122276
122349
|
if (url) {
|
|
122277
122350
|
const token = getToken();
|
|
122278
122351
|
tunnelUrl = appendToken(url, token);
|
|
122279
|
-
|
|
122352
|
+
log26.debug("detected URL: %s", tunnelUrl);
|
|
122280
122353
|
emit({ kind: "tunnel-url", url: tunnelUrl });
|
|
122281
122354
|
if (!settled) {
|
|
122282
122355
|
settled = true;
|
|
@@ -122291,7 +122364,7 @@ function spawnTunnel(options2, resolvedPath) {
|
|
|
122291
122364
|
handleOutput(data);
|
|
122292
122365
|
});
|
|
122293
122366
|
child.on("error", (err) => {
|
|
122294
|
-
|
|
122367
|
+
log26.debug("process error: %s", err.message);
|
|
122295
122368
|
tunnelProcess = null;
|
|
122296
122369
|
tunnelUrl = null;
|
|
122297
122370
|
emit({ kind: "tunnel-error", error: err.message });
|
|
@@ -122301,7 +122374,7 @@ function spawnTunnel(options2, resolvedPath) {
|
|
|
122301
122374
|
}
|
|
122302
122375
|
});
|
|
122303
122376
|
child.on("exit", (code) => {
|
|
122304
|
-
|
|
122377
|
+
log26.debug("process exited with code: %d", code ?? -1);
|
|
122305
122378
|
const wasRunning = tunnelProcess !== null && settled;
|
|
122306
122379
|
tunnelProcess = null;
|
|
122307
122380
|
tunnelUrl = null;
|
|
@@ -122323,7 +122396,7 @@ function spawnTunnel(options2, resolvedPath) {
|
|
|
122323
122396
|
});
|
|
122324
122397
|
setTimeout(() => {
|
|
122325
122398
|
if (!settled) {
|
|
122326
|
-
|
|
122399
|
+
log26.debug("30s timeout reached, resolving without URL");
|
|
122327
122400
|
settled = true;
|
|
122328
122401
|
resolve7();
|
|
122329
122402
|
}
|
|
@@ -122332,12 +122405,12 @@ function spawnTunnel(options2, resolvedPath) {
|
|
|
122332
122405
|
}
|
|
122333
122406
|
async function startTunnel(options2) {
|
|
122334
122407
|
if (startInProgress) {
|
|
122335
|
-
|
|
122408
|
+
log26.debug("startTunnel: start already in progress, waiting...");
|
|
122336
122409
|
await startInProgress;
|
|
122337
122410
|
return;
|
|
122338
122411
|
}
|
|
122339
122412
|
if (tunnelProcess) {
|
|
122340
|
-
|
|
122413
|
+
log26.debug("startTunnel: already running, re-emitting URL");
|
|
122341
122414
|
if (tunnelUrl) {
|
|
122342
122415
|
emit({ kind: "tunnel-url", url: tunnelUrl });
|
|
122343
122416
|
}
|
|
@@ -133763,7 +133836,7 @@ function createContext8() {
|
|
|
133763
133836
|
|
|
133764
133837
|
// src/trpc/router.ts
|
|
133765
133838
|
init_src();
|
|
133766
|
-
import { execFile as
|
|
133839
|
+
import { execFile as execFile6, execFileSync as execFileSync2, spawn as spawn8 } from "node:child_process";
|
|
133767
133840
|
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
133768
133841
|
import {
|
|
133769
133842
|
existsSync as existsSync9,
|
|
@@ -133885,7 +133958,7 @@ function clearHistory(workspaceId, range, now = Date.now()) {
|
|
|
133885
133958
|
|
|
133886
133959
|
// src/lib/chat-session-summary.ts
|
|
133887
133960
|
init_src();
|
|
133888
|
-
var
|
|
133961
|
+
var log27 = createLogger("chat-session-summary");
|
|
133889
133962
|
var REFRESH_KEY = Symbol.for("band.chat-session-summary.refresh");
|
|
133890
133963
|
var g15 = globalThis;
|
|
133891
133964
|
if (!g15[REFRESH_KEY]) g15[REFRESH_KEY] = /* @__PURE__ */ new Map();
|
|
@@ -133907,7 +133980,7 @@ async function ensureActiveSessionSummary(chatId, worktreePath) {
|
|
|
133907
133980
|
}
|
|
133908
133981
|
return chat;
|
|
133909
133982
|
} catch (err) {
|
|
133910
|
-
|
|
133983
|
+
log27.warn({ chatId, err }, "ensureActiveSessionSummary failed");
|
|
133911
133984
|
return chat;
|
|
133912
133985
|
}
|
|
133913
133986
|
}
|
|
@@ -133934,7 +134007,56 @@ async function doRefresh(chatId, worktreePath) {
|
|
|
133934
134007
|
return;
|
|
133935
134008
|
}
|
|
133936
134009
|
} catch (err) {
|
|
133937
|
-
|
|
134010
|
+
log27.warn({ chatId, err }, "active session refresh failed");
|
|
134011
|
+
}
|
|
134012
|
+
}
|
|
134013
|
+
|
|
134014
|
+
// src/lib/disk-usage.ts
|
|
134015
|
+
import { execFile as execFile5 } from "node:child_process";
|
|
134016
|
+
var MAX_BUFFER2 = 10 * 1024 * 1024;
|
|
134017
|
+
var DU_TIMEOUT_MS = 3e4;
|
|
134018
|
+
var DU_GLOBAL_CONCURRENCY = 8;
|
|
134019
|
+
var inFlight = 0;
|
|
134020
|
+
var waiting = [];
|
|
134021
|
+
function acquireSlot() {
|
|
134022
|
+
return new Promise((resolve7) => {
|
|
134023
|
+
const grant = () => {
|
|
134024
|
+
inFlight++;
|
|
134025
|
+
resolve7(() => {
|
|
134026
|
+
inFlight--;
|
|
134027
|
+
const next = waiting.shift();
|
|
134028
|
+
if (next) next();
|
|
134029
|
+
});
|
|
134030
|
+
};
|
|
134031
|
+
if (inFlight < DU_GLOBAL_CONCURRENCY) grant();
|
|
134032
|
+
else waiting.push(grant);
|
|
134033
|
+
});
|
|
134034
|
+
}
|
|
134035
|
+
async function duBytes(path3) {
|
|
134036
|
+
const release = await acquireSlot();
|
|
134037
|
+
try {
|
|
134038
|
+
const stdout = await new Promise((resolve7, reject) => {
|
|
134039
|
+
execFile5(
|
|
134040
|
+
"du",
|
|
134041
|
+
["-sk", path3],
|
|
134042
|
+
{ maxBuffer: MAX_BUFFER2, timeout: DU_TIMEOUT_MS },
|
|
134043
|
+
(err, out) => {
|
|
134044
|
+
if (err && !out) {
|
|
134045
|
+
reject(err);
|
|
134046
|
+
return;
|
|
134047
|
+
}
|
|
134048
|
+
resolve7(out);
|
|
134049
|
+
}
|
|
134050
|
+
);
|
|
134051
|
+
});
|
|
134052
|
+
const kbStr = stdout.trim().split(/\s+/)[0];
|
|
134053
|
+
const kb2 = Number.parseInt(kbStr, 10);
|
|
134054
|
+
if (!Number.isFinite(kb2)) {
|
|
134055
|
+
throw new Error(`du output not numeric: ${JSON.stringify(stdout)}`);
|
|
134056
|
+
}
|
|
134057
|
+
return kb2 * 1024;
|
|
134058
|
+
} finally {
|
|
134059
|
+
release();
|
|
133938
134060
|
}
|
|
133939
134061
|
}
|
|
133940
134062
|
|
|
@@ -134035,7 +134157,7 @@ init_src();
|
|
|
134035
134157
|
import { existsSync as existsSync8, realpathSync as realpathSync4 } from "node:fs";
|
|
134036
134158
|
import { basename, dirname as dirname6, isAbsolute, join as join22, resolve as resolvePath } from "node:path";
|
|
134037
134159
|
import prettier from "prettier";
|
|
134038
|
-
var
|
|
134160
|
+
var log28 = createLogger("formatter");
|
|
134039
134161
|
var FormatterError = class extends Error {
|
|
134040
134162
|
code;
|
|
134041
134163
|
detail;
|
|
@@ -134090,7 +134212,7 @@ async function formatFile(worktreePath, filePath, content2, options2 = {}) {
|
|
|
134090
134212
|
}
|
|
134091
134213
|
const changed = formatted !== content2;
|
|
134092
134214
|
if (changed) {
|
|
134093
|
-
|
|
134215
|
+
log28.info(
|
|
134094
134216
|
"Formatted %s with parser=%s (%d bytes in)",
|
|
134095
134217
|
absFile,
|
|
134096
134218
|
info.inferredParser,
|
|
@@ -134229,7 +134351,7 @@ function fuzzyScore(query, filePath) {
|
|
|
134229
134351
|
// src/lib/terminal-config.ts
|
|
134230
134352
|
init_src();
|
|
134231
134353
|
init_zod();
|
|
134232
|
-
var
|
|
134354
|
+
var log29 = createLogger("terminal-config");
|
|
134233
134355
|
var TerminalPaneConfigSchema = external_exports.object({
|
|
134234
134356
|
name: external_exports.string().optional(),
|
|
134235
134357
|
command: external_exports.string().optional(),
|
|
@@ -134260,7 +134382,7 @@ function loadWorkspaceTerminalConfig(worktreePath, projectPath) {
|
|
|
134260
134382
|
if (!terminalBlock) return null;
|
|
134261
134383
|
const result = WorkspaceTerminalConfigSchema.safeParse(terminalBlock);
|
|
134262
134384
|
if (!result.success) {
|
|
134263
|
-
|
|
134385
|
+
log29.warn(
|
|
134264
134386
|
"Invalid workspace.terminal config: %s",
|
|
134265
134387
|
result.error.issues.map((i2) => `${i2.path.join(".")}: ${i2.message}`).join("; ")
|
|
134266
134388
|
);
|
|
@@ -134270,8 +134392,8 @@ function loadWorkspaceTerminalConfig(worktreePath, projectPath) {
|
|
|
134270
134392
|
}
|
|
134271
134393
|
|
|
134272
134394
|
// src/trpc/router.ts
|
|
134273
|
-
var execFileAsync = promisify(
|
|
134274
|
-
var
|
|
134395
|
+
var execFileAsync = promisify(execFile6);
|
|
134396
|
+
var log30 = createLogger("trpc");
|
|
134275
134397
|
var t2 = initTRPC.context().create();
|
|
134276
134398
|
var publicProcedure = t2.procedure;
|
|
134277
134399
|
var projectsRouter = t2.router({
|
|
@@ -134381,7 +134503,14 @@ var projectsRouter = t2.router({
|
|
|
134381
134503
|
defaultBranch,
|
|
134382
134504
|
worktrees: worktrees2,
|
|
134383
134505
|
label: input.label ?? void 0,
|
|
134384
|
-
kind
|
|
134506
|
+
kind,
|
|
134507
|
+
// For git projects, default to `true` so the first CI poll
|
|
134508
|
+
// still runs the GraphQL query — `syncWorktrees` writes the
|
|
134509
|
+
// real value on the next tick. For plain projects there's no
|
|
134510
|
+
// remote by construction, so set `false` directly: sync skips
|
|
134511
|
+
// plain projects (`kind !== "plain"` filter), so this initial
|
|
134512
|
+
// value sticks for the lifetime of the row. See issue #458.
|
|
134513
|
+
hasOrigin: kind === "git"
|
|
134385
134514
|
};
|
|
134386
134515
|
state2.projects.push(project);
|
|
134387
134516
|
saveState(state2);
|
|
@@ -134572,13 +134701,13 @@ var workspacesRouter = t2.router({
|
|
|
134572
134701
|
try {
|
|
134573
134702
|
const deletedTasks = deleteWorkspaceTasks(workspaceId);
|
|
134574
134703
|
if (deletedTasks > 0) {
|
|
134575
|
-
|
|
134704
|
+
log30.info(
|
|
134576
134705
|
{ workspaceId, count: deletedTasks },
|
|
134577
134706
|
"deleted workspace tasks on removal"
|
|
134578
134707
|
);
|
|
134579
134708
|
}
|
|
134580
134709
|
} catch (err) {
|
|
134581
|
-
|
|
134710
|
+
log30.error({ workspaceId, err }, "failed to delete workspace tasks on removal");
|
|
134582
134711
|
}
|
|
134583
134712
|
emit({ kind: "remove", workspaceId });
|
|
134584
134713
|
const projPath = proj.path;
|
|
@@ -134596,7 +134725,7 @@ var workspacesRouter = t2.router({
|
|
|
134596
134725
|
timeout: 6e4
|
|
134597
134726
|
});
|
|
134598
134727
|
} catch (err) {
|
|
134599
|
-
|
|
134728
|
+
log30.warn({ err, workspaceId }, "teardown script failed");
|
|
134600
134729
|
}
|
|
134601
134730
|
}
|
|
134602
134731
|
try {
|
|
@@ -134614,7 +134743,7 @@ var workspacesRouter = t2.router({
|
|
|
134614
134743
|
encoding: "utf-8"
|
|
134615
134744
|
});
|
|
134616
134745
|
} catch (err) {
|
|
134617
|
-
|
|
134746
|
+
log30.warn({ err, workspaceId }, "git worktree prune failed");
|
|
134618
134747
|
}
|
|
134619
134748
|
}
|
|
134620
134749
|
try {
|
|
@@ -134626,7 +134755,7 @@ var workspacesRouter = t2.router({
|
|
|
134626
134755
|
} catch {
|
|
134627
134756
|
}
|
|
134628
134757
|
})().catch((err) => {
|
|
134629
|
-
|
|
134758
|
+
log30.error({ err, workspaceId }, "background workspace cleanup failed");
|
|
134630
134759
|
});
|
|
134631
134760
|
});
|
|
134632
134761
|
return { ok: true };
|
|
@@ -134707,7 +134836,7 @@ var workspacesRouter = t2.router({
|
|
|
134707
134836
|
throw new Error(`Script "${input.scriptType}" not found`);
|
|
134708
134837
|
}
|
|
134709
134838
|
return new Promise((resolve7, reject) => {
|
|
134710
|
-
|
|
134839
|
+
execFile6("bash", [scriptPath], { cwd: input.path }, (err) => {
|
|
134711
134840
|
if (err) {
|
|
134712
134841
|
reject(new Error(err.message));
|
|
134713
134842
|
} else {
|
|
@@ -134978,7 +135107,7 @@ var workspaceRouter = t2.router({
|
|
|
134978
135107
|
);
|
|
134979
135108
|
branches = output.trim().split("\n").map((b10) => b10.trim()).filter(Boolean);
|
|
134980
135109
|
} catch (err) {
|
|
134981
|
-
|
|
135110
|
+
log30.error(
|
|
134982
135111
|
`listBranches: for-each-ref failed for ${cwd}: ${err instanceof Error ? err.message : err}`
|
|
134983
135112
|
);
|
|
134984
135113
|
}
|
|
@@ -135838,21 +135967,21 @@ var tunnelRouter = t2.router({
|
|
|
135838
135967
|
return getTunnelStatus();
|
|
135839
135968
|
}),
|
|
135840
135969
|
start: publicProcedure.input(external_exports.object({}).optional()).mutation(async () => {
|
|
135841
|
-
|
|
135970
|
+
log30.debug("tunnel.start called");
|
|
135842
135971
|
const port = parseInt(process.env.BAND_PORT || "3456", 10);
|
|
135843
|
-
|
|
135972
|
+
log30.debug("tunnel.start: port=%d", port);
|
|
135844
135973
|
try {
|
|
135845
135974
|
await startTunnel({ port });
|
|
135846
135975
|
} catch (err) {
|
|
135847
|
-
|
|
135976
|
+
log30.debug({ err }, "tunnel.start: startTunnel failed");
|
|
135848
135977
|
return { ok: true, url: null };
|
|
135849
135978
|
}
|
|
135850
135979
|
const status = getTunnelStatus();
|
|
135851
|
-
|
|
135980
|
+
log30.debug({ status }, "tunnel.start: after startTunnel");
|
|
135852
135981
|
if (status.url) {
|
|
135853
135982
|
return { ok: true, url: status.url };
|
|
135854
135983
|
}
|
|
135855
|
-
|
|
135984
|
+
log30.debug("tunnel.start: no URL available");
|
|
135856
135985
|
return { ok: true, url: null };
|
|
135857
135986
|
}),
|
|
135858
135987
|
stop: publicProcedure.mutation(async () => {
|
|
@@ -135867,7 +135996,7 @@ var prereqsRouter = t2.router({
|
|
|
135867
135996
|
installTunnel: publicProcedure.mutation(async () => {
|
|
135868
135997
|
const resolvedPath = await shellPath();
|
|
135869
135998
|
await new Promise((resolve7, reject) => {
|
|
135870
|
-
|
|
135999
|
+
execFile6(
|
|
135871
136000
|
"brew",
|
|
135872
136001
|
["install", "cloudflared"],
|
|
135873
136002
|
{ env: { ...process.env, PATH: resolvedPath }, timeout: 12e4 },
|
|
@@ -136071,15 +136200,15 @@ var sessionsRouter = t2.router({
|
|
|
136071
136200
|
});
|
|
136072
136201
|
var servicesRouter = t2.router({
|
|
136073
136202
|
health: publicProcedure.query(() => {
|
|
136074
|
-
|
|
136203
|
+
log30.debug("services.health called");
|
|
136075
136204
|
const tunnel = getTunnelStatus();
|
|
136076
|
-
|
|
136205
|
+
log30.debug({ tunnel }, "services.health: tunnel status");
|
|
136077
136206
|
const result = {
|
|
136078
136207
|
webserver: true,
|
|
136079
136208
|
tunnel: tunnel.running,
|
|
136080
136209
|
tunnel_url: tunnel.url
|
|
136081
136210
|
};
|
|
136082
|
-
|
|
136211
|
+
log30.debug({ result }, "services.health result");
|
|
136083
136212
|
return result;
|
|
136084
136213
|
}),
|
|
136085
136214
|
// Activity level controls how often the branch-status poller fires.
|
|
@@ -136089,7 +136218,124 @@ var servicesRouter = t2.router({
|
|
|
136089
136218
|
setPollerActivity(input.activity);
|
|
136090
136219
|
return { activity: input.activity };
|
|
136091
136220
|
}),
|
|
136092
|
-
getActivity: publicProcedure.query(() => ({ activity: getPollerActivity() }))
|
|
136221
|
+
getActivity: publicProcedure.query(() => ({ activity: getPollerActivity() })),
|
|
136222
|
+
// Resources dashboard — server CPU/memory snapshot (cheap, instant).
|
|
136223
|
+
// `process.cpuUsage()` is cumulative since process start; the UI labels
|
|
136224
|
+
// it "Total CPU time" so callers don't read it as instantaneous load.
|
|
136225
|
+
resourcesServer: publicProcedure.query(() => {
|
|
136226
|
+
const mem = process.memoryUsage();
|
|
136227
|
+
const cpu = process.cpuUsage();
|
|
136228
|
+
return {
|
|
136229
|
+
pid: process.pid,
|
|
136230
|
+
uptimeSeconds: process.uptime(),
|
|
136231
|
+
nodeVersion: process.version,
|
|
136232
|
+
platform: process.platform,
|
|
136233
|
+
arch: process.arch,
|
|
136234
|
+
memory: {
|
|
136235
|
+
rssBytes: mem.rss,
|
|
136236
|
+
heapTotalBytes: mem.heapTotal,
|
|
136237
|
+
heapUsedBytes: mem.heapUsed,
|
|
136238
|
+
externalBytes: mem.external,
|
|
136239
|
+
arrayBuffersBytes: mem.arrayBuffers
|
|
136240
|
+
},
|
|
136241
|
+
cpu: {
|
|
136242
|
+
userMicros: cpu.user,
|
|
136243
|
+
systemMicros: cpu.system
|
|
136244
|
+
}
|
|
136245
|
+
};
|
|
136246
|
+
}),
|
|
136247
|
+
// Resources dashboard — list every tracked git project + its
|
|
136248
|
+
// worktree paths *without* doing any disk walks. Instant: just
|
|
136249
|
+
// reads state + a single `git worktree list --porcelain` per
|
|
136250
|
+
// project (in parallel). The client uses this to paint rows
|
|
136251
|
+
// immediately, then fetches each project's size individually
|
|
136252
|
+
// via `resourcesProjectSize` so the slow `du` work is amortised
|
|
136253
|
+
// and observable per-row.
|
|
136254
|
+
resourcesProjects: publicProcedure.query(async () => {
|
|
136255
|
+
const state2 = loadState();
|
|
136256
|
+
const projects2 = await Promise.all(
|
|
136257
|
+
state2.projects.filter((p6) => p6.kind === "git").map(async (project) => {
|
|
136258
|
+
try {
|
|
136259
|
+
const list2 = await listWorktrees(project.path);
|
|
136260
|
+
const worktrees2 = list2.filter((wt) => !wt.isBare).map((wt) => ({
|
|
136261
|
+
// Detached HEAD (mid-rebase, mid-bisect, or
|
|
136262
|
+
// explicit `git checkout <sha>`) produces an empty
|
|
136263
|
+
// branch string. Keep the row with a sentinel
|
|
136264
|
+
// label so the size still gets counted — silently
|
|
136265
|
+
// dropping it would make a developer's largest
|
|
136266
|
+
// worktree disappear from the accounting whenever
|
|
136267
|
+
// they happened to be on a detached HEAD.
|
|
136268
|
+
branch: wt.branch || "(detached HEAD)",
|
|
136269
|
+
path: wt.path
|
|
136270
|
+
}));
|
|
136271
|
+
return {
|
|
136272
|
+
project: project.name,
|
|
136273
|
+
path: project.path,
|
|
136274
|
+
worktrees: worktrees2,
|
|
136275
|
+
error: void 0
|
|
136276
|
+
};
|
|
136277
|
+
} catch (err) {
|
|
136278
|
+
return {
|
|
136279
|
+
project: project.name,
|
|
136280
|
+
path: project.path,
|
|
136281
|
+
worktrees: [],
|
|
136282
|
+
error: err instanceof Error ? err.message : String(err)
|
|
136283
|
+
};
|
|
136284
|
+
}
|
|
136285
|
+
})
|
|
136286
|
+
);
|
|
136287
|
+
return { projects: projects2 };
|
|
136288
|
+
}),
|
|
136289
|
+
// Resources dashboard — measure disk usage for a single project.
|
|
136290
|
+
//
|
|
136291
|
+
// Slow: runs `du -sk` once per worktree, in parallel via
|
|
136292
|
+
// Promise.all. The client fan-outs are concurrency-limited so the
|
|
136293
|
+
// server doesn't see a thundering herd of `du` processes from a
|
|
136294
|
+
// single page open. Per-worktree errors are absorbed into the
|
|
136295
|
+
// response (sizeBytes 0, `error` populated) so a single broken
|
|
136296
|
+
// worktree doesn't fail the whole query.
|
|
136297
|
+
resourcesProjectSize: publicProcedure.input(external_exports.object({ project: external_exports.string() })).query(async ({ input }) => {
|
|
136298
|
+
const state2 = loadState();
|
|
136299
|
+
const project = state2.projects.find((p6) => p6.name === input.project && p6.kind === "git");
|
|
136300
|
+
if (!project) {
|
|
136301
|
+
throw new TRPCError({ code: "NOT_FOUND", message: "Project not found" });
|
|
136302
|
+
}
|
|
136303
|
+
let worktreePaths;
|
|
136304
|
+
try {
|
|
136305
|
+
const list2 = await listWorktrees(project.path);
|
|
136306
|
+
worktreePaths = list2.filter((wt) => !wt.isBare).map((wt) => ({
|
|
136307
|
+
// See `resourcesProjects` above — detached HEAD gets a
|
|
136308
|
+
// sentinel label rather than being dropped.
|
|
136309
|
+
branch: wt.branch || "(detached HEAD)",
|
|
136310
|
+
path: wt.path
|
|
136311
|
+
}));
|
|
136312
|
+
} catch (err) {
|
|
136313
|
+
return {
|
|
136314
|
+
project: project.name,
|
|
136315
|
+
sizeBytes: 0,
|
|
136316
|
+
worktrees: [],
|
|
136317
|
+
error: err instanceof Error ? err.message : String(err)
|
|
136318
|
+
};
|
|
136319
|
+
}
|
|
136320
|
+
const worktrees2 = await Promise.all(
|
|
136321
|
+
worktreePaths.map(async (wt) => {
|
|
136322
|
+
try {
|
|
136323
|
+
const sizeBytes2 = await duBytes(wt.path);
|
|
136324
|
+
return { branch: wt.branch, path: wt.path, sizeBytes: sizeBytes2 };
|
|
136325
|
+
} catch (err) {
|
|
136326
|
+
return {
|
|
136327
|
+
branch: wt.branch,
|
|
136328
|
+
path: wt.path,
|
|
136329
|
+
sizeBytes: 0,
|
|
136330
|
+
error: err instanceof Error ? err.message : String(err)
|
|
136331
|
+
};
|
|
136332
|
+
}
|
|
136333
|
+
})
|
|
136334
|
+
);
|
|
136335
|
+
worktrees2.sort((a6, b10) => b10.sizeBytes - a6.sizeBytes);
|
|
136336
|
+
const sizeBytes = worktrees2.reduce((sum, wt) => sum + wt.sizeBytes, 0);
|
|
136337
|
+
return { project: project.name, sizeBytes, worktrees: worktrees2 };
|
|
136338
|
+
})
|
|
136093
136339
|
});
|
|
136094
136340
|
function canonicalizeMaybeMissing(p6) {
|
|
136095
136341
|
if (existsSync9(p6)) {
|
|
@@ -136132,11 +136378,12 @@ var editorRouter = t2.router({
|
|
|
136132
136378
|
/**
|
|
136133
136379
|
* Either an absolute filesystem path or a workspace-relative
|
|
136134
136380
|
* path. Paths inside the workspace root open as normal editor
|
|
136135
|
-
* tabs (
|
|
136136
|
-
*
|
|
136137
|
-
*
|
|
136138
|
-
*
|
|
136139
|
-
*
|
|
136381
|
+
* tabs (the renderer routes to the Files panel via the
|
|
136382
|
+
* `open-file` SSE event; see `dispatchOpenFileEvent`); paths
|
|
136383
|
+
* outside any workspace root open as external tabs (same
|
|
136384
|
+
* surface as desktop Cmd+O / "Open File…"). May include a
|
|
136385
|
+
* trailing line / column suffix in the standard
|
|
136386
|
+
* `path:line[:column]` / `path:line-lineEnd` notation.
|
|
136140
136387
|
*/
|
|
136141
136388
|
filePath: external_exports.string().min(1),
|
|
136142
136389
|
line: external_exports.number().int().positive().optional(),
|
|
@@ -136609,7 +136856,7 @@ var chatsRouter = t2.router({
|
|
|
136609
136856
|
summary = info?.summary;
|
|
136610
136857
|
lastModified = info?.lastModified;
|
|
136611
136858
|
} catch (err) {
|
|
136612
|
-
|
|
136859
|
+
log30.warn(
|
|
136613
136860
|
{ chatId: input.chatId, sessionId: input.sessionId, err },
|
|
136614
136861
|
"setActiveSession: getSessionInfo failed"
|
|
136615
136862
|
);
|
|
@@ -136729,7 +136976,7 @@ var browserHostRouter = t2.router({
|
|
|
136729
136976
|
// can confirm in the server log that the bridge component actually
|
|
136730
136977
|
// executed. Drop once the experiment is stable.
|
|
136731
136978
|
ping: publicProcedure.input(external_exports.object({ where: external_exports.string() })).mutation(({ input }) => {
|
|
136732
|
-
|
|
136979
|
+
log30.info("browserHost.ping from %s", input.where);
|
|
136733
136980
|
return { ok: true };
|
|
136734
136981
|
}),
|
|
136735
136982
|
ensureView: publicProcedure.subscription(async function* (opts) {
|
|
@@ -136883,7 +137130,7 @@ async function resolveQueuedFiles(chatId, files) {
|
|
|
136883
137130
|
const derivedPath = file.path ?? (uploadsUrlMatch ? join23(bandHome(), "uploads", uploadsUrlMatch[1]) : void 0);
|
|
136884
137131
|
if (derivedPath) {
|
|
136885
137132
|
if (!isPathWithinUploadDir(derivedPath)) {
|
|
136886
|
-
|
|
137133
|
+
log30.warn(
|
|
136887
137134
|
{ chatId, path: derivedPath, filename: file.filename },
|
|
136888
137135
|
"queue: dropping file with path outside uploads directory"
|
|
136889
137136
|
);
|
|
@@ -136908,7 +137155,7 @@ async function resolveQueuedFiles(chatId, files) {
|
|
|
136908
137155
|
});
|
|
136909
137156
|
continue;
|
|
136910
137157
|
}
|
|
136911
|
-
|
|
137158
|
+
log30.warn(
|
|
136912
137159
|
{ chatId, url: file.url, filename: file.filename },
|
|
136913
137160
|
"queue: dropping file with no path and non-data URL \u2014 cannot recover disk path"
|
|
136914
137161
|
);
|
|
@@ -136916,7 +137163,7 @@ async function resolveQueuedFiles(chatId, files) {
|
|
|
136916
137163
|
if (needsSave.length > 0) {
|
|
136917
137164
|
const saved = await saveUploadedFilesDetailed(needsSave);
|
|
136918
137165
|
if (saved.length !== needsSave.length) {
|
|
136919
|
-
|
|
137166
|
+
log30.error(
|
|
136920
137167
|
{ chatId, expected: needsSave.length, got: saved.length },
|
|
136921
137168
|
"queue: saveUploadedFilesDetailed returned unexpected count \u2014 dropping data-URL files (cannot map 1:1)"
|
|
136922
137169
|
);
|
|
@@ -136949,7 +137196,7 @@ var queueRouter = t2.router({
|
|
|
136949
137196
|
try {
|
|
136950
137197
|
files = await resolveQueuedFiles(chatId, input.files);
|
|
136951
137198
|
} catch (err) {
|
|
136952
|
-
|
|
137199
|
+
log30.error(
|
|
136953
137200
|
{ chatId, err: err instanceof Error ? err.message : err },
|
|
136954
137201
|
"queue.push: failed to persist file uploads; enqueuing text only"
|
|
136955
137202
|
);
|
|
@@ -136985,7 +137232,7 @@ var queueRouter = t2.router({
|
|
|
136985
137232
|
files: await resolveQueuedFiles(chatId, m11.files)
|
|
136986
137233
|
};
|
|
136987
137234
|
} catch (err) {
|
|
136988
|
-
|
|
137235
|
+
log30.error(
|
|
136989
137236
|
{ chatId, messageId: m11.id, err: err instanceof Error ? err.message : err },
|
|
136990
137237
|
"queue: failed to resolve files for queued message; dropping its files"
|
|
136991
137238
|
);
|