@overdeck/desktop 0.45.15 → 0.45.16
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/package.json +1 -1
- package/server/{acceptance-criteria-DHZk2ceV.js → acceptance-criteria-BZ_nQS1f.js} +2 -2
- package/server/{advancing-selfheal-CSuZ31bB.js → advancing-selfheal-DJYAvGv-.js} +6 -5
- package/server/{agent-gc-D_DxfBHR.js → agent-gc-D0wDIeV1.js} +3 -3
- package/server/{agent-state-EP2QFV9n.js → agent-state-lGvgPP4m.js} +1 -1
- package/server/{agent-state-service-C_2ZAQRP.js → agent-state-service-CZrayD_G.js} +1 -1
- package/server/{agent-state-service-BZkvgQf4.js → agent-state-service-DFslS5go.js} +9 -52
- package/server/{agents-CsOzAmRg.js → agents-B9GwfCyp.js} +99 -140
- package/server/{agents-DCvyTXNU.js → agents-CEcaxSkR.js} +1 -1
- package/server/{archive-planning-DkivCk1A.js → archive-planning-CbghE9-o.js} +5 -5
- package/server/{archive-planning-CTILQRnV.js → archive-planning-CoyIbgGK.js} +1 -1
- package/server/{artifact-index-jobs-CmsvQ1ey.js → artifact-index-jobs-CcSrUoSE.js} +2 -2
- package/server/{auto-commit-QAfsu3Sb.js → auto-commit-IW-eik_b.js} +1 -1
- package/server/{backlog-auto-trigger-ueRaT8Dy.js → backlog-auto-trigger-BfgDsII0.js} +3 -3
- package/server/{bd-process-lock-D3S4T4o-.js → bd-process-lock-XAXAet9O.js} +2 -2
- package/server/{beads-CYsLiyIM.js → beads-B1u04n3o.js} +1 -1
- package/server/{beads-BGGxrkZ5.js → beads-BeSMEjGT.js} +7 -7
- package/server/{beads-query-B1DlJVp9.js → beads-query-Dl4FhT8J.js} +2 -2
- package/server/{beads-restore-CyygSmmn.js → beads-restore-BUItPOjI.js} +2 -2
- package/server/behavior-BTpYbAv4.js +10 -0
- package/server/{briefing-freshness-Kh5V8RTh.js → briefing-freshness-DESTCWo-.js} +4 -4
- package/server/{checkpoint-manager-fu9oVsR-.js → checkpoint-manager-BwFdegJF.js} +2 -2
- package/server/{checkpoint-manager-CAFos8e1.js → checkpoint-manager-DWSXooZV.js} +1 -1
- package/server/checkpoint-worker.js +1 -1
- package/server/{checkpoints-1BqOlS4q.js → checkpoints-BtUonbs3.js} +2 -2
- package/server/{checkpoints-DvhGi8P_.js → checkpoints-fjadfOKF.js} +1 -1
- package/server/{claude-hooks-provision-s_wdpeVj.js → claude-hooks-provision-DAtxutOs.js} +132 -114
- package/server/claude-hooks-provision-DiK62u0k.js +3 -0
- package/server/{claude-permissions-CaWqysff.js → claude-permissions-CThLgf8d.js} +2 -2
- package/server/{claude-settings-overlay-CcTf0xzG.js → claude-settings-overlay-BF9MPIwx.js} +2 -2
- package/server/{claude-settings-overlay-BbA4FbVI.js → claude-settings-overlay-Dx_Uqcmv.js} +1 -1
- package/server/{cli-BwCvCUBK.js → cli-ByKIIMfT.js} +9 -9
- package/server/cli-D9cUTbBr.js +3 -0
- package/server/{cliproxy-BsoNNDAj.js → cliproxy-B4c1BUvs.js} +2 -2
- package/server/{cliproxy-C2xC-3vH.js → cliproxy-C_GuT5DU.js} +1 -1
- package/server/{close-issue-BleIwP3f.js → close-issue-BOuLKr6e.js} +5 -5
- package/server/{closed-issue-reaper-BwUUvjEW.js → closed-issue-reaper-CksfuiFD.js} +1 -1
- package/server/{closed-issue-reaper-mC5pujeb.js → closed-issue-reaper-DCAYzNXW.js} +9 -9
- package/server/{codex-B7DTpwEw.js → codex-BYPz6ZdF.js} +1 -1
- package/server/{codex-DW60_5j2.js → codex-BbqIRZjd.js} +6 -5
- package/server/{behavior-Cpj03N4v.js → codex-parser-mFYZh8vR.js} +3 -9
- package/server/{compact-beads-DKL54y6j.js → compact-beads-CyJtoXJi.js} +5 -5
- package/server/{compact-beads-CK_hHEnB.js → compact-beads-N00E4EVa.js} +1 -1
- package/server/{config-ZNnMpIlh.js → config-DVLdmnMJ.js} +2 -2
- package/server/{config-BRNQJXhA.js → config-Dj6N8EP9.js} +1 -1
- package/server/{config-yaml-Dcz-8uit.js → config-yaml-cNOZcEww.js} +91 -22
- package/server/{conflict-gate-DTje2Ll7.js → conflict-gate-BMKm_5DV.js} +3 -3
- package/server/{conflict-gate-DGT8jCLp.js → conflict-gate-CuXUv-bP.js} +1 -1
- package/server/{context-layers-ByOWUjUg.js → context-layers-CeAwSYNt.js} +2 -2
- package/server/{context-layers-BdUCQ-cl.js → context-layers-c0JqYHcS.js} +3 -3
- package/server/{control-settings-DwkAeooY.js → control-settings-D4EFsRBd.js} +4 -4
- package/server/{conversation-compaction-OTYgd6eg.js → conversation-compaction-BCggyih4.js} +8 -8
- package/server/{conversation-compaction-WYQZUVDm.js → conversation-compaction-kHVfVRg3.js} +1 -1
- package/server/{conversation-service-BR1OgvxO.js → conversation-service-B8LFQQm1.js} +6 -5
- package/server/{conversation-service-C_kNZPLx.js → conversation-service-BTzObqGi.js} +1 -1
- package/server/{conversations-DG2M8WnT.js → conversations-B-lcHv-5.js} +4 -4
- package/server/{conversations-izHvSoAR.js → conversations-BM7zlXjr.js} +1 -1
- package/server/{cost-B2mj17iG.js → cost-BcpRQ-7o.js} +3 -3
- package/server/{cost-DQ2ajr_m.js → cost-D9kPIY_5.js} +2 -2
- package/server/{cost-sync-gTayEuWP.js → cost-sync-DF6odxK9.js} +3 -3
- package/server/{dag-CqTehWpY.js → dag-DKI3sOmX.js} +3 -3
- package/server/{dangerous-git-ops-DDWQlPC3.js → dangerous-git-ops-Bn18PEcN.js} +1 -1
- package/server/dashboard-db-worker.js +6 -6
- package/server/{deacon-BqW9HMew.js → deacon-DONuopff.js} +3 -3
- package/server/{deacon-DrKDBeJL.js → deacon-DdARMjZq.js} +127 -107
- package/server/{deacon-nudge-log-D1wEK6zF.js → deacon-nudge-log-B-naf89q.js} +1 -1
- package/server/{deacon-swarm-CO_A7xyd.js → deacon-swarm-BNGkmYR_.js} +11 -11
- package/server/deacon-swarm-CvdFekIO.js +2 -0
- package/server/deacon.js +7 -7
- package/server/{devcontainer-renderer-BQolp_qZ.js → devcontainer-renderer-C-34Sxyz.js} +3 -3
- package/server/{dist-Bc32rWJB.js → dist-BMXvKiZP.js} +1 -1
- package/server/dist-BNwrgsUO.js +3 -0
- package/server/{dist-src-Byxt1ifL.js → dist-src-BgGUblXg.js} +1 -1
- package/server/{docker-s-esqZ__.js → docker-apZ9pBYw.js} +2 -2
- package/server/{ensure-devcontainer-DA4-jF6R.js → ensure-devcontainer-Bqi1EF1P.js} +4 -4
- package/server/{ensure-devcontainer-pUVaT0h3.js → ensure-devcontainer-Dq3KoOIl.js} +1 -1
- package/server/{esm-shims-CJHy8CZY.js → esm-shims-BEjvINX3.js} +1 -1
- package/server/{event-store-CcJAhKCl.js → event-store-CqDgfbAs.js} +1 -1
- package/server/{event-store-DRte2Rwt.js → event-store-D89fMfXS.js} +3 -3
- package/server/{events-Bej1w_k8.js → events-S_C0pvl6.js} +3 -3
- package/server/{events-CtsLScn8.js → events-rIGncmP1.js} +1 -1
- package/server/{export-Dx_qJ3h8.js → export-BJHSVwKP.js} +2 -2
- package/server/{factory-FN727tWr.js → factory-DV18m0rc.js} +5 -5
- package/server/{feature-registry-population-ie-yBcQC.js → feature-registry-population-CqZSnqQi.js} +4 -4
- package/server/{feature-registry-storage-CkZTFSsn.js → feature-registry-storage-BeXmNBwK.js} +2 -2
- package/server/{features-Dtm9ABuz.js → features-u5XeMaOK.js} +2 -2
- package/server/{feedback-target-BYtpyt1i.js → feedback-target-CwyWf0Dg.js} +6 -6
- package/server/{feedback-target-DVJQDiE4.js → feedback-target-DDG1PWl3.js} +1 -1
- package/server/{feedback-writer-DOUhyIW2.js → feedback-writer-BsJiw5aT.js} +1 -1
- package/server/{feedback-writer-fdE1BzeL.js → feedback-writer-D20HSXre.js} +4 -4
- package/server/{flywheel-CUErLAyN.js → flywheel-9Y1X7IM-.js} +13 -13
- package/server/{flywheel-Bv3wv2S6.js → flywheel-Dczmgchd.js} +12 -12
- package/server/{flywheel-Bi82iiNl.js → flywheel-RCnHAgc4.js} +1 -1
- package/server/{flywheel-merge-order-BaEN3iyN.js → flywheel-merge-order-CtCYsFJP.js} +7 -7
- package/server/{flywheel-merge-order-DXjeBnJ1.js → flywheel-merge-order-DEtEd3aK.js} +1 -1
- package/server/forge-8y6aEPTB.js +2 -0
- package/server/{forge-ButEdJ31.js → forge-DFDThFil.js} +2 -2
- package/server/{from-CbtTxftl.js → from-NSJypkI8.js} +1 -1
- package/server/{fts-db-CBgBLZcL.js → fts-db-C5A_TTOM.js} +2 -2
- package/server/{fts-operations-CI9Xuo_1.js → fts-operations-DvCSimfU.js} +2 -2
- package/server/{git-utils-BCLRWQ-y.js → git-utils-C0neHvQx.js} +1 -1
- package/server/{git-utils-ClfpP47N.js → git-utils-Dr0L7mFk.js} +2 -2
- package/server/{github-app-DRD2woO0.js → github-app-Bwt9lK4A.js} +1 -1
- package/server/{github-app-DscZ0_B6.js → github-app-u9-SX7Gc.js} +2 -2
- package/server/{github-client-DpiZnxGH.js → github-client-Btyy3uan.js} +3 -3
- package/server/{github-client-iFRw8f7e.js → github-client-Do3k-N1W.js} +1 -1
- package/server/{github-pr-lookup-D-EBexxC.js → github-pr-lookup-DOF1U2WW.js} +2 -2
- package/server/{harness-resolve-iMjyNUJ2.js → harness-resolve-C6g2R0Cd.js} +3 -3
- package/server/{health-events-CRdxDFN2.js → health-events-B4u-2a9m.js} +2 -2
- package/server/{health-events-B_WsQyYm.js → health-events-Bos3sk5g.js} +1 -1
- package/server/{hooks-C9b7Vqpw.js → hooks-BCoOjL_R.js} +2 -2
- package/server/{hooks-C1ScyVxP.js → hooks-uEr8WTx_.js} +1 -1
- package/server/{hume-TQ5pvOZ_.js → hume-BqxYKbUf.js} +2 -2
- package/server/hume-CerGi2RH.js +3 -0
- package/server/{idle-stack-reaper-B1kG7B_X.js → idle-stack-reaper-DbZ8ukMd.js} +2 -2
- package/server/{idle-stack-reaper-iFVOAoJy.js → idle-stack-reaper-H0W6XtHh.js} +1 -1
- package/server/{infra-bpq1MHKU.js → infra-Ba9mS6e6.js} +3 -3
- package/server/{injection-BLWfwTVZ.js → injection-C1DKXeIZ.js} +1 -1
- package/server/{injection-DJqWld1v.js → injection-yrMBxzVq.js} +7 -7
- package/server/{inspect-agent-DytCsltn.js → inspect-agent-B-mnb4uh.js} +9 -9
- package/server/inspect-agent-CWkeAB7J.js +2 -0
- package/server/{internal-token-CCaWaTwE.js → internal-token-BPYEaXFh.js} +1 -1
- package/server/{internal-token-CjlhdufS.js → internal-token-BtqSbKTx.js} +2 -2
- package/server/{io-BiQ2Cs3k.js → io-VEGSAqsd.js} +15 -22
- package/server/{issue-closed-FApNiOOs.js → issue-closed-BxcePXL-.js} +4 -4
- package/server/{issue-lifecycle-C-K53ASY.js → issue-lifecycle--8MRxrG1.js} +22 -22
- package/server/{issue-lifecycle-BkFWNjlD.js → issue-lifecycle-CdMUauyb.js} +1 -1
- package/server/{issue-service-singleton-CuHGpJJP.js → issue-service-singleton-CkTUI-eu.js} +10 -10
- package/server/{issue-service-singleton-bG1WdSdQ.js → issue-service-singleton-MZsDhAob.js} +1 -1
- package/server/{issues-CwQMphDH.js → issues-CBAsuoAO.js} +2 -2
- package/server/{jsonl-parser-dNIjHgym.js → jsonl-parser-BUW5_sSK.js} +3 -3
- package/server/{label-cleanup-DYvAZknd.js → label-cleanup-htK6fBRU.js} +3 -3
- package/server/{layers-CD6FysRU.js → layers-jjL16At6.js} +2 -2
- package/server/{lifecycle-C_73gi-C.js → lifecycle-Ck2UR27D.js} +7 -7
- package/server/{lifecycle-io-C_Wu0_i-.js → lifecycle-io-DXv8Utct.js} +1 -1
- package/server/{lifecycle-io-CeYxP3cE.js → lifecycle-io-IehcRt2v.js} +36 -47
- package/server/{linear-client-4qoKnuQu.js → linear-client-By7hjwuN.js} +1 -1
- package/server/{linear-client-EtVyblVz.js → linear-client-D9cSQfvD.js} +3 -3
- package/server/memory-fts-worker.js +1 -1
- package/server/{merge-brm721Es.js → merge-BLcEZNXz.js} +1 -1
- package/server/{merge-7rqkTUm2.js → merge-BN8FGJ2q.js} +3 -3
- package/server/{merge-agent-4Zhlgvqp.js → merge-agent-B3u2szOL.js} +29 -29
- package/server/{merge-agent-36wfYm2u.js → merge-agent-ejC7Wos8.js} +1 -1
- package/server/{merge-batch-itfnwdsT.js → merge-batch-DyqlgYGp.js} +1 -1
- package/server/{merge-blockers-Bto_Oe_o.js → merge-blockers-cq-aS2KG.js} +2 -2
- package/server/merge-ops-CFkQtXEj.js +2 -0
- package/server/{merge-rebase-Czfqfe4q.js → merge-rebase-Dl7yIxtV.js} +2 -2
- package/server/{merge-set-BIkGQL9j.js → merge-set-CZ9Nbay0.js} +3 -3
- package/server/{merge-set-G1RHcu3D.js → merge-set-Dy0D0r3i.js} +1 -1
- package/server/{merge-sync-DIrmlZUr.js → merge-sync-CG9kDCdT.js} +1 -1
- package/server/{merge-sync-B43Dybea.js → merge-sync-D7jWLgCC.js} +2 -2
- package/server/{merge-train-DGqVuNZV.js → merge-train-CH33XJOH.js} +3 -3
- package/server/{merge-train-deps-q15XLnAS.js → merge-train-deps-JoVdGnOg.js} +4 -4
- package/server/{merge-verification-Cqfxx6bE.js → merge-verification-D4wTChdX.js} +4 -4
- package/server/{multipart-parser-CiPxxfUH.js → multipart-parser-Csn8U-K9.js} +2 -2
- package/server/{no-resume-mode-yrPEQ_pC.js → no-resume-mode-Gh5R_YLF.js} +1 -1
- package/server/node_modules/.package-lock.json +1 -1
- package/server/{orphan-proposed-reconciler-DAD9FJtQ.js → orphan-proposed-reconciler-BIcNu4tl.js} +1 -1
- package/server/{orphan-proposed-reconciler-BWWHn4Lr.js → orphan-proposed-reconciler-DI_IS1p_.js} +10 -10
- package/server/package-lock.json +2 -2
- package/server/package.json +1 -1
- package/server/{pan-dir-Bj7Hy8iu.js → pan-dir-CQIfKG8c.js} +4 -4
- package/server/{paths-C9DkhIOT.js → paths-Blj6A9AJ.js} +2 -2
- package/server/{pickup-CKRuGDsB.js → pickup-BtvRBbvI.js} +1 -1
- package/server/{pipeline-notifier-BkKbQ8ji.js → pipeline-notifier-BH4PAi-w.js} +1 -1
- package/server/{pipeline-notifier-CAurUste.js → pipeline-notifier-D_WYtEwl.js} +2 -2
- package/server/{project-pipelines-BRWaGmI4.js → project-pipelines-jMTitpeO.js} +2 -2
- package/server/projects-CrBE6IhN.js +3 -0
- package/server/{prompts-DfI5qbTW.js → prompts-B3njaImU.js} +2 -2
- package/server/{providers-CWDXoaMA.js → providers-BbEyFhPX.js} +7 -7
- package/server/{providers-D-5txBRc.js → providers-DnPxkHoG.js} +1 -1
- package/server/public/assets/chunk-BO2N2NFS-3qh9TUJi.js +103 -0
- package/server/public/assets/{diagram-OG6HWLK6-Avtvq2qI.js → diagram-OG6HWLK6-D8UVTPj7.js} +1 -1
- package/server/public/assets/{dist-BEHQuasD.js → dist-BvLLn1YC.js} +3 -3
- package/server/public/assets/{dist-BvmY-qb1.js → dist-CyubL7Wj.js} +1 -1
- package/server/public/assets/{ganttDiagram-6RSMTGT7-7KhCd0fH.js → ganttDiagram-6RSMTGT7-BI4E1LbQ.js} +1 -1
- package/server/public/assets/{highlighted-body-OFNGDK62-iQoBMTf0.js → highlighted-body-OFNGDK62-D_bapWkF.js} +1 -1
- package/server/public/assets/index-BAZxZ-8I.js +796 -0
- package/server/public/assets/{index-DUFDmvmH.css → index-FBG3JBfq.css} +1 -1
- package/server/public/assets/{linear-CiJHW9g5.js → linear-CEdobObr.js} +1 -1
- package/server/public/assets/mermaid-GHXKKRXX-BYP8MI37.js +1 -0
- package/server/public/assets/{pieDiagram-4H26LBE5-BOhmvUhW.js → pieDiagram-4H26LBE5-DT79L01f.js} +1 -1
- package/server/public/assets/{prod-DmLBBqat.js → prod-CR_K2DFV.js} +4 -4
- package/server/public/assets/{quadrantDiagram-W4KKPZXB-Cjku660G.js → quadrantDiagram-W4KKPZXB-BEkKXXrL.js} +1 -1
- package/server/public/assets/{sankeyDiagram-5OEKKPKP-D52w5oPh.js → sankeyDiagram-5OEKKPKP-BxSCqn-j.js} +1 -1
- package/server/public/assets/{xychartDiagram-2RQKCTM6-BTO07_Iv.js → xychartDiagram-2RQKCTM6-DicwJGG_.js} +1 -1
- package/server/public/index.html +2 -2
- package/server/{pull-requests-CKZPWhjD.js → pull-requests-43LPDfM8.js} +1 -1
- package/server/{pull-requests-Bmre-Xlz.js → pull-requests-DyUkQl4W.js} +3 -3
- package/server/{rally-BBd9tQ__.js → rally-BtWjybOa.js} +3 -3
- package/server/{rally-api-DDc85HIz.js → rally-api-B-YA_oXx.js} +1 -1
- package/server/{rally-api-DxZFObI_.js → rally-api-B-osULNL.js} +2 -2
- package/server/{rally-client-BADHn0m_.js → rally-client-CzFymP7P.js} +1 -1
- package/server/{rally-client-DvvLiAQP.js → rally-client-sErNQBO0.js} +5 -5
- package/server/rally-oggyp4cs.js +3 -0
- package/server/{reap-terminal-sessions-D6JDJsqF.js → reap-terminal-sessions-2s-fvilz.js} +1 -1
- package/server/{reap-terminal-sessions-D_xvy-Mk.js → reap-terminal-sessions-DnDQ7pf9.js} +1 -1
- package/server/{rebuild-stack-D19i080j.js → rebuild-stack-CoU-HqZj.js} +6 -6
- package/server/{rebuild-stack-GOsWqXi3.js → rebuild-stack-nGD_nPZo.js} +1 -1
- package/server/{reconstruct-cache-lQrG4xGg.js → reconstruct-cache-Wj8GrYB0.js} +6 -6
- package/server/{record-pyB6VA32.js → record-lEYK__LD.js} +1 -1
- package/server/{recovery-trip-Dfh1tNHn.js → recovery-trip-BT7nb9OV.js} +2 -2
- package/server/{release-engine-DxcMWRuK.js → release-engine-CBLQXDlH.js} +5 -5
- package/server/{release-set-BYsgX7o6.js → release-set-BNiqi7hy.js} +3 -3
- package/server/{remote-DmeL21dF.js → remote-DW_TWQnr.js} +3 -3
- package/server/{remote-8W2Yhygw.js → remote-DcO9An_f.js} +3 -3
- package/server/{remote-agents-BfQBE6MN.js → remote-agents-C4cyxHQS.js} +6 -6
- package/server/{remote-agents-DlvbzO7m.js → remote-agents-Cv-U-_V8.js} +1 -1
- package/server/{remote-completion-BgkiSQmx.js → remote-completion-PhXGGFQy.js} +13 -13
- package/server/{resolver-dTpSSzaH.js → resolver-C7dLn8OK.js} +2 -2
- package/server/resume-BYZBIab-.js +3 -0
- package/server/{review-agent-D025Wt7w.js → review-agent-Dn-yn7Zj.js} +23 -23
- package/server/{review-agent-Rub0OpZc.js → review-agent-u5q3ip7H.js} +1 -1
- package/server/{review-artifacts-CX951jTU.js → review-artifacts-D4T04aYI.js} +6 -6
- package/server/{review-context-DGGGR_w5.js → review-context-Rc0VDLG_.js} +8 -8
- package/server/{review-monitor-0_qqMcnS.js → review-monitor-BC--miCO.js} +2 -2
- package/server/{review-status-Br6lAFGO.js → review-status-CG0iDuWa.js} +1 -1
- package/server/{review-status-4qqLkRMu.js → review-status-Dc1l4dVz.js} +18 -18
- package/server/{review-status-enrichment-Cr8m3uVL.js → review-status-enrichment-C1a1OG_1.js} +3 -3
- package/server/{review-status-sync-OC-l1lNt.js → review-status-sync-CAr-hfnJ.js} +2 -2
- package/server/{review-status-sync-D3KUhsdA.js → review-status-sync-CfSixhhX.js} +1 -1
- package/server/{review-verdict-feedback-DrWMuRaj.js → review-verdict-feedback-CVDbIDBe.js} +7 -7
- package/server/{review-verdict-feedback-YOzmsq9G.js → review-verdict-feedback-D2Q960wX.js} +1 -1
- package/server/{rollup-DmazRY0j.js → rollup-CakjztPl.js} +1 -1
- package/server/{rollup-CnxbwaLH.js → rollup-DctoIu-A.js} +8 -8
- package/server/{scanner-DE1MqAaF.js → scanner-BTM1jc_u.js} +7 -7
- package/server/{sequence-io-C0uoqfGx.js → sequence-io-pnoIDGv4.js} +4 -4
- package/server/{sequencer-agent-i-b2u4SJ.js → sequencer-agent-9Soi-WL-.js} +6 -6
- package/server/server.js +422 -1746
- package/server/{service-D0_gh2tl.js → service-DfTVoqJg.js} +46 -46
- package/server/{session-fork-DZ12vipL.js → session-fork-C4jAFHj8.js} +2 -2
- package/server/session-history-DanhhiCw.js +168 -0
- package/server/{settings-ByqjPtFO.js → settings-Cuc12oP_.js} +2 -2
- package/server/settings-Cy7SCFO9.js +2 -0
- package/server/{settings-DCC4BAqj.js → settings-DfT3f86D.js} +3 -3
- package/server/{shadow-engineering-BhnmtW5m.js → shadow-engineering-bKuKTCn-.js} +3 -3
- package/server/{shadow-state-ByXZehsy.js → shadow-state-CVHpRWlb.js} +1 -1
- package/server/{shadow-state-CKm8xWX9.js → shadow-state-DJz6_pb_.js} +2 -2
- package/server/{ship-log-DE_0Cv_i.js → ship-log-CwqPFfqx.js} +1 -1
- package/server/{smart-compaction-h4_ca6Uk.js → smart-compaction-B4KlpZGN.js} +1 -1
- package/server/{smart-compaction-D5Zen3AA.js → smart-compaction-CiWfGfRZ.js} +7 -7
- package/server/{spawn-planning-session-Dueit4WX.js → spawn-planning-session-CU-DwyDl.js} +15 -15
- package/server/{spawn-planning-session-Bgi7Ub02.js → spawn-planning-session-D5N3RuLG.js} +1 -1
- package/server/{specialist-completion-BZ8M-WZ0.js → specialist-completion-CJcv-NXH.js} +1 -1
- package/server/{specialist-context-BMq83C58.js → specialist-context-B2HlbNxS.js} +5 -5
- package/server/{specialist-handoff-logger-BxX1YefH.js → specialist-handoff-logger-CQyF1ygu.js} +2 -2
- package/server/{specialist-logs-BWZYcJ6P.js → specialist-logs-CdcUpfjj.js} +3 -3
- package/server/{specialists-BudKrjOu.js → specialists-CFgw_0Q6.js} +1657 -113
- package/server/{specialists-DrPrC9Y9.js → specialists-CwzFdapR.js} +18 -18
- package/server/{specialists-ZkW4Mb7U.js → specialists-D7AcFi1u.js} +1 -1
- package/server/{specialists-8ZAguXef.js → specialists-k22_Btaq.js} +1 -1
- package/server/specs-RzcDgozr.js +3 -0
- package/server/{src-DHn4Rd2F.js → src-B4TTzNSr.js} +72 -1
- package/server/{src-Dv6L03vW.js → src-BvpMg4EB.js} +3 -3
- package/server/{src-DNUUqkec.js → src-D4YUZrwR.js} +6 -6
- package/server/{stack-health-DxsTx7II.js → stack-health-CSgcYcr8.js} +2 -2
- package/server/{stack-health-Dclm7_tu.js → stack-health-DVN7zRnL.js} +1 -1
- package/server/{state-home-CRowbXqU.js → state-home-CEvD_v5F.js} +6 -6
- package/server/{state-mapping-BvAgFK8n.js → state-mapping-C13UaCL7.js} +1 -1
- package/server/{stuck-remediation-CFWUP8_I.js → stuck-remediation-CxsyxwFO.js} +43 -21
- package/server/{stuck-remediation-CLHd-lrF.js → stuck-remediation-nTIvhGOR.js} +1 -1
- package/server/{summary-fork-CKc01Our.js → summary-fork-CnRMPCYd.js} +2 -2
- package/server/{summary-fork-CtCwBJ2Z.js → summary-fork-gKSoFAnK.js} +8 -8
- package/server/{supervisor-BA5D72Qa.js → supervisor-CZMs8s0M.js} +2 -2
- package/server/supervisor-CfX192ma.js +2 -0
- package/server/{swarm-readiness-CL5sM9B1.js → swarm-readiness-h6-pwY8w.js} +3 -3
- package/server/{system-prerequisites-DmFSXIE5.js → system-prerequisites-DZZTi2G6.js} +1 -1
- package/server/{teardown-workspace-DWmFJzTw.js → teardown-workspace-B4D-oCVg.js} +17 -17
- package/server/{test-agent-queue-DjsQoV5X.js → test-agent-queue-CnuYku4B.js} +6 -6
- package/server/{test-verdict-BSqsQp3G.js → test-verdict-CRsPpByy.js} +1 -1
- package/server/{test-verdict-D1AmZ2c0.js → test-verdict-CXMLATGc.js} +1 -1
- package/server/{tldr-daemon-DD9rI5gA.js → tldr-daemon-CgZQ3jmZ.js} +1 -1
- package/server/{tldr-daemon-C-MGomL8.js → tldr-daemon-CuA8hz21.js} +2 -2
- package/server/{tmux-x291Gjjb.js → tmux-By8E_Yv_.js} +1 -1
- package/server/{tmux-C_d-lSIq.js → tmux-C3g9VFcg.js} +2 -2
- package/server/{token-DfBf1bsd.js → token-g_sJ19g3.js} +2 -2
- package/server/token-util-C9u4An3K.js +3 -0
- package/server/{token-util-CROoF5ic.js → token-util-DiwnnbJo.js} +1 -1
- package/server/{tracker-config-DItsdelv.js → tracker-config-BzfVj41Z.js} +1 -1
- package/server/{tracker-config-CNODpd11.js → tracker-config-dQxC15vH.js} +2 -2
- package/server/{tracker-utils-Ch2_5GGf.js → tracker-utils--z8FLSWn.js} +2 -2
- package/server/{tracker-utils-B9ZoVA9b.js → tracker-utils-DkKyRT0H.js} +1 -1
- package/server/{traefik-connect-BF4x_LUQ.js → traefik-connect-CZYB3dlm.js} +1 -1
- package/server/{tunnel-r_5nHAI6.js → tunnel-BpWZs0Jy.js} +3 -3
- package/server/{tunnel-YD80_IHr.js → tunnel-CN2px87h.js} +1 -1
- package/server/{typed-errors-DSPn_xWP.js → typed-errors-CrN1AByg.js} +1 -1
- package/server/{typed-errors-BEJhbjJg.js → typed-errors-sLpGfegz.js} +1 -1
- package/server/{types-CE1m_daD.js → types-BLS_Zbmd.js} +1 -1
- package/server/{types-33JEP4LZ.js → types-tlXf80x3.js} +1 -1
- package/server/{uat-train-DjkFWXge.js → uat-train-BRo6DM7p.js} +24 -24
- package/server/{uat-train-DDI00aqD.js → uat-train-utGVmqdm.js} +1 -1
- package/server/{validation-DUTiJnyz.js → validation-CsPVsoA0.js} +4 -4
- package/server/{validation-ict8hnXk.js → validation-Dq_wwcw3.js} +1 -1
- package/server/{verification-runner-inLgeQux.js → verification-runner-CMT5WRMS.js} +11 -11
- package/server/{verification-runner-ATaLbpr5.js → verification-runner-D0Uh-9jc.js} +1 -1
- package/server/{vtt-parser-QnRfcjiU.js → vtt-parser-C_XPlifj.js} +1 -1
- package/server/{work-agent-prompt-fZljjA1_.js → work-agent-prompt-ZTAb2Hyf.js} +11 -11
- package/server/workflows-BLwxUMP7.js +2 -0
- package/server/{workflows-oBnJ7Tm0.js → workflows-CXRwhw_o.js} +14 -14
- package/server/{workspace-B2WOW9Hw.js → workspace-9UEsKuiP.js} +1 -1
- package/server/{workspace-CNuW2j41.js → workspace-CNfuj1-5.js} +3 -3
- package/server/{workspace-config-CBgMGhWs.js → workspace-config-ChWOECy0.js} +1 -1
- package/server/{workspace-manager-DjUAJCSs.js → workspace-manager-BO-6k3sP.js} +1 -1
- package/server/{workspace-manager-CB-R07R3.js → workspace-manager-D8AByFIT.js} +13 -13
- package/server/{workspace-metadata-9Nn5kgRl.js → workspace-metadata-CvC268MN.js} +2 -2
- package/server/{workspace-metadata-Fd58uUQG.js → workspace-metadata-DZiJtnuF.js} +1 -1
- package/server/{workspaces-BjWXntty.js → workspaces-D-uIoqbg.js} +103 -95
- package/server/{writer-CQMGzEkw.js → writer-BUweuRPx.js} +1 -1
- package/server/{writer-fe1-8iGc.js → writer-CrP2xuBn.js} +3 -3
- package/sync-sources/hooks/ask-user-question-hook +7 -1
- package/sync-sources/hooks/record-cost-event.js +2 -2
- package/sync-sources/hooks/record-cost-event.js.map +1 -1
- package/server/agent-runtime-mirror-DrWxopNA.js +0 -37
- package/server/cli-ClIQwgMI.js +0 -3
- package/server/deacon-swarm-BY5hKNaU.js +0 -2
- package/server/dist-DGTwcZhI.js +0 -3
- package/server/forge-XlDgPQWs.js +0 -2
- package/server/hume-K1pi8jC4.js +0 -3
- package/server/inspect-agent-477VxQim.js +0 -2
- package/server/merge-ops-PzqsW69V.js +0 -2
- package/server/projects-KJ94e50I.js +0 -3
- package/server/public/assets/chunk-BO2N2NFS-ClukPsZQ.js +0 -103
- package/server/public/assets/index-DnTZ2QeN.js +0 -796
- package/server/public/assets/mermaid-GHXKKRXX-DZJOwgBG.js +0 -1
- package/server/rally-Dc2Wnxw2.js +0 -3
- package/server/resume-DhcIqsTm.js +0 -3
- package/server/settings-yydgaqhv.js +0 -2
- package/server/specs-DwoAEGrW.js +0 -3
- package/server/supervisor-DHjumXlL.js +0 -2
- package/server/token-util-xNaV-00f.js +0 -3
- package/server/workflows-tU7KKxQi.js +0 -2
package/server/server.js
CHANGED
|
@@ -1,126 +1,124 @@
|
|
|
1
|
-
import { a as __toCommonJS, i as __require, o as __toESM, t as __commonJSMin } from "./rolldown-runtime-DNCzzKnI.js";
|
|
2
|
-
import { $ as MODEL_DEPRECATIONS, Ar as
|
|
3
|
-
import { _ as getDashboardIdentity, b as shouldRefuseHostDashboardPort, c as startUatTrainReconciler, d as openFlywheelRunReportForDashboard, f as pauseFlywheelRunForDashboard, g as runDashboardDbJob, h as startFlywheelRunForDashboard, l as stopUatTrainReconciler, m as resumeFlywheelRunForDashboard, p as readCurrentFlywheelStatusForDashboard, u as abortFlywheelRunForDashboard, v as isWorkspaceRepoRoot, y as readHostDashboardApiPort } from "./uat-train-
|
|
4
|
-
import { C as
|
|
1
|
+
import { a as __toCommonJS, i as __require, n as __esmMin, o as __toESM, r as __exportAll, t as __commonJSMin } from "./rolldown-runtime-DNCzzKnI.js";
|
|
2
|
+
import { $ as MODEL_DEPRECATIONS, Ar as LOGS_DIR, Br as encodeClaudeProjectDir, C as init_tier_table, D as canUseHarnessSync, Dr as CLAUDE_DIR, Dt as getIssueWorkspacePath, E as validateTieredExecutionConfig, En as getIssuePrefix, F as getBuiltInDefaultHarness, Fn as init_projects, G as defaultBackgroundAiFeatures, Hr as getDocsDisableStatePath, I as getKimiAnthropicBaseUrl, J as DEFAULT_WORKHORSES, Jr as init_paths, K as init_registry, Kn as resolveProjectFromIssue, Kr as getLegacyHome, N as UnknownModelError, Q as MODEL_CAPABILITIES, Qr as sessionFilePath, R as getProviderForModelSync, Rn as listProjects, Rr as SYNC_SOURCES, S as TieredExecutionConfigError, Sn as findProjectByPathSync, Sr as AGENTS_DIR, Ur as getDocsIndexPath, Vr as getDocsBudgetStatePath, Wn as registerProjectSync, Wr as getDocsTelemetryPath, Xr as packageRoot, Y as computeModelOrigin, Yr as isDevMode, Z as resolveModel, Zn as setProjectAutoMergeDefaultSync, _ as getDefaultDocsConfig, _r as ProcessSpawnError, at as resolveModelIdSync, bn as extractTeamPrefix, d as loadConfigNoMigration, dr as FsError, dt as ROLE_EFFORTS, f as loadConfigSync, g as mergeConfigs, h as jsYaml, hn as resolveStateReadHomeSync, i as getConversationsConfig, in as init_auto_commit, ir as parseIssueIdSync, it as modelSupportsImagesSync, jr as OVERDECK_HOME, k as init_harness_policy, kn as getProjectSync, kt as init_record, lt as COMPLIANCE_MODES, m as init_js_yaml, mn as init_state_read_home, n as clearConfigCache, nn as flushAllPendingAutoCommits, nr as init_issue_id, nt as hasModelCapabilitySync, o as getGlobalConfigPath, p as updateConversationsConfig, pr as GitHubApiError, q as DEFAULT_ROLES, qn as resolveProjectFromIssueSync, qr as getOverdeckHome, r as getConversationSearchConfigSync, rn as flushAutoCommits, rt as init_model_capabilities, s as init_load, sr as require_dist$1, t as init_config_yaml, tr as extractPrefixSync, tt as getModelEffortLevelsSync, u as isTldrEnabledSync, ut as PARENT_MODEL_REF, v as getDefaultTtsDaemonConfig, w as resolveTieredExecutionEnabled, wn as findProjectByTeamSync, xr as init_errors, y as mergeTtsDaemonConfigs, yr as TrackerError, z as init_providers, zn as listProjectsSync } from "./config-yaml-cNOZcEww.js";
|
|
3
|
+
import { _ as getDashboardIdentity, b as shouldRefuseHostDashboardPort, c as startUatTrainReconciler, d as openFlywheelRunReportForDashboard, f as pauseFlywheelRunForDashboard, g as runDashboardDbJob, h as startFlywheelRunForDashboard, l as stopUatTrainReconciler, m as resumeFlywheelRunForDashboard, p as readCurrentFlywheelStatusForDashboard, u as abortFlywheelRunForDashboard, v as isWorkspaceRepoRoot, y as readHostDashboardApiPort } from "./uat-train-BRo6DM7p.js";
|
|
4
|
+
import { $ as readLauncherPinnedSessionId, A as resolveAllowedHarness, B as cleanupUnreferencedConversationAttachments, C as handleConversationCreate, D as handleConversationStop, E as handleConversationResume, F as tmuxSessionExists, G as isManagedConversationAttachmentPath, H as extractConversationAttachmentPaths, I as waitForPiTuiReady, J as evaluateSpawnGuardrails, K as removeConversationAttachment, L as waitForTmuxSession$1, M as spawnConversationSession, N as startConversationModelBackfill, O as handleConversationSwitchModel, P as stopConversationRuntime, R as cleanupConversationAttachments, S as conversationSessionAliveFromState, T as handleConversationRestartAll, U as getConversationAttachmentsRoot, V as ensureConversationAttachmentDir, W as hasConversationAttachment, X as resolveAgentGitInfo, Y as invalidateAgentsCache, Z as resolveConversationGitInfo, _ as isPiControlChannelHarness, _t as jsonStringResponse, a as agentsRouteLayer, at as isRespawnPending, b as validateConversationControlAckOrigin, c as codexConversationPendingInput, d as handleConversationCodexApproval, dt as validateOrigin$1, et as resolveAgentHarness, f as handleConversationCompact, ft as validateOriginHeaders, g as handleConversationThinkingLevel, gt as jsonResponse, h as handleConversationPlanAction, ht as getDefaultCwd, it as resolvePiSessionPath, j as shouldReportUnresolvedLiveSession, k as isInsideGitWorkTree, l as deliverConversationViaControlChannel, lt as isTrustedOriginForHost, m as handleConversationDeliveryMethod, mt as httpHandler, nt as resolveCodexRolloutPath, o as saveAgentStateAndEmitEvent, ot as waitForSessionRespawn, p as handleConversationControlAck, pt as checkCodexAuthStatus, q as runInBatches, rt as resolveJsonlPath, s as saveAgentStateAndEmitEventProgram, st as getHeaderFromMap, t as specialistsRouteLayer, tt as resolveClaudeSessionId, u as handleConversationAbort, v as pickDeliverAs, w as handleConversationDelete, x as conversationNeedsRunningRepair, y as resolveConversationDeliveryMethod, z as cleanupOrphanedConversationAttachments } from "./specialists-CFgw_0Q6.js";
|
|
5
5
|
import { a as init_activity_logger, i as emitDashboardLifecycleSync, n as emitActivityEntrySync, r as emitActivityTtsSync } from "./activity-logger-pcbf-e30.js";
|
|
6
|
-
import { A as init_paths$1, O as OVERDECK_MIGRATION_PATH, d as getOverdeckDatabaseSync, f as init_infra, i as DbLive, k as getOverdeckDatabasePath, u as TmuxLive } from "./infra-
|
|
6
|
+
import { A as init_paths$1, O as OVERDECK_MIGRATION_PATH, d as getOverdeckDatabaseSync, f as init_infra, i as DbLive, k as getOverdeckDatabasePath, u as TmuxLive } from "./infra-Ba9mS6e6.js";
|
|
7
7
|
import { n as openDatabase, t as init_driver } from "./driver-D-HBOQa_.js";
|
|
8
|
-
import { E as listPaneValues,
|
|
9
|
-
import { a as init_event_store, i as initEventStore, n as getEventStore, r as getSharedDb } from "./event-store-
|
|
10
|
-
import { _ as FlywheelRunId, a as getHarnessBehavior, b as DomainEvent, c as FlywheelStats, g as WS_METHODS, h as PanRpcGroup, m as PanRpcError, o as ContextLayerSaveRequest, s as ContextPreviewRequest, t as init_src, v as FlywheelStatus, x as MemoryObservation, y as EDITORS } from "./src-
|
|
11
|
-
import { a as fixStuckReadyForMerge, c as init_review_status, i as fixStuckCommentedReviews, l as loadReadyForMergeFlags, n as clearReviewStatus, o as getReviewStatus, r as clearStuckMergeStatuses, s as getReviewStatusSync, u as loadReviewStatuses, v as setReviewStatus, y as setReviewStatusSync } from "./review-status-
|
|
12
|
-
import { a as EventStoreService, c as ReadModelService, d as init_read_model, f as toAgentResolution, i as init_issue_lifecycle, l as ReadModelServiceLive, m as toRole, n as IssueLifecycleLive, o as EventStoreServiceLive, p as toAgentStatus, s as init_domain_services, t as IssueLifecycle } from "./issue-lifecycle
|
|
13
|
-
import { d as init_agents, i as recordBriefingSessionStart, n as ensureSessionContextBriefingFile, p as listAllAgentsSync, r as init_briefing_freshness, s as AgentsResolverLive, t as appendFreshBriefingUpdate } from "./briefing-freshness-
|
|
14
|
-
import { i as init_paths$2, l as resolveObservationsFile, r as ensureParentDir, s as resolveIssueMemoryRoot, t as assertMemorySafeSegment } from "./paths-
|
|
15
|
-
import { n as listFeatureRegistryEntries, t as init_feature_registry_storage } from "./feature-registry-storage-
|
|
16
|
-
import { a as diffAgainstMain, c as diffCheckpoints, d as diffPatchSinceCommit, f as findCommitAtTime, h as listCheckpoints, l as diffFilesAgainstHead, m as init_checkpoint_manager, o as diffAgainstMainFiles, s as diffCheckpointFiles, t as captureCheckpoint, u as diffPatchFilesAgainstHead } from "./checkpoint-manager-
|
|
17
|
-
import { An as getAgentDir,
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
21
|
-
import { n as AgentStateServiceLive } from "./agent-state-service-
|
|
22
|
-
import { a as init_tracker_config, i as initTrackerConfigCache, n as getLinearApiKey, r as getRallyConfig, t as getGitHubConfig } from "./tracker-config-
|
|
23
|
-
import { d as init_typed_errors, l as WorkspaceCreateError, n as AgentStartError, r as BeadsNotInitialized, s as TrackerApiError, t as AgentAlreadyRunning, u as WorkspaceNotFound } from "./typed-errors-
|
|
24
|
-
import { i as init_linear_client, r as LinearClientOptionalLive, t as LinearClient } from "./linear-client-
|
|
25
|
-
import { i as init_github_client, r as GitHubClientOptionalLive, t as GitHubClient } from "./github-client-
|
|
26
|
-
import { i as init_rally_client, r as RallyClientOptionalLive, t as RallyClient } from "./rally-client-
|
|
27
|
-
import { a as resolveTrackerTypeSync, i as resolveGitHubIssueSync, n as init_tracker_utils } from "./tracker-utils
|
|
28
|
-
import { a as CacheService, i as startSharedIssueService, n as init_issue_service_singleton, o as init_cache_service, r as issue_service_singleton_exports, s as parseIntegerHeader, t as getSharedIssueService } from "./issue-service-singleton-
|
|
29
|
-
import { i as ensureInternalTokenSync, o as getInternalTokenSync, s as init_internal_token, t as INTERNAL_TOKEN_HEADER } from "./internal-token-
|
|
30
|
-
import { a as setPipelineHandlerSync, t as init_pipeline_notifier } from "./pipeline-notifier-
|
|
31
|
-
import { c as init_review_status_sync, i as getMergeBlockerReconcileCandidates } from "./review-status-sync-
|
|
32
|
-
import { a as PAN_DIRNAME, f as asPanSpecDocument, i as PAN_CONTINUE_FILENAME, p as init_types } from "./types-
|
|
33
|
-
import { C as transitionToMerging, _ as markFailed, c as isFlywheelGloballyPaused, d as listDuePendingAutoMerges, f as listProblemAutoMerges, g as markBlocked, n as getActionableAutoMerge, o as init_merge_sync, t as cancelPending, u as listActiveAutoMerges, v as markMerged, x as scheduleAutoMergeWithResult, y as requeueToPending } from "./merge-sync-
|
|
34
|
-
import { C as findSpecByIssue,
|
|
35
|
-
import { C as restartCliproxy, S as readPidFile, T as stopCliproxy, b as isCliproxyInstalled, d as getCliproxyAuthDir, o as bridgeCodexAuthToCliproxy, v as init_cliproxy, w as startCliproxy, x as isCliproxyRunning, y as installCliproxy } from "./cliproxy-
|
|
36
|
-
import { f as init_config$1, m as loadConfigSync$1, s as getDashboardApiUrlSync } from "./config-
|
|
37
|
-
import { n as require_auth_errors, r as require_token_error, t as require_token_util } from "./token-util-
|
|
38
|
-
import { $ as updateConversationForkFallbackReason, A as isAgentConversationName, B as removeFavorite, C as getConversationByTmuxSession, D as importLegacyConversation,
|
|
39
|
-
import { _ as init_codex_conversation_parser, a as contextUsageFromParseResult, c as parseEntireConversation, d as init_pi_conversation_parser, f as isPiSessionFile, g as parseOhmypiConversationMessages, h as isOhmypiSessionFile, i as computeContextUsage, l as parseFromLastCompactBoundary, m as init_ohmypi_conversation_parser, n as gateSnapshotEmission, o as summarizeConversationActivity, p as parsePiConversationMessages, r as watchConversation, s as parseConversationMessages, t as init_conversation_service, v as parseCodexConversationMessages } from "./conversation-service-
|
|
40
|
-
import { n as isBackgroundFeatureEnabled, t as init_features } from "./features-
|
|
41
|
-
import { i as init_settings, r as getMemoryWorkerConcurrency, t as areMemoryObservationsEnabled } from "./settings-
|
|
42
|
-
import { i as updateMemoryHealth, n as extractWithProviderPolicy, r as init_health, t as init_providers$1 } from "./providers-
|
|
43
|
-
import { a as init_launcher_generator, i as generateLauncherScriptSync, n as init_state_home, r as isStateMigrated } from "./state-home-
|
|
44
|
-
import { a as init_claude_permissions,
|
|
45
|
-
import { a as globalContextFile$1, f as resolveProjectContextFile, h as workspaceContextFile,
|
|
46
|
-
import { l as init_codex, s as findRolloutPath } from "./codex-
|
|
47
|
-
import { C as setMergeTrainEnabled, S as setFlywheelRequireUatBeforeMerge, b as setFlywheelAutoPickupBacklog, c as isCloisterSpawnsPausedSync, d as isFlywheelAutoPickupBacklog, f as isFlywheelGloballyPaused$1, g as setCloisterSpawnsPausedSync, h as setBootReconciliationDecision, m as isMergeTrainEnabled, o as getSetting, p as isFlywheelRequireUatBeforeMerge, r as getBootReconciliationState, s as init_control_settings, u as isDeaconGloballyPausedSync, v as setDeaconGloballyPausedSync, w as setSetting } from "./control-settings-
|
|
48
|
-
import { a as withBdProcessLock, n as init_bd_process_lock } from "./bd-process-lock-
|
|
49
|
-
import { n as init_resolver, t as createBeadsResolver } from "./resolver-
|
|
50
|
-
import {
|
|
51
|
-
import {
|
|
52
|
-
import {
|
|
53
|
-
import {
|
|
54
|
-
import {
|
|
55
|
-
import {
|
|
56
|
-
import {
|
|
57
|
-
import {
|
|
58
|
-
import { S as
|
|
59
|
-
import {
|
|
60
|
-
import {
|
|
61
|
-
import {
|
|
62
|
-
import {
|
|
63
|
-
import {
|
|
64
|
-
import {
|
|
65
|
-
import {
|
|
66
|
-
import {
|
|
67
|
-
import { a as
|
|
68
|
-
import {
|
|
69
|
-
import {
|
|
70
|
-
import {
|
|
71
|
-
import {
|
|
72
|
-
import {
|
|
73
|
-
import {
|
|
74
|
-
import {
|
|
75
|
-
import {
|
|
76
|
-
import {
|
|
77
|
-
import { n as
|
|
78
|
-
import {
|
|
79
|
-
import { t as
|
|
80
|
-
import {
|
|
81
|
-
import {
|
|
82
|
-
import {
|
|
83
|
-
import {
|
|
84
|
-
import {
|
|
85
|
-
import {
|
|
86
|
-
import {
|
|
87
|
-
import { n as
|
|
88
|
-
import { a as
|
|
89
|
-
import {
|
|
90
|
-
import { a as
|
|
91
|
-
import {
|
|
92
|
-
import {
|
|
93
|
-
import { t as
|
|
94
|
-
import
|
|
95
|
-
import "./
|
|
96
|
-
import { i as listTranscriptCheckpoints, r as getTranscriptCheckpoint$1 } from "./checkpoints-1BqOlS4q.js";
|
|
8
|
+
import { E as listPaneValues, G as buildChildEnvSync, H as init_ui_theme, K as buildChildEnvWithoutTmuxSync, L as sessionExists, M as resizeWindow, O as listSessionNames, P as sendKeys, S as isHarnessProcessAlive, U as setUiTheme, b as getWindowDimensions, c as ensureManagedTmuxContextOnce, i as capturePane, k as listSessions, n as buildTmuxArgs, o as createSession, q as init_child_env, w as killSession, x as init_tmux } from "./tmux-C3g9VFcg.js";
|
|
9
|
+
import { a as init_event_store, i as initEventStore, n as getEventStore, r as getSharedDb } from "./event-store-D89fMfXS.js";
|
|
10
|
+
import { _ as FlywheelRunId, a as getHarnessBehavior, b as DomainEvent, c as FlywheelStats, g as WS_METHODS, h as PanRpcGroup, m as PanRpcError, o as ContextLayerSaveRequest, s as ContextPreviewRequest, t as init_src, v as FlywheelStatus, x as MemoryObservation, y as EDITORS } from "./src-B4TTzNSr.js";
|
|
11
|
+
import { a as fixStuckReadyForMerge, c as init_review_status, i as fixStuckCommentedReviews, l as loadReadyForMergeFlags, n as clearReviewStatus, o as getReviewStatus, r as clearStuckMergeStatuses, s as getReviewStatusSync, u as loadReviewStatuses, v as setReviewStatus, y as setReviewStatusSync } from "./review-status-Dc1l4dVz.js";
|
|
12
|
+
import { a as EventStoreService, c as ReadModelService, d as init_read_model, f as toAgentResolution, i as init_issue_lifecycle, l as ReadModelServiceLive, m as toRole, n as IssueLifecycleLive, o as EventStoreServiceLive, p as toAgentStatus, s as init_domain_services, t as IssueLifecycle } from "./issue-lifecycle--8MRxrG1.js";
|
|
13
|
+
import { d as init_agents, i as recordBriefingSessionStart, n as ensureSessionContextBriefingFile, p as listAllAgentsSync, r as init_briefing_freshness, s as AgentsResolverLive, t as appendFreshBriefingUpdate } from "./briefing-freshness-DESTCWo-.js";
|
|
14
|
+
import { i as init_paths$2, l as resolveObservationsFile, r as ensureParentDir, s as resolveIssueMemoryRoot, t as assertMemorySafeSegment } from "./paths-Blj6A9AJ.js";
|
|
15
|
+
import { n as listFeatureRegistryEntries, t as init_feature_registry_storage } from "./feature-registry-storage-BeXmNBwK.js";
|
|
16
|
+
import { a as diffAgainstMain, c as diffCheckpoints, d as diffPatchSinceCommit, f as findCommitAtTime, h as listCheckpoints, l as diffFilesAgainstHead, m as init_checkpoint_manager, o as diffAgainstMainFiles, s as diffCheckpointFiles, t as captureCheckpoint, u as diffPatchFilesAgainstHead } from "./checkpoint-manager-BwFdegJF.js";
|
|
17
|
+
import { An as getAgentDir, Dt as captureTranscriptUserRecordSnapshot, Jn as saveAgentStateSync, Jt as getProviderAuthMode, M as init_operator_interventions, Mn as getAgentState, N as operatorInterventionEvent, Nn as getAgentStateFilePath, Ot as init_transcript_landing, Pn as getAgentStateSync, Q as listRunningAgentsSync, St as deliverAgentMessage, X as listAgentStates, Z as listRunningAgents, Zt as injectPiConversationMemory, _t as init_config, an as init_claude_auth, at as init_concurrency, bt as saveCloisterConfigSync, c as init_tier_supervisor, cr as normalizeAgentId, dr as waitForReadySignal, er as init_agent_record_sync, f as supervisorAgentId, fr as getAgentRuntimeState, hn as init_openai_auth, in as getClaudeAuthStatus, j as messageAgent, kt as probeTranscriptSince, ln as getProviderEnvForModel, mn as getOpenAIAuthStatus, pr as getAgentRuntimeStateSync, rt as emergencyBrake, s as deliverCommitForReview, t as init_agents$1, tr as readAgentHarnessModelRecordSync, vt as loadCloisterConfig, xt as shouldAutoStart, yt as loadCloisterConfigSync } from "./agents-B9GwfCyp.js";
|
|
18
|
+
import { a as getCostForIssueAggregateSync, c as getDailyTrendsSync, d as init_cost_sync, l as getModelRollupSync, n as getBackgroundCostBySourceSync, p as queryCostEventsSync, r as getCavemanExperimentDataSync, s as getCostsByIssueSync, u as getTodayCostSync } from "./cost-sync-DF6odxK9.js";
|
|
19
|
+
import { c as getAgentsNeedingAttention, d as CostResolverLive, f as CostWriter, l as CostDoorLive, n as readCloisterStateFile, o as generateHealthSummary, s as getAgentHealth, t as getCloisterService, u as CostResolver } from "./service-DfTVoqJg.js";
|
|
20
|
+
import { t as init_behavior } from "./behavior-BTpYbAv4.js";
|
|
21
|
+
import { n as AgentStateServiceLive } from "./agent-state-service-DFslS5go.js";
|
|
22
|
+
import { a as init_tracker_config, i as initTrackerConfigCache, n as getLinearApiKey, r as getRallyConfig, t as getGitHubConfig } from "./tracker-config-dQxC15vH.js";
|
|
23
|
+
import { d as init_typed_errors, l as WorkspaceCreateError, n as AgentStartError, r as BeadsNotInitialized, s as TrackerApiError, t as AgentAlreadyRunning, u as WorkspaceNotFound } from "./typed-errors-sLpGfegz.js";
|
|
24
|
+
import { i as init_linear_client, r as LinearClientOptionalLive, t as LinearClient } from "./linear-client-D9cSQfvD.js";
|
|
25
|
+
import { i as init_github_client, r as GitHubClientOptionalLive, t as GitHubClient } from "./github-client-Btyy3uan.js";
|
|
26
|
+
import { i as init_rally_client, r as RallyClientOptionalLive, t as RallyClient } from "./rally-client-sErNQBO0.js";
|
|
27
|
+
import { a as resolveTrackerTypeSync, i as resolveGitHubIssueSync, n as init_tracker_utils } from "./tracker-utils--z8FLSWn.js";
|
|
28
|
+
import { a as CacheService, i as startSharedIssueService, n as init_issue_service_singleton, o as init_cache_service, r as issue_service_singleton_exports, s as parseIntegerHeader, t as getSharedIssueService } from "./issue-service-singleton-CkTUI-eu.js";
|
|
29
|
+
import { i as ensureInternalTokenSync, o as getInternalTokenSync, s as init_internal_token, t as INTERNAL_TOKEN_HEADER } from "./internal-token-BtqSbKTx.js";
|
|
30
|
+
import { a as setPipelineHandlerSync, t as init_pipeline_notifier } from "./pipeline-notifier-D_WYtEwl.js";
|
|
31
|
+
import { c as init_review_status_sync, i as getMergeBlockerReconcileCandidates } from "./review-status-sync-CAr-hfnJ.js";
|
|
32
|
+
import { a as PAN_DIRNAME, f as asPanSpecDocument, i as PAN_CONTINUE_FILENAME, p as init_types } from "./types-BLS_Zbmd.js";
|
|
33
|
+
import { C as transitionToMerging, _ as markFailed, c as isFlywheelGloballyPaused, d as listDuePendingAutoMerges, f as listProblemAutoMerges, g as markBlocked, n as getActionableAutoMerge, o as init_merge_sync, t as cancelPending, u as listActiveAutoMerges, v as markMerged, x as scheduleAutoMergeWithResult, y as requeueToPending } from "./merge-sync-D7jWLgCC.js";
|
|
34
|
+
import { C as findSpecByIssue, D as writeSpec, O as writeSpecForIssue, T as init_specs, a as findWorkspaceDraftPlan, b as init_types$1, m as readWorkspacePlanSync, o as init_io, p as readWorkspacePlan, r as findPlan, s as isPlanningComplete, u as readPlan, x as subItemsOf } from "./io-VEGSAqsd.js";
|
|
35
|
+
import { C as restartCliproxy, S as readPidFile, T as stopCliproxy, b as isCliproxyInstalled, d as getCliproxyAuthDir, o as bridgeCodexAuthToCliproxy, v as init_cliproxy, w as startCliproxy, x as isCliproxyRunning, y as installCliproxy } from "./cliproxy-B4c1BUvs.js";
|
|
36
|
+
import { f as init_config$1, m as loadConfigSync$1, s as getDashboardApiUrlSync } from "./config-DVLdmnMJ.js";
|
|
37
|
+
import { n as require_auth_errors, r as require_token_error, t as require_token_util } from "./token-util-DiwnnbJo.js";
|
|
38
|
+
import { $ as updateConversationForkFallbackReason, A as isAgentConversationName, B as removeFavorite, C as getConversationByTmuxSession, D as importLegacyConversation, F as markConversationEnded, H as setClearedToConvId, I as markConversationRunning, J as setForkRequest, M as listConversations, N as listFavoritedIds, O as incrementForkRetryCount, P as markConversationActive, S as getConversationByName, T as getStuckForks, U as setConversationClaudeSessionId, X as unarchiveConversation, Y as setImportedConversationLinks, Z as updateConversationCost, _ as canRefineTitle, b as getConversationByClaudeSessionId, et as updateConversationTitle, gt as getDiscoveredSessionBySessionId, h as archiveConversation, j as listArchivedConversationsWithEnrichment, k as init_conversations, q as setFavorite, tt as updateForkStatus, v as canReplaceTitle, w as getConversationLedgerCosts, x as getConversationById, y as createConversation, yt as init_discovered_sessions, z as recordConversationHandoff } from "./conversations-B-lcHv-5.js";
|
|
39
|
+
import { _ as init_codex_conversation_parser, a as contextUsageFromParseResult, c as parseEntireConversation, d as init_pi_conversation_parser, f as isPiSessionFile, g as parseOhmypiConversationMessages, h as isOhmypiSessionFile, i as computeContextUsage, l as parseFromLastCompactBoundary, m as init_ohmypi_conversation_parser, n as gateSnapshotEmission, o as summarizeConversationActivity, p as parsePiConversationMessages, r as watchConversation, s as parseConversationMessages, t as init_conversation_service, v as parseCodexConversationMessages } from "./conversation-service-B8LFQQm1.js";
|
|
40
|
+
import { n as isBackgroundFeatureEnabled, t as init_features } from "./features-u5XeMaOK.js";
|
|
41
|
+
import { i as init_settings, r as getMemoryWorkerConcurrency, t as areMemoryObservationsEnabled } from "./settings-DfT3f86D.js";
|
|
42
|
+
import { i as updateMemoryHealth, n as extractWithProviderPolicy, r as init_health, t as init_providers$1 } from "./providers-BbEyFhPX.js";
|
|
43
|
+
import { a as init_launcher_generator, i as generateLauncherScriptSync, n as init_state_home, r as isStateMigrated } from "./state-home-CEvD_v5F.js";
|
|
44
|
+
import { a as init_claude_permissions, r as getClaudePermissionFlagsStringSync } from "./claude-permissions-CThLgf8d.js";
|
|
45
|
+
import { a as globalContextFile$1, f as resolveProjectContextFile, h as workspaceContextFile, n as codexGlobalContextFile, o as init_layers, p as resolveWorkspaceContextFile, r as ensureProjectLayer } from "./layers-jjL16At6.js";
|
|
46
|
+
import { l as init_codex, s as findRolloutPath } from "./codex-BbqIRZjd.js";
|
|
47
|
+
import { C as setMergeTrainEnabled, S as setFlywheelRequireUatBeforeMerge, b as setFlywheelAutoPickupBacklog, c as isCloisterSpawnsPausedSync, d as isFlywheelAutoPickupBacklog, f as isFlywheelGloballyPaused$1, g as setCloisterSpawnsPausedSync, h as setBootReconciliationDecision, m as isMergeTrainEnabled, o as getSetting, p as isFlywheelRequireUatBeforeMerge, r as getBootReconciliationState, s as init_control_settings, u as isDeaconGloballyPausedSync, v as setDeaconGloballyPausedSync, w as setSetting } from "./control-settings-D4EFsRBd.js";
|
|
48
|
+
import { a as withBdProcessLock, n as init_bd_process_lock } from "./bd-process-lock-XAXAet9O.js";
|
|
49
|
+
import { n as init_resolver, t as createBeadsResolver } from "./resolver-C7dLn8OK.js";
|
|
50
|
+
import { i as checkPrdGateSync, t as init_pan_dir } from "./pan-dir-CQIfKG8c.js";
|
|
51
|
+
import { a as init_lifecycle_io, t as appendContinueSessionEntryForIssue } from "./lifecycle-io-IehcRt2v.js";
|
|
52
|
+
import { r as init_swarm_readiness, t as analyzeSwarmReadiness } from "./swarm-readiness-h6-pwY8w.js";
|
|
53
|
+
import { c as countPendingAskUserQuestionsForAgent, h as detectAwaitingInputFromPaneSync, l as getAgentJsonlMtime, m as detectAwaitingInputForAgent, o as getRuntimeForAgent, p as scanPendingInputsPromise, s as computeAgentEnrichment } from "./stuck-remediation-CxsyxwFO.js";
|
|
54
|
+
import { i as CostThresholdError, l as embed, s as parseRelativeTime } from "./scanner-BTM1jc_u.js";
|
|
55
|
+
import { c as tailEventsSync, n as deduplicateEventsSync, o as readEventsSync } from "./events-S_C0pvl6.js";
|
|
56
|
+
import { n as recordBackgroundAiCost, t as init_cost } from "./cost-BcpRQ-7o.js";
|
|
57
|
+
import { S as writeLatestFlywheelStatus, _ as readCurrentLatestFlywheelStatus, b as subscribeLatestFlywheelStatus, f as getFlywheelRunDetail, h as listFlywheelRuns, l as buildClassifyLookups, m as isFlywheelRunId, y as resolveLiveFlywheelRunId } from "./flywheel-Dczmgchd.js";
|
|
58
|
+
import { C as hasDashboardInternalToken, D as getWorkspacePathForIssue, E as rejectUnsafeDashboardMutationRequest, S as dashboardSessionCookieHeader, T as rejectUnauthorizedDashboardSessionMintRequest, _ as syncCacheSync, b as resolveIssueHeadlineCost, d as reconcile, f as reconcilePiTranscripts, g as rebuildCacheSync, h as getCostsForIssueSync, l as resumeQueuedMerges, m as migrateAllSessionsSync, p as reclassifyUnknownCostEventsSync, t as workspacesRouteLayer, u as syncWalFromAllProjects, v as processPendingFeedbackDeliveries, w as rejectUnauthorizedDashboardRequest, x as dashboardCsrfToken, y as getCachedRunningAgents } from "./workspaces-D-uIoqbg.js";
|
|
59
|
+
import { B as applyIssueBlocksMainLabel, Bt as getContainerHistory, F as setAgentStatusChangedNotifier, G as applyIssueVetoedLabel, Gt as startSmeeProcessSync, H as applyIssueParkedLabel, I as setAgentStoppedNotifier, J as removeIssueParkedLabel, K as removeIssueBlocksMainLabel, L as setMergeReadyNotifier, O as loadConfig, Q as createInFlightGuard, Rt as getResourceStacks, U as applyIssueReadyLabel, Ut as getSystemHealthSnapshot, V as applyIssueObjectionLabel, Vt as getCurrentDockerStats, W as applyIssueReleasedLabel, Wt as isSmeeConfiguredSync, X as removeIssueReleasedLabel, Y as removeIssueReadyLabel, Z as removeIssueVetoedLabel, _t as withConcurrencyLimit, at as listBootReconciliationCandidates, it as isBootReconciliationCandidate, k as loadState, n as assessDeaconPatrolFreshness, ot as startBootReconciliation, q as removeIssueObjectionLabel, t as applyBootReconciliationDecision, x as getDeaconLogs, zt as formatUptime } from "./deacon-DdARMjZq.js";
|
|
60
|
+
import { l as detectPlatform, u as init_platform } from "./workspace-manager-D8AByFIT.js";
|
|
61
|
+
import { O as init_specialists, b as getReviewerSessionName } from "./specialists-CwzFdapR.js";
|
|
62
|
+
import { c as findPrdAtStatusSync, l as init_prd_locations } from "./archive-planning-CbghE9-o.js";
|
|
63
|
+
import { a as getShadowState, s as init_shadow_state } from "./shadow-state-DJz6_pb_.js";
|
|
64
|
+
import { T as verifyAppCanMerge, d as getPullRequestState, f as init_github_app, l as getMergeBackendStatus, p as isGitHubAppConfigured } from "./github-app-u9-SX7Gc.js";
|
|
65
|
+
import { n as init_issue_closed, t as clearIssueClosedCache } from "./issue-closed-BxcePXL-.js";
|
|
66
|
+
import { a as writeFeedbackFile, i as init_feedback_writer } from "./feedback-writer-D20HSXre.js";
|
|
67
|
+
import { a as init_boot_gates, i as formatBootGateState, o as resolveBootGates } from "./no-resume-mode-Gh5R_YLF.js";
|
|
68
|
+
import { c as computeCohort, d as computeStats, f as computeWaves, h as selectNeedsPlanning, l as computeEpicGroups, m as normalizeGate, s as classifyIssue, u as computeLanes } from "./pickup-BtvRBbvI.js";
|
|
69
|
+
import { n as parseSequenceMd, r as writeSequenceMd, t as init_sequence_io } from "./sequence-io-pnoIDGv4.js";
|
|
70
|
+
import { a as loadWorkspaceMetadataSync } from "./workspace-metadata-CvC268MN.js";
|
|
71
|
+
import { l as withBdMutex } from "./beads-BeSMEjGT.js";
|
|
72
|
+
import { i as resolveAutoSpawnOnFinalize, o as spawnPlanningSession } from "./spawn-planning-session-CU-DwyDl.js";
|
|
73
|
+
import { d as killRemoteAgent, m as loadRemoteAgentState, o as getRemoteAgentOutput, r as checkRemoteSpendCap, s as init_remote_agents, v as sendToRemoteAgent, y as spawnRemoteAgent } from "./remote-agents-C4cyxHQS.js";
|
|
74
|
+
import { r as spawnInspectAgent } from "./inspect-agent-B-mnb4uh.js";
|
|
75
|
+
import { a as init_telemetry, i as getBeadsHealth, o as recordBeadsPull, s as recordBeadsSyncError } from "./writer-CrP2xuBn.js";
|
|
76
|
+
import { n as init_github_pr_lookup, r as lookupPullRequestNumberForBranch, t as githubPrLookupSource } from "./github-pr-lookup-DOF1U2WW.js";
|
|
77
|
+
import { a as init_pull_requests, c as getIssuePrTabCacheGeneration, i as fetchIssuePullRequestDiff, l as init_pr_tab_cache, n as fetchIssuePullRequest, o as bumpIssuePrTabCacheGeneration, r as fetchIssuePullRequestDetails, s as getCachedIssuePrTabResponse, t as fetchIssueCheckRuns, u as setCachedIssuePrTabResponse } from "./pull-requests-DyUkQl4W.js";
|
|
78
|
+
import { t as enrichReviewStatus } from "./review-status-enrichment-C1a1OG_1.js";
|
|
79
|
+
import { i as runMemoryFtsTransaction, n as init_fts_db, r as runMemoryFtsStatement, t as closeMemoryFtsDatabases } from "./fts-db-C5A_TTOM.js";
|
|
80
|
+
import { c as init_pending, l as maybeTriggerStatusRollup, o as readRecentObservations, r as init_rollup, u as writePendingTurn } from "./rollup-DctoIu-A.js";
|
|
81
|
+
import { n as getTldrDaemonServiceSync, r as init_tldr_daemon } from "./tldr-daemon-CuA8hz21.js";
|
|
82
|
+
import { T as listGitOperationsSync, w as init_git_activity } from "./merge-agent-B3u2szOL.js";
|
|
83
|
+
import { t as getAgentCommandSync } from "./settings-Cuc12oP_.js";
|
|
84
|
+
import { n as init_review_agent, r as isExtendedReviewEnabled } from "./review-agent-Dn-yn7Zj.js";
|
|
85
|
+
import { r as isRemoteAvailable, t as createFlyProviderFromConfig } from "./remote-DcO9An_f.js";
|
|
86
|
+
import { n as init_claude_settings_overlay, t as detectProviderEnvConflicts } from "./claude-settings-overlay-BF9MPIwx.js";
|
|
87
|
+
import { a as init_query_expansion, i as clearQueryExpansionCache, n as init_injection, o as buildMatchQuery, r as injectPromptTimeMemory, s as init_search } from "./injection-yrMBxzVq.js";
|
|
88
|
+
import { _ as init_transcript_adapter, a as generateFallbackSummary, c as handoffPreconditionFallbackReason, d as prependFallbackFocus, f as requestHandoffFromAgent, g as getTranscriptAdapter, i as copySessionFromCompactBoundary, l as init_summary_fork, o as generateSummaryForFork, p as reserveSummaryForkSession, r as authorHandoffExternal, s as handoffFailureReason, u as logHandoffFallback } from "./summary-fork-gKSoFAnK.js";
|
|
89
|
+
import { a as init_conversation_compaction, c as shouldInterceptManualCompact, n as compactConversationNative, o as isCompacting } from "./conversation-compaction-BCggyih4.js";
|
|
90
|
+
import { a as init_render, d as validateTemplate, i as hasManagedRegion, l as init_harness, o as userContentOutsideRegion, t as init_context_layers, u as renderForHarness } from "./context-layers-c0JqYHcS.js";
|
|
91
|
+
import { r as parseArtifactRef } from "./forge-DFDThFil.js";
|
|
92
|
+
import { t as getMergeBlockersPayload } from "./merge-blockers-cq-aS2KG.js";
|
|
93
|
+
import { a as spawnSequencerAgent, i as init_sequencer_agent, n as clearFinishedSequencerRun, r as getSequencerRunStatus, t as SEQUENCER_AGENT_ID } from "./sequencer-agent-9Soi-WL-.js";
|
|
94
|
+
import "./supervisor-CZMs8s0M.js";
|
|
95
|
+
import { i as listTranscriptCheckpoints, r as getTranscriptCheckpoint$1 } from "./checkpoints-BtUonbs3.js";
|
|
97
96
|
import { createRequire } from "node:module";
|
|
98
97
|
import * as sp from "node:path";
|
|
99
98
|
import { basename, delimiter, dirname, extname, isAbsolute, join, normalize, relative, resolve, sep } from "node:path";
|
|
100
99
|
import { Cause, Context, Data, Duration, Effect, Exit, Fiber, FileSystem, Layer, Option, Path, Queue, Result, Schedule, Schema, Stream } from "effect";
|
|
101
|
-
import { createReadStream, createWriteStream, existsSync, fstatSync, mkdirSync, readFileSync, statSync, writeFileSync } from "fs";
|
|
100
|
+
import { createReadStream, createWriteStream, existsSync, fstatSync, mkdirSync, readFileSync, readdirSync, statSync, writeFileSync } from "fs";
|
|
102
101
|
import { basename as basename$1, dirname as dirname$1, join as join$1, resolve as resolve$1 } from "path";
|
|
103
102
|
import { homedir } from "os";
|
|
104
103
|
import { freemem as freemem$1, homedir as homedir$1, loadavg as loadavg$1, totalmem as totalmem$1, type } from "node:os";
|
|
105
|
-
import { constants, createReadStream as createReadStream$1, existsSync as existsSync$1, mkdirSync as mkdirSync$1, promises as promises$1, readFileSync as readFileSync$1, readdirSync as readdirSync$1, readlinkSync,
|
|
104
|
+
import { constants, createReadStream as createReadStream$1, existsSync as existsSync$1, mkdirSync as mkdirSync$1, promises as promises$1, readFileSync as readFileSync$1, readdirSync as readdirSync$1, readlinkSync, renameSync as renameSync$1, rmSync as rmSync$1, stat, statSync as statSync$1, symlinkSync as symlinkSync$1, unwatchFile, watch, watchFile } from "node:fs";
|
|
106
105
|
import { FetchHttpClient, HttpRouter, HttpServer, HttpServerRequest, HttpServerResponse } from "effect/unstable/http";
|
|
107
106
|
import { EventEmitter } from "node:events";
|
|
108
107
|
import { access, appendFile, chmod, lstat, mkdir, open, readFile, readdir, realpath, rename, rm, stat as stat$1, unlink, writeFile } from "node:fs/promises";
|
|
109
108
|
import { createHash, randomUUID } from "crypto";
|
|
110
109
|
import { appendFile as appendFile$1, chmod as chmod$1, mkdir as mkdir$1, open as open$1, readFile as readFile$1, readdir as readdir$1, rename as rename$1, stat as stat$2, unlink as unlink$1, writeFile as writeFile$1 } from "fs/promises";
|
|
111
|
-
import { exec, execFile, execFileSync,
|
|
110
|
+
import { exec, execFile, execFileSync, fork, spawn } from "node:child_process";
|
|
112
111
|
import { promisify } from "node:util";
|
|
113
112
|
import { createHmac, randomBytes, randomUUID as randomUUID$1, timingSafeEqual } from "node:crypto";
|
|
114
113
|
import * as pty from "@homebridge/node-pty-prebuilt-multiarch";
|
|
115
114
|
import { Buffer as Buffer$1 } from "node:buffer";
|
|
116
115
|
import { PassThrough, Readable } from "node:stream";
|
|
117
|
-
import { fileURLToPath
|
|
116
|
+
import { fileURLToPath } from "node:url";
|
|
118
117
|
import { RpcSerialization, RpcServer } from "effect/unstable/rpc";
|
|
119
118
|
import { layer } from "@effect/platform-node/NodeServices";
|
|
120
119
|
import { createInterface } from "readline";
|
|
121
120
|
import { Worker } from "node:worker_threads";
|
|
122
121
|
import { monitorEventLoopDelay } from "node:perf_hooks";
|
|
123
|
-
import { createInterface as createInterface$1 } from "node:readline";
|
|
124
122
|
import * as Multipart from "effect/unstable/http/Multipart";
|
|
125
123
|
//#region path-env.ts
|
|
126
124
|
/**
|
|
@@ -458,7 +456,7 @@ var NodePtyProcess = class {
|
|
|
458
456
|
};
|
|
459
457
|
}
|
|
460
458
|
};
|
|
461
|
-
async function waitForTmuxSession
|
|
459
|
+
async function waitForTmuxSession(sessionName, timeoutMs = 6e4) {
|
|
462
460
|
const start = Date.now();
|
|
463
461
|
while (Date.now() - start < timeoutMs) {
|
|
464
462
|
if (await Effect.runPromise(sessionExists(sessionName))) return;
|
|
@@ -523,7 +521,7 @@ const TerminalServiceLive = Layer.effect(TerminalService, Effect.sync(() => {
|
|
|
523
521
|
state.lastCols = cols;
|
|
524
522
|
state.lastRows = rows;
|
|
525
523
|
console.log(`[terminal-service] Spawning PTY for ${state.sessionName} at ${cols}x${rows}`);
|
|
526
|
-
Promise.all([waitForTmuxSession
|
|
524
|
+
Promise.all([waitForTmuxSession(state.sessionName), getNodePty()]).then(() => {
|
|
527
525
|
const proc = spawnPtyImmediate(state.sessionName, cols, rows);
|
|
528
526
|
state.ptyProcess = proc;
|
|
529
527
|
let chunkCount = 0;
|
|
@@ -680,7 +678,7 @@ const AgentSpawnerLive = Layer.effect(AgentSpawner, Effect.sync(() => ({
|
|
|
680
678
|
const beadsDir = join(workspacePath, ".beads");
|
|
681
679
|
const projectBeadsDir = join(workspacePath, "..", "..", ".beads");
|
|
682
680
|
if (!(existsSync$1(beadsDir) || existsSync$1(projectBeadsDir))) throw new BeadsNotInitialized({ workspace: workspacePath });
|
|
683
|
-
const { getAgentState, spawnAgent, normalizeAgentId } = await import("./agents-
|
|
681
|
+
const { getAgentState, spawnAgent, normalizeAgentId } = await import("./agents-CEcaxSkR.js");
|
|
684
682
|
const normalizedId = normalizeAgentId(issueId);
|
|
685
683
|
if ((await Effect.runPromise(getAgentState(normalizedId)))?.status === "running") throw new AgentAlreadyRunning({ id: issueId });
|
|
686
684
|
return {
|
|
@@ -711,7 +709,7 @@ const AgentSpawnerLive = Layer.effect(AgentSpawner, Effect.sync(() => ({
|
|
|
711
709
|
const { workspacePath, projectPath, issue } = opts;
|
|
712
710
|
if (!existsSync$1(workspacePath)) throw new WorkspaceNotFound({ id: issueId });
|
|
713
711
|
const sessionName = opts.sessionName ?? `planning-${issueId.toLowerCase()}`;
|
|
714
|
-
const { spawnPlanningSession } = await import("./spawn-planning-session-
|
|
712
|
+
const { spawnPlanningSession } = await import("./spawn-planning-session-D5N3RuLG.js");
|
|
715
713
|
const result = await spawnPlanningSession({
|
|
716
714
|
issue: {
|
|
717
715
|
id: issue.id,
|
|
@@ -744,14 +742,14 @@ const AgentSpawnerLive = Layer.effect(AgentSpawner, Effect.sync(() => ({
|
|
|
744
742
|
}),
|
|
745
743
|
kill: (agentId) => Effect.tryPromise({
|
|
746
744
|
try: async () => {
|
|
747
|
-
const { stopAgent } = await import("./agents-
|
|
745
|
+
const { stopAgent } = await import("./agents-CEcaxSkR.js");
|
|
748
746
|
await Effect.runPromise(stopAgent(agentId));
|
|
749
747
|
},
|
|
750
748
|
catch: () => void 0
|
|
751
749
|
}).pipe(Effect.ignore),
|
|
752
750
|
message: (agentId, msg) => Effect.tryPromise({
|
|
753
751
|
try: async () => {
|
|
754
|
-
const { messageAgent } = await import("./agents-
|
|
752
|
+
const { messageAgent } = await import("./agents-CEcaxSkR.js");
|
|
755
753
|
await messageAgent(agentId, msg);
|
|
756
754
|
},
|
|
757
755
|
catch: (err) => new AgentStartError({
|
|
@@ -762,8 +760,8 @@ const AgentSpawnerLive = Layer.effect(AgentSpawner, Effect.sync(() => ({
|
|
|
762
760
|
}),
|
|
763
761
|
deepWipe: (issueId, opts) => Effect.tryPromise({
|
|
764
762
|
try: async () => {
|
|
765
|
-
const { deepWipe } = await import("./workflows-
|
|
766
|
-
const { resolveProjectFromIssueSync } = await import("./projects-
|
|
763
|
+
const { deepWipe } = await import("./workflows-BLwxUMP7.js");
|
|
764
|
+
const { resolveProjectFromIssueSync } = await import("./projects-CrBE6IhN.js");
|
|
767
765
|
const project = resolveProjectFromIssueSync(issueId);
|
|
768
766
|
const projectPath = project?.projectPath ?? process.cwd();
|
|
769
767
|
await Effect.runPromise(deepWipe({
|
|
@@ -792,7 +790,7 @@ const AgentSpawnerLive = Layer.effect(AgentSpawner, Effect.sync(() => ({
|
|
|
792
790
|
* Route handlers and AgentSpawner use this instead of calling workspace-manager directly.
|
|
793
791
|
*/
|
|
794
792
|
init_typed_errors();
|
|
795
|
-
const execAsync$
|
|
793
|
+
const execAsync$10 = promisify(exec);
|
|
796
794
|
var WorkspaceService = class extends Context.Service()("overdeck/dashboard/WorkspaceService") {};
|
|
797
795
|
const WorkspaceServiceLive = Layer.effect(WorkspaceService, Effect.sync(() => {
|
|
798
796
|
function getWorkspacePath(issueId) {
|
|
@@ -819,8 +817,8 @@ const WorkspaceServiceLive = Layer.effect(WorkspaceService, Effect.sync(() => {
|
|
|
819
817
|
const { workspacePath, branch } = getWorkspacePath(issueId);
|
|
820
818
|
const issueLower = issueId.toLowerCase();
|
|
821
819
|
if (existsSync$1(workspacePath)) return workspacePath;
|
|
822
|
-
const { createWorkspace } = await import("./workspace-manager-
|
|
823
|
-
const { loadProjectsConfigSync } = await import("./projects-
|
|
820
|
+
const { createWorkspace } = await import("./workspace-manager-BO-6k3sP.js");
|
|
821
|
+
const { loadProjectsConfigSync } = await import("./projects-CrBE6IhN.js");
|
|
824
822
|
const { projects } = loadProjectsConfigSync();
|
|
825
823
|
const project = resolveProjectFromIssueSync(issueId);
|
|
826
824
|
if (!project) throw new WorkspaceCreateError({
|
|
@@ -855,7 +853,7 @@ const WorkspaceServiceLive = Layer.effect(WorkspaceService, Effect.sync(() => {
|
|
|
855
853
|
const { workspacePath } = getWorkspacePath(issueId);
|
|
856
854
|
const issueLower = issueId.toLowerCase();
|
|
857
855
|
if (!existsSync$1(workspacePath)) throw new WorkspaceNotFound({ id: issueId });
|
|
858
|
-
const { removeWorkspace } = await import("./workspace-manager-
|
|
856
|
+
const { removeWorkspace } = await import("./workspace-manager-BO-6k3sP.js");
|
|
859
857
|
const project = resolveProjectFromIssueSync(issueId);
|
|
860
858
|
if (!project) throw new WorkspaceCreateError({
|
|
861
859
|
id: issueId,
|
|
@@ -886,7 +884,7 @@ const WorkspaceServiceLive = Layer.effect(WorkspaceService, Effect.sync(() => {
|
|
|
886
884
|
try: async () => {
|
|
887
885
|
const { workspacePath } = getWorkspacePath(issueId);
|
|
888
886
|
const issueLower = issueId.toLowerCase();
|
|
889
|
-
const { stopWorkspaceDocker } = await import("./workspace-manager-
|
|
887
|
+
const { stopWorkspaceDocker } = await import("./workspace-manager-BO-6k3sP.js");
|
|
890
888
|
await Effect.runPromise(stopWorkspaceDocker(workspacePath, issueLower));
|
|
891
889
|
},
|
|
892
890
|
catch: () => void 0
|
|
@@ -955,7 +953,7 @@ const WorkspaceServiceLive = Layer.effect(WorkspaceService, Effect.sync(() => {
|
|
|
955
953
|
join(workspacePath, ".devcontainer", "docker-compose.devcontainer.yml")
|
|
956
954
|
];
|
|
957
955
|
if (!composePaths.find((p) => existsSync$1(p))) {
|
|
958
|
-
const { ensureDevcontainerSync } = await import("./ensure-devcontainer-
|
|
956
|
+
const { ensureDevcontainerSync } = await import("./ensure-devcontainer-Dq3KoOIl.js");
|
|
959
957
|
const ensure = ensureDevcontainerSync({
|
|
960
958
|
workspacePath,
|
|
961
959
|
issueId
|
|
@@ -966,7 +964,7 @@ const WorkspaceServiceLive = Layer.effect(WorkspaceService, Effect.sync(() => {
|
|
|
966
964
|
});
|
|
967
965
|
}
|
|
968
966
|
const finalComposePath = composePaths.find((p) => existsSync$1(p));
|
|
969
|
-
if (finalComposePath) await execAsync$
|
|
967
|
+
if (finalComposePath) await execAsync$10(`docker compose -f "${finalComposePath}" up -d --build`, {
|
|
970
968
|
cwd: dirname(finalComposePath),
|
|
971
969
|
timeout: 3e5
|
|
972
970
|
});
|
|
@@ -1110,26 +1108,9 @@ const OpenRouterServiceLive = Layer.effect(OpenRouterService, Effect.sync(() =>
|
|
|
1110
1108
|
};
|
|
1111
1109
|
}));
|
|
1112
1110
|
//#endregion
|
|
1113
|
-
//#region ../../lib/default-cwd.ts
|
|
1114
|
-
/**
|
|
1115
|
-
* Resolve the default cwd used when no project is selected — the "devroot"
|
|
1116
|
-
* fallback. Prefers `~/Projects` if it exists, otherwise the user's home
|
|
1117
|
-
* directory.
|
|
1118
|
-
*
|
|
1119
|
-
* Replaces the deprecated `sync.devroot` config (PAN-1201) for the runtime
|
|
1120
|
-
* code paths that still need a sensible default working directory:
|
|
1121
|
-
*
|
|
1122
|
-
* - New conversations created without a `projectKey` (conversations.ts)
|
|
1123
|
-
* - The global editor-launcher in the dashboard top bar (PanOpenInPicker)
|
|
1124
|
-
*/
|
|
1125
|
-
function getDefaultCwd() {
|
|
1126
|
-
const candidate = join(homedir$1(), "Projects");
|
|
1127
|
-
return existsSync$1(candidate) ? candidate : homedir$1();
|
|
1128
|
-
}
|
|
1129
|
-
//#endregion
|
|
1130
1111
|
//#region services/open.ts
|
|
1131
1112
|
init_src();
|
|
1132
|
-
const execAsync$
|
|
1113
|
+
const execAsync$9 = promisify(exec);
|
|
1133
1114
|
function getFileManagerCommand() {
|
|
1134
1115
|
switch (process.platform) {
|
|
1135
1116
|
case "linux": return "xdg-open";
|
|
@@ -1162,7 +1143,7 @@ function launchDetached(launch) {
|
|
|
1162
1143
|
}
|
|
1163
1144
|
async function isCommandAvailable(command) {
|
|
1164
1145
|
try {
|
|
1165
|
-
await execAsync$
|
|
1146
|
+
await execAsync$9(`${process.platform === "win32" ? "where" : "which"} ${command}`);
|
|
1166
1147
|
return true;
|
|
1167
1148
|
} catch {
|
|
1168
1149
|
return false;
|
|
@@ -4975,71 +4956,6 @@ const postCodexReauthStatusRoute = HttpRouter.add("POST", "/api/settings/codex-r
|
|
|
4975
4956
|
})));
|
|
4976
4957
|
const codexAuthRouteLayer = Layer.mergeAll(getCodexAuthRoute, postCodexReauthRoute, postCodexReauthStatusRoute);
|
|
4977
4958
|
//#endregion
|
|
4978
|
-
//#region services/pending-respawn.ts
|
|
4979
|
-
/**
|
|
4980
|
-
* Tracks tmux sessions that are mid-respawn so that `/ws/terminal`
|
|
4981
|
-
* reconnects landing in the kill→spawn gap don't get a fatal 4404.
|
|
4982
|
-
*
|
|
4983
|
-
* Background: switch-model, resume, and restart-all all do
|
|
4984
|
-
*
|
|
4985
|
-
* await killSessionAsync(name) // old tmux dies, PTY exits,
|
|
4986
|
-
* // ws-terminal closes clients with 1000
|
|
4987
|
-
* await spawnConversationSession(...) // new tmux session with same name
|
|
4988
|
-
* await waitForTmuxSession(name)
|
|
4989
|
-
* await waitForReadySignal(name, 30) // up to 30s
|
|
4990
|
-
*
|
|
4991
|
-
* The terminal frontend (`XTerminal.tsx`) reconnects on close 1000 with
|
|
4992
|
-
* exponential backoff (1s, 2s, 4s, 8s, 16s). Every reconnect re-enters
|
|
4993
|
-
* `ws-terminal.ts`, which checks the tmux session list upfront and
|
|
4994
|
-
* `close(4404, 'session-not-found')` if the name isn't there yet.
|
|
4995
|
-
* 4404 is treated as fatal on the client (no retry — the session is
|
|
4996
|
-
* presumed gone), so the panel sticks on "Could not reconnect" even
|
|
4997
|
-
* after the respawn completes a moment later.
|
|
4998
|
-
*
|
|
4999
|
-
* This registry lets `ws-terminal.ts` distinguish "transient absence
|
|
5000
|
-
* during respawn" from "session is actually gone". Respawn sites mark
|
|
5001
|
-
* the name with `markRespawnPending()` for the duration of their kill+
|
|
5002
|
-
* spawn block; ws-terminal calls `waitForSessionRespawn()` instead of
|
|
5003
|
-
* 4404-ing immediately when the session is missing AND
|
|
5004
|
-
* `isRespawnPending()` is true.
|
|
5005
|
-
*/
|
|
5006
|
-
init_tmux();
|
|
5007
|
-
const pendingRespawns = /* @__PURE__ */ new Set();
|
|
5008
|
-
/**
|
|
5009
|
-
* Mark a tmux session as mid-respawn. The returned `done()` must run in
|
|
5010
|
-
* a `finally` so the marker is cleared even if the respawn throws.
|
|
5011
|
-
*/
|
|
5012
|
-
function markRespawnPending(sessionName) {
|
|
5013
|
-
pendingRespawns.add(sessionName);
|
|
5014
|
-
return { done: () => {
|
|
5015
|
-
pendingRespawns.delete(sessionName);
|
|
5016
|
-
} };
|
|
5017
|
-
}
|
|
5018
|
-
/** True if a respawn is currently in progress for this session name. */
|
|
5019
|
-
function isRespawnPending(sessionName) {
|
|
5020
|
-
return pendingRespawns.has(sessionName);
|
|
5021
|
-
}
|
|
5022
|
-
const POLL_INTERVAL_MS$4 = 200;
|
|
5023
|
-
/**
|
|
5024
|
-
* Poll for the session to come back, up to `timeoutMs`. Returns whether
|
|
5025
|
-
* it did. Bails early once `pendingRespawns` no longer contains the name
|
|
5026
|
-
* (the wrapping respawn block finished, success or failure) and the
|
|
5027
|
-
* session still isn't there — at that point the absence is real.
|
|
5028
|
-
*
|
|
5029
|
-
* `timeoutMs` should comfortably exceed the longest respawn window. The
|
|
5030
|
-
* dominant cost is `waitForReadySignal`'s 30s ceiling in the conversation
|
|
5031
|
-
* routes, so 35s is the right default for those callers.
|
|
5032
|
-
*/
|
|
5033
|
-
async function waitForSessionRespawn(sessionName, timeoutMs) {
|
|
5034
|
-
const deadline = Date.now() + timeoutMs;
|
|
5035
|
-
while (Date.now() < deadline) {
|
|
5036
|
-
if (await Effect.runPromise(sessionExists(sessionName))) return true;
|
|
5037
|
-
if (!pendingRespawns.has(sessionName)) return Effect.runPromise(sessionExists(sessionName));
|
|
5038
|
-
await new Promise((r) => setTimeout(r, POLL_INTERVAL_MS$4));
|
|
5039
|
-
}
|
|
5040
|
-
return Effect.runPromise(sessionExists(sessionName));
|
|
5041
|
-
}
|
|
5042
|
-
//#endregion
|
|
5043
4959
|
//#region ws-terminal.ts
|
|
5044
4960
|
init_tmux();
|
|
5045
4961
|
init_child_env();
|
|
@@ -15973,7 +15889,7 @@ var require_get_vercel_oidc_token = /* @__PURE__ */ __commonJSMin(((exports, mod
|
|
|
15973
15889
|
err = error;
|
|
15974
15890
|
}
|
|
15975
15891
|
try {
|
|
15976
|
-
const [{ getTokenPayload, isExpired }, { refreshToken }] = await Promise.all([await import("./token-util-
|
|
15892
|
+
const [{ getTokenPayload, isExpired }, { refreshToken }] = await Promise.all([await import("./token-util-C9u4An3K.js").then((m) => /* @__PURE__ */ __toESM(m.default)), await import("./token-g_sJ19g3.js").then((m) => /* @__PURE__ */ __toESM(m.default))]);
|
|
15977
15893
|
if (!token || isExpired(getTokenPayload(token), options?.expirationBufferMs)) {
|
|
15978
15894
|
await refreshToken(options);
|
|
15979
15895
|
token = getVercelOidcTokenSync();
|
|
@@ -28290,7 +28206,7 @@ var GoogleCloudTranscription = class {
|
|
|
28290
28206
|
}
|
|
28291
28207
|
async start(apiKey, model) {
|
|
28292
28208
|
try {
|
|
28293
|
-
const { SpeechClient } = await import("./src-
|
|
28209
|
+
const { SpeechClient } = await import("./src-D4YUZrwR.js").then((m) => /* @__PURE__ */ __toESM(m.default, 1)).then((module) => module.v1p1beta1 ?? module.v1);
|
|
28294
28210
|
if (this.closed) return;
|
|
28295
28211
|
const stream = new SpeechClient({ apiKey }).streamingRecognize({
|
|
28296
28212
|
config: {
|
|
@@ -28956,9 +28872,9 @@ function setupAutoPresoWebSocket(server) {
|
|
|
28956
28872
|
}
|
|
28957
28873
|
//#endregion
|
|
28958
28874
|
//#region services/read-workspace-file.ts
|
|
28875
|
+
init_behavior();
|
|
28959
28876
|
init_discovered_sessions();
|
|
28960
28877
|
init_conversations();
|
|
28961
|
-
init_behavior();
|
|
28962
28878
|
init_codex_conversation_parser();
|
|
28963
28879
|
init_ohmypi_conversation_parser();
|
|
28964
28880
|
init_pi_conversation_parser();
|
|
@@ -30076,18 +29992,13 @@ init_briefing_freshness();
|
|
|
30076
29992
|
init_types();
|
|
30077
29993
|
init_specs();
|
|
30078
29994
|
init_io();
|
|
30079
|
-
init_pty_supervisor_locate();
|
|
30080
|
-
init_pty_token();
|
|
30081
29995
|
init_agent_record_sync();
|
|
30082
29996
|
init_openai_auth();
|
|
30083
29997
|
init_claude_permissions();
|
|
30084
29998
|
init_claude_auth();
|
|
30085
29999
|
init_layers();
|
|
30086
30000
|
init_codex();
|
|
30087
|
-
init_ohmypi_fifo();
|
|
30088
|
-
init_pi_fifo();
|
|
30089
30001
|
init_launcher_generator();
|
|
30090
|
-
init_bridge_token();
|
|
30091
30002
|
init_transcript_landing();
|
|
30092
30003
|
init_state_home();
|
|
30093
30004
|
init_operator_interventions();
|
|
@@ -30418,7 +30329,7 @@ function parseIssueIdFromTextSync(value) {
|
|
|
30418
30329
|
//#region services/resource-discovery.ts
|
|
30419
30330
|
init_projects();
|
|
30420
30331
|
init_tmux();
|
|
30421
|
-
const execFileAsync$
|
|
30332
|
+
const execFileAsync$15 = promisify(execFile);
|
|
30422
30333
|
const RESOURCE_DISCOVERY_TTL_MS = 3e4;
|
|
30423
30334
|
const RECENT_ACTIVITY_WINDOW_MS = 5e3;
|
|
30424
30335
|
let cachedResourceIssues = null;
|
|
@@ -30526,7 +30437,7 @@ function isDiscoverableAgentSession(sessionName) {
|
|
|
30526
30437
|
async function loadTrackerIssues() {
|
|
30527
30438
|
const map = /* @__PURE__ */ new Map();
|
|
30528
30439
|
try {
|
|
30529
|
-
const { getSharedIssueService } = await import("./issue-service-singleton-
|
|
30440
|
+
const { getSharedIssueService } = await import("./issue-service-singleton-MZsDhAob.js");
|
|
30530
30441
|
const issues = (await getSharedIssueService()).getIssues();
|
|
30531
30442
|
for (const issue of issues) if (issue.identifier) map.set(issue.identifier.toUpperCase(), issue);
|
|
30532
30443
|
} catch {
|
|
@@ -30543,7 +30454,7 @@ async function loadTmuxSessions() {
|
|
|
30543
30454
|
}
|
|
30544
30455
|
async function loadDockerContainers() {
|
|
30545
30456
|
try {
|
|
30546
|
-
const { stdout } = await execFileAsync$
|
|
30457
|
+
const { stdout } = await execFileAsync$15("docker", [
|
|
30547
30458
|
"ps",
|
|
30548
30459
|
"--format",
|
|
30549
30460
|
"{{.Names}}"
|
|
@@ -30561,7 +30472,7 @@ async function loadOpenPullRequests() {
|
|
|
30561
30472
|
const repos = getGitHubConfig()?.repos ?? [];
|
|
30562
30473
|
await Promise.all(repos.map(async (repo) => {
|
|
30563
30474
|
try {
|
|
30564
|
-
const { stdout } = await execFileAsync$
|
|
30475
|
+
const { stdout } = await execFileAsync$15("gh", [
|
|
30565
30476
|
"pr",
|
|
30566
30477
|
"list",
|
|
30567
30478
|
"--repo",
|
|
@@ -30592,7 +30503,7 @@ async function loadOpenPullRequests() {
|
|
|
30592
30503
|
}
|
|
30593
30504
|
async function loadProjectBranches(projectPath) {
|
|
30594
30505
|
try {
|
|
30595
|
-
const [localResult, remoteResult] = await Promise.all([execFileAsync$
|
|
30506
|
+
const [localResult, remoteResult] = await Promise.all([execFileAsync$15("git", [
|
|
30596
30507
|
"for-each-ref",
|
|
30597
30508
|
"refs/heads/feature/*",
|
|
30598
30509
|
"--format=%(refname:short)"
|
|
@@ -30600,7 +30511,7 @@ async function loadProjectBranches(projectPath) {
|
|
|
30600
30511
|
cwd: projectPath,
|
|
30601
30512
|
encoding: "utf-8",
|
|
30602
30513
|
timeout: 1e4
|
|
30603
|
-
}).catch(() => ({ stdout: "" })), execFileAsync$
|
|
30514
|
+
}).catch(() => ({ stdout: "" })), execFileAsync$15("git", [
|
|
30604
30515
|
"for-each-ref",
|
|
30605
30516
|
"refs/remotes/origin/feature/*",
|
|
30606
30517
|
"--format=%(refname:short)"
|
|
@@ -30725,7 +30636,7 @@ async function computeResourceAllocatedIssues() {
|
|
|
30725
30636
|
if (!issue.resourceDetails.tmuxSessions.includes(sessionName)) issue.resourceDetails.tmuxSessions.push(sessionName);
|
|
30726
30637
|
}
|
|
30727
30638
|
try {
|
|
30728
|
-
const { listActiveRemoteAgentStates } = await import("./remote-agents-
|
|
30639
|
+
const { listActiveRemoteAgentStates } = await import("./remote-agents-Cv-U-_V8.js");
|
|
30729
30640
|
for (const remoteState of listActiveRemoteAgentStates()) {
|
|
30730
30641
|
const issue = ensureIssue(remoteState.issueId);
|
|
30731
30642
|
if (!issue) continue;
|
|
@@ -31221,7 +31132,7 @@ init_projects();
|
|
|
31221
31132
|
init_remote_agents();
|
|
31222
31133
|
init_tracker_utils();
|
|
31223
31134
|
init_tmux();
|
|
31224
|
-
const execFileAsync$
|
|
31135
|
+
const execFileAsync$14 = promisify(execFile);
|
|
31225
31136
|
function getIssueDataService$9() {
|
|
31226
31137
|
return getSharedIssueService();
|
|
31227
31138
|
}
|
|
@@ -31284,7 +31195,7 @@ async function completePlanningArtifacts(options) {
|
|
|
31284
31195
|
if (workspaceIssueId && workspaceIssueId.toLowerCase() !== issueLower) throw new Error(`Workspace vBRIEF is for ${workspaceIssueId.toUpperCase()}, not ${upperIssueId}`);
|
|
31285
31196
|
assertPlanQuality(workspaceDoc);
|
|
31286
31197
|
const createBeads = options.createBeads ?? (async (path) => {
|
|
31287
|
-
const mod = await import("./beads-
|
|
31198
|
+
const mod = await import("./beads-B1u04n3o.js");
|
|
31288
31199
|
return await Effect.runPromise(mod.createBeadsFromVBrief(path));
|
|
31289
31200
|
});
|
|
31290
31201
|
emitCompletePlanningPhase(upperIssueId, "specWrite", "start", "writing proposed vBRIEF spec", { projectPath });
|
|
@@ -31376,7 +31287,7 @@ async function commitWorkspaceRecordBeforeAutoSpawn(gitRoot, issueId) {
|
|
|
31376
31287
|
} catch {}
|
|
31377
31288
|
const recordPath = join(".pan", "records", `${issueLower}.json`);
|
|
31378
31289
|
try {
|
|
31379
|
-
const { stdout: statusOut } = await execFileAsync$
|
|
31290
|
+
const { stdout: statusOut } = await execFileAsync$14("git", [
|
|
31380
31291
|
"status",
|
|
31381
31292
|
"--porcelain",
|
|
31382
31293
|
"--",
|
|
@@ -31386,7 +31297,7 @@ async function commitWorkspaceRecordBeforeAutoSpawn(gitRoot, issueId) {
|
|
|
31386
31297
|
encoding: "utf-8"
|
|
31387
31298
|
});
|
|
31388
31299
|
if (!statusOut.trim()) return;
|
|
31389
|
-
await execFileAsync$
|
|
31300
|
+
await execFileAsync$14("git", [
|
|
31390
31301
|
"add",
|
|
31391
31302
|
"--",
|
|
31392
31303
|
recordPath
|
|
@@ -31395,7 +31306,7 @@ async function commitWorkspaceRecordBeforeAutoSpawn(gitRoot, issueId) {
|
|
|
31395
31306
|
encoding: "utf-8"
|
|
31396
31307
|
});
|
|
31397
31308
|
try {
|
|
31398
|
-
await execFileAsync$
|
|
31309
|
+
await execFileAsync$14("git", [
|
|
31399
31310
|
"diff",
|
|
31400
31311
|
"--cached",
|
|
31401
31312
|
"--quiet",
|
|
@@ -31407,7 +31318,7 @@ async function commitWorkspaceRecordBeforeAutoSpawn(gitRoot, issueId) {
|
|
|
31407
31318
|
});
|
|
31408
31319
|
return;
|
|
31409
31320
|
} catch {}
|
|
31410
|
-
await execFileAsync$
|
|
31321
|
+
await execFileAsync$14("git", [
|
|
31411
31322
|
"commit",
|
|
31412
31323
|
"-m",
|
|
31413
31324
|
`chore(records): update ${issueId.toUpperCase()} per-issue record before auto-start`,
|
|
@@ -31626,7 +31537,7 @@ async function completePlanningForIssue(options) {
|
|
|
31626
31537
|
if (migrated) await Effect.runPromise(flushAutoCommits(projectPath));
|
|
31627
31538
|
else if (!projectIsGitRepo) console.log(`[complete-planning] Project root ${projectPath} is not a git repository (polyrepo) — pan spec updated on disk but not committed`);
|
|
31628
31539
|
else {
|
|
31629
|
-
const { stdout: branchStdout } = await execFileAsync$
|
|
31540
|
+
const { stdout: branchStdout } = await execFileAsync$14("git", [
|
|
31630
31541
|
"rev-parse",
|
|
31631
31542
|
"--abbrev-ref",
|
|
31632
31543
|
"HEAD"
|
|
@@ -31636,7 +31547,7 @@ async function completePlanningForIssue(options) {
|
|
|
31636
31547
|
});
|
|
31637
31548
|
const currentBranch = branchStdout.trim();
|
|
31638
31549
|
if (currentBranch === "main") {
|
|
31639
|
-
await execFileAsync$
|
|
31550
|
+
await execFileAsync$14("git", [
|
|
31640
31551
|
"add",
|
|
31641
31552
|
"--",
|
|
31642
31553
|
...filesToStage
|
|
@@ -31645,7 +31556,7 @@ async function completePlanningForIssue(options) {
|
|
|
31645
31556
|
encoding: "utf-8"
|
|
31646
31557
|
});
|
|
31647
31558
|
try {
|
|
31648
|
-
await execFileAsync$
|
|
31559
|
+
await execFileAsync$14("git", [
|
|
31649
31560
|
"diff",
|
|
31650
31561
|
"--cached",
|
|
31651
31562
|
"--quiet",
|
|
@@ -31656,7 +31567,7 @@ async function completePlanningForIssue(options) {
|
|
|
31656
31567
|
encoding: "utf-8"
|
|
31657
31568
|
});
|
|
31658
31569
|
} catch {
|
|
31659
|
-
await execFileAsync$
|
|
31570
|
+
await execFileAsync$14("git", [
|
|
31660
31571
|
"commit",
|
|
31661
31572
|
"-m",
|
|
31662
31573
|
`chore(scope): propose ${upperIssueId} vBRIEF`,
|
|
@@ -31669,7 +31580,7 @@ async function completePlanningForIssue(options) {
|
|
|
31669
31580
|
});
|
|
31670
31581
|
console.log(`[complete-planning] Committed pan spec on main for ${upperIssueId}`);
|
|
31671
31582
|
try {
|
|
31672
|
-
const { stdout: remotes } = await execFileAsync$
|
|
31583
|
+
const { stdout: remotes } = await execFileAsync$14("git", ["remote"], {
|
|
31673
31584
|
cwd: projectPath,
|
|
31674
31585
|
encoding: "utf-8"
|
|
31675
31586
|
});
|
|
@@ -31682,16 +31593,16 @@ async function completePlanningForIssue(options) {
|
|
|
31682
31593
|
}
|
|
31683
31594
|
} else console.log(`[complete-planning] Project root not on main (${currentBranch}) — pan spec updated on disk but not committed on main`);
|
|
31684
31595
|
}
|
|
31685
|
-
if (!existsSync$1(join(gitRoot, ".git"))) await execFileAsync$
|
|
31596
|
+
if (!existsSync$1(join(gitRoot, ".git"))) await execFileAsync$14("git", ["init"], {
|
|
31686
31597
|
cwd: gitRoot,
|
|
31687
31598
|
encoding: "utf-8"
|
|
31688
31599
|
});
|
|
31689
|
-
for (const args of completePlanningWorkspaceGitAddCommands(gitRoot, migrated)) await execFileAsync$
|
|
31600
|
+
for (const args of completePlanningWorkspaceGitAddCommands(gitRoot, migrated)) await execFileAsync$14("git", args, {
|
|
31690
31601
|
cwd: gitRoot,
|
|
31691
31602
|
encoding: "utf-8"
|
|
31692
31603
|
});
|
|
31693
31604
|
try {
|
|
31694
|
-
await execFileAsync$
|
|
31605
|
+
await execFileAsync$14("git", [
|
|
31695
31606
|
"diff",
|
|
31696
31607
|
"--cached",
|
|
31697
31608
|
"--quiet"
|
|
@@ -31700,7 +31611,7 @@ async function completePlanningForIssue(options) {
|
|
|
31700
31611
|
encoding: "utf-8"
|
|
31701
31612
|
});
|
|
31702
31613
|
} catch {
|
|
31703
|
-
await execFileAsync$
|
|
31614
|
+
await execFileAsync$14("git", [
|
|
31704
31615
|
"commit",
|
|
31705
31616
|
"-m",
|
|
31706
31617
|
`chore(plan): complete planning for ${id}`,
|
|
@@ -31711,7 +31622,7 @@ async function completePlanningForIssue(options) {
|
|
|
31711
31622
|
});
|
|
31712
31623
|
}
|
|
31713
31624
|
try {
|
|
31714
|
-
const { stdout: remotes } = await execFileAsync$
|
|
31625
|
+
const { stdout: remotes } = await execFileAsync$14("git", ["remote"], {
|
|
31715
31626
|
cwd: gitRoot,
|
|
31716
31627
|
encoding: "utf-8"
|
|
31717
31628
|
});
|
|
@@ -31891,8 +31802,8 @@ init_tracker_utils();
|
|
|
31891
31802
|
init_agents$1();
|
|
31892
31803
|
init_issue_id();
|
|
31893
31804
|
init_io();
|
|
31894
|
-
const execAsync$
|
|
31895
|
-
const execFileAsync$
|
|
31805
|
+
const execAsync$8 = promisify(exec);
|
|
31806
|
+
const execFileAsync$13 = promisify(execFile);
|
|
31896
31807
|
function isGitHubIssue$4(issueId) {
|
|
31897
31808
|
const resolved = resolveGitHubIssueSync(issueId);
|
|
31898
31809
|
if (resolved.isGitHub) return {
|
|
@@ -31931,7 +31842,7 @@ async function closeIssuePullRequest(issueId, reason = "Canceled via Overdeck")
|
|
|
31931
31842
|
if (!githubCheck.isGitHub || !githubCheck.owner || !githubCheck.repo) return ["No GitHub PR to close"];
|
|
31932
31843
|
const branchName = `feature/${issueId.toLowerCase()}`;
|
|
31933
31844
|
try {
|
|
31934
|
-
const { stdout: prListRaw } = await execFileAsync$
|
|
31845
|
+
const { stdout: prListRaw } = await execFileAsync$13("gh", [
|
|
31935
31846
|
"pr",
|
|
31936
31847
|
"list",
|
|
31937
31848
|
"--repo",
|
|
@@ -31950,7 +31861,7 @@ async function closeIssuePullRequest(issueId, reason = "Canceled via Overdeck")
|
|
|
31950
31861
|
});
|
|
31951
31862
|
const prNumber = prListRaw.trim();
|
|
31952
31863
|
if (!prNumber) return ["No open PR found for branch"];
|
|
31953
|
-
await execFileAsync$
|
|
31864
|
+
await execFileAsync$13("gh", [
|
|
31954
31865
|
"pr",
|
|
31955
31866
|
"close",
|
|
31956
31867
|
prNumber,
|
|
@@ -31963,7 +31874,7 @@ async function closeIssuePullRequest(issueId, reason = "Canceled via Overdeck")
|
|
|
31963
31874
|
timeout: 15e3
|
|
31964
31875
|
});
|
|
31965
31876
|
try {
|
|
31966
|
-
const { setReviewStatusSync } = await import("./review-status-
|
|
31877
|
+
const { setReviewStatusSync } = await import("./review-status-CG0iDuWa.js");
|
|
31967
31878
|
setReviewStatusSync(issueId.toUpperCase(), { prUrl: void 0 });
|
|
31968
31879
|
} catch {}
|
|
31969
31880
|
return [`Closed PR #${prNumber} on ${githubCheck.owner}/${githubCheck.repo}`];
|
|
@@ -32017,7 +31928,7 @@ async function runDestructiveIssueLifecycle(id, mode, opts = {}) {
|
|
|
32017
31928
|
const { ctx, projectConfig } = buildLifecycleContext(id, getIssueDataService$8().getIssueSource(id) ?? void 0);
|
|
32018
31929
|
const deleteWorkspace = opts.deleteWorkspace ?? true;
|
|
32019
31930
|
cleanupLog.push(...await closeIssuePullRequest(id, mode === "cancel" ? "Canceled via Overdeck" : "Reset to Todo via Overdeck"));
|
|
32020
|
-
const { resetToTodo, cancelIssueWorkflow } = await import("./lifecycle-
|
|
31931
|
+
const { resetToTodo, cancelIssueWorkflow } = await import("./lifecycle-Ck2UR27D.js");
|
|
32021
31932
|
const workflow = mode === "cancel" ? cancelIssueWorkflow : resetToTodo;
|
|
32022
31933
|
const result = await Effect.runPromise(workflow(ctx, {
|
|
32023
31934
|
deleteWorkspace,
|
|
@@ -32032,7 +31943,7 @@ async function runDestructiveIssueLifecycle(id, mode, opts = {}) {
|
|
|
32032
31943
|
}));
|
|
32033
31944
|
cleanupLog.push(...result.steps.flatMap((step) => step.details || [step.error].filter(Boolean)));
|
|
32034
31945
|
if (mode === "cancel") try {
|
|
32035
|
-
const { transitionVBriefOnMain } = await import("./lifecycle-io-
|
|
31946
|
+
const { transitionVBriefOnMain } = await import("./lifecycle-io-DXv8Utct.js");
|
|
32036
31947
|
const tx = await Effect.runPromise(transitionVBriefOnMain(ctx.projectPath, id, "cancelled", "cancelled", `scope: cancel ${id.toUpperCase()} vBRIEF`));
|
|
32037
31948
|
if (tx.moved) cleanupLog.push(`vBRIEF moved ${tx.fromDir} → cancelled`);
|
|
32038
31949
|
if (tx.committed) cleanupLog.push(`Committed vBRIEF cancellation on main`);
|
|
@@ -32040,8 +31951,8 @@ async function runDestructiveIssueLifecycle(id, mode, opts = {}) {
|
|
|
32040
31951
|
cleanupLog.push(`vBRIEF cancel transition failed (non-fatal): ${err?.message ?? err}`);
|
|
32041
31952
|
}
|
|
32042
31953
|
try {
|
|
32043
|
-
const { killAllReviewerSessions } = await import("./review-agent-
|
|
32044
|
-
const { resolveProjectFromIssueSync } = await import("./projects-
|
|
31954
|
+
const { killAllReviewerSessions } = await import("./review-agent-u5q3ip7H.js");
|
|
31955
|
+
const { resolveProjectFromIssueSync } = await import("./projects-CrBE6IhN.js");
|
|
32045
31956
|
const projectKey = resolveProjectFromIssueSync(id)?.projectKey;
|
|
32046
31957
|
if (projectKey) {
|
|
32047
31958
|
const { killed } = await Effect.runPromise(killAllReviewerSessions(projectKey, id.toUpperCase()));
|
|
@@ -32055,7 +31966,7 @@ async function runDestructiveIssueLifecycle(id, mode, opts = {}) {
|
|
|
32055
31966
|
cleanupLog.push("Cleared review status");
|
|
32056
31967
|
} catch {}
|
|
32057
31968
|
try {
|
|
32058
|
-
const { resetPostMergeState } = await import("./merge-agent-
|
|
31969
|
+
const { resetPostMergeState } = await import("./merge-agent-ejC7Wos8.js");
|
|
32059
31970
|
resetPostMergeState(id);
|
|
32060
31971
|
resetPostMergeState(id.toUpperCase());
|
|
32061
31972
|
cleanupLog.push("Cleared merge state");
|
|
@@ -32075,7 +31986,7 @@ function closeIssueTransition(options) {
|
|
|
32075
31986
|
const { issueId, body, eventStore } = options;
|
|
32076
31987
|
const { reason } = body;
|
|
32077
31988
|
const projectPath = getProjectPath$3(void 0, extractPrefixSync(issueId) ?? issueId.split("-")[0]);
|
|
32078
|
-
const { close: closeWorkflow } = yield* Effect.promise(() => import("./lifecycle-
|
|
31989
|
+
const { close: closeWorkflow } = yield* Effect.promise(() => import("./lifecycle-Ck2UR27D.js"));
|
|
32079
31990
|
const githubCheck = isGitHubIssue$4(issueId);
|
|
32080
31991
|
const issueDataService = getIssueDataService$8();
|
|
32081
31992
|
const issueSource = issueDataService.getIssueSource(issueId);
|
|
@@ -32098,7 +32009,7 @@ function closeIssueTransition(options) {
|
|
|
32098
32009
|
};
|
|
32099
32010
|
}
|
|
32100
32011
|
const result = yield* closeWorkflow(ctx, { reason });
|
|
32101
|
-
if (githubCheck.isGitHub) execAsync$
|
|
32012
|
+
if (githubCheck.isGitHub) execAsync$8("pan sync", {
|
|
32102
32013
|
encoding: "utf-8",
|
|
32103
32014
|
timeout: 3e4
|
|
32104
32015
|
}).catch(() => {});
|
|
@@ -32309,13 +32220,13 @@ function reopenIssueTransition(options) {
|
|
|
32309
32220
|
}
|
|
32310
32221
|
yield* Effect.promise(async () => {
|
|
32311
32222
|
try {
|
|
32312
|
-
const { stdout } = await execAsync$
|
|
32223
|
+
const { stdout } = await execAsync$8(`gh pr list --head ${`feature/${id.toLowerCase()}`} --state closed --json number,mergedAt --limit 1`, {
|
|
32313
32224
|
encoding: "utf-8",
|
|
32314
32225
|
timeout: 15e3
|
|
32315
32226
|
});
|
|
32316
32227
|
const prs = JSON.parse(stdout.trim() || "[]");
|
|
32317
32228
|
if (prs.length > 0 && !prs[0].mergedAt) {
|
|
32318
|
-
await execAsync$
|
|
32229
|
+
await execAsync$8(`gh pr reopen ${prs[0].number}`, {
|
|
32319
32230
|
encoding: "utf-8",
|
|
32320
32231
|
timeout: 15e3
|
|
32321
32232
|
});
|
|
@@ -32342,7 +32253,7 @@ function reopenIssueTransition(options) {
|
|
|
32342
32253
|
else clearReviewStatus(id.toUpperCase());
|
|
32343
32254
|
} catch {}
|
|
32344
32255
|
try {
|
|
32345
|
-
const { resetPostMergeState } = await import("./merge-agent-
|
|
32256
|
+
const { resetPostMergeState } = await import("./merge-agent-ejC7Wos8.js");
|
|
32346
32257
|
resetPostMergeState(id);
|
|
32347
32258
|
resetPostMergeState(id.toUpperCase());
|
|
32348
32259
|
} catch {}
|
|
@@ -32362,9 +32273,9 @@ function reopenIssueTransition(options) {
|
|
|
32362
32273
|
const projectPath = (teamPrefix ? findProjectByTeamSync(teamPrefix) : null)?.path || "";
|
|
32363
32274
|
if (projectPath) {
|
|
32364
32275
|
const workspacePath = join(projectPath, "workspaces", `feature-${issueLower}`);
|
|
32365
|
-
const { createBeadsFromVBrief } = await import("./beads-
|
|
32276
|
+
const { createBeadsFromVBrief } = await import("./beads-B1u04n3o.js");
|
|
32366
32277
|
if (existsSync$1(workspacePath) && await Effect.runPromise(findPlan(workspacePath))) try {
|
|
32367
|
-
const { stdout: bdCheck } = await Effect.runPromise(withBdMutex(() => Effect.promise(() => execFileAsync$
|
|
32278
|
+
const { stdout: bdCheck } = await Effect.runPromise(withBdMutex(() => Effect.promise(() => execFileAsync$13("bd", [
|
|
32368
32279
|
"list",
|
|
32369
32280
|
"--json",
|
|
32370
32281
|
"-l",
|
|
@@ -32439,7 +32350,7 @@ function moveIssueStatus(options) {
|
|
|
32439
32350
|
"done"
|
|
32440
32351
|
];
|
|
32441
32352
|
if (!targetStatus || !validStatuses.includes(targetStatus)) return jsonResponse({ error: `Invalid targetStatus. Must be one of: ${validStatuses.join(", ")}` }, { status: 400 });
|
|
32442
|
-
const { updateShadowState } = yield* Effect.promise(() => import("./shadow-state-
|
|
32353
|
+
const { updateShadowState } = yield* Effect.promise(() => import("./shadow-state-CVHpRWlb.js"));
|
|
32443
32354
|
const issueState = {
|
|
32444
32355
|
backlog: "open",
|
|
32445
32356
|
todo: "open",
|
|
@@ -32502,7 +32413,7 @@ function moveIssueStatus(options) {
|
|
|
32502
32413
|
init_issue_service_singleton();
|
|
32503
32414
|
init_issue_id();
|
|
32504
32415
|
init_agents$1();
|
|
32505
|
-
const execAsync$
|
|
32416
|
+
const execAsync$7 = promisify(exec);
|
|
32506
32417
|
function getIssueDataService$7() {
|
|
32507
32418
|
return getSharedIssueService();
|
|
32508
32419
|
}
|
|
@@ -32527,28 +32438,28 @@ async function cleanupWorkspaceForIssue(rawId, eventStore) {
|
|
|
32527
32438
|
if (projectRoot) {
|
|
32528
32439
|
const workspacePath = join(projectRoot, "workspaces", `feature-${issueLower}`);
|
|
32529
32440
|
try {
|
|
32530
|
-
if ((await execAsync$
|
|
32441
|
+
if ((await execAsync$7("git worktree list --porcelain", {
|
|
32531
32442
|
cwd: projectRoot,
|
|
32532
32443
|
encoding: "utf-8"
|
|
32533
32444
|
})).stdout.includes(workspacePath)) {
|
|
32534
|
-
await execAsync$
|
|
32445
|
+
await execAsync$7(`git worktree remove "${workspacePath}" --force`, {
|
|
32535
32446
|
cwd: projectRoot,
|
|
32536
32447
|
encoding: "utf-8"
|
|
32537
32448
|
});
|
|
32538
32449
|
cleanupLog.push(`Removed git worktree: ${workspacePath}`);
|
|
32539
32450
|
} else if (existsSync$1(workspacePath)) {
|
|
32540
|
-
await execAsync$
|
|
32451
|
+
await execAsync$7(`rm -rf "${workspacePath}"`, { encoding: "utf-8" });
|
|
32541
32452
|
cleanupLog.push(`Removed directory: ${workspacePath}`);
|
|
32542
32453
|
}
|
|
32543
32454
|
} catch {
|
|
32544
32455
|
if (existsSync$1(workspacePath)) {
|
|
32545
|
-
await execAsync$
|
|
32456
|
+
await execAsync$7(`rm -rf "${workspacePath}"`, { encoding: "utf-8" });
|
|
32546
32457
|
cleanupLog.push(`Removed directory: ${workspacePath}`);
|
|
32547
32458
|
}
|
|
32548
32459
|
}
|
|
32549
32460
|
const branchName = `feature/${issueLower}`;
|
|
32550
32461
|
try {
|
|
32551
|
-
await execAsync$
|
|
32462
|
+
await execAsync$7(`git branch -D "${branchName}" 2>/dev/null || true`, {
|
|
32552
32463
|
cwd: projectRoot,
|
|
32553
32464
|
encoding: "utf-8"
|
|
32554
32465
|
});
|
|
@@ -32557,7 +32468,7 @@ async function cleanupWorkspaceForIssue(rawId, eventStore) {
|
|
|
32557
32468
|
}
|
|
32558
32469
|
const agentDir = join(homedir$1(), ".overdeck", "agents", `agent-${issueLower}`);
|
|
32559
32470
|
if (existsSync$1(agentDir)) {
|
|
32560
|
-
await execAsync$
|
|
32471
|
+
await execAsync$7(`rm -rf "${agentDir}"`, { encoding: "utf-8" });
|
|
32561
32472
|
cleanupLog.push(`Removed agent state: ${agentDir}`);
|
|
32562
32473
|
}
|
|
32563
32474
|
await Effect.runPromise(eventStore.append({
|
|
@@ -32666,7 +32577,7 @@ async function copySettingsToWorkspace(id) {
|
|
|
32666
32577
|
success: false,
|
|
32667
32578
|
error: "Workspace not found"
|
|
32668
32579
|
}, { status: 404 });
|
|
32669
|
-
const { copyOverdeckSettingsToWorkspaceSync } = await import("./workspace-manager-
|
|
32580
|
+
const { copyOverdeckSettingsToWorkspaceSync } = await import("./workspace-manager-BO-6k3sP.js");
|
|
32670
32581
|
const result = copyOverdeckSettingsToWorkspaceSync(workspacePath);
|
|
32671
32582
|
return jsonResponse({
|
|
32672
32583
|
success: result.errors.length === 0 || result.copied.length > 0,
|
|
@@ -32701,7 +32612,7 @@ function generateTasksForIssue(id) {
|
|
|
32701
32612
|
success: false,
|
|
32702
32613
|
error: `No vBRIEF spec found on main for ${id} — run planning first.`
|
|
32703
32614
|
}, { status: 409 });
|
|
32704
|
-
const { createBeadsFromVBrief } = yield* Effect.promise(() => import("./beads-
|
|
32615
|
+
const { createBeadsFromVBrief } = yield* Effect.promise(() => import("./beads-B1u04n3o.js"));
|
|
32705
32616
|
const result = yield* createBeadsFromVBrief(workspacePath);
|
|
32706
32617
|
if (!result.success || result.created.length === 0) {
|
|
32707
32618
|
const errors = result.errors.length > 0 ? result.errors : ["Beads creation produced no tasks"];
|
|
@@ -32731,8 +32642,8 @@ init_projects();
|
|
|
32731
32642
|
init_tracker_utils();
|
|
32732
32643
|
init_tmux();
|
|
32733
32644
|
init_typed_errors();
|
|
32734
|
-
const execAsync$
|
|
32735
|
-
const execFileAsync$
|
|
32645
|
+
const execAsync$6 = promisify(exec);
|
|
32646
|
+
const execFileAsync$12 = promisify(execFile);
|
|
32736
32647
|
function getIssueDataService$6() {
|
|
32737
32648
|
return getSharedIssueService();
|
|
32738
32649
|
}
|
|
@@ -33032,7 +32943,7 @@ function abortPlanningForIssue(options) {
|
|
|
33032
32943
|
const featureWorkspacePath = join(projectPath, "workspaces", `feature-${issueIdentifier.toLowerCase()}`);
|
|
33033
32944
|
const plainWorkspacePath = join(projectPath, "workspaces", issueIdentifier.toLowerCase());
|
|
33034
32945
|
if (existsSync$1(existsSync$1(featureWorkspacePath) ? featureWorkspacePath : plainWorkspacePath)) {
|
|
33035
|
-
await execFileAsync$
|
|
32946
|
+
await execFileAsync$12("pan", [
|
|
33036
32947
|
"workspace",
|
|
33037
32948
|
"destroy",
|
|
33038
32949
|
issueIdentifier.toLowerCase(),
|
|
@@ -33141,10 +33052,10 @@ function restartFromPlan(options) {
|
|
|
33141
33052
|
});
|
|
33142
33053
|
const resetResult = yield* Effect.promise(async () => {
|
|
33143
33054
|
try {
|
|
33144
|
-
const { runGitResetHard } = await import("./dangerous-git-ops-
|
|
33055
|
+
const { runGitResetHard } = await import("./dangerous-git-ops-Bn18PEcN.js");
|
|
33145
33056
|
async function findPlanningCommit(grep, label) {
|
|
33146
33057
|
try {
|
|
33147
|
-
const { stdout } = await execAsync$
|
|
33058
|
+
const { stdout } = await execAsync$6(`git log --grep="${grep.replace(/"/g, "\\\"")}" --format=%H -1`, {
|
|
33148
33059
|
cwd: workspacePath,
|
|
33149
33060
|
encoding: "utf-8",
|
|
33150
33061
|
timeout: 1e4
|
|
@@ -33160,7 +33071,7 @@ function restartFromPlan(options) {
|
|
|
33160
33071
|
}
|
|
33161
33072
|
const found = await findPlanningCommit(`Complete planning for ${id}`, "complete-planning message") ?? await findPlanningCommit(`chore: planning artifacts for ${id}`, "agent-start message") ?? await (async () => {
|
|
33162
33073
|
try {
|
|
33163
|
-
const { stdout } = await execAsync$
|
|
33074
|
+
const { stdout } = await execAsync$6(`git log --diff-filter=A --format=%H -1 -- .pan/spec.vbrief.json`, {
|
|
33164
33075
|
cwd: workspacePath,
|
|
33165
33076
|
encoding: "utf-8",
|
|
33166
33077
|
timeout: 1e4
|
|
@@ -33294,7 +33205,7 @@ init_github_pr_lookup();
|
|
|
33294
33205
|
init_tracker_utils();
|
|
33295
33206
|
init_tracker_config();
|
|
33296
33207
|
init_pr_tab_cache();
|
|
33297
|
-
const execAsync$
|
|
33208
|
+
const execAsync$5 = promisify(exec);
|
|
33298
33209
|
function isGitHubIssue$2(issueId) {
|
|
33299
33210
|
const resolved = resolveGitHubIssueSync(issueId);
|
|
33300
33211
|
if (resolved.isGitHub) return {
|
|
@@ -33342,7 +33253,7 @@ async function fetchIssueDiscussions(issueId, deps = {}) {
|
|
|
33342
33253
|
if (githubCheck.isGitHub && githubCheck.owner && githubCheck.repo && githubCheck.number) {
|
|
33343
33254
|
const { owner, repo, number } = githubCheck;
|
|
33344
33255
|
try {
|
|
33345
|
-
const { stdout } = await execAsync$
|
|
33256
|
+
const { stdout } = await execAsync$5(`gh api "repos/${owner}/${repo}/issues/${number}/comments?per_page=100"`, {
|
|
33346
33257
|
encoding: "utf-8",
|
|
33347
33258
|
timeout: 15e3,
|
|
33348
33259
|
maxBuffer: 8 * 1024 * 1024
|
|
@@ -33405,7 +33316,7 @@ async function fetchIssueDiscussions(issueId, deps = {}) {
|
|
|
33405
33316
|
const collectedItems = [];
|
|
33406
33317
|
const prConversation = (async () => {
|
|
33407
33318
|
try {
|
|
33408
|
-
const { stdout } = await execAsync$
|
|
33319
|
+
const { stdout } = await execAsync$5(`gh api "repos/${prOwner}/${prRepo}/issues/${prNumber}/comments?per_page=100"`, {
|
|
33409
33320
|
encoding: "utf-8",
|
|
33410
33321
|
timeout: 15e3,
|
|
33411
33322
|
maxBuffer: 8 * 1024 * 1024
|
|
@@ -33426,7 +33337,7 @@ async function fetchIssueDiscussions(issueId, deps = {}) {
|
|
|
33426
33337
|
})();
|
|
33427
33338
|
const prReviews = (async () => {
|
|
33428
33339
|
try {
|
|
33429
|
-
const { stdout } = await execAsync$
|
|
33340
|
+
const { stdout } = await execAsync$5(`gh api "repos/${prOwner}/${prRepo}/pulls/${prNumber}/reviews?per_page=100"`, {
|
|
33430
33341
|
encoding: "utf-8",
|
|
33431
33342
|
timeout: 15e3,
|
|
33432
33343
|
maxBuffer: 8 * 1024 * 1024
|
|
@@ -33451,7 +33362,7 @@ async function fetchIssueDiscussions(issueId, deps = {}) {
|
|
|
33451
33362
|
})();
|
|
33452
33363
|
const prInlineComments = (async () => {
|
|
33453
33364
|
try {
|
|
33454
|
-
const { stdout } = await execAsync$
|
|
33365
|
+
const { stdout } = await execAsync$5(`gh api "repos/${prOwner}/${prRepo}/pulls/${prNumber}/comments?per_page=100"`, {
|
|
33455
33366
|
encoding: "utf-8",
|
|
33456
33367
|
timeout: 15e3,
|
|
33457
33368
|
maxBuffer: 8 * 1024 * 1024
|
|
@@ -33593,7 +33504,7 @@ function closeOutIssue(id) {
|
|
|
33593
33504
|
}
|
|
33594
33505
|
const closeOutResult = yield* Effect.promise(async () => {
|
|
33595
33506
|
try {
|
|
33596
|
-
const { closeOut } = await import("./lifecycle-
|
|
33507
|
+
const { closeOut } = await import("./lifecycle-Ck2UR27D.js");
|
|
33597
33508
|
return {
|
|
33598
33509
|
ok: true,
|
|
33599
33510
|
result: await Effect.runPromise(closeOut(ctx))
|
|
@@ -33679,7 +33590,7 @@ function bulkCloseOut(body) {
|
|
|
33679
33590
|
const invalidIds = issueIds.filter((id) => !isValidIssueId(id));
|
|
33680
33591
|
if (invalidIds.length > 0) return jsonResponse({ error: `Invalid issue ID format: ${invalidIds.join(", ")}` }, { status: 400 });
|
|
33681
33592
|
const eventStore = yield* EventStoreService;
|
|
33682
|
-
const { closeOut } = yield* Effect.promise(() => import("./lifecycle-
|
|
33593
|
+
const { closeOut } = yield* Effect.promise(() => import("./lifecycle-Ck2UR27D.js"));
|
|
33683
33594
|
const issueDataService = getIssueDataService$5();
|
|
33684
33595
|
const tasks = [];
|
|
33685
33596
|
const agentChecks = yield* withConcurrencyLimit(issueIds.map((id) => Effect.promise(async () => {
|
|
@@ -33875,8 +33786,8 @@ const getIssueShipLogRoute = HttpRouter.add("GET", "/api/issues/:id/ship-log", h
|
|
|
33875
33786
|
const id = (yield* HttpRouter.params)["id"] ?? "";
|
|
33876
33787
|
if (!parseIssueIdSync(id)) return jsonResponse({ error: "Invalid issue ID" }, { status: 400 });
|
|
33877
33788
|
return yield* Effect.promise(async () => {
|
|
33878
|
-
const { getShipLog } = await import("./ship-log-
|
|
33879
|
-
const { getReviewStatusSync } = await import("./review-status-
|
|
33789
|
+
const { getShipLog } = await import("./ship-log-CwqPFfqx.js");
|
|
33790
|
+
const { getReviewStatusSync } = await import("./review-status-CG0iDuWa.js");
|
|
33880
33791
|
const log = getShipLog(id);
|
|
33881
33792
|
const rs = getReviewStatusSync(id);
|
|
33882
33793
|
return jsonResponse({
|
|
@@ -34832,7 +34743,7 @@ const cloisterRouteLayer = Layer.mergeAll(getCloisterStatusRoute, postCloisterSt
|
|
|
34832
34743
|
init_agents$1();
|
|
34833
34744
|
init_cost_sync();
|
|
34834
34745
|
init_tmux();
|
|
34835
|
-
const execFileAsync$
|
|
34746
|
+
const execFileAsync$11 = promisify(execFile);
|
|
34836
34747
|
const BURN_WINDOW_MS = 1800 * 1e3;
|
|
34837
34748
|
function buildAgentStatsSnapshot(options) {
|
|
34838
34749
|
const nowMs = options.nowMs ?? Date.now();
|
|
@@ -34905,7 +34816,7 @@ function getAgentStatsSnapshotEffect(deps = {}) {
|
|
|
34905
34816
|
});
|
|
34906
34817
|
});
|
|
34907
34818
|
}
|
|
34908
|
-
function parseProcessTable
|
|
34819
|
+
function parseProcessTable(psTable) {
|
|
34909
34820
|
return psTable.split("\n").map((line) => line.trim()).filter(Boolean).flatMap((line) => {
|
|
34910
34821
|
const match = line.match(/^(\d+)\s+(\d+)\s+([0-9.]+)\s+(\d+)$/);
|
|
34911
34822
|
if (!match) return [];
|
|
@@ -34918,8 +34829,8 @@ function parseProcessTable$1(psTable) {
|
|
|
34918
34829
|
});
|
|
34919
34830
|
}
|
|
34920
34831
|
async function readBatchedProcessTable() {
|
|
34921
|
-
const { stdout } = await execFileAsync$
|
|
34922
|
-
return parseProcessTable
|
|
34832
|
+
const { stdout } = await execFileAsync$11("ps", ["-eo", "pid=,ppid=,pcpu=,rss="], { encoding: "utf8" });
|
|
34833
|
+
return parseProcessTable(stdout);
|
|
34923
34834
|
}
|
|
34924
34835
|
function defaultListSessionNames() {
|
|
34925
34836
|
return listSessions().pipe(Effect.map((sessions) => sessions.map((session) => session.name)));
|
|
@@ -35845,11 +35756,11 @@ const postUnpauseContainerRoute = HttpRouter.add("POST", "/api/resources/docker/
|
|
|
35845
35756
|
//#endregion
|
|
35846
35757
|
//#region routes/resources/prune.ts
|
|
35847
35758
|
init_domain_services();
|
|
35848
|
-
const execFileAsync$
|
|
35759
|
+
const execFileAsync$9 = promisify(execFile);
|
|
35849
35760
|
const postPruneContainersRoute = HttpRouter.add("POST", "/api/resources/docker/prune-containers", httpHandler(Effect.gen(function* () {
|
|
35850
35761
|
const eventStore = yield* EventStoreService;
|
|
35851
35762
|
const { stdout } = yield* Effect.tryPromise({
|
|
35852
|
-
try: () => execFileAsync$
|
|
35763
|
+
try: () => execFileAsync$9("docker", [
|
|
35853
35764
|
"container",
|
|
35854
35765
|
"prune",
|
|
35855
35766
|
"-f"
|
|
@@ -35874,7 +35785,7 @@ const deleteDockerNetworkRoute = HttpRouter.add("DELETE", "/api/resources/docker
|
|
|
35874
35785
|
const eventStore = yield* EventStoreService;
|
|
35875
35786
|
if (!/^[a-zA-Z0-9][a-zA-Z0-9_.-]*$/.test(name)) return jsonResponse({ error: "Invalid network name" }, { status: 400 });
|
|
35876
35787
|
yield* Effect.tryPromise({
|
|
35877
|
-
try: () => execFileAsync$
|
|
35788
|
+
try: () => execFileAsync$9("docker", [
|
|
35878
35789
|
"network",
|
|
35879
35790
|
"rm",
|
|
35880
35791
|
name
|
|
@@ -35896,7 +35807,7 @@ const deleteDockerVolumeRoute = HttpRouter.add("DELETE", "/api/resources/docker/
|
|
|
35896
35807
|
const eventStore = yield* EventStoreService;
|
|
35897
35808
|
if (!/^[a-zA-Z0-9][a-zA-Z0-9_.-]*$/.test(name)) return jsonResponse({ error: "Invalid volume name" }, { status: 400 });
|
|
35898
35809
|
yield* Effect.tryPromise({
|
|
35899
|
-
try: () => execFileAsync$
|
|
35810
|
+
try: () => execFileAsync$9("docker", [
|
|
35900
35811
|
"volume",
|
|
35901
35812
|
"rm",
|
|
35902
35813
|
name
|
|
@@ -35916,7 +35827,7 @@ const deleteDockerVolumeRoute = HttpRouter.add("DELETE", "/api/resources/docker/
|
|
|
35916
35827
|
const postPruneVolumesRoute = HttpRouter.add("POST", "/api/resources/docker/prune-volumes", httpHandler(Effect.gen(function* () {
|
|
35917
35828
|
const eventStore = yield* EventStoreService;
|
|
35918
35829
|
const { stdout } = yield* Effect.tryPromise({
|
|
35919
|
-
try: () => execFileAsync$
|
|
35830
|
+
try: () => execFileAsync$9("docker", [
|
|
35920
35831
|
"volume",
|
|
35921
35832
|
"prune",
|
|
35922
35833
|
"-f"
|
|
@@ -36101,9 +36012,9 @@ function findStack$1(issueId) {
|
|
|
36101
36012
|
//#region routes/resources/teardown.ts
|
|
36102
36013
|
init_activity_logger();
|
|
36103
36014
|
init_domain_services();
|
|
36104
|
-
const execFileAsync$
|
|
36015
|
+
const execFileAsync$7 = promisify(execFile);
|
|
36105
36016
|
const CONFIRM_TOKEN_TTL_MS = 300 * 1e3;
|
|
36106
|
-
let dockerTeardownExec = execFileAsync$
|
|
36017
|
+
let dockerTeardownExec = execFileAsync$7;
|
|
36107
36018
|
let teardownTokenGenerator = () => `td-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;
|
|
36108
36019
|
let activityEmitter = emitActivityEntrySync;
|
|
36109
36020
|
const teardownTokens = /* @__PURE__ */ new Map();
|
|
@@ -37572,8 +37483,8 @@ init_linear_client();
|
|
|
37572
37483
|
init_config_yaml();
|
|
37573
37484
|
init_issue_service_singleton();
|
|
37574
37485
|
init_io();
|
|
37575
|
-
const execAsync$
|
|
37576
|
-
const execFileAsync$
|
|
37486
|
+
const execAsync$4 = promisify(exec);
|
|
37487
|
+
const execFileAsync$6 = promisify(execFile);
|
|
37577
37488
|
function getIssueDataService$3() {
|
|
37578
37489
|
return getSharedIssueService();
|
|
37579
37490
|
}
|
|
@@ -38115,7 +38026,7 @@ async function fetchPlanningData(issueId, options = {}) {
|
|
|
38115
38026
|
const cached = stashCountCache.get(cacheKey);
|
|
38116
38027
|
if (cached && cached.timestamp > Date.now() - STASH_COUNT_CACHE_TTL_MS) result.stashCount = cached.count;
|
|
38117
38028
|
else {
|
|
38118
|
-
const { stdout: stashList } = await execAsync$
|
|
38029
|
+
const { stdout: stashList } = await execAsync$4("git stash list", {
|
|
38119
38030
|
cwd: workspacePath,
|
|
38120
38031
|
encoding: "utf-8"
|
|
38121
38032
|
});
|
|
@@ -38203,7 +38114,7 @@ async function generateStatusReview(issueId) {
|
|
|
38203
38114
|
};
|
|
38204
38115
|
const execSafe = async (cmd, opts) => {
|
|
38205
38116
|
try {
|
|
38206
|
-
const { stdout } = await execAsync$
|
|
38117
|
+
const { stdout } = await execAsync$4(cmd, {
|
|
38207
38118
|
encoding: "utf-8",
|
|
38208
38119
|
timeout: 1e4,
|
|
38209
38120
|
...opts
|
|
@@ -38305,7 +38216,7 @@ Be specific: reference actual file names, function names, requirement text, disc
|
|
|
38305
38216
|
const { command: cliCmd, args: cliArgs } = getAgentCommandSync(statusModelId);
|
|
38306
38217
|
const modelFlag = cliArgs.length > 0 ? ` ${cliArgs.join(" ")}` : "";
|
|
38307
38218
|
const promptFile = join(planningDir, ".status-review-prompt.tmp");
|
|
38308
|
-
const { getProviderForModelSync, getProviderEnvSync } = await import("./providers-
|
|
38219
|
+
const { getProviderForModelSync, getProviderEnvSync } = await import("./providers-DnPxkHoG.js");
|
|
38309
38220
|
let providerEnvStr = "";
|
|
38310
38221
|
let providerEnv = {};
|
|
38311
38222
|
const statusProvider = getProviderForModelSync(statusModelId);
|
|
@@ -38322,7 +38233,7 @@ Be specific: reference actual file names, function names, requirement text, disc
|
|
|
38322
38233
|
try {
|
|
38323
38234
|
const env = buildChildEnvSync(process.env, providerEnv);
|
|
38324
38235
|
const promptContent = await readFile(promptFile, "utf-8");
|
|
38325
|
-
const { stdout: aiReview } = await execAsync$
|
|
38236
|
+
const { stdout: aiReview } = await execAsync$4(`${cliCmd} -p${modelFlag} --no-session-persistence`, {
|
|
38326
38237
|
encoding: "utf-8",
|
|
38327
38238
|
timeout: 12e4,
|
|
38328
38239
|
maxBuffer: 1024 * 1024,
|
|
@@ -38388,7 +38299,7 @@ const postMissionControlUploadRoute = HttpRouter.add("POST", "/api/command-deck/
|
|
|
38388
38299
|
let safeName = filename.replace(/[^a-zA-Z0-9._-]/g, "-");
|
|
38389
38300
|
let processedContent = content;
|
|
38390
38301
|
if (safeName.endsWith(".vtt")) {
|
|
38391
|
-
const { vttToMarkdown } = yield* Effect.promise(() => import("./vtt-parser-
|
|
38302
|
+
const { vttToMarkdown } = yield* Effect.promise(() => import("./vtt-parser-C_XPlifj.js"));
|
|
38392
38303
|
processedContent = vttToMarkdown(content);
|
|
38393
38304
|
safeName = safeName.replace(/\.vtt$/, ".md");
|
|
38394
38305
|
}
|
|
@@ -38430,7 +38341,7 @@ const postMissionControlSyncDiscussionsRoute = HttpRouter.add("POST", "/api/comm
|
|
|
38430
38341
|
if (!ghConfig) return jsonResponse({ error: "GitHub not configured" }, { status: 400 });
|
|
38431
38342
|
yield* Effect.promise(async () => {
|
|
38432
38343
|
try {
|
|
38433
|
-
const { stdout } = await execFileAsync$
|
|
38344
|
+
const { stdout } = await execFileAsync$6("gh", [
|
|
38434
38345
|
"issue",
|
|
38435
38346
|
"view",
|
|
38436
38347
|
issueId.replace(/^[A-Z]+-/, ""),
|
|
@@ -38453,7 +38364,7 @@ const postMissionControlSyncDiscussionsRoute = HttpRouter.add("POST", "/api/comm
|
|
|
38453
38364
|
console.warn(`Failed to sync GitHub comments for ${issueId}:`, err);
|
|
38454
38365
|
}
|
|
38455
38366
|
try {
|
|
38456
|
-
const { stdout: prList } = await execFileAsync$
|
|
38367
|
+
const { stdout: prList } = await execFileAsync$6("gh", [
|
|
38457
38368
|
"pr",
|
|
38458
38369
|
"list",
|
|
38459
38370
|
"--repo",
|
|
@@ -38469,7 +38380,7 @@ const postMissionControlSyncDiscussionsRoute = HttpRouter.add("POST", "/api/comm
|
|
|
38469
38380
|
timeout: 15e3
|
|
38470
38381
|
});
|
|
38471
38382
|
for (const prNum of prList.trim().split("\n").filter(Boolean)) try {
|
|
38472
|
-
const { stdout: prComments } = await execFileAsync$
|
|
38383
|
+
const { stdout: prComments } = await execFileAsync$6("gh", [
|
|
38473
38384
|
"pr",
|
|
38474
38385
|
"view",
|
|
38475
38386
|
prNum,
|
|
@@ -38600,7 +38511,6 @@ async function fetchProjectTree() {
|
|
|
38600
38511
|
const commandDeckRouteLayer = Layer.mergeAll(getMissionControlActivityRoute, getMissionControlPlanningRoute, postMissionControlStatusReviewRoute, postMissionControlUploadRoute, postMissionControlSyncDiscussionsRoute, postMissionControlPlanningInitRoute, getMissionControlProjectsRoute);
|
|
38601
38512
|
//#endregion
|
|
38602
38513
|
//#region routes/remote.ts
|
|
38603
|
-
init_harness_resolve();
|
|
38604
38514
|
/**
|
|
38605
38515
|
* Remote route module — Effect HttpRouter.Layer (PAN-428 B14)
|
|
38606
38516
|
*
|
|
@@ -38933,7 +38843,7 @@ async function refreshTtsRuntimeConfig() {
|
|
|
38933
38843
|
init_paths();
|
|
38934
38844
|
init_config_yaml();
|
|
38935
38845
|
init_errors();
|
|
38936
|
-
const execFileAsync$
|
|
38846
|
+
const execFileAsync$5 = promisify(execFile);
|
|
38937
38847
|
const QWEN_TTS_PID_PATH = join(OVERDECK_HOME, "pids", "qwen-tts.pid");
|
|
38938
38848
|
const QWEN_TTS_STATE_PATH = join(OVERDECK_HOME, "pids", "qwen-tts.json");
|
|
38939
38849
|
const QWEN_TTS_START_LOCK_PATH = join(OVERDECK_HOME, "pids", "qwen-tts.start.lock");
|
|
@@ -39120,7 +39030,7 @@ function isWithinStartupGrace(state, now = Date.now()) {
|
|
|
39120
39030
|
const deadline = Date.parse(state.startupDeadlineAt);
|
|
39121
39031
|
return Number.isFinite(deadline) && now < deadline;
|
|
39122
39032
|
}
|
|
39123
|
-
function isProcessAlive$
|
|
39033
|
+
function isProcessAlive$1(pid) {
|
|
39124
39034
|
try {
|
|
39125
39035
|
process.kill(pid, 0);
|
|
39126
39036
|
return true;
|
|
@@ -39150,7 +39060,7 @@ async function buildManagedProcessIdentity(pid, scriptPath) {
|
|
|
39150
39060
|
};
|
|
39151
39061
|
}
|
|
39152
39062
|
async function isManagedProcessAlive(state) {
|
|
39153
|
-
if (!state || !isProcessAlive$
|
|
39063
|
+
if (!state || !isProcessAlive$1(state.pid)) return false;
|
|
39154
39064
|
if (!state.scriptPath || !state.processStartTimeTicks) return false;
|
|
39155
39065
|
const identity = await readProcessIdentity(state.pid);
|
|
39156
39066
|
return identity !== null && identity.startTimeTicks === state.processStartTimeTicks && identity.cmdline.includes(state.scriptPath);
|
|
@@ -39172,7 +39082,7 @@ async function terminateManagedProcess(state, timeoutMs) {
|
|
|
39172
39082
|
}
|
|
39173
39083
|
async function sampleGpuMemoryUsedMb(pid) {
|
|
39174
39084
|
try {
|
|
39175
|
-
const { stdout } = await execFileAsync$
|
|
39085
|
+
const { stdout } = await execFileAsync$5("nvidia-smi", ["--query-compute-apps=pid,used_memory", "--format=csv,noheader,nounits"], { timeout: 2e3 });
|
|
39176
39086
|
for (const line of stdout.split("\n")) {
|
|
39177
39087
|
const [rawPid, rawMemory] = line.split(",").map((part) => part?.trim());
|
|
39178
39088
|
if (Number.parseInt(rawPid ?? "", 10) === pid) {
|
|
@@ -43630,14 +43540,14 @@ const postOpenRouterTestKeyRoute = HttpRouter.add("POST", "/api/settings/openrou
|
|
|
43630
43540
|
if (!apiKey) return jsonResponse({ error: "apiKey is required" }, { status: 400 });
|
|
43631
43541
|
return jsonResponse(yield* (yield* OpenRouterService).validateApiKey(apiKey));
|
|
43632
43542
|
})));
|
|
43633
|
-
const SAFE_MODEL_PATTERN$
|
|
43543
|
+
const SAFE_MODEL_PATTERN$1 = /^[a-zA-Z0-9_.:\/-]+$/;
|
|
43634
43544
|
const MAX_HARNESS_POLICY_MODELS = 250;
|
|
43635
43545
|
const MAX_HARNESS_POLICY_MODEL_LENGTH = 200;
|
|
43636
43546
|
const getHarnessPolicyRoute = HttpRouter.add("GET", "/api/settings/harness-policy", httpHandler(Effect.gen(function* () {
|
|
43637
43547
|
const request = yield* HttpServerRequest.HttpServerRequest;
|
|
43638
43548
|
return yield* Effect.promise(async () => {
|
|
43639
43549
|
const models = (new URL(request.url, "http://localhost").searchParams.get("models") ?? "").split(",").map((model) => model.trim()).filter(Boolean);
|
|
43640
|
-
if (models.length === 0 || models.length > MAX_HARNESS_POLICY_MODELS || models.some((model) => model.length > MAX_HARNESS_POLICY_MODEL_LENGTH || !SAFE_MODEL_PATTERN$
|
|
43550
|
+
if (models.length === 0 || models.length > MAX_HARNESS_POLICY_MODELS || models.some((model) => model.length > MAX_HARNESS_POLICY_MODEL_LENGTH || !SAFE_MODEL_PATTERN$1.test(model))) return jsonResponse({ error: "Valid models parameter is required" }, { status: 400 });
|
|
43641
43551
|
return jsonResponse({ decisions: await buildHarnessPolicyDecisions(models, getProviderAuthMode) });
|
|
43642
43552
|
});
|
|
43643
43553
|
})));
|
|
@@ -43645,7 +43555,7 @@ const getProviderEnvConflictsRoute = HttpRouter.add("GET", "/api/settings/provid
|
|
|
43645
43555
|
const request = yield* HttpServerRequest.HttpServerRequest;
|
|
43646
43556
|
return yield* Effect.promise(async () => {
|
|
43647
43557
|
const model = new URL(request.url, "http://localhost").searchParams.get("model");
|
|
43648
|
-
if (!model || !SAFE_MODEL_PATTERN$
|
|
43558
|
+
if (!model || !SAFE_MODEL_PATTERN$1.test(model)) return jsonResponse({ error: "Valid model parameter is required" }, { status: 400 });
|
|
43649
43559
|
try {
|
|
43650
43560
|
const providerEnv = await getProviderEnvForModel(model);
|
|
43651
43561
|
return jsonResponse({ conflicts: await Effect.runPromise(detectProviderEnvConflicts(providerEnv)) });
|
|
@@ -44216,7 +44126,7 @@ const postRallyValidateRoute = HttpRouter.add("POST", "/api/rally/validate", Eff
|
|
|
44216
44126
|
}, { status: 400 });
|
|
44217
44127
|
return yield* Effect.promise(async () => {
|
|
44218
44128
|
try {
|
|
44219
|
-
const { RallyRestApi } = await import("./rally-api-
|
|
44129
|
+
const { RallyRestApi } = await import("./rally-api-B-YA_oXx.js");
|
|
44220
44130
|
const api = new RallyRestApi({
|
|
44221
44131
|
apiKey,
|
|
44222
44132
|
server: server || "https://rally1.rallydev.com"
|
|
@@ -44544,7 +44454,7 @@ const getPlanningStatusRoute = HttpRouter.add("GET", "/api/planning/:issueId/sta
|
|
|
44544
44454
|
const remoteState = loadRemoteAgentState(sessionName);
|
|
44545
44455
|
const isRemote = !!remoteState;
|
|
44546
44456
|
const vmName = remoteState?.vmName ?? "";
|
|
44547
|
-
const { getAgentStateSync } = await import("./agents-
|
|
44457
|
+
const { getAgentStateSync } = await import("./agents-CEcaxSkR.js");
|
|
44548
44458
|
const agentStarting = getAgentStateSync(sessionName)?.status === "starting";
|
|
44549
44459
|
let tmuxSessionAlive = false;
|
|
44550
44460
|
if (!isRemote) try {
|
|
@@ -44583,12 +44493,12 @@ async function claudePlanningSystemPromptFiles(workspacePath) {
|
|
|
44583
44493
|
await stat$1(contextFile);
|
|
44584
44494
|
files.push(contextFile);
|
|
44585
44495
|
} catch (error) {
|
|
44586
|
-
if (!isNotFound
|
|
44496
|
+
if (!isNotFound(error)) throw error;
|
|
44587
44497
|
}
|
|
44588
44498
|
files.push(await ensureSessionContextBriefingFile());
|
|
44589
44499
|
return files;
|
|
44590
44500
|
}
|
|
44591
|
-
function isNotFound
|
|
44501
|
+
function isNotFound(error) {
|
|
44592
44502
|
return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
|
|
44593
44503
|
}
|
|
44594
44504
|
const postPlanningMessageRoute = HttpRouter.add("POST", "/api/planning/:issueId/message", Effect.gen(function* () {
|
|
@@ -44687,7 +44597,7 @@ Continue the PLANNING session. Do NOT implement anything.
|
|
|
44687
44597
|
`);
|
|
44688
44598
|
const agentCwd = workspacePath;
|
|
44689
44599
|
if (existsSync$1(outputFile)) await rename(outputFile, join(planningDir, `output-${Date.now()}.jsonl`));
|
|
44690
|
-
const { getAgentCommandSync } = await import("./settings-
|
|
44600
|
+
const { getAgentCommandSync } = await import("./settings-Cy7SCFO9.js");
|
|
44691
44601
|
let msgPlanningModel = "claude-sonnet-5";
|
|
44692
44602
|
try {
|
|
44693
44603
|
msgPlanningModel = resolveModel("plan", void 0, loadConfigSync().config);
|
|
@@ -44808,7 +44718,7 @@ async function getIndexStats(rootPath, isMain) {
|
|
|
44808
44718
|
}
|
|
44809
44719
|
const getTldrStatusRoute = HttpRouter.add("GET", "/api/services/tldr/status", Effect.promise(async () => {
|
|
44810
44720
|
try {
|
|
44811
|
-
const { getTldrDaemonServiceSync } = await import("./tldr-daemon-
|
|
44721
|
+
const { getTldrDaemonServiceSync } = await import("./tldr-daemon-CgZQ3jmZ.js");
|
|
44812
44722
|
const projectRoot = process.cwd();
|
|
44813
44723
|
const venvPath = join(projectRoot, ".venv");
|
|
44814
44724
|
const results = [];
|
|
@@ -44853,7 +44763,7 @@ const getTldrStatusRoute = HttpRouter.add("GET", "/api/services/tldr/status", Ef
|
|
|
44853
44763
|
}));
|
|
44854
44764
|
const postTldrStartRoute = HttpRouter.add("POST", "/api/services/tldr/start", Effect.promise(async () => {
|
|
44855
44765
|
try {
|
|
44856
|
-
const { getTldrDaemonServiceSync } = await import("./tldr-daemon-
|
|
44766
|
+
const { getTldrDaemonServiceSync } = await import("./tldr-daemon-CgZQ3jmZ.js");
|
|
44857
44767
|
const projectRoot = process.cwd();
|
|
44858
44768
|
const venvPath = join(projectRoot, ".venv");
|
|
44859
44769
|
if (!existsSync$1(venvPath)) return jsonResponse({ error: "No .venv found in project root" }, { status: 404 });
|
|
@@ -44870,7 +44780,7 @@ const postTldrStartRoute = HttpRouter.add("POST", "/api/services/tldr/start", Ef
|
|
|
44870
44780
|
}));
|
|
44871
44781
|
const postTldrStopRoute = HttpRouter.add("POST", "/api/services/tldr/stop", Effect.promise(async () => {
|
|
44872
44782
|
try {
|
|
44873
|
-
const { getTldrDaemonServiceSync } = await import("./tldr-daemon-
|
|
44783
|
+
const { getTldrDaemonServiceSync } = await import("./tldr-daemon-CgZQ3jmZ.js");
|
|
44874
44784
|
const projectRoot = process.cwd();
|
|
44875
44785
|
const venvPath = join(projectRoot, ".venv");
|
|
44876
44786
|
if (!existsSync$1(venvPath)) return jsonResponse({ error: "No .venv found in project root" }, { status: 404 });
|
|
@@ -44887,7 +44797,7 @@ const postTldrStopRoute = HttpRouter.add("POST", "/api/services/tldr/stop", Effe
|
|
|
44887
44797
|
}));
|
|
44888
44798
|
const postTldrReloadRoute = HttpRouter.add("POST", "/api/services/tldr/reload", Effect.promise(async () => {
|
|
44889
44799
|
try {
|
|
44890
|
-
const { getTldrDaemonServiceSync } = await import("./tldr-daemon-
|
|
44800
|
+
const { getTldrDaemonServiceSync } = await import("./tldr-daemon-CgZQ3jmZ.js");
|
|
44891
44801
|
const enabled = isTldrEnabledSync();
|
|
44892
44802
|
const projectRoot = process.cwd();
|
|
44893
44803
|
const targets = [];
|
|
@@ -44934,12 +44844,123 @@ const postTldrReloadRoute = HttpRouter.add("POST", "/api/services/tldr/reload",
|
|
|
44934
44844
|
}));
|
|
44935
44845
|
const tldrRouteLayer = Layer.mergeAll(getTldrStatusRoute, postTldrStartRoute, postTldrStopRoute, postTldrReloadRoute);
|
|
44936
44846
|
//#endregion
|
|
44847
|
+
//#region ../../lib/sync-startup-gate.ts
|
|
44848
|
+
var sync_startup_gate_exports = /* @__PURE__ */ __exportAll({
|
|
44849
|
+
isStartupSyncNeededSync: () => isStartupSyncNeededSync,
|
|
44850
|
+
writeSyncManifestSync: () => writeSyncManifestSync
|
|
44851
|
+
});
|
|
44852
|
+
/**
|
|
44853
|
+
* Compute a deterministic hash of every input that can change the output of
|
|
44854
|
+
* `pan sync`. Missing a sync input is treated as an error by the caller so
|
|
44855
|
+
* that the conservative fallback is always a full sync.
|
|
44856
|
+
*/
|
|
44857
|
+
function computeSyncInputHash() {
|
|
44858
|
+
const hash = createHash("sha256");
|
|
44859
|
+
hash.update(String(isDevMode()));
|
|
44860
|
+
hash.update(process.cwd());
|
|
44861
|
+
const cwdSkillsRoot = resolveTopLevelSkillsRoot(process.cwd());
|
|
44862
|
+
if (cwdSkillsRoot) updateHashFromDirectory(hash, join$1(cwdSkillsRoot, "skills"));
|
|
44863
|
+
for (const [key, dir] of Object.entries(SYNC_SOURCES)) {
|
|
44864
|
+
if (!existsSync(dir)) throw new Error(`missing sync input: ${key} at ${dir}`);
|
|
44865
|
+
updateHashFromDirectory(hash, dir);
|
|
44866
|
+
}
|
|
44867
|
+
const globalMd = join$1(OVERDECK_HOME, "context", "global.md");
|
|
44868
|
+
if (!existsSync(globalMd)) throw new Error("missing global context layer");
|
|
44869
|
+
updateHashFromFile(hash, globalMd);
|
|
44870
|
+
for (const { config } of listProjectsSync()) {
|
|
44871
|
+
const projectMd = resolveProjectContextFile(config.path);
|
|
44872
|
+
if (existsSync(projectMd)) updateHashFromFile(hash, projectMd);
|
|
44873
|
+
const projectSkills = join$1(config.path, ".pan", "skills");
|
|
44874
|
+
if (existsSync(projectSkills)) updateHashFromDirectory(hash, projectSkills);
|
|
44875
|
+
}
|
|
44876
|
+
return hash.digest("hex");
|
|
44877
|
+
}
|
|
44878
|
+
function resolveTopLevelSkillsRoot(startDir) {
|
|
44879
|
+
let dir = startDir;
|
|
44880
|
+
while (true) {
|
|
44881
|
+
if (containsSkillDefinitions(join$1(dir, "skills"))) return dir;
|
|
44882
|
+
const parent = dirname$1(dir);
|
|
44883
|
+
if (parent === dir) return null;
|
|
44884
|
+
dir = parent;
|
|
44885
|
+
}
|
|
44886
|
+
}
|
|
44887
|
+
function containsSkillDefinitions(dir) {
|
|
44888
|
+
if (!existsSync(dir)) return false;
|
|
44889
|
+
try {
|
|
44890
|
+
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
44891
|
+
if (!entry.isDirectory()) continue;
|
|
44892
|
+
if (existsSync(join$1(dir, entry.name, "SKILL.md")) || existsSync(join$1(dir, entry.name, "skill.md"))) return true;
|
|
44893
|
+
}
|
|
44894
|
+
} catch {
|
|
44895
|
+
return false;
|
|
44896
|
+
}
|
|
44897
|
+
return false;
|
|
44898
|
+
}
|
|
44899
|
+
function updateHashFromDirectory(hash, dir) {
|
|
44900
|
+
const entries = readdirSync(dir, { withFileTypes: true });
|
|
44901
|
+
entries.sort((a, b) => a.name.localeCompare(b.name));
|
|
44902
|
+
for (const entry of entries) {
|
|
44903
|
+
const entryPath = join$1(dir, entry.name);
|
|
44904
|
+
if (entry.isDirectory()) updateHashFromDirectory(hash, entryPath);
|
|
44905
|
+
else if (entry.isFile()) updateHashFromFile(hash, entryPath);
|
|
44906
|
+
}
|
|
44907
|
+
}
|
|
44908
|
+
function updateHashFromFile(hash, filePath) {
|
|
44909
|
+
hash.update(filePath);
|
|
44910
|
+
hash.update(readFileSync(filePath));
|
|
44911
|
+
}
|
|
44912
|
+
/**
|
|
44913
|
+
* Decide whether the startup sync has work to do. Returns `{ needed: false }`
|
|
44914
|
+
* only when the persisted manifest at ~/.overdeck/.sync-manifest.json matches
|
|
44915
|
+
* the current input hash. Any uncertainty (missing input, unreadable manifest,
|
|
44916
|
+
* hash computation error) falls back to `{ needed: true }`.
|
|
44917
|
+
*/
|
|
44918
|
+
function isStartupSyncNeededSync() {
|
|
44919
|
+
const manifestPath = join$1(OVERDECK_HOME, ".sync-manifest.json");
|
|
44920
|
+
try {
|
|
44921
|
+
const currentHash = computeSyncInputHash();
|
|
44922
|
+
if (existsSync(manifestPath)) {
|
|
44923
|
+
if (JSON.parse(readFileSync(manifestPath, "utf-8")).hash === currentHash) return {
|
|
44924
|
+
needed: false,
|
|
44925
|
+
reason: "inputs unchanged"
|
|
44926
|
+
};
|
|
44927
|
+
}
|
|
44928
|
+
return {
|
|
44929
|
+
needed: true,
|
|
44930
|
+
reason: "inputs changed or no manifest"
|
|
44931
|
+
};
|
|
44932
|
+
} catch (err) {
|
|
44933
|
+
return {
|
|
44934
|
+
needed: true,
|
|
44935
|
+
reason: `hash computation failed: ${err instanceof Error ? err.message : String(err)}`
|
|
44936
|
+
};
|
|
44937
|
+
}
|
|
44938
|
+
}
|
|
44939
|
+
/**
|
|
44940
|
+
* Write the current sync input hash to ~/.overdeck/.sync-manifest.json.
|
|
44941
|
+
* Call after a full sync so the next startup skip gate can succeed.
|
|
44942
|
+
*/
|
|
44943
|
+
function writeSyncManifestSync() {
|
|
44944
|
+
const manifestPath = join$1(OVERDECK_HOME, ".sync-manifest.json");
|
|
44945
|
+
const hash = computeSyncInputHash();
|
|
44946
|
+
writeFileSync(manifestPath, JSON.stringify({
|
|
44947
|
+
hash,
|
|
44948
|
+
generatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
44949
|
+
}, null, 2) + "\n", "utf-8");
|
|
44950
|
+
}
|
|
44951
|
+
var init_sync_startup_gate = __esmMin((() => {
|
|
44952
|
+
init_paths();
|
|
44953
|
+
init_projects();
|
|
44954
|
+
init_layers();
|
|
44955
|
+
}));
|
|
44956
|
+
//#endregion
|
|
44937
44957
|
//#region routes/misc/meta.ts
|
|
44938
44958
|
init_tracker_config();
|
|
44939
44959
|
init_issue_id();
|
|
44940
44960
|
init_projects();
|
|
44941
44961
|
init_tmux();
|
|
44942
|
-
const execAsync$
|
|
44962
|
+
const execAsync$3 = promisify(exec);
|
|
44963
|
+
const execFileAsync$4 = promisify(execFile);
|
|
44943
44964
|
function getIssueDataService$1() {
|
|
44944
44965
|
const { getSharedIssueService } = (init_issue_service_singleton(), __toCommonJS(issue_service_singleton_exports));
|
|
44945
44966
|
return getSharedIssueService();
|
|
@@ -44963,7 +44984,7 @@ const getVersionRoute = HttpRouter.add("GET", "/api/version", Effect.promise(asy
|
|
|
44963
44984
|
const version = await getOverdeckVersion();
|
|
44964
44985
|
let supervisorUrl = null;
|
|
44965
44986
|
try {
|
|
44966
|
-
const { getSupervisorUrlSync } = await import("./supervisor-
|
|
44987
|
+
const { getSupervisorUrlSync } = await import("./supervisor-CfX192ma.js");
|
|
44967
44988
|
supervisorUrl = getSupervisorUrlSync();
|
|
44968
44989
|
} catch {}
|
|
44969
44990
|
return jsonResponse({
|
|
@@ -44973,9 +44994,30 @@ const getVersionRoute = HttpRouter.add("GET", "/api/version", Effect.promise(asy
|
|
|
44973
44994
|
});
|
|
44974
44995
|
}));
|
|
44975
44996
|
const getPrerequisitesRoute = HttpRouter.add("GET", "/api/prerequisites", Effect.promise(async () => {
|
|
44976
|
-
const { checkSystemPrerequisites } = await import("./system-prerequisites-
|
|
44997
|
+
const { checkSystemPrerequisites } = await import("./system-prerequisites-DZZTi2G6.js");
|
|
44977
44998
|
return jsonResponse(await checkSystemPrerequisites());
|
|
44978
44999
|
}));
|
|
45000
|
+
const getSyncStatusRoute = HttpRouter.add("GET", "/api/sync-status", Effect.sync(() => {
|
|
45001
|
+
const { isStartupSyncNeededSync } = (init_sync_startup_gate(), __toCommonJS(sync_startup_gate_exports));
|
|
45002
|
+
return jsonResponse(isStartupSyncNeededSync());
|
|
45003
|
+
}));
|
|
45004
|
+
const postRunSyncRoute = HttpRouter.add("POST", "/api/system/sync", Effect.promise(async () => {
|
|
45005
|
+
try {
|
|
45006
|
+
const { stdout, stderr } = await execFileAsync$4("pan", ["sync"], {
|
|
45007
|
+
encoding: "utf-8",
|
|
45008
|
+
timeout: 18e4
|
|
45009
|
+
});
|
|
45010
|
+
return jsonResponse({
|
|
45011
|
+
ok: true,
|
|
45012
|
+
output: `${stdout}${stderr}`.trim()
|
|
45013
|
+
});
|
|
45014
|
+
} catch (error) {
|
|
45015
|
+
return jsonResponse({
|
|
45016
|
+
ok: false,
|
|
45017
|
+
error: `pan sync failed: ${String(error?.stderr || error?.message || error)}`
|
|
45018
|
+
}, { status: 500 });
|
|
45019
|
+
}
|
|
45020
|
+
}));
|
|
44979
45021
|
const getRegisteredProjectsRoute = HttpRouter.add("GET", "/api/registered-projects", Effect.try({
|
|
44980
45022
|
try: () => {
|
|
44981
45023
|
return jsonResponse(listProjectsSync().map((p) => ({
|
|
@@ -45131,7 +45173,7 @@ const postShadowMonitorRoute = HttpRouter.add("POST", "/api/shadow/:issueId/moni
|
|
|
45131
45173
|
const projectPath = await getProjectPath(issuePrefix);
|
|
45132
45174
|
const workspacePath = join(projectPath, "workspaces", `feature-${issueLower}`);
|
|
45133
45175
|
if (!existsSync$1(workspacePath)) return jsonResponse({ error: "Workspace not found" }, { status: 404 });
|
|
45134
|
-
const { gatherArtifacts, generateBasicInference, updateInferenceDocumentSync } = await import("./shadow-engineering-
|
|
45176
|
+
const { gatherArtifacts, generateBasicInference, updateInferenceDocumentSync } = await import("./shadow-engineering-bKuKTCn-.js");
|
|
45135
45177
|
const config = {
|
|
45136
45178
|
issueId,
|
|
45137
45179
|
workspacePath,
|
|
@@ -45161,7 +45203,7 @@ const postShadowObserveRoute = HttpRouter.add("POST", "/api/shadow/:issueId/obse
|
|
|
45161
45203
|
if (!existsSync$1(workspacePath)) return jsonResponse({ error: "Workspace not found" }, { status: 404 });
|
|
45162
45204
|
const ghConfig = getGitHubConfig();
|
|
45163
45205
|
if (!ghConfig) return jsonResponse({ error: "GitHub not configured - Observer requires GitHub" }, { status: 400 });
|
|
45164
|
-
const { runObserverCycle } = await import("./shadow-engineering-
|
|
45206
|
+
const { runObserverCycle } = await import("./shadow-engineering-bKuKTCn-.js");
|
|
45165
45207
|
const firstRepo = ghConfig.repos[0];
|
|
45166
45208
|
const config = {
|
|
45167
45209
|
issueId,
|
|
@@ -45193,7 +45235,7 @@ const postDevRebuildRoute = HttpRouter.add("POST", "/api/dev/rebuild", Effect.ge
|
|
|
45193
45235
|
if (!overdeckDevMode || !overdeckProjectRoot) return jsonResponse({ error: "Rebuild only available in dev mode" }, { status: 403 });
|
|
45194
45236
|
return yield* Effect.promise(async () => {
|
|
45195
45237
|
try {
|
|
45196
|
-
const { stdout, stderr } = await execAsync$
|
|
45238
|
+
const { stdout, stderr } = await execAsync$3("npm run build", {
|
|
45197
45239
|
cwd: overdeckProjectRoot,
|
|
45198
45240
|
timeout: 12e4
|
|
45199
45241
|
});
|
|
@@ -45225,7 +45267,7 @@ const postRestartDashboardRoute = HttpRouter.add("POST", "/api/system/restart-da
|
|
|
45225
45267
|
return jsonResponse({ error: "Restart failed: " + (error instanceof Error ? error.message : String(error)) }, { status: 500 });
|
|
45226
45268
|
}
|
|
45227
45269
|
}));
|
|
45228
|
-
const metaRouteLayer = Layer.mergeAll(getVersionRoute, getPrerequisitesRoute, getRegisteredProjectsRoute, getConfirmationsRoute, postConfirmationRespondRoute, getSkillsRoute, getCacheStatusRoute, clearCacheRoute, getMetricsRuntimesRoute, getMetricsTasksRoute, postShadowMonitorRoute, postShadowObserveRoute, postDevRebuildRoute, postRestartDashboardRoute);
|
|
45270
|
+
const metaRouteLayer = Layer.mergeAll(getVersionRoute, getPrerequisitesRoute, getSyncStatusRoute, postRunSyncRoute, getRegisteredProjectsRoute, getConfirmationsRoute, postConfirmationRespondRoute, getSkillsRoute, getCacheStatusRoute, clearCacheRoute, getMetricsRuntimesRoute, getMetricsTasksRoute, postShadowMonitorRoute, postShadowObserveRoute, postDevRebuildRoute, postRestartDashboardRoute);
|
|
45229
45271
|
//#endregion
|
|
45230
45272
|
//#region routes/misc.ts
|
|
45231
45273
|
/**
|
|
@@ -46020,1401 +46062,6 @@ const getPaletteSearchRoute = HttpRouter.add("GET", "/api/palette/search", Effec
|
|
|
46020
46062
|
}));
|
|
46021
46063
|
const paletteRouteLayer = Layer.mergeAll(getPaletteCommandsRoute, getPaletteSearchRoute);
|
|
46022
46064
|
//#endregion
|
|
46023
|
-
//#region ../../lib/ohmypi-codex-auth.ts
|
|
46024
|
-
/**
|
|
46025
|
-
* oh-my-pi (omp) OAuth helpers for the openai-codex (ChatGPT subscription) provider.
|
|
46026
|
-
* Forked from pi-codex-auth.ts (PAN-1520) for the omp migration (PAN-1989).
|
|
46027
|
-
*
|
|
46028
|
-
* omp stores its general credentials in ~/.omp/agent/agent.db (SQLite). The
|
|
46029
|
-
* openai-codex OAuth credential is persisted separately at ~/.omp/agent/auth.json
|
|
46030
|
-
* (same JSON format as Pi's ~/.pi/agent/auth.json) so that this helper's
|
|
46031
|
-
* read/write logic is unchanged from the Pi side.
|
|
46032
|
-
*
|
|
46033
|
-
* This module:
|
|
46034
|
-
* - reads/writes the openai-codex credential under ~/.omp/agent/auth.json,
|
|
46035
|
-
* - reports auth status (for `pan doctor` and the conversation spawn gate),
|
|
46036
|
-
* - refreshes an expired-but-recoverable token, and
|
|
46037
|
-
* - drives omp's headless device-code login to re-authenticate.
|
|
46038
|
-
*
|
|
46039
|
-
* The OAuth module is loaded from the installed `omp` package dynamically.
|
|
46040
|
-
* A missing or relocated omp OAuth module degrades to 'unavailable' — never throws.
|
|
46041
|
-
*/
|
|
46042
|
-
const PI_CODEX_PROVIDER = "openai-codex";
|
|
46043
|
-
function getOhmypiAuthPath() {
|
|
46044
|
-
return join(homedir$1(), ".omp", "agent", "auth.json");
|
|
46045
|
-
}
|
|
46046
|
-
function readAuthFile() {
|
|
46047
|
-
const path = getOhmypiAuthPath();
|
|
46048
|
-
if (!existsSync$1(path)) return {};
|
|
46049
|
-
try {
|
|
46050
|
-
const parsed = JSON.parse(readFileSync$1(path, "utf-8"));
|
|
46051
|
-
return parsed && typeof parsed === "object" ? parsed : {};
|
|
46052
|
-
} catch {
|
|
46053
|
-
return {};
|
|
46054
|
-
}
|
|
46055
|
-
}
|
|
46056
|
-
function readOhmypiCodexCredential() {
|
|
46057
|
-
const cred = readAuthFile()[PI_CODEX_PROVIDER];
|
|
46058
|
-
if (cred && typeof cred === "object" && typeof cred["access"] === "string" && typeof cred["refresh"] === "string") return cred;
|
|
46059
|
-
return null;
|
|
46060
|
-
}
|
|
46061
|
-
/** Atomically merge a fresh codex credential into auth.json (mode 0600). */
|
|
46062
|
-
function writeOhmypiCodexCredential(tokens) {
|
|
46063
|
-
const path = getOhmypiAuthPath();
|
|
46064
|
-
mkdirSync$1(dirname(path), { recursive: true });
|
|
46065
|
-
const auth = readAuthFile();
|
|
46066
|
-
const stored = {
|
|
46067
|
-
type: "oauth",
|
|
46068
|
-
access: tokens.access,
|
|
46069
|
-
refresh: tokens.refresh,
|
|
46070
|
-
expires: tokens.expires,
|
|
46071
|
-
accountId: tokens.accountId
|
|
46072
|
-
};
|
|
46073
|
-
auth[PI_CODEX_PROVIDER] = stored;
|
|
46074
|
-
const tmp = `${path}.tmp-${process.pid}`;
|
|
46075
|
-
writeFileSync$1(tmp, JSON.stringify(auth, null, 2), { mode: 384 });
|
|
46076
|
-
renameSync$1(tmp, path);
|
|
46077
|
-
return stored;
|
|
46078
|
-
}
|
|
46079
|
-
/** Locate the `omp` executable on PATH (no subprocess — event-loop safe). */
|
|
46080
|
-
function findOmpBinary() {
|
|
46081
|
-
for (const dir of (process.env["PATH"] ?? "").split(delimiter)) {
|
|
46082
|
-
if (!dir) continue;
|
|
46083
|
-
const candidate = join(dir, "omp");
|
|
46084
|
-
if (existsSync$1(candidate)) return candidate;
|
|
46085
|
-
}
|
|
46086
|
-
return null;
|
|
46087
|
-
}
|
|
46088
|
-
/** omp is @oh-my-pi/pi-coding-agent; the oauth submodule path mirrors pi-ai's layout. */
|
|
46089
|
-
const OMP_AI_OAUTH_SUBPATH = join("@oh-my-pi", "pi-ai", "dist", "utils", "oauth", "openai-codex.js");
|
|
46090
|
-
/**
|
|
46091
|
-
* Resolve omp's openai-codex OAuth submodule by walking node_modules upward
|
|
46092
|
-
* from the real omp binary. Returns null when not found — the caller degrades
|
|
46093
|
-
* gracefully to 'unavailable' status.
|
|
46094
|
-
*/
|
|
46095
|
-
function resolveOmpCodexOAuthFile(ompBin) {
|
|
46096
|
-
let dir = dirname(realpathSync$1(ompBin));
|
|
46097
|
-
for (let i = 0; i < 10; i++) {
|
|
46098
|
-
const candidate = join(dir, "node_modules", OMP_AI_OAUTH_SUBPATH);
|
|
46099
|
-
if (existsSync$1(candidate)) return candidate;
|
|
46100
|
-
const parent = dirname(dir);
|
|
46101
|
-
if (parent === dir) break;
|
|
46102
|
-
dir = parent;
|
|
46103
|
-
}
|
|
46104
|
-
return null;
|
|
46105
|
-
}
|
|
46106
|
-
let cachedModule = null;
|
|
46107
|
-
/**
|
|
46108
|
-
* Dynamically load omp's openai-codex OAuth submodule from the installed `omp`
|
|
46109
|
-
* package. Returns null on any failure so callers can degrade gracefully.
|
|
46110
|
-
*/
|
|
46111
|
-
async function loadOhmypiCodexOAuth() {
|
|
46112
|
-
if (cachedModule) return cachedModule;
|
|
46113
|
-
cachedModule = (async () => {
|
|
46114
|
-
try {
|
|
46115
|
-
const ompBin = findOmpBinary();
|
|
46116
|
-
if (!ompBin) return null;
|
|
46117
|
-
const oauthFile = resolveOmpCodexOAuthFile(ompBin);
|
|
46118
|
-
if (!oauthFile) return null;
|
|
46119
|
-
const mod = await import(pathToFileURL(oauthFile).href);
|
|
46120
|
-
if (typeof mod.refreshOpenAICodexToken !== "function" || typeof mod.loginOpenAICodexDeviceCode !== "function") return null;
|
|
46121
|
-
return mod;
|
|
46122
|
-
} catch {
|
|
46123
|
-
return null;
|
|
46124
|
-
}
|
|
46125
|
-
})();
|
|
46126
|
-
return cachedModule;
|
|
46127
|
-
}
|
|
46128
|
-
const EXPIRY_MARGIN_MS = 6e4;
|
|
46129
|
-
async function getOhmypiCodexAuthStatus(opts) {
|
|
46130
|
-
const cred = readOhmypiCodexCredential();
|
|
46131
|
-
if (!cred) return { status: "missing" };
|
|
46132
|
-
if (cred.expires > Date.now() + EXPIRY_MARGIN_MS) return {
|
|
46133
|
-
status: "ok",
|
|
46134
|
-
expiresAt: cred.expires
|
|
46135
|
-
};
|
|
46136
|
-
if (opts?.refreshIfExpired) {
|
|
46137
|
-
const refreshed = await refreshOhmypiCodexAuth();
|
|
46138
|
-
if (refreshed) return {
|
|
46139
|
-
status: "ok",
|
|
46140
|
-
expiresAt: refreshed.expires
|
|
46141
|
-
};
|
|
46142
|
-
return {
|
|
46143
|
-
status: "expired",
|
|
46144
|
-
expiresAt: cred.expires,
|
|
46145
|
-
refreshFailed: true
|
|
46146
|
-
};
|
|
46147
|
-
}
|
|
46148
|
-
return {
|
|
46149
|
-
status: "expired",
|
|
46150
|
-
expiresAt: cred.expires,
|
|
46151
|
-
refreshFailed: false
|
|
46152
|
-
};
|
|
46153
|
-
}
|
|
46154
|
-
async function refreshOhmypiCodexAuth() {
|
|
46155
|
-
const cred = readOhmypiCodexCredential();
|
|
46156
|
-
if (!cred?.refresh) return null;
|
|
46157
|
-
const mod = await loadOhmypiCodexOAuth();
|
|
46158
|
-
if (!mod) return null;
|
|
46159
|
-
try {
|
|
46160
|
-
return writeOhmypiCodexCredential(await mod.refreshOpenAICodexToken(cred.refresh));
|
|
46161
|
-
} catch {
|
|
46162
|
-
return null;
|
|
46163
|
-
}
|
|
46164
|
-
}
|
|
46165
|
-
//#endregion
|
|
46166
|
-
//#region services/conversation-attachments.ts
|
|
46167
|
-
init_paths();
|
|
46168
|
-
const CONVERSATION_ATTACHMENTS_DIR = "conversation-attachments";
|
|
46169
|
-
/** Run async tasks in bounded batches to avoid unbounded Promise.all
|
|
46170
|
-
* that can exhaust file descriptors or memory under heavy load. */
|
|
46171
|
-
async function runInBatches(items, batchSize, fn) {
|
|
46172
|
-
for (let i = 0; i < items.length; i += batchSize) {
|
|
46173
|
-
const batch = items.slice(i, i + batchSize);
|
|
46174
|
-
await Promise.all(batch.map(fn));
|
|
46175
|
-
}
|
|
46176
|
-
}
|
|
46177
|
-
/** Max JSONL line length to process. Lines larger than this are skipped to
|
|
46178
|
-
* prevent readline from stalling permanently on oversized input (e.g. a
|
|
46179
|
-
* single-line base64 payload >15 MB). */
|
|
46180
|
-
const MAX_JSONL_LINE_LENGTH = 15 * 1024 * 1024;
|
|
46181
|
-
/** Bounded LRU cache for readSessionAttachmentBasenames to avoid full JSONL
|
|
46182
|
-
* rescans when the session file has not changed. Key = sessionFile:mtimeMs. */
|
|
46183
|
-
const SESSION_ATTACHMENT_CACHE_MAX = 100;
|
|
46184
|
-
const sessionAttachmentCache = /* @__PURE__ */ new Map();
|
|
46185
|
-
function getAttachmentCacheKey(sessionFile, mtimeMs) {
|
|
46186
|
-
return `${sessionFile}:${mtimeMs}`;
|
|
46187
|
-
}
|
|
46188
|
-
function setAttachmentCache(sessionFile, mtimeMs, basenames) {
|
|
46189
|
-
const key = getAttachmentCacheKey(sessionFile, mtimeMs);
|
|
46190
|
-
sessionAttachmentCache.set(key, basenames);
|
|
46191
|
-
if (sessionAttachmentCache.size > SESSION_ATTACHMENT_CACHE_MAX) {
|
|
46192
|
-
const firstKey = sessionAttachmentCache.keys().next().value;
|
|
46193
|
-
if (firstKey !== void 0) sessionAttachmentCache.delete(firstKey);
|
|
46194
|
-
}
|
|
46195
|
-
}
|
|
46196
|
-
function getAttachmentCache(sessionFile, mtimeMs) {
|
|
46197
|
-
const key = getAttachmentCacheKey(sessionFile, mtimeMs);
|
|
46198
|
-
return sessionAttachmentCache.get(key);
|
|
46199
|
-
}
|
|
46200
|
-
/** Conversation names are sanitized to [a-zA-Z0-9_-]{1,64} on creation.
|
|
46201
|
-
* Re-validate here for defense-in-depth against path traversal. */
|
|
46202
|
-
function assertSafeName(name) {
|
|
46203
|
-
if (!/^[a-zA-Z0-9_-]{1,64}$/.test(name)) throw new Error("Invalid conversation name");
|
|
46204
|
-
}
|
|
46205
|
-
function getConversationAttachmentsRoot() {
|
|
46206
|
-
return join(getOverdeckHome(), CONVERSATION_ATTACHMENTS_DIR);
|
|
46207
|
-
}
|
|
46208
|
-
function getConversationAttachmentDir(name) {
|
|
46209
|
-
assertSafeName(name);
|
|
46210
|
-
return join(getConversationAttachmentsRoot(), name);
|
|
46211
|
-
}
|
|
46212
|
-
async function ensureConversationAttachmentDir(name) {
|
|
46213
|
-
const dir = getConversationAttachmentDir(name);
|
|
46214
|
-
await mkdir(dir, { recursive: true });
|
|
46215
|
-
return dir;
|
|
46216
|
-
}
|
|
46217
|
-
async function cleanupConversationAttachments(name) {
|
|
46218
|
-
assertSafeName(name);
|
|
46219
|
-
await rm(getConversationAttachmentDir(name), {
|
|
46220
|
-
recursive: true,
|
|
46221
|
-
force: true
|
|
46222
|
-
});
|
|
46223
|
-
}
|
|
46224
|
-
/** Safety-net cleanup: remove attachment directories for conversations that no
|
|
46225
|
-
* longer exist in the database. Catches orphaned files from abandoned/crashed
|
|
46226
|
-
* sessions that the lifecycle poller missed. */
|
|
46227
|
-
async function cleanupOrphanedConversationAttachments() {
|
|
46228
|
-
try {
|
|
46229
|
-
const { listConversations } = await import("./conversations-izHvSoAR.js");
|
|
46230
|
-
const convNames = new Set(listConversations().map((c) => c.name));
|
|
46231
|
-
const root = getConversationAttachmentsRoot();
|
|
46232
|
-
await runInBatches((await readdir(root, { withFileTypes: true })).filter((entry) => entry.isDirectory() && !convNames.has(entry.name)).map((entry) => join(root, entry.name)), 10, (path) => rm(path, {
|
|
46233
|
-
recursive: true,
|
|
46234
|
-
force: true
|
|
46235
|
-
}).catch(() => {}));
|
|
46236
|
-
} catch {}
|
|
46237
|
-
}
|
|
46238
|
-
async function listConversationAttachmentPaths(name) {
|
|
46239
|
-
const dir = getConversationAttachmentDir(name);
|
|
46240
|
-
try {
|
|
46241
|
-
return (await readdir(dir, { withFileTypes: true })).filter((entry) => entry.isFile()).map((entry) => join(dir, entry.name));
|
|
46242
|
-
} catch {
|
|
46243
|
-
return [];
|
|
46244
|
-
}
|
|
46245
|
-
}
|
|
46246
|
-
/** Synchronous containment check: does the normalized path start with the
|
|
46247
|
-
* pre-resolved attachment directory prefix? Uses resolve() (not realpath)
|
|
46248
|
-
* so the check is I/O-free — safe because we are only cataloguing references
|
|
46249
|
-
* in the JSONL, not accessing the filesystem. */
|
|
46250
|
-
function isUnderAttachmentDir(resolvedAttachmentDir, attachmentPath) {
|
|
46251
|
-
try {
|
|
46252
|
-
return resolve(attachmentPath).startsWith(`${resolvedAttachmentDir}/`);
|
|
46253
|
-
} catch {
|
|
46254
|
-
return false;
|
|
46255
|
-
}
|
|
46256
|
-
}
|
|
46257
|
-
async function readSessionAttachmentBasenames(sessionFile, name) {
|
|
46258
|
-
try {
|
|
46259
|
-
let mtimeMs;
|
|
46260
|
-
try {
|
|
46261
|
-
mtimeMs = (await stat$1(sessionFile)).mtimeMs;
|
|
46262
|
-
} catch {
|
|
46263
|
-
return /* @__PURE__ */ new Set();
|
|
46264
|
-
}
|
|
46265
|
-
const cached = getAttachmentCache(sessionFile, mtimeMs);
|
|
46266
|
-
if (cached) return cached;
|
|
46267
|
-
let resolvedAttachmentDir;
|
|
46268
|
-
try {
|
|
46269
|
-
resolvedAttachmentDir = await realpath(getConversationAttachmentDir(name));
|
|
46270
|
-
} catch {
|
|
46271
|
-
resolvedAttachmentDir = resolve(getConversationAttachmentDir(name));
|
|
46272
|
-
}
|
|
46273
|
-
const referenced = /* @__PURE__ */ new Set();
|
|
46274
|
-
const stream = createReadStream$1(sessionFile, { encoding: "utf-8" });
|
|
46275
|
-
const rl = createInterface$1({
|
|
46276
|
-
input: stream,
|
|
46277
|
-
crlfDelay: Infinity
|
|
46278
|
-
});
|
|
46279
|
-
try {
|
|
46280
|
-
for await (const line of rl) {
|
|
46281
|
-
if (!line.trim()) continue;
|
|
46282
|
-
if (line.length > MAX_JSONL_LINE_LENGTH) continue;
|
|
46283
|
-
let text;
|
|
46284
|
-
let structuredFoundPaths = false;
|
|
46285
|
-
try {
|
|
46286
|
-
const entry = JSON.parse(line);
|
|
46287
|
-
if (typeof entry?.message?.content === "string") text = entry.message.content;
|
|
46288
|
-
else if (Array.isArray(entry?.message?.content)) text = entry.message.content.map((c) => typeof c === "string" ? c : c?.text ?? "").join("");
|
|
46289
|
-
else if (typeof entry?.message?.text === "string") text = entry.message.text;
|
|
46290
|
-
else if (typeof entry?.text === "string") text = entry.text;
|
|
46291
|
-
} catch {
|
|
46292
|
-
text = line;
|
|
46293
|
-
}
|
|
46294
|
-
if (text) {
|
|
46295
|
-
for (const attachmentPath of extractConversationAttachmentPaths(text)) if (isUnderAttachmentDir(resolvedAttachmentDir, attachmentPath)) {
|
|
46296
|
-
referenced.add(basename(attachmentPath));
|
|
46297
|
-
structuredFoundPaths = true;
|
|
46298
|
-
}
|
|
46299
|
-
}
|
|
46300
|
-
if (!structuredFoundPaths) for (const match of line.matchAll(/"@([^"]+)"/g)) {
|
|
46301
|
-
const rawValue = match[1];
|
|
46302
|
-
if (!rawValue.startsWith("/") && !rawValue.startsWith("\\/")) continue;
|
|
46303
|
-
let attachmentPath;
|
|
46304
|
-
try {
|
|
46305
|
-
attachmentPath = JSON.parse(`"${rawValue}"`);
|
|
46306
|
-
} catch {
|
|
46307
|
-
attachmentPath = rawValue;
|
|
46308
|
-
}
|
|
46309
|
-
if (typeof attachmentPath === "string" && attachmentPath.startsWith("/")) {
|
|
46310
|
-
if (isUnderAttachmentDir(resolvedAttachmentDir, attachmentPath)) referenced.add(basename(attachmentPath));
|
|
46311
|
-
}
|
|
46312
|
-
}
|
|
46313
|
-
}
|
|
46314
|
-
} finally {
|
|
46315
|
-
rl.close();
|
|
46316
|
-
stream.destroy();
|
|
46317
|
-
}
|
|
46318
|
-
setAttachmentCache(sessionFile, mtimeMs, referenced);
|
|
46319
|
-
return referenced;
|
|
46320
|
-
} catch {
|
|
46321
|
-
return /* @__PURE__ */ new Set();
|
|
46322
|
-
}
|
|
46323
|
-
}
|
|
46324
|
-
async function cleanupUnreferencedConversationAttachments(conversation) {
|
|
46325
|
-
const attachmentPaths = await listConversationAttachmentPaths(conversation.name);
|
|
46326
|
-
if (attachmentPaths.length === 0) return;
|
|
46327
|
-
if (!conversation.sessionFile) {
|
|
46328
|
-
await runInBatches(attachmentPaths, 10, async (attachmentPath) => {
|
|
46329
|
-
await rm(attachmentPath, { force: true });
|
|
46330
|
-
});
|
|
46331
|
-
return;
|
|
46332
|
-
}
|
|
46333
|
-
let sessionMtimeMs;
|
|
46334
|
-
try {
|
|
46335
|
-
sessionMtimeMs = (await stat$1(conversation.sessionFile)).mtimeMs;
|
|
46336
|
-
} catch {
|
|
46337
|
-
return;
|
|
46338
|
-
}
|
|
46339
|
-
const referencedBasenames = await readSessionAttachmentBasenames(conversation.sessionFile, conversation.name);
|
|
46340
|
-
try {
|
|
46341
|
-
const freshStats = await stat$1(conversation.sessionFile);
|
|
46342
|
-
if (freshStats.mtimeMs > sessionMtimeMs) sessionMtimeMs = freshStats.mtimeMs;
|
|
46343
|
-
} catch {}
|
|
46344
|
-
await runInBatches(attachmentPaths, 10, async (attachmentPath) => {
|
|
46345
|
-
if (referencedBasenames.has(basename(attachmentPath))) return;
|
|
46346
|
-
try {
|
|
46347
|
-
if ((await stat$1(attachmentPath)).mtimeMs >= sessionMtimeMs) return;
|
|
46348
|
-
} catch {
|
|
46349
|
-
return;
|
|
46350
|
-
}
|
|
46351
|
-
await rm(attachmentPath, { force: true });
|
|
46352
|
-
});
|
|
46353
|
-
}
|
|
46354
|
-
function extractConversationAttachmentPaths(message) {
|
|
46355
|
-
return Array.from(message.matchAll(/(?<!\S)@(\/[^\s]+)/g), ([, attachmentPath]) => {
|
|
46356
|
-
let path = attachmentPath;
|
|
46357
|
-
while (path.length > 1 && /[.,;:!?)\]}+"']$/.test(path)) path = path.slice(0, -1);
|
|
46358
|
-
return path;
|
|
46359
|
-
});
|
|
46360
|
-
}
|
|
46361
|
-
/** Resolve a path for containment checking, walking parent directories with
|
|
46362
|
-
* realpath to preserve symlink detection even when the target file is missing. */
|
|
46363
|
-
async function resolveForContainment(attachmentPath) {
|
|
46364
|
-
try {
|
|
46365
|
-
return await realpath(attachmentPath);
|
|
46366
|
-
} catch {
|
|
46367
|
-
let dir = dirname(attachmentPath);
|
|
46368
|
-
const remaining = [basename(attachmentPath)];
|
|
46369
|
-
while (dir !== "/" && dir !== ".") try {
|
|
46370
|
-
return join(await realpath(dir), ...remaining);
|
|
46371
|
-
} catch {
|
|
46372
|
-
remaining.unshift(basename(dir));
|
|
46373
|
-
dir = dirname(dir);
|
|
46374
|
-
}
|
|
46375
|
-
return resolve(attachmentPath);
|
|
46376
|
-
}
|
|
46377
|
-
}
|
|
46378
|
-
async function isManagedConversationAttachmentPath(attachmentPath) {
|
|
46379
|
-
try {
|
|
46380
|
-
const attachmentsRoot = await realpath(getConversationAttachmentsRoot());
|
|
46381
|
-
return (await resolveForContainment(attachmentPath)).startsWith(`${attachmentsRoot}/`);
|
|
46382
|
-
} catch {
|
|
46383
|
-
return false;
|
|
46384
|
-
}
|
|
46385
|
-
}
|
|
46386
|
-
async function isConversationAttachmentPath(name, attachmentPath) {
|
|
46387
|
-
try {
|
|
46388
|
-
const attachmentDir = resolve(getConversationAttachmentDir(name));
|
|
46389
|
-
return (await resolveForContainment(attachmentPath)).startsWith(`${attachmentDir}/`);
|
|
46390
|
-
} catch {
|
|
46391
|
-
return false;
|
|
46392
|
-
}
|
|
46393
|
-
}
|
|
46394
|
-
async function hasConversationAttachment(name, attachmentPath) {
|
|
46395
|
-
try {
|
|
46396
|
-
const attachmentDir = await realpath(getConversationAttachmentDir(name));
|
|
46397
|
-
const candidate = await resolveForContainment(attachmentPath);
|
|
46398
|
-
if (!candidate.startsWith(`${attachmentDir}/`)) return false;
|
|
46399
|
-
return existsSync$1(candidate);
|
|
46400
|
-
} catch {
|
|
46401
|
-
return false;
|
|
46402
|
-
}
|
|
46403
|
-
}
|
|
46404
|
-
async function removeConversationAttachment(name, attachmentPath) {
|
|
46405
|
-
if (!await isConversationAttachmentPath(name, attachmentPath)) return false;
|
|
46406
|
-
await rm(attachmentPath, { force: true });
|
|
46407
|
-
return true;
|
|
46408
|
-
}
|
|
46409
|
-
//#endregion
|
|
46410
|
-
//#region ../../lib/runtimes/conversation-control.ts
|
|
46411
|
-
function conversationControlPaths(agentId, home) {
|
|
46412
|
-
const { agentDir } = ohmypiFifoPaths(agentId, home);
|
|
46413
|
-
return {
|
|
46414
|
-
agentDir,
|
|
46415
|
-
controlDir: join(agentDir, "control")
|
|
46416
|
-
};
|
|
46417
|
-
}
|
|
46418
|
-
async function writeConversationControlCommand(agentId, command, home) {
|
|
46419
|
-
const paths = conversationControlPaths(agentId, home);
|
|
46420
|
-
await mkdir(paths.controlDir, {
|
|
46421
|
-
recursive: true,
|
|
46422
|
-
mode: 448
|
|
46423
|
-
});
|
|
46424
|
-
await chmod(paths.controlDir, 448);
|
|
46425
|
-
const finalPath = join(paths.controlDir, `${Date.now()}-${command.id}-${randomUUID$1()}.json`);
|
|
46426
|
-
const tempPath = `${finalPath}.tmp`;
|
|
46427
|
-
await writeFile(tempPath, `${JSON.stringify(command)}\n`, {
|
|
46428
|
-
encoding: "utf8",
|
|
46429
|
-
mode: 384
|
|
46430
|
-
});
|
|
46431
|
-
await chmod(tempPath, 384);
|
|
46432
|
-
await rename(tempPath, finalPath);
|
|
46433
|
-
await chmod(finalPath, 384);
|
|
46434
|
-
return finalPath;
|
|
46435
|
-
}
|
|
46436
|
-
//#endregion
|
|
46437
|
-
//#region ../../lib/overdeck/conversation-delivery.ts
|
|
46438
|
-
init_conversations();
|
|
46439
|
-
init_behavior();
|
|
46440
|
-
init_tmux();
|
|
46441
|
-
init_agents$1();
|
|
46442
|
-
const CONTROL_ACK_TIMEOUT_MS = 1e4;
|
|
46443
|
-
const pendingConversationControlAcks = /* @__PURE__ */ new Map();
|
|
46444
|
-
const PLAN_ACTION_KEYSTROKES = {
|
|
46445
|
-
"approve-auto": "1",
|
|
46446
|
-
"approve-manual": "2",
|
|
46447
|
-
"reject-ultraplan": "3"
|
|
46448
|
-
};
|
|
46449
|
-
function registerConversationControlAck(commandId, timeoutMs = CONTROL_ACK_TIMEOUT_MS) {
|
|
46450
|
-
const existing = pendingConversationControlAcks.get(commandId);
|
|
46451
|
-
if (existing) {
|
|
46452
|
-
clearTimeout(existing.timer);
|
|
46453
|
-
existing.reject(/* @__PURE__ */ new Error(`Replaced pending conversation control ack ${commandId}`));
|
|
46454
|
-
pendingConversationControlAcks.delete(commandId);
|
|
46455
|
-
}
|
|
46456
|
-
return new Promise((resolve, reject) => {
|
|
46457
|
-
const timer = setTimeout(() => {
|
|
46458
|
-
pendingConversationControlAcks.delete(commandId);
|
|
46459
|
-
reject(/* @__PURE__ */ new Error(`Timed out waiting for conversation control ack ${commandId}`));
|
|
46460
|
-
}, timeoutMs);
|
|
46461
|
-
pendingConversationControlAcks.set(commandId, {
|
|
46462
|
-
resolve: () => {
|
|
46463
|
-
clearTimeout(timer);
|
|
46464
|
-
pendingConversationControlAcks.delete(commandId);
|
|
46465
|
-
resolve();
|
|
46466
|
-
},
|
|
46467
|
-
reject: (error) => {
|
|
46468
|
-
clearTimeout(timer);
|
|
46469
|
-
pendingConversationControlAcks.delete(commandId);
|
|
46470
|
-
reject(error);
|
|
46471
|
-
},
|
|
46472
|
-
timer
|
|
46473
|
-
});
|
|
46474
|
-
});
|
|
46475
|
-
}
|
|
46476
|
-
function resolveConversationControlAck(ack) {
|
|
46477
|
-
const pending = pendingConversationControlAcks.get(ack.id);
|
|
46478
|
-
if (!pending) return "unknown";
|
|
46479
|
-
if (ack.ok) {
|
|
46480
|
-
pending.resolve();
|
|
46481
|
-
return "resolved";
|
|
46482
|
-
}
|
|
46483
|
-
pending.reject(new Error(ack.error || `Conversation control command ${ack.id} failed`));
|
|
46484
|
-
return "rejected";
|
|
46485
|
-
}
|
|
46486
|
-
function handleConversationControlAck(body) {
|
|
46487
|
-
const id = typeof body["id"] === "string" ? body["id"].trim() : "";
|
|
46488
|
-
if (!id) return {
|
|
46489
|
-
status: 400,
|
|
46490
|
-
body: { error: "id is required" }
|
|
46491
|
-
};
|
|
46492
|
-
const ok = body["ok"] === true;
|
|
46493
|
-
const error = typeof body["error"] === "string" ? body["error"] : void 0;
|
|
46494
|
-
return {
|
|
46495
|
-
status: 200,
|
|
46496
|
-
body: {
|
|
46497
|
-
ok: true,
|
|
46498
|
-
outcome: resolveConversationControlAck({
|
|
46499
|
-
id,
|
|
46500
|
-
ok,
|
|
46501
|
-
...error !== void 0 ? { error } : {}
|
|
46502
|
-
})
|
|
46503
|
-
}
|
|
46504
|
-
};
|
|
46505
|
-
}
|
|
46506
|
-
function validateConversationControlAckOrigin(headers, method = "POST") {
|
|
46507
|
-
const origin = getHeaderFromMap(headers, "origin");
|
|
46508
|
-
const referer = getHeaderFromMap(headers, "referer");
|
|
46509
|
-
if (!origin && !referer) return { ok: true };
|
|
46510
|
-
return validateOriginHeaders(headers, method);
|
|
46511
|
-
}
|
|
46512
|
-
async function handleConversationCodexApproval(rawId, body) {
|
|
46513
|
-
try {
|
|
46514
|
-
const optionNumber = Number(body.optionNumber);
|
|
46515
|
-
if (!Number.isInteger(optionNumber) || optionNumber < 1 || optionNumber > 9) return jsonResponse({ error: "optionNumber must be an integer 1-9" }, { status: 400 });
|
|
46516
|
-
const numericId = Number(rawId);
|
|
46517
|
-
const conv = !Number.isNaN(numericId) && /^\d+$/.test(rawId) ? getConversationById(numericId) : getConversationByName(rawId);
|
|
46518
|
-
if (!conv) return jsonResponse({ error: "Conversation not found" }, { status: 404 });
|
|
46519
|
-
if (getHarnessBehavior(conv.harness).transcriptKind !== "codex-rollout-jsonl") return jsonResponse({ error: "Not a Codex conversation" }, { status: 400 });
|
|
46520
|
-
if (!await tmuxSessionExists(conv.tmuxSession)) return jsonResponse({ error: "Conversation session is not running" }, { status: 409 });
|
|
46521
|
-
const detection = await Effect.runPromise(detectAwaitingInputForAgent(conv.tmuxSession, {
|
|
46522
|
-
isPlanning: false,
|
|
46523
|
-
cache: false
|
|
46524
|
-
}));
|
|
46525
|
-
const parsed = detection ? parseCodexApprovalPrompt(detection.prompt) : null;
|
|
46526
|
-
if (!parsed) return jsonResponse({ error: "No Codex approval prompt is currently pending" }, { status: 409 });
|
|
46527
|
-
if (optionNumber > parsed.options.length) return jsonResponse({ error: `optionNumber out of range (1-${parsed.options.length})` }, { status: 400 });
|
|
46528
|
-
await deliverCodexApprovalChoice(conv.tmuxSession, optionNumber);
|
|
46529
|
-
return jsonResponse({
|
|
46530
|
-
ok: true,
|
|
46531
|
-
optionNumber
|
|
46532
|
-
});
|
|
46533
|
-
} catch (error) {
|
|
46534
|
-
const msg = error instanceof Error ? error.message : String(error);
|
|
46535
|
-
console.error("[conversations] codex approval failed:", msg);
|
|
46536
|
-
return jsonResponse({ error: "Internal server error" }, { status: 500 });
|
|
46537
|
-
}
|
|
46538
|
-
}
|
|
46539
|
-
async function handleConversationPlanAction(name, body) {
|
|
46540
|
-
try {
|
|
46541
|
-
const conv = getConversationByName(name);
|
|
46542
|
-
if (!conv) return jsonResponse({ error: "Conversation not found" }, { status: 404 });
|
|
46543
|
-
const action = typeof body["action"] === "string" ? body["action"] : "";
|
|
46544
|
-
const feedback = typeof body["feedback"] === "string" ? body["feedback"].trim() : "";
|
|
46545
|
-
if (action === "reject-feedback") {
|
|
46546
|
-
await Effect.runPromise(sendRawKeystroke(conv.tmuxSession, "4", "plan-action-reject"));
|
|
46547
|
-
if (feedback) {
|
|
46548
|
-
await new Promise((r) => setTimeout(r, 300));
|
|
46549
|
-
await deliverAgentMessage(conv.tmuxSession, feedback, "plan-action-feedback", resolveConversationDeliveryMethod(conv));
|
|
46550
|
-
}
|
|
46551
|
-
return jsonResponse({ ok: true });
|
|
46552
|
-
}
|
|
46553
|
-
const keystroke = PLAN_ACTION_KEYSTROKES[action];
|
|
46554
|
-
if (!keystroke) return jsonResponse({ error: `Invalid action: ${action}` }, { status: 400 });
|
|
46555
|
-
await Effect.runPromise(sendRawKeystroke(conv.tmuxSession, keystroke, `plan-action-${action}`));
|
|
46556
|
-
return jsonResponse({ ok: true });
|
|
46557
|
-
} catch (error) {
|
|
46558
|
-
const msg = error instanceof Error ? error.message : String(error);
|
|
46559
|
-
console.error("[conversations] plan action failed:", msg);
|
|
46560
|
-
return jsonResponse({ error: "Internal server error" }, { status: 500 });
|
|
46561
|
-
}
|
|
46562
|
-
}
|
|
46563
|
-
const THINKING_LEVELS = [
|
|
46564
|
-
"off",
|
|
46565
|
-
"minimal",
|
|
46566
|
-
"low",
|
|
46567
|
-
"medium",
|
|
46568
|
-
"high",
|
|
46569
|
-
"xhigh"
|
|
46570
|
-
];
|
|
46571
|
-
const PI_CONVERSATION_ABORT_KEY = "Escape";
|
|
46572
|
-
function isPiControlChannelHarness(harness) {
|
|
46573
|
-
return harness === "ohmypi" || harness === "pi";
|
|
46574
|
-
}
|
|
46575
|
-
function parseThinkingLevel(value) {
|
|
46576
|
-
return typeof value === "string" && THINKING_LEVELS.includes(value) ? value : null;
|
|
46577
|
-
}
|
|
46578
|
-
function pickDeliverAs(bodyDeliverAs) {
|
|
46579
|
-
if (bodyDeliverAs === "follow_up") return "follow_up";
|
|
46580
|
-
return "steer";
|
|
46581
|
-
}
|
|
46582
|
-
function resolveConversationDeliveryMethod(conv) {
|
|
46583
|
-
const harness = conv.harness ?? "claude-code";
|
|
46584
|
-
if (isPiControlChannelHarness(harness)) return "auto";
|
|
46585
|
-
return conv.deliveryMethod ?? (getHarnessBehavior(harness).deliveryKind === "rpc-fifo" ? "tmux" : "auto");
|
|
46586
|
-
}
|
|
46587
|
-
async function sendConversationControlCommand(conv, commandInput) {
|
|
46588
|
-
const id = randomUUID$1();
|
|
46589
|
-
const ackPromise = registerConversationControlAck(id);
|
|
46590
|
-
const command = {
|
|
46591
|
-
id,
|
|
46592
|
-
...commandInput
|
|
46593
|
-
};
|
|
46594
|
-
try {
|
|
46595
|
-
await writeConversationControlCommand(conv.tmuxSession, command);
|
|
46596
|
-
} catch (err) {
|
|
46597
|
-
resolveConversationControlAck({
|
|
46598
|
-
id,
|
|
46599
|
-
ok: false,
|
|
46600
|
-
error: err instanceof Error ? err.message : String(err)
|
|
46601
|
-
});
|
|
46602
|
-
}
|
|
46603
|
-
await ackPromise;
|
|
46604
|
-
}
|
|
46605
|
-
async function deliverConversationViaControlChannel(conv, message, options) {
|
|
46606
|
-
await sendConversationControlCommand(conv, {
|
|
46607
|
-
type: options.deliverAs,
|
|
46608
|
-
message,
|
|
46609
|
-
source: options.source
|
|
46610
|
-
});
|
|
46611
|
-
}
|
|
46612
|
-
async function handleConversationThinkingLevel(name, body) {
|
|
46613
|
-
const conv = getConversationByName(name);
|
|
46614
|
-
if (!conv) return jsonResponse({ error: "Conversation not found" }, { status: 404 });
|
|
46615
|
-
if (!isPiControlChannelHarness(conv.harness ?? "claude-code")) return jsonResponse({ error: "Thinking level control is only supported for Pi conversations" }, { status: 400 });
|
|
46616
|
-
if (conv.status === "ended") return jsonResponse({ error: "Session has ended — start a new run to interact" }, { status: 422 });
|
|
46617
|
-
const level = parseThinkingLevel(body["level"]);
|
|
46618
|
-
if (!level) return jsonResponse({ error: "Invalid thinking level" }, { status: 400 });
|
|
46619
|
-
await sendConversationControlCommand(conv, {
|
|
46620
|
-
type: "set_thinking_level",
|
|
46621
|
-
level
|
|
46622
|
-
});
|
|
46623
|
-
setConversationEffort(name, level);
|
|
46624
|
-
return jsonResponse({
|
|
46625
|
-
ok: true,
|
|
46626
|
-
effort: (getConversationByName(name) ?? conv).effort ?? level
|
|
46627
|
-
});
|
|
46628
|
-
}
|
|
46629
|
-
async function handleConversationCompact(name) {
|
|
46630
|
-
const conv = getConversationByName(name);
|
|
46631
|
-
if (!conv) return jsonResponse({ error: "Conversation not found" }, { status: 404 });
|
|
46632
|
-
if (!isPiControlChannelHarness(conv.harness ?? "claude-code")) return jsonResponse({ error: "Compact control endpoint is only supported for Pi conversations" }, { status: 400 });
|
|
46633
|
-
if (conv.status === "ended") return jsonResponse({ error: "Session has ended — start a new run to interact" }, { status: 422 });
|
|
46634
|
-
await sendConversationControlCommand(conv, { type: "compact" });
|
|
46635
|
-
return jsonResponse({ ok: true });
|
|
46636
|
-
}
|
|
46637
|
-
async function handleConversationAbort(name) {
|
|
46638
|
-
const conv = getConversationByName(name);
|
|
46639
|
-
if (!conv) return jsonResponse({ error: "Conversation not found" }, { status: 404 });
|
|
46640
|
-
if (!isPiControlChannelHarness(conv.harness ?? "claude-code")) return jsonResponse({ error: "Abort control endpoint is only supported for Pi conversations" }, { status: 400 });
|
|
46641
|
-
if (conv.status === "ended") return jsonResponse({ error: "Session has ended — start a new run to interact" }, { status: 422 });
|
|
46642
|
-
await sendKeysAsync(conv.tmuxSession, PI_CONVERSATION_ABORT_KEY, "conversation-abort");
|
|
46643
|
-
return jsonResponse({
|
|
46644
|
-
ok: true,
|
|
46645
|
-
key: PI_CONVERSATION_ABORT_KEY
|
|
46646
|
-
});
|
|
46647
|
-
}
|
|
46648
|
-
async function handleConversationDeliveryMethod(name, body) {
|
|
46649
|
-
if (!getConversationByName(name)) return jsonResponse({ error: "Conversation not found" }, { status: 404 });
|
|
46650
|
-
const deliveryMethod = body["deliveryMethod"] ?? body["method"];
|
|
46651
|
-
if (deliveryMethod !== "auto" && deliveryMethod !== "channels" && deliveryMethod !== "tmux" && deliveryMethod !== null) return jsonResponse({ error: "deliveryMethod must be 'auto', 'channels', 'tmux', or null" }, { status: 400 });
|
|
46652
|
-
updateConversationDeliveryMethod(name, deliveryMethod);
|
|
46653
|
-
return jsonResponse({
|
|
46654
|
-
ok: true,
|
|
46655
|
-
deliveryMethod
|
|
46656
|
-
});
|
|
46657
|
-
}
|
|
46658
|
-
const CODEX_APPROVAL_TOOL_PREFIX = "codex-approval:";
|
|
46659
|
-
async function codexConversationPendingInput(conv, sessionAlive, askedAt) {
|
|
46660
|
-
if (!sessionAlive || getHarnessBehavior(conv.harness).transcriptKind !== "codex-rollout-jsonl") return { kinds: [] };
|
|
46661
|
-
try {
|
|
46662
|
-
const detection = await Effect.runPromise(detectAwaitingInputForAgent(conv.tmuxSession, { isPlanning: false }));
|
|
46663
|
-
if (!detection) return { kinds: [] };
|
|
46664
|
-
if (detection.reason === "session_resume") return { kinds: ["sessionResume"] };
|
|
46665
|
-
const parsed = parseCodexApprovalPrompt(detection.prompt);
|
|
46666
|
-
if (parsed) return {
|
|
46667
|
-
kinds: ["permissionRequest"],
|
|
46668
|
-
approval: {
|
|
46669
|
-
toolUseId: `${CODEX_APPROVAL_TOOL_PREFIX}${conv.tmuxSession}`,
|
|
46670
|
-
askedAt,
|
|
46671
|
-
questions: [{
|
|
46672
|
-
question: parsed.detail ? `${parsed.header}\n\n${parsed.detail}` : parsed.header,
|
|
46673
|
-
header: "Codex approval",
|
|
46674
|
-
multiSelect: false,
|
|
46675
|
-
options: parsed.options.map((o) => ({ label: `${o.number}. ${o.label}` }))
|
|
46676
|
-
}]
|
|
46677
|
-
}
|
|
46678
|
-
};
|
|
46679
|
-
return { kinds: ["permissionRequest"] };
|
|
46680
|
-
} catch {
|
|
46681
|
-
return { kinds: [] };
|
|
46682
|
-
}
|
|
46683
|
-
}
|
|
46684
|
-
async function deliverCodexApprovalChoice(tmuxSession, optionNumber) {
|
|
46685
|
-
for (let i = 1; i < optionNumber; i += 1) {
|
|
46686
|
-
await Effect.runPromise(sendRawKeystroke(tmuxSession, "Down", "codex-approval"));
|
|
46687
|
-
await new Promise((r) => setTimeout(r, 60));
|
|
46688
|
-
}
|
|
46689
|
-
await Effect.runPromise(sendRawKeystroke(tmuxSession, "Enter", "codex-approval"));
|
|
46690
|
-
}
|
|
46691
|
-
//#endregion
|
|
46692
|
-
//#region ../../lib/overdeck/conversation-runtime.ts
|
|
46693
|
-
init_child_env();
|
|
46694
|
-
init_claude_permissions();
|
|
46695
|
-
init_projects();
|
|
46696
|
-
init_conversations();
|
|
46697
|
-
init_tmux();
|
|
46698
|
-
init_agents$1();
|
|
46699
|
-
init_config_yaml();
|
|
46700
|
-
init_harness_policy();
|
|
46701
|
-
init_providers();
|
|
46702
|
-
init_behavior();
|
|
46703
|
-
init_launcher_generator();
|
|
46704
|
-
init_layers();
|
|
46705
|
-
init_briefing_freshness();
|
|
46706
|
-
init_paths();
|
|
46707
|
-
init_event_store();
|
|
46708
|
-
const execAsync$3 = promisify(exec);
|
|
46709
|
-
const execFileAsync$3 = promisify(execFile);
|
|
46710
|
-
const PROCESS_CLEANUP_GRACE_MS = 750;
|
|
46711
|
-
const PTY_SUPERVISOR_SOCKET_WAIT_MS = 3e4;
|
|
46712
|
-
function parseProcessTable(output) {
|
|
46713
|
-
return output.split("\n").map((line) => {
|
|
46714
|
-
const match = line.match(/^\s*(\d+)\s+(\d+)\s+(.*)$/);
|
|
46715
|
-
if (!match) return null;
|
|
46716
|
-
return {
|
|
46717
|
-
pid: Number(match[1]),
|
|
46718
|
-
ppid: Number(match[2]),
|
|
46719
|
-
args: match[3] ?? ""
|
|
46720
|
-
};
|
|
46721
|
-
}).filter((row) => row !== null && Number.isFinite(row.pid) && Number.isFinite(row.ppid));
|
|
46722
|
-
}
|
|
46723
|
-
async function readProcessTable() {
|
|
46724
|
-
const { stdout } = await execFileAsync$3("ps", ["-eo", "pid=,ppid=,args="], {
|
|
46725
|
-
encoding: "utf-8",
|
|
46726
|
-
maxBuffer: 10 * 1024 * 1024
|
|
46727
|
-
});
|
|
46728
|
-
return parseProcessTable(stdout);
|
|
46729
|
-
}
|
|
46730
|
-
function collectProcessTree(rootPids, rows) {
|
|
46731
|
-
const childrenByParent = /* @__PURE__ */ new Map();
|
|
46732
|
-
for (const row of rows) {
|
|
46733
|
-
const children = childrenByParent.get(row.ppid) ?? [];
|
|
46734
|
-
children.push(row.pid);
|
|
46735
|
-
childrenByParent.set(row.ppid, children);
|
|
46736
|
-
}
|
|
46737
|
-
const seen = /* @__PURE__ */ new Set();
|
|
46738
|
-
const ordered = [];
|
|
46739
|
-
const visit = (pid) => {
|
|
46740
|
-
if (seen.has(pid) || pid === process.pid) return;
|
|
46741
|
-
seen.add(pid);
|
|
46742
|
-
for (const child of childrenByParent.get(pid) ?? []) visit(child);
|
|
46743
|
-
ordered.push(pid);
|
|
46744
|
-
};
|
|
46745
|
-
for (const pid of rootPids) visit(pid);
|
|
46746
|
-
return ordered;
|
|
46747
|
-
}
|
|
46748
|
-
function isProcessAlive$1(pid) {
|
|
46749
|
-
try {
|
|
46750
|
-
process.kill(pid, 0);
|
|
46751
|
-
return true;
|
|
46752
|
-
} catch {
|
|
46753
|
-
return false;
|
|
46754
|
-
}
|
|
46755
|
-
}
|
|
46756
|
-
async function terminatePids(pids) {
|
|
46757
|
-
if (pids.length === 0) return;
|
|
46758
|
-
for (const pid of pids) try {
|
|
46759
|
-
process.kill(pid, "SIGTERM");
|
|
46760
|
-
} catch {}
|
|
46761
|
-
await new Promise((resolve) => setTimeout(resolve, PROCESS_CLEANUP_GRACE_MS));
|
|
46762
|
-
for (const pid of pids) {
|
|
46763
|
-
if (!isProcessAlive$1(pid)) continue;
|
|
46764
|
-
try {
|
|
46765
|
-
process.kill(pid, "SIGKILL");
|
|
46766
|
-
} catch {}
|
|
46767
|
-
}
|
|
46768
|
-
}
|
|
46769
|
-
function conversationRuntimeRootPids(conv, rows) {
|
|
46770
|
-
const launcherScript = join(getOverdeckHome(), "conversations", conv.tmuxSession, "launcher.sh");
|
|
46771
|
-
const sessionId = conv.claudeSessionId?.trim();
|
|
46772
|
-
const sessionNeedles = sessionId ? [`--resume ${sessionId}`, `--session-id ${sessionId}`] : [];
|
|
46773
|
-
const serverPid = findManagedServerPidSync();
|
|
46774
|
-
return rows.filter((row) => {
|
|
46775
|
-
if (row.pid === process.pid) return false;
|
|
46776
|
-
if (serverPid !== void 0 && row.pid === serverPid) return false;
|
|
46777
|
-
if (row.args.includes(launcherScript)) return true;
|
|
46778
|
-
return sessionNeedles.some((needle) => row.args.includes(needle));
|
|
46779
|
-
}).map((row) => row.pid);
|
|
46780
|
-
}
|
|
46781
|
-
async function killConversationRuntimeProcesses(conv) {
|
|
46782
|
-
const rows = await readProcessTable();
|
|
46783
|
-
await terminatePids(collectProcessTree(conversationRuntimeRootPids(conv, rows), rows));
|
|
46784
|
-
}
|
|
46785
|
-
async function stopConversationRuntime(conv, name) {
|
|
46786
|
-
if (hasOtherActiveConversationOnTmuxSession(conv.tmuxSession, name)) return;
|
|
46787
|
-
await Effect.runPromise(killSession(conv.tmuxSession).pipe(Effect.catch(() => Effect.succeed(void 0))));
|
|
46788
|
-
try {
|
|
46789
|
-
await killConversationRuntimeProcesses(conv);
|
|
46790
|
-
} catch (error) {
|
|
46791
|
-
const msg = error instanceof Error ? error.message : String(error);
|
|
46792
|
-
console.warn(`[conversations] failed to cleanup runtime processes for ${name}: ${msg}`);
|
|
46793
|
-
}
|
|
46794
|
-
}
|
|
46795
|
-
/** Quote a string for safe use in a bash script using single-quote wrapping. */
|
|
46796
|
-
function shellQuote(str) {
|
|
46797
|
-
return "'" + str.replace(/'/g, "'\"'\"'") + "'";
|
|
46798
|
-
}
|
|
46799
|
-
const SAFE_MODEL_PATTERN$1 = /^[a-zA-Z0-9_.:\/-]+$/;
|
|
46800
|
-
const SAFE_EFFORT_PATTERN = /^(low|medium|high)$/;
|
|
46801
|
-
const SAFE_ISSUE_ID_PATTERN = /^[A-Z0-9]+-[0-9]+$/;
|
|
46802
|
-
const PI_CONVERSATION_SOURCE_CONTRACT = [
|
|
46803
|
-
"Pi conversation source contract:",
|
|
46804
|
-
"A message marked source:'extension' was injected by the Overdeck orchestrator or another agent, not typed by the human operator.",
|
|
46805
|
-
"Treat it as coordination guidance; do not attribute it to the human operator."
|
|
46806
|
-
].join(" ");
|
|
46807
|
-
async function resolveAllowedHarness(requested, model) {
|
|
46808
|
-
if (!model) return "claude-code";
|
|
46809
|
-
return resolveHarness({
|
|
46810
|
-
model,
|
|
46811
|
-
explicit: requested === "ohmypi" || requested === "claude-code" || requested === "codex" ? requested : void 0
|
|
46812
|
-
});
|
|
46813
|
-
}
|
|
46814
|
-
async function isInsideGitWorkTree(dir) {
|
|
46815
|
-
try {
|
|
46816
|
-
const { stdout } = await execAsync$3("git rev-parse --is-inside-work-tree", {
|
|
46817
|
-
cwd: dir,
|
|
46818
|
-
encoding: "utf-8"
|
|
46819
|
-
});
|
|
46820
|
-
return stdout.trim() === "true";
|
|
46821
|
-
} catch {
|
|
46822
|
-
return false;
|
|
46823
|
-
}
|
|
46824
|
-
}
|
|
46825
|
-
async function validateCwdContainment$1(cwd) {
|
|
46826
|
-
if (!cwd.startsWith("/")) return false;
|
|
46827
|
-
if (cwd.split("/").filter(Boolean).includes("..")) return false;
|
|
46828
|
-
try {
|
|
46829
|
-
const resolved = await realpath(cwd);
|
|
46830
|
-
if (!(await stat$1(resolved)).isDirectory()) return false;
|
|
46831
|
-
const home = homedir$1();
|
|
46832
|
-
return resolved.startsWith(`${home}/`) || resolved === home;
|
|
46833
|
-
} catch {
|
|
46834
|
-
return false;
|
|
46835
|
-
}
|
|
46836
|
-
}
|
|
46837
|
-
async function waitForClaudeReady(tmuxSession) {
|
|
46838
|
-
const deadline = Date.now() + 3e4;
|
|
46839
|
-
while (Date.now() < deadline) {
|
|
46840
|
-
if ((await Effect.runPromise(capturePane(tmuxSession, 200))).includes("❯")) {
|
|
46841
|
-
console.log(`[conversations] Claude Code ready in ${tmuxSession}`);
|
|
46842
|
-
return;
|
|
46843
|
-
}
|
|
46844
|
-
await new Promise((r) => setTimeout(r, 500));
|
|
46845
|
-
}
|
|
46846
|
-
console.warn(`[conversations] Timed out waiting for Claude Code prompt in ${tmuxSession}`);
|
|
46847
|
-
}
|
|
46848
|
-
function isPiTuiInputReady(snapshot) {
|
|
46849
|
-
return /^\s*[❯›>]\s/m.test(snapshot) || /(?:^|\s)0(?:\.\d+)?%\s+context\s+used\b/i.test(snapshot) || /⬢[^\n]*◕/.test(snapshot);
|
|
46850
|
-
}
|
|
46851
|
-
async function waitForPiTuiReady(tmuxSession, timeoutMs = 6e4) {
|
|
46852
|
-
const deadline = Date.now() + timeoutMs;
|
|
46853
|
-
while (Date.now() < deadline) {
|
|
46854
|
-
if (isPiTuiInputReady(await Effect.runPromise(capturePane(tmuxSession, 40).pipe(Effect.catch(() => Effect.succeed("")))))) {
|
|
46855
|
-
console.log(`[conversations] Pi TUI ready for ${tmuxSession}`);
|
|
46856
|
-
return true;
|
|
46857
|
-
}
|
|
46858
|
-
await new Promise((r) => setTimeout(r, 250));
|
|
46859
|
-
}
|
|
46860
|
-
console.warn(`[conversations] Timed out waiting for Pi TUI to render in ${tmuxSession}`);
|
|
46861
|
-
return false;
|
|
46862
|
-
}
|
|
46863
|
-
function shouldReportUnresolvedLiveSession(conv) {
|
|
46864
|
-
if (!conv || conv.status !== "active") return false;
|
|
46865
|
-
return getHarnessBehavior(conv.harness).transcriptKind === "claude-jsonl";
|
|
46866
|
-
}
|
|
46867
|
-
function conversationSessionAliveFromState(conv, tmuxSessionAlive) {
|
|
46868
|
-
return conv.status === "active" && !conv.forkStatus && tmuxSessionAlive;
|
|
46869
|
-
}
|
|
46870
|
-
function conversationNeedsRunningRepair(conv, tmuxSessionAlive, harnessProcessAlive) {
|
|
46871
|
-
return conv.status === "ended" && !conv.forkStatus && tmuxSessionAlive && harnessProcessAlive;
|
|
46872
|
-
}
|
|
46873
|
-
/** Generate a default conversation name, e.g. 20260404-1234 */
|
|
46874
|
-
function generateConversationName() {
|
|
46875
|
-
return `${(/* @__PURE__ */ new Date()).toISOString().slice(0, 10).replace(/-/g, "")}-${Math.floor(Math.random() * 9e3 + 1e3)}`;
|
|
46876
|
-
}
|
|
46877
|
-
async function tmuxSessionExists(sessionName) {
|
|
46878
|
-
return Effect.runPromise(sessionExists(sessionName));
|
|
46879
|
-
}
|
|
46880
|
-
async function waitForTmuxSession(sessionName, timeoutMs = 3e4) {
|
|
46881
|
-
const start = Date.now();
|
|
46882
|
-
while (Date.now() - start < timeoutMs) {
|
|
46883
|
-
if (await Effect.runPromise(sessionExists(sessionName))) return;
|
|
46884
|
-
await new Promise((r) => setTimeout(r, 250));
|
|
46885
|
-
}
|
|
46886
|
-
throw new Error(`Timed out waiting for tmux session ${sessionName}`);
|
|
46887
|
-
}
|
|
46888
|
-
function shouldUseSupervisorForConversation(harness) {
|
|
46889
|
-
return getHarnessBehavior(harness).supportsPtySupervisor && process.env.OVERDECK_DOCKER_WORKSPACE !== "1" && process.env.PAN_DOCKER !== "1";
|
|
46890
|
-
}
|
|
46891
|
-
async function waitForConversationRuntimeReady(tmuxSession, harness, mode) {
|
|
46892
|
-
const transcriptKind = getHarnessBehavior(harness).transcriptKind;
|
|
46893
|
-
if (transcriptKind === "ohmypi-jsonl") {
|
|
46894
|
-
if (!await waitForPiTuiReady(tmuxSession)) throw new Error(`Pi (ohmypi) did not become interactive in ${tmuxSession} within the startup window — MCP server connections are likely still in progress. Retry once MCP servers finish connecting, or check ~/.claude/mcp.json for a slow/hanging server.`);
|
|
46895
|
-
} else if (transcriptKind !== "codex-rollout-jsonl" && mode === "spawn") {
|
|
46896
|
-
await waitForClaudeReady(tmuxSession);
|
|
46897
|
-
console.log(`[conversations] Claude ready in ${tmuxSession}`);
|
|
46898
|
-
} else if (transcriptKind !== "codex-rollout-jsonl") await waitForReadySignal(tmuxSession, 30);
|
|
46899
|
-
}
|
|
46900
|
-
async function handleConversationSwitchModel(name, body) {
|
|
46901
|
-
const conv = getConversationByName(name);
|
|
46902
|
-
if (!conv) return jsonResponse({ error: "Conversation not found" }, { status: 404 });
|
|
46903
|
-
const model = typeof body["model"] === "string" && body["model"].trim() ? body["model"].trim() : conv.model ?? void 0;
|
|
46904
|
-
const currentHarness = conv.harness ?? "claude-code";
|
|
46905
|
-
const requestedHarness = body["harness"];
|
|
46906
|
-
let harness = currentHarness;
|
|
46907
|
-
if (requestedHarness === "ohmypi" || requestedHarness === "pi" || requestedHarness === "claude-code" || requestedHarness === "codex") {
|
|
46908
|
-
const requestedRuntime = requestedHarness === "pi" ? "ohmypi" : requestedHarness;
|
|
46909
|
-
if (requestedRuntime !== currentHarness) {
|
|
46910
|
-
const policyModel = model ?? conv.model ?? "";
|
|
46911
|
-
const decision = canUseHarnessSync(requestedRuntime, policyModel, await getProviderAuthMode(policyModel));
|
|
46912
|
-
if (!decision.allowed) return jsonResponse({ error: decision.reason ?? "Harness not allowed for this model" }, { status: 400 });
|
|
46913
|
-
}
|
|
46914
|
-
harness = requestedRuntime;
|
|
46915
|
-
}
|
|
46916
|
-
const harnessChanged = harness !== currentHarness;
|
|
46917
|
-
if (!await validateCwdContainment$1(conv.cwd)) return jsonResponse({ error: "Invalid cwd" }, { status: 400 });
|
|
46918
|
-
if (model && !SAFE_MODEL_PATTERN$1.test(model)) return jsonResponse({ error: "Invalid model" }, { status: 400 });
|
|
46919
|
-
const livePiSwitch = isPiControlChannelHarness(currentHarness) && conv.status !== "ended";
|
|
46920
|
-
if (conv.claudeSessionId && harnessChanged) return jsonResponse({ error: "Conversation harness is locked once a conversation has started" }, { status: 409 });
|
|
46921
|
-
if (conv.claudeSessionId && !livePiSwitch) return jsonResponse({ error: "Conversation model is locked once a conversation has started" }, { status: 409 });
|
|
46922
|
-
if (model) {
|
|
46923
|
-
if (livePiSwitch) await sendConversationControlCommand(conv, {
|
|
46924
|
-
type: "set_model",
|
|
46925
|
-
model
|
|
46926
|
-
});
|
|
46927
|
-
setConversationModel(name, model);
|
|
46928
|
-
}
|
|
46929
|
-
if (harnessChanged) setConversationHarness(name, harness);
|
|
46930
|
-
const updated = getConversationByName(name) ?? conv;
|
|
46931
|
-
return jsonResponse({
|
|
46932
|
-
...updated,
|
|
46933
|
-
model: model ?? updated.model,
|
|
46934
|
-
harness,
|
|
46935
|
-
sessionAlive: false
|
|
46936
|
-
});
|
|
46937
|
-
}
|
|
46938
|
-
function getPtySupervisorSocketPath(agentId) {
|
|
46939
|
-
return join(getOverdeckHome(), "sockets", `pty-${agentId}.sock`);
|
|
46940
|
-
}
|
|
46941
|
-
async function waitForPtySupervisorSocket(agentId, timeoutMs = PTY_SUPERVISOR_SOCKET_WAIT_MS) {
|
|
46942
|
-
const socketPath = getPtySupervisorSocketPath(agentId);
|
|
46943
|
-
const start = Date.now();
|
|
46944
|
-
while (Date.now() - start < timeoutMs) {
|
|
46945
|
-
try {
|
|
46946
|
-
if (((await stat$1(socketPath)).mode & 511) === 384) return;
|
|
46947
|
-
} catch {}
|
|
46948
|
-
await new Promise((r) => setTimeout(r, 250));
|
|
46949
|
-
}
|
|
46950
|
-
throw new Error(`Timed out waiting for PTY supervisor socket ${socketPath}`);
|
|
46951
|
-
}
|
|
46952
|
-
async function extractModelFromSessionFile(sessionFile) {
|
|
46953
|
-
try {
|
|
46954
|
-
if (!existsSync$1(sessionFile)) return null;
|
|
46955
|
-
const stream = createReadStream$1(sessionFile, { encoding: "utf-8" });
|
|
46956
|
-
const rl = createInterface$1({
|
|
46957
|
-
input: stream,
|
|
46958
|
-
crlfDelay: Infinity
|
|
46959
|
-
});
|
|
46960
|
-
try {
|
|
46961
|
-
for await (const line of rl) {
|
|
46962
|
-
if (!line.trim()) continue;
|
|
46963
|
-
const entry = JSON.parse(line);
|
|
46964
|
-
if (entry.type === "assistant" && entry.message?.model) return entry.message.model;
|
|
46965
|
-
}
|
|
46966
|
-
} finally {
|
|
46967
|
-
rl.close();
|
|
46968
|
-
stream.destroy();
|
|
46969
|
-
}
|
|
46970
|
-
} catch {}
|
|
46971
|
-
return null;
|
|
46972
|
-
}
|
|
46973
|
-
let backfillRunning = false;
|
|
46974
|
-
async function backfillConversationModels(resolveSessionFile) {
|
|
46975
|
-
if (backfillRunning) return;
|
|
46976
|
-
backfillRunning = true;
|
|
46977
|
-
try {
|
|
46978
|
-
const convs = listConversations();
|
|
46979
|
-
const probe = await Promise.all(convs.map(async (conv) => !conv.model ? await resolveSessionFile(conv) : null));
|
|
46980
|
-
const candidates = convs.filter((_, i) => probe[i] !== null);
|
|
46981
|
-
const BATCH_SIZE = 10;
|
|
46982
|
-
let backfilled = 0;
|
|
46983
|
-
for (let i = 0; i < candidates.length; i += BATCH_SIZE) {
|
|
46984
|
-
const batch = candidates.slice(i, i + BATCH_SIZE);
|
|
46985
|
-
const results = await Promise.all(batch.map(async (conv) => {
|
|
46986
|
-
const sessionFile = await resolveSessionFile(conv);
|
|
46987
|
-
if (!sessionFile) return false;
|
|
46988
|
-
const model = await extractModelFromSessionFile(sessionFile);
|
|
46989
|
-
if (model && SAFE_MODEL_PATTERN$1.test(model)) {
|
|
46990
|
-
backfillConversationModel(conv.name, model);
|
|
46991
|
-
return true;
|
|
46992
|
-
}
|
|
46993
|
-
return false;
|
|
46994
|
-
}));
|
|
46995
|
-
backfilled += results.filter(Boolean).length;
|
|
46996
|
-
}
|
|
46997
|
-
if (backfilled > 0) console.log(`[conversations] Backfilled model for ${backfilled} conversation(s)`);
|
|
46998
|
-
} finally {
|
|
46999
|
-
backfillRunning = false;
|
|
47000
|
-
}
|
|
47001
|
-
}
|
|
47002
|
-
function startConversationModelBackfill(resolveSessionFile) {
|
|
47003
|
-
backfillConversationModels(resolveSessionFile).catch((err) => {
|
|
47004
|
-
console.error("[conversations] Model backfill failed:", err);
|
|
47005
|
-
});
|
|
47006
|
-
}
|
|
47007
|
-
async function claudeConversationSystemPromptFiles(cwd) {
|
|
47008
|
-
const files = [];
|
|
47009
|
-
const contextFile = workspaceContextFile(cwd);
|
|
47010
|
-
try {
|
|
47011
|
-
await stat$1(contextFile);
|
|
47012
|
-
files.push(contextFile);
|
|
47013
|
-
} catch (error) {
|
|
47014
|
-
if (!isNotFound(error)) throw error;
|
|
47015
|
-
}
|
|
47016
|
-
files.push(await ensureSessionContextBriefingFile());
|
|
47017
|
-
return files;
|
|
47018
|
-
}
|
|
47019
|
-
async function ensurePiConversationSourceContractFile() {
|
|
47020
|
-
const contextDir = join(getOverdeckHome(), "context");
|
|
47021
|
-
await mkdir(contextDir, { recursive: true });
|
|
47022
|
-
const path = join(contextDir, "pi-conversation-source-contract.md");
|
|
47023
|
-
await writeFile(path, `${PI_CONVERSATION_SOURCE_CONTRACT}\n`, "utf-8");
|
|
47024
|
-
return path;
|
|
47025
|
-
}
|
|
47026
|
-
async function piConversationSystemPromptFiles(cwd) {
|
|
47027
|
-
const files = [];
|
|
47028
|
-
const globalFile = piGlobalContextFile();
|
|
47029
|
-
try {
|
|
47030
|
-
await stat$1(globalFile);
|
|
47031
|
-
files.push(globalFile);
|
|
47032
|
-
} catch (error) {
|
|
47033
|
-
if (!isNotFound(error)) throw error;
|
|
47034
|
-
}
|
|
47035
|
-
files.push(await ensurePiConversationSourceContractFile());
|
|
47036
|
-
const contextFile = workspaceContextFile(cwd);
|
|
47037
|
-
try {
|
|
47038
|
-
await stat$1(contextFile);
|
|
47039
|
-
files.push(contextFile);
|
|
47040
|
-
} catch (error) {
|
|
47041
|
-
if (!isNotFound(error)) throw error;
|
|
47042
|
-
}
|
|
47043
|
-
files.push(await ensureSessionContextBriefingFile());
|
|
47044
|
-
return files;
|
|
47045
|
-
}
|
|
47046
|
-
function isNotFound(error) {
|
|
47047
|
-
return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
|
|
47048
|
-
}
|
|
47049
|
-
async function spawnConversationSession(tmuxSession, cwd, claudeSessionId, model, effort, issueId, resume = false, harness = "claude-code", plainFork = false) {
|
|
47050
|
-
const behavior = getHarnessBehavior(harness);
|
|
47051
|
-
const stateDir = join(getOverdeckHome(), "conversations", tmuxSession);
|
|
47052
|
-
await mkdir(stateDir, { recursive: true });
|
|
47053
|
-
clearReadySignal(tmuxSession);
|
|
47054
|
-
const launcherScript = join(stateDir, "launcher.sh");
|
|
47055
|
-
let runtimeCommand = `claude ${getClaudePermissionFlagsStringSync()}`;
|
|
47056
|
-
let providerExportsStr = "";
|
|
47057
|
-
let piFields;
|
|
47058
|
-
let codexFields;
|
|
47059
|
-
if (model) {
|
|
47060
|
-
if (!SAFE_MODEL_PATTERN$1.test(model)) throw new Error("Invalid model name");
|
|
47061
|
-
runtimeCommand = await getAgentRuntimeBaseCommand(model, void 0, void 0, harness);
|
|
47062
|
-
const mode = resolvePermissionModeSync();
|
|
47063
|
-
if (!runtimeCommand.includes("--permission-mode")) runtimeCommand = `${runtimeCommand} --permission-mode ${mode === "auto" ? "auto" : BYPASS_PERMISSION_MODE}`;
|
|
47064
|
-
providerExportsStr = (await getProviderExportsForModel(model)).trim();
|
|
47065
|
-
await getProviderEnvForModel(model);
|
|
47066
|
-
if (behavior.transcriptKind === "ohmypi-jsonl") {
|
|
47067
|
-
if (getProviderForModelSync(model).name === "openai") {
|
|
47068
|
-
const auth = await getOhmypiCodexAuthStatus({ refreshIfExpired: true });
|
|
47069
|
-
if (auth.status === "missing" || auth.status === "expired") throw new Error("ohmypi ChatGPT/Codex login (openai-codex) has expired and could not be refreshed. Re-authenticate with `pan pi-auth login`, then retry.");
|
|
47070
|
-
}
|
|
47071
|
-
const paths = piFifoPaths(tmuxSession);
|
|
47072
|
-
const piSessionDir = join(paths.agentDir, "sessions");
|
|
47073
|
-
await mkdir(paths.agentDir, {
|
|
47074
|
-
recursive: true,
|
|
47075
|
-
mode: 448
|
|
47076
|
-
});
|
|
47077
|
-
await mkdir(piSessionDir, {
|
|
47078
|
-
recursive: true,
|
|
47079
|
-
mode: 448
|
|
47080
|
-
});
|
|
47081
|
-
const storedPiSessionId = resume ? await readFile(join(paths.agentDir, "session.id"), "utf-8").then((s) => s.trim()).catch(() => void 0) : void 0;
|
|
47082
|
-
piFields = {
|
|
47083
|
-
harness: "ohmypi",
|
|
47084
|
-
piMode: "tui",
|
|
47085
|
-
piExtensionPath: resolveOhmypiExtensionPath() ?? resolve(process.cwd(), "packages/ohmypi-extension/dist/index.js"),
|
|
47086
|
-
piSessionDir,
|
|
47087
|
-
resumeSessionId: storedPiSessionId || void 0
|
|
47088
|
-
};
|
|
47089
|
-
} else if (behavior.usesCodexHome) {
|
|
47090
|
-
const codexHome = join(getOverdeckHome(), "agents", tmuxSession, "codex-home");
|
|
47091
|
-
const codexPermMode = loadConfigSync().config.codex?.permissionMode ?? "workspace";
|
|
47092
|
-
const codexApprovalPolicy = codexPermMode === "full-access" ? "never" : "on-request";
|
|
47093
|
-
const codexSandboxMode = codexPermMode === "full-access" ? "danger-full-access" : codexPermMode === "read-only" ? "read-only" : "workspace-write";
|
|
47094
|
-
const codexApprovalsReviewer = codexPermMode === "auto-review" ? "auto_review" : void 0;
|
|
47095
|
-
const { initCodexHome, extractThreadIdFromRollout } = await import("./codex-B7DTpwEw.js");
|
|
47096
|
-
initCodexHome(codexHome, {
|
|
47097
|
-
trustedDir: cwd,
|
|
47098
|
-
approvalPolicy: codexApprovalPolicy,
|
|
47099
|
-
sandboxMode: codexSandboxMode,
|
|
47100
|
-
approvalsReviewer: codexApprovalsReviewer
|
|
47101
|
-
});
|
|
47102
|
-
const resumeSessionId = resume ? await resolveCodexRolloutPath(tmuxSession, { agentsDirOverride: join(getOverdeckHome(), "agents") }).then((rollout) => rollout ? extractThreadIdFromRollout(rollout) ?? void 0 : void 0) : void 0;
|
|
47103
|
-
codexFields = {
|
|
47104
|
-
harness: "codex",
|
|
47105
|
-
codexMode: "tui",
|
|
47106
|
-
codexHome,
|
|
47107
|
-
codexSessionDir: join(codexHome, "sessions"),
|
|
47108
|
-
resumeSessionId
|
|
47109
|
-
};
|
|
47110
|
-
}
|
|
47111
|
-
}
|
|
47112
|
-
let launcherModel = model;
|
|
47113
|
-
if (behavior.contextLayerKind === "pi" && model) {
|
|
47114
|
-
const piProvider = piProviderForModel(model);
|
|
47115
|
-
if (piProvider) launcherModel = `${piProvider}/${model}`;
|
|
47116
|
-
}
|
|
47117
|
-
if (effort && !SAFE_EFFORT_PATTERN.test(effort)) throw new Error("Invalid effort level");
|
|
47118
|
-
const useSupervisor = shouldUseSupervisorForConversation(harness);
|
|
47119
|
-
let supervisorScriptPath;
|
|
47120
|
-
if (useSupervisor) {
|
|
47121
|
-
supervisorScriptPath = resolvePtySupervisorScriptPath();
|
|
47122
|
-
await writePtyToken(tmuxSession);
|
|
47123
|
-
}
|
|
47124
|
-
let channelsBridgeMcpConfig;
|
|
47125
|
-
if (!piFields && !codexFields && !plainFork && isClaudeCodeChannelsEnabled() && (!model || getProviderForModelSync(model).name === "anthropic") && process.env.CLAUDE_CODE_USE_BEDROCK !== "1" && process.env.CLAUDE_CODE_USE_VERTEX !== "1" && process.env.CLAUDE_CODE_USE_FOUNDRY !== "1" && process.env.OVERDECK_DOCKER_WORKSPACE !== "1" && process.env.PAN_DOCKER !== "1") {
|
|
47126
|
-
channelsBridgeMcpConfig = join(stateDir, "agent-mcp.json");
|
|
47127
|
-
writeBridgeTokenSync(tmuxSession);
|
|
47128
|
-
await writeChannelsBridgeMcpConfig(channelsBridgeMcpConfig, tmuxSession);
|
|
47129
|
-
}
|
|
47130
|
-
const launcherTmp = `${launcherScript}.${randomUUID$1()}.tmp`;
|
|
47131
|
-
await writeFile(launcherTmp, generateLauncherScriptSync({
|
|
47132
|
-
role: "work",
|
|
47133
|
-
spawnMode: "conversation",
|
|
47134
|
-
workingDir: cwd,
|
|
47135
|
-
setTerminalEnv: true,
|
|
47136
|
-
unsetProviderEnv: true,
|
|
47137
|
-
overdeckEnv: {
|
|
47138
|
-
...issueId ? { issueId } : {},
|
|
47139
|
-
...piFields || codexFields || useSupervisor ? { agentId: tmuxSession } : {}
|
|
47140
|
-
},
|
|
47141
|
-
extraEnvExports: [`export OVERDECK_DASHBOARD_URL="http://127.0.0.1:${process.env["API_PORT"] ?? process.env["PORT"] ?? "3011"}"`],
|
|
47142
|
-
providerExports: providerExportsStr || void 0,
|
|
47143
|
-
trapHup: true,
|
|
47144
|
-
baseCommand: runtimeCommand,
|
|
47145
|
-
appendSystemPromptFiles: piFields ? await piConversationSystemPromptFiles(cwd) : codexFields ? [] : await claudeConversationSystemPromptFiles(cwd),
|
|
47146
|
-
model: launcherModel,
|
|
47147
|
-
...piFields ?? codexFields ?? {
|
|
47148
|
-
resumeSessionId: resume ? claudeSessionId : void 0,
|
|
47149
|
-
sessionId: resume ? void 0 : claudeSessionId
|
|
47150
|
-
},
|
|
47151
|
-
extraArgs: !piFields && effort ? `--effort "${effort}"` : void 0,
|
|
47152
|
-
keepAlive: true,
|
|
47153
|
-
fileMode: 448,
|
|
47154
|
-
channelsBridgeMcpConfig,
|
|
47155
|
-
useSupervisor,
|
|
47156
|
-
supervisorScriptPath
|
|
47157
|
-
}), { mode: 448 });
|
|
47158
|
-
await rename(launcherTmp, launcherScript);
|
|
47159
|
-
try {
|
|
47160
|
-
await Effect.runPromise(killSession(tmuxSession));
|
|
47161
|
-
} catch {}
|
|
47162
|
-
console.log(`[claude-invoke] purpose=conversation-session | model=${model || "default"} | source=conversations.ts:spawnConversationSession | session=${tmuxSession} | resume=${resume} | command="${runtimeCommand}"`);
|
|
47163
|
-
try {
|
|
47164
|
-
const { preTrustDirectory } = await import("./workspace-manager-DjUAJCSs.js");
|
|
47165
|
-
preTrustDirectory(cwd);
|
|
47166
|
-
} catch {}
|
|
47167
|
-
try {
|
|
47168
|
-
await Effect.runPromise(createSession(tmuxSession, cwd, `bash ${shellQuote(launcherScript)}`, { env: {
|
|
47169
|
-
...BLANKED_PROVIDER_ENV,
|
|
47170
|
-
TERM: "xterm-256color"
|
|
47171
|
-
} }));
|
|
47172
|
-
} catch (err) {
|
|
47173
|
-
if (err?.code === "ENOENT") throw new Error("tmux is not installed. Install it with: brew install tmux (macOS) or sudo apt-get install tmux (Linux)");
|
|
47174
|
-
throw err;
|
|
47175
|
-
}
|
|
47176
|
-
if (useSupervisor) await waitForPtySupervisorSocket(tmuxSession);
|
|
47177
|
-
if (behavior.usesCodexHome && codexFields?.codexHome) {
|
|
47178
|
-
const codexHomeDir = codexFields.codexHome;
|
|
47179
|
-
(async () => {
|
|
47180
|
-
try {
|
|
47181
|
-
const { waitForCodexRollout, extractThreadIdFromRollout, writeThreadId } = await import("./codex-B7DTpwEw.js");
|
|
47182
|
-
const rollout = await waitForCodexRollout(codexHomeDir, 12e4);
|
|
47183
|
-
if (rollout) {
|
|
47184
|
-
const threadId = extractThreadIdFromRollout(rollout);
|
|
47185
|
-
if (threadId) writeThreadId(tmuxSession, threadId);
|
|
47186
|
-
}
|
|
47187
|
-
} catch {}
|
|
47188
|
-
})();
|
|
47189
|
-
}
|
|
47190
|
-
if (channelsBridgeMcpConfig) dismissDevChannelsDialog(tmuxSession).catch((err) => {
|
|
47191
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
47192
|
-
console.error(`[conversations] dismissDevChannelsDialog failed for ${tmuxSession}: ${msg}`);
|
|
47193
|
-
});
|
|
47194
|
-
await Effect.runPromise(setOption(tmuxSession, "destroy-unattached", "off"));
|
|
47195
|
-
await Effect.runPromise(setOption(exactPaneTarget(tmuxSession), "remain-on-exit", "on"));
|
|
47196
|
-
}
|
|
47197
|
-
/**
|
|
47198
|
-
* Resolve a conversation's cwd from a project identifier.
|
|
47199
|
-
*
|
|
47200
|
-
* The Command Deck identifies projects by display name, not yaml key
|
|
47201
|
-
* (PAN-2590) — accept either, like GET /api/session-trees does.
|
|
47202
|
-
*/
|
|
47203
|
-
function resolveProjectCwd(projectKey) {
|
|
47204
|
-
const projectConfig = getProjectSync(projectKey) ?? listProjectsSync().find((p) => p.config.name === projectKey)?.config ?? null;
|
|
47205
|
-
if (!projectConfig) return { error: `Unknown project: ${projectKey}` };
|
|
47206
|
-
if (!projectConfig.path || !existsSync$1(projectConfig.path)) return { error: `Project path does not exist: ${projectConfig.path || "(unset)"} (project: ${projectKey})` };
|
|
47207
|
-
return { cwd: projectConfig.path };
|
|
47208
|
-
}
|
|
47209
|
-
async function handleConversationCreate(body, deps) {
|
|
47210
|
-
try {
|
|
47211
|
-
const message = typeof body["message"] === "string" ? body["message"].trim() : "";
|
|
47212
|
-
const model = typeof body["model"] === "string" ? body["model"].trim() : void 0;
|
|
47213
|
-
const effort = typeof body["effort"] === "string" ? body["effort"].trim() : void 0;
|
|
47214
|
-
const harness = await resolveAllowedHarness(body["harness"], model);
|
|
47215
|
-
const issueId = typeof body["issueId"] === "string" ? body["issueId"] : void 0;
|
|
47216
|
-
const projectKey = typeof body["projectKey"] === "string" ? body["projectKey"].trim() : void 0;
|
|
47217
|
-
if (issueId && !SAFE_ISSUE_ID_PATTERN.test(issueId)) return jsonResponse({ error: "Invalid issueId" }, { status: 400 });
|
|
47218
|
-
if (model && !SAFE_MODEL_PATTERN$1.test(model)) return jsonResponse({ error: "Invalid model" }, { status: 400 });
|
|
47219
|
-
if (effort && !SAFE_EFFORT_PATTERN.test(effort)) return jsonResponse({ error: "Invalid effort" }, { status: 400 });
|
|
47220
|
-
let cwd = getDefaultCwd();
|
|
47221
|
-
if (projectKey) {
|
|
47222
|
-
const resolved = resolveProjectCwd(projectKey);
|
|
47223
|
-
if ("error" in resolved) return jsonResponse({ error: resolved.error }, { status: 400 });
|
|
47224
|
-
cwd = resolved.cwd;
|
|
47225
|
-
}
|
|
47226
|
-
if (message && message.length > 5e4) return jsonResponse({ error: "message exceeds maximum length of 50000 characters" }, { status: 400 });
|
|
47227
|
-
let name = generateConversationName();
|
|
47228
|
-
for (let i = 0; i < 5 && getConversationByName(name); i++) name = generateConversationName();
|
|
47229
|
-
const tmuxSession = `conv-${name}`;
|
|
47230
|
-
const claudeSessionId = randomUUID$1();
|
|
47231
|
-
console.log(`[conversations] Creating conversation "${name}" with model=${model ?? "default"} effort=${effort ?? "default"} cwd=${cwd}`);
|
|
47232
|
-
const MAX_TITLE_LEN = 60;
|
|
47233
|
-
const title = message ? message.slice(0, MAX_TITLE_LEN) + (message.length > MAX_TITLE_LEN ? "…" : "") : "New conversation";
|
|
47234
|
-
const conv = createConversation({
|
|
47235
|
-
name,
|
|
47236
|
-
tmuxSession,
|
|
47237
|
-
cwd,
|
|
47238
|
-
issueId,
|
|
47239
|
-
claudeSessionId,
|
|
47240
|
-
title,
|
|
47241
|
-
titleSource: message ? "auto" : "default",
|
|
47242
|
-
titleSeed: title,
|
|
47243
|
-
model,
|
|
47244
|
-
effort,
|
|
47245
|
-
harness
|
|
47246
|
-
});
|
|
47247
|
-
getEventStore().emitOnly({
|
|
47248
|
-
type: "conversation.created",
|
|
47249
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
47250
|
-
payload: { conversationName: name }
|
|
47251
|
-
});
|
|
47252
|
-
(async () => {
|
|
47253
|
-
try {
|
|
47254
|
-
await spawnConversationSession(tmuxSession, cwd, claudeSessionId, model, effort, issueId, false, harness);
|
|
47255
|
-
console.log(`[conversations] tmux session ${tmuxSession} spawned, sessionId: ${claudeSessionId}`);
|
|
47256
|
-
await waitForConversationRuntimeReady(tmuxSession, harness, "spawn");
|
|
47257
|
-
if (message) await deliverAgentMessage(tmuxSession, message, "conversation-message", resolveConversationDeliveryMethod(conv));
|
|
47258
|
-
} catch (spawnErr) {
|
|
47259
|
-
const msg = spawnErr instanceof Error ? spawnErr.message : String(spawnErr);
|
|
47260
|
-
console.error(`[conversations] background spawn failed for ${tmuxSession}: ${msg}`);
|
|
47261
|
-
updateSpawnError(name, msg);
|
|
47262
|
-
getEventStore().emitOnly({
|
|
47263
|
-
type: "conversation.created",
|
|
47264
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
47265
|
-
payload: { conversationName: name }
|
|
47266
|
-
});
|
|
47267
|
-
}
|
|
47268
|
-
})();
|
|
47269
|
-
if (message) deps.generateAiTitle(name, message).catch((err) => {
|
|
47270
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
47271
|
-
console.error(`[TITLE-GEN-FAILED] AI title generation FAILED for "${name}" — NO RETRY, NO FALLBACK:`, msg);
|
|
47272
|
-
});
|
|
47273
|
-
return jsonResponse({
|
|
47274
|
-
...conv,
|
|
47275
|
-
sessionAlive: false
|
|
47276
|
-
}, { status: 201 });
|
|
47277
|
-
} catch (error) {
|
|
47278
|
-
const msg = error instanceof Error ? error.message : String(error);
|
|
47279
|
-
console.error("[conversations] create conversation failed:", msg);
|
|
47280
|
-
return jsonResponse({ error: msg || "Internal server error" }, { status: error instanceof UnknownModelError ? 400 : 500 });
|
|
47281
|
-
}
|
|
47282
|
-
}
|
|
47283
|
-
async function handleConversationStop(name, deps) {
|
|
47284
|
-
try {
|
|
47285
|
-
const conv = getConversationByName(name);
|
|
47286
|
-
if (!conv) return jsonResponse({ error: "Conversation not found" }, { status: 404 });
|
|
47287
|
-
await stopConversationRuntime(conv, name);
|
|
47288
|
-
markConversationEnded(name);
|
|
47289
|
-
(async () => {
|
|
47290
|
-
await new Promise((r) => setTimeout(r, 500));
|
|
47291
|
-
await cleanupUnreferencedConversationAttachments({
|
|
47292
|
-
name: conv.name,
|
|
47293
|
-
sessionFile: deps.resolveSessionFileForCleanup?.(conv) ?? null
|
|
47294
|
-
});
|
|
47295
|
-
})();
|
|
47296
|
-
return jsonResponse({ success: true });
|
|
47297
|
-
} catch (error) {
|
|
47298
|
-
const msg = error instanceof Error ? error.message : String(error);
|
|
47299
|
-
console.error("[conversations] stop conversation failed:", msg);
|
|
47300
|
-
return jsonResponse({ error: "Internal server error" }, { status: 500 });
|
|
47301
|
-
}
|
|
47302
|
-
}
|
|
47303
|
-
async function handleConversationResume(name, body, deps) {
|
|
47304
|
-
try {
|
|
47305
|
-
const conv = getConversationByName(name);
|
|
47306
|
-
if (!conv) return jsonResponse({ error: "Conversation not found" }, { status: 404 });
|
|
47307
|
-
const model = typeof body["model"] === "string" && body["model"].trim() ? body["model"].trim() : conv.model ?? void 0;
|
|
47308
|
-
const effort = typeof body["effort"] === "string" && body["effort"].trim() ? body["effort"].trim() : conv.effort ?? void 0;
|
|
47309
|
-
if (await isHarnessProcessAlive(conv.tmuxSession)) {
|
|
47310
|
-
updateLastAttached(name);
|
|
47311
|
-
markConversationActive(name);
|
|
47312
|
-
return jsonResponse({
|
|
47313
|
-
...conv,
|
|
47314
|
-
status: "active",
|
|
47315
|
-
reattached: true
|
|
47316
|
-
});
|
|
47317
|
-
}
|
|
47318
|
-
const oldSessionId = conv.claudeSessionId;
|
|
47319
|
-
const harness = conv.harness ?? "claude-code";
|
|
47320
|
-
const modelChanged = !!model && model !== conv.model;
|
|
47321
|
-
if (!await validateCwdContainment$1(conv.cwd)) return jsonResponse({ error: "Invalid cwd" }, { status: 400 });
|
|
47322
|
-
if (model && modelChanged && !SAFE_MODEL_PATTERN$1.test(model)) return jsonResponse({ error: "Invalid model" }, { status: 400 });
|
|
47323
|
-
if (model && modelChanged) setConversationModel(name, model);
|
|
47324
|
-
let canResume = !!oldSessionId;
|
|
47325
|
-
if (oldSessionId) {
|
|
47326
|
-
const resumeFile = await deps.resolveSessionFile(conv);
|
|
47327
|
-
if (!resumeFile || !existsSync$1(resumeFile)) {
|
|
47328
|
-
canResume = false;
|
|
47329
|
-
console.error(`[conversations] SESSION-LOST ${name} harness=${harness} claudeSessionId=${oldSessionId} resolved=${resumeFile ?? "null"} — resuming with a fresh session`);
|
|
47330
|
-
}
|
|
47331
|
-
}
|
|
47332
|
-
const respawn = markRespawnPending(conv.tmuxSession);
|
|
47333
|
-
try {
|
|
47334
|
-
await spawnConversationSession(conv.tmuxSession, conv.cwd, oldSessionId ?? randomUUID$1(), model, effort, conv.issueId ?? void 0, canResume, harness);
|
|
47335
|
-
await waitForTmuxSession(conv.tmuxSession);
|
|
47336
|
-
await waitForConversationRuntimeReady(conv.tmuxSession, harness, "respawn");
|
|
47337
|
-
markConversationActive(name);
|
|
47338
|
-
return jsonResponse({
|
|
47339
|
-
...conv,
|
|
47340
|
-
status: "active",
|
|
47341
|
-
model: model ?? conv.model,
|
|
47342
|
-
harness,
|
|
47343
|
-
reattached: false,
|
|
47344
|
-
sessionAlive: true
|
|
47345
|
-
});
|
|
47346
|
-
} finally {
|
|
47347
|
-
respawn.done();
|
|
47348
|
-
}
|
|
47349
|
-
} catch (error) {
|
|
47350
|
-
const msg = error instanceof Error ? error.message : String(error);
|
|
47351
|
-
console.error("[conversations] resume conversation failed:", msg);
|
|
47352
|
-
return jsonResponse({ error: msg || "Internal server error" }, { status: 500 });
|
|
47353
|
-
}
|
|
47354
|
-
}
|
|
47355
|
-
async function handleConversationDelete(name, deps) {
|
|
47356
|
-
try {
|
|
47357
|
-
const conv = getConversationByName(name);
|
|
47358
|
-
if (!conv) return jsonResponse({ error: "Conversation not found" }, { status: 404 });
|
|
47359
|
-
await stopConversationRuntime(conv, name);
|
|
47360
|
-
markConversationEnded(name);
|
|
47361
|
-
archiveConversation(name);
|
|
47362
|
-
removeFavorite("conversation", name);
|
|
47363
|
-
deps.invalidateFavoritesCache();
|
|
47364
|
-
await cleanupConversationAttachments(name);
|
|
47365
|
-
return jsonResponse({ success: true });
|
|
47366
|
-
} catch (error) {
|
|
47367
|
-
const msg = error instanceof Error ? error.message : String(error);
|
|
47368
|
-
console.error("[conversations] delete conversation failed:", msg);
|
|
47369
|
-
return jsonResponse({ error: "Internal server error" }, { status: 500 });
|
|
47370
|
-
}
|
|
47371
|
-
}
|
|
47372
|
-
async function handleConversationRestartAll(deps) {
|
|
47373
|
-
try {
|
|
47374
|
-
const allConvs = listConversations();
|
|
47375
|
-
const liveSessionNames = new Set(await Effect.runPromise(listSessionNames()));
|
|
47376
|
-
const convs = allConvs.filter((c) => liveSessionNames.has(c.tmuxSession));
|
|
47377
|
-
const results = [];
|
|
47378
|
-
for (const conv of convs) {
|
|
47379
|
-
const respawn = markRespawnPending(conv.tmuxSession);
|
|
47380
|
-
try {
|
|
47381
|
-
await Effect.runPromise(killSession(conv.tmuxSession).pipe(Effect.catch(() => Effect.succeed(void 0))));
|
|
47382
|
-
const oldSessionId = conv.claudeSessionId;
|
|
47383
|
-
const sessionFileForResume = await deps.resolveSessionFile(conv);
|
|
47384
|
-
const canResume = !!oldSessionId && !!sessionFileForResume && existsSync$1(sessionFileForResume);
|
|
47385
|
-
const harness = await resolveAllowedHarness(conv.harness, conv.model);
|
|
47386
|
-
await spawnConversationSession(conv.tmuxSession, conv.cwd, oldSessionId ?? randomUUID$1(), conv.model ?? void 0, conv.effort ?? void 0, conv.issueId ?? void 0, canResume, harness);
|
|
47387
|
-
setConversationHarness(conv.name, harness);
|
|
47388
|
-
markConversationActive(conv.name);
|
|
47389
|
-
results.push({
|
|
47390
|
-
name: conv.name,
|
|
47391
|
-
model: conv.model,
|
|
47392
|
-
status: "restarted"
|
|
47393
|
-
});
|
|
47394
|
-
} catch (err) {
|
|
47395
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
47396
|
-
console.error(`[conversations] Failed to restart ${conv.name}:`, msg);
|
|
47397
|
-
results.push({
|
|
47398
|
-
name: conv.name,
|
|
47399
|
-
model: conv.model,
|
|
47400
|
-
status: "failed"
|
|
47401
|
-
});
|
|
47402
|
-
} finally {
|
|
47403
|
-
respawn.done();
|
|
47404
|
-
}
|
|
47405
|
-
}
|
|
47406
|
-
console.log(`[conversations] Restarted ${results.filter((r) => r.status === "restarted").length}/${convs.length} conversations`);
|
|
47407
|
-
return jsonResponse({
|
|
47408
|
-
restarted: results.length,
|
|
47409
|
-
results
|
|
47410
|
-
});
|
|
47411
|
-
} catch (error) {
|
|
47412
|
-
const msg = error instanceof Error ? error.message : String(error);
|
|
47413
|
-
console.error("[conversations] restart conversations failed:", msg);
|
|
47414
|
-
return jsonResponse({ error: "Internal server error" }, { status: 500 });
|
|
47415
|
-
}
|
|
47416
|
-
}
|
|
47417
|
-
//#endregion
|
|
47418
46065
|
//#region ../../lib/overdeck/conversation-archive.ts
|
|
47419
46066
|
init_paths();
|
|
47420
46067
|
init_conversations();
|
|
@@ -48237,25 +46884,29 @@ async function getConversationsPendingInputFeed(deps) {
|
|
|
48237
46884
|
return result((await Effect.runPromise(withConcurrencyLimit(alive.map((conv) => Effect.promise(async () => {
|
|
48238
46885
|
const convSf = await deps.resolveSessionFile(conv);
|
|
48239
46886
|
let pending;
|
|
46887
|
+
let pendingPlan;
|
|
48240
46888
|
let lastActivityAt = null;
|
|
48241
46889
|
if (convSf && existsSync$1(convSf)) {
|
|
48242
46890
|
try {
|
|
48243
46891
|
lastActivityAt = new Date((await stat$1(convSf)).mtimeMs).toISOString();
|
|
48244
46892
|
} catch {}
|
|
48245
46893
|
try {
|
|
48246
|
-
|
|
46894
|
+
const scan = await scanPendingInputsPromise(convSf);
|
|
46895
|
+
pending = askUserQuestionSnapshotFromScan(scan);
|
|
46896
|
+
pendingPlan = scan.pendingProposedPlan;
|
|
48247
46897
|
} catch {}
|
|
48248
46898
|
}
|
|
48249
46899
|
if (!pending) {
|
|
48250
46900
|
const codex = await codexConversationPendingInput(conv, true, lastActivityAt ?? (/* @__PURE__ */ new Date()).toISOString());
|
|
48251
46901
|
if (codex.approval) pending = codex.approval;
|
|
48252
46902
|
}
|
|
48253
|
-
if (!pending) return null;
|
|
46903
|
+
if (!pending && !pendingPlan) return null;
|
|
48254
46904
|
return {
|
|
48255
46905
|
name: conv.name,
|
|
48256
46906
|
title: conv.title ?? null,
|
|
48257
46907
|
issueId: conv.issueId ?? null,
|
|
48258
|
-
pendingAskUserQuestion: pending
|
|
46908
|
+
...pending ? { pendingAskUserQuestion: pending } : {},
|
|
46909
|
+
...pendingPlan ? { pendingProposedPlan: pendingPlan } : {}
|
|
48259
46910
|
};
|
|
48260
46911
|
})), 8))).filter((row) => row !== null));
|
|
48261
46912
|
} catch (error) {
|
|
@@ -49174,7 +47825,7 @@ async function forkSpawnConversationSession(...args) {
|
|
|
49174
47825
|
return (forkPipelineRuntimeOverrides.spawnConversationSession ?? spawnConversationSession)(...args);
|
|
49175
47826
|
}
|
|
49176
47827
|
async function forkWaitForTmuxSession(...args) {
|
|
49177
|
-
return (forkPipelineRuntimeOverrides.waitForTmuxSession ?? waitForTmuxSession)(...args);
|
|
47828
|
+
return (forkPipelineRuntimeOverrides.waitForTmuxSession ?? waitForTmuxSession$1)(...args);
|
|
49178
47829
|
}
|
|
49179
47830
|
async function confirmForkPromptAccepted(tmuxSession, timeoutMs) {
|
|
49180
47831
|
const deadline = Date.now() + timeoutMs;
|
|
@@ -50209,7 +48860,7 @@ async function registerProjectFromPath(opts) {
|
|
|
50209
48860
|
registerProjectSync(key, projectConfig);
|
|
50210
48861
|
const seededContextLayer = ensureProjectLayer(fullPath);
|
|
50211
48862
|
try {
|
|
50212
|
-
const { preTrustDirectorySync } = await import("./workspace-manager-
|
|
48863
|
+
const { preTrustDirectorySync } = await import("./workspace-manager-BO-6k3sP.js");
|
|
50213
48864
|
preTrustDirectorySync(fullPath);
|
|
50214
48865
|
} catch {}
|
|
50215
48866
|
let hooksInstalled = 0;
|
|
@@ -50245,7 +48896,7 @@ init_pan_dir();
|
|
|
50245
48896
|
init_paths();
|
|
50246
48897
|
const execAsync$2 = promisify(exec);
|
|
50247
48898
|
async function getIssueDataService() {
|
|
50248
|
-
const { getSharedIssueService } = await import("./issue-service-singleton-
|
|
48899
|
+
const { getSharedIssueService } = await import("./issue-service-singleton-MZsDhAob.js");
|
|
50249
48900
|
return getSharedIssueService();
|
|
50250
48901
|
}
|
|
50251
48902
|
/** Returns true if the path exists (any type). */
|
|
@@ -50641,7 +49292,7 @@ const getProjectReleaseStatusRoute = HttpRouter.add("GET", "/api/projects/:proje
|
|
|
50641
49292
|
const projectKey = (yield* HttpRouter.params)["projectKey"] ?? "";
|
|
50642
49293
|
return jsonResponse(yield* Effect.tryPromise({
|
|
50643
49294
|
try: async () => {
|
|
50644
|
-
const { fetchProjectReleaseStatus } = await import("./project-pipelines-
|
|
49295
|
+
const { fetchProjectReleaseStatus } = await import("./project-pipelines-jMTitpeO.js");
|
|
50645
49296
|
return fetchProjectReleaseStatus(projectKey);
|
|
50646
49297
|
},
|
|
50647
49298
|
catch: (err) => new Error(err instanceof Error ? err.message : String(err))
|
|
@@ -50793,7 +49444,7 @@ const PREVIEW_HARNESSES = [
|
|
|
50793
49444
|
"codex"
|
|
50794
49445
|
];
|
|
50795
49446
|
const FRONTMATTER_RE = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?/;
|
|
50796
|
-
const execFileAsync$
|
|
49447
|
+
const execFileAsync$3 = promisify(execFile);
|
|
50797
49448
|
const decodePreviewRequest = Schema.decodeUnknownSync(ContextPreviewRequest);
|
|
50798
49449
|
const decodeSaveRequest = Schema.decodeUnknownSync(ContextLayerSaveRequest);
|
|
50799
49450
|
function globalContextFile(overdeckHome = getOverdeckHome()) {
|
|
@@ -51123,7 +49774,7 @@ async function saveContextLayer(projects, requestOrTarget, maybeContentOrOverdec
|
|
|
51123
49774
|
};
|
|
51124
49775
|
}
|
|
51125
49776
|
async function runPanContextSync() {
|
|
51126
|
-
const { stdout, stderr } = await execFileAsync$
|
|
49777
|
+
const { stdout, stderr } = await execFileAsync$3("pan", ["context", "sync"], { encoding: "utf-8" });
|
|
51127
49778
|
return {
|
|
51128
49779
|
stdout,
|
|
51129
49780
|
stderr
|
|
@@ -51327,6 +49978,7 @@ const adminRouteLayer = Layer.mergeAll(getAdminTldrRoute, postAdminBackfillTitle
|
|
|
51327
49978
|
*/
|
|
51328
49979
|
init_platform();
|
|
51329
49980
|
const execAsync$1 = promisify(exec);
|
|
49981
|
+
const execFileAsync$2 = promisify(execFile);
|
|
51330
49982
|
const PREREQ_REGISTRY = {
|
|
51331
49983
|
addGitHubProject: ["gh"],
|
|
51332
49984
|
addGitLabProject: ["glab"],
|
|
@@ -51338,6 +49990,7 @@ const PREREQ_REGISTRY = {
|
|
|
51338
49990
|
"traefik"
|
|
51339
49991
|
],
|
|
51340
49992
|
enableBeads: ["bd"],
|
|
49993
|
+
runClaudeCodeHooks: ["jq"],
|
|
51341
49994
|
useClaudeCodeRoutedAgents: [],
|
|
51342
49995
|
useOxAgents: ["ox"]
|
|
51343
49996
|
};
|
|
@@ -51347,19 +50000,31 @@ const INSTALLABLE_TOOLS = [
|
|
|
51347
50000
|
"ttyd",
|
|
51348
50001
|
"mkcert",
|
|
51349
50002
|
"bd",
|
|
50003
|
+
"jq",
|
|
51350
50004
|
"ox"
|
|
51351
50005
|
];
|
|
51352
|
-
function checkCommand(cmd) {
|
|
50006
|
+
async function checkCommand(cmd, args = ["--version"]) {
|
|
51353
50007
|
try {
|
|
51354
|
-
|
|
50008
|
+
await execFileAsync$2(cmd, args, { timeout: 1e4 });
|
|
51355
50009
|
return true;
|
|
51356
50010
|
} catch {
|
|
51357
50011
|
return false;
|
|
51358
50012
|
}
|
|
51359
50013
|
}
|
|
51360
50014
|
async function isToolInstalled(tool) {
|
|
51361
|
-
if (tool === "
|
|
51362
|
-
if (tool === "
|
|
50015
|
+
if (tool === "docker") return checkCommand("docker", ["info"]);
|
|
50016
|
+
if (tool === "traefik") try {
|
|
50017
|
+
const { stdout } = await execFileAsync$2("docker", [
|
|
50018
|
+
"inspect",
|
|
50019
|
+
"--format",
|
|
50020
|
+
"{{.State.Running}}",
|
|
50021
|
+
"overdeck-traefik"
|
|
50022
|
+
], { timeout: 1e4 });
|
|
50023
|
+
return stdout.trim() === "true";
|
|
50024
|
+
} catch {
|
|
50025
|
+
return false;
|
|
50026
|
+
}
|
|
50027
|
+
if (tool === "ttyd") return await checkCommand("ttyd", ["--version"]) || existsSync$1(join(homedir$1(), "bin", "ttyd"));
|
|
51363
50028
|
return checkCommand(tool);
|
|
51364
50029
|
}
|
|
51365
50030
|
/** Install a single tool. Returns a result object (never throws). */
|
|
@@ -51370,6 +50035,7 @@ async function installTool(tool) {
|
|
|
51370
50035
|
case "ttyd": return await installTtyd();
|
|
51371
50036
|
case "mkcert": return await installMkcert();
|
|
51372
50037
|
case "bd": return await installBeads();
|
|
50038
|
+
case "jq": return await installJq();
|
|
51373
50039
|
case "ox": return await installOx();
|
|
51374
50040
|
default: return {
|
|
51375
50041
|
tool,
|
|
@@ -51451,6 +50117,15 @@ async function installBeads() {
|
|
|
51451
50117
|
message: "beads installed via install script"
|
|
51452
50118
|
};
|
|
51453
50119
|
}
|
|
50120
|
+
async function installJq() {
|
|
50121
|
+
if (await Effect.runPromise(detectPlatform()) === "darwin") await execAsync$1("brew install jq", { timeout: 12e4 });
|
|
50122
|
+
else await execAsync$1("sudo apt-get update && sudo apt-get install -y jq", { timeout: 12e4 });
|
|
50123
|
+
return {
|
|
50124
|
+
tool: "jq",
|
|
50125
|
+
success: true,
|
|
50126
|
+
message: "jq installed"
|
|
50127
|
+
};
|
|
50128
|
+
}
|
|
51454
50129
|
async function installOx() {
|
|
51455
50130
|
const plat = await Effect.runPromise(detectPlatform());
|
|
51456
50131
|
const arch = process.arch === "x64" ? "amd64" : process.arch;
|
|
@@ -52255,7 +50930,7 @@ async function refreshMergeStateFromGitHub(issueId, repo, prNumber) {
|
|
|
52255
50930
|
let mergeState;
|
|
52256
50931
|
let isDraft;
|
|
52257
50932
|
let checksFailed;
|
|
52258
|
-
const { isGitHubAppConfigured, getPullRequestState } = await import("./github-app-
|
|
50933
|
+
const { isGitHubAppConfigured, getPullRequestState } = await import("./github-app-Bwt9lK4A.js");
|
|
52259
50934
|
if (isGitHubAppConfigured()) {
|
|
52260
50935
|
const prState = await Effect.runPromise(getPullRequestState(owner, repoName, prNumber));
|
|
52261
50936
|
mergeable = prState.mergeable === null ? "UNKNOWN" : prState.mergeable ? "MERGEABLE" : "CONFLICTING";
|
|
@@ -52404,8 +51079,8 @@ async function handlePullRequestPromise(payload) {
|
|
|
52404
51079
|
bumpIssuePrTabCacheGeneration(issueId);
|
|
52405
51080
|
const repo = payload.repository.full_name;
|
|
52406
51081
|
if (payload.action === "closed" && pr.merged === true) try {
|
|
52407
|
-
const { postMergeLifecycle } = await import("./merge-agent-
|
|
52408
|
-
const { resolveProjectFromIssueSync } = await import("./projects-
|
|
51082
|
+
const { postMergeLifecycle } = await import("./merge-agent-ejC7Wos8.js");
|
|
51083
|
+
const { resolveProjectFromIssueSync } = await import("./projects-CrBE6IhN.js");
|
|
52409
51084
|
const project = resolveProjectFromIssueSync(issueId);
|
|
52410
51085
|
if (project) {
|
|
52411
51086
|
const branchName = pr.head.ref;
|
|
@@ -52970,7 +51645,7 @@ function getCheckpointWorker() {
|
|
|
52970
51645
|
return worker;
|
|
52971
51646
|
}
|
|
52972
51647
|
async function runInline(operation, payload) {
|
|
52973
|
-
const { claimTranscriptRange, commitTranscriptRange, releaseTranscriptRange, getTranscriptCheckpoint, listTranscriptCheckpoints } = await import("./checkpoints-
|
|
51648
|
+
const { claimTranscriptRange, commitTranscriptRange, releaseTranscriptRange, getTranscriptCheckpoint, listTranscriptCheckpoints } = await import("./checkpoints-fjadfOKF.js");
|
|
52974
51649
|
switch (operation) {
|
|
52975
51650
|
case "claimTranscriptRange": return claimTranscriptRange(payload);
|
|
52976
51651
|
case "commitTranscriptRange": return commitTranscriptRange(payload);
|
|
@@ -54124,7 +52799,7 @@ function buildPendingTurn(input, fromOffset, toOffset, compressed) {
|
|
|
54124
52799
|
};
|
|
54125
52800
|
}
|
|
54126
52801
|
async function emitMemoryObservationCreated(observation, timestamp) {
|
|
54127
|
-
const { initEventStore } = await import("./event-store-
|
|
52802
|
+
const { initEventStore } = await import("./event-store-CqDgfbAs.js");
|
|
54128
52803
|
await (await initEventStore()).appendAsync({
|
|
54129
52804
|
type: "memory.observation_created",
|
|
54130
52805
|
timestamp,
|
|
@@ -57778,7 +56453,7 @@ async function getFlywheelConversationPayload() {
|
|
|
57778
56453
|
};
|
|
57779
56454
|
}
|
|
57780
56455
|
async function postFlywheelReportPayload() {
|
|
57781
|
-
const { flywheelReportCommand } = await import("./flywheel-
|
|
56456
|
+
const { flywheelReportCommand } = await import("./flywheel-9Y1X7IM-.js");
|
|
57782
56457
|
await flywheelReportCommand({ cwd: process.cwd() });
|
|
57783
56458
|
return {
|
|
57784
56459
|
status: 200,
|
|
@@ -57936,11 +56611,11 @@ const getMergeBlockersRoute = HttpRouter.add("GET", "/api/flywheel/merge-blocker
|
|
|
57936
56611
|
async function defaultGetOrderedIssueIds() {
|
|
57937
56612
|
const status = await readCurrentFlywheelStatusForDashboard();
|
|
57938
56613
|
if (!status) return [];
|
|
57939
|
-
const { computeMergeQueue } = await import("./flywheel-merge-order-
|
|
56614
|
+
const { computeMergeQueue } = await import("./flywheel-merge-order-DEtEd3aK.js");
|
|
57940
56615
|
return (await Effect.runPromise(computeMergeQueue(status.activePipeline, process.cwd()).pipe(Effect.provide(layer)))).map((i) => i.issueId);
|
|
57941
56616
|
}
|
|
57942
56617
|
async function defaultMergeOne(issueId) {
|
|
57943
|
-
const { triggerMerge } = await import("./merge-ops-
|
|
56618
|
+
const { triggerMerge } = await import("./merge-ops-CFkQtXEj.js");
|
|
57944
56619
|
const r = await triggerMerge(issueId);
|
|
57945
56620
|
return r.success ? { ok: true } : {
|
|
57946
56621
|
ok: false,
|
|
@@ -57960,7 +56635,7 @@ async function postFlywheelMergeNextPayload(payload, deps = {}) {
|
|
|
57960
56635
|
body: { error: "n must be a positive integer" }
|
|
57961
56636
|
};
|
|
57962
56637
|
const issueIds = (await (deps.getOrderedIssueIds ?? defaultGetOrderedIssueIds)()).slice(0, n);
|
|
57963
|
-
const { shipMergeBatch } = await import("./merge-batch-
|
|
56638
|
+
const { shipMergeBatch } = await import("./merge-batch-DyqlgYGp.js");
|
|
57964
56639
|
return {
|
|
57965
56640
|
status: 200,
|
|
57966
56641
|
body: { outcomes: await shipMergeBatch(issueIds, { merge: deps.merge ?? defaultMergeOne }) }
|
|
@@ -58117,7 +56792,7 @@ const getFlywheelMergeQueueRoute = HttpRouter.add("GET", "/api/flywheel/merge-qu
|
|
|
58117
56792
|
return yield* Effect.promise(async () => {
|
|
58118
56793
|
const status = await readCurrentFlywheelStatusForDashboard();
|
|
58119
56794
|
if (!status) return jsonResponse([]);
|
|
58120
|
-
const { computeMergeQueue, resolveMergeQueuePrUrl } = await import("./flywheel-merge-order-
|
|
56795
|
+
const { computeMergeQueue, resolveMergeQueuePrUrl } = await import("./flywheel-merge-order-DEtEd3aK.js");
|
|
58121
56796
|
return jsonResponse(await Effect.runPromise(computeMergeQueue(status.activePipeline, process.cwd(), { getPrUrl: resolveMergeQueuePrUrl }).pipe(Effect.provide(layer))));
|
|
58122
56797
|
});
|
|
58123
56798
|
})));
|
|
@@ -58131,18 +56806,18 @@ function uatGenerationNameFromParam(param) {
|
|
|
58131
56806
|
return decoded.startsWith("uat/") ? decoded : `uat/${decoded}`;
|
|
58132
56807
|
}
|
|
58133
56808
|
const getUatGenerationsRoute = HttpRouter.add("GET", "/api/flywheel/uat-generations", httpHandler(Effect.gen(function* () {
|
|
58134
|
-
const { getUatGenerationsPayload } = yield* Effect.promise(() => import("./uat-train-
|
|
56809
|
+
const { getUatGenerationsPayload } = yield* Effect.promise(() => import("./uat-train-utGVmqdm.js"));
|
|
58135
56810
|
return jsonResponse(yield* Effect.promise(() => getUatGenerationsPayload()));
|
|
58136
56811
|
})));
|
|
58137
56812
|
const getUatCandidateRoute = HttpRouter.add("GET", "/api/flywheel/uat-candidate", httpHandler(Effect.gen(function* () {
|
|
58138
|
-
const { getUatCandidatePayload } = yield* Effect.promise(() => import("./uat-train-
|
|
56813
|
+
const { getUatCandidatePayload } = yield* Effect.promise(() => import("./uat-train-utGVmqdm.js"));
|
|
58139
56814
|
return jsonResponse(yield* Effect.promise(() => getUatCandidatePayload()));
|
|
58140
56815
|
})));
|
|
58141
56816
|
const postUatGenerationStackRoute = HttpRouter.add("POST", "/api/flywheel/uat-generations/:name/stack", httpHandler(Effect.gen(function* () {
|
|
58142
56817
|
const authError = rejectUnsafeDashboardMutationRequest(yield* HttpServerRequest.HttpServerRequest);
|
|
58143
56818
|
if (authError) return authError;
|
|
58144
56819
|
const name = uatGenerationNameFromParam((yield* HttpRouter.params)["name"] ?? "");
|
|
58145
|
-
const { postUatGenerationStackPayload } = yield* Effect.promise(() => import("./uat-train-
|
|
56820
|
+
const { postUatGenerationStackPayload } = yield* Effect.promise(() => import("./uat-train-utGVmqdm.js"));
|
|
58146
56821
|
const result = yield* Effect.promise(() => postUatGenerationStackPayload(name));
|
|
58147
56822
|
if (!result.ok) return jsonResponse({ error: result.error }, { status: result.status });
|
|
58148
56823
|
return jsonResponse({
|
|
@@ -58154,8 +56829,8 @@ const postUatGenerationPromoteRoute = HttpRouter.add("POST", "/api/flywheel/uat-
|
|
|
58154
56829
|
const authError = rejectUnsafeDashboardMutationRequest(yield* HttpServerRequest.HttpServerRequest);
|
|
58155
56830
|
if (authError) return authError;
|
|
58156
56831
|
const name = uatGenerationNameFromParam((yield* HttpRouter.params)["name"] ?? "");
|
|
58157
|
-
const { postUatGenerationPromotePayload } = yield* Effect.promise(() => import("./uat-train-
|
|
58158
|
-
const { firePostMergeLifecycle } = yield* Effect.promise(() => import("./specialists-
|
|
56832
|
+
const { postUatGenerationPromotePayload } = yield* Effect.promise(() => import("./uat-train-utGVmqdm.js"));
|
|
56833
|
+
const { firePostMergeLifecycle } = yield* Effect.promise(() => import("./specialists-D7AcFi1u.js"));
|
|
58159
56834
|
const result = yield* Effect.promise(() => postUatGenerationPromotePayload(name, firePostMergeLifecycle));
|
|
58160
56835
|
if (!result.success) return jsonResponse(result, { status: result.reason === "not-found" ? 404 : result.reason === "merge-failed" ? 500 : 409 });
|
|
58161
56836
|
return jsonResponse(result);
|
|
@@ -58168,7 +56843,7 @@ const postUatGenerationPromoteRoute = HttpRouter.add("POST", "/api/flywheel/uat-
|
|
|
58168
56843
|
const postFlywheelAssembleUatRoute = HttpRouter.add("POST", "/api/flywheel/assemble-uat", httpHandler(Effect.gen(function* () {
|
|
58169
56844
|
const authError = rejectUnsafeDashboardMutationRequest(yield* HttpServerRequest.HttpServerRequest);
|
|
58170
56845
|
if (authError) return authError;
|
|
58171
|
-
const { runUatTrainReconcile } = yield* Effect.promise(() => import("./uat-train-
|
|
56846
|
+
const { runUatTrainReconcile } = yield* Effect.promise(() => import("./uat-train-utGVmqdm.js"));
|
|
58172
56847
|
return jsonResponse(yield* Effect.promise(() => runUatTrainReconcile({ force: true })));
|
|
58173
56848
|
})));
|
|
58174
56849
|
const getFlywheelStateRoute = HttpRouter.add("GET", "/api/flywheel/state", httpHandler(Effect.gen(function* () {
|
|
@@ -61463,7 +60138,7 @@ init_activity_logger();
|
|
|
61463
60138
|
init_read_model();
|
|
61464
60139
|
function enrichmentChanged(prev, next) {
|
|
61465
60140
|
if (!prev) return true;
|
|
61466
|
-
return prev.role !== next.role || prev.hasPendingQuestion !== next.hasPendingQuestion || prev.pendingQuestionCount !== next.pendingQuestionCount || prev.pendingQuestionPrompt !== next.pendingQuestionPrompt || prev.pendingQuestionReason !== next.pendingQuestionReason || prev.pendingInputCount !== next.pendingInputCount || prev.pendingInputKinds.join(",") !== next.pendingInputKinds.join(",") || prev.pendingAskUserQuestion?.toolUseId !== next.pendingAskUserQuestion?.toolUseId || prev.resolution !== next.resolution || prev.resolutionCount !== next.resolutionCount;
|
|
60141
|
+
return prev.role !== next.role || prev.hasPendingQuestion !== next.hasPendingQuestion || prev.pendingQuestionCount !== next.pendingQuestionCount || prev.pendingQuestionPrompt !== next.pendingQuestionPrompt || prev.pendingQuestionReason !== next.pendingQuestionReason || prev.pendingInputCount !== next.pendingInputCount || prev.pendingInputKinds.join(",") !== next.pendingInputKinds.join(",") || prev.pendingAskUserQuestion?.toolUseId !== next.pendingAskUserQuestion?.toolUseId || prev.pendingProposedPlan?.toolUseId !== next.pendingProposedPlan?.toolUseId || prev.resolution !== next.resolution || prev.resolutionCount !== next.resolutionCount;
|
|
61467
60142
|
}
|
|
61468
60143
|
function isAwaitingInputRisingEdge(previous, current) {
|
|
61469
60144
|
return (previous?.pendingInputCount ?? 0) === 0 && current.pendingInputCount > 0;
|
|
@@ -61580,6 +60255,7 @@ async function pollOnce$1(state) {
|
|
|
61580
60255
|
pendingInputCount: enrichment.pendingInputCount,
|
|
61581
60256
|
pendingInputKinds: enrichment.pendingInputKinds,
|
|
61582
60257
|
pendingAskUserQuestion: enrichment.pendingAskUserQuestion,
|
|
60258
|
+
pendingProposedPlan: enrichment.pendingProposedPlan,
|
|
61583
60259
|
resolution: enrichment.resolution,
|
|
61584
60260
|
resolutionCount: enrichment.resolutionCount
|
|
61585
60261
|
}
|
|
@@ -61777,7 +60453,7 @@ async function pollOnce(state) {
|
|
|
61777
60453
|
try {
|
|
61778
60454
|
const remoteState = await readFile(join(homedir$1(), ".overdeck", "agents", agentId, "remote-state.json"), "utf-8").then((text) => JSON.parse(text)).catch(() => null);
|
|
61779
60455
|
if (remoteState?.location === "remote" && remoteState?.vmName) {
|
|
61780
|
-
const { getRemoteAgentOutput } = await import("./remote-agents-
|
|
60456
|
+
const { getRemoteAgentOutput } = await import("./remote-agents-Cv-U-_V8.js");
|
|
61781
60457
|
stdout = await getRemoteAgentOutput(agentId, remoteState.vmName, 50);
|
|
61782
60458
|
} else stdout = await Effect.runPromise(capturePane(agentId, 50));
|
|
61783
60459
|
} catch {
|
|
@@ -63084,7 +61760,7 @@ const RESTART_MARKER = join$1(homedir(), ".overdeck", "dashboard-restarting.json
|
|
|
63084
61760
|
* loads new content-hashed chunk filenames (no ERR_MODULE_NOT_FOUND after rebuild).
|
|
63085
61761
|
*/
|
|
63086
61762
|
async function defaultLifecycleRunner(pending) {
|
|
63087
|
-
const { postMergeLifecycle, notifyTldrDaemon } = await import("./merge-agent-
|
|
61763
|
+
const { postMergeLifecycle, notifyTldrDaemon } = await import("./merge-agent-ejC7Wos8.js");
|
|
63088
61764
|
await postMergeLifecycle(pending.issueId, pending.projectPath, pending.sourceBranch, { skipDeploy: true });
|
|
63089
61765
|
if (pending.sourceBranch) await notifyTldrDaemon(pending.projectPath, pending.sourceBranch);
|
|
63090
61766
|
}
|
|
@@ -63405,7 +62081,7 @@ function failureReason(result) {
|
|
|
63405
62081
|
return result.error ?? result.message ?? `merge returned status ${result.statusCode ?? "unknown"}`;
|
|
63406
62082
|
}
|
|
63407
62083
|
async function defaultMergeIssue(issueId) {
|
|
63408
|
-
const { triggerMerge } = await import("./merge-ops-
|
|
62084
|
+
const { triggerMerge } = await import("./merge-ops-CFkQtXEj.js");
|
|
63409
62085
|
return triggerMerge(issueId);
|
|
63410
62086
|
}
|
|
63411
62087
|
function defaultAnnounceFailure(issueId, reason) {
|
|
@@ -63688,7 +62364,7 @@ startMergeBlockerReconcileService();
|
|
|
63688
62364
|
console.log("[overdeck] MergeBlockerReconcileService started");
|
|
63689
62365
|
if (process.env.OVERDECK_MODE === "desktop") (async () => {
|
|
63690
62366
|
try {
|
|
63691
|
-
const { provisionClaudeHooks } = await import("./claude-hooks-provision-
|
|
62367
|
+
const { provisionClaudeHooks } = await import("./claude-hooks-provision-DiK62u0k.js");
|
|
63692
62368
|
const result = await provisionClaudeHooks();
|
|
63693
62369
|
if (!result.ok) console.warn(`[overdeck] Claude hook provisioning skipped: ${result.reason}`);
|
|
63694
62370
|
else if (result.changed) console.log(`[overdeck] Claude hooks provisioned: ${result.binariesSynced} scripts, registered ${result.registered.length} hook(s)${result.pruned.length ? `, pruned ${result.pruned.length} stale` : ""}`);
|
|
@@ -64052,7 +62728,7 @@ reconcileStaleGitHubBlockers().then((n) => {
|
|
|
64052
62728
|
}
|
|
64053
62729
|
}).catch((err) => console.warn(`[overdeck] Startup blocker reconciliation failed: ${err.message}`));
|
|
64054
62730
|
try {
|
|
64055
|
-
const { resetProcessingToQueued } = await import("./merge-sync-
|
|
62731
|
+
const { resetProcessingToQueued } = await import("./merge-sync-CG9kDCdT.js");
|
|
64056
62732
|
const resetCount = resetProcessingToQueued();
|
|
64057
62733
|
if (resetCount > 0) {
|
|
64058
62734
|
console.log(`[overdeck] Reset ${resetCount} stuck merge queue entries to queued`);
|