@band-app/server 0.16.8 → 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-Ct-e0Qqq.js +1 -0
- package/dist/client/assets/_baseUniq-CxKOXF1k.js +1 -0
- 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-BKiU7fF0.js → blockDiagram-VD42YOAC-CsuIx-c9.js} +5 -5
- package/dist/client/assets/{c4Diagram-YG6GDRKO-CYISxlyF.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-DltWViHS.js → chunk-B4BG7PRW-DKCONMEK.js} +6 -6
- package/dist/client/assets/{chunk-DI55MBZ5-51JXB972.js → chunk-DI55MBZ5-D5zzjeE8.js} +1 -1
- package/dist/client/assets/{chunk-FMBD7UC4-CynepQnx.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-DZUjamhk.js → erDiagram-Q2GNP2WA-D-EqIR9o.js} +4 -4
- package/dist/client/assets/{flowDiagram-NV44I4VS-oIHer-h-.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-r-V7AF54.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-DAMgQMyn.js → index-BCbe81ki.js} +2 -2
- package/dist/client/assets/index-BOdifnXB.js +1 -0
- package/dist/client/assets/{index-W1CPMGYX.js → index-BQW7Zpk7.js} +1 -1
- package/dist/client/assets/index-BX_7-t5E.js +1 -0
- package/dist/client/assets/{index-u_2V_RF4.js → index-BktK8Iwc.js} +1 -1
- package/dist/client/assets/{index-DQixQE5Y.js → index-BtEs1oEp.js} +1 -1
- package/dist/client/assets/{index-CdJ3WH3f.js → index-BtajlvkF.js} +1 -1
- package/dist/client/assets/{index-NMjGSNmU.js → index-Bx3rRbZG.js} +1 -1
- package/dist/client/assets/{index-DhTLiwux.js → index-C6MgAn1q.js} +1 -1
- package/dist/client/assets/{index-foc9a7eE.js → index-CzCjpAqZ.js} +5 -5
- package/dist/client/assets/{index-CFEu-Cf9.js → index-DQAckahj.js} +1 -1
- package/dist/client/assets/index-DaRnNd02.js +7 -0
- package/dist/client/assets/{index-CYvgC-U1.js → index-Im7rGMYn.js} +1 -1
- package/dist/client/assets/{index-BvWkKnfY.js → index-WmGuuT8Z.js} +1 -1
- package/dist/client/assets/{index-BiUUT09K.js → index-aTt3zXBv.js} +1 -1
- package/dist/client/assets/{index-BDQWeqNk.js → index-nPplcWzt.js} +1 -1
- package/dist/client/assets/{index-y0IIofTa.js → index-vaGaAlmP.js} +1 -1
- package/dist/client/assets/infoDiagram-HS3SLOUP-Dp2iuUeA.js +2 -0
- package/dist/client/assets/{journeyDiagram-XKPGCS4Q-E4OGYZo3.js → journeyDiagram-XKPGCS4Q-BaVzrE3V.js} +3 -3
- package/dist/client/assets/{kanban-definition-3W4ZIXB7-DDOW42i6.js → kanban-definition-3W4ZIXB7-DdbWsnm7.js} +8 -8
- package/dist/client/assets/{layout-BU7n9QQq.js → layout-vxWf40Ht.js} +1 -1
- package/dist/client/assets/{linear-CFFUeqRn.js → linear-BstrgKy8.js} +1 -1
- package/dist/client/assets/{main-onb8WwfN.js → main-DRq9Axai.js} +231 -234
- package/dist/client/assets/main-evBJruhw.css +1 -0
- package/dist/client/assets/{mindmap-definition-VGOIOE7T-BQlhTP7t.js → mindmap-definition-VGOIOE7T-CAEEMYhK.js} +3 -3
- package/dist/client/assets/pieDiagram-ADFJNKIX-DCNv4UlO.js +30 -0
- package/dist/client/assets/{quadrantDiagram-AYHSOK5B-D7D_64Ur.js → quadrantDiagram-AYHSOK5B-BeP4t0hp.js} +2 -2
- package/dist/client/assets/{requirementDiagram-UZGBJVZJ-Dd-Qxkau.js → requirementDiagram-UZGBJVZJ-CAdiLb_M.js} +2 -2
- package/dist/client/assets/sankeyDiagram-TZEHDZUN-DW9xKT5Y.js +10 -0
- package/dist/client/assets/{sequenceDiagram-WL72ISMW-UH13bSlf.js → sequenceDiagram-WL72ISMW-D9y8fK_R.js} +1 -1
- package/dist/client/assets/{square-terminal-BgnPkQhG.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-DoLvii7e.js → timeline-definition-IT6M3QCI-Ci_SXZdO.js} +4 -4
- package/dist/client/assets/{treemap-GDKQZRPO-C6cooeby.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-DjUMVf0W.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 +431 -16
- package/dist/server/assets/DockviewBrowserContainer-BAe7TLKD.js +1954 -0
- package/dist/server/assets/{DockviewTerminalContainer-Dl-H-7q5.js → DockviewTerminalContainer-CC7i0yMZ.js} +73 -24
- package/dist/server/assets/{TerminalPanel-Nx4CmvlW.js → TerminalPanel-gBh8VBn0.js} +1 -1
- package/dist/server/assets/{_basePickBy-BG2OhlJc.js → _basePickBy-CTks6QXq.js} +2 -2
- package/dist/server/assets/{_baseUniq-DB6mvOCI.js → _baseUniq-BJI4qneQ.js} +1 -1
- package/dist/server/assets/_tanstack-start-manifest_v-CfuSyuIp.js +4 -0
- package/dist/server/assets/{arc-DaVwrLrM.js → arc-Fdc_l0PB.js} +1 -1
- package/dist/server/assets/{architecture-7HQA4BMR-DIi4TM4E.js → architecture-7HQA4BMR-CfPXboDr.js} +6 -6
- package/dist/server/assets/{architectureDiagram-VXUJARFQ-DBRmPh1t.js → architectureDiagram-VXUJARFQ-D6UEkzy_.js} +6 -6
- package/dist/server/assets/{blockDiagram-VD42YOAC-CFdPLnD-.js → blockDiagram-VD42YOAC-BvasIENt.js} +6 -6
- package/dist/server/assets/{c4Diagram-YG6GDRKO-BJi6gbIt.js → c4Diagram-YG6GDRKO-MW5H9zoJ.js} +2 -2
- package/dist/server/assets/{channel-DkntTxx0.js → channel-XhTiPor2.js} +1 -1
- package/dist/server/assets/{chunk-4BX2VUAB-D2FiW3aP.js → chunk-4BX2VUAB-C6POw9HJ.js} +1 -1
- package/dist/server/assets/{chunk-55IACEB6-jZmh1Z5I.js → chunk-55IACEB6-BZ0x-UQb.js} +1 -1
- package/dist/server/assets/{chunk-B4BG7PRW-CNZgnxgA.js → chunk-B4BG7PRW-BAYqNQHL.js} +4 -4
- package/dist/server/assets/{chunk-DI55MBZ5-q0pODS0a.js → chunk-DI55MBZ5-DbsR50vR.js} +3 -3
- package/dist/server/assets/{chunk-FMBD7UC4-C96aN_Us.js → chunk-FMBD7UC4-D_KXTL87.js} +1 -1
- package/dist/server/assets/{chunk-QN33PNHL-Dam5gy0m.js → chunk-QN33PNHL-RXXHu7T0.js} +1 -1
- package/dist/server/assets/{chunk-QZHKN3VN-CXCmBbbu.js → chunk-QZHKN3VN-5QE6weTd.js} +1 -1
- package/dist/server/assets/{chunk-TZMSLE5B-CbK3gIHb.js → chunk-TZMSLE5B-HlRXkCDZ.js} +1 -1
- package/dist/server/assets/{classDiagram-v2-WZHVMYZB-BHB2vhDs.js → classDiagram-2ON5EDUG-B90fR_EV.js} +5 -5
- package/dist/server/assets/{classDiagram-2ON5EDUG-BHB2vhDs.js → classDiagram-v2-WZHVMYZB-B90fR_EV.js} +5 -5
- package/dist/server/assets/{clone-CN5lfg2Z.js → clone-Bjcb6OQr.js} +1 -1
- package/dist/server/assets/{cose-bilkent-S5V4N54A-Bq-O80sc.js → cose-bilkent-S5V4N54A-BgnWrjAl.js} +1 -1
- package/dist/server/assets/{dagre-6UL2VRFP-U80sNC8f.js → dagre-6UL2VRFP-LfRXD26Q.js} +6 -6
- package/dist/server/assets/{diagram-PSM6KHXK-5ksUDb2Z.js → diagram-PSM6KHXK-DLrJ9Eja.js} +7 -7
- package/dist/server/assets/{diagram-QEK2KX5R-COmUOoRU.js → diagram-QEK2KX5R-atbHIh96.js} +6 -6
- package/dist/server/assets/{diagram-S2PKOQOG-BOTznhFu.js → diagram-S2PKOQOG-BnxctnIJ.js} +6 -6
- package/dist/server/assets/{erDiagram-Q2GNP2WA-CZOlCzBi.js → erDiagram-Q2GNP2WA-Ct1zXovC.js} +4 -4
- package/dist/server/assets/{flowDiagram-NV44I4VS-ObYcdqyZ.js → flowDiagram-NV44I4VS-DtWHb6Ay.js} +5 -5
- package/dist/server/assets/{ganttDiagram-JELNMOA3-6c9A3Tfv.js → ganttDiagram-JELNMOA3-CySyldy4.js} +2 -2
- package/dist/server/assets/{gitGraph-G5XIXVHT-Q_zXZbiJ.js → gitGraph-G5XIXVHT-DFo7FJzL.js} +6 -6
- package/dist/server/assets/{gitGraphDiagram-V2S2FVAM-C-GqaejI.js → gitGraphDiagram-V2S2FVAM-DvT5EUG7.js} +7 -7
- package/dist/server/assets/{graph-CGXsNa6T.js → graph-B5XlkLf_.js} +2 -2
- package/dist/server/assets/{highlighted-body-B3W2YXNL-CjyCfwez.js → highlighted-body-B3W2YXNL-CLJWhRU_.js} +1 -1
- package/dist/server/assets/{index-C-7vS9m8.js → index--4MijjkY.js} +2 -2
- package/dist/server/assets/{index-DKtCHZcS.js → index-4SOjxyuO.js} +2 -2
- package/dist/server/assets/{index-CAfRymUE.js → index-BQ5LDgRA.js} +3 -3
- package/dist/server/assets/{index-DU_XVqOC.js → index-BanzNq86.js} +1 -1
- package/dist/server/assets/{index-BaYLnq50.js → index-BvJzvUfR.js} +2 -2
- package/dist/server/assets/{index-DIahp6rS.js → index-C2GzB22l.js} +2 -2
- package/dist/server/assets/{index-B3U9PRLr.js → index-CAJcSCqE.js} +2 -2
- package/dist/server/assets/{index-BBvVnzgd.js → index-CLUle2oh.js} +5 -5
- package/dist/server/assets/{index-C0kihLnk.js → index-CMO4FLK_.js} +2 -2
- package/dist/server/assets/{index-DIdSfU9-.js → index-CXMNOcuN.js} +1 -1
- package/dist/server/assets/{index-73YfcfUk.js → index-CXmMBSCL.js} +2 -2
- package/dist/server/assets/{index-C71uG8NB.js → index-CdgmRfZg.js} +2 -2
- package/dist/server/assets/{index-BfyUYDbk.js → index-DJ8A5E65.js} +5 -5
- package/dist/server/assets/{index-CxSyZwen.js → index-DjySh3G7.js} +3 -3
- package/dist/server/assets/{index-D_0vKELK.js → index-DuXjusjn.js} +2 -2
- package/dist/server/assets/{index-DejplVdQ.js → index-QiPzMfSX.js} +2 -2
- package/dist/server/assets/{index-DnWmaxai.js → index-SuLB6TaE.js} +2 -2
- package/dist/server/assets/{index-ukALXr65.js → index-bmq-aMYV.js} +4 -4
- package/dist/server/assets/{info-VBDWY6EO-BsWgc-Ym.js → info-VBDWY6EO-CW57QiJi.js} +6 -6
- package/dist/server/assets/{infoDiagram-HS3SLOUP-C04udjz-.js → infoDiagram-HS3SLOUP-D_Zdx-MM.js} +5 -5
- package/dist/server/assets/{journeyDiagram-XKPGCS4Q-D3MBfJwF.js → journeyDiagram-XKPGCS4Q-BcO9qzr2.js} +4 -4
- package/dist/server/assets/{kanban-definition-3W4ZIXB7-Czuz4I_Q.js → kanban-definition-3W4ZIXB7-BatZ7RKG.js} +2 -2
- package/dist/server/assets/{layout-D6n2z2ff.js → layout-Cwuj9CwZ.js} +4 -4
- package/dist/server/assets/{linear-BDP9KC1O.js → linear-CP3xC85V.js} +1 -1
- package/dist/server/assets/{mermaid-3ZIDBTTL-oS_2f_Id.js → mermaid-3ZIDBTTL-BZm8jQDo.js} +1 -1
- package/dist/server/assets/{mermaid-parser.core-DRwka5gl.js → mermaid-parser.core-Cx17C8XR.js} +11 -11
- package/dist/server/assets/{mindmap-definition-VGOIOE7T-BPhhfr5z.js → mindmap-definition-VGOIOE7T-CpzqFomk.js} +3 -3
- package/dist/server/assets/{packet-DYOGHKS2-XJIQk327.js → packet-DYOGHKS2-x3ihoqUO.js} +6 -6
- package/dist/server/assets/{pie-VRWISCQL-BEbH9jgO.js → pie-VRWISCQL-DsMBDe8r.js} +6 -6
- package/dist/server/assets/{pieDiagram-ADFJNKIX-oLEFnRFT.js → pieDiagram-ADFJNKIX-DI4Hh6KE.js} +7 -7
- package/dist/server/assets/{quadrantDiagram-AYHSOK5B-nsrtyikJ.js → quadrantDiagram-AYHSOK5B-Cqc_vrUG.js} +2 -2
- package/dist/server/assets/{radar-ZZBFDIW7-XJaR0sVv.js → radar-ZZBFDIW7-CqwCJm3D.js} +6 -6
- package/dist/server/assets/{requirementDiagram-UZGBJVZJ-CHkWIv3O.js → requirementDiagram-UZGBJVZJ-96ab-40P.js} +3 -3
- package/dist/server/assets/{router-DqGeMR0F.js → router-CYNdQEN4.js} +1384 -2657
- package/dist/server/assets/{sankeyDiagram-TZEHDZUN-XynupQoy.js → sankeyDiagram-TZEHDZUN-Bux2-BQd.js} +1 -1
- package/dist/server/assets/{sequenceDiagram-WL72ISMW-Cnkmy2xq.js → sequenceDiagram-WL72ISMW-CFKyfvmC.js} +3 -3
- package/dist/server/assets/{square-terminal-D7AxF9nB.js → square-terminal-gVSeBp7-.js} +1 -1
- package/dist/server/assets/{stateDiagram-FKZM4ZOC-Chk4nsf_.js → stateDiagram-FKZM4ZOC-DGZQd18J.js} +8 -8
- package/dist/server/assets/{stateDiagram-v2-4FDKWEC3-DNIM2ODr.js → stateDiagram-v2-4FDKWEC3-DJXeLDOB.js} +4 -4
- package/dist/server/assets/{timeline-definition-IT6M3QCI-Fz2nlxYj.js → timeline-definition-IT6M3QCI-DzTJZPN5.js} +2 -2
- package/dist/server/assets/{treemap-GDKQZRPO-DNxd_7q0.js → treemap-GDKQZRPO-CD9jkQrA.js} +6 -6
- package/dist/server/assets/workspace._workspaceId-ClAAZ5aq.js +23 -0
- package/dist/server/assets/{workspace._workspaceId-KoR0msx0.js → workspace._workspaceId-DT6Kz8RH.js} +125 -97
- package/dist/server/assets/{xychartDiagram-PRI3JC2R-DtoxEUbW.js → xychartDiagram-PRI3JC2R-ByA0_p8p.js} +2 -2
- package/dist/server/server.js +2 -2
- package/dist/start-server.mjs +694 -297
- package/package.json +4 -4
- package/dist/client/assets/DockviewTerminalContainer-CfWqm1iB.js +0 -2
- package/dist/client/assets/TerminalPanel-C6VJtwdn.js +0 -5
- package/dist/client/assets/_basePickBy-CIXRHkYC.js +0 -1
- package/dist/client/assets/_baseUniq-K3DMbXu0.js +0 -1
- package/dist/client/assets/arc-BkgOQsVG.js +0 -1
- package/dist/client/assets/architectureDiagram-VXUJARFQ-CD44Dllc.js +0 -36
- package/dist/client/assets/channel-DjN8EGMy.js +0 -1
- package/dist/client/assets/chunk-4BX2VUAB-Bphc00nU.js +0 -1
- package/dist/client/assets/chunk-55IACEB6-CfN6hb2c.js +0 -1
- package/dist/client/assets/chunk-QN33PNHL-B45qeM-p.js +0 -1
- package/dist/client/assets/chunk-QZHKN3VN-1ObdmeeM.js +0 -1
- package/dist/client/assets/chunk-TZMSLE5B-CWtn_mgw.js +0 -1
- package/dist/client/assets/classDiagram-2ON5EDUG-C3N3Omm0.js +0 -1
- package/dist/client/assets/classDiagram-v2-WZHVMYZB-C3N3Omm0.js +0 -1
- package/dist/client/assets/clone-Co6N-TQN.js +0 -1
- package/dist/client/assets/cose-bilkent-S5V4N54A-B4IAbafd.js +0 -1
- package/dist/client/assets/dagre-6UL2VRFP-BGoRZDH9.js +0 -4
- package/dist/client/assets/diagram-PSM6KHXK-DIkN7d-V.js +0 -24
- package/dist/client/assets/diagram-QEK2KX5R-B-hPXzou.js +0 -43
- package/dist/client/assets/diagram-S2PKOQOG-BlUeis_2.js +0 -24
- package/dist/client/assets/ganttDiagram-JELNMOA3-D8LfLthv.js +0 -267
- package/dist/client/assets/gitGraphDiagram-V2S2FVAM-BgFUKaMK.js +0 -65
- package/dist/client/assets/highlighted-body-B3W2YXNL-BHkeGyHR.js +0 -1
- package/dist/client/assets/index-CNerXIiJ.js +0 -7
- package/dist/client/assets/index-CXHZbHRT.js +0 -1
- package/dist/client/assets/index-DLFTwdhm.js +0 -1
- package/dist/client/assets/index-fbwZk1fH.js +0 -1
- package/dist/client/assets/infoDiagram-HS3SLOUP-xB0m1ffH.js +0 -2
- package/dist/client/assets/main-BLOY6Nam.css +0 -1
- package/dist/client/assets/pieDiagram-ADFJNKIX-khlEdX5z.js +0 -30
- package/dist/client/assets/sankeyDiagram-TZEHDZUN-BxF-L0mm.js +0 -10
- package/dist/client/assets/stateDiagram-FKZM4ZOC-DJXW-Mwx.js +0 -1
- package/dist/client/assets/stateDiagram-v2-4FDKWEC3-BCtCzm2C.js +0 -1
- package/dist/client/assets/useSessionListContext-DJKT08Su.js +0 -1
- package/dist/client/assets/workspace._workspaceId-BZyIo0Fq.js +0 -1
- package/dist/client/assets/workspace._workspaceId.changes-WzxDrDHA.js +0 -1
- package/dist/client/assets/workspace._workspaceId.code-DGeXE4KO.js +0 -1
- package/dist/client/assets/workspace._workspaceId.code._-DjAaAaSY.js +0 -1
- package/dist/client/assets/workspace._workspaceId.code.index-D0PytT4F.js +0 -1
- package/dist/client/assets/workspace._workspaceId.index-DUzba27e.js +0 -1
- package/dist/client/assets/workspace._workspaceId.terminal-BeG77FAq.js +0 -2
- package/dist/server/assets/_tanstack-start-manifest_v-2XlZMknZ.js +0 -4
- package/dist/server/assets/useSessionListContext-D_vX6E2e.js +0 -23
- package/dist/server/assets/workspace._workspaceId.changes-BJoSmFXW.js +0 -38
- package/dist/server/assets/workspace._workspaceId.code-Cuj0zH98.js +0 -12
- package/dist/server/assets/workspace._workspaceId.code._-D3Ifnqrr.js +0 -44
- package/dist/server/assets/workspace._workspaceId.code.index-DZZZQ6sT.js +0 -36
- package/dist/server/assets/workspace._workspaceId.index-D1ULJxZJ.js +0 -96
- package/dist/server/assets/workspace._workspaceId.terminal-BaKW7ZGQ.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,8 +118146,82 @@ 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";
|
|
118212
|
+
function toWireQueuedMessages(messages) {
|
|
118213
|
+
return messages.map((m11) => ({
|
|
118214
|
+
id: m11.id,
|
|
118215
|
+
text: m11.text,
|
|
118216
|
+
...m11.files && m11.files.length > 0 && {
|
|
118217
|
+
files: m11.files.map((f10) => ({
|
|
118218
|
+
mediaType: f10.mediaType,
|
|
118219
|
+
url: f10.url,
|
|
118220
|
+
...f10.filename !== void 0 && { filename: f10.filename }
|
|
118221
|
+
}))
|
|
118222
|
+
}
|
|
118223
|
+
}));
|
|
118224
|
+
}
|
|
118095
118225
|
var QUEUED_KEY = Symbol.for("band.queued-messages");
|
|
118096
118226
|
var LISTENERS_KEY = Symbol.for("band.queued-messages.listeners");
|
|
118097
118227
|
var g10 = globalThis;
|
|
@@ -118187,7 +118317,7 @@ function clearQueuedMessages(chatId) {
|
|
|
118187
118317
|
// src/lib/task-runner.ts
|
|
118188
118318
|
init_src();
|
|
118189
118319
|
import { mkdirSync as mkdirSync4, readdirSync as readdirSync6 } from "node:fs";
|
|
118190
|
-
import { join as
|
|
118320
|
+
import { join as join15 } from "node:path";
|
|
118191
118321
|
|
|
118192
118322
|
// src/lib/mime-types.ts
|
|
118193
118323
|
import { extname } from "node:path";
|
|
@@ -118252,7 +118382,7 @@ function hasPendingInputForWorkspace(workspaceId) {
|
|
|
118252
118382
|
|
|
118253
118383
|
// src/lib/task-store.ts
|
|
118254
118384
|
init_src();
|
|
118255
|
-
var
|
|
118385
|
+
var log12 = createLogger("task-store");
|
|
118256
118386
|
function generateTaskId() {
|
|
118257
118387
|
return `tsk_${Date.now()}`;
|
|
118258
118388
|
}
|
|
@@ -118325,7 +118455,7 @@ function cleanupStaleTasks() {
|
|
|
118325
118455
|
const result = db2.update(tasks).set({ status: "failed", completedAt: now }).where(eq2(tasks.status, "running")).run();
|
|
118326
118456
|
const count3 = result.changes;
|
|
118327
118457
|
if (count3 > 0) {
|
|
118328
|
-
|
|
118458
|
+
log12.info({ count: count3 }, "cleaned up stale tasks on startup");
|
|
118329
118459
|
}
|
|
118330
118460
|
return count3;
|
|
118331
118461
|
}
|
|
@@ -118362,7 +118492,7 @@ function pruneOldTasks(retentionMs = TASK_RETENTION_MS) {
|
|
|
118362
118492
|
const cutoff = Date.now() - retentionMs;
|
|
118363
118493
|
const count3 = deleteTasksOlderThan(cutoff);
|
|
118364
118494
|
if (count3 > 0) {
|
|
118365
|
-
|
|
118495
|
+
log12.info({ count: count3, retentionMs }, "pruned tasks older than retention window");
|
|
118366
118496
|
}
|
|
118367
118497
|
return count3;
|
|
118368
118498
|
}
|
|
@@ -118373,13 +118503,13 @@ function startTaskPruneScheduler(options2 = {}) {
|
|
|
118373
118503
|
try {
|
|
118374
118504
|
pruneOldTasks(retentionMs);
|
|
118375
118505
|
} catch (err) {
|
|
118376
|
-
|
|
118506
|
+
log12.error({ err }, "initial task prune on boot failed");
|
|
118377
118507
|
}
|
|
118378
118508
|
const timer = setInterval(() => {
|
|
118379
118509
|
try {
|
|
118380
118510
|
pruneOldTasks(retentionMs);
|
|
118381
118511
|
} catch (err) {
|
|
118382
|
-
|
|
118512
|
+
log12.error({ err }, "scheduled task prune failed");
|
|
118383
118513
|
}
|
|
118384
118514
|
}, intervalMs);
|
|
118385
118515
|
timer.unref();
|
|
@@ -118420,38 +118550,6 @@ function rowToRecord(row) {
|
|
|
118420
118550
|
};
|
|
118421
118551
|
}
|
|
118422
118552
|
|
|
118423
|
-
// src/lib/upload-utils.ts
|
|
118424
|
-
import { mkdir, writeFile } from "node:fs/promises";
|
|
118425
|
-
import { join as join15 } from "node:path";
|
|
118426
|
-
async function saveUploadedFilesDetailed(fileParts) {
|
|
118427
|
-
const uploadDir = join15(bandHome(), "uploads");
|
|
118428
|
-
await mkdir(uploadDir, { recursive: true });
|
|
118429
|
-
const baseTimestamp = Date.now();
|
|
118430
|
-
const saved = [];
|
|
118431
|
-
for (let i2 = 0; i2 < fileParts.length; i2++) {
|
|
118432
|
-
const part = fileParts[i2];
|
|
118433
|
-
const dataUrlMatch = part.url.match(/^data:[^;]+;base64,(.+)$/);
|
|
118434
|
-
if (!dataUrlMatch) continue;
|
|
118435
|
-
const buffer = Buffer.from(dataUrlMatch[1], "base64");
|
|
118436
|
-
const filename = part.filename || `file-${baseTimestamp}`;
|
|
118437
|
-
const safeOriginal = filename.replace(/[^a-zA-Z0-9._-]/g, "_");
|
|
118438
|
-
const storedName = `${baseTimestamp}-${i2}-${safeOriginal}`;
|
|
118439
|
-
const filePath = join15(uploadDir, storedName);
|
|
118440
|
-
await writeFile(filePath, buffer);
|
|
118441
|
-
saved.push({
|
|
118442
|
-
path: filePath,
|
|
118443
|
-
storedName,
|
|
118444
|
-
mediaType: part.mediaType,
|
|
118445
|
-
originalName: part.filename
|
|
118446
|
-
});
|
|
118447
|
-
}
|
|
118448
|
-
return saved;
|
|
118449
|
-
}
|
|
118450
|
-
async function saveUploadedFiles(fileParts) {
|
|
118451
|
-
const saved = await saveUploadedFilesDetailed(fileParts);
|
|
118452
|
-
return saved.map((f10) => f10.path);
|
|
118453
|
-
}
|
|
118454
|
-
|
|
118455
118553
|
// src/lib/workspace.ts
|
|
118456
118554
|
function resolveWorkspace(workspaceId) {
|
|
118457
118555
|
const state2 = loadState();
|
|
@@ -118466,7 +118564,7 @@ function resolveWorkspace(workspaceId) {
|
|
|
118466
118564
|
}
|
|
118467
118565
|
|
|
118468
118566
|
// src/lib/task-runner.ts
|
|
118469
|
-
var
|
|
118567
|
+
var log13 = createLogger("task-runner");
|
|
118470
118568
|
function listFiles(dir) {
|
|
118471
118569
|
try {
|
|
118472
118570
|
return new Set(readdirSync6(dir));
|
|
@@ -118525,7 +118623,7 @@ function persistTask(task) {
|
|
|
118525
118623
|
chatId: task.chatId
|
|
118526
118624
|
});
|
|
118527
118625
|
} catch (err) {
|
|
118528
|
-
|
|
118626
|
+
log13.warn({ err, taskId: task.taskRecordId }, "failed to persist task");
|
|
118529
118627
|
}
|
|
118530
118628
|
}
|
|
118531
118629
|
function broadcast(chatId, chunk) {
|
|
@@ -118549,7 +118647,7 @@ function broadcast(chatId, chunk) {
|
|
|
118549
118647
|
}
|
|
118550
118648
|
const subs = listeners2.get(chatId);
|
|
118551
118649
|
if (!subs || subs.size === 0) {
|
|
118552
|
-
|
|
118650
|
+
log13.warn({ chatId, chunkType: chunk.type }, "broadcast: no listeners");
|
|
118553
118651
|
return;
|
|
118554
118652
|
}
|
|
118555
118653
|
for (const listener of subs) {
|
|
@@ -118615,7 +118713,7 @@ function submitTask(options2) {
|
|
|
118615
118713
|
});
|
|
118616
118714
|
}
|
|
118617
118715
|
runTask(chatId, task).catch((err) => {
|
|
118618
|
-
|
|
118716
|
+
log13.error({ chatId, err }, "task execution failed");
|
|
118619
118717
|
if (task.status === "running") {
|
|
118620
118718
|
task.status = "failed";
|
|
118621
118719
|
task.completedAt = Date.now();
|
|
@@ -118657,7 +118755,7 @@ function abortTask(chatId) {
|
|
|
118657
118755
|
updateChatStatus(chatId, "idle");
|
|
118658
118756
|
const updated = upsertWorkspaceStatus(task.workspaceId, { status: "waiting" });
|
|
118659
118757
|
emit({ kind: "update", status: updated });
|
|
118660
|
-
|
|
118758
|
+
log13.info({ chatId }, "task aborted by user");
|
|
118661
118759
|
return true;
|
|
118662
118760
|
}
|
|
118663
118761
|
function cancelTask(taskId) {
|
|
@@ -118682,7 +118780,7 @@ function cancelTask(taskId) {
|
|
|
118682
118780
|
updateChatStatus(chatId, "idle");
|
|
118683
118781
|
const updated = upsertWorkspaceStatus(task.workspaceId, { status: "waiting" });
|
|
118684
118782
|
emit({ kind: "update", status: updated });
|
|
118685
|
-
|
|
118783
|
+
log13.info({ chatId, taskId }, "task cancelled (was running in-memory)");
|
|
118686
118784
|
return { cancelled: true, workspaceId: task.workspaceId };
|
|
118687
118785
|
}
|
|
118688
118786
|
}
|
|
@@ -118690,7 +118788,7 @@ function cancelTask(taskId) {
|
|
|
118690
118788
|
if (record2) {
|
|
118691
118789
|
const updated = upsertWorkspaceStatus(record2.workspaceId, { status: "waiting" });
|
|
118692
118790
|
emit({ kind: "update", status: updated });
|
|
118693
|
-
|
|
118791
|
+
log13.info({ taskId, workspaceId: record2.workspaceId }, "orphaned task cancelled");
|
|
118694
118792
|
return { cancelled: true, workspaceId: record2.workspaceId };
|
|
118695
118793
|
}
|
|
118696
118794
|
return { cancelled: false };
|
|
@@ -118710,7 +118808,7 @@ async function runTask(chatId, task) {
|
|
|
118710
118808
|
const taskAgentId = task.codingAgentId;
|
|
118711
118809
|
const resolvedAgentId = taskAgentId ?? chatSession?.agent;
|
|
118712
118810
|
const needsReplace = taskAgentId && taskAgentId !== chatSession?.agent;
|
|
118713
|
-
|
|
118811
|
+
log13.info(
|
|
118714
118812
|
{ chatId, taskAgentId, chatAgent: chatSession?.agent, resolvedAgentId, needsReplace },
|
|
118715
118813
|
"resolving agent for task"
|
|
118716
118814
|
);
|
|
@@ -118718,7 +118816,7 @@ async function runTask(chatId, task) {
|
|
|
118718
118816
|
updateChatStatus(chatId, "running");
|
|
118719
118817
|
const working = upsertWorkspaceStatus(task.workspaceId, { status: "working" });
|
|
118720
118818
|
emit({ kind: "update", status: working });
|
|
118721
|
-
const sharedDir =
|
|
118819
|
+
const sharedDir = join15(bandHome(), "shared", task.workspaceId);
|
|
118722
118820
|
mkdirSync4(sharedDir, { recursive: true });
|
|
118723
118821
|
const INTERACTIVE_TOOLS = /* @__PURE__ */ new Set(["AskUserQuestion", "ExitPlanMode"]);
|
|
118724
118822
|
let textPartId = "";
|
|
@@ -118759,7 +118857,7 @@ async function runTask(chatId, task) {
|
|
|
118759
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.]`;
|
|
118760
118858
|
const effectivePrompt = task.sessionId ? task.agentPrompt : task.agentPrompt + fileSharingHint;
|
|
118761
118859
|
for await (const event of agent.runSession(effectivePrompt, task.sessionId, sessionOptions)) {
|
|
118762
|
-
|
|
118860
|
+
log13.info({ chatId, eventType: event.type }, "task event");
|
|
118763
118861
|
switch (event.type) {
|
|
118764
118862
|
case "session-start": {
|
|
118765
118863
|
task.sessionId = event.sessionId;
|
|
@@ -118959,7 +119057,7 @@ async function runTask(chatId, task) {
|
|
|
118959
119057
|
break;
|
|
118960
119058
|
}
|
|
118961
119059
|
case "session-id-resolved": {
|
|
118962
|
-
|
|
119060
|
+
log13.info(
|
|
118963
119061
|
{ chatId, previous: event.previousSessionId, resolved: event.resolvedSessionId },
|
|
118964
119062
|
"session ID resolved"
|
|
118965
119063
|
);
|
|
@@ -119030,17 +119128,17 @@ async function runTask(chatId, task) {
|
|
|
119030
119128
|
let agentPrompt;
|
|
119031
119129
|
let displayFiles;
|
|
119032
119130
|
if (queued.files && queued.files.length > 0) {
|
|
119033
|
-
const
|
|
119034
|
-
if (
|
|
119035
|
-
const fileList =
|
|
119131
|
+
const usableFiles = queued.files.filter((f10) => f10.path);
|
|
119132
|
+
if (usableFiles.length > 0) {
|
|
119133
|
+
const fileList = usableFiles.map((f10) => `- ${f10.path}`).join("\n");
|
|
119036
119134
|
agentPrompt = `I'm sharing these files with you:
|
|
119037
119135
|
${fileList}
|
|
119038
119136
|
|
|
119039
119137
|
${queued.text}`;
|
|
119040
|
-
displayFiles =
|
|
119041
|
-
mediaType:
|
|
119042
|
-
url:
|
|
119043
|
-
filename:
|
|
119138
|
+
displayFiles = usableFiles.map((f10) => ({
|
|
119139
|
+
mediaType: f10.mediaType,
|
|
119140
|
+
url: f10.url,
|
|
119141
|
+
filename: f10.filename
|
|
119044
119142
|
}));
|
|
119045
119143
|
}
|
|
119046
119144
|
}
|
|
@@ -119054,7 +119152,7 @@ ${queued.text}`;
|
|
|
119054
119152
|
});
|
|
119055
119153
|
autoStarted = true;
|
|
119056
119154
|
} catch (err) {
|
|
119057
|
-
|
|
119155
|
+
log13.warn({ chatId, err }, "failed to auto-start queued task");
|
|
119058
119156
|
}
|
|
119059
119157
|
}
|
|
119060
119158
|
}
|
|
@@ -119207,7 +119305,7 @@ function openSseStream(res) {
|
|
|
119207
119305
|
}
|
|
119208
119306
|
|
|
119209
119307
|
// src/api/chat-events.ts
|
|
119210
|
-
var
|
|
119308
|
+
var log14 = createLogger("chat-events");
|
|
119211
119309
|
async function handleChatEvents(req, res, chatId) {
|
|
119212
119310
|
const url = new URL(req.url, `http://${req.headers.host}`);
|
|
119213
119311
|
const lastEventIdHeader = req.headers["last-event-id"];
|
|
@@ -119229,7 +119327,7 @@ async function handleChatEvents(req, res, chatId) {
|
|
|
119229
119327
|
});
|
|
119230
119328
|
emit2(writer, {
|
|
119231
119329
|
type: "queue-updated",
|
|
119232
|
-
messages: getQueuedMessages(chatId),
|
|
119330
|
+
messages: toWireQueuedMessages(getQueuedMessages(chatId)),
|
|
119233
119331
|
eventId: nextSyntheticId--
|
|
119234
119332
|
});
|
|
119235
119333
|
if (resolvedSessionId) {
|
|
@@ -119270,7 +119368,7 @@ async function handleChatEvents(req, res, chatId) {
|
|
|
119270
119368
|
if (qChatId !== chatId) return;
|
|
119271
119369
|
queue.push({
|
|
119272
119370
|
type: "queue-updated",
|
|
119273
|
-
messages,
|
|
119371
|
+
messages: toWireQueuedMessages(messages),
|
|
119274
119372
|
eventId: nextSyntheticId--
|
|
119275
119373
|
});
|
|
119276
119374
|
notify2?.();
|
|
@@ -119287,7 +119385,7 @@ async function handleChatEvents(req, res, chatId) {
|
|
|
119287
119385
|
chatWorkspaceId: chat?.workspaceId ?? explicitWorkspaceId,
|
|
119288
119386
|
agentTypeHint: chat?.agent
|
|
119289
119387
|
}).catch((err) => {
|
|
119290
|
-
|
|
119388
|
+
log14.warn({ chatId, err }, "replay phase failed; continuing to live tail");
|
|
119291
119389
|
});
|
|
119292
119390
|
try {
|
|
119293
119391
|
while (!res.destroyed && !writer.closed) {
|
|
@@ -119346,7 +119444,7 @@ async function replayPast(opts) {
|
|
|
119346
119444
|
}
|
|
119347
119445
|
}
|
|
119348
119446
|
} catch (err) {
|
|
119349
|
-
|
|
119447
|
+
log14.warn({ chatId, sessionId, err }, "JSONL backfill failed; falling through to buffer");
|
|
119350
119448
|
}
|
|
119351
119449
|
}
|
|
119352
119450
|
if (!jsonlEmittedAny && buf) {
|
|
@@ -119380,7 +119478,7 @@ async function replayPast(opts) {
|
|
|
119380
119478
|
}
|
|
119381
119479
|
}
|
|
119382
119480
|
} catch (err) {
|
|
119383
|
-
|
|
119481
|
+
log14.warn({ chatId, sessionId, err }, "JSONL backfill failed; falling through to buffer");
|
|
119384
119482
|
}
|
|
119385
119483
|
}
|
|
119386
119484
|
if (buf) {
|
|
@@ -119393,50 +119491,6 @@ async function replayPast(opts) {
|
|
|
119393
119491
|
}
|
|
119394
119492
|
}
|
|
119395
119493
|
}
|
|
119396
|
-
function stripFileSharingHint(text3) {
|
|
119397
|
-
return text3.replace(/\n\n\[File sharing:[\s\S]*?\]\s*$/, "");
|
|
119398
|
-
}
|
|
119399
|
-
function jsonlMessageToEvents(msg, startId) {
|
|
119400
|
-
const events = [];
|
|
119401
|
-
let id = startId;
|
|
119402
|
-
if (msg.role === "user") {
|
|
119403
|
-
const textPart = msg.content.find(
|
|
119404
|
-
(p6) => p6.type === "text"
|
|
119405
|
-
);
|
|
119406
|
-
events.push({
|
|
119407
|
-
type: "user-message",
|
|
119408
|
-
text: stripFileSharingHint(textPart?.text ?? ""),
|
|
119409
|
-
eventId: id++
|
|
119410
|
-
});
|
|
119411
|
-
return events;
|
|
119412
|
-
}
|
|
119413
|
-
for (const part of msg.content) {
|
|
119414
|
-
if (part.type === "text") {
|
|
119415
|
-
const textPartId = `${msg.id}-text-${id}`;
|
|
119416
|
-
events.push({ type: "text-start", id: textPartId, eventId: id++ });
|
|
119417
|
-
events.push({ type: "text-delta", id: textPartId, delta: part.text, eventId: id++ });
|
|
119418
|
-
events.push({ type: "text-end", id: textPartId, eventId: id++ });
|
|
119419
|
-
} else if (part.type === "tool_use") {
|
|
119420
|
-
events.push({
|
|
119421
|
-
type: "tool-input-available",
|
|
119422
|
-
toolCallId: part.toolCallId,
|
|
119423
|
-
toolName: part.toolName,
|
|
119424
|
-
displayTitle: part.displayTitle,
|
|
119425
|
-
input: part.input,
|
|
119426
|
-
eventId: id++
|
|
119427
|
-
});
|
|
119428
|
-
} else if (part.type === "tool_result") {
|
|
119429
|
-
events.push({
|
|
119430
|
-
type: "tool-output-available",
|
|
119431
|
-
toolCallId: part.toolCallId,
|
|
119432
|
-
output: part.output,
|
|
119433
|
-
isError: part.isError,
|
|
119434
|
-
eventId: id++
|
|
119435
|
-
});
|
|
119436
|
-
}
|
|
119437
|
-
}
|
|
119438
|
-
return events;
|
|
119439
|
-
}
|
|
119440
119494
|
function chunkToChatEvent(chunk, _sessionId) {
|
|
119441
119495
|
const c2 = chunk;
|
|
119442
119496
|
switch (c2.type) {
|
|
@@ -119532,7 +119586,41 @@ function chunkToChatEvent(chunk, _sessionId) {
|
|
|
119532
119586
|
|
|
119533
119587
|
// src/api/chat-submit.ts
|
|
119534
119588
|
init_src();
|
|
119535
|
-
|
|
119589
|
+
|
|
119590
|
+
// src/lib/upload-utils.ts
|
|
119591
|
+
import { mkdir, writeFile } from "node:fs/promises";
|
|
119592
|
+
import { join as join16 } from "node:path";
|
|
119593
|
+
async function saveUploadedFilesDetailed(fileParts) {
|
|
119594
|
+
const uploadDir = join16(bandHome(), "uploads");
|
|
119595
|
+
await mkdir(uploadDir, { recursive: true });
|
|
119596
|
+
const baseTimestamp = Date.now();
|
|
119597
|
+
const saved = [];
|
|
119598
|
+
for (let i2 = 0; i2 < fileParts.length; i2++) {
|
|
119599
|
+
const part = fileParts[i2];
|
|
119600
|
+
const dataUrlMatch = part.url.match(/^data:[^;]+;base64,(.+)$/);
|
|
119601
|
+
if (!dataUrlMatch) continue;
|
|
119602
|
+
const buffer = Buffer.from(dataUrlMatch[1], "base64");
|
|
119603
|
+
const filename = part.filename || `file-${baseTimestamp}`;
|
|
119604
|
+
const safeOriginal = filename.replace(/[^a-zA-Z0-9._-]/g, "_");
|
|
119605
|
+
const storedName = `${baseTimestamp}-${i2}-${safeOriginal}`;
|
|
119606
|
+
const filePath = join16(uploadDir, storedName);
|
|
119607
|
+
await writeFile(filePath, buffer);
|
|
119608
|
+
saved.push({
|
|
119609
|
+
path: filePath,
|
|
119610
|
+
storedName,
|
|
119611
|
+
mediaType: part.mediaType,
|
|
119612
|
+
originalName: part.filename
|
|
119613
|
+
});
|
|
119614
|
+
}
|
|
119615
|
+
return saved;
|
|
119616
|
+
}
|
|
119617
|
+
async function saveUploadedFiles(fileParts) {
|
|
119618
|
+
const saved = await saveUploadedFilesDetailed(fileParts);
|
|
119619
|
+
return saved.map((f10) => f10.path);
|
|
119620
|
+
}
|
|
119621
|
+
|
|
119622
|
+
// src/api/chat-submit.ts
|
|
119623
|
+
var log15 = createLogger("chat-submit");
|
|
119536
119624
|
function readBody(req) {
|
|
119537
119625
|
return new Promise((resolve7, reject) => {
|
|
119538
119626
|
const chunks = [];
|
|
@@ -119565,15 +119653,22 @@ async function handleChatSubmit(req, res, chatId) {
|
|
|
119565
119653
|
const resumeSessionId = sessionId ?? getChat(chatId)?.activeSessionId;
|
|
119566
119654
|
let agentPrompt;
|
|
119567
119655
|
let displayFiles;
|
|
119656
|
+
let savedFiles = [];
|
|
119568
119657
|
if (files && files.length > 0) {
|
|
119569
|
-
|
|
119570
|
-
if (
|
|
119571
|
-
|
|
119658
|
+
savedFiles = await saveUploadedFilesDetailed(files);
|
|
119659
|
+
if (savedFiles.length !== files.length) {
|
|
119660
|
+
log15.warn(
|
|
119661
|
+
{ chatId, submitted: files.length, saved: savedFiles.length },
|
|
119662
|
+
"chat-submit: some file uploads were dropped (malformed data URL?)"
|
|
119663
|
+
);
|
|
119664
|
+
}
|
|
119665
|
+
if (savedFiles.length > 0) {
|
|
119666
|
+
const fileList = savedFiles.map((s6) => `- ${s6.path}`).join("\n");
|
|
119572
119667
|
agentPrompt = `I'm sharing these files with you:
|
|
119573
119668
|
${fileList}
|
|
119574
119669
|
|
|
119575
119670
|
${text3}`;
|
|
119576
|
-
displayFiles =
|
|
119671
|
+
displayFiles = savedFiles.map((s6) => ({
|
|
119577
119672
|
mediaType: s6.mediaType,
|
|
119578
119673
|
url: `/api/uploads/${s6.storedName}`,
|
|
119579
119674
|
filename: s6.originalName
|
|
@@ -119593,15 +119688,22 @@ ${text3}`;
|
|
|
119593
119688
|
model,
|
|
119594
119689
|
codingAgentId
|
|
119595
119690
|
});
|
|
119596
|
-
|
|
119691
|
+
log15.info({ chatId, workspaceId }, "chat-submit: task started");
|
|
119597
119692
|
sendJson(res, 200, { ok: true, queued: false });
|
|
119598
119693
|
} catch (err) {
|
|
119599
119694
|
if (err instanceof TaskConflictError) {
|
|
119600
119695
|
pushQueuedMessage(chatId, {
|
|
119601
119696
|
text: text3,
|
|
119602
|
-
...
|
|
119697
|
+
...savedFiles.length > 0 && {
|
|
119698
|
+
files: savedFiles.map((s6) => ({
|
|
119699
|
+
mediaType: s6.mediaType,
|
|
119700
|
+
url: `/api/uploads/${s6.storedName}`,
|
|
119701
|
+
path: s6.path,
|
|
119702
|
+
filename: s6.originalName
|
|
119703
|
+
}))
|
|
119704
|
+
}
|
|
119603
119705
|
});
|
|
119604
|
-
|
|
119706
|
+
log15.info({ chatId, workspaceId }, "chat-submit: task busy, message queued");
|
|
119605
119707
|
sendJson(res, 200, { ok: true, queued: true });
|
|
119606
119708
|
return;
|
|
119607
119709
|
}
|
|
@@ -119609,7 +119711,7 @@ ${text3}`;
|
|
|
119609
119711
|
sendJson(res, 404, { error: err.message });
|
|
119610
119712
|
return;
|
|
119611
119713
|
}
|
|
119612
|
-
|
|
119714
|
+
log15.error({ chatId, err }, "chat-submit: unexpected error");
|
|
119613
119715
|
sendJson(res, 500, { error: "Internal server error" });
|
|
119614
119716
|
}
|
|
119615
119717
|
}
|
|
@@ -119643,7 +119745,7 @@ function removeBrowserFromLayout(workspaceId, browserId) {
|
|
|
119643
119745
|
}
|
|
119644
119746
|
|
|
119645
119747
|
// src/lib/browser-manager.ts
|
|
119646
|
-
var
|
|
119748
|
+
var log16 = createLogger("browser-manager");
|
|
119647
119749
|
var PANEL_TYPE2 = "browser";
|
|
119648
119750
|
var browserTabs = /* @__PURE__ */ new Map();
|
|
119649
119751
|
var workspaceBrowsers = /* @__PURE__ */ new Map();
|
|
@@ -119704,7 +119806,7 @@ function createBrowser(workspaceId, options2) {
|
|
|
119704
119806
|
title: tab.name,
|
|
119705
119807
|
initialUrl: tab.url || void 0
|
|
119706
119808
|
});
|
|
119707
|
-
|
|
119809
|
+
log16.info({ browserId: tab.id, workspaceId, url: tab.url }, "browser tab created");
|
|
119708
119810
|
return tab;
|
|
119709
119811
|
}
|
|
119710
119812
|
function getBrowser(browserId) {
|
|
@@ -119731,7 +119833,7 @@ function updateBrowser(browserId, updates) {
|
|
|
119731
119833
|
state: serializeState2(tab),
|
|
119732
119834
|
updatedAt: Date.now()
|
|
119733
119835
|
});
|
|
119734
|
-
|
|
119836
|
+
log16.info({ browserId, updates }, "browser tab updated");
|
|
119735
119837
|
return tab;
|
|
119736
119838
|
}
|
|
119737
119839
|
function updateBrowserUrl(browserId, url) {
|
|
@@ -119748,7 +119850,7 @@ function removeBrowser(browserId) {
|
|
|
119748
119850
|
if (!tab) return false;
|
|
119749
119851
|
deletePanelState(browserId);
|
|
119750
119852
|
removeFromIndex2(browserId);
|
|
119751
|
-
|
|
119853
|
+
log16.info({ browserId, workspaceId: tab.workspaceId }, "browser tab removed");
|
|
119752
119854
|
return true;
|
|
119753
119855
|
}
|
|
119754
119856
|
function removeWorkspaceBrowsers(workspaceId) {
|
|
@@ -119759,7 +119861,7 @@ function removeWorkspaceBrowsers(workspaceId) {
|
|
|
119759
119861
|
}
|
|
119760
119862
|
deletePanelStatesForWorkspace(workspaceId, PANEL_TYPE2);
|
|
119761
119863
|
workspaceBrowsers.delete(workspaceId);
|
|
119762
|
-
|
|
119864
|
+
log16.info({ workspaceId }, "all browser tabs removed for workspace");
|
|
119763
119865
|
}
|
|
119764
119866
|
function loadBrowsersFromDb() {
|
|
119765
119867
|
_initialized2 = true;
|
|
@@ -119778,13 +119880,13 @@ function loadBrowsersFromDb() {
|
|
|
119778
119880
|
addToIndex2(tab);
|
|
119779
119881
|
}
|
|
119780
119882
|
if (rows.length > 0) {
|
|
119781
|
-
|
|
119883
|
+
log16.info({ count: rows.length }, "loaded browser tabs from database");
|
|
119782
119884
|
}
|
|
119783
119885
|
return rows.length;
|
|
119784
119886
|
}
|
|
119785
119887
|
|
|
119786
119888
|
// src/lib/browser-host.ts
|
|
119787
|
-
var
|
|
119889
|
+
var log17 = createLogger("browser-host");
|
|
119788
119890
|
var DESKTOP_CDP_HOST = "127.0.0.1";
|
|
119789
119891
|
var DESKTOP_CDP_PORT = 9223;
|
|
119790
119892
|
var globalAny = globalThis;
|
|
@@ -119835,7 +119937,7 @@ async function ensureCdpTargetId(bandTabId) {
|
|
|
119835
119937
|
reject: rejectFn,
|
|
119836
119938
|
timeoutId
|
|
119837
119939
|
});
|
|
119838
|
-
|
|
119940
|
+
log17.info(
|
|
119839
119941
|
"ensureCdpTargetId emitting ensureView for %s (url=%s, listeners=%d)",
|
|
119840
119942
|
bandTabId,
|
|
119841
119943
|
tab.url,
|
|
@@ -119849,13 +119951,13 @@ async function ensureCdpTargetId(bandTabId) {
|
|
|
119849
119951
|
url: tab.url
|
|
119850
119952
|
});
|
|
119851
119953
|
} catch (err) {
|
|
119852
|
-
|
|
119954
|
+
log17.warn("ensureView listener threw: %s", err instanceof Error ? err.message : err);
|
|
119853
119955
|
}
|
|
119854
119956
|
}
|
|
119855
119957
|
return promise;
|
|
119856
119958
|
}
|
|
119857
119959
|
function resolveTargetReady(bandTabId, cdpTargetId) {
|
|
119858
|
-
|
|
119960
|
+
log17.info("resolveTargetReady %s \u2192 %s", bandTabId, cdpTargetId);
|
|
119859
119961
|
targetIdByBandTabId.set(bandTabId, cdpTargetId);
|
|
119860
119962
|
const pending2 = pendingEnsures.get(bandTabId);
|
|
119861
119963
|
if (pending2) {
|
|
@@ -119865,7 +119967,7 @@ function resolveTargetReady(bandTabId, cdpTargetId) {
|
|
|
119865
119967
|
}
|
|
119866
119968
|
}
|
|
119867
119969
|
function markTargetDestroyed(bandTabId) {
|
|
119868
|
-
|
|
119970
|
+
log17.info("markTargetDestroyed %s", bandTabId);
|
|
119869
119971
|
targetIdByBandTabId.delete(bandTabId);
|
|
119870
119972
|
const pending2 = pendingEnsures.get(bandTabId);
|
|
119871
119973
|
if (pending2) {
|
|
@@ -119876,10 +119978,10 @@ function markTargetDestroyed(bandTabId) {
|
|
|
119876
119978
|
}
|
|
119877
119979
|
function onEnsureView(listener) {
|
|
119878
119980
|
ensureListeners.add(listener);
|
|
119879
|
-
|
|
119981
|
+
log17.info("onEnsureView subscriber added (total=%d)", ensureListeners.size);
|
|
119880
119982
|
return () => {
|
|
119881
119983
|
ensureListeners.delete(listener);
|
|
119882
|
-
|
|
119984
|
+
log17.info("onEnsureView subscriber removed (total=%d)", ensureListeners.size);
|
|
119883
119985
|
if (ensureListeners.size === 0) {
|
|
119884
119986
|
for (const [bandTabId, pending2] of pendingEnsures) {
|
|
119885
119987
|
clearTimeout(pending2.timeoutId);
|
|
@@ -119896,7 +119998,7 @@ function isDesktopHostConnected() {
|
|
|
119896
119998
|
|
|
119897
119999
|
// src/lib/cdp-proxy.ts
|
|
119898
120000
|
init_src();
|
|
119899
|
-
var
|
|
120001
|
+
var log18 = createLogger("cdp-proxy");
|
|
119900
120002
|
async function handleCdpConnection(ws, req) {
|
|
119901
120003
|
const url = new URL(req.url ?? "", `http://${req.headers.host}`);
|
|
119902
120004
|
const bandTabId = url.searchParams.get("bandTabId");
|
|
@@ -119919,17 +120021,17 @@ async function handleCdpConnection(ws, req) {
|
|
|
119919
120021
|
cdpTargetId = await ensureCdpTargetId(bandTabId);
|
|
119920
120022
|
} catch (err) {
|
|
119921
120023
|
const message = err instanceof Error ? err.message : String(err);
|
|
119922
|
-
|
|
120024
|
+
log18.debug("ensureCdpTargetId failed for %s: %s", bandTabId, message);
|
|
119923
120025
|
if (ws.readyState === ws.OPEN) {
|
|
119924
120026
|
ws.close(4001, message.slice(0, 123));
|
|
119925
120027
|
}
|
|
119926
120028
|
return;
|
|
119927
120029
|
}
|
|
119928
120030
|
const upstreamUrl = `ws://${DESKTOP_CDP_HOST}:${DESKTOP_CDP_PORT}/devtools/page/${encodeURIComponent(cdpTargetId)}`;
|
|
119929
|
-
|
|
120031
|
+
log18.info("CDP proxy connecting bandTabId=%s upstream=%s", bandTabId, upstreamUrl);
|
|
119930
120032
|
upstream = new wrapper_default(upstreamUrl);
|
|
119931
120033
|
upstream.on("open", () => {
|
|
119932
|
-
|
|
120034
|
+
log18.info("CDP upstream open bandTabId=%s pending=%d", bandTabId, pending2.length);
|
|
119933
120035
|
for (const msg of pending2) {
|
|
119934
120036
|
upstream?.send(msg);
|
|
119935
120037
|
}
|
|
@@ -119941,20 +120043,20 @@ async function handleCdpConnection(ws, req) {
|
|
|
119941
120043
|
}
|
|
119942
120044
|
});
|
|
119943
120045
|
upstream.on("error", (err) => {
|
|
119944
|
-
|
|
120046
|
+
log18.warn("CDP upstream error bandTabId=%s: %s", bandTabId, err.message);
|
|
119945
120047
|
markTargetDestroyed(bandTabId);
|
|
119946
120048
|
if (ws.readyState === ws.OPEN) {
|
|
119947
120049
|
ws.close(4001, `Desktop CDP error: ${err.message}`.slice(0, 123));
|
|
119948
120050
|
}
|
|
119949
120051
|
});
|
|
119950
120052
|
upstream.on("close", (code) => {
|
|
119951
|
-
|
|
120053
|
+
log18.info("CDP upstream closed bandTabId=%s code=%d", bandTabId, code);
|
|
119952
120054
|
if (ws.readyState === ws.OPEN) {
|
|
119953
120055
|
ws.close(1e3, "Upstream closed");
|
|
119954
120056
|
}
|
|
119955
120057
|
});
|
|
119956
120058
|
ws.on("close", () => {
|
|
119957
|
-
|
|
120059
|
+
log18.debug("CDP client closed bandTabId=%s", bandTabId);
|
|
119958
120060
|
if (upstream && (upstream.readyState === wrapper_default.OPEN || upstream.readyState === wrapper_default.CONNECTING)) {
|
|
119959
120061
|
try {
|
|
119960
120062
|
upstream.close();
|
|
@@ -119963,7 +120065,7 @@ async function handleCdpConnection(ws, req) {
|
|
|
119963
120065
|
}
|
|
119964
120066
|
});
|
|
119965
120067
|
ws.on("error", (err) => {
|
|
119966
|
-
|
|
120068
|
+
log18.debug("CDP client error bandTabId=%s: %s", bandTabId, err.message);
|
|
119967
120069
|
try {
|
|
119968
120070
|
upstream?.close();
|
|
119969
120071
|
} catch {
|
|
@@ -119973,7 +120075,7 @@ async function handleCdpConnection(ws, req) {
|
|
|
119973
120075
|
|
|
119974
120076
|
// src/lib/cdp-targets.ts
|
|
119975
120077
|
init_src();
|
|
119976
|
-
var
|
|
120078
|
+
var log19 = createLogger("cdp-targets");
|
|
119977
120079
|
var CdpUnreachableError = class extends Error {
|
|
119978
120080
|
constructor(message) {
|
|
119979
120081
|
super(message);
|
|
@@ -120029,7 +120131,7 @@ async function captureSnapshot(bandTabId) {
|
|
|
120029
120131
|
});
|
|
120030
120132
|
ws.on("error", (err) => {
|
|
120031
120133
|
clearTimeout(timeout);
|
|
120032
|
-
|
|
120134
|
+
log19.debug("captureSnapshot ws error for tab %s: %s", bandTabId, err.message);
|
|
120033
120135
|
markTargetDestroyed(bandTabId);
|
|
120034
120136
|
settle(new CdpUnreachableError(err.message));
|
|
120035
120137
|
});
|
|
@@ -120749,7 +120851,7 @@ function rowToDefinition(row) {
|
|
|
120749
120851
|
}
|
|
120750
120852
|
|
|
120751
120853
|
// src/lib/cronjob-scheduler.ts
|
|
120752
|
-
var
|
|
120854
|
+
var log20 = createLogger("cronjob-scheduler");
|
|
120753
120855
|
var SCHEDULER_KEY = Symbol.for("band.cronjob-scheduler");
|
|
120754
120856
|
var g14 = globalThis;
|
|
120755
120857
|
if (!g14[SCHEDULER_KEY]) {
|
|
@@ -120769,16 +120871,16 @@ function scheduleJob(job, fileKey) {
|
|
|
120769
120871
|
try {
|
|
120770
120872
|
const cronInstance = new E2(job.cronExpression, () => {
|
|
120771
120873
|
executeCronjob(job, fileKey).catch((err) => {
|
|
120772
|
-
|
|
120874
|
+
log20.error({ jobId: job.id, err }, "unhandled error in cronjob execution");
|
|
120773
120875
|
});
|
|
120774
120876
|
});
|
|
120775
120877
|
state.jobs.set(job.id, cronInstance);
|
|
120776
|
-
|
|
120878
|
+
log20.info(
|
|
120777
120879
|
{ jobId: job.id, name: job.name, cron: job.cronExpression, scope: job.scope },
|
|
120778
120880
|
"scheduled cronjob"
|
|
120779
120881
|
);
|
|
120780
120882
|
} catch (err) {
|
|
120781
|
-
|
|
120883
|
+
log20.error(
|
|
120782
120884
|
{ jobId: job.id, cronExpression: job.cronExpression, err },
|
|
120783
120885
|
"invalid cron expression, skipping job"
|
|
120784
120886
|
);
|
|
@@ -120792,24 +120894,24 @@ async function executeCronjob(job, fileKey) {
|
|
|
120792
120894
|
const appState = loadState();
|
|
120793
120895
|
const project = appState.projects.find((p6) => p6.name === fileKey);
|
|
120794
120896
|
if (!project) {
|
|
120795
|
-
|
|
120897
|
+
log20.warn({ jobId: job.id, fileKey }, "project not found for cronjob, skipping");
|
|
120796
120898
|
updateLastRun(job.id, "failed");
|
|
120797
120899
|
return;
|
|
120798
120900
|
}
|
|
120799
120901
|
workspaceId = toWorkspaceId(project.name, project.defaultBranch);
|
|
120800
120902
|
}
|
|
120801
|
-
|
|
120903
|
+
log20.info({ jobId: job.id, name: job.name, workspaceId }, "executing cronjob");
|
|
120802
120904
|
try {
|
|
120803
120905
|
const chat = getOrCreateDefaultChat(workspaceId);
|
|
120804
120906
|
submitTask({ workspaceId, chatId: chat.id, prompt: job.prompt });
|
|
120805
120907
|
updateLastRun(job.id, "completed");
|
|
120806
120908
|
} catch (err) {
|
|
120807
120909
|
if (err instanceof TaskConflictError) {
|
|
120808
|
-
|
|
120910
|
+
log20.info({ jobId: job.id, workspaceId }, "task already running, skipping cronjob execution");
|
|
120809
120911
|
updateLastRun(job.id, "skipped");
|
|
120810
120912
|
return;
|
|
120811
120913
|
}
|
|
120812
|
-
|
|
120914
|
+
log20.error({ jobId: job.id, err }, "cronjob execution failed");
|
|
120813
120915
|
updateLastRun(job.id, "failed");
|
|
120814
120916
|
}
|
|
120815
120917
|
}
|
|
@@ -120818,7 +120920,7 @@ function updateLastRun(jobId, status) {
|
|
|
120818
120920
|
const db2 = getDb();
|
|
120819
120921
|
db2.update(cronjobs).set({ lastRunAt: (/* @__PURE__ */ new Date()).toISOString(), lastRunStatus: status }).where(eq2(cronjobs.id, jobId)).run();
|
|
120820
120922
|
} catch (err) {
|
|
120821
|
-
|
|
120923
|
+
log20.warn({ jobId, err }, "failed to update lastRun on cronjob");
|
|
120822
120924
|
}
|
|
120823
120925
|
}
|
|
120824
120926
|
function loadAndScheduleAll() {
|
|
@@ -120829,13 +120931,13 @@ function loadAndScheduleAll() {
|
|
|
120829
120931
|
for (const job of listAllCronjobs()) {
|
|
120830
120932
|
scheduleJob(job, job.fileKey);
|
|
120831
120933
|
}
|
|
120832
|
-
|
|
120934
|
+
log20.info({ count: state.jobs.size }, "loaded cronjob schedules");
|
|
120833
120935
|
}
|
|
120834
120936
|
function startCronjobScheduler() {
|
|
120835
120937
|
if (state.started) return;
|
|
120836
120938
|
state.started = true;
|
|
120837
120939
|
loadAndScheduleAll();
|
|
120838
|
-
|
|
120940
|
+
log20.info("cronjob scheduler started");
|
|
120839
120941
|
}
|
|
120840
120942
|
function stopCronjobScheduler() {
|
|
120841
120943
|
for (const [, cron] of state.jobs) {
|
|
@@ -120843,7 +120945,7 @@ function stopCronjobScheduler() {
|
|
|
120843
120945
|
}
|
|
120844
120946
|
state.jobs.clear();
|
|
120845
120947
|
state.started = false;
|
|
120846
|
-
|
|
120948
|
+
log20.info("cronjob scheduler stopped");
|
|
120847
120949
|
}
|
|
120848
120950
|
function reloadSchedules() {
|
|
120849
120951
|
if (!state.started) return;
|
|
@@ -120856,7 +120958,7 @@ function stopJobsForKey(key) {
|
|
|
120856
120958
|
if (cron) {
|
|
120857
120959
|
cron.stop();
|
|
120858
120960
|
state.jobs.delete(job.id);
|
|
120859
|
-
|
|
120961
|
+
log20.info({ jobId: job.id, key }, "stopped cronjob");
|
|
120860
120962
|
}
|
|
120861
120963
|
}
|
|
120862
120964
|
}
|
|
@@ -120922,7 +121024,7 @@ async function checkPrereqs() {
|
|
|
120922
121024
|
|
|
120923
121025
|
// src/lib/lsp-manager.ts
|
|
120924
121026
|
var __dirname2 = dirname2(fileURLToPath(import.meta.url));
|
|
120925
|
-
var
|
|
121027
|
+
var log21 = createLogger("lsp");
|
|
120926
121028
|
var LANG_SERVER_CONFIG = {
|
|
120927
121029
|
typescript: { command: "typescript-language-server", args: ["--stdio"] }
|
|
120928
121030
|
};
|
|
@@ -120950,7 +121052,7 @@ async function getOrSpawnServer(workspaceId, lang) {
|
|
|
120950
121052
|
const workspaceBin = join17(cwd, "node_modules/.bin");
|
|
120951
121053
|
const pathSep = process.platform === "win32" ? ";" : ":";
|
|
120952
121054
|
const combinedPath = [bundledBin, appBin, workspaceBin, resolvedPath].join(pathSep);
|
|
120953
|
-
|
|
121055
|
+
log21.debug("Spawning %s language server in %s for workspace %s", lang, cwd, workspaceId);
|
|
120954
121056
|
const child = spawn6(config2.command, config2.args, {
|
|
120955
121057
|
cwd,
|
|
120956
121058
|
stdio: ["pipe", "pipe", "pipe"],
|
|
@@ -120978,15 +121080,15 @@ async function getOrSpawnServer(workspaceId, lang) {
|
|
|
120978
121080
|
}
|
|
120979
121081
|
ids.add(serverId);
|
|
120980
121082
|
child.on("exit", (code) => {
|
|
120981
|
-
|
|
121083
|
+
log21.debug("Language server exited: %s (code %s)", serverId, String(code));
|
|
120982
121084
|
removeSession();
|
|
120983
121085
|
});
|
|
120984
121086
|
child.on("error", (err) => {
|
|
120985
|
-
|
|
121087
|
+
log21.error("Language server error: %s \u2014 %s", serverId, err.message);
|
|
120986
121088
|
removeSession();
|
|
120987
121089
|
});
|
|
120988
121090
|
child.stderr?.on("data", (chunk) => {
|
|
120989
|
-
|
|
121091
|
+
log21.debug("LSP stderr [%s]: %s", serverId, chunk.toString().trimEnd());
|
|
120990
121092
|
});
|
|
120991
121093
|
await new Promise((resolve7, reject) => {
|
|
120992
121094
|
child.once("spawn", resolve7);
|
|
@@ -121016,7 +121118,7 @@ function killAllServers() {
|
|
|
121016
121118
|
|
|
121017
121119
|
// src/lib/lsp-proxy.ts
|
|
121018
121120
|
init_src();
|
|
121019
|
-
var
|
|
121121
|
+
var log22 = createLogger("lsp-proxy");
|
|
121020
121122
|
function frameMessage(json2) {
|
|
121021
121123
|
const body = Buffer.from(json2, "utf-8");
|
|
121022
121124
|
const header = `Content-Length: ${body.byteLength}\r
|
|
@@ -121034,7 +121136,7 @@ function createFrameParser(onMessage) {
|
|
|
121034
121136
|
const headerStr = buffer.subarray(0, separatorIdx).toString("ascii");
|
|
121035
121137
|
const match = headerStr.match(/Content-Length:\s*(\d+)/i);
|
|
121036
121138
|
if (!match) {
|
|
121037
|
-
|
|
121139
|
+
log22.warn("Malformed LSP header: %s", headerStr);
|
|
121038
121140
|
buffer = buffer.subarray(separatorIdx + 4);
|
|
121039
121141
|
continue;
|
|
121040
121142
|
}
|
|
@@ -121067,7 +121169,7 @@ async function handleLspConnection(ws, req) {
|
|
|
121067
121169
|
session = await getOrSpawnServer(workspaceId, lang);
|
|
121068
121170
|
} catch (err) {
|
|
121069
121171
|
const message = err instanceof Error ? err.message : String(err);
|
|
121070
|
-
|
|
121172
|
+
log22.error(
|
|
121071
121173
|
"Failed to spawn %s language server for workspace %s: %s",
|
|
121072
121174
|
lang,
|
|
121073
121175
|
workspaceId,
|
|
@@ -121081,12 +121183,12 @@ async function handleLspConnection(ws, req) {
|
|
|
121081
121183
|
ws.close(4002, "Language server stdio not available");
|
|
121082
121184
|
return;
|
|
121083
121185
|
}
|
|
121084
|
-
|
|
121186
|
+
log22.debug("LSP client connected: %s/%s", workspaceId, lang);
|
|
121085
121187
|
const pendingRequests = /* @__PURE__ */ new Map();
|
|
121086
121188
|
const retriedIds = /* @__PURE__ */ new Set();
|
|
121087
121189
|
const RETRY_DELAY_MS = 2e3;
|
|
121088
121190
|
const parseFrame = createFrameParser((json2) => {
|
|
121089
|
-
|
|
121191
|
+
log22.debug(
|
|
121090
121192
|
"LSP stdout [%s/%s]: %s",
|
|
121091
121193
|
workspaceId,
|
|
121092
121194
|
lang,
|
|
@@ -121098,7 +121200,7 @@ async function handleLspConnection(ws, req) {
|
|
|
121098
121200
|
const originalRequest = pendingRequests.get(msg.id);
|
|
121099
121201
|
retriedIds.add(msg.id);
|
|
121100
121202
|
pendingRequests.delete(msg.id);
|
|
121101
|
-
|
|
121203
|
+
log22.debug(
|
|
121102
121204
|
"LSP retrying request %d after 'No Project' error [%s/%s]",
|
|
121103
121205
|
msg.id,
|
|
121104
121206
|
workspaceId,
|
|
@@ -121120,14 +121222,14 @@ async function handleLspConnection(ws, req) {
|
|
|
121120
121222
|
const onStdoutData = (chunk) => parseFrame(chunk);
|
|
121121
121223
|
lspProcess.stdout.on("data", onStdoutData);
|
|
121122
121224
|
const onExit = (code) => {
|
|
121123
|
-
|
|
121225
|
+
log22.debug("LSP server exited (code %s), closing WebSocket", String(code));
|
|
121124
121226
|
if (ws.readyState === ws.OPEN) {
|
|
121125
121227
|
ws.close(1e3, "Language server exited");
|
|
121126
121228
|
}
|
|
121127
121229
|
};
|
|
121128
121230
|
lspProcess.on("exit", onExit);
|
|
121129
121231
|
function forwardToStdin(json2) {
|
|
121130
|
-
|
|
121232
|
+
log22.debug(
|
|
121131
121233
|
"LSP stdin [%s/%s]: %s",
|
|
121132
121234
|
workspaceId,
|
|
121133
121235
|
lang,
|
|
@@ -121154,7 +121256,7 @@ async function handleLspConnection(ws, req) {
|
|
|
121154
121256
|
ws.on("close", () => {
|
|
121155
121257
|
lspProcess.stdout?.off("data", onStdoutData);
|
|
121156
121258
|
lspProcess.off("exit", onExit);
|
|
121157
|
-
|
|
121259
|
+
log22.debug("LSP client disconnected: %s/%s (server kept alive)", workspaceId, lang);
|
|
121158
121260
|
});
|
|
121159
121261
|
}
|
|
121160
121262
|
|
|
@@ -121683,7 +121785,7 @@ async function installHooks() {
|
|
|
121683
121785
|
}
|
|
121684
121786
|
|
|
121685
121787
|
// src/lib/setup.ts
|
|
121686
|
-
var
|
|
121788
|
+
var log23 = createLogger("setup");
|
|
121687
121789
|
var AGENT_CHECKS = [
|
|
121688
121790
|
{ id: "claude-code", type: "claude-code", label: "Claude Code", binary: "claude" },
|
|
121689
121791
|
{ id: "codex", type: "codex", label: "Codex", binary: "codex" },
|
|
@@ -121700,7 +121802,7 @@ async function runFirstTimeSetup() {
|
|
|
121700
121802
|
]);
|
|
121701
121803
|
for (const r6 of results) {
|
|
121702
121804
|
if (r6.status === "rejected") {
|
|
121703
|
-
|
|
121805
|
+
log23.warn(
|
|
121704
121806
|
"Setup step failed: %s",
|
|
121705
121807
|
r6.reason instanceof Error ? r6.reason.message : String(r6.reason)
|
|
121706
121808
|
);
|
|
@@ -121715,7 +121817,7 @@ async function ensureProjectStateInSync() {
|
|
|
121715
121817
|
try {
|
|
121716
121818
|
await syncWorktrees();
|
|
121717
121819
|
} catch (err) {
|
|
121718
|
-
|
|
121820
|
+
log23.warn(
|
|
121719
121821
|
"Failed to sync project state at boot: %s",
|
|
121720
121822
|
err instanceof Error ? err.message : String(err)
|
|
121721
121823
|
);
|
|
@@ -121726,22 +121828,22 @@ async function ensureCliInstalled() {
|
|
|
121726
121828
|
try {
|
|
121727
121829
|
cliStatus = await checkCli();
|
|
121728
121830
|
} catch (err) {
|
|
121729
|
-
|
|
121831
|
+
log23.warn("Could not check CLI status: %s", err instanceof Error ? err.message : String(err));
|
|
121730
121832
|
return;
|
|
121731
121833
|
}
|
|
121732
121834
|
if (cliStatus === "Installed") {
|
|
121733
121835
|
return;
|
|
121734
121836
|
}
|
|
121735
121837
|
if (cliStatus !== "NotInstalled") {
|
|
121736
|
-
|
|
121838
|
+
log23.warn("CLI not auto-installed (status: %s)", cliStatus);
|
|
121737
121839
|
return;
|
|
121738
121840
|
}
|
|
121739
|
-
|
|
121841
|
+
log23.info("Installing band CLI...");
|
|
121740
121842
|
try {
|
|
121741
121843
|
await installCli();
|
|
121742
|
-
|
|
121844
|
+
log23.info("CLI installed to /usr/local/bin/band");
|
|
121743
121845
|
} catch (err) {
|
|
121744
|
-
|
|
121846
|
+
log23.warn("CLI installation failed: %s", err instanceof Error ? err.message : String(err));
|
|
121745
121847
|
}
|
|
121746
121848
|
}
|
|
121747
121849
|
async function ensureDefaultCodingAgents() {
|
|
@@ -121750,17 +121852,17 @@ async function ensureDefaultCodingAgents() {
|
|
|
121750
121852
|
if (Array.isArray(existing) && existing.length > 0) {
|
|
121751
121853
|
return;
|
|
121752
121854
|
}
|
|
121753
|
-
|
|
121855
|
+
log23.info("Detecting installed coding agents...");
|
|
121754
121856
|
const detected = [];
|
|
121755
121857
|
for (const check2 of AGENT_CHECKS) {
|
|
121756
121858
|
const path3 = await whichBinary(check2.binary);
|
|
121757
121859
|
if (path3) {
|
|
121758
|
-
|
|
121860
|
+
log23.info("Detected coding agent: %s (%s)", check2.id, path3);
|
|
121759
121861
|
detected.push({ id: check2.id, type: check2.type, label: check2.label });
|
|
121760
121862
|
}
|
|
121761
121863
|
}
|
|
121762
121864
|
if (detected.length === 0) {
|
|
121763
|
-
|
|
121865
|
+
log23.info("No coding agent CLIs detected on PATH");
|
|
121764
121866
|
return;
|
|
121765
121867
|
}
|
|
121766
121868
|
const current = loadSettings();
|
|
@@ -121769,7 +121871,7 @@ async function ensureDefaultCodingAgents() {
|
|
|
121769
121871
|
current.defaultCodingAgent = detected[0].id;
|
|
121770
121872
|
}
|
|
121771
121873
|
saveSettings(current);
|
|
121772
|
-
|
|
121874
|
+
log23.info("Enabled %d coding agent(s); default = %s", detected.length, current.defaultCodingAgent);
|
|
121773
121875
|
}
|
|
121774
121876
|
function ensureNotificationDefaults() {
|
|
121775
121877
|
const settings = loadSettings();
|
|
@@ -121781,7 +121883,7 @@ function ensureNotificationDefaults() {
|
|
|
121781
121883
|
...settings,
|
|
121782
121884
|
notifications: { ...notifications, soundOnNeedsAttention: true }
|
|
121783
121885
|
});
|
|
121784
|
-
|
|
121886
|
+
log23.info("Set default notifications.soundOnNeedsAttention = true");
|
|
121785
121887
|
}
|
|
121786
121888
|
async function ensureClaudeHooks() {
|
|
121787
121889
|
try {
|
|
@@ -121790,9 +121892,9 @@ async function ensureClaudeHooks() {
|
|
|
121790
121892
|
return;
|
|
121791
121893
|
}
|
|
121792
121894
|
await installHooks();
|
|
121793
|
-
|
|
121895
|
+
log23.info("Installed Claude Code hooks");
|
|
121794
121896
|
} catch (err) {
|
|
121795
|
-
|
|
121897
|
+
log23.warn(
|
|
121796
121898
|
"Failed to install Claude Code hooks: %s",
|
|
121797
121899
|
err instanceof Error ? err.message : String(err)
|
|
121798
121900
|
);
|
|
@@ -121800,11 +121902,11 @@ async function ensureClaudeHooks() {
|
|
|
121800
121902
|
}
|
|
121801
121903
|
async function ensureSkillsInstalled() {
|
|
121802
121904
|
try {
|
|
121803
|
-
const result = await installSkills({ log:
|
|
121905
|
+
const result = await installSkills({ log: log23 });
|
|
121804
121906
|
const wrote = result.written.length + result.updated.length;
|
|
121805
121907
|
const linkChange = result.linked.length;
|
|
121806
121908
|
if (wrote > 0 || linkChange > 0 || result.conflicts.length > 0) {
|
|
121807
|
-
|
|
121909
|
+
log23.info(
|
|
121808
121910
|
"Synced CLI skills (shared: %d written, %d updated, %d unchanged; symlinks: %d created, %d already-linked, %d conflicts, %d skipped)",
|
|
121809
121911
|
result.written.length,
|
|
121810
121912
|
result.updated.length,
|
|
@@ -121816,7 +121918,7 @@ async function ensureSkillsInstalled() {
|
|
|
121816
121918
|
);
|
|
121817
121919
|
}
|
|
121818
121920
|
} catch (err) {
|
|
121819
|
-
|
|
121921
|
+
log23.warn("Failed to sync CLI skills: %s", err instanceof Error ? err.message : String(err));
|
|
121820
121922
|
}
|
|
121821
121923
|
}
|
|
121822
121924
|
|
|
@@ -121850,7 +121952,7 @@ function removeTerminalFromLayout(workspaceId, terminalId) {
|
|
|
121850
121952
|
}
|
|
121851
121953
|
|
|
121852
121954
|
// src/lib/terminal-manager.ts
|
|
121853
|
-
var
|
|
121955
|
+
var log24 = createLogger("terminal");
|
|
121854
121956
|
var MAX_SCROLLBACK_SIZE = 1e5;
|
|
121855
121957
|
var terminals = /* @__PURE__ */ new Map();
|
|
121856
121958
|
var workspaceTerminals = /* @__PURE__ */ new Map();
|
|
@@ -121881,11 +121983,11 @@ async function spawnTerminal(workspaceId, terminalId, options2) {
|
|
|
121881
121983
|
if (options2?.cwd) {
|
|
121882
121984
|
const resolved = join21(workspaceRoot, options2.cwd);
|
|
121883
121985
|
if (!resolved.startsWith(workspaceRoot)) {
|
|
121884
|
-
|
|
121986
|
+
log24.warn("Ignoring cwd %s \u2014 resolves outside workspace root %s", options2.cwd, workspaceRoot);
|
|
121885
121987
|
} else if (existsSync7(resolved)) {
|
|
121886
121988
|
cwd = resolved;
|
|
121887
121989
|
} else {
|
|
121888
|
-
|
|
121990
|
+
log24.warn("Ignoring cwd %s \u2014 directory does not exist", options2.cwd);
|
|
121889
121991
|
}
|
|
121890
121992
|
}
|
|
121891
121993
|
if (!existsSync7(cwd)) {
|
|
@@ -121894,7 +121996,7 @@ async function spawnTerminal(workspaceId, terminalId, options2) {
|
|
|
121894
121996
|
if (!existsSync7(shell)) {
|
|
121895
121997
|
throw new Error(`Shell not found: ${shell}`);
|
|
121896
121998
|
}
|
|
121897
|
-
|
|
121999
|
+
log24.debug(
|
|
121898
122000
|
"Spawning shell %s in %s for terminal %s (PATH=%s)",
|
|
121899
122001
|
shell,
|
|
121900
122002
|
cwd,
|
|
@@ -121913,7 +122015,7 @@ async function spawnTerminal(workspaceId, terminalId, options2) {
|
|
|
121913
122015
|
});
|
|
121914
122016
|
} catch (err) {
|
|
121915
122017
|
const msg = err instanceof Error ? err.message : String(err);
|
|
121916
|
-
|
|
122018
|
+
log24.error("pty.spawn failed: %s (shell=%s, cwd=%s)", msg, shell, cwd);
|
|
121917
122019
|
throw err;
|
|
121918
122020
|
}
|
|
121919
122021
|
const session = { pty: ptyProcess, scrollback: "", workspaceId };
|
|
@@ -121949,7 +122051,7 @@ async function spawnTerminal(workspaceId, terminalId, options2) {
|
|
|
121949
122051
|
}
|
|
121950
122052
|
});
|
|
121951
122053
|
ptyProcess.onExit(() => {
|
|
121952
|
-
|
|
122054
|
+
log24.debug("Terminal exited: %s (workspace %s)", terminalId, workspaceId);
|
|
121953
122055
|
terminals.delete(terminalId);
|
|
121954
122056
|
outputListeners.delete(terminalId);
|
|
121955
122057
|
const set = workspaceTerminals.get(workspaceId);
|
|
@@ -122057,7 +122159,7 @@ function killAllTerminals() {
|
|
|
122057
122159
|
|
|
122058
122160
|
// src/lib/terminal-ws.ts
|
|
122059
122161
|
init_src();
|
|
122060
|
-
var
|
|
122162
|
+
var log25 = createLogger("terminal-ws");
|
|
122061
122163
|
var MAX_CLOSE_REASON_BYTES = 123;
|
|
122062
122164
|
function clampCloseReason(reason) {
|
|
122063
122165
|
const enc = new TextEncoder();
|
|
@@ -122121,7 +122223,7 @@ async function handleTerminalConnection(ws, req) {
|
|
|
122121
122223
|
session = await spawnTerminal(workspaceId, terminalId, spawnOpts);
|
|
122122
122224
|
} catch (err) {
|
|
122123
122225
|
const msg = err instanceof Error ? err.message : String(err);
|
|
122124
|
-
|
|
122226
|
+
log25.error("Failed to spawn terminal %s for workspace %s: %s", terminalId, workspaceId, msg);
|
|
122125
122227
|
safeClose(ws, 4001, msg);
|
|
122126
122228
|
return;
|
|
122127
122229
|
}
|
|
@@ -122135,7 +122237,7 @@ async function handleTerminalConnection(ws, req) {
|
|
|
122135
122237
|
});
|
|
122136
122238
|
}
|
|
122137
122239
|
function attachSession(ws, terminalId, workspaceId, session, isNew) {
|
|
122138
|
-
|
|
122240
|
+
log25.debug(
|
|
122139
122241
|
"Terminal %s: %s (workspace %s)",
|
|
122140
122242
|
isNew ? "connected" : "reconnected",
|
|
122141
122243
|
terminalId,
|
|
@@ -122164,7 +122266,7 @@ function attachSession(ws, terminalId, workspaceId, session, isNew) {
|
|
|
122164
122266
|
}, 3e3);
|
|
122165
122267
|
const exitDisposable = session.pty.onExit(({ exitCode }) => {
|
|
122166
122268
|
clearInterval(processInterval);
|
|
122167
|
-
|
|
122269
|
+
log25.debug("PTY exited with code %d for terminal %s", exitCode, terminalId);
|
|
122168
122270
|
if (ws.readyState === ws.OPEN) {
|
|
122169
122271
|
ws.close(1e3, "Terminal exited");
|
|
122170
122272
|
}
|
|
@@ -122176,7 +122278,7 @@ function attachSession(ws, terminalId, workspaceId, session, isNew) {
|
|
|
122176
122278
|
clearInterval(processInterval);
|
|
122177
122279
|
dataDisposable.dispose();
|
|
122178
122280
|
exitDisposable.dispose();
|
|
122179
|
-
|
|
122281
|
+
log25.debug("Terminal disconnected: %s (PTY kept alive)", terminalId);
|
|
122180
122282
|
});
|
|
122181
122283
|
}
|
|
122182
122284
|
function handleMessage(ws, terminalId, session, message) {
|
|
@@ -122214,7 +122316,7 @@ function getToken() {
|
|
|
122214
122316
|
}
|
|
122215
122317
|
|
|
122216
122318
|
// src/lib/tunnel.ts
|
|
122217
|
-
var
|
|
122319
|
+
var log26 = createLogger("tunnel");
|
|
122218
122320
|
var tunnelProcess = null;
|
|
122219
122321
|
var tunnelUrl = null;
|
|
122220
122322
|
var startInProgress = null;
|
|
@@ -122228,7 +122330,7 @@ function appendToken(baseUrl, token) {
|
|
|
122228
122330
|
}
|
|
122229
122331
|
function spawnTunnel(options2, resolvedPath) {
|
|
122230
122332
|
const args = ["tunnel", "--config", "/dev/null", "--url", `http://localhost:${options2.port}`];
|
|
122231
|
-
|
|
122333
|
+
log26.debug("spawning cloudflared %s", args.join(" "));
|
|
122232
122334
|
return new Promise((resolve7, reject) => {
|
|
122233
122335
|
const child = spawn7("cloudflared", args, {
|
|
122234
122336
|
env: { ...process.env, PATH: resolvedPath },
|
|
@@ -122242,12 +122344,12 @@ function spawnTunnel(options2, resolvedPath) {
|
|
|
122242
122344
|
for (const line2 of text3.split("\n")) {
|
|
122243
122345
|
const trimmed = line2.trim();
|
|
122244
122346
|
if (!trimmed) continue;
|
|
122245
|
-
|
|
122347
|
+
log26.debug("output: %s", trimmed);
|
|
122246
122348
|
const url = extractUrl(trimmed);
|
|
122247
122349
|
if (url) {
|
|
122248
122350
|
const token = getToken();
|
|
122249
122351
|
tunnelUrl = appendToken(url, token);
|
|
122250
|
-
|
|
122352
|
+
log26.debug("detected URL: %s", tunnelUrl);
|
|
122251
122353
|
emit({ kind: "tunnel-url", url: tunnelUrl });
|
|
122252
122354
|
if (!settled) {
|
|
122253
122355
|
settled = true;
|
|
@@ -122262,7 +122364,7 @@ function spawnTunnel(options2, resolvedPath) {
|
|
|
122262
122364
|
handleOutput(data);
|
|
122263
122365
|
});
|
|
122264
122366
|
child.on("error", (err) => {
|
|
122265
|
-
|
|
122367
|
+
log26.debug("process error: %s", err.message);
|
|
122266
122368
|
tunnelProcess = null;
|
|
122267
122369
|
tunnelUrl = null;
|
|
122268
122370
|
emit({ kind: "tunnel-error", error: err.message });
|
|
@@ -122272,7 +122374,7 @@ function spawnTunnel(options2, resolvedPath) {
|
|
|
122272
122374
|
}
|
|
122273
122375
|
});
|
|
122274
122376
|
child.on("exit", (code) => {
|
|
122275
|
-
|
|
122377
|
+
log26.debug("process exited with code: %d", code ?? -1);
|
|
122276
122378
|
const wasRunning = tunnelProcess !== null && settled;
|
|
122277
122379
|
tunnelProcess = null;
|
|
122278
122380
|
tunnelUrl = null;
|
|
@@ -122294,7 +122396,7 @@ function spawnTunnel(options2, resolvedPath) {
|
|
|
122294
122396
|
});
|
|
122295
122397
|
setTimeout(() => {
|
|
122296
122398
|
if (!settled) {
|
|
122297
|
-
|
|
122399
|
+
log26.debug("30s timeout reached, resolving without URL");
|
|
122298
122400
|
settled = true;
|
|
122299
122401
|
resolve7();
|
|
122300
122402
|
}
|
|
@@ -122303,12 +122405,12 @@ function spawnTunnel(options2, resolvedPath) {
|
|
|
122303
122405
|
}
|
|
122304
122406
|
async function startTunnel(options2) {
|
|
122305
122407
|
if (startInProgress) {
|
|
122306
|
-
|
|
122408
|
+
log26.debug("startTunnel: start already in progress, waiting...");
|
|
122307
122409
|
await startInProgress;
|
|
122308
122410
|
return;
|
|
122309
122411
|
}
|
|
122310
122412
|
if (tunnelProcess) {
|
|
122311
|
-
|
|
122413
|
+
log26.debug("startTunnel: already running, re-emitting URL");
|
|
122312
122414
|
if (tunnelUrl) {
|
|
122313
122415
|
emit({ kind: "tunnel-url", url: tunnelUrl });
|
|
122314
122416
|
}
|
|
@@ -133734,7 +133836,7 @@ function createContext8() {
|
|
|
133734
133836
|
|
|
133735
133837
|
// src/trpc/router.ts
|
|
133736
133838
|
init_src();
|
|
133737
|
-
import { execFile as
|
|
133839
|
+
import { execFile as execFile6, execFileSync as execFileSync2, spawn as spawn8 } from "node:child_process";
|
|
133738
133840
|
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
133739
133841
|
import {
|
|
133740
133842
|
existsSync as existsSync9,
|
|
@@ -133856,7 +133958,7 @@ function clearHistory(workspaceId, range, now = Date.now()) {
|
|
|
133856
133958
|
|
|
133857
133959
|
// src/lib/chat-session-summary.ts
|
|
133858
133960
|
init_src();
|
|
133859
|
-
var
|
|
133961
|
+
var log27 = createLogger("chat-session-summary");
|
|
133860
133962
|
var REFRESH_KEY = Symbol.for("band.chat-session-summary.refresh");
|
|
133861
133963
|
var g15 = globalThis;
|
|
133862
133964
|
if (!g15[REFRESH_KEY]) g15[REFRESH_KEY] = /* @__PURE__ */ new Map();
|
|
@@ -133878,7 +133980,7 @@ async function ensureActiveSessionSummary(chatId, worktreePath) {
|
|
|
133878
133980
|
}
|
|
133879
133981
|
return chat;
|
|
133880
133982
|
} catch (err) {
|
|
133881
|
-
|
|
133983
|
+
log27.warn({ chatId, err }, "ensureActiveSessionSummary failed");
|
|
133882
133984
|
return chat;
|
|
133883
133985
|
}
|
|
133884
133986
|
}
|
|
@@ -133905,7 +134007,56 @@ async function doRefresh(chatId, worktreePath) {
|
|
|
133905
134007
|
return;
|
|
133906
134008
|
}
|
|
133907
134009
|
} catch (err) {
|
|
133908
|
-
|
|
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();
|
|
133909
134060
|
}
|
|
133910
134061
|
}
|
|
133911
134062
|
|
|
@@ -134006,7 +134157,7 @@ init_src();
|
|
|
134006
134157
|
import { existsSync as existsSync8, realpathSync as realpathSync4 } from "node:fs";
|
|
134007
134158
|
import { basename, dirname as dirname6, isAbsolute, join as join22, resolve as resolvePath } from "node:path";
|
|
134008
134159
|
import prettier from "prettier";
|
|
134009
|
-
var
|
|
134160
|
+
var log28 = createLogger("formatter");
|
|
134010
134161
|
var FormatterError = class extends Error {
|
|
134011
134162
|
code;
|
|
134012
134163
|
detail;
|
|
@@ -134061,7 +134212,7 @@ async function formatFile(worktreePath, filePath, content2, options2 = {}) {
|
|
|
134061
134212
|
}
|
|
134062
134213
|
const changed = formatted !== content2;
|
|
134063
134214
|
if (changed) {
|
|
134064
|
-
|
|
134215
|
+
log28.info(
|
|
134065
134216
|
"Formatted %s with parser=%s (%d bytes in)",
|
|
134066
134217
|
absFile,
|
|
134067
134218
|
info.inferredParser,
|
|
@@ -134200,7 +134351,7 @@ function fuzzyScore(query, filePath) {
|
|
|
134200
134351
|
// src/lib/terminal-config.ts
|
|
134201
134352
|
init_src();
|
|
134202
134353
|
init_zod();
|
|
134203
|
-
var
|
|
134354
|
+
var log29 = createLogger("terminal-config");
|
|
134204
134355
|
var TerminalPaneConfigSchema = external_exports.object({
|
|
134205
134356
|
name: external_exports.string().optional(),
|
|
134206
134357
|
command: external_exports.string().optional(),
|
|
@@ -134231,7 +134382,7 @@ function loadWorkspaceTerminalConfig(worktreePath, projectPath) {
|
|
|
134231
134382
|
if (!terminalBlock) return null;
|
|
134232
134383
|
const result = WorkspaceTerminalConfigSchema.safeParse(terminalBlock);
|
|
134233
134384
|
if (!result.success) {
|
|
134234
|
-
|
|
134385
|
+
log29.warn(
|
|
134235
134386
|
"Invalid workspace.terminal config: %s",
|
|
134236
134387
|
result.error.issues.map((i2) => `${i2.path.join(".")}: ${i2.message}`).join("; ")
|
|
134237
134388
|
);
|
|
@@ -134241,8 +134392,8 @@ function loadWorkspaceTerminalConfig(worktreePath, projectPath) {
|
|
|
134241
134392
|
}
|
|
134242
134393
|
|
|
134243
134394
|
// src/trpc/router.ts
|
|
134244
|
-
var execFileAsync = promisify(
|
|
134245
|
-
var
|
|
134395
|
+
var execFileAsync = promisify(execFile6);
|
|
134396
|
+
var log30 = createLogger("trpc");
|
|
134246
134397
|
var t2 = initTRPC.context().create();
|
|
134247
134398
|
var publicProcedure = t2.procedure;
|
|
134248
134399
|
var projectsRouter = t2.router({
|
|
@@ -134352,7 +134503,14 @@ var projectsRouter = t2.router({
|
|
|
134352
134503
|
defaultBranch,
|
|
134353
134504
|
worktrees: worktrees2,
|
|
134354
134505
|
label: input.label ?? void 0,
|
|
134355
|
-
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"
|
|
134356
134514
|
};
|
|
134357
134515
|
state2.projects.push(project);
|
|
134358
134516
|
saveState(state2);
|
|
@@ -134543,13 +134701,13 @@ var workspacesRouter = t2.router({
|
|
|
134543
134701
|
try {
|
|
134544
134702
|
const deletedTasks = deleteWorkspaceTasks(workspaceId);
|
|
134545
134703
|
if (deletedTasks > 0) {
|
|
134546
|
-
|
|
134704
|
+
log30.info(
|
|
134547
134705
|
{ workspaceId, count: deletedTasks },
|
|
134548
134706
|
"deleted workspace tasks on removal"
|
|
134549
134707
|
);
|
|
134550
134708
|
}
|
|
134551
134709
|
} catch (err) {
|
|
134552
|
-
|
|
134710
|
+
log30.error({ workspaceId, err }, "failed to delete workspace tasks on removal");
|
|
134553
134711
|
}
|
|
134554
134712
|
emit({ kind: "remove", workspaceId });
|
|
134555
134713
|
const projPath = proj.path;
|
|
@@ -134567,7 +134725,7 @@ var workspacesRouter = t2.router({
|
|
|
134567
134725
|
timeout: 6e4
|
|
134568
134726
|
});
|
|
134569
134727
|
} catch (err) {
|
|
134570
|
-
|
|
134728
|
+
log30.warn({ err, workspaceId }, "teardown script failed");
|
|
134571
134729
|
}
|
|
134572
134730
|
}
|
|
134573
134731
|
try {
|
|
@@ -134585,7 +134743,7 @@ var workspacesRouter = t2.router({
|
|
|
134585
134743
|
encoding: "utf-8"
|
|
134586
134744
|
});
|
|
134587
134745
|
} catch (err) {
|
|
134588
|
-
|
|
134746
|
+
log30.warn({ err, workspaceId }, "git worktree prune failed");
|
|
134589
134747
|
}
|
|
134590
134748
|
}
|
|
134591
134749
|
try {
|
|
@@ -134597,7 +134755,7 @@ var workspacesRouter = t2.router({
|
|
|
134597
134755
|
} catch {
|
|
134598
134756
|
}
|
|
134599
134757
|
})().catch((err) => {
|
|
134600
|
-
|
|
134758
|
+
log30.error({ err, workspaceId }, "background workspace cleanup failed");
|
|
134601
134759
|
});
|
|
134602
134760
|
});
|
|
134603
134761
|
return { ok: true };
|
|
@@ -134678,7 +134836,7 @@ var workspacesRouter = t2.router({
|
|
|
134678
134836
|
throw new Error(`Script "${input.scriptType}" not found`);
|
|
134679
134837
|
}
|
|
134680
134838
|
return new Promise((resolve7, reject) => {
|
|
134681
|
-
|
|
134839
|
+
execFile6("bash", [scriptPath], { cwd: input.path }, (err) => {
|
|
134682
134840
|
if (err) {
|
|
134683
134841
|
reject(new Error(err.message));
|
|
134684
134842
|
} else {
|
|
@@ -134949,7 +135107,7 @@ var workspaceRouter = t2.router({
|
|
|
134949
135107
|
);
|
|
134950
135108
|
branches = output.trim().split("\n").map((b10) => b10.trim()).filter(Boolean);
|
|
134951
135109
|
} catch (err) {
|
|
134952
|
-
|
|
135110
|
+
log30.error(
|
|
134953
135111
|
`listBranches: for-each-ref failed for ${cwd}: ${err instanceof Error ? err.message : err}`
|
|
134954
135112
|
);
|
|
134955
135113
|
}
|
|
@@ -135809,21 +135967,21 @@ var tunnelRouter = t2.router({
|
|
|
135809
135967
|
return getTunnelStatus();
|
|
135810
135968
|
}),
|
|
135811
135969
|
start: publicProcedure.input(external_exports.object({}).optional()).mutation(async () => {
|
|
135812
|
-
|
|
135970
|
+
log30.debug("tunnel.start called");
|
|
135813
135971
|
const port = parseInt(process.env.BAND_PORT || "3456", 10);
|
|
135814
|
-
|
|
135972
|
+
log30.debug("tunnel.start: port=%d", port);
|
|
135815
135973
|
try {
|
|
135816
135974
|
await startTunnel({ port });
|
|
135817
135975
|
} catch (err) {
|
|
135818
|
-
|
|
135976
|
+
log30.debug({ err }, "tunnel.start: startTunnel failed");
|
|
135819
135977
|
return { ok: true, url: null };
|
|
135820
135978
|
}
|
|
135821
135979
|
const status = getTunnelStatus();
|
|
135822
|
-
|
|
135980
|
+
log30.debug({ status }, "tunnel.start: after startTunnel");
|
|
135823
135981
|
if (status.url) {
|
|
135824
135982
|
return { ok: true, url: status.url };
|
|
135825
135983
|
}
|
|
135826
|
-
|
|
135984
|
+
log30.debug("tunnel.start: no URL available");
|
|
135827
135985
|
return { ok: true, url: null };
|
|
135828
135986
|
}),
|
|
135829
135987
|
stop: publicProcedure.mutation(async () => {
|
|
@@ -135838,7 +135996,7 @@ var prereqsRouter = t2.router({
|
|
|
135838
135996
|
installTunnel: publicProcedure.mutation(async () => {
|
|
135839
135997
|
const resolvedPath = await shellPath();
|
|
135840
135998
|
await new Promise((resolve7, reject) => {
|
|
135841
|
-
|
|
135999
|
+
execFile6(
|
|
135842
136000
|
"brew",
|
|
135843
136001
|
["install", "cloudflared"],
|
|
135844
136002
|
{ env: { ...process.env, PATH: resolvedPath }, timeout: 12e4 },
|
|
@@ -136042,15 +136200,15 @@ var sessionsRouter = t2.router({
|
|
|
136042
136200
|
});
|
|
136043
136201
|
var servicesRouter = t2.router({
|
|
136044
136202
|
health: publicProcedure.query(() => {
|
|
136045
|
-
|
|
136203
|
+
log30.debug("services.health called");
|
|
136046
136204
|
const tunnel = getTunnelStatus();
|
|
136047
|
-
|
|
136205
|
+
log30.debug({ tunnel }, "services.health: tunnel status");
|
|
136048
136206
|
const result = {
|
|
136049
136207
|
webserver: true,
|
|
136050
136208
|
tunnel: tunnel.running,
|
|
136051
136209
|
tunnel_url: tunnel.url
|
|
136052
136210
|
};
|
|
136053
|
-
|
|
136211
|
+
log30.debug({ result }, "services.health result");
|
|
136054
136212
|
return result;
|
|
136055
136213
|
}),
|
|
136056
136214
|
// Activity level controls how often the branch-status poller fires.
|
|
@@ -136060,7 +136218,124 @@ var servicesRouter = t2.router({
|
|
|
136060
136218
|
setPollerActivity(input.activity);
|
|
136061
136219
|
return { activity: input.activity };
|
|
136062
136220
|
}),
|
|
136063
|
-
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
|
+
})
|
|
136064
136339
|
});
|
|
136065
136340
|
function canonicalizeMaybeMissing(p6) {
|
|
136066
136341
|
if (existsSync9(p6)) {
|
|
@@ -136103,11 +136378,12 @@ var editorRouter = t2.router({
|
|
|
136103
136378
|
/**
|
|
136104
136379
|
* Either an absolute filesystem path or a workspace-relative
|
|
136105
136380
|
* path. Paths inside the workspace root open as normal editor
|
|
136106
|
-
* tabs (
|
|
136107
|
-
*
|
|
136108
|
-
*
|
|
136109
|
-
*
|
|
136110
|
-
*
|
|
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.
|
|
136111
136387
|
*/
|
|
136112
136388
|
filePath: external_exports.string().min(1),
|
|
136113
136389
|
line: external_exports.number().int().positive().optional(),
|
|
@@ -136580,7 +136856,7 @@ var chatsRouter = t2.router({
|
|
|
136580
136856
|
summary = info?.summary;
|
|
136581
136857
|
lastModified = info?.lastModified;
|
|
136582
136858
|
} catch (err) {
|
|
136583
|
-
|
|
136859
|
+
log30.warn(
|
|
136584
136860
|
{ chatId: input.chatId, sessionId: input.sessionId, err },
|
|
136585
136861
|
"setActiveSession: getSessionInfo failed"
|
|
136586
136862
|
);
|
|
@@ -136700,7 +136976,7 @@ var browserHostRouter = t2.router({
|
|
|
136700
136976
|
// can confirm in the server log that the bridge component actually
|
|
136701
136977
|
// executed. Drop once the experiment is stable.
|
|
136702
136978
|
ping: publicProcedure.input(external_exports.object({ where: external_exports.string() })).mutation(({ input }) => {
|
|
136703
|
-
|
|
136979
|
+
log30.info("browserHost.ping from %s", input.where);
|
|
136704
136980
|
return { ok: true };
|
|
136705
136981
|
}),
|
|
136706
136982
|
ensureView: publicProcedure.subscription(async function* (opts) {
|
|
@@ -136826,8 +137102,86 @@ var historyRouter = t2.router({
|
|
|
136826
137102
|
var queuedFileSchema = external_exports.object({
|
|
136827
137103
|
mediaType: external_exports.string(),
|
|
136828
137104
|
url: external_exports.string(),
|
|
137105
|
+
path: external_exports.string().optional(),
|
|
136829
137106
|
filename: external_exports.string().optional()
|
|
136830
137107
|
});
|
|
137108
|
+
function isPathWithinUploadDir(p6) {
|
|
137109
|
+
const uploadDir = join23(bandHome(), "uploads");
|
|
137110
|
+
const normalized = resolve5(p6);
|
|
137111
|
+
if (normalized !== uploadDir && !normalized.startsWith(uploadDir + sep2)) {
|
|
137112
|
+
return false;
|
|
137113
|
+
}
|
|
137114
|
+
try {
|
|
137115
|
+
const canonicalUploadDir = realpathSync5(uploadDir);
|
|
137116
|
+
const canonicalPath = realpathSync5(p6);
|
|
137117
|
+
return canonicalPath === canonicalUploadDir || canonicalPath.startsWith(canonicalUploadDir + sep2);
|
|
137118
|
+
} catch {
|
|
137119
|
+
return true;
|
|
137120
|
+
}
|
|
137121
|
+
}
|
|
137122
|
+
async function resolveQueuedFiles(chatId, files) {
|
|
137123
|
+
if (!files || files.length === 0) return void 0;
|
|
137124
|
+
const resolved = [];
|
|
137125
|
+
const needsSave = [];
|
|
137126
|
+
const needsSaveIdx = [];
|
|
137127
|
+
for (let i2 = 0; i2 < files.length; i2++) {
|
|
137128
|
+
const file = files[i2];
|
|
137129
|
+
const uploadsUrlMatch = file.url.match(/^\/api\/uploads\/(.+)$/);
|
|
137130
|
+
const derivedPath = file.path ?? (uploadsUrlMatch ? join23(bandHome(), "uploads", uploadsUrlMatch[1]) : void 0);
|
|
137131
|
+
if (derivedPath) {
|
|
137132
|
+
if (!isPathWithinUploadDir(derivedPath)) {
|
|
137133
|
+
log30.warn(
|
|
137134
|
+
{ chatId, path: derivedPath, filename: file.filename },
|
|
137135
|
+
"queue: dropping file with path outside uploads directory"
|
|
137136
|
+
);
|
|
137137
|
+
continue;
|
|
137138
|
+
}
|
|
137139
|
+
resolved.push({
|
|
137140
|
+
mediaType: file.mediaType,
|
|
137141
|
+
url: file.url,
|
|
137142
|
+
path: derivedPath,
|
|
137143
|
+
...file.filename !== void 0 && { filename: file.filename }
|
|
137144
|
+
});
|
|
137145
|
+
continue;
|
|
137146
|
+
}
|
|
137147
|
+
if (file.url.startsWith("data:")) {
|
|
137148
|
+
needsSave.push(file);
|
|
137149
|
+
needsSaveIdx.push(resolved.length);
|
|
137150
|
+
resolved.push({
|
|
137151
|
+
mediaType: file.mediaType,
|
|
137152
|
+
url: file.url,
|
|
137153
|
+
path: "",
|
|
137154
|
+
filename: file.filename
|
|
137155
|
+
});
|
|
137156
|
+
continue;
|
|
137157
|
+
}
|
|
137158
|
+
log30.warn(
|
|
137159
|
+
{ chatId, url: file.url, filename: file.filename },
|
|
137160
|
+
"queue: dropping file with no path and non-data URL \u2014 cannot recover disk path"
|
|
137161
|
+
);
|
|
137162
|
+
}
|
|
137163
|
+
if (needsSave.length > 0) {
|
|
137164
|
+
const saved = await saveUploadedFilesDetailed(needsSave);
|
|
137165
|
+
if (saved.length !== needsSave.length) {
|
|
137166
|
+
log30.error(
|
|
137167
|
+
{ chatId, expected: needsSave.length, got: saved.length },
|
|
137168
|
+
"queue: saveUploadedFilesDetailed returned unexpected count \u2014 dropping data-URL files (cannot map 1:1)"
|
|
137169
|
+
);
|
|
137170
|
+
} else {
|
|
137171
|
+
for (let k4 = 0; k4 < saved.length; k4++) {
|
|
137172
|
+
const target = needsSaveIdx[k4];
|
|
137173
|
+
resolved[target] = {
|
|
137174
|
+
mediaType: saved[k4].mediaType,
|
|
137175
|
+
url: `/api/uploads/${saved[k4].storedName}`,
|
|
137176
|
+
path: saved[k4].path,
|
|
137177
|
+
...saved[k4].originalName !== void 0 && { filename: saved[k4].originalName }
|
|
137178
|
+
};
|
|
137179
|
+
}
|
|
137180
|
+
}
|
|
137181
|
+
}
|
|
137182
|
+
const finalized = resolved.filter((f10) => f10.path !== "");
|
|
137183
|
+
return finalized.length > 0 ? finalized : void 0;
|
|
137184
|
+
}
|
|
136831
137185
|
var queueRouter = t2.router({
|
|
136832
137186
|
push: publicProcedure.input(
|
|
136833
137187
|
external_exports.object({
|
|
@@ -136836,10 +137190,24 @@ var queueRouter = t2.router({
|
|
|
136836
137190
|
text: external_exports.string(),
|
|
136837
137191
|
files: external_exports.array(queuedFileSchema).optional()
|
|
136838
137192
|
})
|
|
136839
|
-
).mutation(({ input }) => {
|
|
137193
|
+
).mutation(async ({ input }) => {
|
|
136840
137194
|
const chatId = input.chatId ?? getOrCreateDefaultChat(input.workspaceId).id;
|
|
136841
|
-
|
|
136842
|
-
|
|
137195
|
+
let files;
|
|
137196
|
+
try {
|
|
137197
|
+
files = await resolveQueuedFiles(chatId, input.files);
|
|
137198
|
+
} catch (err) {
|
|
137199
|
+
log30.error(
|
|
137200
|
+
{ chatId, err: err instanceof Error ? err.message : err },
|
|
137201
|
+
"queue.push: failed to persist file uploads; enqueuing text only"
|
|
137202
|
+
);
|
|
137203
|
+
files = void 0;
|
|
137204
|
+
}
|
|
137205
|
+
const message = pushQueuedMessage(chatId, { text: input.text, files });
|
|
137206
|
+
return {
|
|
137207
|
+
ok: true,
|
|
137208
|
+
message: toWireQueuedMessages([message])[0],
|
|
137209
|
+
messages: toWireQueuedMessages(getQueuedMessages(chatId))
|
|
137210
|
+
};
|
|
136843
137211
|
}),
|
|
136844
137212
|
set: publicProcedure.input(
|
|
136845
137213
|
external_exports.object({
|
|
@@ -136853,20 +137221,44 @@ var queueRouter = t2.router({
|
|
|
136853
137221
|
})
|
|
136854
137222
|
)
|
|
136855
137223
|
})
|
|
136856
|
-
).mutation(({ input }) => {
|
|
137224
|
+
).mutation(async ({ input }) => {
|
|
136857
137225
|
const chatId = input.chatId ?? getOrCreateDefaultChat(input.workspaceId).id;
|
|
136858
|
-
|
|
136859
|
-
|
|
137226
|
+
const messages = await Promise.all(
|
|
137227
|
+
input.messages.map(async (m11) => {
|
|
137228
|
+
try {
|
|
137229
|
+
return {
|
|
137230
|
+
...m11.id !== void 0 && { id: m11.id },
|
|
137231
|
+
text: m11.text,
|
|
137232
|
+
files: await resolveQueuedFiles(chatId, m11.files)
|
|
137233
|
+
};
|
|
137234
|
+
} catch (err) {
|
|
137235
|
+
log30.error(
|
|
137236
|
+
{ chatId, messageId: m11.id, err: err instanceof Error ? err.message : err },
|
|
137237
|
+
"queue: failed to resolve files for queued message; dropping its files"
|
|
137238
|
+
);
|
|
137239
|
+
return {
|
|
137240
|
+
...m11.id !== void 0 && { id: m11.id },
|
|
137241
|
+
text: m11.text,
|
|
137242
|
+
files: void 0
|
|
137243
|
+
};
|
|
137244
|
+
}
|
|
137245
|
+
})
|
|
137246
|
+
);
|
|
137247
|
+
setQueuedMessages(chatId, messages);
|
|
137248
|
+
return { ok: true, messages: toWireQueuedMessages(getQueuedMessages(chatId)) };
|
|
136860
137249
|
}),
|
|
136861
137250
|
get: publicProcedure.input(external_exports.object({ workspaceId: external_exports.string(), chatId: external_exports.string().optional() })).query(({ input }) => {
|
|
136862
137251
|
const chatId = input.chatId ?? getOrCreateDefaultChat(input.workspaceId).id;
|
|
136863
|
-
|
|
136864
|
-
return { messages };
|
|
137252
|
+
return { messages: toWireQueuedMessages(getQueuedMessages(chatId)) };
|
|
136865
137253
|
}),
|
|
136866
137254
|
remove: publicProcedure.input(external_exports.object({ workspaceId: external_exports.string(), chatId: external_exports.string().optional(), id: external_exports.string() })).mutation(({ input }) => {
|
|
136867
137255
|
const chatId = input.chatId ?? getOrCreateDefaultChat(input.workspaceId).id;
|
|
136868
137256
|
const removed = removeQueuedMessage(chatId, input.id);
|
|
136869
|
-
return {
|
|
137257
|
+
return {
|
|
137258
|
+
ok: true,
|
|
137259
|
+
removed,
|
|
137260
|
+
messages: toWireQueuedMessages(getQueuedMessages(chatId))
|
|
137261
|
+
};
|
|
136870
137262
|
}),
|
|
136871
137263
|
update: publicProcedure.input(
|
|
136872
137264
|
external_exports.object({
|
|
@@ -136878,12 +137270,16 @@ var queueRouter = t2.router({
|
|
|
136878
137270
|
).mutation(({ input }) => {
|
|
136879
137271
|
const chatId = input.chatId ?? getOrCreateDefaultChat(input.workspaceId).id;
|
|
136880
137272
|
const updated = updateQueuedMessage(chatId, input.id, input.text);
|
|
136881
|
-
return {
|
|
137273
|
+
return {
|
|
137274
|
+
ok: true,
|
|
137275
|
+
updated,
|
|
137276
|
+
messages: toWireQueuedMessages(getQueuedMessages(chatId))
|
|
137277
|
+
};
|
|
136882
137278
|
}),
|
|
136883
137279
|
shift: publicProcedure.input(external_exports.object({ workspaceId: external_exports.string(), chatId: external_exports.string().optional() })).mutation(({ input }) => {
|
|
136884
137280
|
const chatId = input.chatId ?? getOrCreateDefaultChat(input.workspaceId).id;
|
|
136885
137281
|
const message = shiftQueuedMessage(chatId);
|
|
136886
|
-
return { message };
|
|
137282
|
+
return { message: message ? toWireQueuedMessages([message])[0] : null };
|
|
136887
137283
|
}),
|
|
136888
137284
|
clear: publicProcedure.input(external_exports.object({ workspaceId: external_exports.string(), chatId: external_exports.string().optional() })).mutation(({ input }) => {
|
|
136889
137285
|
const chatId = input.chatId ?? getOrCreateDefaultChat(input.workspaceId).id;
|
|
@@ -136903,12 +137299,13 @@ var queueRouter = t2.router({
|
|
|
136903
137299
|
unsubscribe();
|
|
136904
137300
|
resolve7?.();
|
|
136905
137301
|
});
|
|
136906
|
-
yield { messages: getQueuedMessages(chatId) };
|
|
137302
|
+
yield { messages: toWireQueuedMessages(getQueuedMessages(chatId)) };
|
|
136907
137303
|
queue.length = 0;
|
|
136908
137304
|
try {
|
|
136909
137305
|
while (!opts.signal?.aborted) {
|
|
136910
137306
|
while (queue.length > 0) {
|
|
136911
|
-
|
|
137307
|
+
const update = queue.shift();
|
|
137308
|
+
yield { messages: toWireQueuedMessages(update.messages) };
|
|
136912
137309
|
}
|
|
136913
137310
|
await new Promise((r6) => {
|
|
136914
137311
|
resolve7 = r6;
|