@repo-os/repoos 0.5.68 → 0.5.70
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.build-info.json +2 -2
- package/dist/.build-stamp.json +1 -1
- package/dist/cli/api-route-parity.js +4 -0
- package/dist/cli/help.js +9 -3
- package/dist/cli/index.js +7 -1
- package/dist/commands/control-api.d.ts +1 -0
- package/dist/commands/control-api.js +114 -4
- package/dist/commands/init.js +7 -2
- package/dist/commands/ui-contrast-audit.js +55 -2
- package/dist/core/config.d.ts +1 -0
- package/dist/core/config.js +40 -2
- package/dist/core/dev-targets.d.ts +25 -0
- package/dist/core/dev-targets.js +155 -0
- package/dist/core/git.d.ts +18 -0
- package/dist/core/git.js +10 -1
- package/dist/core/models.js +7 -1
- package/dist/core/shot-page.d.ts +9 -0
- package/dist/core/shot-page.js +76 -1
- package/dist/core/types.d.ts +51 -2
- package/dist/core/types.js +9 -1
- package/dist/server/agents.d.ts +19 -0
- package/dist/server/agents.js +143 -5
- package/dist/server/conflict-resolution.d.ts +26 -6
- package/dist/server/conflict-resolution.js +71 -3
- package/dist/server/dev.d.ts +131 -0
- package/dist/server/dev.js +621 -0
- package/dist/server/integration-orchestrator.js +75 -13
- package/dist/server/merge-conflict.d.ts +9 -2
- package/dist/server/merge-conflict.js +10 -4
- package/dist/server/review.d.ts +1 -1
- package/dist/server/review.js +20 -10
- package/dist/server/routes/config.js +117 -1
- package/dist/server/routes/dev.d.ts +19 -0
- package/dist/server/routes/dev.js +60 -0
- package/dist/server/routes/index.d.ts +1 -0
- package/dist/server/routes/index.js +1 -0
- package/dist/server/routes/tasks.js +89 -10
- package/dist/server/routes/types.d.ts +6 -0
- package/dist/server/server.js +23 -1
- package/dist/server/shot-capture.js +4 -0
- package/dist/server/ui-handoff-gate.d.ts +27 -0
- package/dist/server/ui-handoff-gate.js +46 -5
- package/dist/ui/assets/{AgentModelModal-BU_T-d03.js → AgentModelModal-qiRXdw6a.js} +1 -1
- package/dist/ui/assets/AgentsView-YS1AZ1v2.js +1 -0
- package/dist/ui/assets/AgentsView-kKt4CrDo.css +1 -0
- package/dist/ui/assets/ChecksView-Ch8Ncat5.js +0 -0
- package/dist/ui/assets/ConfirmDialog-CcPmuMHQ.js +1 -0
- package/dist/ui/assets/ContextView-DGMk39_r.js +4 -0
- package/dist/ui/assets/DashboardView-B_9hD8tR.js +1 -0
- package/dist/ui/assets/{DeleteConfirmDialog-B7_fR8N6.js → DeleteConfirmDialog-BLHJs3Sg.js} +1 -1
- package/dist/ui/assets/{DeploymentsView-oXkw2BSL.js → DeploymentsView-CJBx2mcp.js} +1 -1
- package/dist/ui/assets/DevView-CoL2KIaZ.css +1 -0
- package/dist/ui/assets/DevView-DZb2LbMn.js +2 -0
- package/dist/ui/assets/{DiffView-DLFmq-vx.js → DiffView-DeZzB47D.js} +1 -1
- package/dist/ui/assets/{FailedTestsList-3_oexlME.js → FailedTestsList-CdlcNhbe.js} +1 -1
- package/dist/ui/assets/InputsView-0b4Sjg0Q.js +1 -0
- package/dist/ui/assets/LoginView-B2WAQcq0.js +1 -0
- package/dist/ui/assets/ReleasesView-B7yJdjLp.js +5 -0
- package/dist/ui/assets/SearchOverlay-D44KxIbl.js +1 -0
- package/dist/ui/assets/SettingsView-BN-H2QBT.js +4 -0
- package/dist/ui/assets/SettingsView-CEWHEE4r.css +1 -0
- package/dist/ui/assets/StoriesView-CnAlxgkT.js +1 -0
- package/dist/ui/assets/VoiceDictate-CS-9Kmsa.css +1 -0
- package/dist/ui/assets/{VoiceDictate-CMtXjAXc.js → VoiceDictate-CbJnmeNg.js} +2 -2
- package/dist/ui/assets/WorkView-B4J9uqPn.js +2 -0
- package/dist/ui/assets/{WorkView-BhDux3s_.css → WorkView-B4O1dgd8.css} +1 -1
- package/dist/ui/assets/abnfDiagram-VCTEODGH-DrTaHBvQ.js +1 -0
- package/dist/ui/assets/architecture-7GRP2DOG-BHZiePHg.js +1 -0
- package/dist/ui/assets/architectureDiagram-5GKGNRK7-4pbmksoa.js +36 -0
- package/dist/ui/assets/auth-DOfKWRWn.js +1 -0
- package/dist/ui/assets/{blockDiagram-I7D4REHJ-CSam08UZ.js → blockDiagram-I7D4REHJ-DotXLktk.js} +1 -1
- package/dist/ui/assets/{button-uIODk23A.js → button-Cg7Fwvfz.js} +1 -1
- package/dist/ui/assets/{c4Diagram-7LVT6UL2-D6YRpohJ.js → c4Diagram-7LVT6UL2-CX4XAag_.js} +1 -1
- package/dist/ui/assets/card-h3OmE2_z.js +1 -0
- package/dist/ui/assets/channel-BrKb638S.js +1 -0
- package/dist/ui/assets/{checkbox-EUK8itx1.js → checkbox-CJdatFyS.js} +1 -1
- package/dist/ui/assets/chunk-2E4U76K2-DBwbHQrf.js +2 -0
- package/dist/ui/assets/chunk-2ZTRR5NV-Cr-_ry_6.js +2 -0
- package/dist/ui/assets/chunk-3Z5EZCMW-BBL48ahF.js +1 -0
- package/dist/ui/assets/{chunk-4HAMMTFA-BnbHtCpa.js → chunk-4HAMMTFA-CC2YIavJ.js} +1 -1
- package/dist/ui/assets/chunk-5V3GS4D5-B6UpbGCn.js +1 -0
- package/dist/ui/assets/chunk-6AZGARVD-CYyHPsEW.js +1 -0
- package/dist/ui/assets/chunk-6EIED4P4-DLcrKSZa.js +1 -0
- package/dist/ui/assets/chunk-6K3QC6MW-8lwas69x.js +1 -0
- package/dist/ui/assets/chunk-6TQVIW2G-kn-138pS.js +1 -0
- package/dist/ui/assets/chunk-747NJXEK-ZQ1az0_F.js +2 -0
- package/dist/ui/assets/{chunk-75Z2AOVW-CYy9Me4H.js → chunk-75Z2AOVW-GQ3dA3RS.js} +1 -1
- package/dist/ui/assets/chunk-CLGD4ZFX-DJeOtdRW.js +1 -0
- package/dist/ui/assets/{chunk-DU6HZSFF-JVoEkt2i.js → chunk-DU6HZSFF-Dth3AgVP.js} +1 -1
- package/dist/ui/assets/{chunk-F27PBJKO-g4ruqsFu.js → chunk-F27PBJKO-CUKJ_1GV.js} +1 -1
- package/dist/ui/assets/{chunk-GMAD6QVW-BfX4kTq8.js → chunk-GMAD6QVW-DUokwNqt.js} +1 -1
- package/dist/ui/assets/{chunk-GVQU2GXP-C9yJ2E9t.js → chunk-GVQU2GXP--wyu3z_M.js} +1 -1
- package/dist/ui/assets/chunk-I5DQTOEV-Cux5OBYe.js +1 -0
- package/dist/ui/assets/chunk-ICYGCRZG-BSFpafu0.js +1 -0
- package/dist/ui/assets/chunk-IH6LHLGP-D3gp9iPn.js +1 -0
- package/dist/ui/assets/{chunk-IMKFNOWR-CbzZAPQV.js → chunk-IMKFNOWR-DKnHgEdS.js} +1 -1
- package/dist/ui/assets/chunk-KI3K4JFJ-bgHYJH0f.js +1 -0
- package/dist/ui/assets/{chunk-L3NEJ4N5-Cjbclivl.js → chunk-L3NEJ4N5-vio-PK5r.js} +1 -1
- package/dist/ui/assets/chunk-LNGE3PJU-p78rraeW.js +34 -0
- package/dist/ui/assets/{chunk-OSK3NFVY-YA4gtld_.js → chunk-OSK3NFVY-BF4uJ1Wv.js} +1 -1
- package/dist/ui/assets/chunk-OUJLGHUK-CYjUPErt.js +2 -0
- package/dist/ui/assets/{chunk-P2QGCYS3-Cj7e9ARN.js → chunk-P2QGCYS3-B9OHNM4g.js} +1 -1
- package/dist/ui/assets/{chunk-POPQ4Y6H-fwh_frIf.js → chunk-POPQ4Y6H-DfPkV4K8.js} +1 -1
- package/dist/ui/assets/{chunk-PWAF6VOD-BUHsDYf7.js → chunk-PWAF6VOD-C6pQpja9.js} +1 -1
- package/dist/ui/assets/{chunk-SHT3W25Y-BsPOUuAn.js → chunk-SHT3W25Y-D1FyTkkv.js} +3 -3
- package/dist/ui/assets/{chunk-SVP7TREG-CwMeLZi5.js → chunk-SVP7TREG-DtQlvhPk.js} +1 -1
- package/dist/ui/assets/{chunk-TICWLB2K-B9QsE3VX.js → chunk-TICWLB2K-BpnCR3pz.js} +1 -1
- package/dist/ui/assets/chunk-TLUHSLCS-BeK-nkSE.js +2 -0
- package/dist/ui/assets/chunk-UY3FDG6J-XZwQOzbF.js +1 -0
- package/dist/ui/assets/chunk-XHIXRSVI-Bu6LAW6p.js +1 -0
- package/dist/ui/assets/classDiagram-ZZMXUADV-BO_a0cvs.js +1 -0
- package/dist/ui/assets/classDiagram-v2-VYDZK3BY-BO_a0cvs.js +1 -0
- package/dist/ui/assets/cynefin-OW5HDTMX-Bxpgy9Q-.js +1 -0
- package/dist/ui/assets/cynefinDiagram-5FMLGOSQ-D3SEdRnG.js +62 -0
- package/dist/ui/assets/{dagre-GXQ25YYZ-CJefo5Cd.js → dagre-GXQ25YYZ-C8gQG-lD.js} +2 -2
- package/dist/ui/assets/{diagram-S7CK7UJ4-BshX_cqp.js → diagram-S7CK7UJ4-Czu_0uu0.js} +3 -3
- package/dist/ui/assets/diagram-UQ7AKVKN-ViXph8nh.js +41 -0
- package/dist/ui/assets/diagram-VSXAHHWV-C6BtTSHW.js +3 -0
- package/dist/ui/assets/diagram-VX7I27RA-TbbO1fXg.js +24 -0
- package/dist/ui/assets/diagram-Z3DM3KII-BO9R4sQs.js +24 -0
- package/dist/ui/assets/docs-CypCpmgt.js +1 -0
- package/dist/ui/assets/ebnfDiagram-PWID7BFC-aKXt7bQt.js +1 -0
- package/dist/ui/assets/{erDiagram-RLTQ6QDP-DKrnpHSN.js → erDiagram-RLTQ6QDP-47HSz_yo.js} +1 -1
- package/dist/ui/assets/eventmodeling-NTZA5JFV-CKBX3xli.js +1 -0
- package/dist/ui/assets/flowDiagram-HODETNUW-DPrFUvzg.js +1 -0
- package/dist/ui/assets/{ganttDiagram-EL5Y4UJY-DzU13pix.js → ganttDiagram-EL5Y4UJY-CLH5Zx6B.js} +1 -1
- package/dist/ui/assets/gitGraph-4MIJSDKK-DBRsV9Fh.js +1 -0
- package/dist/ui/assets/gitGraphDiagram-WWUBYQGX-BOxdVoS7.js +106 -0
- package/dist/ui/assets/index-ChEmz2Dy.css +1 -0
- package/dist/ui/assets/index-DcF5KN6q.js +57 -0
- package/dist/ui/assets/info-A6RAGUB7-AZ8VcEaY.js +1 -0
- package/dist/ui/assets/infoDiagram-27XIBGKW-CuAZPnDi.js +2 -0
- package/dist/ui/assets/input-Cg7deJC2.js +1 -0
- package/dist/ui/assets/{ishikawaDiagram-5VMMS53U-Cdigo_vG.js → ishikawaDiagram-5VMMS53U-B7Eq3ePc.js} +2 -2
- package/dist/ui/assets/{journeyDiagram-3NMN7TZE-DmZ4MIYL.js → journeyDiagram-3NMN7TZE-BhW2Sqpt.js} +1 -1
- package/dist/ui/assets/{kanban-definition-UXKFOSKX-2sVFLArm.js → kanban-definition-UXKFOSKX-Cw_klMxM.js} +3 -3
- package/dist/ui/assets/{line-C77c3pt1.js → line-CX-sssw_.js} +1 -1
- package/dist/ui/assets/mermaid-parser.core-DU36LHRU.js +4 -0
- package/dist/ui/assets/mermaid.core-DKxErDRT.js +11 -0
- package/dist/ui/assets/{mindmap-definition-YA3MSWOX-BsOAbuQD.js → mindmap-definition-YA3MSWOX-NMTZuXGJ.js} +1 -1
- package/dist/ui/assets/packet-AYTQ26CC-Bdg2essy.js +1 -0
- package/dist/ui/assets/pegDiagram-XKGWAZYB-B9DqL68I.js +1 -0
- package/dist/ui/assets/pie-WAS4IAKB-D5QrUC2g.js +1 -0
- package/dist/ui/assets/pieDiagram-E7YTZNPT-EPN4fJwb.js +39 -0
- package/dist/ui/assets/{quadrantDiagram-AXDQQJYC-BFIIZWqg.js → quadrantDiagram-AXDQQJYC-B1vP5hUF.js} +1 -1
- package/dist/ui/assets/radar-RG4KPBEZ-BuYYKOJl.js +1 -0
- package/dist/ui/assets/railroad-74A4TZTK-Nkuw4fzg.js +1 -0
- package/dist/ui/assets/railroad-abnf-HS5TGJTU-gAPZoBfp.js +1 -0
- package/dist/ui/assets/railroad-ebnf-LZEXJU2U-DvwkawHG.js +1 -0
- package/dist/ui/assets/railroad-peg-WCYAUIDC-CrrHZFIz.js +1 -0
- package/dist/ui/assets/railroadDiagram-O6MQD6OU-q57-HBoV.js +1 -0
- package/dist/ui/assets/{repo-Rgx38OJH.js → repo-3D9Lh1aB.js} +1 -1
- package/dist/ui/assets/{requirementDiagram-BXWQKSXE-DzN62GBp.js → requirementDiagram-BXWQKSXE-B1nzxnDE.js} +1 -1
- package/dist/ui/assets/{sankeyDiagram-P5KCCOFB-Twa9FjBx.js → sankeyDiagram-P5KCCOFB-CvGzdKI2.js} +1 -1
- package/dist/ui/assets/screenshot-viewer-Zxr6licW.js +1 -0
- package/dist/ui/assets/{sequenceDiagram-WJ2MYXX4-DGUe1AcR.js → sequenceDiagram-WJ2MYXX4-G73REJUS.js} +1 -1
- package/dist/ui/assets/stateDiagram-D77RDMKH-CRW4gM0e.js +1 -0
- package/dist/ui/assets/stateDiagram-v2-MP3YSRHH-C8VGcrPt.js +1 -0
- package/dist/ui/assets/swimlanes-42K2YHIH-CE91Y-lT.js +1 -0
- package/dist/ui/assets/swimlanesDiagram-VR7AAH4N-CJy_fpiy.js +8 -0
- package/dist/ui/assets/switch-BYQwbwcZ.js +1 -0
- package/dist/ui/assets/{timeline-definition-24CTP7MA-D5A6I-WY.js → timeline-definition-24CTP7MA-DVw_tCzX.js} +1 -1
- package/dist/ui/assets/{title-ClcAtTzM.js → title-CKCTFTPg.js} +1 -1
- package/dist/ui/assets/treeView-Q6P3EWNA-DVwK8Kqr.js +1 -0
- package/dist/ui/assets/treemap-WGGIJYW6-dx7qI3mD.js +1 -0
- package/dist/ui/assets/useChatScroll-BiQjE1tB.js +1 -0
- package/dist/ui/assets/value-BsoQhhdg.js +1 -0
- package/dist/ui/assets/vendor-ui-D3ucVR3C.js +3 -0
- package/dist/ui/assets/{vennDiagram-4TSXK5OY-CbrfLPNL.js → vennDiagram-4TSXK5OY-gBaTlcOW.js} +2 -2
- package/dist/ui/assets/viewport-BVLcUJ9I.js +1 -0
- package/dist/ui/assets/wardley-WFR3VGLG-Dexzwvt6.js +1 -0
- package/dist/ui/assets/{wardleyDiagram-VM6X3IG4-cG-Vx9Gs.js → wardleyDiagram-VM6X3IG4-B9w0GtT1.js} +3 -3
- package/dist/ui/assets/{xychartDiagram-S5SC5T6Z-DXzo3wNb.js → xychartDiagram-S5SC5T6Z-D2o0fTLK.js} +3 -3
- package/dist/ui/index.html +19 -10
- package/dist/ui/sw.js +2 -2
- package/package.json +1 -1
- package/dist/ui/assets/AgentsView-0r3QjL0C.css +0 -1
- package/dist/ui/assets/AgentsView-B2AXFnUJ.js +0 -1
- package/dist/ui/assets/ChecksView-RAHI2BB3.js +0 -0
- package/dist/ui/assets/ContextView-DAxjJdK4.js +0 -4
- package/dist/ui/assets/DashboardView-hZr-QF_E.js +0 -1
- package/dist/ui/assets/InputsView-CE9ZOYMD.js +0 -1
- package/dist/ui/assets/LoginView-dfYNibLg.js +0 -1
- package/dist/ui/assets/ReleasesView-Cq8kGWZq.js +0 -5
- package/dist/ui/assets/SettingsView-BlDj5TRt.css +0 -1
- package/dist/ui/assets/SettingsView-BzZQH1hi.js +0 -4
- package/dist/ui/assets/StoriesView-3P5nmoFU.js +0 -1
- package/dist/ui/assets/VoiceDictate-Bc00yWSj.css +0 -1
- package/dist/ui/assets/WorkView-P_JFoClW.js +0 -2
- package/dist/ui/assets/abnfDiagram-VCTEODGH-DB7IT3Oz.js +0 -1
- package/dist/ui/assets/architecture-7GRP2DOG-D0IdEE2Q.js +0 -1
- package/dist/ui/assets/architectureDiagram-5GKGNRK7-BKe4O-fa.js +0 -36
- package/dist/ui/assets/channel-C0fJQ3Uq.js +0 -1
- package/dist/ui/assets/classDiagram-ZZMXUADV-DdZ1tR-T.js +0 -1
- package/dist/ui/assets/classDiagram-v2-VYDZK3BY-DdZ1tR-T.js +0 -1
- package/dist/ui/assets/cynefin-OW5HDTMX-DaO-Ofss.js +0 -1
- package/dist/ui/assets/cynefinDiagram-5FMLGOSQ-DbkXxB0L.js +0 -62
- package/dist/ui/assets/diagram-UQ7AKVKN-xP1_CqiO.js +0 -41
- package/dist/ui/assets/diagram-VSXAHHWV-BygVWS22.js +0 -3
- package/dist/ui/assets/diagram-VX7I27RA-CH--xipF.js +0 -24
- package/dist/ui/assets/diagram-Z3DM3KII-DJrYKohr.js +0 -24
- package/dist/ui/assets/ebnfDiagram-PWID7BFC-BkQ5ACZ8.js +0 -1
- package/dist/ui/assets/eventmodeling-NTZA5JFV-DHsluImP.js +0 -1
- package/dist/ui/assets/flowDiagram-HODETNUW-CpTJSjiU.js +0 -1
- package/dist/ui/assets/gitGraph-4MIJSDKK-C2NqgafQ.js +0 -1
- package/dist/ui/assets/gitGraphDiagram-WWUBYQGX-CD7Lar3K.js +0 -106
- package/dist/ui/assets/index-C3vwYKvY.js +0 -55
- package/dist/ui/assets/index-CjZQAL44.css +0 -1
- package/dist/ui/assets/info-A6RAGUB7-Cl6FFCuQ.js +0 -1
- package/dist/ui/assets/infoDiagram-27XIBGKW-Co-YjPmk.js +0 -2
- package/dist/ui/assets/mermaid-parser.core-xjtJ3pXb.js +0 -7
- package/dist/ui/assets/mermaid.core-CMyeUwV9.js +0 -44
- package/dist/ui/assets/packet-AYTQ26CC-BDcVOEez.js +0 -1
- package/dist/ui/assets/pegDiagram-XKGWAZYB-C1hq_Ygi.js +0 -1
- package/dist/ui/assets/pie-WAS4IAKB-CXk97zCx.js +0 -1
- package/dist/ui/assets/pieDiagram-E7YTZNPT-CG9wAg_-.js +0 -39
- package/dist/ui/assets/radar-RG4KPBEZ-D9HuDG1X.js +0 -1
- package/dist/ui/assets/railroad-74A4TZTK-kCOU5-RT.js +0 -1
- package/dist/ui/assets/railroad-abnf-HS5TGJTU-CtNhQpzv.js +0 -1
- package/dist/ui/assets/railroad-ebnf-LZEXJU2U-5rUlNGX_.js +0 -1
- package/dist/ui/assets/railroad-peg-WCYAUIDC-DOPhbUMW.js +0 -1
- package/dist/ui/assets/railroadDiagram-O6MQD6OU-RK45rPYx.js +0 -1
- package/dist/ui/assets/stateDiagram-D77RDMKH-ByryPTRm.js +0 -1
- package/dist/ui/assets/stateDiagram-v2-MP3YSRHH-xS7RBCS4.js +0 -1
- package/dist/ui/assets/swimlanes-42K2YHIH-CnU3MB_t.js +0 -1
- package/dist/ui/assets/swimlanesDiagram-VR7AAH4N-Dd7VwNJ9.js +0 -8
- package/dist/ui/assets/treeView-Q6P3EWNA-BzAgp6hO.js +0 -1
- package/dist/ui/assets/treemap-WGGIJYW6-BOnPgUXz.js +0 -1
- package/dist/ui/assets/useChatScroll-BD10j3cq.js +0 -1
- package/dist/ui/assets/vendor-ui-DsOjPSxk.js +0 -3
- package/dist/ui/assets/wardley-WFR3VGLG-BzZdYjpA.js +0 -1
package/dist/.build-info.json
CHANGED
package/dist/.build-stamp.json
CHANGED
|
@@ -12,6 +12,10 @@ const CONTROL_API_MATCHERS = [
|
|
|
12
12
|
re("POST", /^\/api\/tasks\/([^/]+)\/(start|pause|message|done)$/.source),
|
|
13
13
|
re("POST", /^\/api\/tasks\/([^/]+)\/preview$/.source),
|
|
14
14
|
re("POST", /^\/api\/tasks\/([^/]+)\/preview\/stop$/.source),
|
|
15
|
+
// `repoos dev …` (#0747): list/status/get and start/stop/restart.
|
|
16
|
+
exact("GET", "/api/dev/targets"),
|
|
17
|
+
re("GET", /^\/api\/dev\/targets\/([^/]+)$/.source),
|
|
18
|
+
re("POST", /^\/api\/dev\/targets\/([^/]+)\/(start|stop|restart)$/.source),
|
|
15
19
|
exact("GET", "/api/config"),
|
|
16
20
|
exact("PATCH", "/api/config"),
|
|
17
21
|
exact("GET", "/api/remote-validation/status"),
|
package/dist/cli/help.js
CHANGED
|
@@ -88,9 +88,9 @@ const GROUPS = [
|
|
|
88
88
|
},
|
|
89
89
|
{
|
|
90
90
|
name: "message",
|
|
91
|
-
usage: 'message <id> "<text>" [--json] [--port N]',
|
|
92
|
-
desc: "Send a follow-up to the task agent (POST /api/tasks/:id/message)",
|
|
93
|
-
flags: "--json · --port",
|
|
91
|
+
usage: 'message <id> "<text>" [--now] [--json] [--port N]',
|
|
92
|
+
desc: "Send a follow-up to the task agent; queues while busy, --now interrupts the turn and delivers immediately (POST /api/tasks/:id/message)",
|
|
93
|
+
flags: "--now · --json · --port",
|
|
94
94
|
},
|
|
95
95
|
{
|
|
96
96
|
name: "review",
|
|
@@ -116,6 +116,12 @@ const GROUPS = [
|
|
|
116
116
|
desc: "Start or stop the task preview (POST /api/tasks/:id/preview)",
|
|
117
117
|
flags: "--stop · --json · --port",
|
|
118
118
|
},
|
|
119
|
+
{
|
|
120
|
+
name: "dev",
|
|
121
|
+
usage: "dev [list] · dev <name> start|stop|restart|status|logs [--json] [--port N]",
|
|
122
|
+
desc: "Start, stop and inspect a declared dev target (GET/POST /api/dev/targets)",
|
|
123
|
+
flags: "--json · --port",
|
|
124
|
+
},
|
|
119
125
|
{
|
|
120
126
|
name: "config",
|
|
121
127
|
usage: "config get|set <key> [value] [--json] [--port N]",
|
package/dist/cli/index.js
CHANGED
|
@@ -21,7 +21,7 @@ import { cmdDoctor } from "../commands/doctor.js";
|
|
|
21
21
|
import { cmdCertify } from "../commands/certify.js";
|
|
22
22
|
import { cmdSupport } from "../commands/support.js";
|
|
23
23
|
import { cmdService } from "../commands/service.js";
|
|
24
|
-
import { cmdAgentsRunning, cmdConfig, cmdDone, cmdMessage, cmdOverride, cmdPause, cmdPreview, cmdReview, cmdRunners, cmdStart, cmdStats, cmdDecisions, } from "../commands/control-api.js";
|
|
24
|
+
import { cmdAgentsRunning, cmdConfig, cmdDone, cmdMessage, cmdOverride, cmdPause, cmdPreview, cmdDev, cmdReview, cmdRunners, cmdStart, cmdStats, cmdDecisions, } from "../commands/control-api.js";
|
|
25
25
|
import { cmdWatch } from "../commands/watch.js";
|
|
26
26
|
import { cmdDriver } from "../commands/driver.js";
|
|
27
27
|
import { checkBuild } from "../core/build.js";
|
|
@@ -242,6 +242,12 @@ function main() {
|
|
|
242
242
|
process.exitCode = code;
|
|
243
243
|
});
|
|
244
244
|
break;
|
|
245
|
+
case "dev":
|
|
246
|
+
void cmdDev(rest).then((code) => {
|
|
247
|
+
if (code !== 0)
|
|
248
|
+
process.exitCode = code;
|
|
249
|
+
});
|
|
250
|
+
break;
|
|
245
251
|
case "config":
|
|
246
252
|
void cmdConfig(rest).then((code) => {
|
|
247
253
|
if (code !== 0)
|
|
@@ -5,6 +5,7 @@ export declare function cmdReview(args: string[]): Promise<number>;
|
|
|
5
5
|
export declare function cmdDone(args: string[]): Promise<number>;
|
|
6
6
|
export declare function cmdOverride(args: string[]): Promise<number>;
|
|
7
7
|
export declare function cmdPreview(args: string[]): Promise<number>;
|
|
8
|
+
export declare function cmdDev(args: string[]): Promise<number>;
|
|
8
9
|
export declare function cmdConfig(args: string[]): Promise<number>;
|
|
9
10
|
export declare function cmdRunners(args: string[]): Promise<number>;
|
|
10
11
|
export declare function cmdAgentsRunning(args: string[]): Promise<number>;
|
|
@@ -6,7 +6,7 @@ import { pollUntil, RepoOsApi, RepoOsApiError, resolveControlPlaneBase, } from "
|
|
|
6
6
|
import { effectiveEngineerFromApi } from "../cli/effective-from-api.js";
|
|
7
7
|
import { HANDOFF_DEADLINE_MS } from "../server/handoff.js";
|
|
8
8
|
function parseCommonFlags(args) {
|
|
9
|
-
const opts = { json: false, wait: false };
|
|
9
|
+
const opts = { json: false, wait: false, now: false };
|
|
10
10
|
const rest = [];
|
|
11
11
|
for (let i = 0; i < args.length; i++) {
|
|
12
12
|
const a = args[i];
|
|
@@ -14,6 +14,8 @@ function parseCommonFlags(args) {
|
|
|
14
14
|
opts.json = true;
|
|
15
15
|
else if (a === "--wait")
|
|
16
16
|
opts.wait = true;
|
|
17
|
+
else if (a === "--now")
|
|
18
|
+
opts.now = true;
|
|
17
19
|
else if (a === "--port") {
|
|
18
20
|
const p = args[++i];
|
|
19
21
|
const n = Number(p);
|
|
@@ -133,17 +135,31 @@ export async function cmdMessage(args) {
|
|
|
133
135
|
const id = rest[0];
|
|
134
136
|
const text = rest.slice(1).join(" ").trim();
|
|
135
137
|
if (!id || !text) {
|
|
136
|
-
printErr('Usage: repoos message <id> "<text>" [--json] [--port N]');
|
|
138
|
+
printErr('Usage: repoos message <id> "<text>" [--now] [--json] [--port N]');
|
|
137
139
|
return 1;
|
|
138
140
|
}
|
|
139
141
|
const api = new RepoOsApi({ port: opts.port });
|
|
140
142
|
try {
|
|
141
143
|
await ensureServer(api);
|
|
142
|
-
const data = await api.requestOk("POST", `/api/tasks/${id}/message`, {
|
|
144
|
+
const data = await api.requestOk("POST", `/api/tasks/${id}/message`, {
|
|
145
|
+
text,
|
|
146
|
+
...(opts.now ? { now: true } : {}),
|
|
147
|
+
});
|
|
143
148
|
if (opts.json)
|
|
144
149
|
printJson(data);
|
|
145
|
-
else
|
|
150
|
+
else if (data?.queued) {
|
|
151
|
+
const why = data.now
|
|
152
|
+
? (data.reason ?? "agent still busy after the interrupt")
|
|
153
|
+
: "agent busy — delivers when the turn ends";
|
|
154
|
+
console.log(c.green(" ✓ ") + c.dim(`message queued to #${id} (${why})`));
|
|
155
|
+
}
|
|
156
|
+
else if (data?.deliveredNow) {
|
|
157
|
+
const how = data.interrupted ? " (interrupted the running turn)" : " (agent was idle)";
|
|
158
|
+
console.log(c.green(" ✓ ") + c.dim(`message delivered now to #${id}${how}`));
|
|
159
|
+
}
|
|
160
|
+
else {
|
|
146
161
|
console.log(c.green(" ✓ ") + c.dim(`message sent to #${id}`));
|
|
162
|
+
}
|
|
147
163
|
return 0;
|
|
148
164
|
}
|
|
149
165
|
catch (e) {
|
|
@@ -381,6 +397,100 @@ export async function cmdPreview(args) {
|
|
|
381
397
|
return 1;
|
|
382
398
|
}
|
|
383
399
|
}
|
|
400
|
+
export async function cmdDev(args) {
|
|
401
|
+
const { rest, opts, error } = parseCommonFlags(args);
|
|
402
|
+
if (error) {
|
|
403
|
+
printErr(error);
|
|
404
|
+
return 1;
|
|
405
|
+
}
|
|
406
|
+
// `repoos dev list` · `repoos dev <name> start|stop|restart` · `repoos dev <name>`
|
|
407
|
+
// The command run is ALWAYS the one declared in repoos.toml, resolved by name.
|
|
408
|
+
const sub = rest[0];
|
|
409
|
+
if (!sub || sub === "list" || sub === "status") {
|
|
410
|
+
const api = new RepoOsApi({ port: opts.port });
|
|
411
|
+
try {
|
|
412
|
+
await ensureServer(api);
|
|
413
|
+
const data = (await api.requestOk("GET", "/api/dev/targets", undefined));
|
|
414
|
+
if (opts.json) {
|
|
415
|
+
printJson(data);
|
|
416
|
+
return 0;
|
|
417
|
+
}
|
|
418
|
+
if (data.errors?.length) {
|
|
419
|
+
for (const e of data.errors)
|
|
420
|
+
console.log(c.yellow(" ! ") + c.dim(e));
|
|
421
|
+
}
|
|
422
|
+
const targets = data.targets ?? [];
|
|
423
|
+
if (!targets.length) {
|
|
424
|
+
console.log(c.dim(" no dev targets declared in repoos.toml ([[dev.targets]])"));
|
|
425
|
+
return 0;
|
|
426
|
+
}
|
|
427
|
+
for (const t of targets) {
|
|
428
|
+
const dot = t.status === "running"
|
|
429
|
+
? c.green("●")
|
|
430
|
+
: t.status === "failed"
|
|
431
|
+
? c.red("●")
|
|
432
|
+
: t.status === "starting"
|
|
433
|
+
? c.yellow("●")
|
|
434
|
+
: c.dim("○");
|
|
435
|
+
const target = t.url ?? t.artifactPath ?? "";
|
|
436
|
+
console.log(` ${dot} ${t.name} ${c.dim(`[${t.kind}] ${t.status}`)}${target ? c.dim(` ${target}`) : ""}`);
|
|
437
|
+
if (t.error)
|
|
438
|
+
console.log(c.red(` ${t.error}`));
|
|
439
|
+
}
|
|
440
|
+
return 0;
|
|
441
|
+
}
|
|
442
|
+
catch (e) {
|
|
443
|
+
printErr(e.message);
|
|
444
|
+
return 1;
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
const name = sub;
|
|
448
|
+
const action = rest[1] ?? "status";
|
|
449
|
+
const valid = ["start", "stop", "restart", "status", "logs"];
|
|
450
|
+
if (!valid.includes(action)) {
|
|
451
|
+
printErr("Usage: repoos dev [list] · repoos dev <name> start|stop|restart|status|logs [--json] [--port N]");
|
|
452
|
+
return 1;
|
|
453
|
+
}
|
|
454
|
+
const api = new RepoOsApi({ port: opts.port });
|
|
455
|
+
try {
|
|
456
|
+
await ensureServer(api);
|
|
457
|
+
const base = `/api/dev/targets/${encodeURIComponent(name)}`;
|
|
458
|
+
if (action === "start" || action === "stop" || action === "restart") {
|
|
459
|
+
const data = (await api.requestOk("POST", `${base}/${action}`, {}));
|
|
460
|
+
if (opts.json) {
|
|
461
|
+
printJson(data);
|
|
462
|
+
return 0;
|
|
463
|
+
}
|
|
464
|
+
if (data.target?.error) {
|
|
465
|
+
printErr(`dev target "${name}" ${data.target.status}: ${data.target.error}`);
|
|
466
|
+
return 1;
|
|
467
|
+
}
|
|
468
|
+
console.log(c.green(" ✓ ") +
|
|
469
|
+
c.dim(`dev target "${name}" ${data.target?.status ?? action}${data.target?.url ? ` ${data.target.url}` : ""}`));
|
|
470
|
+
return 0;
|
|
471
|
+
}
|
|
472
|
+
if (action === "status" || action === "logs") {
|
|
473
|
+
const data = (await api.requestOk("GET", base, undefined));
|
|
474
|
+
if (opts.json) {
|
|
475
|
+
printJson(data);
|
|
476
|
+
return 0;
|
|
477
|
+
}
|
|
478
|
+
console.log(c.dim(` ${name}: ${data.target?.status ?? "unknown"}`));
|
|
479
|
+
if (data.target?.error)
|
|
480
|
+
console.log(c.red(` ${data.target.error}`));
|
|
481
|
+
if (action === "logs") {
|
|
482
|
+
for (const line of data.target?.log ?? [])
|
|
483
|
+
console.log(` ${line}`);
|
|
484
|
+
}
|
|
485
|
+
return 0;
|
|
486
|
+
}
|
|
487
|
+
return 0;
|
|
488
|
+
}
|
|
489
|
+
catch (e) {
|
|
490
|
+
printErr(e.message);
|
|
491
|
+
return 1;
|
|
492
|
+
}
|
|
493
|
+
}
|
|
384
494
|
export async function cmdConfig(args) {
|
|
385
495
|
const { rest, opts, error } = parseCommonFlags(args);
|
|
386
496
|
if (error) {
|
package/dist/commands/init.js
CHANGED
|
@@ -296,8 +296,13 @@ Problem / Desired UX / Acceptance criteria / Notes for AI is refused unless
|
|
|
296
296
|
\`--force\` is passed.
|
|
297
297
|
|
|
298
298
|
For tabbed views (e.g. Agents), prefer \`?tab=<id>\` routes
|
|
299
|
-
(\`/agents?tab=detected\`) over click steps to reach the right tab
|
|
300
|
-
|
|
299
|
+
(\`/agents?tab=detected\`) over click steps to reach the right tab; a task drawer
|
|
300
|
+
is reached the same way (\`/work?task=<id>&tab=changes\`), and always
|
|
301
|
+
set \`highlight\` to the changed elements. Reach a populated state with a
|
|
302
|
+
\`route\` or a named \`state\` fixture, never with \`steps\` that click a
|
|
303
|
+
placeholder selector (\`data-task-id "9999"\` and the like) — such a step times
|
|
304
|
+
out and the capture lands on a loading state instead of the content, which is
|
|
305
|
+
reported as a failed step, not a match. A declared \`highlight\` or \`selector\`
|
|
301
306
|
that matches nothing at capture time records a visible warning — capture still
|
|
302
307
|
succeeds. Declared shots default to the whole visible window (\`fullPage:
|
|
303
308
|
false\`) with changed elements outlined via \`highlight\`; \`selector\` (element
|
|
@@ -676,10 +676,63 @@ function makeAuditFixture() {
|
|
|
676
676
|
mime: "image/png",
|
|
677
677
|
});
|
|
678
678
|
}
|
|
679
|
+
// #0753: handoff verification evidence so the Changes tab renders the
|
|
680
|
+
// per-shot check/cross verdict icon and the "Handoff checked …" status line
|
|
681
|
+
// — both are real text/colour the audit must gate. One matching shot and
|
|
682
|
+
// one checking shot with a failed step, plus a console/overflow issue so
|
|
683
|
+
// the popover's content is present too.
|
|
684
|
+
const shots = localShotStore(config, "0001");
|
|
685
|
+
const first = shots.list()[0];
|
|
686
|
+
const second = shots.list()[1];
|
|
687
|
+
const savedUrls = [];
|
|
688
|
+
if (first)
|
|
689
|
+
savedUrls.push(first.url);
|
|
690
|
+
if (second)
|
|
691
|
+
savedUrls.push(second.url);
|
|
692
|
+
const cacheDir = join(root, config.cacheDir || ".repoos", "ui-verification");
|
|
693
|
+
mkdirSync(cacheDir, { recursive: true });
|
|
694
|
+
writeFileSync(join(cacheDir, "0001.json"), JSON.stringify({
|
|
695
|
+
at: new Date().toISOString(),
|
|
696
|
+
issues: [
|
|
697
|
+
{ kind: "console", message: "TypeError: fixture is undefined" },
|
|
698
|
+
{ kind: "overflow", message: "content wider than viewport", viewportWidth: 1280 },
|
|
699
|
+
],
|
|
700
|
+
blankShots: [],
|
|
701
|
+
captures: savedUrls.length,
|
|
702
|
+
sourceIdentity: "fixture0001",
|
|
703
|
+
evidenceDir: "work/.attachments/0001/shots",
|
|
704
|
+
captureDetails: [
|
|
705
|
+
{
|
|
706
|
+
target: "default",
|
|
707
|
+
route: "/",
|
|
708
|
+
label: "Dashboard",
|
|
709
|
+
url: "http://127.0.0.1:0/",
|
|
710
|
+
finalRoute: "/",
|
|
711
|
+
routeMatched: true,
|
|
712
|
+
assertions: [],
|
|
713
|
+
assertionsPassed: 0,
|
|
714
|
+
assertionsChecked: 0,
|
|
715
|
+
...(savedUrls[0] ? { shot: { name: "a", path: "", url: savedUrls[0] } } : {}),
|
|
716
|
+
},
|
|
717
|
+
{
|
|
718
|
+
target: "default",
|
|
719
|
+
route: "/",
|
|
720
|
+
label: "Auto shot",
|
|
721
|
+
url: "http://127.0.0.1:0/",
|
|
722
|
+
finalRoute: "/",
|
|
723
|
+
routeMatched: true,
|
|
724
|
+
targetWarnings: ['click [data-test-id="fullscreen"]: Timeout 5000ms exceeded'],
|
|
725
|
+
assertions: [],
|
|
726
|
+
assertionsPassed: 0,
|
|
727
|
+
assertionsChecked: 0,
|
|
728
|
+
...(savedUrls[1] ? { shot: { name: "b", path: "", url: savedUrls[1] } } : {}),
|
|
729
|
+
},
|
|
730
|
+
],
|
|
731
|
+
}));
|
|
679
732
|
}
|
|
680
733
|
catch {
|
|
681
|
-
// The shot store is disk-only and cannot realistically fail
|
|
682
|
-
// does, the Changes tab simply has
|
|
734
|
+
// The shot/verification store is disk-only and cannot realistically fail
|
|
735
|
+
// here; if it does, the Changes tab simply has less to audit.
|
|
683
736
|
}
|
|
684
737
|
return root;
|
|
685
738
|
}
|
package/dist/core/config.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Agent, BuiltInAgentConfig, DistributionConfig, PreviewConfig, RepoOSConfig, AreaConfig } from "./types.js";
|
|
2
|
+
export { parseDevTargets } from "./dev-targets.js";
|
|
2
3
|
/** Default display labels for board columns, keyed by canonical status ID. */
|
|
3
4
|
export declare const DEFAULT_COLUMN_LABELS: Record<string, string>;
|
|
4
5
|
/** Coding agents an Agent can run under. */
|
package/dist/core/config.js
CHANGED
|
@@ -8,9 +8,14 @@ import { cpus } from "node:os";
|
|
|
8
8
|
import { basename, dirname, join, resolve } from "node:path";
|
|
9
9
|
import { STATUSES } from "./types.js";
|
|
10
10
|
import { parseCheckPlanConfig } from "./check-plan.js";
|
|
11
|
+
import { parseDevTargets } from "./dev-targets.js";
|
|
11
12
|
import { parseTailscaleHosts } from "./remote-hosts.js";
|
|
12
13
|
import { DEFAULT_STORAGE_PROVIDER_ID } from "./storage/registry.js";
|
|
13
14
|
import { stripTomlComment, unquoteTomlString } from "./toml-line.js";
|
|
15
|
+
// `parseDevTargets` (#0747) lives in the node-free `core/dev-targets.ts` so the
|
|
16
|
+
// browser bundle can validate a target through the SAME function the server
|
|
17
|
+
// uses (#0749). Re-exported for the existing core/CLI importers.
|
|
18
|
+
export { parseDevTargets } from "./dev-targets.js";
|
|
14
19
|
/** Default display labels for board columns, keyed by canonical status ID. */
|
|
15
20
|
export const DEFAULT_COLUMN_LABELS = {
|
|
16
21
|
draft: "Draft",
|
|
@@ -1106,8 +1111,16 @@ export function loadConfig(rootArg, options = {}) {
|
|
|
1106
1111
|
enabled: typeof devInspectorEnabled === "boolean" ? devInspectorEnabled : true,
|
|
1107
1112
|
editorCommand: typeof devInspectorEditor === "string" ? devInspectorEditor.trim() : "",
|
|
1108
1113
|
};
|
|
1109
|
-
cfg.dev = { inspector };
|
|
1110
|
-
}
|
|
1114
|
+
cfg.dev = { ...cfg.dev, inspector };
|
|
1115
|
+
}
|
|
1116
|
+
// [[dev.targets]] (#0747) — the user-declared runnable dev targets. Bad
|
|
1117
|
+
// rows are recorded as validation errors on the config, not silently
|
|
1118
|
+
// dropped: the Dev page and CLI surface them so a typo is visible.
|
|
1119
|
+
const devTargets = parseDevTargets(parsed);
|
|
1120
|
+
if (devTargets.targets.length)
|
|
1121
|
+
cfg.dev = { ...cfg.dev, targets: devTargets.targets };
|
|
1122
|
+
if (devTargets.errors.length)
|
|
1123
|
+
cfg.devTargetErrors = devTargets.errors;
|
|
1111
1124
|
if (typeof get("ntfyEnabled") === "boolean")
|
|
1112
1125
|
cfg.ntfyEnabled = get("ntfyEnabled");
|
|
1113
1126
|
if (typeof get("ntfyTopic") === "string")
|
|
@@ -2431,6 +2444,21 @@ export function getConfigSchema() {
|
|
|
2431
2444
|
default: "",
|
|
2432
2445
|
description: "Optional editor launcher, e.g. `zed {file}:{line}`. Placeholders `{file}` and `{line}`; omit `{line}` to open without a line number.",
|
|
2433
2446
|
},
|
|
2447
|
+
{
|
|
2448
|
+
// The Settings control is a dedicated hand-rendered card on Advanced
|
|
2449
|
+
// (#0749), never an auto-rendered General row — like `areas`, this schema
|
|
2450
|
+
// entry exists so the search overlay and the "does this key have a UI
|
|
2451
|
+
// row?" resolver can find it.
|
|
2452
|
+
key: "dev.targets",
|
|
2453
|
+
label: "Dev targets",
|
|
2454
|
+
type: "array",
|
|
2455
|
+
tier: "live",
|
|
2456
|
+
restartRequired: false,
|
|
2457
|
+
default: [],
|
|
2458
|
+
description: "The things you run yourself while developing — a local HMR web server, a debug build, a native app process — " +
|
|
2459
|
+
"as opposed to task previews, which RepoOS manages for a task's worktree. Only commands " +
|
|
2460
|
+
"declared here can be started; edit them under Advanced → Dev targets.",
|
|
2461
|
+
},
|
|
2434
2462
|
// [board.columns] — display-only label overrides (#0396).
|
|
2435
2463
|
...STATUSES.map((status) => ({
|
|
2436
2464
|
key: `board.columns.${status}`,
|
|
@@ -2516,6 +2544,16 @@ export const SUPPORTED_TOML_KEYS = [
|
|
|
2516
2544
|
"preview.services.cwd",
|
|
2517
2545
|
"preview.services.readyPath",
|
|
2518
2546
|
"preview.services.readyTimeoutMs",
|
|
2547
|
+
// Dev targets (#0747) — the user-runnable things the Dev page controls.
|
|
2548
|
+
// Declared as a repeatable `[[dev.targets]]` table; each row is one target.
|
|
2549
|
+
"dev.targets.name",
|
|
2550
|
+
"dev.targets.kind",
|
|
2551
|
+
"dev.targets.command",
|
|
2552
|
+
"dev.targets.url",
|
|
2553
|
+
"dev.targets.artifactPath",
|
|
2554
|
+
"dev.targets.label",
|
|
2555
|
+
"dev.targets.healthCheck.url",
|
|
2556
|
+
"dev.targets.healthCheck.file",
|
|
2519
2557
|
// Preview-only overrides (#0464): a `[preview.<base path>]` table applied
|
|
2520
2558
|
// only by the preview/UI-test preview runtime. auth.enabled is the headline
|
|
2521
2559
|
// case; any supported base key can be overridden the same way.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `[[dev.targets]]` parsing (#0747, extracted node-free in #0749).
|
|
3
|
+
*
|
|
4
|
+
* The user-declared runnable dev targets are parsed here rather than in
|
|
5
|
+
* `core/config.ts` so the SAME validator runs in the browser bundle: the
|
|
6
|
+
* Settings control composes a row and validates it through `parseDevTargets`,
|
|
7
|
+
* exactly as the server re-validates the submitted list. `core/config.ts` has
|
|
8
|
+
* node imports (`node:fs`, `node:os`, `node:path`) and cannot be pulled into the
|
|
9
|
+
* Vite browser build, so this pure function lives on its own.
|
|
10
|
+
*
|
|
11
|
+
* Unlike `[preview]`, which resolves cleanly to "nothing" and drops bad rows, a
|
|
12
|
+
* dev target is something the user asked the server to run, so an unusable row
|
|
13
|
+
* is a loud validation error rather than a silent drop: a target with a missing
|
|
14
|
+
* name/command/kind or a conflicting field is reported with a clear message.
|
|
15
|
+
*/
|
|
16
|
+
import type { DevTargetConfig } from "./types.js";
|
|
17
|
+
/**
|
|
18
|
+
* Parse the `[[dev.targets]]` array of tables — the user-declared runnable dev
|
|
19
|
+
* targets. Returns `{ targets, errors }`; `loadConfig` records the errors on
|
|
20
|
+
* the config so the API/UI can surface them.
|
|
21
|
+
*/
|
|
22
|
+
export declare function parseDevTargets(parsed: Record<string, unknown>): {
|
|
23
|
+
targets: DevTargetConfig[];
|
|
24
|
+
errors: string[];
|
|
25
|
+
};
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parse the flat TOML parser's leftover inline-table string for `healthCheck`
|
|
3
|
+
* (`'{ url = "..." }'` — `parseFlatToml` has no inline-table support, so the
|
|
4
|
+
* whole table stays a string). Returns the url/file fields, or null when the
|
|
5
|
+
* string is not a `{ … }` table at all, so the caller can report the right
|
|
6
|
+
* error. Quoted string values only, which is all a URL or a file path needs.
|
|
7
|
+
*/
|
|
8
|
+
function parseInlineHealthCheck(raw) {
|
|
9
|
+
const s = raw.trim();
|
|
10
|
+
if (!s.startsWith("{") || !s.endsWith("}"))
|
|
11
|
+
return null;
|
|
12
|
+
const out = {};
|
|
13
|
+
for (const m of s.slice(1, -1).matchAll(/([A-Za-z0-9_]+)\s*=\s*(?:"([^"]*)"|'([^']*)')/g)) {
|
|
14
|
+
const value = (m[2] ?? m[3] ?? "").trim();
|
|
15
|
+
if (!value)
|
|
16
|
+
continue;
|
|
17
|
+
if (m[1] === "url")
|
|
18
|
+
out.url = value;
|
|
19
|
+
else if (m[1] === "file")
|
|
20
|
+
out.file = value;
|
|
21
|
+
}
|
|
22
|
+
return out;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Parse the `[[dev.targets]]` array of tables — the user-declared runnable dev
|
|
26
|
+
* targets. Returns `{ targets, errors }`; `loadConfig` records the errors on
|
|
27
|
+
* the config so the API/UI can surface them.
|
|
28
|
+
*/
|
|
29
|
+
export function parseDevTargets(parsed) {
|
|
30
|
+
const raw = parsed["dev.targets"];
|
|
31
|
+
const targets = [];
|
|
32
|
+
const errors = [];
|
|
33
|
+
if (raw === undefined)
|
|
34
|
+
return { targets, errors };
|
|
35
|
+
if (!Array.isArray(raw)) {
|
|
36
|
+
errors.push("[dev.targets] must be an array of tables");
|
|
37
|
+
return { targets, errors };
|
|
38
|
+
}
|
|
39
|
+
const seen = new Set();
|
|
40
|
+
for (const entry of raw) {
|
|
41
|
+
if (typeof entry !== "object" || entry === null || Array.isArray(entry)) {
|
|
42
|
+
errors.push("[dev.targets] ignoring a non-table row");
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
const r = entry;
|
|
46
|
+
const name = typeof r.name === "string" ? r.name.trim() : "";
|
|
47
|
+
if (!name) {
|
|
48
|
+
errors.push("[dev.targets] a target is missing a name");
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
if (seen.has(name)) {
|
|
52
|
+
errors.push(`[dev.targets] duplicate target name "${name}"`);
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
const kindRaw = typeof r.kind === "string" ? r.kind.trim() : "";
|
|
56
|
+
if (kindRaw !== "server" && kindRaw !== "artifact" && kindRaw !== "process") {
|
|
57
|
+
errors.push(`[dev.targets] ${name}: kind must be "server", "artifact" or "process"${kindRaw ? ` (got "${kindRaw}")` : ""}`);
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
const command = typeof r.command === "string" ? r.command.trim() : "";
|
|
61
|
+
if (!command) {
|
|
62
|
+
errors.push(`[dev.targets] ${name}: a command is required`);
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
const target = { name, kind: kindRaw, command };
|
|
66
|
+
const url = typeof r.url === "string" ? r.url.trim() : "";
|
|
67
|
+
const artifactPath = typeof r.artifactPath === "string" ? r.artifactPath.trim() : "";
|
|
68
|
+
if (kindRaw === "server" && !url) {
|
|
69
|
+
// A long-lived target with no URL is a `process`, not a `server` — point
|
|
70
|
+
// the user at the right kind rather than leaving them stuck.
|
|
71
|
+
errors.push(`[dev.targets] ${name}: a "server" target needs a url (use kind = "process" for a long-lived target with no URL)`);
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
if (kindRaw === "artifact" && !artifactPath) {
|
|
75
|
+
errors.push(`[dev.targets] ${name}: an "artifact" target needs an artifactPath`);
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
if (kindRaw === "server" && artifactPath) {
|
|
79
|
+
errors.push(`[dev.targets] ${name}: a "server" target cannot have an artifactPath`);
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
if (kindRaw === "artifact" && url) {
|
|
83
|
+
errors.push(`[dev.targets] ${name}: an "artifact" target cannot have a url`);
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
// A process has neither a URL nor a build artifact — it is healthy while it
|
|
87
|
+
// is alive, which is its health check. Reject the conflicting fields so a
|
|
88
|
+
// typo can never silently change what the target means.
|
|
89
|
+
if (kindRaw === "process" && url) {
|
|
90
|
+
errors.push(`[dev.targets] ${name}: a "process" target cannot have a url`);
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
if (kindRaw === "process" && artifactPath) {
|
|
94
|
+
errors.push(`[dev.targets] ${name}: a "process" target cannot have an artifactPath`);
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
if (url)
|
|
98
|
+
target.url = url;
|
|
99
|
+
if (artifactPath)
|
|
100
|
+
target.artifactPath = artifactPath;
|
|
101
|
+
const label = typeof r.label === "string" ? r.label.trim() : "";
|
|
102
|
+
if (label)
|
|
103
|
+
target.label = label;
|
|
104
|
+
// healthCheck arrives in one of three shapes, all accepted here so the
|
|
105
|
+
// documented `healthCheck = { url = "..." }` actually works:
|
|
106
|
+
// - an object, from a real TOML parser (or a test passing rows directly);
|
|
107
|
+
// - the raw inline-table string the flat line parser leaves behind
|
|
108
|
+
// (`'{ url = "..." }'`, since it has no inline-table support);
|
|
109
|
+
// - dotted keys `healthCheck.url` / `healthCheck.file`, which the flat
|
|
110
|
+
// parser keeps as literal keys on the row.
|
|
111
|
+
const hcRaw = r.healthCheck;
|
|
112
|
+
let hcUrl = typeof r["healthCheck.url"] === "string" ? r["healthCheck.url"].trim() : "";
|
|
113
|
+
let hcFile = typeof r["healthCheck.file"] === "string" ? r["healthCheck.file"].trim() : "";
|
|
114
|
+
const hasInlineKeys = r["healthCheck.url"] !== undefined || r["healthCheck.file"] !== undefined;
|
|
115
|
+
if (hcRaw !== undefined) {
|
|
116
|
+
if (typeof hcRaw === "string") {
|
|
117
|
+
const parsedHc = parseInlineHealthCheck(hcRaw);
|
|
118
|
+
if (!parsedHc) {
|
|
119
|
+
errors.push(`[dev.targets] ${name}: healthCheck must be a table with url or file`);
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
hcUrl = hcUrl || parsedHc.url || "";
|
|
123
|
+
hcFile = hcFile || parsedHc.file || "";
|
|
124
|
+
}
|
|
125
|
+
else if (typeof hcRaw === "object" && hcRaw !== null && !Array.isArray(hcRaw)) {
|
|
126
|
+
const hc = hcRaw;
|
|
127
|
+
hcUrl = hcUrl || (typeof hc.url === "string" ? hc.url.trim() : "");
|
|
128
|
+
hcFile = hcFile || (typeof hc.file === "string" ? hc.file.trim() : "");
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
errors.push(`[dev.targets] ${name}: healthCheck must be a table with url or file`);
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
if (hcUrl || hcFile) {
|
|
136
|
+
target.healthCheck = {
|
|
137
|
+
...(hcUrl ? { url: hcUrl } : {}),
|
|
138
|
+
...(hcFile ? { file: hcFile } : {}),
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
else if (hcRaw !== undefined || hasInlineKeys) {
|
|
142
|
+
errors.push(`[dev.targets] ${name}: healthCheck needs a url or a file`);
|
|
143
|
+
continue;
|
|
144
|
+
}
|
|
145
|
+
// A process is healthy while its process is alive; a readiness check would
|
|
146
|
+
// only muddy that. Reject one rather than silently ignore it.
|
|
147
|
+
if (kindRaw === "process" && target.healthCheck) {
|
|
148
|
+
errors.push(`[dev.targets] ${name}: a "process" target cannot have a healthCheck (it is running while its process is alive)`);
|
|
149
|
+
continue;
|
|
150
|
+
}
|
|
151
|
+
seen.add(name);
|
|
152
|
+
targets.push(target);
|
|
153
|
+
}
|
|
154
|
+
return { targets, errors };
|
|
155
|
+
}
|
package/dist/core/git.d.ts
CHANGED
|
@@ -407,6 +407,12 @@ export declare function gitInit(root: string): boolean;
|
|
|
407
407
|
* where 0023's surgical `commitNewFile` applies. Fail-soft: null on failure.
|
|
408
408
|
*/
|
|
409
409
|
export declare function gitCommitAll(root: string, message: string): string | null;
|
|
410
|
+
/**
|
|
411
|
+
* The short HEAD sha of `root`, or null when git is unavailable or the path is
|
|
412
|
+
* not a repository (#0755). Used to tie handoff UI evidence to the exact tree
|
|
413
|
+
* it captured, so a later commit can be flagged as a stale capture.
|
|
414
|
+
*/
|
|
415
|
+
export declare function shortHeadOf(root: string): string | null;
|
|
410
416
|
export interface CommitNewFileResult {
|
|
411
417
|
ok: boolean;
|
|
412
418
|
/** Short commit hash (when committed). */
|
|
@@ -638,6 +644,18 @@ export interface UncommittedWorkFilesOptions {
|
|
|
638
644
|
* the default answer for handoff and pre-merge guards.
|
|
639
645
|
*/
|
|
640
646
|
export declare function uncommittedWorkFiles(root: string, filter?: WorkFileFilter, opts?: UncommittedWorkFilesOptions): Promise<string[]>;
|
|
647
|
+
/**
|
|
648
|
+
* Whether a path that conflicted between two sides is one the merge is allowed
|
|
649
|
+
* to resolve on its own: it matches an `autoResolve` entry (generated output,
|
|
650
|
+
* the closing task's own file) or an `autoResolveOurs` entry (unrelated task
|
|
651
|
+
* files, where main's copy wins). A conflicted path matching neither is a REAL
|
|
652
|
+
* conflict. This is the single definition of "a real conflict" shared by the
|
|
653
|
+
* real merge and `mergeBranch`'s dry-run pre-flight, so the two can never drift.
|
|
654
|
+
*/
|
|
655
|
+
export declare function isResolvableConflict(path: string, opts: {
|
|
656
|
+
autoResolve?: string[];
|
|
657
|
+
autoResolveOurs?: string[];
|
|
658
|
+
}): boolean;
|
|
641
659
|
/**
|
|
642
660
|
* Merge `branch` into the CURRENT checkout — the main worktree, never the
|
|
643
661
|
* task's worktree. Default merge semantics: fast-forward when main is an
|
package/dist/core/git.js
CHANGED
|
@@ -1116,6 +1116,15 @@ export function gitCommitAll(root, message) {
|
|
|
1116
1116
|
notifyGitMutation(root, "commit");
|
|
1117
1117
|
return git(root, ["rev-parse", "--short", "HEAD"]);
|
|
1118
1118
|
}
|
|
1119
|
+
/**
|
|
1120
|
+
* The short HEAD sha of `root`, or null when git is unavailable or the path is
|
|
1121
|
+
* not a repository (#0755). Used to tie handoff UI evidence to the exact tree
|
|
1122
|
+
* it captured, so a later commit can be flagged as a stale capture.
|
|
1123
|
+
*/
|
|
1124
|
+
export function shortHeadOf(root) {
|
|
1125
|
+
const sha = git(root, ["rev-parse", "--short", "HEAD"]);
|
|
1126
|
+
return sha ? sha.trim() || null : null;
|
|
1127
|
+
}
|
|
1119
1128
|
/**
|
|
1120
1129
|
* Surgically commit a single new file with the user's own git identity.
|
|
1121
1130
|
*
|
|
@@ -1518,7 +1527,7 @@ function blockingFiles(stderr) {
|
|
|
1518
1527
|
* conflict. This is the single definition of "a real conflict" shared by the
|
|
1519
1528
|
* real merge and `mergeBranch`'s dry-run pre-flight, so the two can never drift.
|
|
1520
1529
|
*/
|
|
1521
|
-
function isResolvableConflict(path, opts) {
|
|
1530
|
+
export function isResolvableConflict(path, opts) {
|
|
1522
1531
|
const matches = (rule, p) => p === rule || p.startsWith(rule.endsWith("/") ? rule : rule + "/");
|
|
1523
1532
|
return [...(opts.autoResolve ?? []), ...(opts.autoResolveOurs ?? [])].some((r) => matches(r, path));
|
|
1524
1533
|
}
|
package/dist/core/models.js
CHANGED
|
@@ -293,10 +293,16 @@ const opencodeAdapter = {
|
|
|
293
293
|
};
|
|
294
294
|
const args = opts.refresh ? ["models", "--refresh"] : ["models"];
|
|
295
295
|
const timeoutMs = opts.timeoutMs ?? MODELS_TIMEOUT_MS;
|
|
296
|
-
|
|
296
|
+
let out = await spawnModels(bin, args, {
|
|
297
297
|
timeoutMs,
|
|
298
298
|
cwd: opts.cwd,
|
|
299
299
|
});
|
|
300
|
+
// Some opencode builds (v2.0.11 among them) reject `--refresh` with exit 1.
|
|
301
|
+
// Retry the plain probe: the caller has already bypassed RepoOS's own cache,
|
|
302
|
+
// so this is still a fresh list rather than the cached one.
|
|
303
|
+
if (opts.refresh && out.code !== 0 && /Unrecognized flag: --refresh/.test(out.stderr)) {
|
|
304
|
+
out = await spawnModels(bin, ["models"], { timeoutMs, cwd: opts.cwd });
|
|
305
|
+
}
|
|
300
306
|
const error = probeError(bin, out, timeoutMs);
|
|
301
307
|
return {
|
|
302
308
|
supported: true,
|