@ebrindley/build 0.0.0-stage → 1.42.1-rc28
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/.build-project/providers/catalog.json +13951 -0
- package/.build-project/providers/pricing.json +1978 -0
- package/.build-project/providers/registry.json +4103 -0
- package/.github/SECURITY.md +75 -0
- package/.nvmrc +1 -0
- package/CHANGELOG.md +661 -0
- package/CODE_OF_CONDUCT.md +44 -0
- package/CONTRIBUTING.md +24 -0
- package/INSTALL.md +623 -0
- package/LICENSE +21 -0
- package/README.md +118 -2
- package/THIRD_PARTY_NOTICES.txt +26 -0
- package/dist/ai-judge-UE5UOYOO.js +191 -0
- package/dist/allowlist-grounding-KPLN6NC5.js +16 -0
- package/dist/allowlist-utils-MZZKKXRD.js +31 -0
- package/dist/apply-completion-mode-EM37UZHB.js +110 -0
- package/dist/artifact-migrator-WPACNSEP.js +276 -0
- package/dist/ask-2OZ4JFQR.js +176 -0
- package/dist/auth-6UKBTJUQ.js +185 -0
- package/dist/auth-H5KJL6HL.js +165 -0
- package/dist/auth-LVJRJDMU.js +12 -0
- package/dist/auth-NHZOCNRR.js +94 -0
- package/dist/auth-PBXHWXGW.js +95 -0
- package/dist/auth-T7Y5DCAH.js +91 -0
- package/dist/auth-TVVKCHQW.js +13 -0
- package/dist/auth-UHB2UCSS.js +97 -0
- package/dist/auth-VACA3VUL.js +98 -0
- package/dist/auth-VVLC77S3.js +44 -0
- package/dist/auth-liveness-XO4AGDDD.js +53 -0
- package/dist/autoloop-cleanup-SI3VGAAR.js +106 -0
- package/dist/autoloop-evidence-gates-J5GG5YQB.js +39 -0
- package/dist/autoloop-gate-policy-SUNAEP6Q.js +169 -0
- package/dist/autoloop-helpers-VQGQNTT6.js +52 -0
- package/dist/autoloop-ledger-P6TIDP7C.js +96 -0
- package/dist/autoloop-ledger-subscriber-HFAGOZXH.js +161 -0
- package/dist/autoloop-run-defaults-GWGZBNT7.js +27 -0
- package/dist/autoloop-run-lock-GBWRM5A2.js +197 -0
- package/dist/autoloop-success-C32QVWOP.js +93 -0
- package/dist/autoloop-termination-summary-GI6IBQWD.js +58 -0
- package/dist/autoloop-trajectory-AMKSQISD.js +70 -0
- package/dist/autoloop-wall-clock-T7ZVIQOC.js +12 -0
- package/dist/automatic-branch-cleanup-R62X2C5O.js +49 -0
- package/dist/autonomous-loop-controller-2WL363LW.js +4386 -0
- package/dist/backend-YUTFDZXZ.js +30 -0
- package/dist/background-executor-Z3ODTMD7.js +260 -0
- package/dist/backlog-75QPEAMW.js +403 -0
- package/dist/backlog-execution-intent-GWUV5TUK.js +19 -0
- package/dist/backup-active-store-XHWLN34M.js +16 -0
- package/dist/backup-machine-stores-UI4LTJOY.js +251 -0
- package/dist/backup-telemetry-db-Z4ICYCNW.js +26 -0
- package/dist/branch-archive-manager-FMSQ7YJF.js +18 -0
- package/dist/branch-cleanup-manager-ST6FJGND.js +35 -0
- package/dist/build-gate-7NKWPY62.js +68 -0
- package/dist/build-root-S7DINODY.js +18 -0
- package/dist/change-summary-R6CB6VXJ.js +50 -0
- package/dist/chunk-24MNKKOM.js +173 -0
- package/dist/chunk-2H6VZFIO.js +235 -0
- package/dist/chunk-2JIX3EKV.js +39 -0
- package/dist/chunk-2KO7HVZM.js +106 -0
- package/dist/chunk-2L36U25O.js +100 -0
- package/dist/chunk-2NMNFUQA.js +475 -0
- package/dist/chunk-2OUAEH67.js +83 -0
- package/dist/chunk-2VLJUXJU.js +115 -0
- package/dist/chunk-2VUEDIUM.js +77 -0
- package/dist/chunk-2Y2IIHPI.js +430 -0
- package/dist/chunk-2YRG3LHZ.js +220 -0
- package/dist/chunk-2Z5Q3SUY.js +65 -0
- package/dist/chunk-32IYXIE5.js +873 -0
- package/dist/chunk-33IGPPUI.js +292 -0
- package/dist/chunk-352PCJLK.js +283 -0
- package/dist/chunk-35J4NE6S.js +226 -0
- package/dist/chunk-3C7WBIVK.js +1016 -0
- package/dist/chunk-3H3EY6U7.js +1225 -0
- package/dist/chunk-3H4MWYIC.js +198 -0
- package/dist/chunk-3HHWQR3N.js +2479 -0
- package/dist/chunk-3JKNRYEE.js +14 -0
- package/dist/chunk-3LECCYZY.js +128 -0
- package/dist/chunk-3LOY6YZI.js +852 -0
- package/dist/chunk-3M57DADF.js +44 -0
- package/dist/chunk-3NOTLVLG.js +3803 -0
- package/dist/chunk-3OPP2OZB.js +1480 -0
- package/dist/chunk-3P5IN5E7.js +9 -0
- package/dist/chunk-3PL22IYZ.js +20 -0
- package/dist/chunk-3REDAJUJ.js +14 -0
- package/dist/chunk-3S2R4XJI.js +203 -0
- package/dist/chunk-3UBZI5DW.js +61 -0
- package/dist/chunk-3VV5OBGG.js +308 -0
- package/dist/chunk-3WY5TU2O.js +823 -0
- package/dist/chunk-43OKHTW4.js +82 -0
- package/dist/chunk-45KUJBDI.js +112 -0
- package/dist/chunk-47X5LM7B.js +224 -0
- package/dist/chunk-4B6FQJ77.js +268 -0
- package/dist/chunk-4BTDUT2S.js +42 -0
- package/dist/chunk-4DJL2VXA.js +24 -0
- package/dist/chunk-4EBSXZ73.js +48 -0
- package/dist/chunk-4QKP6I4C.js +294 -0
- package/dist/chunk-4U6XK2DG.js +300 -0
- package/dist/chunk-4UMRUFBD.js +132 -0
- package/dist/chunk-4US4SYJ4.js +569 -0
- package/dist/chunk-4ZPLWEZO.js +154 -0
- package/dist/chunk-56WPYDJH.js +624 -0
- package/dist/chunk-57WRCJJW.js +50 -0
- package/dist/chunk-5AW4RMNG.js +24 -0
- package/dist/chunk-5EQN56OZ.js +155 -0
- package/dist/chunk-5F43TUIN.js +38 -0
- package/dist/chunk-5FKHIKTS.js +115 -0
- package/dist/chunk-5HDP7XZG.js +91 -0
- package/dist/chunk-5KQETTNS.js +152 -0
- package/dist/chunk-5PDVN2KO.js +498 -0
- package/dist/chunk-5UBIFVRD.js +509 -0
- package/dist/chunk-5YDE3Q62.js +46 -0
- package/dist/chunk-626AJVMU.js +302 -0
- package/dist/chunk-633XZ7UF.js +3583 -0
- package/dist/chunk-63DHNHGA.js +236 -0
- package/dist/chunk-666656AR.js +568 -0
- package/dist/chunk-67YRJPJO.js +19 -0
- package/dist/chunk-6CAU7VBA.js +20 -0
- package/dist/chunk-6CB3KJRY.js +21 -0
- package/dist/chunk-6DBMALXL.js +29 -0
- package/dist/chunk-6E25C4IA.js +269 -0
- package/dist/chunk-6FIBNIQU.js +73 -0
- package/dist/chunk-6G57FYBV.js +189 -0
- package/dist/chunk-6KZKRTG3.js +4885 -0
- package/dist/chunk-6LAH2UV2.js +525 -0
- package/dist/chunk-6PZY2TTU.js +921 -0
- package/dist/chunk-6T6NHXK4.js +230 -0
- package/dist/chunk-6TBEX4R4.js +432 -0
- package/dist/chunk-6TRD7TEE.js +911 -0
- package/dist/chunk-6XCP2RAI.js +47 -0
- package/dist/chunk-726G6WDL.js +351 -0
- package/dist/chunk-75EMT7BF.js +616 -0
- package/dist/chunk-762ACDZJ.js +4696 -0
- package/dist/chunk-77I6G4CO.js +1 -0
- package/dist/chunk-7DJ6SQH3.js +510 -0
- package/dist/chunk-7HPCIOMA.js +1383 -0
- package/dist/chunk-7HYBSRPZ.js +17503 -0
- package/dist/chunk-7KBEOPVB.js +73 -0
- package/dist/chunk-7LHJDJB3.js +2222 -0
- package/dist/chunk-7NVJMH52.js +306 -0
- package/dist/chunk-7RMARDVH.js +33 -0
- package/dist/chunk-7SEWU4QG.js +36 -0
- package/dist/chunk-7TUTZTI2.js +911 -0
- package/dist/chunk-7VBDFPUM.js +340 -0
- package/dist/chunk-7VRJHTGZ.js +6406 -0
- package/dist/chunk-7YAOUUKK.js +493 -0
- package/dist/chunk-AAAODV76.js +860 -0
- package/dist/chunk-AB4HUJVQ.js +339 -0
- package/dist/chunk-AEQWV746.js +611 -0
- package/dist/chunk-AHU3FKPA.js +11639 -0
- package/dist/chunk-AISTV5XU.js +226 -0
- package/dist/chunk-AJBTKGJZ.js +48 -0
- package/dist/chunk-AJJNW7XT.js +248 -0
- package/dist/chunk-AJN5Y5YZ.js +160 -0
- package/dist/chunk-ALDTFNZ3.js +150 -0
- package/dist/chunk-ARARVIZK.js +281 -0
- package/dist/chunk-ATBM6AW5.js +53 -0
- package/dist/chunk-ATKEKM3E.js +206 -0
- package/dist/chunk-AUJLW6JZ.js +92 -0
- package/dist/chunk-AY3MHEFM.js +24 -0
- package/dist/chunk-B7PYTV72.js +236 -0
- package/dist/chunk-B7YRSULE.js +1423 -0
- package/dist/chunk-BAWJNMWF.js +339 -0
- package/dist/chunk-BBPIILO2.js +88 -0
- package/dist/chunk-BD3PGW6A.js +957 -0
- package/dist/chunk-BDPYFAB4.js +44 -0
- package/dist/chunk-BIUV23HH.js +729 -0
- package/dist/chunk-BQ3VAGXH.js +243 -0
- package/dist/chunk-BQJOGAWT.js +31 -0
- package/dist/chunk-BT7EG7CO.js +68 -0
- package/dist/chunk-BV3XQQLU.js +27 -0
- package/dist/chunk-BY6ODHNZ.js +78 -0
- package/dist/chunk-BZRLSZNV.js +79 -0
- package/dist/chunk-C3DH3NCY.js +2773 -0
- package/dist/chunk-C3KCMAJP.js +756 -0
- package/dist/chunk-C7AGUJ5K.js +267 -0
- package/dist/chunk-CBSWKQCX.js +342 -0
- package/dist/chunk-CE5OZBYY.js +21 -0
- package/dist/chunk-CFCVYHSW.js +373 -0
- package/dist/chunk-CHA2HDE5.js +126 -0
- package/dist/chunk-CIHWPGS5.js +146 -0
- package/dist/chunk-CJBSZX3F.js +127 -0
- package/dist/chunk-CLA6QIJM.js +43 -0
- package/dist/chunk-CPSVQR2I.js +365 -0
- package/dist/chunk-CRPRVNQ4.js +254 -0
- package/dist/chunk-CSIE4Y7C.js +1093 -0
- package/dist/chunk-CSOPSYDY.js +142 -0
- package/dist/chunk-CSXLLEGB.js +205 -0
- package/dist/chunk-CTDLERWU.js +293 -0
- package/dist/chunk-CULBXMSK.js +110 -0
- package/dist/chunk-D2M2Y5ID.js +21 -0
- package/dist/chunk-D37WY7SH.js +1060 -0
- package/dist/chunk-D4VJFCGZ.js +89 -0
- package/dist/chunk-D6WTZMZB.js +48 -0
- package/dist/chunk-DBHOWDUH.js +976 -0
- package/dist/chunk-DCACX7BV.js +19364 -0
- package/dist/chunk-DFHX4XYA.js +128 -0
- package/dist/chunk-DIKBRRKE.js +176 -0
- package/dist/chunk-DJG5RIOR.js +9 -0
- package/dist/chunk-DNIOIISW.js +616 -0
- package/dist/chunk-DOA5G7IA.js +315 -0
- package/dist/chunk-DP7FKP6W.js +855 -0
- package/dist/chunk-DS2JZ677.js +79 -0
- package/dist/chunk-DSRLVYBS.js +82 -0
- package/dist/chunk-EAEVKNJA.js +209 -0
- package/dist/chunk-EEUESN3T.js +575 -0
- package/dist/chunk-EJ4LUU5Y.js +73 -0
- package/dist/chunk-EJIWTPSZ.js +1063 -0
- package/dist/chunk-EJVCDTAN.js +116 -0
- package/dist/chunk-EKLUBDBQ.js +627 -0
- package/dist/chunk-EN62WLFD.js +849 -0
- package/dist/chunk-ENYRCL43.js +26 -0
- package/dist/chunk-EP22ZMFO.js +273 -0
- package/dist/chunk-EP4SVAVI.js +87 -0
- package/dist/chunk-EPAMVGI3.js +1562 -0
- package/dist/chunk-EPRMH6HO.js +24 -0
- package/dist/chunk-ES6NWJ36.js +4057 -0
- package/dist/chunk-ETA2K4KI.js +30 -0
- package/dist/chunk-ETAD4NKD.js +31 -0
- package/dist/chunk-EUWIIDQ7.js +93 -0
- package/dist/chunk-EVE3OD2W.js +141 -0
- package/dist/chunk-EXA26FFC.js +459 -0
- package/dist/chunk-EXSPAA35.js +244 -0
- package/dist/chunk-F55YABKV.js +258 -0
- package/dist/chunk-F5DNGU5W.js +27 -0
- package/dist/chunk-F622MJYV.js +103 -0
- package/dist/chunk-F6NIQD74.js +5111 -0
- package/dist/chunk-FAWJTC34.js +43 -0
- package/dist/chunk-FAZBRHGG.js +47 -0
- package/dist/chunk-FIEUSGNJ.js +39 -0
- package/dist/chunk-FKCG7K6H.js +1146 -0
- package/dist/chunk-FOVVXV45.js +229 -0
- package/dist/chunk-FRBPKBFE.js +30 -0
- package/dist/chunk-FSA5BPFI.js +268 -0
- package/dist/chunk-FSJ5TTZ3.js +29 -0
- package/dist/chunk-FT7SGLXT.js +193 -0
- package/dist/chunk-FUUVZZUB.js +62 -0
- package/dist/chunk-FYMRVUNZ.js +1697 -0
- package/dist/chunk-FYTAA5FG.js +162 -0
- package/dist/chunk-G3VB2UCZ.js +3892 -0
- package/dist/chunk-G6OIMVXH.js +405 -0
- package/dist/chunk-G7PQCXVH.js +228 -0
- package/dist/chunk-GAB6UW52.js +1087 -0
- package/dist/chunk-GAFJEYLK.js +29 -0
- package/dist/chunk-GC4CRMTS.js +642 -0
- package/dist/chunk-GFHSIWHL.js +5297 -0
- package/dist/chunk-GI5M67YA.js +735 -0
- package/dist/chunk-GIJWHUWF.js +191 -0
- package/dist/chunk-GO6DRECI.js +1 -0
- package/dist/chunk-GOFVBTMN.js +314 -0
- package/dist/chunk-GQIP72ZJ.js +13 -0
- package/dist/chunk-GQXLXRFA.js +28 -0
- package/dist/chunk-GT6HFKJB.js +48 -0
- package/dist/chunk-GVJGSSKM.js +174 -0
- package/dist/chunk-GWHGTG37.js +36 -0
- package/dist/chunk-GZAJHLKO.js +18 -0
- package/dist/chunk-GZK62I3N.js +314 -0
- package/dist/chunk-H3HGMISG.js +483 -0
- package/dist/chunk-H3ISZJMJ.js +403 -0
- package/dist/chunk-H4HXVWEC.js +9 -0
- package/dist/chunk-H6MJGKAW.js +120 -0
- package/dist/chunk-HBTTGVR5.js +353 -0
- package/dist/chunk-HBZ322WZ.js +35 -0
- package/dist/chunk-HEP3ILP4.js +34 -0
- package/dist/chunk-HGFXODKO.js +106 -0
- package/dist/chunk-HHWDTB6S.js +59 -0
- package/dist/chunk-HKO45NLZ.js +286 -0
- package/dist/chunk-HLVTEA6A.js +89 -0
- package/dist/chunk-HS3SY6HN.js +160 -0
- package/dist/chunk-HT5OCGKN.js +899 -0
- package/dist/chunk-HXIIEMGF.js +78 -0
- package/dist/chunk-I56TH7VM.js +46 -0
- package/dist/chunk-I6FN3R5D.js +352 -0
- package/dist/chunk-I7SCBHJN.js +655 -0
- package/dist/chunk-IJM4GKAT.js +529 -0
- package/dist/chunk-IMEYU36R.js +344 -0
- package/dist/chunk-INJ3SS6A.js +936 -0
- package/dist/chunk-IUKOPCCE.js +441 -0
- package/dist/chunk-IVEPZQJO.js +33 -0
- package/dist/chunk-IVZEONFC.js +43 -0
- package/dist/chunk-IWBHRSG7.js +936 -0
- package/dist/chunk-IYY3HQAD.js +484 -0
- package/dist/chunk-J2ICMYDA.js +48 -0
- package/dist/chunk-J2QCFLUN.js +505 -0
- package/dist/chunk-J5HM6V5P.js +1039 -0
- package/dist/chunk-J6NZX6QH.js +398 -0
- package/dist/chunk-JBBB2Y47.js +432 -0
- package/dist/chunk-JDCZQZU7.js +42 -0
- package/dist/chunk-JEDNXGSS.js +169 -0
- package/dist/chunk-JHP7OT6K.js +89 -0
- package/dist/chunk-JLS65NUQ.js +14 -0
- package/dist/chunk-JNMWYMC6.js +38 -0
- package/dist/chunk-JNSTWNNW.js +25 -0
- package/dist/chunk-JOSK6GEU.js +9564 -0
- package/dist/chunk-JQUMSIGC.js +100 -0
- package/dist/chunk-JVHGMURQ.js +1106 -0
- package/dist/chunk-JYXS47FQ.js +951 -0
- package/dist/chunk-K2ZMW2Z5.js +2147 -0
- package/dist/chunk-K7FAFORM.js +14 -0
- package/dist/chunk-KBJXX3ON.js +333 -0
- package/dist/chunk-KHFKVQWY.js +486 -0
- package/dist/chunk-KHMEI3DQ.js +173 -0
- package/dist/chunk-KHW3UD7B.js +69 -0
- package/dist/chunk-KKQKWAMF.js +365 -0
- package/dist/chunk-KOKXJV2U.js +455 -0
- package/dist/chunk-KQ4NGOJI.js +14 -0
- package/dist/chunk-KQYQOXMS.js +342 -0
- package/dist/chunk-KTMW65UX.js +14 -0
- package/dist/chunk-KUEWV2JH.js +593 -0
- package/dist/chunk-KXYDV3HP.js +1523 -0
- package/dist/chunk-KZ4JMGZ5.js +96 -0
- package/dist/chunk-KZWGBUIO.js +2659 -0
- package/dist/chunk-L2CBG5IX.js +1892 -0
- package/dist/chunk-L2S235CU.js +314 -0
- package/dist/chunk-L32WD57F.js +98 -0
- package/dist/chunk-LDJCKAJP.js +123 -0
- package/dist/chunk-LDWNBEN7.js +541 -0
- package/dist/chunk-LJVH57G2.js +241 -0
- package/dist/chunk-LPQ7NZEN.js +209 -0
- package/dist/chunk-LRGH3CCV.js +148 -0
- package/dist/chunk-LULOGMMM.js +1133 -0
- package/dist/chunk-LWGKN2GY.js +8284 -0
- package/dist/chunk-LX4F24ZH.js +157 -0
- package/dist/chunk-M4BUEXXF.js +839 -0
- package/dist/chunk-M6UHOC4I.js +553 -0
- package/dist/chunk-MCBNWZNO.js +657 -0
- package/dist/chunk-MEMSY6VY.js +223 -0
- package/dist/chunk-MHLEZQQI.js +145 -0
- package/dist/chunk-MJ6WNSIX.js +192 -0
- package/dist/chunk-MKASIKWZ.js +442 -0
- package/dist/chunk-MNOVBYFU.js +60 -0
- package/dist/chunk-MO2BYAAF.js +2896 -0
- package/dist/chunk-MP6P7Y2A.js +180 -0
- package/dist/chunk-MQ4TFJAG.js +3365 -0
- package/dist/chunk-MT2WAIR3.js +131 -0
- package/dist/chunk-MTU7VTNN.js +1122 -0
- package/dist/chunk-MULMXX4V.js +150 -0
- package/dist/chunk-MW2DWWVA.js +147 -0
- package/dist/chunk-MY3ZPUN4.js +151 -0
- package/dist/chunk-MYLH2S4G.js +64 -0
- package/dist/chunk-MZ5WYKNA.js +28 -0
- package/dist/chunk-N3Q2JNPV.js +249 -0
- package/dist/chunk-N5DX4JAK.js +12 -0
- package/dist/chunk-NAINGKHF.js +35 -0
- package/dist/chunk-NEQUQHOX.js +223 -0
- package/dist/chunk-NHNPEZS4.js +1408 -0
- package/dist/chunk-NHTIXJCR.js +17 -0
- package/dist/chunk-NKLPMBNV.js +1154 -0
- package/dist/chunk-NMVZ5YES.js +199 -0
- package/dist/chunk-NRFRY3GE.js +256 -0
- package/dist/chunk-NTD6CSI6.js +1266 -0
- package/dist/chunk-NUO7B3SH.js +318 -0
- package/dist/chunk-NVOHIJKG.js +1319 -0
- package/dist/chunk-NXH3RX7O.js +523 -0
- package/dist/chunk-NXZ3DURF.js +257 -0
- package/dist/chunk-O26L6F7F.js +209 -0
- package/dist/chunk-O5RRIUEP.js +124 -0
- package/dist/chunk-O5X6BKAO.js +10 -0
- package/dist/chunk-O6ZQUVTR.js +31 -0
- package/dist/chunk-O7FE75QZ.js +306 -0
- package/dist/chunk-OC7Z6AJQ.js +81 -0
- package/dist/chunk-OH7IEZ63.js +307 -0
- package/dist/chunk-OI734GRS.js +115 -0
- package/dist/chunk-OJBH62DK.js +684 -0
- package/dist/chunk-OKJLVSTJ.js +247 -0
- package/dist/chunk-OMX5VL43.js +79 -0
- package/dist/chunk-ONHAMBN6.js +12 -0
- package/dist/chunk-ONYPLIVE.js +753 -0
- package/dist/chunk-OSK7QWPD.js +637 -0
- package/dist/chunk-OTXLMJKP.js +438 -0
- package/dist/chunk-OV5PKQMA.js +213 -0
- package/dist/chunk-OXK5HA4B.js +31 -0
- package/dist/chunk-OYDWFQA4.js +272 -0
- package/dist/chunk-OZAUKWHB.js +22 -0
- package/dist/chunk-P5P2EKGH.js +94 -0
- package/dist/chunk-P6SSWAKY.js +29 -0
- package/dist/chunk-P7CQGPLS.js +30 -0
- package/dist/chunk-P7RVCHQV.js +197 -0
- package/dist/chunk-PEBWDYIW.js +726 -0
- package/dist/chunk-PFCXFO7A.js +9193 -0
- package/dist/chunk-PFLDWMX6.js +168 -0
- package/dist/chunk-PHZGLQSK.js +15883 -0
- package/dist/chunk-PNFTPNSR.js +20 -0
- package/dist/chunk-PPHXX4W7.js +175 -0
- package/dist/chunk-PPZESPJT.js +262 -0
- package/dist/chunk-PRDHI2L5.js +296 -0
- package/dist/chunk-PSTKWHHN.js +32 -0
- package/dist/chunk-PV53ODOT.js +555 -0
- package/dist/chunk-PVJBTI7P.js +24 -0
- package/dist/chunk-PXKERBKX.js +100 -0
- package/dist/chunk-PZ5AY32C.js +10 -0
- package/dist/chunk-Q3DHEZA5.js +85 -0
- package/dist/chunk-Q5RZDVQK.js +204 -0
- package/dist/chunk-Q64IR2Z2.js +4933 -0
- package/dist/chunk-Q6Z5UGPL.js +398 -0
- package/dist/chunk-QAMAV4DT.js +627 -0
- package/dist/chunk-QBWF4444.js +112 -0
- package/dist/chunk-QDKYT4CI.js +22805 -0
- package/dist/chunk-QFLBRWCJ.js +126 -0
- package/dist/chunk-QILAQACE.js +107 -0
- package/dist/chunk-QJ6OEH4K.js +3683 -0
- package/dist/chunk-QK3NLYTV.js +320 -0
- package/dist/chunk-QOFLUS24.js +535 -0
- package/dist/chunk-QOIASNEJ.js +98 -0
- package/dist/chunk-QP4UTSOV.js +3587 -0
- package/dist/chunk-QP5ST7RI.js +904 -0
- package/dist/chunk-QS5AGRZN.js +167 -0
- package/dist/chunk-QTAOU53N.js +107 -0
- package/dist/chunk-QTCLJHLZ.js +351 -0
- package/dist/chunk-QTOLTG4L.js +119 -0
- package/dist/chunk-QWDV4OSL.js +142 -0
- package/dist/chunk-QWMQ74KD.js +508 -0
- package/dist/chunk-QX6LOMMH.js +158 -0
- package/dist/chunk-QXBKIHY7.js +238 -0
- package/dist/chunk-QXBKTJT6.js +270 -0
- package/dist/chunk-QYQOVOLR.js +196 -0
- package/dist/chunk-R2CKS6WT.js +73 -0
- package/dist/chunk-R2TIYG7U.js +68 -0
- package/dist/chunk-R2W3LESH.js +465 -0
- package/dist/chunk-R5EXHMUN.js +100 -0
- package/dist/chunk-RBBTBCHX.js +289 -0
- package/dist/chunk-RBKLOUXA.js +121 -0
- package/dist/chunk-RCP2Y6DQ.js +86 -0
- package/dist/chunk-RCYEJSD5.js +260 -0
- package/dist/chunk-RFDVSI4N.js +134 -0
- package/dist/chunk-RGJU63FV.js +1717 -0
- package/dist/chunk-RI4EX2QE.js +18 -0
- package/dist/chunk-RIMARPCF.js +152 -0
- package/dist/chunk-RJ6RSNT6.js +42 -0
- package/dist/chunk-RNI2GUIF.js +131 -0
- package/dist/chunk-RPHUWJ3K.js +264 -0
- package/dist/chunk-RPIMAMV7.js +361 -0
- package/dist/chunk-RQFX6YRN.js +49 -0
- package/dist/chunk-RRC5BL7B.js +285 -0
- package/dist/chunk-RSYTSBOO.js +79 -0
- package/dist/chunk-RWQQIKIC.js +35 -0
- package/dist/chunk-RZUBOZH2.js +373 -0
- package/dist/chunk-S2E632FQ.js +380 -0
- package/dist/chunk-S2VQCZO4.js +22 -0
- package/dist/chunk-S2XIMQJQ.js +681 -0
- package/dist/chunk-S47ISY27.js +183 -0
- package/dist/chunk-S6I4KISU.js +142 -0
- package/dist/chunk-S6TAFQI5.js +2403 -0
- package/dist/chunk-SBBNT5ZJ.js +27 -0
- package/dist/chunk-SDJV2DTQ.js +491 -0
- package/dist/chunk-SDPIFNLD.js +33 -0
- package/dist/chunk-SF6YK3JI.js +835 -0
- package/dist/chunk-SK3ZFONO.js +976 -0
- package/dist/chunk-SKTFRFQ7.js +1775 -0
- package/dist/chunk-SNGM452K.js +2002 -0
- package/dist/chunk-STW7OFOA.js +581 -0
- package/dist/chunk-SU6UFUQY.js +1351 -0
- package/dist/chunk-SVJM3LJA.js +27 -0
- package/dist/chunk-SVUNZOPG.js +129 -0
- package/dist/chunk-T5XLUYV3.js +34 -0
- package/dist/chunk-T7E5JS6N.js +57 -0
- package/dist/chunk-TA3N5MMO.js +450 -0
- package/dist/chunk-TAJPCXSB.js +13 -0
- package/dist/chunk-TDEMDRN2.js +1639 -0
- package/dist/chunk-TDSEX5CF.js +24 -0
- package/dist/chunk-TGCVL74Y.js +28 -0
- package/dist/chunk-TGXXYDL4.js +1012 -0
- package/dist/chunk-TIKTYUJO.js +296 -0
- package/dist/chunk-TIZAJD4M.js +6029 -0
- package/dist/chunk-TLSEZZCG.js +5549 -0
- package/dist/chunk-TMBDRHAX.js +19 -0
- package/dist/chunk-TRURQUBP.js +1217 -0
- package/dist/chunk-TSQ256N5.js +152 -0
- package/dist/chunk-TUQMMFEQ.js +2244 -0
- package/dist/chunk-U424MJLC.js +81 -0
- package/dist/chunk-U4DRS6ZW.js +11 -0
- package/dist/chunk-U5KS22IN.js +204 -0
- package/dist/chunk-UAPHFJPN.js +673 -0
- package/dist/chunk-UB7LQITD.js +1040 -0
- package/dist/chunk-UBVRHGAZ.js +237 -0
- package/dist/chunk-UDNNAQN5.js +98 -0
- package/dist/chunk-UJP3XM54.js +342 -0
- package/dist/chunk-UJYDH2MW.js +305 -0
- package/dist/chunk-UKMPASIC.js +399 -0
- package/dist/chunk-UKUL3EHK.js +763 -0
- package/dist/chunk-UPHU64NB.js +1327 -0
- package/dist/chunk-URMSZXAD.js +43 -0
- package/dist/chunk-US3RT6CY.js +525 -0
- package/dist/chunk-UTDEOPKV.js +30 -0
- package/dist/chunk-UUUDKV7N.js +13 -0
- package/dist/chunk-UVKWU3SM.js +39 -0
- package/dist/chunk-V2TVPO3X.js +521 -0
- package/dist/chunk-V3KLVK7B.js +398 -0
- package/dist/chunk-V3YFFHDR.js +17 -0
- package/dist/chunk-VAG6GUBR.js +1162 -0
- package/dist/chunk-VBENAHDA.js +1814 -0
- package/dist/chunk-VBNCKCCI.js +16 -0
- package/dist/chunk-VCGSWN5M.js +1300 -0
- package/dist/chunk-VE2O2I7M.js +115 -0
- package/dist/chunk-VIFHYTI5.js +31 -0
- package/dist/chunk-VJER3FUS.js +5080 -0
- package/dist/chunk-VLMDM56Q.js +268 -0
- package/dist/chunk-VMFZEVVX.js +99 -0
- package/dist/chunk-VNDPQVUZ.js +1853 -0
- package/dist/chunk-VSPJRLGA.js +4783 -0
- package/dist/chunk-VSWC5ZXI.js +103 -0
- package/dist/chunk-VYI4DSZP.js +2017 -0
- package/dist/chunk-W4BAIQ6L.js +1212 -0
- package/dist/chunk-W7VQAL2K.js +2203 -0
- package/dist/chunk-WEI3ZDZH.js +33 -0
- package/dist/chunk-WEIUS5NT.js +26 -0
- package/dist/chunk-WEW7UFWE.js +546 -0
- package/dist/chunk-WGQAXLNA.js +384 -0
- package/dist/chunk-WJAL4JL3.js +206 -0
- package/dist/chunk-WKFOJ5ZG.js +141 -0
- package/dist/chunk-WMWQEFLN.js +2177 -0
- package/dist/chunk-WNECKKO2.js +154 -0
- package/dist/chunk-WPKLYOAM.js +195 -0
- package/dist/chunk-WSH37YQN.js +243 -0
- package/dist/chunk-WV3KQDPE.js +84 -0
- package/dist/chunk-WZFC4V4U.js +389 -0
- package/dist/chunk-XCOIBNET.js +13 -0
- package/dist/chunk-XDM65LBX.js +53 -0
- package/dist/chunk-XGU6PBO5.js +645 -0
- package/dist/chunk-XHOI4V62.js +43 -0
- package/dist/chunk-XIBVFMLQ.js +6858 -0
- package/dist/chunk-XJ2E7YEJ.js +117 -0
- package/dist/chunk-XON4ZCYX.js +69 -0
- package/dist/chunk-XQPEWJPI.js +127 -0
- package/dist/chunk-XSJTIFUY.js +31 -0
- package/dist/chunk-XT7OVWM3.js +64 -0
- package/dist/chunk-XTXYIISX.js +1104 -0
- package/dist/chunk-XV7NZL4B.js +57 -0
- package/dist/chunk-XWIZ6B5S.js +109 -0
- package/dist/chunk-XWLIKOBX.js +240 -0
- package/dist/chunk-XZOXEIN4.js +156 -0
- package/dist/chunk-XZRS7I7W.js +3673 -0
- package/dist/chunk-Y4ZDDHB6.js +44 -0
- package/dist/chunk-Y733RB7T.js +194 -0
- package/dist/chunk-YBHUB4XR.js +14931 -0
- package/dist/chunk-YKC75XK4.js +147 -0
- package/dist/chunk-YKMXFVK7.js +27 -0
- package/dist/chunk-YO5BAJ55.js +225 -0
- package/dist/chunk-YPDCLXNZ.js +568 -0
- package/dist/chunk-YSQPGVFK.js +116 -0
- package/dist/chunk-YTVVTIWJ.js +716 -0
- package/dist/chunk-YVCMDVBB.js +698 -0
- package/dist/chunk-YYTOA6DP.js +114 -0
- package/dist/chunk-Z5WGNULV.js +88 -0
- package/dist/chunk-Z6NGVVXG.js +66 -0
- package/dist/chunk-Z7CDQNH3.js +20 -0
- package/dist/chunk-ZH4G3FU5.js +187 -0
- package/dist/chunk-ZJB6SQPA.js +257 -0
- package/dist/chunk-ZL6E4HMY.js +42 -0
- package/dist/chunk-ZMLOC3DW.js +62 -0
- package/dist/chunk-ZORW64QH.js +101 -0
- package/dist/chunk-ZVVD2XGV.js +1369 -0
- package/dist/cli-utils-ER33ODC5.js +31 -0
- package/dist/cli-validation-6CHPTANV.js +146 -0
- package/dist/commit-utils-3STAY7C7.js +49 -0
- package/dist/compatibility-notice-IHNXR2JR.js +21 -0
- package/dist/compete-config-resolver-V3GDNJMM.js +125 -0
- package/dist/compete-results-XUM3PJHS.js +318 -0
- package/dist/competition-outcome-tracker-NWSMVUPG.js +62 -0
- package/dist/config-4HHE4OIK.js +238 -0
- package/dist/config-D6YAZASH.js +10 -0
- package/dist/config-MIPRDYYV.js +46 -0
- package/dist/config-audit-GA5DCUAI.js +371 -0
- package/dist/config-explain-4LMO556H.js +71 -0
- package/dist/config-loader-RGP634PC.js +51 -0
- package/dist/config-manager-J2UTO635.js +114 -0
- package/dist/config-merger-TVUJBZTS.js +14 -0
- package/dist/config-validator-H4ZVIE56.js +122 -0
- package/dist/cost-HSIV5U2Y.js +85 -0
- package/dist/data-migration-state-OAUL2WPQ.js +35 -0
- package/dist/db-migrator-NUOW5NKR.js +34 -0
- package/dist/default-paths-UILB62BN.js +49 -0
- package/dist/discovery-V6GYUJUC.js +53 -0
- package/dist/doctor-BBSMCDWE.js +271 -0
- package/dist/doctor-context-blocks-LPY75VZA.js +231 -0
- package/dist/doctor-instructions-import-JXHDDOE5.js +70 -0
- package/dist/doctor-purpose-6YJOXPBE.js +30 -0
- package/dist/domain-analyzer-S35ABUNA.js +48 -0
- package/dist/ensure-initialized-Q6PEU55O.js +78 -0
- package/dist/entry.js +922 -0
- package/dist/error-parser-core-MZFMFANN.js +70 -0
- package/dist/evaluation-context-GQBYDAEV.js +63 -0
- package/dist/evidence-plan-resolver-5FUAP3SA.js +111 -0
- package/dist/execution-data-writer-YCG5UH37.js +72 -0
- package/dist/execution-policy-applier-PWZM5LNA.js +63 -0
- package/dist/execution-preflight-DASJWWQF.js +223 -0
- package/dist/execution-roles-KNSNNB2D.js +112 -0
- package/dist/exit-code-error-QIY5DOKF.js +18 -0
- package/dist/external-temp-cleanup-CAW7LQ6R.js +360 -0
- package/dist/factory-YCYCB7AE.js +209 -0
- package/dist/file-utils-ZQYNBQBW.js +45 -0
- package/dist/flywheel-allowlist-revert-H22HA6JE.js +21 -0
- package/dist/flywheel-autoloop-executor-PDOASJEZ.js +316 -0
- package/dist/flywheel-autoloop-unverified-TOKYFCDC.js +36 -0
- package/dist/flywheel-competition-executor-YJUMMEJO.js +320 -0
- package/dist/flywheel-executor-JWU43KAY.js +437 -0
- package/dist/flywheel-git-isolation-FQ2TRWMB.js +56 -0
- package/dist/flywheel-manifest-HDPNMWWF.js +114 -0
- package/dist/flywheel-model-defaults-UHAKTZT3.js +110 -0
- package/dist/flywheel-preflight-III2C7TH.js +163 -0
- package/dist/flywheel-resume-2O45MS7Y.js +31 -0
- package/dist/flywheel-resume-execution-lease-P2BK257J.js +59 -0
- package/dist/flywheel-safety-AVAVFXIJ.js +19 -0
- package/dist/flywheel-scope-decision-ALJUUNGG.js +14 -0
- package/dist/get-telemetry-logger-MPDVO2JA.js +155 -0
- package/dist/git-message-style-KCXGMTDT.js +104 -0
- package/dist/guidance-profile-config-G3K5YQOO.js +113 -0
- package/dist/guidance-profile-renderer-TX4TNDFL.js +23 -0
- package/dist/identity-XLQJ4YJF.js +25 -0
- package/dist/index-query-6NUY4FKX.js +37 -0
- package/dist/index.js +85588 -0
- package/dist/indexer-DL54CM3K.js +44 -0
- package/dist/init-OUZ72344.js +245 -0
- package/dist/instructions-import-offer-NSYXSITC.js +363 -0
- package/dist/instructions-run-NBII7W36.js +114 -0
- package/dist/interrupted-work-E4TLKJLE.js +43 -0
- package/dist/invoke-provider-auth-NEWEIHCI.js +38 -0
- package/dist/judge-scoring.json +64 -0
- package/dist/lab-mode-YXQ2Y3NG.js +44 -0
- package/dist/lab-utils-5QAMDJR5.js +29 -0
- package/dist/linux-host-class-YDWQX65O.js +31 -0
- package/dist/llm-judge-executor-OJSNCTFJ.js +179 -0
- package/dist/local-ci-config-VZ4WWDT5.js +48 -0
- package/dist/local-executor-DCMDDRX2.js +280 -0
- package/dist/logger-5KNKS3O4.js +154 -0
- package/dist/matrix-prompt-builder-4ZBOGZSB.js +527 -0
- package/dist/matrix-result-parser-EZJM4YXP.js +14 -0
- package/dist/merge-batch-RTEEMVDB.js +313 -0
- package/dist/merge-batch-members-VIWGVRHP.js +24 -0
- package/dist/merge-queue-TIIUSOY6.js +126 -0
- package/dist/merge-queue-trust-DUNZ4J65.js +21 -0
- package/dist/metadata-UKSMWM6J.js +29 -0
- package/dist/model-catalog-readiness-R5KJBP5M.js +202 -0
- package/dist/model-invocations-db-XTUPPQ34.js +70 -0
- package/dist/model-resolver-JFZ2MHOJ.js +39 -0
- package/dist/model-resolver-SCQ57KAQ.js +217 -0
- package/dist/model-roles-D3OR4NAH.js +110 -0
- package/dist/monitor-F4SIU5G2.js +96 -0
- package/dist/nested-worktrees-2WUWQ75N.js +23 -0
- package/dist/next-S3IRLVER.js +96 -0
- package/dist/next-UKPFRXOO.js +148 -0
- package/dist/opportunistic-TL4S26VX.js +86 -0
- package/dist/optimization-config-resolver-NAEIYU6A.js +148 -0
- package/dist/package-HJR4QJT4.js +10 -0
- package/dist/parse-git-status-7PIYFPS2.js +21 -0
- package/dist/path-security-5WJSY56G.js +41 -0
- package/dist/paths-JUI7C4KU.js +45 -0
- package/dist/plan-backlog-list-fast-SSTQL5XP.js +89 -0
- package/dist/plan-backlog-show-fast-PFRAQ3JB.js +114 -0
- package/dist/plan-sprint-list-fast-HD2KBZSY.js +110 -0
- package/dist/plan-sprint-status-fast-YFYH7WQF.js +116 -0
- package/dist/plan-task-status-fast-JU5PNLUU.js +114 -0
- package/dist/plan-to-flywheel-PY5MSY2H.js +529 -0
- package/dist/preflight-PJHGTJNZ.js +12 -0
- package/dist/process-registry-B4ZUCN7T.js +28 -0
- package/dist/process-scanner-TU3QHWVB.js +23 -0
- package/dist/processes-6FHVGT72.js +28 -0
- package/dist/processes-json-fast-YWTMUWXB.js +72 -0
- package/dist/profile-HWTC56SG.js +209 -0
- package/dist/project-runtime-paths-2UQNG5Y4.js +41 -0
- package/dist/protected-branches-N36LDBFY.js +71 -0
- package/dist/provider-aware-resource-manager-YTFAHNGJ.js +40 -0
- package/dist/provider-matrix-2KO2V5OM.js +214 -0
- package/dist/provider-matrix-renderer-MEC3PER7.js +139 -0
- package/dist/provider-output-forwarding-2AHL7YMA.js +26 -0
- package/dist/provider-registry-WCZ65QHC.js +136 -0
- package/dist/provider-temp-cleanup-IUNPJCZF.js +14 -0
- package/dist/prune-engine-EOQVWEP6.js +448 -0
- package/dist/publication-turn-S42RZTQF.js +44 -0
- package/dist/quality-gate-JQMVCKOO.js +72 -0
- package/dist/quickstart-3O6FRCFB.js +105 -0
- package/dist/readiness-GW6ABRHB.js +139 -0
- package/dist/readiness-KFZCXDTT.js +215 -0
- package/dist/registry-7XG376SY.js +217 -0
- package/dist/repair-helpers-TTV5FEF4.js +117 -0
- package/dist/repo-root-YG6MQZDW.js +28 -0
- package/dist/resolution-engine-FFEK7HQ2.js +187 -0
- package/dist/resolve-provider-cli-ZEXVZKET.js +44 -0
- package/dist/restore-telemetry-db-E7BR5PO7.js +459 -0
- package/dist/routing-events-AW6SRZ6G.js +13 -0
- package/dist/routing-history-store-FMDDQL6W.js +39 -0
- package/dist/routing-planner-C6OHO3EY.js +221 -0
- package/dist/runner-KHDNQ5KU.js +1194 -0
- package/dist/runner-PIS2BW7Y.js +1801 -0
- package/dist/safety-E3JJVSFL.js +67 -0
- package/dist/safety-stanza-HE6GXP4G.js +49 -0
- package/dist/sandbox-7LBZC5PE.js +72 -0
- package/dist/sandbox-ASWCDYZL.js +80 -0
- package/dist/schema-extensions.sql +234 -0
- package/dist/security-JI22TBEB.js +17 -0
- package/dist/setup-bb-plugin-FQXLA76Y.js +531 -0
- package/dist/setup-claude-code-NF4ZSHVE.js +197 -0
- package/dist/setup-temp-cleanup-2APZ4HMA.js +29 -0
- package/dist/shared-utils-34HJZ6JX.js +40 -0
- package/dist/simple-artifact-goal-MQLDDMMX.js +29 -0
- package/dist/sprint-N7JFTEGL.js +403 -0
- package/dist/sprint-bridge-KJXIBNRJ.js +117 -0
- package/dist/sprint-completion-dependents-34SR7JVL.js +43 -0
- package/dist/sprint-execution-service-A6JPUBWY.js +376 -0
- package/dist/sprint-manager-MU2ZUWN2.js +140 -0
- package/dist/sqlite-timeout-config-U2CT4LKU.js +13 -0
- package/dist/sqlite-wrapper-FSGJ2QEW.js +19 -0
- package/dist/stale-cleanup-orchestrator-4X6324VF.js +71 -0
- package/dist/storage-access-I3V5LER7.js +31 -0
- package/dist/store-XVG64ZR2.js +25 -0
- package/dist/task-classifier-MN2DYE5R.js +558 -0
- package/dist/task-list-fast-7AT6LTTA.js +112 -0
- package/dist/task-manager-LHPBBRRE.js +136 -0
- package/dist/task-report-OLPAWBTK.js +64 -0
- package/dist/task-type-detector-6RG3YNZF.js +27 -0
- package/dist/task-type-resolver-EQHOUIHT.js +64 -0
- package/dist/telemetry-5VYSK772.js +212 -0
- package/dist/telemetry-health-tracker-4GFW2EMP.js +12 -0
- package/dist/telemetry-path-resolver-H3NFHHQY.js +34 -0
- package/dist/telemetry-reliability-URJDTNPZ.js +76 -0
- package/dist/transports-NREZQTJK.js +106 -0
- package/dist/unified-cost-tracker-5MTBJ2CL.js +59 -0
- package/dist/unified-state-cleanup-GGAXLHXF.js +292 -0
- package/dist/universal-cost-calculator-JTFEJVWK.js +70 -0
- package/dist/user-agents-QLIGPLP2.js +30 -0
- package/dist/variant-execution-I4ZZUAWY.js +319 -0
- package/dist/variant-opt-parser-JHCXKY2K.js +251 -0
- package/dist/variant-request-input-PL37N3AN.js +11 -0
- package/dist/variant-state-cleanup-KHMXRBZN.js +287 -0
- package/dist/variant-worker-COB5YTJX.js +4517 -0
- package/dist/variant-worker.js +26 -0
- package/dist/variants-XGDSXYG3.js +267 -0
- package/dist/verification-command-YSPU4VBH.js +66 -0
- package/dist/verify-command-timeout-DQUYH33Z.js +11 -0
- package/dist/verify-commands-LOHMOFKC.js +65 -0
- package/dist/warning-JSKSFKBT.js +13 -0
- package/dist/work-edge-K65NHVWY.js +50 -0
- package/dist/work-item-writer-KY5ZWZWW.js +30 -0
- package/dist/worker-JNXXEIT6.js +1504 -0
- package/dist/worker.js +21 -0
- package/dist/workspace-tree-identity-JO5PSKTW.js +52 -0
- package/dist/worktree-environment-WTVABAQW.js +64 -0
- package/dist/worktree-metrics-VZRQI26T.js +66 -0
- package/dist/writeback-TQFQBJNU.js +50 -0
- package/docs/CLI_REFERENCE.md +8287 -0
- package/docs/PROVIDER_SETUP.md +1737 -0
- package/docs/README.md +96 -0
- package/docs/TROUBLESHOOTING.md +2209 -0
- package/docs/getting-started/QUICK_START.md +260 -0
- package/docs/getting-started/README.md +198 -0
- package/docs/getting-started/SETUP.md +25 -0
- package/docs/reference/AGENT_CONTEXT.md +84 -0
- package/docs/reference/DELIVERY_ONBOARDING.md +198 -0
- package/docs/reference/PROVIDER_RELEASE_TIERS.md +34 -0
- package/docs/reference/SECURITY.md +291 -0
- package/docs/reference/TELEMETRY_PRIVACY.md +259 -0
- package/integrations/bb-plugin-build/README.md +391 -0
- package/integrations/bb-plugin-build/app.css +431 -0
- package/integrations/bb-plugin-build/app.tsx +6210 -0
- package/integrations/bb-plugin-build/package.json +45 -0
- package/integrations/bb-plugin-build/server.ts +488 -0
- package/integrations/bb-plugin-build/src/adapter.ts +3672 -0
- package/integrations/bb-plugin-build/src/backlog-authoring-model.ts +150 -0
- package/integrations/bb-plugin-build/src/backlog-authoring-schema.ts +458 -0
- package/integrations/bb-plugin-build/src/backlog-authoring-service.ts +467 -0
- package/integrations/bb-plugin-build/src/backlog-authoring-view.ts +1025 -0
- package/integrations/bb-plugin-build/src/command-evidence-schema.ts +13 -0
- package/integrations/bb-plugin-build/src/competition-defaults-schema.ts +122 -0
- package/integrations/bb-plugin-build/src/competition-defaults-service.ts +105 -0
- package/integrations/bb-plugin-build/src/competition-defaults-view.ts +138 -0
- package/integrations/bb-plugin-build/src/contract.ts +718 -0
- package/integrations/bb-plugin-build/src/execution-activity-view.ts +98 -0
- package/integrations/bb-plugin-build/src/finalize-model.ts +205 -0
- package/integrations/bb-plugin-build/src/finalize-schema.ts +150 -0
- package/integrations/bb-plugin-build/src/finalize-service.ts +330 -0
- package/integrations/bb-plugin-build/src/finalize-view.ts +159 -0
- package/integrations/bb-plugin-build/src/judge-operations-readback.ts +303 -0
- package/integrations/bb-plugin-build/src/judge-operations-schema.ts +33 -0
- package/integrations/bb-plugin-build/src/judge-operations-view.ts +459 -0
- package/integrations/bb-plugin-build/src/model.ts +1318 -0
- package/integrations/bb-plugin-build/src/monitor-service.ts +233 -0
- package/integrations/bb-plugin-build/src/panel-read-ux.ts +97 -0
- package/integrations/bb-plugin-build/src/patch-preview-schema.ts +166 -0
- package/integrations/bb-plugin-build/src/patch-preview-service.ts +480 -0
- package/integrations/bb-plugin-build/src/patch-preview-view.ts +109 -0
- package/integrations/bb-plugin-build/src/planning-readback.ts +228 -0
- package/integrations/bb-plugin-build/src/planning-service.ts +647 -0
- package/integrations/bb-plugin-build/src/planning-sync-evidence.ts +37 -0
- package/integrations/bb-plugin-build/src/planning-workspace-readback.ts +33 -0
- package/integrations/bb-plugin-build/src/planning-workspace-schema.ts +131 -0
- package/integrations/bb-plugin-build/src/planning-workspace.ts +333 -0
- package/integrations/bb-plugin-build/src/poll-handoff.ts +136 -0
- package/integrations/bb-plugin-build/src/project-target-server.ts +21 -0
- package/integrations/bb-plugin-build/src/project-target.ts +45 -0
- package/integrations/bb-plugin-build/src/reference-index.ts +218 -0
- package/integrations/bb-plugin-build/src/repository-identity.ts +17 -0
- package/integrations/bb-plugin-build/src/repository-schema.ts +30 -0
- package/integrations/bb-plugin-build/src/result-explorer-view.ts +597 -0
- package/integrations/bb-plugin-build/src/result-readback-model.ts +163 -0
- package/integrations/bb-plugin-build/src/result-readback-schema.ts +319 -0
- package/integrations/bb-plugin-build/src/result-readback-service.ts +333 -0
- package/integrations/bb-plugin-build/src/run-page-view.ts +332 -0
- package/integrations/bb-plugin-build/src/setup-config-schema.ts +293 -0
- package/integrations/bb-plugin-build/src/setup-config-service.ts +620 -0
- package/integrations/bb-plugin-build/src/setup-config-view.ts +388 -0
- package/integrations/bb-plugin-build/src/sprint-close-model.ts +150 -0
- package/integrations/bb-plugin-build/src/sprint-close-schema.ts +128 -0
- package/integrations/bb-plugin-build/src/sprint-close-service.ts +293 -0
- package/integrations/bb-plugin-build/src/sprint-close-view.ts +116 -0
- package/integrations/bb-plugin-build/src/sprint-composition-model.ts +709 -0
- package/integrations/bb-plugin-build/src/sprint-composition-readback.ts +231 -0
- package/integrations/bb-plugin-build/src/sprint-composition-schema.ts +597 -0
- package/integrations/bb-plugin-build/src/sprint-composition-service.ts +773 -0
- package/integrations/bb-plugin-build/src/sprint-composition-view.ts +1221 -0
- package/integrations/bb-plugin-build/src/sprint-execution-schema.ts +188 -0
- package/integrations/bb-plugin-build/src/sprint-execution-service.ts +289 -0
- package/integrations/bb-plugin-build/src/sprint-execution-view.ts +54 -0
- package/integrations/bb-plugin-build/src/task-authoring-model.ts +563 -0
- package/integrations/bb-plugin-build/src/task-authoring-schema.ts +629 -0
- package/integrations/bb-plugin-build/src/task-authoring-service.ts +842 -0
- package/integrations/bb-plugin-build/src/task-authoring-view.ts +1227 -0
- package/integrations/bb-plugin-build/src/task-catalog-schema.ts +46 -0
- package/integrations/bb-plugin-build/src/task-catalog-service.ts +44 -0
- package/integrations/bb-plugin-build/src/task-detail-readback.ts +56 -0
- package/integrations/bb-plugin-build/src/task-detail-schema.ts +171 -0
- package/integrations/bb-plugin-build/src/task-navigation.ts +446 -0
- package/integrations/bb-plugin-build/src/workbench-route.ts +74 -0
- package/package.json +306 -4
- package/schemas/README.md +80 -0
- package/schemas/build.config.schema.json +2110 -0
- package/schemas/config-v1.schema.json +136 -0
- package/schemas/execution-config.schema.json +47 -0
- package/schemas/judge-scoring.schema.json +257 -0
- package/schemas/provider-config.schema.json +179 -0
- package/schemas/telemetry-config.schema.json +79 -0
- package/schemas/user-preferences.schema.json +141 -0
- package/scripts/assert-node-runtime.mjs +146 -0
- package/scripts/preflight-native.mjs +49 -0
- package/scripts/setup-git-hooks.mjs +39 -0
- package/scripts/sync.sh +2871 -0
- package/scripts/write-node-launcher.sh +138 -0
- package/src/resources/gemini/slash-packs/default/plan.toml +15 -0
- package/src/resources/gemini/slash-packs/default/summary.toml +16 -0
- package/src/resources/gemini/slash-packs/default/tests.toml +16 -0
- package/templates/.build-project/README.md +41 -0
- package/templates/.build-project/agents/README.md +50 -0
- package/templates/.build-project/agents/architect.md +10 -0
- package/templates/.build-project/agents/code-reviewer.md +10 -0
- package/templates/.build-project/agents/debugger.md +10 -0
- package/templates/.build-project/agents/documenter.md +10 -0
- package/templates/.build-project/agents/test-automator.md +10 -0
- package/templates/.build-project/config/build.config.jsonc +64 -0
- package/templates/.build-project/config/project-context.template.json +6 -0
- package/templates/.build-project/config/task-type-aliases.presets/kanban.yaml +14 -0
- package/templates/.build-project/config/task-type-aliases.presets/scrum.yaml +17 -0
- package/templates/.build-project/config/task-type-aliases.presets/xp.yaml +12 -0
- package/templates/.build-project/config/task-type-aliases.yaml +29 -0
- package/templates/.build-project/gitignore.template +70 -0
- package/templates/.build-project/task-types/analysis.yaml +38 -0
- package/templates/.build-project/task-types/architecture.yaml +35 -0
- package/templates/.build-project/task-types/doc.yaml +34 -0
- package/templates/.build-project/task-types/feature.yaml +22 -0
- package/templates/.build-project/task-types/general.yaml +4 -0
- package/templates/.build-project/task-types/security.yaml +38 -0
- package/templates/AGENTS.template.md +85 -0
- package/templates/CLAUDE.template.md +1 -0
- package/templates/GEMINI.template.md +1 -0
- package/templates/builtin-workflows/code-review.yaml +73 -0
- package/templates/builtin-workflows/skills/code-review/SKILL.md +61 -0
- package/templates/builtin-workflows/skills/execution-contract-analysis/SKILL.md +24 -0
- package/templates/builtin-workflows/skills/execution-contract-code/SKILL.md +19 -0
- package/templates/builtin-workflows/skills/execution-contract-structured/SKILL.md +17 -0
- package/templates/ci/incident-intake.mjs +787 -0
- package/templates/ci/incidents.yml.template +103 -0
- package/templates/ci/node.yml.template +17 -0
- package/templates/ci/python.yml.template +17 -0
- package/templates/guard-kit/GUARD_SETUP.md.template +258 -0
- package/templates/guard-kit/build-guard.yml.template +189 -0
- package/templates/guard-kit/check.mjs.template +932 -0
- package/templates/guard-kit/config.json.template +7 -0
- package/templates/guard-kit/policy.json.template +1 -0
- package/templates/profiles/README.md +57 -0
- package/templates/profiles/frontier-claude.json +23 -0
- package/templates/profiles/frontier-codex.json +23 -0
|
@@ -0,0 +1,3683 @@
|
|
|
1
|
+
import {
|
|
2
|
+
normalizeCodexHomePath,
|
|
3
|
+
readTomlValues
|
|
4
|
+
} from "./chunk-BD3PGW6A.js";
|
|
5
|
+
import {
|
|
6
|
+
LongContextPricingSchema,
|
|
7
|
+
ModelInfoSchema,
|
|
8
|
+
RouteBackendModesSchema,
|
|
9
|
+
SpeedTierPricingSchema,
|
|
10
|
+
mergeModelEntry
|
|
11
|
+
} from "./chunk-QXBKTJT6.js";
|
|
12
|
+
import {
|
|
13
|
+
normalizeReasoningEffortInput
|
|
14
|
+
} from "./chunk-4BTDUT2S.js";
|
|
15
|
+
import {
|
|
16
|
+
findProjectRoot,
|
|
17
|
+
getConfigPaths,
|
|
18
|
+
resolveProvidersConfigPath
|
|
19
|
+
} from "./chunk-35J4NE6S.js";
|
|
20
|
+
import {
|
|
21
|
+
ProviderExecutionError
|
|
22
|
+
} from "./chunk-RRC5BL7B.js";
|
|
23
|
+
import {
|
|
24
|
+
assertContainedPath
|
|
25
|
+
} from "./chunk-RCP2Y6DQ.js";
|
|
26
|
+
import {
|
|
27
|
+
getEnvVarEntry
|
|
28
|
+
} from "./chunk-O26L6F7F.js";
|
|
29
|
+
import {
|
|
30
|
+
findBuildPackageRoot
|
|
31
|
+
} from "./chunk-RJ6RSNT6.js";
|
|
32
|
+
import {
|
|
33
|
+
getDataDir,
|
|
34
|
+
getUserConfigFile
|
|
35
|
+
} from "./chunk-56WPYDJH.js";
|
|
36
|
+
import {
|
|
37
|
+
validateConfigPath
|
|
38
|
+
} from "./chunk-STW7OFOA.js";
|
|
39
|
+
import {
|
|
40
|
+
BUILD_REFRESH_ORIGIN_ENV,
|
|
41
|
+
debugLog,
|
|
42
|
+
emitWarning,
|
|
43
|
+
getExecutionContext
|
|
44
|
+
} from "./chunk-7VRJHTGZ.js";
|
|
45
|
+
import {
|
|
46
|
+
getErrorCode,
|
|
47
|
+
isObject
|
|
48
|
+
} from "./chunk-CPSVQR2I.js";
|
|
49
|
+
|
|
50
|
+
// src/core/config/provider-registry.ts
|
|
51
|
+
import { createHash as createHash5 } from "crypto";
|
|
52
|
+
import { existsSync as existsSync5, readFileSync as readFileSync8 } from "fs";
|
|
53
|
+
import { homedir as homedir3 } from "os";
|
|
54
|
+
import { join as join4, resolve as resolve5, sep } from "path";
|
|
55
|
+
import yaml from "js-yaml";
|
|
56
|
+
import { z as z3 } from "zod";
|
|
57
|
+
|
|
58
|
+
// src/core/providers/generated/catalog-digest.ts
|
|
59
|
+
var PROVIDER_CATALOG_SHA256 = "3e1596f8b8c9836de23c8cba97e9f2cf947b7416f2f0cb4c2946df34719e3a08";
|
|
60
|
+
var PROVIDER_SOURCE_YAML_SHA256 = "ff6b202852cae9195a1e0d82f71ff246f188efe294484c977f083101e34ad2bd";
|
|
61
|
+
|
|
62
|
+
// src/core/providers/refresh/storage.ts
|
|
63
|
+
import { createHash as createHash2 } from "crypto";
|
|
64
|
+
import { existsSync as existsSync3, readdirSync, readFileSync as readFileSync5, realpathSync, statSync } from "fs";
|
|
65
|
+
import path4 from "path";
|
|
66
|
+
|
|
67
|
+
// src/core/providers/codex/connection.ts
|
|
68
|
+
import { readFileSync as readFileSync2 } from "fs";
|
|
69
|
+
import { homedir } from "os";
|
|
70
|
+
import path2 from "path";
|
|
71
|
+
|
|
72
|
+
// src/core/providers/shared/connection-coordinates.ts
|
|
73
|
+
function endpointCoordinate(value) {
|
|
74
|
+
if (typeof value !== "string") return void 0;
|
|
75
|
+
try {
|
|
76
|
+
const url = new URL(value);
|
|
77
|
+
url.username = "";
|
|
78
|
+
url.password = "";
|
|
79
|
+
url.search = "";
|
|
80
|
+
url.hash = "";
|
|
81
|
+
return url.toString();
|
|
82
|
+
} catch {
|
|
83
|
+
return value.includes("://") ? void 0 : value;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// src/core/providers/codex/bedrock.ts
|
|
88
|
+
import { existsSync, readFileSync } from "fs";
|
|
89
|
+
import * as path from "path";
|
|
90
|
+
var BEDROCK_OPENAI_NAMESPACE = "openai.";
|
|
91
|
+
var BEDROCK_CODEX_MODEL_PROVIDER = "amazon-bedrock";
|
|
92
|
+
var BEDROCK_RUNTIME_CODEX_MODEL_PROVIDER = "amazon-bedrock-runtime";
|
|
93
|
+
var CODEX_CONFIG_FILE = "config.toml";
|
|
94
|
+
function codexProfileConfigFile(profile) {
|
|
95
|
+
return `${profile}.config.toml`;
|
|
96
|
+
}
|
|
97
|
+
var TOP_LEVEL_MODEL_PROVIDER = /^\s*(?:model_provider|"model_provider"|'model_provider')\s*=\s*(?:"""([\s\S]*?)"""|'''([\s\S]*?)'''|"([^"]*)"|'([^']*)')\s*(?:#.*)?$/;
|
|
98
|
+
var TOML_TABLE_HEADER = /^\s*\[/;
|
|
99
|
+
function codexHomeCandidates(env) {
|
|
100
|
+
const explicitHome = env.CODEX_HOME?.trim();
|
|
101
|
+
if (explicitHome) {
|
|
102
|
+
return [normalizeCodexHomePath(explicitHome)];
|
|
103
|
+
}
|
|
104
|
+
const homes = [];
|
|
105
|
+
const home = env.HOME?.trim();
|
|
106
|
+
if (home) {
|
|
107
|
+
homes.push(path.join(home, ".codex"));
|
|
108
|
+
}
|
|
109
|
+
return homes;
|
|
110
|
+
}
|
|
111
|
+
function readCodexConfigModelProvider(configPath) {
|
|
112
|
+
if (!existsSync(configPath)) {
|
|
113
|
+
return void 0;
|
|
114
|
+
}
|
|
115
|
+
try {
|
|
116
|
+
for (const line of readFileSync(configPath, "utf8").split(/\r?\n/)) {
|
|
117
|
+
if (TOML_TABLE_HEADER.test(line)) {
|
|
118
|
+
return void 0;
|
|
119
|
+
}
|
|
120
|
+
const match = TOP_LEVEL_MODEL_PROVIDER.exec(line);
|
|
121
|
+
if (match) {
|
|
122
|
+
const value = (match[1] ?? match[2] ?? match[3] ?? match[4] ?? "").trim();
|
|
123
|
+
return value === "" ? void 0 : value;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return void 0;
|
|
127
|
+
} catch {
|
|
128
|
+
return void 0;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
function backendFromModelProvider(value) {
|
|
132
|
+
const normalized = value.trim().toLowerCase();
|
|
133
|
+
if (isCodexBedrockProviderId(normalized) || normalized === "bedrock") {
|
|
134
|
+
return "bedrock";
|
|
135
|
+
}
|
|
136
|
+
if (normalized === "openai") {
|
|
137
|
+
return "openai";
|
|
138
|
+
}
|
|
139
|
+
return void 0;
|
|
140
|
+
}
|
|
141
|
+
function isCodexBedrockProviderId(value) {
|
|
142
|
+
const normalized = value?.trim().toLowerCase();
|
|
143
|
+
return normalized === BEDROCK_CODEX_MODEL_PROVIDER || normalized === BEDROCK_RUNTIME_CODEX_MODEL_PROVIDER;
|
|
144
|
+
}
|
|
145
|
+
function isBedrockRuntimeCodexProvider(value) {
|
|
146
|
+
return value?.trim().toLowerCase() === BEDROCK_RUNTIME_CODEX_MODEL_PROVIDER;
|
|
147
|
+
}
|
|
148
|
+
function resolveBackendFromCodexConfig(env, profile) {
|
|
149
|
+
const selected = profile?.trim();
|
|
150
|
+
const useProfile = Boolean(selected) && selected !== "default";
|
|
151
|
+
for (const home of codexHomeCandidates(env)) {
|
|
152
|
+
const candidates = [];
|
|
153
|
+
if (useProfile && selected) {
|
|
154
|
+
candidates.push({
|
|
155
|
+
path: path.join(home, codexProfileConfigFile(selected)),
|
|
156
|
+
source: "profile-config"
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
candidates.push({ path: path.join(home, CODEX_CONFIG_FILE), source: "base-config" });
|
|
160
|
+
for (const candidate of candidates) {
|
|
161
|
+
const provider = readCodexConfigModelProvider(candidate.path);
|
|
162
|
+
if (provider === void 0) {
|
|
163
|
+
continue;
|
|
164
|
+
}
|
|
165
|
+
return {
|
|
166
|
+
backend: backendFromModelProvider(provider),
|
|
167
|
+
source: candidate.source,
|
|
168
|
+
configPath: candidate.path,
|
|
169
|
+
modelProvider: provider.trim().toLowerCase()
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
return void 0;
|
|
174
|
+
}
|
|
175
|
+
function resolveCodexBackendDetailed(env = process.env, _workingDir, profile, callerModelProvider) {
|
|
176
|
+
const callerProvider = callerModelProvider?.trim().toLowerCase() || void 0;
|
|
177
|
+
const callerBackend = callerProvider ? backendFromModelProvider(callerProvider) : void 0;
|
|
178
|
+
const observed = callerProvider ? { backend: callerBackend, source: "caller-override", modelProvider: callerProvider } : resolveBackendFromCodexConfig(env, profile);
|
|
179
|
+
const explicit = env.BUILD_CODEX_BACKEND?.trim().toLowerCase();
|
|
180
|
+
if (explicit === "bedrock" || explicit === "openai") {
|
|
181
|
+
return {
|
|
182
|
+
backend: explicit,
|
|
183
|
+
source: "build-env",
|
|
184
|
+
...observed?.modelProvider ? { modelProvider: observed.modelProvider } : {},
|
|
185
|
+
...callerProvider && callerBackend !== explicit ? { conflictingCallerProvider: true } : {}
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
return observed ?? { backend: void 0, source: "none" };
|
|
189
|
+
}
|
|
190
|
+
function resolveCodexBackend(env = process.env, workingDir, profile, callerModelProvider) {
|
|
191
|
+
return resolveCodexBackendDetailed(env, workingDir, profile, callerModelProvider).backend;
|
|
192
|
+
}
|
|
193
|
+
function describeCodexBackendConflict(resolution) {
|
|
194
|
+
if (resolution.source !== "build-env" || resolution.backend !== "openai" || !isCodexBedrockProviderId(resolution.modelProvider)) {
|
|
195
|
+
return void 0;
|
|
196
|
+
}
|
|
197
|
+
return `[Codex] Conflicting backend selection: BUILD_CODEX_BACKEND is "openai" but the Codex config selects model_provider "${resolution.modelProvider}". Set only one.`;
|
|
198
|
+
}
|
|
199
|
+
var BEDROCK_GEOGRAPHY_PREFIXES = ["global.", "us.", "eu.", "jp.", "apac."];
|
|
200
|
+
function isBedrockOpenAiModelId(model) {
|
|
201
|
+
return model.trim().startsWith(BEDROCK_OPENAI_NAMESPACE);
|
|
202
|
+
}
|
|
203
|
+
function toBedrockCodexModelId(model) {
|
|
204
|
+
if (!model) {
|
|
205
|
+
return void 0;
|
|
206
|
+
}
|
|
207
|
+
const trimmed = model.trim();
|
|
208
|
+
if (trimmed === "") {
|
|
209
|
+
return void 0;
|
|
210
|
+
}
|
|
211
|
+
if (isBedrockOpenAiModelId(trimmed)) {
|
|
212
|
+
return trimmed;
|
|
213
|
+
}
|
|
214
|
+
if (BEDROCK_GEOGRAPHY_PREFIXES.some((prefix) => trimmed.startsWith(prefix))) {
|
|
215
|
+
return void 0;
|
|
216
|
+
}
|
|
217
|
+
return `${BEDROCK_OPENAI_NAMESPACE}${trimmed}`;
|
|
218
|
+
}
|
|
219
|
+
function createMissingRuntimeProfileError(model, lookup) {
|
|
220
|
+
const cause = lookup?.outcome === "unavailable" ? `Build could not read the provider registry (${lookup.error}), so no inference profile could be looked up for Codex model "${model}".` : `No Bedrock inference profile is registered for Codex model "${model}".`;
|
|
221
|
+
const declared = lookup?.outcome === "absent" && lookup.declaredModels && lookup.declaredModels.length > 0 ? ` 1. Pin a model with a registered profile: ${lookup.declaredModels.join(", ")}.` : " 1. Pin a model with a registered bedrock-runtime global route.";
|
|
222
|
+
return new ProviderExecutionError(
|
|
223
|
+
[
|
|
224
|
+
`Error: ${cause}`,
|
|
225
|
+
`The ${BEDROCK_RUNTIME_CODEX_MODEL_PROVIDER} provider accepts OpenAI models only through inference profiles; no model was substituted.`,
|
|
226
|
+
"",
|
|
227
|
+
"To fix:",
|
|
228
|
+
declared,
|
|
229
|
+
" 2. Or declare a verified bedrock-runtime global route for this model in your user provider registry (~/.build/config/providers.yaml by default).",
|
|
230
|
+
" 3. Or use the auto model so Codex runs its configured default."
|
|
231
|
+
].join("\n"),
|
|
232
|
+
{
|
|
233
|
+
retryable: false,
|
|
234
|
+
reason: "missing_bedrock_model_mapping",
|
|
235
|
+
providerName: "codex"
|
|
236
|
+
}
|
|
237
|
+
);
|
|
238
|
+
}
|
|
239
|
+
function resolveBedrockCodexWireModel(model, modelProvider, lookup) {
|
|
240
|
+
const derived = toBedrockCodexModelId(model);
|
|
241
|
+
if (derived === void 0 || isBedrockOpenAiModelId(model)) {
|
|
242
|
+
return derived ?? model;
|
|
243
|
+
}
|
|
244
|
+
if (isBedrockRuntimeCodexProvider(modelProvider)) {
|
|
245
|
+
if (lookup?.outcome === "declared" && lookup.backend === "bedrock-runtime") {
|
|
246
|
+
return lookup.profile;
|
|
247
|
+
}
|
|
248
|
+
throw createMissingRuntimeProfileError(model.trim(), lookup);
|
|
249
|
+
}
|
|
250
|
+
return lookup?.outcome === "declared" && lookup.backend === "bedrock-mantle" ? lookup.profile : derived;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// src/core/providers/codex/connection.ts
|
|
254
|
+
function readCodexConnection(env, profile) {
|
|
255
|
+
const home = env.CODEX_HOME?.trim() ? normalizeCodexHomePath(env.CODEX_HOME) : path2.join(env.HOME?.trim() || homedir(), ".codex");
|
|
256
|
+
const values = /* @__PURE__ */ new Map();
|
|
257
|
+
for (const file of [
|
|
258
|
+
path2.join(home, "config.toml"),
|
|
259
|
+
...profile && profile !== "default" ? [path2.join(home, `${profile}.config.toml`)] : []
|
|
260
|
+
]) {
|
|
261
|
+
try {
|
|
262
|
+
for (const [key, value] of readTomlValues(readFileSync2(file, "utf8"))) values.set(key, value);
|
|
263
|
+
} catch {
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
const resolution = resolveCodexBackendDetailed(env, void 0, profile);
|
|
267
|
+
const conflict = describeCodexBackendConflict(resolution);
|
|
268
|
+
const provider = resolution.modelProvider ?? values.get("model_provider");
|
|
269
|
+
const settings = [...values].filter(
|
|
270
|
+
([key]) => key === "model_provider" || key === "model_catalog_json" || key === "models_catalog_json" || key === "model_context_window" || typeof provider === "string" && key.startsWith(`model_providers.${provider}.`) && /\.(?:base_url|wire_api|model_catalog_url|models_url|models_catalog_url|region|project|requires_openai_auth)$/.test(
|
|
271
|
+
key
|
|
272
|
+
)
|
|
273
|
+
);
|
|
274
|
+
return {
|
|
275
|
+
home,
|
|
276
|
+
profile: profile ?? "default",
|
|
277
|
+
backend: resolution.backend,
|
|
278
|
+
modelProvider: provider,
|
|
279
|
+
settings,
|
|
280
|
+
values,
|
|
281
|
+
conflict,
|
|
282
|
+
assertedProvider: resolution.source === "build-env" && resolution.backend === "bedrock" && !isCodexBedrockProviderId(resolution.modelProvider) ? BEDROCK_CODEX_MODEL_PROVIDER : void 0
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
function codexConnectionCoordinates(env, profile) {
|
|
286
|
+
const { values: _values, ...connection } = readCodexConnection(env, profile);
|
|
287
|
+
return {
|
|
288
|
+
...connection,
|
|
289
|
+
settings: connection.settings.map(([key, value]) => [
|
|
290
|
+
key,
|
|
291
|
+
/(?:url)$/.test(key) ? endpointCoordinate(value) : value
|
|
292
|
+
])
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
// src/core/providers/opencode/connection.ts
|
|
297
|
+
import { createHash } from "crypto";
|
|
298
|
+
import { readFileSync as readFileSync3 } from "fs";
|
|
299
|
+
import { homedir as homedir2 } from "os";
|
|
300
|
+
import path3 from "path";
|
|
301
|
+
import { parse } from "jsonc-parser";
|
|
302
|
+
function record(value) {
|
|
303
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
304
|
+
}
|
|
305
|
+
function configCoordinates(value) {
|
|
306
|
+
const config = record(value);
|
|
307
|
+
return {
|
|
308
|
+
enabled_providers: config.enabled_providers,
|
|
309
|
+
disabled_providers: config.disabled_providers,
|
|
310
|
+
providers: Object.entries(record(config.provider)).sort(([a], [b]) => a.localeCompare(b)).map(([id, raw]) => {
|
|
311
|
+
const provider = record(raw);
|
|
312
|
+
const options = record(provider.options);
|
|
313
|
+
return {
|
|
314
|
+
id,
|
|
315
|
+
npm: typeof provider.npm === "string" ? provider.npm : void 0,
|
|
316
|
+
api: endpointCoordinate(provider.api),
|
|
317
|
+
options: Object.fromEntries(
|
|
318
|
+
["baseURL", "region", "profile", "project", "location", "endpoint"].filter((key) => typeof options[key] === "string").map((key) => [
|
|
319
|
+
key,
|
|
320
|
+
key === "baseURL" || key === "endpoint" ? endpointCoordinate(options[key]) : options[key]
|
|
321
|
+
])
|
|
322
|
+
),
|
|
323
|
+
models: Object.entries(record(provider.models)).sort(([a], [b]) => a.localeCompare(b)).map(([selector, model]) => ({
|
|
324
|
+
selector,
|
|
325
|
+
id: typeof record(model).id === "string" ? record(model).id : void 0,
|
|
326
|
+
api: endpointCoordinate(record(model).api)
|
|
327
|
+
}))
|
|
328
|
+
};
|
|
329
|
+
})
|
|
330
|
+
};
|
|
331
|
+
}
|
|
332
|
+
function opencodeConnectionCoordinates(projectRoot, env) {
|
|
333
|
+
const configHome = env.BUILD_OPENCODE_XDG_CONFIG_HOME?.trim() || env.XDG_CONFIG_HOME?.trim() || path3.join(env.HOME?.trim() || homedir2(), ".config");
|
|
334
|
+
const files = [
|
|
335
|
+
path3.join(configHome, "opencode", "opencode.json"),
|
|
336
|
+
path3.join(configHome, "opencode", "opencode.jsonc"),
|
|
337
|
+
path3.join(configHome, "opencode", "config.json")
|
|
338
|
+
];
|
|
339
|
+
for (let current = path3.resolve(projectRoot); ; ) {
|
|
340
|
+
files.push(path3.join(current, "opencode.json"), path3.join(current, "opencode.jsonc"));
|
|
341
|
+
const parent = path3.dirname(current);
|
|
342
|
+
if (parent === current) break;
|
|
343
|
+
current = parent;
|
|
344
|
+
}
|
|
345
|
+
if (env.OPENCODE_CONFIG) files.push(path3.resolve(projectRoot, env.OPENCODE_CONFIG));
|
|
346
|
+
const configs = [];
|
|
347
|
+
for (const file of files) {
|
|
348
|
+
try {
|
|
349
|
+
configs.push([file, configCoordinates(parse(readFileSync3(file, "utf8")))]);
|
|
350
|
+
} catch {
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
if (env.OPENCODE_CONFIG_CONTENT)
|
|
354
|
+
configs.push(["inline", configCoordinates(parse(env.OPENCODE_CONFIG_CONTENT))]);
|
|
355
|
+
return {
|
|
356
|
+
configHome,
|
|
357
|
+
configs,
|
|
358
|
+
awsProfile: env.AWS_PROFILE,
|
|
359
|
+
region: env.AWS_REGION ?? env.AWS_DEFAULT_REGION,
|
|
360
|
+
project: env.GOOGLE_CLOUD_PROJECT,
|
|
361
|
+
location: env.CLOUD_ML_REGION
|
|
362
|
+
};
|
|
363
|
+
}
|
|
364
|
+
function opencodeInventoryContext(projectRoot, env) {
|
|
365
|
+
return createHash("sha256").update(
|
|
366
|
+
JSON.stringify({
|
|
367
|
+
projectRoot: path3.resolve(projectRoot),
|
|
368
|
+
...opencodeConnectionCoordinates(projectRoot, env)
|
|
369
|
+
})
|
|
370
|
+
).digest("hex");
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
// src/core/providers/refresh/overlay.ts
|
|
374
|
+
import { existsSync as existsSync2, readFileSync as readFileSync4 } from "fs";
|
|
375
|
+
import * as fs from "fs/promises";
|
|
376
|
+
import { z } from "zod";
|
|
377
|
+
var REFRESH_OVERLAY_SCHEMA_VERSION = 1;
|
|
378
|
+
var UsdPer1MSchema = z.union([
|
|
379
|
+
z.number().nonnegative(),
|
|
380
|
+
z.string().regex(/^\d+(?:\.\d+)?$/, "Must be non-negative USD")
|
|
381
|
+
]);
|
|
382
|
+
var OverlayModelAvailableEntrySchema = z.object({
|
|
383
|
+
id: z.string().trim().min(1),
|
|
384
|
+
display_name: z.string().min(1),
|
|
385
|
+
full_name: z.string().optional(),
|
|
386
|
+
capabilities: z.array(z.string()),
|
|
387
|
+
context_window: z.number().int().positive().optional(),
|
|
388
|
+
max_output_tokens: z.number().int().positive().optional(),
|
|
389
|
+
reasoning_effort_levels: z.array(z.string()).optional(),
|
|
390
|
+
default_reasoning_effort: z.string().optional(),
|
|
391
|
+
thinking: z.object({
|
|
392
|
+
supported: z.boolean().optional(),
|
|
393
|
+
adaptive: z.boolean().optional(),
|
|
394
|
+
budget_tokens_supported: z.boolean().optional(),
|
|
395
|
+
min_budget_tokens: z.number().int().optional(),
|
|
396
|
+
default_budget_tokens: z.number().int().optional(),
|
|
397
|
+
max_budget_tokens: z.number().int().optional()
|
|
398
|
+
}).strict().optional(),
|
|
399
|
+
canonical_id: z.string().optional(),
|
|
400
|
+
lineage: z.string().optional(),
|
|
401
|
+
release_date: z.string().optional(),
|
|
402
|
+
lifecycle: z.record(z.string(), z.unknown()).optional(),
|
|
403
|
+
metadata_sources: z.record(z.string(), z.enum(["official", "community", "native"])).optional(),
|
|
404
|
+
harness: z.object({
|
|
405
|
+
context_window: z.number().int().positive().optional(),
|
|
406
|
+
max_context_window: z.number().int().positive().optional(),
|
|
407
|
+
max_output_tokens: z.number().int().positive().optional()
|
|
408
|
+
}).strict().optional(),
|
|
409
|
+
notes: z.string().optional(),
|
|
410
|
+
discovery_source: z.enum(["API", "native", "community"]).optional(),
|
|
411
|
+
deprecation: z.record(z.string(), z.unknown()).optional()
|
|
412
|
+
}).strict();
|
|
413
|
+
var OverlayPricingRowSchema = z.object({
|
|
414
|
+
input_per_1m_tokens: UsdPer1MSchema.optional(),
|
|
415
|
+
output_per_1m_tokens: UsdPer1MSchema.optional(),
|
|
416
|
+
cache_read_per_1m_tokens: UsdPer1MSchema.optional(),
|
|
417
|
+
cache_write_per_1m_tokens: UsdPer1MSchema.optional(),
|
|
418
|
+
long_context_pricing: LongContextPricingSchema.optional(),
|
|
419
|
+
speed_tiers: z.record(z.string(), SpeedTierPricingSchema).optional(),
|
|
420
|
+
context_window: z.number().int().positive().optional(),
|
|
421
|
+
features: z.record(z.string(), z.boolean()).optional(),
|
|
422
|
+
// Runtime pricing fields travel with the rates they describe: an overlay-only
|
|
423
|
+
// row has no authored row to inherit them from.
|
|
424
|
+
billing_source: z.string().optional(),
|
|
425
|
+
pricing_source: z.string().optional(),
|
|
426
|
+
pricing_confidence: z.enum(["high", "medium", "low"]).optional(),
|
|
427
|
+
notes: z.string().optional(),
|
|
428
|
+
last_updated: z.string().optional()
|
|
429
|
+
}).strict();
|
|
430
|
+
var REFRESH_SOURCES = [
|
|
431
|
+
"API",
|
|
432
|
+
"community",
|
|
433
|
+
"doc-poll",
|
|
434
|
+
"pricing-only",
|
|
435
|
+
"discovery",
|
|
436
|
+
"static"
|
|
437
|
+
];
|
|
438
|
+
var OverlaySliceProvenanceSchema = z.object({
|
|
439
|
+
source: z.enum(REFRESH_SOURCES),
|
|
440
|
+
fetchedAt: z.string().min(1),
|
|
441
|
+
freshnessMs: z.number().int().nonnegative().optional()
|
|
442
|
+
}).strict();
|
|
443
|
+
var OverlayProviderPayloadSchema = z.object({
|
|
444
|
+
models: z.object({
|
|
445
|
+
available: z.array(OverlayModelAvailableEntrySchema),
|
|
446
|
+
/** Treat available as the complete provider inventory, not an additive patch. */
|
|
447
|
+
replaceInventory: z.literal(true).optional(),
|
|
448
|
+
/**
|
|
449
|
+
* Ids the provider CLI itself reported on its last observed inventory
|
|
450
|
+
* (context payloads only). Offered models are limited to this set; rows
|
|
451
|
+
* from public feeds or earlier refreshes stay resolvable but unlisted.
|
|
452
|
+
*/
|
|
453
|
+
observedIds: z.array(z.string().trim().min(1)).optional()
|
|
454
|
+
}).strict().optional(),
|
|
455
|
+
pricing: z.object({
|
|
456
|
+
models: z.record(z.string(), OverlayPricingRowSchema)
|
|
457
|
+
}).strict().optional(),
|
|
458
|
+
/** Provider-level freshness / provenance. */
|
|
459
|
+
provenance: OverlaySliceProvenanceSchema.optional(),
|
|
460
|
+
/** Per-slice freshness / provenance (models vs pricing). */
|
|
461
|
+
slices: z.object({
|
|
462
|
+
models: OverlaySliceProvenanceSchema.optional(),
|
|
463
|
+
pricing: OverlaySliceProvenanceSchema.optional()
|
|
464
|
+
}).strict().optional()
|
|
465
|
+
}).strict();
|
|
466
|
+
var RefreshOverlayDocumentSchema = z.object({
|
|
467
|
+
schemaVersion: z.literal(REFRESH_OVERLAY_SCHEMA_VERSION),
|
|
468
|
+
baseCatalogDigest: z.string().min(1),
|
|
469
|
+
providers: z.record(z.string(), OverlayProviderPayloadSchema),
|
|
470
|
+
/** Native inventories are never a provider-wide public catalog. */
|
|
471
|
+
contexts: z.record(z.string(), z.record(z.string(), OverlayProviderPayloadSchema)).optional()
|
|
472
|
+
}).strict();
|
|
473
|
+
var REFRESH_OVERLAY_RERUN_GUIDANCE = "Refresh overlay ignored because the release catalog digest changed. Run: build provider refresh";
|
|
474
|
+
var REFRESH_OVERLAY_SOURCE_DRIFT_GUIDANCE = "Refresh overlay ignored because .build-project/config/providers.yaml changed after the provider catalog was generated. Run: node scripts/generate-provider-json.js, then build provider refresh";
|
|
475
|
+
function noticeFromRefreshOverlayDisposition(disposition) {
|
|
476
|
+
if (disposition.status === "degraded") {
|
|
477
|
+
return {
|
|
478
|
+
status: "degraded",
|
|
479
|
+
reason: disposition.reason,
|
|
480
|
+
message: disposition.warning,
|
|
481
|
+
guidance: disposition.reason === "source_base_drift" ? REFRESH_OVERLAY_SOURCE_DRIFT_GUIDANCE : REFRESH_OVERLAY_RERUN_GUIDANCE
|
|
482
|
+
};
|
|
483
|
+
}
|
|
484
|
+
if (disposition.status === "rejected") {
|
|
485
|
+
return {
|
|
486
|
+
status: "rejected",
|
|
487
|
+
reason: disposition.reason,
|
|
488
|
+
message: disposition.error,
|
|
489
|
+
guidance: "Refresh overlay is invalid and was ignored. Run: build provider refresh"
|
|
490
|
+
};
|
|
491
|
+
}
|
|
492
|
+
return void 0;
|
|
493
|
+
}
|
|
494
|
+
function getRefreshOverlayOperatorNotice(overlayPath, expectedBaseCatalogDigest, sourceBaseDrift) {
|
|
495
|
+
if (!existsSync2(overlayPath)) return void 0;
|
|
496
|
+
try {
|
|
497
|
+
const disposition = resolveRefreshOverlayDisposition(readFileSync4(overlayPath, "utf8"), {
|
|
498
|
+
expectedBaseCatalogDigest,
|
|
499
|
+
sourceBaseDrift
|
|
500
|
+
});
|
|
501
|
+
return noticeFromRefreshOverlayDisposition(disposition);
|
|
502
|
+
} catch {
|
|
503
|
+
return void 0;
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
function sortKeysDeep(value) {
|
|
507
|
+
if (Array.isArray(value)) {
|
|
508
|
+
return value.map(sortKeysDeep);
|
|
509
|
+
}
|
|
510
|
+
if (value && typeof value === "object") {
|
|
511
|
+
const sorted = {};
|
|
512
|
+
for (const key of Object.keys(value).sort()) {
|
|
513
|
+
sorted[key] = sortKeysDeep(value[key]);
|
|
514
|
+
}
|
|
515
|
+
return sorted;
|
|
516
|
+
}
|
|
517
|
+
return value;
|
|
518
|
+
}
|
|
519
|
+
function emptyRefreshOverlay(baseCatalogDigest) {
|
|
520
|
+
return {
|
|
521
|
+
schemaVersion: REFRESH_OVERLAY_SCHEMA_VERSION,
|
|
522
|
+
baseCatalogDigest,
|
|
523
|
+
providers: {}
|
|
524
|
+
};
|
|
525
|
+
}
|
|
526
|
+
function serializeRefreshOverlay(overlay) {
|
|
527
|
+
const parsed = RefreshOverlayDocumentSchema.safeParse(overlay);
|
|
528
|
+
if (!parsed.success) {
|
|
529
|
+
throw new Error(
|
|
530
|
+
`Cannot serialize invalid refresh overlay: ${parsed.error.issues.map((issue) => issue.message).join("; ")}`
|
|
531
|
+
);
|
|
532
|
+
}
|
|
533
|
+
return `${JSON.stringify(sortKeysDeep(parsed.data), null, 2)}
|
|
534
|
+
`;
|
|
535
|
+
}
|
|
536
|
+
function parseRefreshOverlayValue(value) {
|
|
537
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
538
|
+
return { ok: false, error: "Refresh overlay must be a JSON object" };
|
|
539
|
+
}
|
|
540
|
+
const parsed = RefreshOverlayDocumentSchema.safeParse(value);
|
|
541
|
+
if (!parsed.success) {
|
|
542
|
+
return {
|
|
543
|
+
ok: false,
|
|
544
|
+
error: `Invalid refresh overlay schema: ${parsed.error.issues.map((issue) => `${issue.path.join(".") || "<root>"}: ${issue.message}`).join("; ")}`
|
|
545
|
+
};
|
|
546
|
+
}
|
|
547
|
+
return { ok: true, overlay: parsed.data };
|
|
548
|
+
}
|
|
549
|
+
function parseRefreshOverlay(raw) {
|
|
550
|
+
let value;
|
|
551
|
+
try {
|
|
552
|
+
value = JSON.parse(raw);
|
|
553
|
+
} catch (error) {
|
|
554
|
+
return {
|
|
555
|
+
ok: false,
|
|
556
|
+
error: `Refresh overlay is not valid JSON: ${error instanceof Error ? error.message : String(error)}`
|
|
557
|
+
};
|
|
558
|
+
}
|
|
559
|
+
return parseRefreshOverlayValue(value);
|
|
560
|
+
}
|
|
561
|
+
function resolveRefreshOverlayDisposition(input, options) {
|
|
562
|
+
const parsed = typeof input === "string" ? parseRefreshOverlay(input) : parseRefreshOverlayValue(input);
|
|
563
|
+
if (!parsed.ok) {
|
|
564
|
+
return { status: "rejected", reason: "invalid_schema", error: parsed.error };
|
|
565
|
+
}
|
|
566
|
+
if (options.sourceBaseDrift) {
|
|
567
|
+
const drift = options.sourceBaseDrift;
|
|
568
|
+
return {
|
|
569
|
+
status: "degraded",
|
|
570
|
+
reason: "source_base_drift",
|
|
571
|
+
warning: `Refresh overlay source base drift: ${drift.path} sha256=${drift.actualDigest} does not match the compiled source digest ${drift.expectedDigest}; overlay ignored until the provider generator runs`,
|
|
572
|
+
overlay: parsed.overlay
|
|
573
|
+
};
|
|
574
|
+
}
|
|
575
|
+
if (options.expectedBaseCatalogDigest !== parsed.overlay.baseCatalogDigest) {
|
|
576
|
+
return {
|
|
577
|
+
status: "degraded",
|
|
578
|
+
reason: "base_digest_mismatch",
|
|
579
|
+
warning: `Refresh overlay base catalog digest mismatch: overlay=${parsed.overlay.baseCatalogDigest} expected=${options.expectedBaseCatalogDigest}; overlay ignored`,
|
|
580
|
+
overlay: parsed.overlay
|
|
581
|
+
};
|
|
582
|
+
}
|
|
583
|
+
return { status: "ready", overlay: parsed.overlay };
|
|
584
|
+
}
|
|
585
|
+
async function loadRefreshOverlayFile(overlayPath, options) {
|
|
586
|
+
try {
|
|
587
|
+
const stat = await fs.lstat(overlayPath);
|
|
588
|
+
if (stat.isSymbolicLink()) {
|
|
589
|
+
return {
|
|
590
|
+
status: "rejected",
|
|
591
|
+
reason: "invalid_schema",
|
|
592
|
+
error: `Provider refresh refuses a symlinked overlay: ${overlayPath}`
|
|
593
|
+
};
|
|
594
|
+
}
|
|
595
|
+
if (!stat.isFile()) {
|
|
596
|
+
return {
|
|
597
|
+
status: "rejected",
|
|
598
|
+
reason: "invalid_schema",
|
|
599
|
+
error: `Provider refresh overlay target is not a regular file: ${overlayPath}`
|
|
600
|
+
};
|
|
601
|
+
}
|
|
602
|
+
const raw = await fs.readFile(overlayPath, "utf8");
|
|
603
|
+
return resolveRefreshOverlayDisposition(raw, options);
|
|
604
|
+
} catch (error) {
|
|
605
|
+
if (error.code === "ENOENT") {
|
|
606
|
+
return { status: "absent" };
|
|
607
|
+
}
|
|
608
|
+
throw error;
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
// src/core/providers/refresh/storage.ts
|
|
613
|
+
function hash(value) {
|
|
614
|
+
return createHash2("sha256").update(value).digest("hex");
|
|
615
|
+
}
|
|
616
|
+
var PROVIDER_CHILD_ONLY_ENV = ["XDG_DATA_HOME", "CURSOR_CONFIG_DIR"];
|
|
617
|
+
function readRefreshOrigin(raw) {
|
|
618
|
+
if (!raw) return void 0;
|
|
619
|
+
try {
|
|
620
|
+
const parsed = JSON.parse(raw);
|
|
621
|
+
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : void 0;
|
|
622
|
+
} catch {
|
|
623
|
+
return void 0;
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
function withRefreshOrigin(overrides) {
|
|
627
|
+
if (!PROVIDER_CHILD_ONLY_ENV.some((key) => key in overrides)) return overrides;
|
|
628
|
+
const inherited = process.env[BUILD_REFRESH_ORIGIN_ENV.name];
|
|
629
|
+
const origin = inherited ?? JSON.stringify(
|
|
630
|
+
Object.fromEntries(PROVIDER_CHILD_ONLY_ENV.map((key) => [key, process.env[key] ?? null]))
|
|
631
|
+
);
|
|
632
|
+
return { ...overrides, [BUILD_REFRESH_ORIGIN_ENV.name]: origin };
|
|
633
|
+
}
|
|
634
|
+
function refreshEnvironment() {
|
|
635
|
+
const env = { ...process.env, ...getExecutionContext().envOverrides };
|
|
636
|
+
const origin = readRefreshOrigin(env[BUILD_REFRESH_ORIGIN_ENV.name]);
|
|
637
|
+
for (const key of PROVIDER_CHILD_ONLY_ENV) {
|
|
638
|
+
const value = origin ? origin[key] : process.env[key];
|
|
639
|
+
if (typeof value === "string") env[key] = value;
|
|
640
|
+
else delete env[key];
|
|
641
|
+
}
|
|
642
|
+
return env;
|
|
643
|
+
}
|
|
644
|
+
function refreshInventoryContext(projectRoot, env = refreshEnvironment()) {
|
|
645
|
+
const root = existsSync3(projectRoot) ? realpathSync(projectRoot) : path4.resolve(projectRoot);
|
|
646
|
+
const label = env.BUILD_MODEL_REFRESH_CONTEXT?.trim();
|
|
647
|
+
const coordinates = [
|
|
648
|
+
label || `unknown:${root}`,
|
|
649
|
+
env.AWS_PROFILE ?? "",
|
|
650
|
+
env.AWS_REGION ?? env.AWS_DEFAULT_REGION ?? "",
|
|
651
|
+
env.GOOGLE_CLOUD_PROJECT ?? "",
|
|
652
|
+
env.CLOUD_ML_REGION ?? "",
|
|
653
|
+
env.CODEX_HOME ?? "",
|
|
654
|
+
env.CLAUDE_CONFIG_DIR ?? "",
|
|
655
|
+
codexConnectionCoordinates(env),
|
|
656
|
+
opencodeConnectionCoordinates(root, env),
|
|
657
|
+
// Appended only when set, so keys for users without these homes are unchanged.
|
|
658
|
+
...env.GROK_HOME?.trim() ? [`grok-home:${env.GROK_HOME.trim()}`] : [],
|
|
659
|
+
...env.CURSOR_CONFIG_DIR?.trim() ? [`cursor-config:${env.CURSOR_CONFIG_DIR.trim()}`] : []
|
|
660
|
+
];
|
|
661
|
+
return hash(JSON.stringify(coordinates));
|
|
662
|
+
}
|
|
663
|
+
function resolveSharedRefreshPaths(digest2 = PROVIDER_CATALOG_SHA256, env = refreshEnvironment()) {
|
|
664
|
+
const dataRoot = assertContainedPath(getDataDir(env), ".", "Provider data root");
|
|
665
|
+
const storageRoot = path4.join(dataRoot, "provider-refresh", hash(digest2));
|
|
666
|
+
return {
|
|
667
|
+
dataRoot,
|
|
668
|
+
storageRoot,
|
|
669
|
+
overlayPath: path4.join(storageRoot, "refresh-overlay.json"),
|
|
670
|
+
lockFile: path4.join(storageRoot, "refresh.lock"),
|
|
671
|
+
auditLogFile: path4.join(storageRoot, "refresh.jsonl")
|
|
672
|
+
};
|
|
673
|
+
}
|
|
674
|
+
function selectRefreshContext(overlay, contextId) {
|
|
675
|
+
const providers = { ...overlay.providers };
|
|
676
|
+
for (const [provider, payload] of Object.entries(overlay.contexts?.[contextId] ?? {})) {
|
|
677
|
+
const publicPayload = providers[provider];
|
|
678
|
+
const models = new Map((publicPayload?.models?.available ?? []).map((row) => [row.id, row]));
|
|
679
|
+
for (const row of payload.models?.available ?? [])
|
|
680
|
+
models.set(row.id, mergeContextModel(models.get(row.id), row));
|
|
681
|
+
providers[provider] = {
|
|
682
|
+
...publicPayload,
|
|
683
|
+
...payload,
|
|
684
|
+
...publicPayload?.models || payload.models ? {
|
|
685
|
+
models: {
|
|
686
|
+
available: [...models.values()],
|
|
687
|
+
...payload.models?.observedIds ? { observedIds: payload.models.observedIds } : {}
|
|
688
|
+
}
|
|
689
|
+
} : {},
|
|
690
|
+
slices: { ...publicPayload?.slices, ...payload.slices },
|
|
691
|
+
...publicPayload?.pricing || payload.pricing ? { pricing: { models: { ...publicPayload?.pricing?.models, ...payload.pricing?.models } } } : {}
|
|
692
|
+
};
|
|
693
|
+
}
|
|
694
|
+
return { ...overlay, providers };
|
|
695
|
+
}
|
|
696
|
+
function mergeContextModel(publicRow, contextRow) {
|
|
697
|
+
if (!publicRow) return contextRow;
|
|
698
|
+
const sources = {};
|
|
699
|
+
const record2 = (value) => Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
700
|
+
const merge = (published, observed, field, inheritedPublic, inheritedNative) => {
|
|
701
|
+
const publicSource = publicRow.metadata_sources?.[field] ?? inheritedPublic;
|
|
702
|
+
const contextSource = contextRow.metadata_sources?.[field] ?? inheritedNative;
|
|
703
|
+
if ((record2(published) || published === void 0) && (record2(observed) || observed === void 0) && (record2(published) || record2(observed))) {
|
|
704
|
+
const left = record2(published) ? published : {};
|
|
705
|
+
const right = record2(observed) ? observed : {};
|
|
706
|
+
return Object.fromEntries(
|
|
707
|
+
[.../* @__PURE__ */ new Set([...Object.keys(left), ...Object.keys(right)])].filter((key) => field !== "" || key !== "metadata_sources").map((key) => [
|
|
708
|
+
key,
|
|
709
|
+
merge(
|
|
710
|
+
left[key],
|
|
711
|
+
right[key],
|
|
712
|
+
field ? `${field}.${key}` : key,
|
|
713
|
+
publicSource,
|
|
714
|
+
contextSource
|
|
715
|
+
)
|
|
716
|
+
])
|
|
717
|
+
);
|
|
718
|
+
}
|
|
719
|
+
const useContext = observed !== void 0 && (published === void 0 || contextSource === "native" || field === "discovery_source");
|
|
720
|
+
const source = useContext ? contextSource : publicSource;
|
|
721
|
+
if (source) sources[field] = source;
|
|
722
|
+
return useContext ? observed : published;
|
|
723
|
+
};
|
|
724
|
+
const merged = merge(publicRow, contextRow, "");
|
|
725
|
+
if (Object.keys(sources).length) merged.metadata_sources = sources;
|
|
726
|
+
return merged;
|
|
727
|
+
}
|
|
728
|
+
function carriedModels(payloads) {
|
|
729
|
+
return Object.fromEntries(
|
|
730
|
+
Object.entries(payloads).flatMap(([provider, payload]) => {
|
|
731
|
+
if (!payload.models) return [];
|
|
732
|
+
const { replaceInventory: _replace, ...models } = payload.models;
|
|
733
|
+
return [[provider, { models }]];
|
|
734
|
+
})
|
|
735
|
+
);
|
|
736
|
+
}
|
|
737
|
+
function carriedForwardOverlay(overlayPath, digest2) {
|
|
738
|
+
const refreshRoot = path4.dirname(path4.dirname(overlayPath));
|
|
739
|
+
const current = path4.basename(path4.dirname(overlayPath));
|
|
740
|
+
let entries;
|
|
741
|
+
try {
|
|
742
|
+
entries = readdirSync(refreshRoot);
|
|
743
|
+
} catch {
|
|
744
|
+
return void 0;
|
|
745
|
+
}
|
|
746
|
+
const previous = entries.filter((entry) => entry !== current).flatMap((entry) => {
|
|
747
|
+
const overlayPath2 = path4.join(refreshRoot, entry, "refresh-overlay.json");
|
|
748
|
+
try {
|
|
749
|
+
const stat = statSync(overlayPath2);
|
|
750
|
+
return stat.isFile() ? [{ overlayPath: overlayPath2, mtimeMs: stat.mtimeMs }] : [];
|
|
751
|
+
} catch {
|
|
752
|
+
return [];
|
|
753
|
+
}
|
|
754
|
+
}).sort((left, right) => right.mtimeMs - left.mtimeMs)[0];
|
|
755
|
+
if (!previous) return void 0;
|
|
756
|
+
let parsed;
|
|
757
|
+
try {
|
|
758
|
+
parsed = parseRefreshOverlay(readFileSync5(previous.overlayPath, "utf8"));
|
|
759
|
+
} catch {
|
|
760
|
+
return void 0;
|
|
761
|
+
}
|
|
762
|
+
if (!parsed.ok) return void 0;
|
|
763
|
+
const contexts = Object.fromEntries(
|
|
764
|
+
Object.entries(parsed.overlay.contexts ?? {}).map(([id, payloads]) => [
|
|
765
|
+
id,
|
|
766
|
+
carriedModels(payloads)
|
|
767
|
+
])
|
|
768
|
+
);
|
|
769
|
+
return {
|
|
770
|
+
schemaVersion: parsed.overlay.schemaVersion,
|
|
771
|
+
baseCatalogDigest: digest2,
|
|
772
|
+
providers: carriedModels(parsed.overlay.providers),
|
|
773
|
+
...Object.keys(contexts).length > 0 ? { contexts } : {}
|
|
774
|
+
};
|
|
775
|
+
}
|
|
776
|
+
function readEffectiveRefreshOverlay(projectRoot, options, env = refreshEnvironment()) {
|
|
777
|
+
const shared = resolveSharedRefreshPaths(options.expectedBaseCatalogDigest, env);
|
|
778
|
+
const isShared = existsSync3(shared.overlayPath);
|
|
779
|
+
const overlayPath = isShared ? shared.overlayPath : path4.join(projectRoot, ".build-project", "cache", "model-update", "refresh-overlay.json");
|
|
780
|
+
let disposition = { status: "absent" };
|
|
781
|
+
const carried = existsSync3(overlayPath) ? void 0 : carriedForwardOverlay(shared.overlayPath, options.expectedBaseCatalogDigest);
|
|
782
|
+
if (carried) {
|
|
783
|
+
disposition = resolveRefreshOverlayDisposition(carried, options);
|
|
784
|
+
if (disposition.status === "ready") {
|
|
785
|
+
disposition = {
|
|
786
|
+
status: "ready",
|
|
787
|
+
overlay: selectRefreshContext(
|
|
788
|
+
disposition.overlay,
|
|
789
|
+
refreshInventoryContext(projectRoot, env)
|
|
790
|
+
)
|
|
791
|
+
};
|
|
792
|
+
}
|
|
793
|
+
return { path: shared.overlayPath, scope: "global", disposition, carried: true };
|
|
794
|
+
}
|
|
795
|
+
if (existsSync3(overlayPath)) {
|
|
796
|
+
try {
|
|
797
|
+
disposition = resolveRefreshOverlayDisposition(readFileSync5(overlayPath, "utf8"), options);
|
|
798
|
+
if (isShared && disposition.status === "ready") {
|
|
799
|
+
disposition = {
|
|
800
|
+
status: "ready",
|
|
801
|
+
overlay: selectRefreshContext(
|
|
802
|
+
disposition.overlay,
|
|
803
|
+
refreshInventoryContext(projectRoot, env)
|
|
804
|
+
)
|
|
805
|
+
};
|
|
806
|
+
}
|
|
807
|
+
} catch (error) {
|
|
808
|
+
disposition = {
|
|
809
|
+
status: "rejected",
|
|
810
|
+
reason: "invalid_schema",
|
|
811
|
+
error: `Cannot read refresh overlay: ${error instanceof Error ? error.message : String(error)}`
|
|
812
|
+
};
|
|
813
|
+
}
|
|
814
|
+
}
|
|
815
|
+
return { path: overlayPath, scope: isShared ? "global" : "legacy", disposition };
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
// src/core/config/cache-fingerprint.ts
|
|
819
|
+
import { createHash as createHash3 } from "crypto";
|
|
820
|
+
import { statSync as statSync2 } from "fs";
|
|
821
|
+
import { resolve } from "path";
|
|
822
|
+
function digest(value) {
|
|
823
|
+
return createHash3("sha256").update(value).digest("hex");
|
|
824
|
+
}
|
|
825
|
+
function fingerprintEnvironment(env, include = (name) => name.startsWith("BUILD_")) {
|
|
826
|
+
const entries = Object.entries(env).filter(([name, value]) => include(name) && value !== void 0).sort(([left], [right]) => left.localeCompare(right)).map(([name, value]) => [name, digest(value ?? "")]);
|
|
827
|
+
return digest(JSON.stringify(entries));
|
|
828
|
+
}
|
|
829
|
+
function fingerprintFile(filePath) {
|
|
830
|
+
const normalized = resolve(filePath);
|
|
831
|
+
try {
|
|
832
|
+
const stat = statSync2(normalized);
|
|
833
|
+
return JSON.stringify({
|
|
834
|
+
path: normalized,
|
|
835
|
+
exists: true,
|
|
836
|
+
dev: stat.dev,
|
|
837
|
+
ino: stat.ino,
|
|
838
|
+
size: stat.size,
|
|
839
|
+
mtimeMs: stat.mtimeMs,
|
|
840
|
+
ctimeMs: stat.ctimeMs
|
|
841
|
+
});
|
|
842
|
+
} catch (error) {
|
|
843
|
+
const code = error.code;
|
|
844
|
+
return JSON.stringify({ path: normalized, exists: false, code: code ?? "UNKNOWN" });
|
|
845
|
+
}
|
|
846
|
+
}
|
|
847
|
+
function fingerprintFiles(filePaths) {
|
|
848
|
+
return digest(JSON.stringify([...new Set(filePaths)].sort().map(fingerprintFile)));
|
|
849
|
+
}
|
|
850
|
+
function combineCacheFingerprints(...parts) {
|
|
851
|
+
return digest(JSON.stringify(parts.filter((part) => part !== void 0)));
|
|
852
|
+
}
|
|
853
|
+
|
|
854
|
+
// src/core/config/config-errors.ts
|
|
855
|
+
var InvalidExplicitConfigError = class extends Error {
|
|
856
|
+
constructor(message, sourceError) {
|
|
857
|
+
super(message);
|
|
858
|
+
this.sourceError = sourceError;
|
|
859
|
+
this.name = "InvalidExplicitConfigError";
|
|
860
|
+
}
|
|
861
|
+
sourceError;
|
|
862
|
+
code = "BUILD_INVALID_EXPLICIT_CONFIG";
|
|
863
|
+
};
|
|
864
|
+
var InvalidConfigContentError = class extends InvalidExplicitConfigError {
|
|
865
|
+
};
|
|
866
|
+
function isInvalidExplicitConfigError(error) {
|
|
867
|
+
return error instanceof InvalidExplicitConfigError || error instanceof Error && error.code === "BUILD_INVALID_EXPLICIT_CONFIG";
|
|
868
|
+
}
|
|
869
|
+
function isConfigValidityError(error) {
|
|
870
|
+
if (isInvalidExplicitConfigError(error)) return true;
|
|
871
|
+
return error instanceof Error && error.code === "BUILD_CONFIG_READ_INVALID";
|
|
872
|
+
}
|
|
873
|
+
function rethrowConfigValidityError(error) {
|
|
874
|
+
if (isConfigValidityError(error)) throw error;
|
|
875
|
+
}
|
|
876
|
+
|
|
877
|
+
// src/core/config/embedded-provider-catalog.ts
|
|
878
|
+
import { createHash as createHash4 } from "crypto";
|
|
879
|
+
import { existsSync as existsSync4, readFileSync as readFileSync6 } from "fs";
|
|
880
|
+
import { resolve as resolve2 } from "path";
|
|
881
|
+
import { fileURLToPath } from "url";
|
|
882
|
+
var __filename = fileURLToPath(import.meta.url);
|
|
883
|
+
var PACKAGED_CATALOG_BASENAME = "catalog.json";
|
|
884
|
+
function getEmbeddedProviderConfigPaths() {
|
|
885
|
+
const packageRoot = findBuildPackageRoot(__filename);
|
|
886
|
+
if (!packageRoot) return [];
|
|
887
|
+
return [
|
|
888
|
+
// A source checkout authors the canonical YAML directly. Prefer it over the
|
|
889
|
+
// ignored generated asset so a stale prebuild output cannot shadow or break
|
|
890
|
+
// local authoring. The YAML path is not published in the npm package.
|
|
891
|
+
resolve2(packageRoot, ".build-project/config/providers.yaml"),
|
|
892
|
+
// Installed runtimes therefore require the packaged, digest-checked asset.
|
|
893
|
+
resolve2(packageRoot, ".build-project/providers/catalog.json")
|
|
894
|
+
];
|
|
895
|
+
}
|
|
896
|
+
function isPackagedCatalogPath(embeddedPath) {
|
|
897
|
+
return embeddedPath.endsWith(PACKAGED_CATALOG_BASENAME);
|
|
898
|
+
}
|
|
899
|
+
function resolveSourceBaseDrift(embeddedPath, bytes) {
|
|
900
|
+
if (isPackagedCatalogPath(embeddedPath)) return void 0;
|
|
901
|
+
const actualDigest = createHash4("sha256").update(bytes).digest("hex");
|
|
902
|
+
if (actualDigest === PROVIDER_SOURCE_YAML_SHA256) return void 0;
|
|
903
|
+
return { path: embeddedPath, expectedDigest: PROVIDER_SOURCE_YAML_SHA256, actualDigest };
|
|
904
|
+
}
|
|
905
|
+
function detectSourceBaseDrift() {
|
|
906
|
+
for (const embeddedPath of getEmbeddedProviderConfigPaths()) {
|
|
907
|
+
if (!existsSync4(embeddedPath)) continue;
|
|
908
|
+
try {
|
|
909
|
+
return resolveSourceBaseDrift(embeddedPath, readFileSync6(embeddedPath));
|
|
910
|
+
} catch {
|
|
911
|
+
return void 0;
|
|
912
|
+
}
|
|
913
|
+
}
|
|
914
|
+
return void 0;
|
|
915
|
+
}
|
|
916
|
+
|
|
917
|
+
// src/core/config/model-selector-normalization.ts
|
|
918
|
+
function normalizeModelSelectorForComparison(value) {
|
|
919
|
+
return value.trim().toLowerCase().replace(/\[[^\]]*\]\s*$/, "").trim();
|
|
920
|
+
}
|
|
921
|
+
|
|
922
|
+
// src/core/config/offered-models.ts
|
|
923
|
+
var PSEUDO_MODEL_IDS = /* @__PURE__ */ new Set(["auto"]);
|
|
924
|
+
function isOfferedModel(models, modelId) {
|
|
925
|
+
if (!models.observed_ids) return true;
|
|
926
|
+
return models.observed_ids.includes(modelId) || PSEUDO_MODEL_IDS.has(modelId) || (models.family_aliases ?? []).includes(modelId);
|
|
927
|
+
}
|
|
928
|
+
function offeredModelRows(models) {
|
|
929
|
+
return models.available.filter((row) => isOfferedModel(models, row.id));
|
|
930
|
+
}
|
|
931
|
+
function offeredModelIds(models) {
|
|
932
|
+
return offeredModelRows(models).map((row) => row.id);
|
|
933
|
+
}
|
|
934
|
+
var warnedUnobservedModels = /* @__PURE__ */ new Set();
|
|
935
|
+
function warnIfModelUnobserved(providerId, models, modelId) {
|
|
936
|
+
if (isOfferedModel(models, modelId)) return;
|
|
937
|
+
const key = `${providerId}:${modelId}`;
|
|
938
|
+
if (warnedUnobservedModels.has(key)) return;
|
|
939
|
+
warnedUnobservedModels.add(key);
|
|
940
|
+
emitWarning(
|
|
941
|
+
"CFG-001",
|
|
942
|
+
{ taskId: "provider-registry", subsystem: "config", executionPhase: "setup" },
|
|
943
|
+
{
|
|
944
|
+
severity: "WARN" /* WARN */,
|
|
945
|
+
message: `Model '${modelId}' is not in the ${providerId} CLI's observed model list; running it as requested.`,
|
|
946
|
+
metadata: { providerId, modelId, operation: "resolveModel" }
|
|
947
|
+
}
|
|
948
|
+
);
|
|
949
|
+
}
|
|
950
|
+
|
|
951
|
+
// src/core/config/project-trust.ts
|
|
952
|
+
import { realpathSync as realpathSync2 } from "fs";
|
|
953
|
+
import { isAbsolute, resolve as resolve3 } from "path";
|
|
954
|
+
var PROJECT_EXECUTION_TRUST_ENV = "BUILD_TRUST_PROJECT_PROVIDER_TEMPLATES";
|
|
955
|
+
function isTrustedProjectRoot(projectRoot) {
|
|
956
|
+
const projectTrustValue = String(process.env[PROJECT_EXECUTION_TRUST_ENV] ?? "").trim();
|
|
957
|
+
if (!projectTrustValue || !isAbsolute(projectTrustValue)) return false;
|
|
958
|
+
try {
|
|
959
|
+
return realpathSync2(resolve3(projectTrustValue)) === realpathSync2(projectRoot);
|
|
960
|
+
} catch {
|
|
961
|
+
return false;
|
|
962
|
+
}
|
|
963
|
+
}
|
|
964
|
+
function formatProjectTrustInstruction(projectRoot) {
|
|
965
|
+
let canonical = projectRoot;
|
|
966
|
+
try {
|
|
967
|
+
canonical = realpathSync2(projectRoot);
|
|
968
|
+
} catch {
|
|
969
|
+
}
|
|
970
|
+
return ` export ${PROJECT_EXECUTION_TRUST_ENV}=${JSON.stringify(canonical)}`;
|
|
971
|
+
}
|
|
972
|
+
|
|
973
|
+
// src/core/config/provider-enable-switches.ts
|
|
974
|
+
import { readFileSync as readFileSync7 } from "fs";
|
|
975
|
+
import { join as join2 } from "path";
|
|
976
|
+
import { parse as parseJsonc } from "jsonc-parser";
|
|
977
|
+
var DISABLED_VALUES = /* @__PURE__ */ new Set(["0", "false", "no", "off"]);
|
|
978
|
+
var ENABLED_VALUES = /* @__PURE__ */ new Set(["1", "true", "yes", "on"]);
|
|
979
|
+
var disabledBy = /* @__PURE__ */ new WeakMap();
|
|
980
|
+
function envFlagName(providerId) {
|
|
981
|
+
return `BUILD_${providerId.toUpperCase().replace(/[^A-Z0-9]/g, "_")}_ENABLED`;
|
|
982
|
+
}
|
|
983
|
+
function layerConfigFiles(projectRoot) {
|
|
984
|
+
return [join2(projectRoot, ".build-project", "config", "build.config.jsonc"), getUserConfigFile()];
|
|
985
|
+
}
|
|
986
|
+
function runtimeEnv() {
|
|
987
|
+
return { ...process.env, ...getExecutionContext().envOverrides };
|
|
988
|
+
}
|
|
989
|
+
function enableSwitchCacheKey(projectRoot) {
|
|
990
|
+
return fingerprintFiles(layerConfigFiles(projectRoot).flatMap(configCandidates));
|
|
991
|
+
}
|
|
992
|
+
function configCandidates(configFile) {
|
|
993
|
+
const base = configFile.replace(/\.jsonc$/i, "");
|
|
994
|
+
return [`${base}.jsonc`, `${base}.json`];
|
|
995
|
+
}
|
|
996
|
+
function readLayerProviders(configFile) {
|
|
997
|
+
for (const candidate of configCandidates(configFile)) {
|
|
998
|
+
let source;
|
|
999
|
+
try {
|
|
1000
|
+
source = readFileSync7(candidate, "utf8");
|
|
1001
|
+
} catch (error) {
|
|
1002
|
+
if (getErrorCode(error) === "ENOENT") continue;
|
|
1003
|
+
return void 0;
|
|
1004
|
+
}
|
|
1005
|
+
const errors = [];
|
|
1006
|
+
const parsed = parseJsonc(source, errors, {
|
|
1007
|
+
allowTrailingComma: true,
|
|
1008
|
+
allowEmptyContent: false,
|
|
1009
|
+
disallowComments: false
|
|
1010
|
+
});
|
|
1011
|
+
if (errors.length > 0) return void 0;
|
|
1012
|
+
const providers = isObject(parsed) && isObject(parsed.providers) ? parsed.providers : {};
|
|
1013
|
+
return { path: candidate, providers };
|
|
1014
|
+
}
|
|
1015
|
+
return void 0;
|
|
1016
|
+
}
|
|
1017
|
+
function applyProviderEnableSwitches(registry, projectRoot, env = runtimeEnv()) {
|
|
1018
|
+
const layers = layerConfigFiles(projectRoot).map(readLayerProviders);
|
|
1019
|
+
const reasons = /* @__PURE__ */ new Map();
|
|
1020
|
+
for (const [providerId, config] of Object.entries(registry.providers)) {
|
|
1021
|
+
if (!config.enabled) continue;
|
|
1022
|
+
const envName = envFlagName(providerId);
|
|
1023
|
+
const envValue = getEnvVarEntry(envName) ? env[envName]?.trim().toLowerCase() : void 0;
|
|
1024
|
+
if (envValue && DISABLED_VALUES.has(envValue)) {
|
|
1025
|
+
reasons.set(providerId, `${envName}=${env[envName]}`);
|
|
1026
|
+
continue;
|
|
1027
|
+
}
|
|
1028
|
+
if (envValue && ENABLED_VALUES.has(envValue)) continue;
|
|
1029
|
+
for (const layer of layers) {
|
|
1030
|
+
const entry = layer?.providers[providerId];
|
|
1031
|
+
const enabled = isObject(entry) ? entry.enabled : void 0;
|
|
1032
|
+
if (typeof enabled !== "boolean") continue;
|
|
1033
|
+
if (enabled === false) {
|
|
1034
|
+
reasons.set(providerId, `providers.${providerId}.enabled: false in ${layer?.path}`);
|
|
1035
|
+
}
|
|
1036
|
+
break;
|
|
1037
|
+
}
|
|
1038
|
+
}
|
|
1039
|
+
if (reasons.size === 0) return registry;
|
|
1040
|
+
const providers = { ...registry.providers };
|
|
1041
|
+
for (const providerId of reasons.keys()) {
|
|
1042
|
+
providers[providerId] = { ...providers[providerId], enabled: false };
|
|
1043
|
+
}
|
|
1044
|
+
const result = { ...registry, providers };
|
|
1045
|
+
disabledBy.set(result, reasons);
|
|
1046
|
+
return result;
|
|
1047
|
+
}
|
|
1048
|
+
function providerDisableSwitch(registry, providerId) {
|
|
1049
|
+
return disabledBy.get(registry)?.get(providerId);
|
|
1050
|
+
}
|
|
1051
|
+
function disabledBySuffix(registry, providerId) {
|
|
1052
|
+
const source = providerDisableSwitch(registry, providerId);
|
|
1053
|
+
return source ? ` (disabled by ${source})` : "";
|
|
1054
|
+
}
|
|
1055
|
+
|
|
1056
|
+
// src/core/config/provider-pricing-schema.ts
|
|
1057
|
+
import { z as z2 } from "zod";
|
|
1058
|
+
var DateLikeStringSchema = z2.union([z2.string(), z2.date()]).transform((value) => value instanceof Date ? value.toISOString() : value);
|
|
1059
|
+
var PriceNumberSchema = z2.union([z2.number(), z2.string()]).transform((value) => typeof value === "string" ? Number(value) : value).pipe(z2.number().min(0)).optional();
|
|
1060
|
+
var ModelPricingSchema = z2.object({
|
|
1061
|
+
input_per_1m_tokens: PriceNumberSchema,
|
|
1062
|
+
output_per_1m_tokens: PriceNumberSchema,
|
|
1063
|
+
cache_read_per_1m_tokens: PriceNumberSchema,
|
|
1064
|
+
cache_write_per_1m_tokens: PriceNumberSchema,
|
|
1065
|
+
/** Rate for cache writes held for the longer duration (Anthropic's 1-hour write). */
|
|
1066
|
+
cache_write_1h_per_1m_tokens: PriceNumberSchema,
|
|
1067
|
+
input_per_1k_tokens: PriceNumberSchema,
|
|
1068
|
+
output_per_1k_tokens: PriceNumberSchema,
|
|
1069
|
+
base_rate_per_1k_tokens: PriceNumberSchema,
|
|
1070
|
+
premium_multiplier: PriceNumberSchema,
|
|
1071
|
+
context_window: z2.number().int().optional(),
|
|
1072
|
+
long_context_pricing: LongContextPricingSchema.optional(),
|
|
1073
|
+
/** Per speed-tier rate sets keyed by tier name (e.g. `fast`). */
|
|
1074
|
+
speed_tiers: z2.record(z2.string(), SpeedTierPricingSchema).optional(),
|
|
1075
|
+
features: z2.record(z2.string(), z2.boolean()).optional(),
|
|
1076
|
+
// Telemetry-only placeholder: pricing is intentionally absent and
|
|
1077
|
+
// missing-pricing telemetry errors log at debug instead of warn.
|
|
1078
|
+
non_metered: z2.boolean().optional(),
|
|
1079
|
+
/** How the row is billed (e.g. `api_list_price`, `included_plan`); decides metered vs provider billing. */
|
|
1080
|
+
billing_source: z2.string().optional(),
|
|
1081
|
+
/** Maker reference the rates come from (e.g. `anthropic_docs`) or the refresh source label. */
|
|
1082
|
+
pricing_source: z2.string().optional(),
|
|
1083
|
+
pricing_confidence: z2.enum(["high", "medium", "low"]).optional(),
|
|
1084
|
+
/** Why the model has no price and must never be priced from another model's rates. */
|
|
1085
|
+
unpriced_reason: z2.string().optional(),
|
|
1086
|
+
notes: z2.string().optional(),
|
|
1087
|
+
last_updated: DateLikeStringSchema.optional(),
|
|
1088
|
+
_meta: z2.record(z2.string(), z2.unknown()).optional()
|
|
1089
|
+
}).strict();
|
|
1090
|
+
var ToolPricingSchema = z2.object({
|
|
1091
|
+
cost_per_request: z2.number().min(0).optional(),
|
|
1092
|
+
cost_per_read_1m_tokens: z2.number().min(0).optional(),
|
|
1093
|
+
cost_per_write_1m_tokens: z2.number().min(0).optional(),
|
|
1094
|
+
unit: z2.string().optional(),
|
|
1095
|
+
notes: z2.string().optional(),
|
|
1096
|
+
available_in: z2.array(z2.string()).optional()
|
|
1097
|
+
}).strict();
|
|
1098
|
+
var SubscriptionPricingSchema = z2.object({
|
|
1099
|
+
monthly_cost: z2.number().min(0).optional(),
|
|
1100
|
+
included_credits: z2.number().min(0).optional(),
|
|
1101
|
+
overage_rate_per_credit: z2.number().min(0).optional(),
|
|
1102
|
+
individual_monthly: z2.number().min(0).optional(),
|
|
1103
|
+
business_monthly_per_user: z2.number().min(0).optional(),
|
|
1104
|
+
enterprise_monthly_per_user: z2.number().min(0).optional()
|
|
1105
|
+
}).strict();
|
|
1106
|
+
var InfrastructurePricingSchema = z2.object({
|
|
1107
|
+
cloud_execution_per_minute: z2.number().min(0).optional(),
|
|
1108
|
+
premium_execution_per_minute: z2.number().min(0).optional(),
|
|
1109
|
+
proxy_routing_per_request: z2.number().min(0).optional(),
|
|
1110
|
+
notes: z2.string().optional()
|
|
1111
|
+
}).strict();
|
|
1112
|
+
var PricingPassthroughSchema = z2.object({
|
|
1113
|
+
provider: z2.string().trim().min(1),
|
|
1114
|
+
strip_prefixes: z2.array(z2.string()).optional()
|
|
1115
|
+
}).strict();
|
|
1116
|
+
var ProviderPricingSchema = z2.object({
|
|
1117
|
+
billing_mode: z2.enum(["metered", "subscription", "hybrid"]),
|
|
1118
|
+
currency: z2.string(),
|
|
1119
|
+
last_updated: DateLikeStringSchema.optional(),
|
|
1120
|
+
notes: z2.string().optional(),
|
|
1121
|
+
exchange_rate_note: z2.string().optional(),
|
|
1122
|
+
models: z2.record(z2.string(), ModelPricingSchema).optional(),
|
|
1123
|
+
tools: z2.record(z2.string(), ToolPricingSchema).optional(),
|
|
1124
|
+
subscription: SubscriptionPricingSchema.optional(),
|
|
1125
|
+
infrastructure: InfrastructurePricingSchema.optional(),
|
|
1126
|
+
passthrough: PricingPassthroughSchema.optional(),
|
|
1127
|
+
features: z2.record(z2.string(), z2.unknown()).optional(),
|
|
1128
|
+
_meta: z2.record(z2.string(), z2.unknown()).optional()
|
|
1129
|
+
}).strict();
|
|
1130
|
+
|
|
1131
|
+
// src/core/config/provider-registry-reload-invalidators.ts
|
|
1132
|
+
var reloadInvalidators = /* @__PURE__ */ new Set();
|
|
1133
|
+
function registerProviderRegistryReloadInvalidator(invalidator) {
|
|
1134
|
+
reloadInvalidators.add(invalidator);
|
|
1135
|
+
return () => {
|
|
1136
|
+
reloadInvalidators.delete(invalidator);
|
|
1137
|
+
};
|
|
1138
|
+
}
|
|
1139
|
+
function runProviderRegistryReloadInvalidators() {
|
|
1140
|
+
for (const invalidator of reloadInvalidators) {
|
|
1141
|
+
invalidator();
|
|
1142
|
+
}
|
|
1143
|
+
}
|
|
1144
|
+
|
|
1145
|
+
// src/core/config/refresh-overlay-apply.ts
|
|
1146
|
+
function baseModelIds(baseRaw, providerId) {
|
|
1147
|
+
const providers = baseRaw?.providers;
|
|
1148
|
+
const provider = providers?.[providerId];
|
|
1149
|
+
const available = provider?.models?.available;
|
|
1150
|
+
return new Set(
|
|
1151
|
+
(Array.isArray(available) ? available : []).flatMap(
|
|
1152
|
+
(entry) => typeof entry?.id === "string" ? [entry.id] : []
|
|
1153
|
+
)
|
|
1154
|
+
);
|
|
1155
|
+
}
|
|
1156
|
+
function additions(baseRaw, payloads) {
|
|
1157
|
+
return Object.fromEntries(
|
|
1158
|
+
Object.entries(payloads).flatMap(([providerId, payload]) => {
|
|
1159
|
+
const shipped = baseModelIds(baseRaw, providerId);
|
|
1160
|
+
const available = (payload.models?.available ?? []).filter((row) => !shipped.has(row.id));
|
|
1161
|
+
return available.length > 0 ? [[providerId, { models: { available } }]] : [];
|
|
1162
|
+
})
|
|
1163
|
+
);
|
|
1164
|
+
}
|
|
1165
|
+
function catalogAdditions(baseRaw, overlay) {
|
|
1166
|
+
const contexts = Object.fromEntries(
|
|
1167
|
+
Object.entries(overlay.contexts ?? {}).map(([id, payloads]) => [
|
|
1168
|
+
id,
|
|
1169
|
+
additions(baseRaw, payloads)
|
|
1170
|
+
])
|
|
1171
|
+
);
|
|
1172
|
+
return {
|
|
1173
|
+
schemaVersion: overlay.schemaVersion,
|
|
1174
|
+
baseCatalogDigest: overlay.baseCatalogDigest,
|
|
1175
|
+
providers: additions(baseRaw, overlay.providers),
|
|
1176
|
+
...overlay.contexts ? { contexts } : {}
|
|
1177
|
+
};
|
|
1178
|
+
}
|
|
1179
|
+
function applyRefreshOverlay(baseRaw, refreshOverlay, options = {}) {
|
|
1180
|
+
if (!baseRaw || typeof baseRaw !== "object" || Array.isArray(baseRaw)) return baseRaw;
|
|
1181
|
+
const overlay = options.carried ? catalogAdditions(baseRaw, refreshOverlay) : refreshOverlay;
|
|
1182
|
+
const base = structuredClone(baseRaw);
|
|
1183
|
+
const providers = base.providers;
|
|
1184
|
+
if (!providers || typeof providers !== "object" || Array.isArray(providers)) return baseRaw;
|
|
1185
|
+
for (const [providerId, payload] of Object.entries(overlay.providers)) {
|
|
1186
|
+
const provider = providers[providerId];
|
|
1187
|
+
if (!provider || typeof provider !== "object" || Array.isArray(provider)) continue;
|
|
1188
|
+
const providerObject = provider;
|
|
1189
|
+
if (payload.models) {
|
|
1190
|
+
const models = providerObject.models;
|
|
1191
|
+
if (models && typeof models === "object" && !Array.isArray(models)) {
|
|
1192
|
+
const modelObject = models;
|
|
1193
|
+
const current = Array.isArray(modelObject.available) ? modelObject.available : [];
|
|
1194
|
+
const overlayById = new Map(payload.models.available.map((entry) => [entry.id, entry]));
|
|
1195
|
+
const merged = current.map((entry) => {
|
|
1196
|
+
if (!entry || typeof entry !== "object" || Array.isArray(entry)) return entry;
|
|
1197
|
+
const id = entry.id;
|
|
1198
|
+
const updated = typeof id === "string" ? overlayById.get(id) : void 0;
|
|
1199
|
+
if (!updated) return entry;
|
|
1200
|
+
overlayById.delete(id);
|
|
1201
|
+
return { ...entry, ...updated };
|
|
1202
|
+
});
|
|
1203
|
+
modelObject.available = [...merged, ...overlayById.values()];
|
|
1204
|
+
if (payload.models.observedIds) modelObject.observed_ids = payload.models.observedIds;
|
|
1205
|
+
}
|
|
1206
|
+
}
|
|
1207
|
+
if (payload.pricing) {
|
|
1208
|
+
const pricing = providerObject.pricing;
|
|
1209
|
+
if (pricing && typeof pricing === "object" && !Array.isArray(pricing)) {
|
|
1210
|
+
const pricingObject = pricing;
|
|
1211
|
+
const currentModels = pricingObject.models && typeof pricingObject.models === "object" && !Array.isArray(pricingObject.models) ? pricingObject.models : {};
|
|
1212
|
+
pricingObject.models = Object.fromEntries(
|
|
1213
|
+
Object.entries({ ...currentModels, ...payload.pricing.models }).map(([id, row]) => [
|
|
1214
|
+
id,
|
|
1215
|
+
currentModels[id] && typeof currentModels[id] === "object" ? { ...currentModels[id], ...row } : row
|
|
1216
|
+
])
|
|
1217
|
+
);
|
|
1218
|
+
}
|
|
1219
|
+
}
|
|
1220
|
+
}
|
|
1221
|
+
return base;
|
|
1222
|
+
}
|
|
1223
|
+
|
|
1224
|
+
// src/core/config/registry-overlay-settings.ts
|
|
1225
|
+
import { join as join3, resolve as resolve4 } from "path";
|
|
1226
|
+
var warnedOverlayPaths = /* @__PURE__ */ new Set();
|
|
1227
|
+
function asRecord(value) {
|
|
1228
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
1229
|
+
}
|
|
1230
|
+
function providersOf(raw) {
|
|
1231
|
+
return asRecord(asRecord(raw)?.providers) ?? {};
|
|
1232
|
+
}
|
|
1233
|
+
function sameValue(a, b, effort = false) {
|
|
1234
|
+
const normalize = (value) => {
|
|
1235
|
+
if (typeof value !== "string") return value;
|
|
1236
|
+
const trimmed = value.trim();
|
|
1237
|
+
return effort ? normalizeReasoningEffortInput(trimmed) ?? trimmed : trimmed;
|
|
1238
|
+
};
|
|
1239
|
+
return JSON.stringify(normalize(a)) === JSON.stringify(normalize(b));
|
|
1240
|
+
}
|
|
1241
|
+
function roleReplacementKey(providerId, role) {
|
|
1242
|
+
if (role === "judge_primary") return "judge.model";
|
|
1243
|
+
if (role === "fast" || role === "cost") return `defaults.providers.${providerId}.fastModel`;
|
|
1244
|
+
return `defaults.providers.${providerId}.model`;
|
|
1245
|
+
}
|
|
1246
|
+
function listOverlaySettingOverrides(overlayRaw, embeddedRaw) {
|
|
1247
|
+
const embeddedProviders = providersOf(embeddedRaw);
|
|
1248
|
+
const overrides = [];
|
|
1249
|
+
for (const [providerId, overlayValue] of Object.entries(providersOf(overlayRaw))) {
|
|
1250
|
+
const canonical = asRecord(embeddedProviders[providerId]);
|
|
1251
|
+
const overlay = asRecord(overlayValue);
|
|
1252
|
+
if (!canonical || !overlay) continue;
|
|
1253
|
+
const add = (field, replacementKey, ignored = false) => overrides.push({ providerId, field, replacementKey, ignored });
|
|
1254
|
+
const models = asRecord(overlay.models);
|
|
1255
|
+
const canonicalModels = asRecord(canonical.models) ?? {};
|
|
1256
|
+
if (models) {
|
|
1257
|
+
if (models.default !== void 0 && !sameValue(models.default, canonicalModels.default)) {
|
|
1258
|
+
add("models.default", `defaults.providers.${providerId}.model`);
|
|
1259
|
+
}
|
|
1260
|
+
const efforts = [
|
|
1261
|
+
["default_reasoning_effort", `defaults.providers.${providerId}.reasoningEffort`],
|
|
1262
|
+
["judge_reasoning_effort", "judge.reasoningEffort"]
|
|
1263
|
+
];
|
|
1264
|
+
for (const [field, replacementKey] of efforts) {
|
|
1265
|
+
if (models[field] !== void 0 && !sameValue(models[field], canonicalModels[field], true)) {
|
|
1266
|
+
add(`models.${field}`, replacementKey);
|
|
1267
|
+
}
|
|
1268
|
+
}
|
|
1269
|
+
const canonicalRoles = asRecord(canonicalModels.roles) ?? {};
|
|
1270
|
+
for (const [role, value] of Object.entries(asRecord(models.roles) ?? {})) {
|
|
1271
|
+
if (!sameValue(value, canonicalRoles[role])) {
|
|
1272
|
+
add(`models.roles.${role}`, roleReplacementKey(providerId, role));
|
|
1273
|
+
}
|
|
1274
|
+
}
|
|
1275
|
+
const canonicalMappings = asRecord(canonicalModels.mappings) ?? {};
|
|
1276
|
+
for (const [name, value] of Object.entries(asRecord(models.mappings) ?? {})) {
|
|
1277
|
+
if (!sameValue(value, canonicalMappings[name])) {
|
|
1278
|
+
add(`models.mappings.${name}`, `providers.${providerId}.aliases.models.${name}`);
|
|
1279
|
+
}
|
|
1280
|
+
}
|
|
1281
|
+
}
|
|
1282
|
+
for (const [taskType, settings] of Object.entries(asRecord(overlay.task_settings) ?? {})) {
|
|
1283
|
+
if (asRecord(settings)?.reasoning_effort !== void 0) {
|
|
1284
|
+
add(
|
|
1285
|
+
`task_settings.${taskType}.reasoning_effort`,
|
|
1286
|
+
`defaults.providers.${providerId}.reasoningEffort`,
|
|
1287
|
+
true
|
|
1288
|
+
);
|
|
1289
|
+
}
|
|
1290
|
+
}
|
|
1291
|
+
}
|
|
1292
|
+
return overrides;
|
|
1293
|
+
}
|
|
1294
|
+
function formatOverlaySettingsWarning(path5, overrides) {
|
|
1295
|
+
const shown = overrides.map(
|
|
1296
|
+
(entry) => `${entry.providerId} ${entry.field} (use ${entry.replacementKey}${entry.ignored ? "; ignored now" : ""})`
|
|
1297
|
+
).join(", ");
|
|
1298
|
+
return `${path5} sets model or effort settings that belong in build.config.jsonc: ${shown}. They still apply this release unless marked ignored; a later release stops reading them from providers.yaml.`;
|
|
1299
|
+
}
|
|
1300
|
+
function isBuildSourceCheckout(projectRoot) {
|
|
1301
|
+
const root = findBuildPackageRoot(join3(projectRoot, "package.json"));
|
|
1302
|
+
return root !== void 0 && resolve4(root) === resolve4(projectRoot);
|
|
1303
|
+
}
|
|
1304
|
+
function warnOverlaySettingsOnce(input) {
|
|
1305
|
+
const dedupeKey = resolve4(input.path);
|
|
1306
|
+
if (warnedOverlayPaths.has(dedupeKey)) return;
|
|
1307
|
+
const overrides = listOverlaySettingOverrides(input.raw, input.embeddedRaw);
|
|
1308
|
+
if (overrides.length === 0) return;
|
|
1309
|
+
if (input.projectRoot !== void 0 && isBuildSourceCheckout(input.projectRoot)) return;
|
|
1310
|
+
warnedOverlayPaths.add(dedupeKey);
|
|
1311
|
+
const applied = new Set(
|
|
1312
|
+
listOverlaySettingOverrides(input.appliedRaw ?? input.raw, input.embeddedRaw).map(
|
|
1313
|
+
(entry) => `${entry.providerId}\0${entry.field}`
|
|
1314
|
+
)
|
|
1315
|
+
);
|
|
1316
|
+
const reported = overrides.map(
|
|
1317
|
+
(entry) => applied.has(`${entry.providerId}\0${entry.field}`) ? entry : { ...entry, ignored: true }
|
|
1318
|
+
);
|
|
1319
|
+
emitWarning(
|
|
1320
|
+
"CFG-001",
|
|
1321
|
+
{ taskId: "provider-registry", subsystem: "config", executionPhase: "setup" },
|
|
1322
|
+
{
|
|
1323
|
+
severity: "WARN" /* WARN */,
|
|
1324
|
+
message: formatOverlaySettingsWarning(input.path, reported),
|
|
1325
|
+
metadata: {
|
|
1326
|
+
operation: "providersYamlOverlaySettings",
|
|
1327
|
+
path: input.path,
|
|
1328
|
+
overrides: reported
|
|
1329
|
+
}
|
|
1330
|
+
}
|
|
1331
|
+
);
|
|
1332
|
+
}
|
|
1333
|
+
|
|
1334
|
+
// src/core/config/registry-project-selection.ts
|
|
1335
|
+
var PROJECT_SELECTION_MODEL_FIELDS = [
|
|
1336
|
+
"default",
|
|
1337
|
+
"default_reasoning_effort",
|
|
1338
|
+
"judge_reasoning_effort",
|
|
1339
|
+
"roles",
|
|
1340
|
+
"mappings"
|
|
1341
|
+
];
|
|
1342
|
+
var PROJECT_SELECTION_PROVIDER_FIELDS = ["enabled", "order"];
|
|
1343
|
+
function pickSelectionModels(modelsValue) {
|
|
1344
|
+
if (!isObject(modelsValue)) return void 0;
|
|
1345
|
+
const models = {};
|
|
1346
|
+
for (const field of PROJECT_SELECTION_MODEL_FIELDS) {
|
|
1347
|
+
if (modelsValue[field] !== void 0) models[field] = modelsValue[field];
|
|
1348
|
+
}
|
|
1349
|
+
return models;
|
|
1350
|
+
}
|
|
1351
|
+
function pickProjectSelectionPolicy(projectedRaw, embeddedRaw) {
|
|
1352
|
+
const embeddedProviders = isObject(embeddedRaw) ? embeddedRaw.providers : void 0;
|
|
1353
|
+
const projectedProviders = isObject(projectedRaw) ? projectedRaw.providers : void 0;
|
|
1354
|
+
const picked = {};
|
|
1355
|
+
if (!isObject(embeddedProviders) || !isObject(projectedProviders)) return { providers: picked };
|
|
1356
|
+
for (const [providerId, value] of Object.entries(projectedProviders)) {
|
|
1357
|
+
if (!(providerId in embeddedProviders) || !isObject(value)) continue;
|
|
1358
|
+
const provider = {};
|
|
1359
|
+
for (const field of PROJECT_SELECTION_PROVIDER_FIELDS) {
|
|
1360
|
+
if (value[field] !== void 0) provider[field] = value[field];
|
|
1361
|
+
}
|
|
1362
|
+
const models = pickSelectionModels(value.models);
|
|
1363
|
+
if (models) provider.models = models;
|
|
1364
|
+
picked[providerId] = provider;
|
|
1365
|
+
}
|
|
1366
|
+
return { providers: picked };
|
|
1367
|
+
}
|
|
1368
|
+
|
|
1369
|
+
// src/core/config/user-model-entries.ts
|
|
1370
|
+
var MAX_REPORTED_ISSUES = 3;
|
|
1371
|
+
function isRecord(value) {
|
|
1372
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
1373
|
+
}
|
|
1374
|
+
function mergeUserModelEntries(userRaw, baseRaw, options) {
|
|
1375
|
+
const ignored = [];
|
|
1376
|
+
if (!isRecord(userRaw) || !isRecord(baseRaw)) return { overlay: userRaw, ignored };
|
|
1377
|
+
const overlay = structuredClone(userRaw);
|
|
1378
|
+
const userProviders = overlay.providers;
|
|
1379
|
+
if (!isRecord(userProviders)) return { overlay, ignored };
|
|
1380
|
+
const baseProviders = isRecord(baseRaw.providers) ? baseRaw.providers : {};
|
|
1381
|
+
for (const [providerId, provider] of Object.entries(userProviders)) {
|
|
1382
|
+
if (!isRecord(provider) || !isRecord(provider.models)) continue;
|
|
1383
|
+
const userAvailable = provider.models.available;
|
|
1384
|
+
if (!Array.isArray(userAvailable)) continue;
|
|
1385
|
+
const baseProvider = baseProviders[providerId];
|
|
1386
|
+
let baseAvailable = [];
|
|
1387
|
+
if (isRecord(baseProvider)) {
|
|
1388
|
+
if (!isRecord(baseProvider.models)) continue;
|
|
1389
|
+
const declared = baseProvider.models.available;
|
|
1390
|
+
if (!Array.isArray(declared)) continue;
|
|
1391
|
+
baseAvailable = declared;
|
|
1392
|
+
}
|
|
1393
|
+
const availableById = /* @__PURE__ */ new Map();
|
|
1394
|
+
for (const entry of baseAvailable) {
|
|
1395
|
+
const key = isRecord(entry) && typeof entry.id === "string" ? entry.id : /* @__PURE__ */ Symbol("entry");
|
|
1396
|
+
availableById.set(key, entry);
|
|
1397
|
+
}
|
|
1398
|
+
userAvailable.forEach((entry, index) => {
|
|
1399
|
+
const id = isRecord(entry) && typeof entry.id === "string" ? entry.id : void 0;
|
|
1400
|
+
if (!isRecord(entry) || id === void 0 || id.trim() === "") {
|
|
1401
|
+
ignored.push({
|
|
1402
|
+
providerId,
|
|
1403
|
+
...id?.trim() ? { modelId: id } : {},
|
|
1404
|
+
index,
|
|
1405
|
+
issues: ["the entry has no id"],
|
|
1406
|
+
previousKept: false,
|
|
1407
|
+
sourcePath: options.sourcePath
|
|
1408
|
+
});
|
|
1409
|
+
return;
|
|
1410
|
+
}
|
|
1411
|
+
const previous = availableById.get(id);
|
|
1412
|
+
const candidate = isRecord(previous) ? mergeModelEntry(previous, entry) : entry;
|
|
1413
|
+
const issues = options.validateEntry(candidate);
|
|
1414
|
+
if (issues.length > 0) {
|
|
1415
|
+
ignored.push({
|
|
1416
|
+
providerId,
|
|
1417
|
+
modelId: id,
|
|
1418
|
+
index,
|
|
1419
|
+
issues,
|
|
1420
|
+
previousKept: previous !== void 0,
|
|
1421
|
+
sourcePath: options.sourcePath
|
|
1422
|
+
});
|
|
1423
|
+
return;
|
|
1424
|
+
}
|
|
1425
|
+
availableById.set(id, candidate);
|
|
1426
|
+
});
|
|
1427
|
+
provider.models.available = [...availableById.values()];
|
|
1428
|
+
}
|
|
1429
|
+
return { overlay, ignored };
|
|
1430
|
+
}
|
|
1431
|
+
function describeIgnoredUserModelEntry(entry) {
|
|
1432
|
+
const subject = entry.modelId !== void 0 ? `model entry "${entry.modelId}"` : `model entry ${entry.index + 1}`;
|
|
1433
|
+
const shown = entry.issues.slice(0, MAX_REPORTED_ISSUES).join("; ");
|
|
1434
|
+
const more = entry.issues.length > MAX_REPORTED_ISSUES ? ` (and ${entry.issues.length - MAX_REPORTED_ISSUES} more)` : "";
|
|
1435
|
+
const outcome = entry.previousKept ? "The previous entry for this model is kept." : "The entry was left out of the model inventory.";
|
|
1436
|
+
return `Ignored invalid ${subject} for provider "${entry.providerId}" in ${entry.sourcePath}: ${shown}${more}. ${outcome}`;
|
|
1437
|
+
}
|
|
1438
|
+
|
|
1439
|
+
// src/core/config/provider-registry.ts
|
|
1440
|
+
function getUserProviderRegistryPaths(cwd = process.cwd()) {
|
|
1441
|
+
let home = "";
|
|
1442
|
+
try {
|
|
1443
|
+
home = homedir3() ?? "";
|
|
1444
|
+
} catch {
|
|
1445
|
+
home = "";
|
|
1446
|
+
}
|
|
1447
|
+
if (!home) home = (process.env.HOME ?? process.env.USERPROFILE ?? "").trim();
|
|
1448
|
+
const canonicalUserDir = getConfigPaths(cwd).userConfigDir;
|
|
1449
|
+
const defaultUserDir = home ? join4(home, ".build", "config") : "";
|
|
1450
|
+
return [
|
|
1451
|
+
join4(canonicalUserDir, "providers.yaml"),
|
|
1452
|
+
// ~/.config/build is the pre-default (XDG) registry location, kept as a
|
|
1453
|
+
// compatibility fallback for the default layout only. An explicit
|
|
1454
|
+
// BUILD_CONFIG_DIR/XDG root is authoritative and must not be contaminated
|
|
1455
|
+
// by state from another user-config tree.
|
|
1456
|
+
...home && resolve5(canonicalUserDir) === resolve5(defaultUserDir) ? [join4(home, ".config", "build", "providers.yaml")] : []
|
|
1457
|
+
];
|
|
1458
|
+
}
|
|
1459
|
+
function getConfiguredProviderRegistryPaths(cwd = process.cwd()) {
|
|
1460
|
+
const projectRoot = findProjectRoot(cwd) ?? cwd;
|
|
1461
|
+
return [
|
|
1462
|
+
...getUserProviderRegistryPaths(projectRoot),
|
|
1463
|
+
resolveProvidersConfigPath({ cwd: projectRoot }),
|
|
1464
|
+
resolve5(projectRoot, ".build-project", "config", "provider-registry.yaml.v1.backup")
|
|
1465
|
+
];
|
|
1466
|
+
}
|
|
1467
|
+
function getProviderRegistryInputPaths(cwd = process.cwd()) {
|
|
1468
|
+
const projectRoot = findProjectRoot(cwd) ?? cwd;
|
|
1469
|
+
return [
|
|
1470
|
+
...getEmbeddedProviderConfigPaths(),
|
|
1471
|
+
resolveSharedRefreshPaths().overlayPath,
|
|
1472
|
+
resolve5(projectRoot, ".build-project", "cache", "model-update", "refresh-overlay.json"),
|
|
1473
|
+
...getConfiguredProviderRegistryPaths(projectRoot)
|
|
1474
|
+
];
|
|
1475
|
+
}
|
|
1476
|
+
var REMOVED_BUILTIN_PROVIDER_IDS = /* @__PURE__ */ new Set(["glm"]);
|
|
1477
|
+
var PROJECT_POLICY_PROVIDER_FIELDS = [
|
|
1478
|
+
"enabled",
|
|
1479
|
+
"order",
|
|
1480
|
+
"concurrency_hint",
|
|
1481
|
+
"concurrency",
|
|
1482
|
+
"timeout_ms",
|
|
1483
|
+
"health_check_timeout_ms",
|
|
1484
|
+
"memory",
|
|
1485
|
+
"env",
|
|
1486
|
+
"retry",
|
|
1487
|
+
"circuit_breaker",
|
|
1488
|
+
"rate_limits",
|
|
1489
|
+
"workspace_edits",
|
|
1490
|
+
"generation",
|
|
1491
|
+
"task_settings",
|
|
1492
|
+
"options"
|
|
1493
|
+
];
|
|
1494
|
+
var PROJECT_TRUSTED_EXTENSION_FIELDS = [
|
|
1495
|
+
"transport",
|
|
1496
|
+
"api",
|
|
1497
|
+
"auth",
|
|
1498
|
+
"cli",
|
|
1499
|
+
"exec",
|
|
1500
|
+
"engine",
|
|
1501
|
+
"route_id",
|
|
1502
|
+
"route",
|
|
1503
|
+
"allow_unsafe_binary",
|
|
1504
|
+
"requires",
|
|
1505
|
+
"requires_if"
|
|
1506
|
+
];
|
|
1507
|
+
var EXECUTION_SENSITIVE_PROVIDER_FIELDS = ["cli", "exec", "engine"];
|
|
1508
|
+
var CURSOR_ID_SYNTAX_ADMISSION_PATTERN = "^[a-z0-9][a-z0-9._-]{0,63}$";
|
|
1509
|
+
function normalizeProviderConfigId(providerId) {
|
|
1510
|
+
const normalized = providerId.trim().toLowerCase();
|
|
1511
|
+
if (normalized === "cursor-cli") return "cursor";
|
|
1512
|
+
if (normalized === "copilot-cli") return "copilot";
|
|
1513
|
+
if (normalized === "anti-gravity" || normalized === "antigravity-cli" || normalized === "agy") {
|
|
1514
|
+
return "antigravity";
|
|
1515
|
+
}
|
|
1516
|
+
return normalized;
|
|
1517
|
+
}
|
|
1518
|
+
function dropRemovedBuiltinProviders(raw) {
|
|
1519
|
+
if (!raw || typeof raw !== "object") return raw;
|
|
1520
|
+
const providers = raw.providers;
|
|
1521
|
+
if (!providers || typeof providers !== "object") return raw;
|
|
1522
|
+
for (const providerId of REMOVED_BUILTIN_PROVIDER_IDS) {
|
|
1523
|
+
delete providers[providerId];
|
|
1524
|
+
}
|
|
1525
|
+
return raw;
|
|
1526
|
+
}
|
|
1527
|
+
function ensureCursorIdSyntaxAdmissionPattern(raw) {
|
|
1528
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return raw;
|
|
1529
|
+
const providers = raw.providers;
|
|
1530
|
+
if (!providers || typeof providers !== "object" || Array.isArray(providers)) return raw;
|
|
1531
|
+
const cursor = providers.cursor;
|
|
1532
|
+
if (!cursor || typeof cursor !== "object" || Array.isArray(cursor)) return raw;
|
|
1533
|
+
const models = cursor.models;
|
|
1534
|
+
if (!models || typeof models !== "object" || Array.isArray(models)) return raw;
|
|
1535
|
+
const patterns = models.allowed_patterns;
|
|
1536
|
+
if (!Array.isArray(patterns)) return raw;
|
|
1537
|
+
if (!patterns.every((pattern) => typeof pattern === "string")) return raw;
|
|
1538
|
+
if (patterns.includes(CURSOR_ID_SYNTAX_ADMISSION_PATTERN)) return raw;
|
|
1539
|
+
models.allowed_patterns = [
|
|
1540
|
+
...patterns,
|
|
1541
|
+
CURSOR_ID_SYNTAX_ADMISSION_PATTERN
|
|
1542
|
+
];
|
|
1543
|
+
return raw;
|
|
1544
|
+
}
|
|
1545
|
+
function projectProjectRegistryPolicy(projectRaw, embeddedRaw, options) {
|
|
1546
|
+
if (!projectRaw || typeof projectRaw !== "object" || Array.isArray(projectRaw)) {
|
|
1547
|
+
return projectRaw;
|
|
1548
|
+
}
|
|
1549
|
+
const embeddedProvidersValue = embeddedRaw && typeof embeddedRaw === "object" && !Array.isArray(embeddedRaw) ? embeddedRaw.providers : null;
|
|
1550
|
+
if (!embeddedProvidersValue || typeof embeddedProvidersValue !== "object" || Array.isArray(embeddedProvidersValue)) {
|
|
1551
|
+
return projectRaw;
|
|
1552
|
+
}
|
|
1553
|
+
const projectProvidersValue = projectRaw.providers;
|
|
1554
|
+
if (!projectProvidersValue || typeof projectProvidersValue !== "object" || Array.isArray(projectProvidersValue)) {
|
|
1555
|
+
return projectRaw;
|
|
1556
|
+
}
|
|
1557
|
+
const embeddedProviders = embeddedProvidersValue;
|
|
1558
|
+
const projectedProviders = {};
|
|
1559
|
+
for (const [providerId, providerValue] of Object.entries(
|
|
1560
|
+
projectProvidersValue
|
|
1561
|
+
)) {
|
|
1562
|
+
if (!(providerId in embeddedProviders)) {
|
|
1563
|
+
projectedProviders[providerId] = providerValue;
|
|
1564
|
+
continue;
|
|
1565
|
+
}
|
|
1566
|
+
if (!providerValue || typeof providerValue !== "object" || Array.isArray(providerValue)) {
|
|
1567
|
+
projectedProviders[providerId] = providerValue;
|
|
1568
|
+
continue;
|
|
1569
|
+
}
|
|
1570
|
+
const sourceProvider = providerValue;
|
|
1571
|
+
const provider = {};
|
|
1572
|
+
for (const field of PROJECT_POLICY_PROVIDER_FIELDS) {
|
|
1573
|
+
if (sourceProvider[field] !== void 0) provider[field] = sourceProvider[field];
|
|
1574
|
+
}
|
|
1575
|
+
if (options.trusted) {
|
|
1576
|
+
for (const field of PROJECT_TRUSTED_EXTENSION_FIELDS) {
|
|
1577
|
+
if (sourceProvider[field] !== void 0) provider[field] = sourceProvider[field];
|
|
1578
|
+
}
|
|
1579
|
+
} else if (sourceProvider.api && typeof sourceProvider.api === "object" && !Array.isArray(sourceProvider.api)) {
|
|
1580
|
+
const sourceApi = sourceProvider.api;
|
|
1581
|
+
const api = {};
|
|
1582
|
+
for (const field of [
|
|
1583
|
+
"stream",
|
|
1584
|
+
"max_tokens",
|
|
1585
|
+
"max_tool_iterations",
|
|
1586
|
+
"per_tool_timeout_ms"
|
|
1587
|
+
]) {
|
|
1588
|
+
if (sourceApi[field] !== void 0) api[field] = sourceApi[field];
|
|
1589
|
+
}
|
|
1590
|
+
if (Object.keys(api).length > 0) provider.api = api;
|
|
1591
|
+
}
|
|
1592
|
+
const models = pickSelectionModels(sourceProvider.models);
|
|
1593
|
+
if (models) provider.models = models;
|
|
1594
|
+
projectedProviders[providerId] = provider;
|
|
1595
|
+
}
|
|
1596
|
+
return {
|
|
1597
|
+
providers: projectedProviders
|
|
1598
|
+
};
|
|
1599
|
+
}
|
|
1600
|
+
var RetryConfigSchema = z3.object({
|
|
1601
|
+
max_attempts: z3.number().int().min(1).max(10),
|
|
1602
|
+
initial_delay_ms: z3.number().int().min(0),
|
|
1603
|
+
max_delay_ms: z3.number().int().min(0),
|
|
1604
|
+
backoff_multiplier: z3.number().min(1)
|
|
1605
|
+
}).strict();
|
|
1606
|
+
var CircuitBreakerConfigSchema = z3.object({
|
|
1607
|
+
failure_threshold: z3.number().int().min(1),
|
|
1608
|
+
cooldown_ms: z3.number().int().min(0),
|
|
1609
|
+
half_open_max_attempts: z3.number().int().min(1).optional()
|
|
1610
|
+
}).strict();
|
|
1611
|
+
var RateLimitEntrySchema = z3.object({
|
|
1612
|
+
rpm: z3.number().int().min(1),
|
|
1613
|
+
// Requests per minute
|
|
1614
|
+
bucket_size: z3.number().int().min(1),
|
|
1615
|
+
// Token bucket burst capacity
|
|
1616
|
+
refill_rate: z3.number().min(0)
|
|
1617
|
+
// Tokens per second
|
|
1618
|
+
}).strict();
|
|
1619
|
+
var RateLimitsConfigSchema = z3.object({
|
|
1620
|
+
rpm: z3.number().int().min(1).optional(),
|
|
1621
|
+
// Default RPM (convenience alias)
|
|
1622
|
+
bucket_size: z3.number().int().min(1).optional(),
|
|
1623
|
+
// Default bucket size
|
|
1624
|
+
refill_rate: z3.number().min(0).optional(),
|
|
1625
|
+
// Default refill rate
|
|
1626
|
+
default: RateLimitEntrySchema.optional(),
|
|
1627
|
+
// Explicit default config
|
|
1628
|
+
models: z3.record(z3.string(), RateLimitEntrySchema).optional()
|
|
1629
|
+
// Per-model overrides
|
|
1630
|
+
}).strict();
|
|
1631
|
+
var MemoryConfigSchema = z3.object({
|
|
1632
|
+
warn_threshold: z3.number().min(0).max(1),
|
|
1633
|
+
critical_threshold: z3.number().min(0).max(1),
|
|
1634
|
+
emergency_threshold: z3.number().min(0).max(1),
|
|
1635
|
+
max_processes: z3.number().int().min(1)
|
|
1636
|
+
}).strict();
|
|
1637
|
+
var PollingConfigSchema = z3.object({
|
|
1638
|
+
initial_interval_ms: z3.number().int().min(0),
|
|
1639
|
+
max_interval_ms: z3.number().int().min(0),
|
|
1640
|
+
backoff_multiplier: z3.number().min(1),
|
|
1641
|
+
timeout_ms: z3.number().int().min(0).optional(),
|
|
1642
|
+
show_progress: z3.boolean()
|
|
1643
|
+
}).strict();
|
|
1644
|
+
var CLIConfigSchema = z3.object({
|
|
1645
|
+
command: z3.string(),
|
|
1646
|
+
binary: z3.string(),
|
|
1647
|
+
install_command: z3.string().default(""),
|
|
1648
|
+
// Installation metadata for setup automation
|
|
1649
|
+
// - manual: show instructions only (no command execution)
|
|
1650
|
+
// - curl: requires explicit opt-in via BUILD_ALLOW_CURL_BASH=1
|
|
1651
|
+
install_method: z3.enum(["npm", "brew", "pipx", "curl", "manual"]).optional().default("manual"),
|
|
1652
|
+
min_node_version: z3.string().optional(),
|
|
1653
|
+
risk_level: z3.enum(["safe", "needs-confirmation"]).optional().default("safe"),
|
|
1654
|
+
install_note: z3.string().optional()
|
|
1655
|
+
}).strict();
|
|
1656
|
+
var AuthConfigSchema = z3.object({
|
|
1657
|
+
type: z3.enum(["cli_login", "api_key", "oauth", "cli_wrapper"]),
|
|
1658
|
+
env_vars: z3.array(z3.string()),
|
|
1659
|
+
skip_env_var: z3.string().optional(),
|
|
1660
|
+
note: z3.string().optional()
|
|
1661
|
+
}).strict();
|
|
1662
|
+
var TemplatedAuthConfigSchema = AuthConfigSchema.default({
|
|
1663
|
+
type: "cli_login",
|
|
1664
|
+
env_vars: [],
|
|
1665
|
+
skip_env_var: "BUILD_SKIP_AUTH"
|
|
1666
|
+
});
|
|
1667
|
+
var ProviderReleaseStatusSchema = z3.enum([
|
|
1668
|
+
"primary_validated",
|
|
1669
|
+
"supported_validated",
|
|
1670
|
+
"supported_beta",
|
|
1671
|
+
"experimental"
|
|
1672
|
+
]);
|
|
1673
|
+
var JsonScalarSchema = z3.union([z3.string(), z3.number(), z3.boolean(), z3.null()]);
|
|
1674
|
+
var ProbeExpectationSchema = z3.union([
|
|
1675
|
+
JsonScalarSchema,
|
|
1676
|
+
z3.object({
|
|
1677
|
+
present: z3.boolean().optional(),
|
|
1678
|
+
truthy: z3.boolean().optional(),
|
|
1679
|
+
equals: JsonScalarSchema.optional()
|
|
1680
|
+
}).strict()
|
|
1681
|
+
]);
|
|
1682
|
+
var CommandProbeSchema = z3.object({
|
|
1683
|
+
command_argv: z3.array(z3.string()).min(1),
|
|
1684
|
+
parse_as: z3.enum(["json", "exit_code"]).optional().default("json"),
|
|
1685
|
+
json_path: z3.string().optional(),
|
|
1686
|
+
expect: ProbeExpectationSchema.optional(),
|
|
1687
|
+
timeout_ms: z3.number().int().min(1).optional()
|
|
1688
|
+
}).strict();
|
|
1689
|
+
var ModelsDiscoverySchema = z3.object({
|
|
1690
|
+
command_argv: z3.array(z3.string()).min(1),
|
|
1691
|
+
json_path: z3.string().optional().default("$"),
|
|
1692
|
+
id_path: z3.string().optional().default("id"),
|
|
1693
|
+
ttl_hours: z3.number().positive().optional().default(24),
|
|
1694
|
+
timeout_ms: z3.number().int().min(1).optional()
|
|
1695
|
+
}).strict();
|
|
1696
|
+
var ModelAccessClassSchema = z3.enum(["first_party_pool", "premium_pool"]);
|
|
1697
|
+
var RegistryReasoningEffortSchema = z3.preprocess(
|
|
1698
|
+
(value) => normalizeReasoningEffortInput(value) ?? value,
|
|
1699
|
+
z3.enum(["low", "medium", "high", "xhigh", "max"])
|
|
1700
|
+
);
|
|
1701
|
+
var ModelAccessConfigSchema = z3.object({
|
|
1702
|
+
default: ModelAccessClassSchema,
|
|
1703
|
+
overrides: z3.record(z3.string().trim().min(1), ModelAccessClassSchema).default({})
|
|
1704
|
+
}).strict();
|
|
1705
|
+
var ModelsConfigSchema = z3.object({
|
|
1706
|
+
default: z3.string().trim().min(1),
|
|
1707
|
+
/** Retired: shipped providers.yaml sets none; user or repo copies still apply it. */
|
|
1708
|
+
default_reasoning_effort: RegistryReasoningEffortSchema.optional(),
|
|
1709
|
+
/** Effort for the judge_primary role; judges without it get no Build effort. */
|
|
1710
|
+
judge_reasoning_effort: RegistryReasoningEffortSchema.optional(),
|
|
1711
|
+
roles: z3.record(z3.string().trim().min(1), z3.string().trim().min(1)).optional().default({}),
|
|
1712
|
+
allowed_patterns: z3.array(z3.string()),
|
|
1713
|
+
mappings: z3.record(z3.string().trim().min(1), z3.string().trim().min(1)),
|
|
1714
|
+
// Zod v4: explicit key and value schemas
|
|
1715
|
+
/** Selectors the provider's own CLI resolves; see model-family-aliases.ts. */
|
|
1716
|
+
family_aliases: z3.array(z3.string().trim().min(1)).optional().default([]),
|
|
1717
|
+
/** Per backend, what a model with no route sends; see model-routes.ts. */
|
|
1718
|
+
route_backends: RouteBackendModesSchema.optional(),
|
|
1719
|
+
available: z3.array(ModelInfoSchema),
|
|
1720
|
+
/** Ids the CLI reported on its last observed inventory; set only by a refresh overlay. */
|
|
1721
|
+
observed_ids: z3.array(z3.string()).optional(),
|
|
1722
|
+
/**
|
|
1723
|
+
* Admission policy for the exact-model invoke bridge.
|
|
1724
|
+
*
|
|
1725
|
+
* A provider whose `allowed_patterns` deliberately admit bounded future model-id
|
|
1726
|
+
* SYNTAX (so a newly released id works before the catalog is refreshed) accepts ids
|
|
1727
|
+
* that are well-formed but not in `available`. That is correct for ordinary
|
|
1728
|
+
* execution and wrong for an exact pin, where a typo should be rejected before
|
|
1729
|
+
* spawn rather than handed to the CLI.
|
|
1730
|
+
*
|
|
1731
|
+
* Set this on such a provider to make the exact bridge additionally require the
|
|
1732
|
+
* resolved id to be present in the effective inventory. Providers that do not admit
|
|
1733
|
+
* syntax-only ids leave it false and keep their declared resolution contract.
|
|
1734
|
+
*
|
|
1735
|
+
* This is model-resolution admission policy, NOT a runtime CLI quirk, so it belongs
|
|
1736
|
+
* here rather than behind `getProviderRuntimeQuirks()`.
|
|
1737
|
+
*/
|
|
1738
|
+
exact_invoke_requires_inventory: z3.boolean().optional().default(false),
|
|
1739
|
+
access: ModelAccessConfigSchema.optional(),
|
|
1740
|
+
discovery: ModelsDiscoverySchema.optional()
|
|
1741
|
+
}).strict().superRefine((models, ctx) => {
|
|
1742
|
+
if (!models.access) return;
|
|
1743
|
+
const availableIds = new Set(models.available.map((model) => model.id));
|
|
1744
|
+
for (const modelId of Object.keys(models.access.overrides)) {
|
|
1745
|
+
if (!availableIds.has(modelId)) {
|
|
1746
|
+
ctx.addIssue({
|
|
1747
|
+
code: z3.ZodIssueCode.custom,
|
|
1748
|
+
message: `models.access override references unavailable model: ${modelId}`,
|
|
1749
|
+
path: ["access", "overrides", modelId]
|
|
1750
|
+
});
|
|
1751
|
+
}
|
|
1752
|
+
}
|
|
1753
|
+
});
|
|
1754
|
+
function declaresFamilyAlias(aliases, model) {
|
|
1755
|
+
if (!model || !aliases || aliases.length === 0) return false;
|
|
1756
|
+
const candidate = normalizeModelSelectorForComparison(model);
|
|
1757
|
+
if (candidate.length === 0) return false;
|
|
1758
|
+
return aliases.some((alias) => normalizeModelSelectorForComparison(alias) === candidate);
|
|
1759
|
+
}
|
|
1760
|
+
var TemplatedModelsConfigSchema = z3.object({
|
|
1761
|
+
default: z3.string().trim().min(1),
|
|
1762
|
+
/** Retired; see `ModelsConfigSchema.default_reasoning_effort`. */
|
|
1763
|
+
default_reasoning_effort: RegistryReasoningEffortSchema.optional(),
|
|
1764
|
+
/** See `ModelsConfigSchema.judge_reasoning_effort`. */
|
|
1765
|
+
judge_reasoning_effort: RegistryReasoningEffortSchema.optional(),
|
|
1766
|
+
roles: z3.record(z3.string().trim().min(1), z3.string().trim().min(1)).optional().default({}),
|
|
1767
|
+
allowed_patterns: z3.array(z3.string()).default([".*"]),
|
|
1768
|
+
mappings: z3.record(z3.string().trim().min(1), z3.string().trim().min(1)).default({}),
|
|
1769
|
+
/**
|
|
1770
|
+
* See `ModelsConfigSchema.family_aliases`. Declared here too so the field is
|
|
1771
|
+
* readable off the `ProviderConfig` union without narrowing to a branch first.
|
|
1772
|
+
*/
|
|
1773
|
+
family_aliases: z3.array(z3.string().trim().min(1)).optional().default([]),
|
|
1774
|
+
/** See `ModelsConfigSchema.route_backends`. */
|
|
1775
|
+
route_backends: RouteBackendModesSchema.optional(),
|
|
1776
|
+
available: z3.array(ModelInfoSchema).default([]),
|
|
1777
|
+
/** See `ModelsConfigSchema.observed_ids`. */
|
|
1778
|
+
observed_ids: z3.array(z3.string()).optional(),
|
|
1779
|
+
/**
|
|
1780
|
+
* See `ModelsConfigSchema.exact_invoke_requires_inventory`. Declared here too so the
|
|
1781
|
+
* flag is readable off the `ProviderConfig` union without narrowing to the native
|
|
1782
|
+
* branch first. It matters at least as much for templated providers, whose
|
|
1783
|
+
* `allowed_patterns` default to `['.*']` and therefore admit any syntax.
|
|
1784
|
+
*/
|
|
1785
|
+
exact_invoke_requires_inventory: z3.boolean().optional().default(false),
|
|
1786
|
+
access: ModelAccessConfigSchema.optional(),
|
|
1787
|
+
discovery: ModelsDiscoverySchema.optional()
|
|
1788
|
+
}).strict().superRefine((models, ctx) => {
|
|
1789
|
+
if (!models.access) return;
|
|
1790
|
+
const availableIds = new Set(models.available.map((model) => model.id));
|
|
1791
|
+
for (const modelId of Object.keys(models.access.overrides)) {
|
|
1792
|
+
if (!availableIds.has(modelId)) {
|
|
1793
|
+
ctx.addIssue({
|
|
1794
|
+
code: z3.ZodIssueCode.custom,
|
|
1795
|
+
message: `models.access override references unavailable model: ${modelId}`,
|
|
1796
|
+
path: ["access", "overrides", modelId]
|
|
1797
|
+
});
|
|
1798
|
+
}
|
|
1799
|
+
}
|
|
1800
|
+
});
|
|
1801
|
+
var CapabilitiesConfigSchema = z3.object({
|
|
1802
|
+
streaming: z3.boolean(),
|
|
1803
|
+
tool_use: z3.boolean(),
|
|
1804
|
+
vision: z3.boolean(),
|
|
1805
|
+
function_calling: z3.boolean(),
|
|
1806
|
+
// Provider has some historically tracked subagent-capable behavior.
|
|
1807
|
+
sub_agents: z3.boolean().optional().default(false),
|
|
1808
|
+
// Build can invoke provider-native subagents for `run --subagents`.
|
|
1809
|
+
provider_native_subagents: z3.boolean().optional().default(false),
|
|
1810
|
+
// Provider-level execution capabilities (narrow matrix — model-level traits are out of scope)
|
|
1811
|
+
// requires_pty: provider CLI needs a PTY for headless runs
|
|
1812
|
+
requires_pty: z3.boolean().optional(),
|
|
1813
|
+
// owns_rate_limit_token: provider enforces its own rate limit / handles 429 internally
|
|
1814
|
+
owns_rate_limit_token: z3.boolean().optional(),
|
|
1815
|
+
// supports_api_judge: provider has a non-CLI API channel usable by the judge/synthesis path
|
|
1816
|
+
supports_api_judge: z3.boolean().optional(),
|
|
1817
|
+
// supports_ask_consult: provider has a tested read-only one-shot consultation path
|
|
1818
|
+
supports_ask_consult: z3.boolean().optional(),
|
|
1819
|
+
// supports_decomposition_tools_profile: adapter implements decomposition-search-only
|
|
1820
|
+
supports_decomposition_tools_profile: z3.boolean().optional(),
|
|
1821
|
+
// requires_sandbox_interlock: provider must verify outer sandbox before spawning
|
|
1822
|
+
requires_sandbox_interlock: z3.boolean().optional(),
|
|
1823
|
+
// native_model_fallback: provider CLI supports a native fallback-model flag
|
|
1824
|
+
// (e.g. Claude's --fallback-model). Gates role-candidate `fallbackModelRole`.
|
|
1825
|
+
native_model_fallback: z3.boolean().optional(),
|
|
1826
|
+
// supports_bounded_edit_allowlist: permissionMode 'dontAsk' plus allowedTools is a
|
|
1827
|
+
// bounded edit allowlist for edit turns (denies unlisted tools instead of failing mid-run).
|
|
1828
|
+
supports_bounded_edit_allowlist: z3.boolean().optional(),
|
|
1829
|
+
// supports_inherited_boundary_read_only: the provider's native read-only posture holds
|
|
1830
|
+
// inside an outer host sandbox Build cannot nest into: it needs no Seatbelt of its own
|
|
1831
|
+
// and exposes no shell tool (or only a read-only shell), so read-only needs no kernel profile.
|
|
1832
|
+
supports_inherited_boundary_read_only: z3.boolean().optional()
|
|
1833
|
+
}).strict();
|
|
1834
|
+
var TemplatedCapabilitiesConfigSchema = z3.object({
|
|
1835
|
+
streaming: z3.boolean().default(false),
|
|
1836
|
+
tool_use: z3.boolean().default(false),
|
|
1837
|
+
vision: z3.boolean().default(false),
|
|
1838
|
+
function_calling: z3.boolean().default(false),
|
|
1839
|
+
// Provider has some historically tracked subagent-capable behavior.
|
|
1840
|
+
sub_agents: z3.boolean().default(false),
|
|
1841
|
+
// Build can invoke provider-native subagents for `run --subagents`.
|
|
1842
|
+
provider_native_subagents: z3.boolean().default(false),
|
|
1843
|
+
// Provider-level execution capabilities (narrow matrix — model-level traits are out of scope)
|
|
1844
|
+
requires_pty: z3.boolean().optional(),
|
|
1845
|
+
owns_rate_limit_token: z3.boolean().optional(),
|
|
1846
|
+
supports_api_judge: z3.boolean().optional(),
|
|
1847
|
+
supports_ask_consult: z3.boolean().optional(),
|
|
1848
|
+
supports_decomposition_tools_profile: z3.boolean().optional(),
|
|
1849
|
+
requires_sandbox_interlock: z3.boolean().optional(),
|
|
1850
|
+
native_model_fallback: z3.boolean().optional(),
|
|
1851
|
+
supports_bounded_edit_allowlist: z3.boolean().optional(),
|
|
1852
|
+
supports_inherited_boundary_read_only: z3.boolean().optional()
|
|
1853
|
+
}).strict().default({
|
|
1854
|
+
streaming: false,
|
|
1855
|
+
tool_use: false,
|
|
1856
|
+
vision: false,
|
|
1857
|
+
function_calling: false,
|
|
1858
|
+
sub_agents: false,
|
|
1859
|
+
provider_native_subagents: false
|
|
1860
|
+
});
|
|
1861
|
+
var BotIdentityConfigSchema = z3.object({
|
|
1862
|
+
display_name: z3.string(),
|
|
1863
|
+
usernames: z3.array(z3.string())
|
|
1864
|
+
}).strict();
|
|
1865
|
+
var EnvConfigSchema = z3.record(z3.string(), z3.string());
|
|
1866
|
+
var RefreshStrategyConfigSchema = z3.discriminatedUnion("kind", [
|
|
1867
|
+
z3.object({
|
|
1868
|
+
kind: z3.literal("direct"),
|
|
1869
|
+
// Deterministic models API to poll; absent = doc-poll only (e.g. xAI).
|
|
1870
|
+
models_api: z3.enum(["anthropic", "openai", "google"]).optional(),
|
|
1871
|
+
doc_poll: z3.boolean(),
|
|
1872
|
+
cli_inventory: z3.enum(["cursor", "grok", "codex"]).optional()
|
|
1873
|
+
}).strict(),
|
|
1874
|
+
z3.object({ kind: z3.literal("aggregator") }).strict(),
|
|
1875
|
+
z3.object({
|
|
1876
|
+
kind: z3.literal("static"),
|
|
1877
|
+
reason: z3.string().trim().min(1).optional(),
|
|
1878
|
+
cli_inventory: z3.enum(["cursor", "grok", "codex"]).optional()
|
|
1879
|
+
}).strict()
|
|
1880
|
+
]);
|
|
1881
|
+
var DefaultPricingSchema = z3.object({
|
|
1882
|
+
billing_mode: z3.string(),
|
|
1883
|
+
currency: z3.string(),
|
|
1884
|
+
unit: z3.string()
|
|
1885
|
+
}).strict();
|
|
1886
|
+
var ConcurrencyConfigSchema = z3.object({
|
|
1887
|
+
max: z3.number().int().min(1),
|
|
1888
|
+
hybrid_batching: z3.boolean().optional().default(false),
|
|
1889
|
+
rationale: z3.string().trim().min(1)
|
|
1890
|
+
}).strict();
|
|
1891
|
+
var RouteConfigSchema = z3.object({
|
|
1892
|
+
// Environment variables to inject (e.g., API keys, endpoints)
|
|
1893
|
+
env: z3.record(z3.string(), z3.string()).optional(),
|
|
1894
|
+
// Auth commands to run before execution.
|
|
1895
|
+
//
|
|
1896
|
+
// SECURITY: Prefer argv form (auth_check_argv/auth_command_argv). String form is
|
|
1897
|
+
// treated as guidance-only and is not executed by Build.
|
|
1898
|
+
auth_check: z3.string().optional(),
|
|
1899
|
+
auth_command: z3.string().optional(),
|
|
1900
|
+
auth_clear: z3.string().optional(),
|
|
1901
|
+
auth_check_argv: z3.array(z3.string()).optional(),
|
|
1902
|
+
auth_command_argv: z3.array(z3.string()).optional(),
|
|
1903
|
+
auth_clear_argv: z3.array(z3.string()).optional(),
|
|
1904
|
+
auth_probe: CommandProbeSchema.optional(),
|
|
1905
|
+
// Model ID transform function name (if custom logic needed)
|
|
1906
|
+
model_transform: z3.string().optional()
|
|
1907
|
+
}).strict();
|
|
1908
|
+
var WorkspaceEditsConfigSchema = z3.object({
|
|
1909
|
+
// Detection mode: 'passthrough' (git-only), 'structured' (JSONL), or 'text-only' (analysis mode)
|
|
1910
|
+
mode: z3.enum(["passthrough", "structured", "text-only"]),
|
|
1911
|
+
// Whether to inject JSONL format instructions into prompts
|
|
1912
|
+
inject_jsonl: z3.boolean().optional(),
|
|
1913
|
+
// Whether to enforce FILE: specification in prompts
|
|
1914
|
+
enforce_file_targets: z3.boolean().optional()
|
|
1915
|
+
}).strict();
|
|
1916
|
+
var GenerationConfigSchema = z3.object({
|
|
1917
|
+
// Temperature controls output randomness (0.0 = deterministic, 1.0+ = creative)
|
|
1918
|
+
// For code generation, 0.2-0.4 is recommended for more deterministic output
|
|
1919
|
+
temperature: z3.number().min(0).max(2).optional(),
|
|
1920
|
+
// Nucleus sampling threshold (0.0-1.0)
|
|
1921
|
+
top_p: z3.number().min(0).max(1).optional(),
|
|
1922
|
+
// Top-k sampling (limits token choices)
|
|
1923
|
+
top_k: z3.number().int().min(1).optional(),
|
|
1924
|
+
// Maximum output tokens
|
|
1925
|
+
max_output_tokens: z3.number().int().min(1).optional()
|
|
1926
|
+
}).strict();
|
|
1927
|
+
var TaskSettingsSchema = z3.record(
|
|
1928
|
+
z3.string(),
|
|
1929
|
+
z3.object({
|
|
1930
|
+
temperature: z3.number().min(0).max(2).optional(),
|
|
1931
|
+
top_p: z3.number().min(0).max(1).optional(),
|
|
1932
|
+
top_k: z3.number().int().min(1).optional(),
|
|
1933
|
+
/** Retired and ignored: Build never picks effort from the task type. */
|
|
1934
|
+
reasoning_effort: z3.preprocess((value) => {
|
|
1935
|
+
if (value === void 0 || value === null) return void 0;
|
|
1936
|
+
const normalized = normalizeReasoningEffortInput(value);
|
|
1937
|
+
return normalized ?? value;
|
|
1938
|
+
}, z3.enum(["low", "medium", "high", "xhigh", "max"]).optional()),
|
|
1939
|
+
thinking_budget: z3.number().int().min(1).optional()
|
|
1940
|
+
}).strict()
|
|
1941
|
+
).optional();
|
|
1942
|
+
var RequirementSchema = z3.union([
|
|
1943
|
+
z3.object({ provider: z3.string() }).strict(),
|
|
1944
|
+
z3.object({ plugin: z3.string() }).strict(),
|
|
1945
|
+
z3.object({ binary: z3.string() }).strict()
|
|
1946
|
+
]);
|
|
1947
|
+
var ProviderOptionSchema = z3.object({
|
|
1948
|
+
// Option type
|
|
1949
|
+
type: z3.enum(["enum", "string", "bool"]),
|
|
1950
|
+
// Allowed values (for enum type)
|
|
1951
|
+
allowed: z3.array(z3.string()).optional(),
|
|
1952
|
+
// Default value
|
|
1953
|
+
default: z3.union([z3.string(), z3.boolean()]),
|
|
1954
|
+
// Description (shown in wizard)
|
|
1955
|
+
description: z3.string()
|
|
1956
|
+
}).strict();
|
|
1957
|
+
var ProviderOptionsSchema = z3.record(z3.string(), ProviderOptionSchema);
|
|
1958
|
+
var ConditionalRequiresSchema = z3.record(z3.string(), z3.array(RequirementSchema));
|
|
1959
|
+
var ProviderRequiresSchema = z3.object({
|
|
1960
|
+
// Always-required dependencies
|
|
1961
|
+
requires: z3.array(RequirementSchema).optional(),
|
|
1962
|
+
// Conditionally-required dependencies based on option values
|
|
1963
|
+
requires_if: ConditionalRequiresSchema.optional()
|
|
1964
|
+
}).strict();
|
|
1965
|
+
var ApiConfigSchema = z3.object({
|
|
1966
|
+
/** API base URL (host only, e.g., "https://api.anthropic.com"). */
|
|
1967
|
+
base_url: z3.url(),
|
|
1968
|
+
/** Environment variable name containing the API key. */
|
|
1969
|
+
api_key_env_var: z3.string(),
|
|
1970
|
+
/** Whether to use streaming responses (default: true). */
|
|
1971
|
+
stream: z3.boolean().optional().default(true),
|
|
1972
|
+
/** Additional HTTP headers to send with requests. */
|
|
1973
|
+
headers: z3.record(z3.string(), z3.string()).optional(),
|
|
1974
|
+
/** Max output tokens per API call. */
|
|
1975
|
+
max_tokens: z3.number().int().positive().optional(),
|
|
1976
|
+
/** Max tool-use iterations in the agentic loop (default: 50). */
|
|
1977
|
+
max_tool_iterations: z3.number().int().min(1).max(200).optional().default(50),
|
|
1978
|
+
/** Timeout per individual tool execution in ms (default: 30000). */
|
|
1979
|
+
per_tool_timeout_ms: z3.number().int().min(1e3).optional().default(3e4)
|
|
1980
|
+
}).strict().optional();
|
|
1981
|
+
var TemplatedCLIExecutionSchema = z3.object({
|
|
1982
|
+
// Base command arguments (before prompt)
|
|
1983
|
+
args: z3.array(z3.string()),
|
|
1984
|
+
// Command-line flags (e.g., {"--quiet": true, "--cwd": "{{workspace}}"})
|
|
1985
|
+
flags: z3.record(z3.string(), z3.union([z3.boolean(), z3.string()])).optional(),
|
|
1986
|
+
// Prompt placement: 'positional' (in args array) or 'stdin'
|
|
1987
|
+
prompt_placement: z3.enum(["positional", "stdin"]),
|
|
1988
|
+
// Whether to add "--" before the prompt when using positional prompt placement.
|
|
1989
|
+
// Defaults to true (safer); set false for CLIs that don't support "--".
|
|
1990
|
+
double_dash_before_prompt: z3.boolean().optional(),
|
|
1991
|
+
// Whether stdin is supported as fallback
|
|
1992
|
+
stdin_fallback: z3.boolean().optional(),
|
|
1993
|
+
// Template variables available for interpolation
|
|
1994
|
+
// (e.g., {{prompt}}, {{model.routing_id}}, {{workspace}})
|
|
1995
|
+
template_vars: z3.array(z3.string()).optional()
|
|
1996
|
+
}).strict();
|
|
1997
|
+
var NativeProviderConfigSchema = z3.object({
|
|
1998
|
+
// Basic metadata
|
|
1999
|
+
id: z3.string(),
|
|
2000
|
+
name: z3.string(),
|
|
2001
|
+
display_name: z3.string(),
|
|
2002
|
+
description: z3.string(),
|
|
2003
|
+
vendor: z3.string(),
|
|
2004
|
+
enabled: z3.boolean(),
|
|
2005
|
+
experimental: z3.boolean(),
|
|
2006
|
+
release_status: ProviderReleaseStatusSchema.optional(),
|
|
2007
|
+
order: z3.number().int(),
|
|
2008
|
+
// Provider type and transport
|
|
2009
|
+
type: z3.enum(["cli", "api", "cloud_cli", "cli_wrapper"]),
|
|
2010
|
+
transport: z3.enum(["cli", "api", "hybrid"]),
|
|
2011
|
+
channels: z3.array(z3.string()),
|
|
2012
|
+
// CLI configuration
|
|
2013
|
+
cli: CLIConfigSchema,
|
|
2014
|
+
// API transport configuration (optional, for direct API inference)
|
|
2015
|
+
api: ApiConfigSchema,
|
|
2016
|
+
// Authentication
|
|
2017
|
+
auth: AuthConfigSchema,
|
|
2018
|
+
// Models
|
|
2019
|
+
models: ModelsConfigSchema,
|
|
2020
|
+
// Capabilities
|
|
2021
|
+
capabilities: CapabilitiesConfigSchema,
|
|
2022
|
+
// Performance
|
|
2023
|
+
concurrency_hint: z3.enum(["low", "medium", "high"]),
|
|
2024
|
+
concurrency: ConcurrencyConfigSchema.optional(),
|
|
2025
|
+
// Timeouts
|
|
2026
|
+
timeout_ms: z3.number().int().min(1),
|
|
2027
|
+
health_check_timeout_ms: z3.number().int().min(1).optional(),
|
|
2028
|
+
// Legacy memory metadata (accepted but not consumed; Memory Guardian owns its profiles)
|
|
2029
|
+
memory: MemoryConfigSchema.optional(),
|
|
2030
|
+
// Legacy polling metadata (accepted but not consumed)
|
|
2031
|
+
polling: PollingConfigSchema.optional(),
|
|
2032
|
+
// Legacy bot identity metadata (accepted but not consumed)
|
|
2033
|
+
bot_identity: BotIdentityConfigSchema.optional(),
|
|
2034
|
+
// Environment variables
|
|
2035
|
+
env: EnvConfigSchema,
|
|
2036
|
+
// Legacy retry and circuit breaker metadata (accepted but not consumed; the provider
|
|
2037
|
+
// retry wrapper and circuit breaker registry own their runtime defaults)
|
|
2038
|
+
retry: RetryConfigSchema.optional(),
|
|
2039
|
+
circuit_breaker: CircuitBreakerConfigSchema.optional(),
|
|
2040
|
+
// Rate limits (optional overrides, new in v2.1)
|
|
2041
|
+
rate_limits: RateLimitsConfigSchema.optional(),
|
|
2042
|
+
// Pricing (optional, new in v2.0)
|
|
2043
|
+
pricing: ProviderPricingSchema.optional(),
|
|
2044
|
+
// Refresh strategy for `build provider refresh` (optional; providers
|
|
2045
|
+
// without a declaration are treated as static by the refresh dispatcher).
|
|
2046
|
+
refresh_strategy: RefreshStrategyConfigSchema.optional(),
|
|
2047
|
+
// Engine type. 'templated_cli' is DEPRECATED: the templated CLI engine was
|
|
2048
|
+
// removed (2026-06) and providers declaring it are no longer registered —
|
|
2049
|
+
// the registry emits a TMPL-001 warning instead. The value stays in the
|
|
2050
|
+
// schema only so legacy user overlays still validate and reach that
|
|
2051
|
+
// warning rather than failing on an unknown enum value.
|
|
2052
|
+
engine: z3.enum(["native", "templated_cli"]).optional().default("native"),
|
|
2053
|
+
// Templated CLI execution config (deprecated with engine=templated_cli)
|
|
2054
|
+
exec: TemplatedCLIExecutionSchema.optional(),
|
|
2055
|
+
// Route configuration (for model ID transforms and env injection)
|
|
2056
|
+
route_id: z3.string().optional(),
|
|
2057
|
+
// Reference to a named route; unrelated to a model row's `routes`
|
|
2058
|
+
route: RouteConfigSchema.optional(),
|
|
2059
|
+
// Inline route override
|
|
2060
|
+
// Workspace edit detection strategy
|
|
2061
|
+
workspace_edits: WorkspaceEditsConfigSchema.optional(),
|
|
2062
|
+
// Generation parameters (temperature, topP, etc.)
|
|
2063
|
+
generation: GenerationConfigSchema.optional(),
|
|
2064
|
+
// Task-type-aware generation settings (overrides generation defaults)
|
|
2065
|
+
task_settings: TaskSettingsSchema,
|
|
2066
|
+
// Binary allowlist for security (only used if engine=templated_cli)
|
|
2067
|
+
allow_unsafe_binary: z3.boolean().optional().default(false),
|
|
2068
|
+
// Explicit opt-in for non-allowlisted binaries
|
|
2069
|
+
// Provider options (generic, any provider)
|
|
2070
|
+
options: ProviderOptionsSchema.optional(),
|
|
2071
|
+
// Dependency management (generic, any provider)
|
|
2072
|
+
requires: z3.array(RequirementSchema).optional(),
|
|
2073
|
+
requires_if: ConditionalRequiresSchema.optional()
|
|
2074
|
+
}).strict();
|
|
2075
|
+
var TemplatedProviderConfigSchema = z3.object({
|
|
2076
|
+
// Basic metadata
|
|
2077
|
+
id: z3.string(),
|
|
2078
|
+
name: z3.string(),
|
|
2079
|
+
display_name: z3.string().optional().default(""),
|
|
2080
|
+
description: z3.string().optional().default(""),
|
|
2081
|
+
vendor: z3.string().optional().default("custom"),
|
|
2082
|
+
enabled: z3.boolean().optional().default(true),
|
|
2083
|
+
experimental: z3.boolean().optional().default(false),
|
|
2084
|
+
release_status: ProviderReleaseStatusSchema.optional(),
|
|
2085
|
+
order: z3.number().int().optional().default(99),
|
|
2086
|
+
// Provider type and transport
|
|
2087
|
+
type: z3.enum(["cli", "api", "cloud_cli", "cli_wrapper"]).optional().default("cli_wrapper"),
|
|
2088
|
+
transport: z3.enum(["cli", "api", "hybrid"]).optional().default("cli"),
|
|
2089
|
+
channels: z3.array(z3.string()).optional().default(["cli"]),
|
|
2090
|
+
// CLI configuration
|
|
2091
|
+
cli: CLIConfigSchema,
|
|
2092
|
+
// API transport configuration (optional, for direct API inference)
|
|
2093
|
+
api: ApiConfigSchema,
|
|
2094
|
+
// Authentication
|
|
2095
|
+
auth: TemplatedAuthConfigSchema,
|
|
2096
|
+
// Models
|
|
2097
|
+
models: TemplatedModelsConfigSchema,
|
|
2098
|
+
// Capabilities
|
|
2099
|
+
capabilities: TemplatedCapabilitiesConfigSchema,
|
|
2100
|
+
// Performance
|
|
2101
|
+
concurrency_hint: z3.enum(["low", "medium", "high"]).optional().default("low"),
|
|
2102
|
+
concurrency: ConcurrencyConfigSchema.optional(),
|
|
2103
|
+
// Timeouts
|
|
2104
|
+
timeout_ms: z3.number().int().min(1).optional().default(6e5),
|
|
2105
|
+
health_check_timeout_ms: z3.number().int().min(1).optional(),
|
|
2106
|
+
// Legacy memory metadata (accepted but not consumed; Memory Guardian owns its profiles)
|
|
2107
|
+
memory: MemoryConfigSchema.optional(),
|
|
2108
|
+
// Legacy polling metadata (accepted but not consumed)
|
|
2109
|
+
polling: PollingConfigSchema.optional(),
|
|
2110
|
+
// Legacy bot identity metadata (accepted but not consumed)
|
|
2111
|
+
bot_identity: BotIdentityConfigSchema.optional(),
|
|
2112
|
+
// Environment variables
|
|
2113
|
+
env: EnvConfigSchema.default({}),
|
|
2114
|
+
// Legacy retry and circuit breaker metadata (accepted but not consumed; the provider
|
|
2115
|
+
// retry wrapper and circuit breaker registry own their runtime defaults)
|
|
2116
|
+
retry: RetryConfigSchema.optional(),
|
|
2117
|
+
circuit_breaker: CircuitBreakerConfigSchema.optional(),
|
|
2118
|
+
// Rate limits (optional overrides)
|
|
2119
|
+
rate_limits: RateLimitsConfigSchema.optional(),
|
|
2120
|
+
// Pricing (optional)
|
|
2121
|
+
pricing: ProviderPricingSchema.optional(),
|
|
2122
|
+
// Engine selection (templated)
|
|
2123
|
+
engine: z3.literal("templated_cli"),
|
|
2124
|
+
// Templated CLI execution config (required)
|
|
2125
|
+
exec: TemplatedCLIExecutionSchema,
|
|
2126
|
+
// Route configuration (optional)
|
|
2127
|
+
route_id: z3.string().optional(),
|
|
2128
|
+
route: RouteConfigSchema.optional(),
|
|
2129
|
+
// Workspace edit detection strategy (optional)
|
|
2130
|
+
workspace_edits: WorkspaceEditsConfigSchema.optional(),
|
|
2131
|
+
// Generation parameters (temperature, topP, etc.)
|
|
2132
|
+
generation: GenerationConfigSchema.optional(),
|
|
2133
|
+
// Task-type-aware generation settings (overrides generation defaults)
|
|
2134
|
+
task_settings: TaskSettingsSchema,
|
|
2135
|
+
// Binary allowlist override
|
|
2136
|
+
allow_unsafe_binary: z3.boolean().optional().default(false),
|
|
2137
|
+
// Provider options (generic, any provider)
|
|
2138
|
+
options: ProviderOptionsSchema.optional(),
|
|
2139
|
+
// Dependency management (generic, any provider)
|
|
2140
|
+
requires: z3.array(RequirementSchema).optional(),
|
|
2141
|
+
requires_if: ConditionalRequiresSchema.optional()
|
|
2142
|
+
}).strict().transform((provider) => ({
|
|
2143
|
+
...provider,
|
|
2144
|
+
display_name: provider.display_name?.trim() ? provider.display_name : provider.name,
|
|
2145
|
+
description: provider.description ?? ""
|
|
2146
|
+
}));
|
|
2147
|
+
var ProviderConfigSchema = z3.union([
|
|
2148
|
+
TemplatedProviderConfigSchema,
|
|
2149
|
+
NativeProviderConfigSchema
|
|
2150
|
+
]);
|
|
2151
|
+
var DefaultsConfigSchema = z3.object({
|
|
2152
|
+
timeout_ms: z3.number().int().min(1),
|
|
2153
|
+
// Legacy retry, circuit breaker and memory metadata (accepted but not consumed)
|
|
2154
|
+
retry: RetryConfigSchema.optional(),
|
|
2155
|
+
circuit_breaker: CircuitBreakerConfigSchema.optional(),
|
|
2156
|
+
rate_limits: RateLimitsConfigSchema.optional(),
|
|
2157
|
+
memory: MemoryConfigSchema.optional(),
|
|
2158
|
+
polling: PollingConfigSchema.optional(),
|
|
2159
|
+
pricing: DefaultPricingSchema.optional()
|
|
2160
|
+
}).strict();
|
|
2161
|
+
var MetadataConfigSchema = z3.object({
|
|
2162
|
+
schema_version: z3.string(),
|
|
2163
|
+
generated_at: DateLikeStringSchema,
|
|
2164
|
+
description: z3.string(),
|
|
2165
|
+
documentation: z3.string(),
|
|
2166
|
+
migration_notes: z3.string().optional(),
|
|
2167
|
+
last_updated: DateLikeStringSchema.optional()
|
|
2168
|
+
}).strict();
|
|
2169
|
+
var ProviderRegistryConfigSchema = z3.object({
|
|
2170
|
+
version: z3.string(),
|
|
2171
|
+
defaults: DefaultsConfigSchema,
|
|
2172
|
+
guidance_profiles: z3.record(z3.string(), z3.unknown()).optional(),
|
|
2173
|
+
judge: z3.record(z3.string(), z3.unknown()).optional(),
|
|
2174
|
+
providers: z3.record(z3.string(), ProviderConfigSchema),
|
|
2175
|
+
metadata: MetadataConfigSchema
|
|
2176
|
+
}).strict();
|
|
2177
|
+
var UNKNOWN_JUDGE_CAPABILITIES = {
|
|
2178
|
+
canJudge: false,
|
|
2179
|
+
canArbitrate: false
|
|
2180
|
+
};
|
|
2181
|
+
var PROVIDER_FAMILY_METADATA = {
|
|
2182
|
+
claude: {
|
|
2183
|
+
family: "anthropic",
|
|
2184
|
+
judge: {
|
|
2185
|
+
canJudge: true,
|
|
2186
|
+
canArbitrate: true
|
|
2187
|
+
}
|
|
2188
|
+
},
|
|
2189
|
+
codex: {
|
|
2190
|
+
family: "openai",
|
|
2191
|
+
judge: {
|
|
2192
|
+
canJudge: true,
|
|
2193
|
+
canArbitrate: true
|
|
2194
|
+
}
|
|
2195
|
+
},
|
|
2196
|
+
cursor: {
|
|
2197
|
+
family: "cursor",
|
|
2198
|
+
judge: {
|
|
2199
|
+
canJudge: true,
|
|
2200
|
+
canArbitrate: false
|
|
2201
|
+
}
|
|
2202
|
+
},
|
|
2203
|
+
grok: {
|
|
2204
|
+
family: "xai",
|
|
2205
|
+
judge: {
|
|
2206
|
+
canJudge: true,
|
|
2207
|
+
canArbitrate: true
|
|
2208
|
+
}
|
|
2209
|
+
},
|
|
2210
|
+
opencode: {
|
|
2211
|
+
family: "opencode",
|
|
2212
|
+
judge: {
|
|
2213
|
+
canJudge: true,
|
|
2214
|
+
canArbitrate: false
|
|
2215
|
+
}
|
|
2216
|
+
},
|
|
2217
|
+
antigravity: {
|
|
2218
|
+
family: "antigravity",
|
|
2219
|
+
judge: {
|
|
2220
|
+
canJudge: true,
|
|
2221
|
+
canArbitrate: false
|
|
2222
|
+
}
|
|
2223
|
+
},
|
|
2224
|
+
copilot: {
|
|
2225
|
+
family: "github",
|
|
2226
|
+
judge: {
|
|
2227
|
+
canJudge: true,
|
|
2228
|
+
canArbitrate: true
|
|
2229
|
+
}
|
|
2230
|
+
},
|
|
2231
|
+
kiro: {
|
|
2232
|
+
family: "aws",
|
|
2233
|
+
judge: {
|
|
2234
|
+
canJudge: true,
|
|
2235
|
+
canArbitrate: false
|
|
2236
|
+
}
|
|
2237
|
+
},
|
|
2238
|
+
gemini: {
|
|
2239
|
+
family: "google",
|
|
2240
|
+
judge: {
|
|
2241
|
+
canJudge: true,
|
|
2242
|
+
canArbitrate: true
|
|
2243
|
+
}
|
|
2244
|
+
},
|
|
2245
|
+
pi: {
|
|
2246
|
+
family: "earendil",
|
|
2247
|
+
judge: {
|
|
2248
|
+
canJudge: true,
|
|
2249
|
+
canArbitrate: false
|
|
2250
|
+
}
|
|
2251
|
+
}
|
|
2252
|
+
};
|
|
2253
|
+
function lookupProviderFamilyMetadata(providerId) {
|
|
2254
|
+
return PROVIDER_FAMILY_METADATA[normalizeProviderConfigId(providerId)];
|
|
2255
|
+
}
|
|
2256
|
+
function getProviderFamily(providerId, registryOverride) {
|
|
2257
|
+
const listed = lookupProviderFamilyMetadata(providerId);
|
|
2258
|
+
if (listed) return listed.family;
|
|
2259
|
+
try {
|
|
2260
|
+
const vendor = ProviderRegistry.getProviderConfig(providerId, registryOverride).vendor;
|
|
2261
|
+
const trimmed = vendor.trim();
|
|
2262
|
+
if (trimmed) return trimmed;
|
|
2263
|
+
} catch {
|
|
2264
|
+
}
|
|
2265
|
+
return normalizeProviderConfigId(providerId);
|
|
2266
|
+
}
|
|
2267
|
+
function getJudgeCapabilities(providerId) {
|
|
2268
|
+
return lookupProviderFamilyMetadata(providerId)?.judge ?? UNKNOWN_JUDGE_CAPABILITIES;
|
|
2269
|
+
}
|
|
2270
|
+
function listModelEntryIssues(entry) {
|
|
2271
|
+
const result = ModelInfoSchema.safeParse(entry);
|
|
2272
|
+
if (result.success) return [];
|
|
2273
|
+
return result.error.issues.map(
|
|
2274
|
+
(issue) => `${issue.path.length > 0 ? issue.path.join(".") : "entry"}: ${issue.message}`
|
|
2275
|
+
);
|
|
2276
|
+
}
|
|
2277
|
+
function cloneProviderRegistryValue(value) {
|
|
2278
|
+
return structuredClone(value);
|
|
2279
|
+
}
|
|
2280
|
+
function verifySchemaDefinitions() {
|
|
2281
|
+
const schemas = {
|
|
2282
|
+
RetryConfigSchema,
|
|
2283
|
+
CircuitBreakerConfigSchema,
|
|
2284
|
+
MemoryConfigSchema,
|
|
2285
|
+
PollingConfigSchema,
|
|
2286
|
+
CLIConfigSchema,
|
|
2287
|
+
AuthConfigSchema,
|
|
2288
|
+
ModelInfoSchema,
|
|
2289
|
+
ModelsConfigSchema,
|
|
2290
|
+
CapabilitiesConfigSchema,
|
|
2291
|
+
BotIdentityConfigSchema,
|
|
2292
|
+
EnvConfigSchema,
|
|
2293
|
+
ModelPricingSchema,
|
|
2294
|
+
ToolPricingSchema,
|
|
2295
|
+
SubscriptionPricingSchema,
|
|
2296
|
+
InfrastructurePricingSchema,
|
|
2297
|
+
ProviderPricingSchema,
|
|
2298
|
+
DefaultPricingSchema,
|
|
2299
|
+
RequirementSchema,
|
|
2300
|
+
ProviderOptionSchema,
|
|
2301
|
+
ProviderOptionsSchema,
|
|
2302
|
+
ConditionalRequiresSchema,
|
|
2303
|
+
ProviderRequiresSchema,
|
|
2304
|
+
ProviderConfigSchema,
|
|
2305
|
+
DefaultsConfigSchema,
|
|
2306
|
+
MetadataConfigSchema,
|
|
2307
|
+
ProviderRegistryConfigSchema
|
|
2308
|
+
};
|
|
2309
|
+
for (const [name, schema] of Object.entries(schemas)) {
|
|
2310
|
+
if (!schema || !("_zod" in schema)) {
|
|
2311
|
+
throw new Error(
|
|
2312
|
+
`Schema ${name} is undefined or invalid. This indicates a schema definition error. Check that all nested schemas in ${name} are properly defined. Common issue: Zod v4 requires z.record(keySchema, valueSchema) with explicit parameters.`
|
|
2313
|
+
);
|
|
2314
|
+
}
|
|
2315
|
+
}
|
|
2316
|
+
}
|
|
2317
|
+
verifySchemaDefinitions();
|
|
2318
|
+
var ProviderRegistry = class _ProviderRegistry {
|
|
2319
|
+
static instance = null;
|
|
2320
|
+
static configPath = null;
|
|
2321
|
+
static configSources = [];
|
|
2322
|
+
static ignoredUserModelEntries = [];
|
|
2323
|
+
static cacheKey = null;
|
|
2324
|
+
static cacheMode = null;
|
|
2325
|
+
static cacheProjectRoot = null;
|
|
2326
|
+
constructor() {
|
|
2327
|
+
}
|
|
2328
|
+
static replaceCachedRegistry(config, configPath, cacheKey, cacheMode, projectRoot, configSources = [configPath], ignoredUserModelEntries = []) {
|
|
2329
|
+
const replacedExistingCache = _ProviderRegistry.instance !== null && (_ProviderRegistry.configPath !== configPath || _ProviderRegistry.cacheKey !== cacheKey || _ProviderRegistry.cacheMode !== cacheMode);
|
|
2330
|
+
_ProviderRegistry.instance = config;
|
|
2331
|
+
_ProviderRegistry.configPath = configPath;
|
|
2332
|
+
_ProviderRegistry.configSources = [...configSources];
|
|
2333
|
+
_ProviderRegistry.ignoredUserModelEntries = [...ignoredUserModelEntries];
|
|
2334
|
+
_ProviderRegistry.cacheKey = cacheKey;
|
|
2335
|
+
_ProviderRegistry.cacheMode = cacheMode;
|
|
2336
|
+
_ProviderRegistry.cacheProjectRoot = projectRoot;
|
|
2337
|
+
if (replacedExistingCache) {
|
|
2338
|
+
runProviderRegistryReloadInvalidators();
|
|
2339
|
+
}
|
|
2340
|
+
return config;
|
|
2341
|
+
}
|
|
2342
|
+
/**
|
|
2343
|
+
* Load the unified provider registry from YAML
|
|
2344
|
+
*
|
|
2345
|
+
* @param configPath - Path to providers.yaml (defaults to .build-project/config/providers.yaml)
|
|
2346
|
+
* @returns Validated and merged configuration
|
|
2347
|
+
*/
|
|
2348
|
+
static load(configPath, cwd = process.cwd(), rootOptions = {}) {
|
|
2349
|
+
const projectRoot = findProjectRoot(cwd, rootOptions) ?? cwd;
|
|
2350
|
+
configPath = configPath ? resolve5(projectRoot, configPath) : void 0;
|
|
2351
|
+
const envCacheKey = _ProviderRegistry.buildEnvOverrideCacheKey();
|
|
2352
|
+
const requestedCacheKey = _ProviderRegistry.buildCacheKey(configPath, envCacheKey, projectRoot);
|
|
2353
|
+
if (_ProviderRegistry.instance && (_ProviderRegistry.cacheKey === requestedCacheKey || !configPath && _ProviderRegistry.cacheMode === "explicit" && _ProviderRegistry.configPath !== null && _ProviderRegistry.canReuseExplicitCacheForImplicit(
|
|
2354
|
+
_ProviderRegistry.configPath,
|
|
2355
|
+
projectRoot
|
|
2356
|
+
) && _ProviderRegistry.cacheKey === _ProviderRegistry.buildCacheKey(_ProviderRegistry.configPath, envCacheKey, projectRoot))) {
|
|
2357
|
+
return _ProviderRegistry.instance;
|
|
2358
|
+
}
|
|
2359
|
+
const embeddedConfigPaths = getEmbeddedProviderConfigPaths();
|
|
2360
|
+
const isTrustedProjectForProviderOverrides = () => isTrustedProjectRoot(projectRoot);
|
|
2361
|
+
const projectTrustInstruction = formatProjectTrustInstruction(projectRoot);
|
|
2362
|
+
const loadYamlRawIfExists = (filePath) => {
|
|
2363
|
+
if (!existsSync5(filePath)) return null;
|
|
2364
|
+
try {
|
|
2365
|
+
const rawYaml = readFileSync8(filePath, "utf-8");
|
|
2366
|
+
return yaml.load(rawYaml);
|
|
2367
|
+
} catch (error) {
|
|
2368
|
+
throw new Error(
|
|
2369
|
+
`Failed to load YAML at ${filePath}: ${error instanceof Error ? error.message : String(error)}`
|
|
2370
|
+
);
|
|
2371
|
+
}
|
|
2372
|
+
};
|
|
2373
|
+
const loadEmbeddedRaw = () => {
|
|
2374
|
+
for (const embeddedConfigPath of embeddedConfigPaths) {
|
|
2375
|
+
if (!existsSync5(embeddedConfigPath)) continue;
|
|
2376
|
+
try {
|
|
2377
|
+
const bytes = readFileSync8(embeddedConfigPath);
|
|
2378
|
+
let sourceBaseDrift;
|
|
2379
|
+
if (isPackagedCatalogPath(embeddedConfigPath)) {
|
|
2380
|
+
const digest2 = createHash5("sha256").update(bytes).digest("hex");
|
|
2381
|
+
if (digest2 !== PROVIDER_CATALOG_SHA256) {
|
|
2382
|
+
throw new Error(
|
|
2383
|
+
`Provider catalog digest mismatch: expected ${PROVIDER_CATALOG_SHA256}, received ${digest2}`
|
|
2384
|
+
);
|
|
2385
|
+
}
|
|
2386
|
+
} else {
|
|
2387
|
+
sourceBaseDrift = resolveSourceBaseDrift(embeddedConfigPath, bytes);
|
|
2388
|
+
if (sourceBaseDrift) {
|
|
2389
|
+
debugLog(
|
|
2390
|
+
`Provider source YAML ${embeddedConfigPath} does not match the compiled source digest (expected ${sourceBaseDrift.expectedDigest}, received ${sourceBaseDrift.actualDigest}); run the provider generator`
|
|
2391
|
+
);
|
|
2392
|
+
}
|
|
2393
|
+
}
|
|
2394
|
+
const raw = yaml.load(bytes.toString("utf8"));
|
|
2395
|
+
if (!raw) continue;
|
|
2396
|
+
return { path: embeddedConfigPath, raw, sourceBaseDrift };
|
|
2397
|
+
} catch (error) {
|
|
2398
|
+
throw new Error(
|
|
2399
|
+
`Failed to load packaged provider catalog at ${embeddedConfigPath}: ${error instanceof Error ? error.message : String(error)}`
|
|
2400
|
+
);
|
|
2401
|
+
}
|
|
2402
|
+
}
|
|
2403
|
+
return null;
|
|
2404
|
+
};
|
|
2405
|
+
const deepMerge = (base, overlay) => {
|
|
2406
|
+
if (!overlay || typeof overlay !== "object") return base;
|
|
2407
|
+
if (!base || typeof base !== "object") return overlay;
|
|
2408
|
+
const baseObj = base;
|
|
2409
|
+
const overlayObj = overlay;
|
|
2410
|
+
const out = { ...baseObj };
|
|
2411
|
+
for (const [key, overlayValue] of Object.entries(overlayObj)) {
|
|
2412
|
+
const baseValue = baseObj[key];
|
|
2413
|
+
if (key === "providers" && overlayValue && typeof overlayValue === "object" && !Array.isArray(overlayValue)) {
|
|
2414
|
+
const existingProviders = baseValue && typeof baseValue === "object" && !Array.isArray(baseValue) ? baseValue : {};
|
|
2415
|
+
const overlayProviders = overlayValue;
|
|
2416
|
+
const mergedProviders = { ...existingProviders };
|
|
2417
|
+
for (const [providerId, providerOverlay] of Object.entries(overlayProviders)) {
|
|
2418
|
+
const existingProvider = existingProviders[providerId];
|
|
2419
|
+
if (existingProvider && typeof existingProvider === "object" && !Array.isArray(existingProvider) && providerOverlay && typeof providerOverlay === "object" && !Array.isArray(providerOverlay)) {
|
|
2420
|
+
mergedProviders[providerId] = deepMerge(existingProvider, providerOverlay);
|
|
2421
|
+
} else {
|
|
2422
|
+
mergedProviders[providerId] = providerOverlay;
|
|
2423
|
+
}
|
|
2424
|
+
}
|
|
2425
|
+
out.providers = mergedProviders;
|
|
2426
|
+
continue;
|
|
2427
|
+
}
|
|
2428
|
+
if (overlayValue && typeof overlayValue === "object" && !Array.isArray(overlayValue) && !(overlayValue instanceof Date) && baseValue && typeof baseValue === "object" && !Array.isArray(baseValue) && !(baseValue instanceof Date)) {
|
|
2429
|
+
out[key] = deepMerge(baseValue, overlayValue);
|
|
2430
|
+
continue;
|
|
2431
|
+
}
|
|
2432
|
+
out[key] = overlayValue;
|
|
2433
|
+
}
|
|
2434
|
+
return out;
|
|
2435
|
+
};
|
|
2436
|
+
const isFullRegistrySnapshot = (raw, base) => {
|
|
2437
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return false;
|
|
2438
|
+
if (!base || typeof base !== "object" || Array.isArray(base)) return false;
|
|
2439
|
+
const rawObject = raw;
|
|
2440
|
+
const baseObject = base;
|
|
2441
|
+
const rawProviders = rawObject.providers;
|
|
2442
|
+
const baseProviders = baseObject.providers;
|
|
2443
|
+
if (!rawProviders || typeof rawProviders !== "object" || Array.isArray(rawProviders) || !baseProviders || typeof baseProviders !== "object" || Array.isArray(baseProviders)) {
|
|
2444
|
+
return false;
|
|
2445
|
+
}
|
|
2446
|
+
return "version" in rawObject && "defaults" in rawObject && "metadata" in rawObject && Object.keys(rawProviders).length > 0;
|
|
2447
|
+
};
|
|
2448
|
+
const migrateLegacyFullSnapshotOverlay = (raw, base) => {
|
|
2449
|
+
if (!isFullRegistrySnapshot(raw, base)) return raw;
|
|
2450
|
+
const migrated = cloneProviderRegistryValue(raw);
|
|
2451
|
+
const migratedProviders = migrated.providers;
|
|
2452
|
+
const baseProviders = base.providers;
|
|
2453
|
+
for (const [providerId, providerValue] of Object.entries(migratedProviders)) {
|
|
2454
|
+
const baseProviderValue = baseProviders[providerId];
|
|
2455
|
+
if (!baseProviderValue || typeof baseProviderValue !== "object" || Array.isArray(baseProviderValue)) {
|
|
2456
|
+
continue;
|
|
2457
|
+
}
|
|
2458
|
+
if (!providerValue || typeof providerValue !== "object" || Array.isArray(providerValue)) {
|
|
2459
|
+
continue;
|
|
2460
|
+
}
|
|
2461
|
+
const provider = providerValue;
|
|
2462
|
+
const modelsValue = provider.models;
|
|
2463
|
+
const baseModelsValue = baseProviderValue.models;
|
|
2464
|
+
if (!modelsValue || typeof modelsValue !== "object" || Array.isArray(modelsValue)) {
|
|
2465
|
+
continue;
|
|
2466
|
+
}
|
|
2467
|
+
if (!baseModelsValue || typeof baseModelsValue !== "object" || Array.isArray(baseModelsValue)) {
|
|
2468
|
+
continue;
|
|
2469
|
+
}
|
|
2470
|
+
const models = modelsValue;
|
|
2471
|
+
const baseModels = baseModelsValue;
|
|
2472
|
+
if (Array.isArray(baseModels.allowed_patterns) && Array.isArray(models.allowed_patterns) && [...baseModels.allowed_patterns, ...models.allowed_patterns].every(
|
|
2473
|
+
(pattern) => typeof pattern === "string"
|
|
2474
|
+
)) {
|
|
2475
|
+
models.allowed_patterns = [
|
|
2476
|
+
.../* @__PURE__ */ new Set([...baseModels.allowed_patterns, ...models.allowed_patterns])
|
|
2477
|
+
];
|
|
2478
|
+
}
|
|
2479
|
+
for (const key of ["mappings", "roles"]) {
|
|
2480
|
+
const baseRecord = baseModels[key];
|
|
2481
|
+
const overlayRecord = models[key];
|
|
2482
|
+
if (baseRecord && typeof baseRecord === "object" && !Array.isArray(baseRecord) && overlayRecord && typeof overlayRecord === "object" && !Array.isArray(overlayRecord)) {
|
|
2483
|
+
models[key] = {
|
|
2484
|
+
...baseRecord,
|
|
2485
|
+
...overlayRecord
|
|
2486
|
+
};
|
|
2487
|
+
}
|
|
2488
|
+
}
|
|
2489
|
+
}
|
|
2490
|
+
return migrated;
|
|
2491
|
+
};
|
|
2492
|
+
const getRawProvider = (raw, providerId) => {
|
|
2493
|
+
if (!raw || typeof raw !== "object") return void 0;
|
|
2494
|
+
const providers = raw.providers;
|
|
2495
|
+
if (!providers || typeof providers !== "object") return void 0;
|
|
2496
|
+
return providers[providerId];
|
|
2497
|
+
};
|
|
2498
|
+
const stableJson = (value) => {
|
|
2499
|
+
if (Array.isArray(value)) {
|
|
2500
|
+
return `[${value.map((entry) => stableJson(entry)).join(",")}]`;
|
|
2501
|
+
}
|
|
2502
|
+
if (value && typeof value === "object") {
|
|
2503
|
+
return `{${Object.entries(value).sort(([a], [b]) => a.localeCompare(b)).map(([key, entry]) => `${JSON.stringify(key)}:${stableJson(entry)}`).join(",")}}`;
|
|
2504
|
+
}
|
|
2505
|
+
return JSON.stringify(value);
|
|
2506
|
+
};
|
|
2507
|
+
const normalizeProviderForTrustComparison = (providerId, provider) => {
|
|
2508
|
+
try {
|
|
2509
|
+
return ProviderConfigSchema.parse(provider);
|
|
2510
|
+
} catch (error) {
|
|
2511
|
+
debugLog(
|
|
2512
|
+
`[provider-registry] Failed to normalize provider "${providerId}" for trust comparison`,
|
|
2513
|
+
error instanceof Error ? error.message : String(error)
|
|
2514
|
+
);
|
|
2515
|
+
return provider;
|
|
2516
|
+
}
|
|
2517
|
+
};
|
|
2518
|
+
const listUntrustedExecutionFieldChanges = (raw, trustedRaw) => {
|
|
2519
|
+
if (!raw || typeof raw !== "object") return [];
|
|
2520
|
+
const providers = raw.providers;
|
|
2521
|
+
if (!providers || typeof providers !== "object" || Array.isArray(providers)) return [];
|
|
2522
|
+
const changes = [];
|
|
2523
|
+
for (const [providerId, candidate] of Object.entries(providers)) {
|
|
2524
|
+
if (!candidate || typeof candidate !== "object" || Array.isArray(candidate)) continue;
|
|
2525
|
+
const candidateProvider = candidate;
|
|
2526
|
+
const trusted = getRawProvider(trustedRaw, providerId);
|
|
2527
|
+
const trustedProvider = trusted && typeof trusted === "object" && !Array.isArray(trusted) ? trusted : null;
|
|
2528
|
+
if (!trustedProvider) {
|
|
2529
|
+
const declaredFields = EXECUTION_SENSITIVE_PROVIDER_FIELDS.filter(
|
|
2530
|
+
(field) => candidateProvider[field] !== void 0
|
|
2531
|
+
);
|
|
2532
|
+
if (declaredFields.length > 0) {
|
|
2533
|
+
changes.push({ providerId, fields: [...declaredFields] });
|
|
2534
|
+
}
|
|
2535
|
+
continue;
|
|
2536
|
+
}
|
|
2537
|
+
const effective = normalizeProviderForTrustComparison(
|
|
2538
|
+
providerId,
|
|
2539
|
+
deepMerge(trustedProvider, candidateProvider)
|
|
2540
|
+
);
|
|
2541
|
+
const baseline = normalizeProviderForTrustComparison(providerId, trustedProvider);
|
|
2542
|
+
const changedFields = EXECUTION_SENSITIVE_PROVIDER_FIELDS.filter((field) => {
|
|
2543
|
+
if (candidateProvider[field] === void 0) return false;
|
|
2544
|
+
return stableJson(effective?.[field]) !== stableJson(baseline?.[field]);
|
|
2545
|
+
});
|
|
2546
|
+
if (changedFields.length > 0) {
|
|
2547
|
+
changes.push({ providerId, fields: [...changedFields] });
|
|
2548
|
+
}
|
|
2549
|
+
}
|
|
2550
|
+
return changes;
|
|
2551
|
+
};
|
|
2552
|
+
const listUntrustedApiIdentityChanges = (projectRaw, effectiveRaw, trustedRaw) => {
|
|
2553
|
+
if (!projectRaw || typeof projectRaw !== "object" || Array.isArray(projectRaw)) return [];
|
|
2554
|
+
const projectProviders = projectRaw.providers;
|
|
2555
|
+
if (!projectProviders || typeof projectProviders !== "object" || Array.isArray(projectProviders)) {
|
|
2556
|
+
return [];
|
|
2557
|
+
}
|
|
2558
|
+
const changes = [];
|
|
2559
|
+
for (const [providerId, projectValue] of Object.entries(
|
|
2560
|
+
projectProviders
|
|
2561
|
+
)) {
|
|
2562
|
+
if (!projectValue || typeof projectValue !== "object" || Array.isArray(projectValue)) {
|
|
2563
|
+
continue;
|
|
2564
|
+
}
|
|
2565
|
+
const projectProvider = projectValue;
|
|
2566
|
+
const effectiveProviderValue = getRawProvider(effectiveRaw, providerId);
|
|
2567
|
+
const trustedProviderValue = getRawProvider(trustedRaw, providerId);
|
|
2568
|
+
if (!effectiveProviderValue || typeof effectiveProviderValue !== "object" || Array.isArray(effectiveProviderValue)) {
|
|
2569
|
+
continue;
|
|
2570
|
+
}
|
|
2571
|
+
const effectiveProvider = effectiveProviderValue;
|
|
2572
|
+
const trustedProvider = trustedProviderValue && typeof trustedProviderValue === "object" && !Array.isArray(trustedProviderValue) ? trustedProviderValue : {};
|
|
2573
|
+
const effectiveApi = effectiveProvider.api && typeof effectiveProvider.api === "object" && !Array.isArray(effectiveProvider.api) ? effectiveProvider.api : {};
|
|
2574
|
+
const trustedApi = trustedProvider.api && typeof trustedProvider.api === "object" && !Array.isArray(trustedProvider.api) ? trustedProvider.api : {};
|
|
2575
|
+
const projectApi = projectProvider.api && typeof projectProvider.api === "object" && !Array.isArray(projectProvider.api) ? projectProvider.api : {};
|
|
2576
|
+
const effectiveChannels = Array.isArray(effectiveProvider.channels) ? effectiveProvider.channels : [];
|
|
2577
|
+
const apiCanRun = effectiveProvider.transport === "api" || effectiveChannels.includes("api");
|
|
2578
|
+
if (!apiCanRun) continue;
|
|
2579
|
+
const fields = [];
|
|
2580
|
+
if (projectProvider.transport !== void 0 && effectiveProvider.transport === "api" && trustedProvider.transport !== "api") {
|
|
2581
|
+
fields.push("transport");
|
|
2582
|
+
}
|
|
2583
|
+
for (const field of ["base_url", "api_key_env_var"]) {
|
|
2584
|
+
if (projectApi[field] !== void 0 && stableJson(effectiveApi[field]) !== stableJson(trustedApi[field])) {
|
|
2585
|
+
fields.push(`api.${field}`);
|
|
2586
|
+
}
|
|
2587
|
+
}
|
|
2588
|
+
if (fields.length > 0) {
|
|
2589
|
+
changes.push({ providerId, fields });
|
|
2590
|
+
}
|
|
2591
|
+
}
|
|
2592
|
+
return changes;
|
|
2593
|
+
};
|
|
2594
|
+
const describeExecutionFieldChanges = (changes) => changes.map(({ providerId, fields }) => `${providerId} (${fields.join(", ")})`).join(", ");
|
|
2595
|
+
const buildUntrustedExecutionFieldError = (changes, root) => new Error(
|
|
2596
|
+
`Security: Project config changes provider execution fields (${describeExecutionFieldChanges(changes)}) which are not allowed unless BUILD_TRUST_PROJECT_PROVIDER_TEMPLATES names this canonical project root.
|
|
2597
|
+
|
|
2598
|
+
These fields can select the binary Build executes or installs, or redirect a credentialed API request, so a cloned repo could otherwise redirect a built-in provider to attacker-controlled code or infrastructure:
|
|
2599
|
+
- User config: ${getUserProviderRegistryPaths(root)[0]}
|
|
2600
|
+
- Project config: .build-project/config/providers.yaml (requires explicit trust)
|
|
2601
|
+
|
|
2602
|
+
Providers are trusted only when their normalized execution config matches the embedded template.
|
|
2603
|
+
|
|
2604
|
+
To trust only this project, run:
|
|
2605
|
+
` + projectTrustInstruction
|
|
2606
|
+
);
|
|
2607
|
+
const isAutoLoadedProjectRegistryPath = (candidatePath, root) => [
|
|
2608
|
+
resolveProvidersConfigPath({ cwd: root }),
|
|
2609
|
+
resolve5(root, ".build-project", "config", "provider-registry.yaml.v1.backup")
|
|
2610
|
+
].some((registryPath) => resolve5(registryPath) === resolve5(candidatePath));
|
|
2611
|
+
const embedded = loadEmbeddedRaw();
|
|
2612
|
+
if (!embedded) {
|
|
2613
|
+
throw new Error("Failed to load the provider catalog. Run the provider generator and retry.");
|
|
2614
|
+
}
|
|
2615
|
+
if (configPath) {
|
|
2616
|
+
const pathValidation = validateConfigPath(configPath, projectRoot, { allowTempDir: false });
|
|
2617
|
+
if (!pathValidation.isValid) {
|
|
2618
|
+
throw new Error(
|
|
2619
|
+
`Security Error: Invalid config path "${configPath}": ${pathValidation.reason}. Risk level: ${pathValidation.riskLevel}`
|
|
2620
|
+
);
|
|
2621
|
+
}
|
|
2622
|
+
const raw = loadYamlRawIfExists(pathValidation.normalizedPath);
|
|
2623
|
+
if (!raw) {
|
|
2624
|
+
throw new Error(
|
|
2625
|
+
`Failed to read unified provider config at ${pathValidation.normalizedPath}`
|
|
2626
|
+
);
|
|
2627
|
+
}
|
|
2628
|
+
const projectBuildDir = resolve5(projectRoot, ".build-project");
|
|
2629
|
+
const isProjectConfig = pathValidation.normalizedPath.startsWith(projectBuildDir + sep);
|
|
2630
|
+
if (isProjectConfig && isAutoLoadedProjectRegistryPath(pathValidation.normalizedPath, projectRoot) && !isTrustedProjectForProviderOverrides()) {
|
|
2631
|
+
const executionFieldChanges = listUntrustedExecutionFieldChanges(raw, embedded.raw);
|
|
2632
|
+
if (executionFieldChanges.length > 0) {
|
|
2633
|
+
throw buildUntrustedExecutionFieldError(executionFieldChanges, projectRoot);
|
|
2634
|
+
}
|
|
2635
|
+
}
|
|
2636
|
+
if (isProjectConfig && isAutoLoadedProjectRegistryPath(pathValidation.normalizedPath, projectRoot) && !isTrustedProjectForProviderOverrides()) {
|
|
2637
|
+
const apiIdentityChanges = listUntrustedApiIdentityChanges(raw, raw, embedded.raw);
|
|
2638
|
+
if (apiIdentityChanges.length > 0) {
|
|
2639
|
+
throw buildUntrustedExecutionFieldError(apiIdentityChanges, projectRoot);
|
|
2640
|
+
}
|
|
2641
|
+
}
|
|
2642
|
+
const withEnvOverrides2 = _ProviderRegistry.applyEnvOverrides(
|
|
2643
|
+
dropRemovedBuiltinProviders(ensureCursorIdSyntaxAdmissionPattern(raw))
|
|
2644
|
+
);
|
|
2645
|
+
const validated2 = _ProviderRegistry.parseRegistryConfig(withEnvOverrides2);
|
|
2646
|
+
return _ProviderRegistry.replaceCachedRegistry(
|
|
2647
|
+
validated2,
|
|
2648
|
+
pathValidation.normalizedPath,
|
|
2649
|
+
requestedCacheKey,
|
|
2650
|
+
"explicit",
|
|
2651
|
+
projectRoot,
|
|
2652
|
+
[pathValidation.normalizedPath]
|
|
2653
|
+
);
|
|
2654
|
+
}
|
|
2655
|
+
let mergedRaw = embedded.raw;
|
|
2656
|
+
const refresh = readEffectiveRefreshOverlay(projectRoot, {
|
|
2657
|
+
expectedBaseCatalogDigest: PROVIDER_CATALOG_SHA256,
|
|
2658
|
+
sourceBaseDrift: embedded.sourceBaseDrift
|
|
2659
|
+
});
|
|
2660
|
+
let appliedOverlayPath;
|
|
2661
|
+
if (refresh.disposition.status === "ready") {
|
|
2662
|
+
mergedRaw = applyRefreshOverlay(mergedRaw, refresh.disposition.overlay, refresh);
|
|
2663
|
+
appliedOverlayPath = refresh.path;
|
|
2664
|
+
} else if (refresh.disposition.status !== "absent") {
|
|
2665
|
+
debugLog(
|
|
2666
|
+
refresh.disposition.status === "degraded" ? refresh.disposition.warning : `Refresh overlay ignored: ${refresh.disposition.error}`
|
|
2667
|
+
);
|
|
2668
|
+
}
|
|
2669
|
+
let securityMergedRaw = mergedRaw;
|
|
2670
|
+
let trustedMergedRaw = mergedRaw;
|
|
2671
|
+
let loadedProjectRaw = null;
|
|
2672
|
+
let projectSelectionPolicy = null;
|
|
2673
|
+
const loadedConfigSources = [
|
|
2674
|
+
embedded.path,
|
|
2675
|
+
...appliedOverlayPath ? [appliedOverlayPath] : []
|
|
2676
|
+
];
|
|
2677
|
+
const projectConfigV2 = resolveProvidersConfigPath({ cwd: projectRoot });
|
|
2678
|
+
const projectConfigV1 = resolve5(
|
|
2679
|
+
projectRoot,
|
|
2680
|
+
".build-project",
|
|
2681
|
+
"config",
|
|
2682
|
+
"provider-registry.yaml.v1.backup"
|
|
2683
|
+
);
|
|
2684
|
+
const discoveredProjectConfigPath = existsSync5(projectConfigV2) ? projectConfigV2 : existsSync5(projectConfigV1) ? projectConfigV1 : null;
|
|
2685
|
+
const projectConfigPath = discoveredProjectConfigPath && resolve5(discoveredProjectConfigPath) !== resolve5(embedded.path) ? discoveredProjectConfigPath : null;
|
|
2686
|
+
let loadedConfigPath = embedded.path;
|
|
2687
|
+
if (projectConfigPath) {
|
|
2688
|
+
const configParentDir = resolve5(projectRoot, ".build-project", "config");
|
|
2689
|
+
if (!existsSync5(configParentDir)) {
|
|
2690
|
+
throw new Error(
|
|
2691
|
+
`Build not initialized: directory '${configParentDir}' does not exist.
|
|
2692
|
+
Run 'build init' to initialize Build in this project.`
|
|
2693
|
+
);
|
|
2694
|
+
}
|
|
2695
|
+
const pathValidation = validateConfigPath(projectConfigPath, projectRoot, {
|
|
2696
|
+
allowTempDir: false
|
|
2697
|
+
});
|
|
2698
|
+
if (!pathValidation.isValid) {
|
|
2699
|
+
throw new Error(
|
|
2700
|
+
`Security Error: Invalid config path "${projectConfigPath}": ${pathValidation.reason}. Risk level: ${pathValidation.riskLevel}`
|
|
2701
|
+
);
|
|
2702
|
+
}
|
|
2703
|
+
const projectRaw = loadYamlRawIfExists(pathValidation.normalizedPath);
|
|
2704
|
+
if (!projectRaw) {
|
|
2705
|
+
throw new Error(
|
|
2706
|
+
`Failed to read unified provider config at ${pathValidation.normalizedPath}`
|
|
2707
|
+
);
|
|
2708
|
+
}
|
|
2709
|
+
loadedProjectRaw = projectRaw;
|
|
2710
|
+
const projectIsTrusted = isTrustedProjectForProviderOverrides();
|
|
2711
|
+
securityMergedRaw = deepMerge(securityMergedRaw, projectRaw);
|
|
2712
|
+
if (!projectIsTrusted) {
|
|
2713
|
+
const executionFieldChanges = listUntrustedExecutionFieldChanges(projectRaw, embedded.raw);
|
|
2714
|
+
if (executionFieldChanges.length > 0) {
|
|
2715
|
+
throw buildUntrustedExecutionFieldError(executionFieldChanges, projectRoot);
|
|
2716
|
+
}
|
|
2717
|
+
}
|
|
2718
|
+
const projectedProjectRaw = projectProjectRegistryPolicy(projectRaw, embedded.raw, {
|
|
2719
|
+
trusted: projectIsTrusted
|
|
2720
|
+
});
|
|
2721
|
+
mergedRaw = deepMerge(mergedRaw, projectedProjectRaw);
|
|
2722
|
+
projectSelectionPolicy = pickProjectSelectionPolicy(projectedProjectRaw, embedded.raw);
|
|
2723
|
+
warnOverlaySettingsOnce({
|
|
2724
|
+
path: pathValidation.normalizedPath,
|
|
2725
|
+
raw: projectRaw,
|
|
2726
|
+
appliedRaw: projectedProjectRaw,
|
|
2727
|
+
embeddedRaw: embedded.raw,
|
|
2728
|
+
projectRoot
|
|
2729
|
+
});
|
|
2730
|
+
loadedConfigPath = pathValidation.normalizedPath;
|
|
2731
|
+
loadedConfigSources.push(pathValidation.normalizedPath);
|
|
2732
|
+
}
|
|
2733
|
+
let ignoredUserModelEntries = [];
|
|
2734
|
+
const userRegistryPaths = getUserProviderRegistryPaths(projectRoot);
|
|
2735
|
+
for (const [index, candidate] of userRegistryPaths.entries()) {
|
|
2736
|
+
const userRaw = loadYamlRawIfExists(candidate);
|
|
2737
|
+
if (userRaw) {
|
|
2738
|
+
warnOverlaySettingsOnce({ path: candidate, raw: userRaw, embeddedRaw: embedded.raw });
|
|
2739
|
+
const migratedUserOverlay = index > 0 ? migrateLegacyFullSnapshotOverlay(userRaw, mergedRaw) : userRaw;
|
|
2740
|
+
const merged = mergeUserModelEntries(migratedUserOverlay, mergedRaw, {
|
|
2741
|
+
validateEntry: listModelEntryIssues,
|
|
2742
|
+
sourcePath: candidate
|
|
2743
|
+
});
|
|
2744
|
+
const userOverlay = merged.overlay;
|
|
2745
|
+
ignoredUserModelEntries = merged.ignored;
|
|
2746
|
+
for (const ignored of merged.ignored) {
|
|
2747
|
+
emitWarning(
|
|
2748
|
+
"CFG-001",
|
|
2749
|
+
{ taskId: "provider-registry", subsystem: "config", executionPhase: "setup" },
|
|
2750
|
+
{
|
|
2751
|
+
severity: "WARN" /* WARN */,
|
|
2752
|
+
message: describeIgnoredUserModelEntry(ignored),
|
|
2753
|
+
metadata: { ...ignored, operation: "mergeUserModelEntries" }
|
|
2754
|
+
}
|
|
2755
|
+
);
|
|
2756
|
+
}
|
|
2757
|
+
mergedRaw = deepMerge(mergedRaw, userOverlay);
|
|
2758
|
+
securityMergedRaw = deepMerge(securityMergedRaw, userOverlay);
|
|
2759
|
+
trustedMergedRaw = deepMerge(trustedMergedRaw, userOverlay);
|
|
2760
|
+
loadedConfigSources.push(candidate);
|
|
2761
|
+
break;
|
|
2762
|
+
}
|
|
2763
|
+
}
|
|
2764
|
+
if (projectSelectionPolicy) mergedRaw = deepMerge(mergedRaw, projectSelectionPolicy);
|
|
2765
|
+
if (loadedProjectRaw && !isTrustedProjectForProviderOverrides()) {
|
|
2766
|
+
const apiIdentityChanges = listUntrustedApiIdentityChanges(
|
|
2767
|
+
loadedProjectRaw,
|
|
2768
|
+
securityMergedRaw,
|
|
2769
|
+
trustedMergedRaw
|
|
2770
|
+
);
|
|
2771
|
+
if (apiIdentityChanges.length > 0) {
|
|
2772
|
+
throw buildUntrustedExecutionFieldError(apiIdentityChanges, projectRoot);
|
|
2773
|
+
}
|
|
2774
|
+
}
|
|
2775
|
+
const withEnvOverrides = _ProviderRegistry.applyEnvOverrides(
|
|
2776
|
+
dropRemovedBuiltinProviders(ensureCursorIdSyntaxAdmissionPattern(mergedRaw))
|
|
2777
|
+
);
|
|
2778
|
+
const validated = _ProviderRegistry.parseRegistryConfig(withEnvOverrides);
|
|
2779
|
+
return _ProviderRegistry.replaceCachedRegistry(
|
|
2780
|
+
applyProviderEnableSwitches(validated, projectRoot),
|
|
2781
|
+
loadedConfigPath,
|
|
2782
|
+
requestedCacheKey,
|
|
2783
|
+
"implicit",
|
|
2784
|
+
projectRoot,
|
|
2785
|
+
loadedConfigSources,
|
|
2786
|
+
ignoredUserModelEntries
|
|
2787
|
+
);
|
|
2788
|
+
}
|
|
2789
|
+
/**
|
|
2790
|
+
* Resolve every live registry read through the same active-root view.
|
|
2791
|
+
*
|
|
2792
|
+
* A prior explicit-root load establishes which project this process is
|
|
2793
|
+
* serving. Rechecking that root on each read preserves file/environment
|
|
2794
|
+
* fingerprint invalidation without letting a later process.cwd() change
|
|
2795
|
+
* silently switch the live registry to another checkout.
|
|
2796
|
+
* Snapshot consumers use this same accessor to retain the model-decision root.
|
|
2797
|
+
*/
|
|
2798
|
+
static getActiveRegistry(registryOverride) {
|
|
2799
|
+
if (registryOverride) {
|
|
2800
|
+
return registryOverride;
|
|
2801
|
+
}
|
|
2802
|
+
if (!_ProviderRegistry.instance || !_ProviderRegistry.cacheProjectRoot) {
|
|
2803
|
+
return _ProviderRegistry.load();
|
|
2804
|
+
}
|
|
2805
|
+
if (_ProviderRegistry.cacheMode === "explicit" && _ProviderRegistry.configPath) {
|
|
2806
|
+
return _ProviderRegistry.load(_ProviderRegistry.configPath, _ProviderRegistry.cacheProjectRoot);
|
|
2807
|
+
}
|
|
2808
|
+
return _ProviderRegistry.load(void 0, _ProviderRegistry.cacheProjectRoot);
|
|
2809
|
+
}
|
|
2810
|
+
/**
|
|
2811
|
+
* Get configuration for a specific provider
|
|
2812
|
+
*
|
|
2813
|
+
* @param providerId - Provider identifier (e.g., 'claude', 'codex')
|
|
2814
|
+
* @returns Provider configuration with defaults applied
|
|
2815
|
+
*/
|
|
2816
|
+
static getProviderConfig(providerId, registryOverride) {
|
|
2817
|
+
const registry = _ProviderRegistry.getActiveRegistry(registryOverride);
|
|
2818
|
+
const normalizedProviderId = normalizeProviderConfigId(providerId);
|
|
2819
|
+
const providerConfig = registry.providers[providerId] ?? registry.providers[normalizedProviderId];
|
|
2820
|
+
if (!providerConfig) {
|
|
2821
|
+
const availableProviders = Object.values(registry.providers).filter((provider) => provider.enabled).sort((a, b) => a.order - b.order).map((provider) => provider.id).join(", ");
|
|
2822
|
+
throw new Error(
|
|
2823
|
+
`Provider '${providerId}' not found in unified config. Available providers: ${availableProviders}`
|
|
2824
|
+
);
|
|
2825
|
+
}
|
|
2826
|
+
return cloneProviderRegistryValue(providerConfig);
|
|
2827
|
+
}
|
|
2828
|
+
/**
|
|
2829
|
+
* Get all provider IDs
|
|
2830
|
+
*
|
|
2831
|
+
* @returns Array of provider IDs
|
|
2832
|
+
*/
|
|
2833
|
+
static getAllProviderIds() {
|
|
2834
|
+
const registry = _ProviderRegistry.getActiveRegistry();
|
|
2835
|
+
return Object.keys(registry.providers);
|
|
2836
|
+
}
|
|
2837
|
+
/**
|
|
2838
|
+
* Get all enabled providers
|
|
2839
|
+
*
|
|
2840
|
+
* @returns Array of enabled provider configurations
|
|
2841
|
+
*/
|
|
2842
|
+
static getEnabledProviders(registryOverride) {
|
|
2843
|
+
const registry = _ProviderRegistry.getActiveRegistry(registryOverride);
|
|
2844
|
+
return Object.values(registry.providers).filter((p) => p.enabled).sort((a, b) => a.order - b.order);
|
|
2845
|
+
}
|
|
2846
|
+
/**
|
|
2847
|
+
* Registry-owned provider family for judge independence. Falls back to
|
|
2848
|
+
* `vendor` for overlay/custom providers, then to the provider id.
|
|
2849
|
+
*/
|
|
2850
|
+
static getProviderFamily(providerId, registryOverride) {
|
|
2851
|
+
return getProviderFamily(providerId, registryOverride);
|
|
2852
|
+
}
|
|
2853
|
+
/** Registry-owned judge-capability facts. Unknown providers fail closed. */
|
|
2854
|
+
static getJudgeCapabilities(providerId) {
|
|
2855
|
+
return getJudgeCapabilities(providerId);
|
|
2856
|
+
}
|
|
2857
|
+
/** The provider's `models.judge_reasoning_effort`; undefined when unset or unknown. */
|
|
2858
|
+
static getJudgeReasoningEffort(providerId, registryOverride) {
|
|
2859
|
+
const registry = _ProviderRegistry.getActiveRegistry(registryOverride);
|
|
2860
|
+
const provider = registry.providers[providerId] ?? registry.providers[normalizeProviderConfigId(providerId)];
|
|
2861
|
+
return provider?.models.judge_reasoning_effort;
|
|
2862
|
+
}
|
|
2863
|
+
/**
|
|
2864
|
+
* Check if a provider is enabled
|
|
2865
|
+
*
|
|
2866
|
+
* @param providerId - Provider identifier
|
|
2867
|
+
* @returns True if provider exists and is enabled
|
|
2868
|
+
*/
|
|
2869
|
+
static isProviderEnabled(providerId) {
|
|
2870
|
+
const registry = _ProviderRegistry.getActiveRegistry();
|
|
2871
|
+
const normalizedProviderId = normalizeProviderConfigId(providerId);
|
|
2872
|
+
const providerConfig = registry.providers[providerId] ?? registry.providers[normalizedProviderId];
|
|
2873
|
+
return providerConfig?.enabled || false;
|
|
2874
|
+
}
|
|
2875
|
+
/**
|
|
2876
|
+
* Report the source path the currently-cached registry was actually loaded
|
|
2877
|
+
* from.
|
|
2878
|
+
*
|
|
2879
|
+
* This is the coherent provenance signal: when the project providers.yaml is
|
|
2880
|
+
* absent and `load()` falls back to the embedded template seed, this returns
|
|
2881
|
+
* the embedded template path that was actually used — NOT the nonexistent
|
|
2882
|
+
* project `.build-project/config/providers.yaml` path. Diagnostics and logs should
|
|
2883
|
+
* read this instead of recomputing the project path (e.g. via
|
|
2884
|
+
* `resolveProvidersConfigPath`), which would falsely claim a project registry
|
|
2885
|
+
* that is not present on disk.
|
|
2886
|
+
*
|
|
2887
|
+
* Returns `null` when no registry has been loaded yet in this process.
|
|
2888
|
+
*
|
|
2889
|
+
* @returns Absolute path of the loaded registry source, or `null`.
|
|
2890
|
+
*/
|
|
2891
|
+
static getLoadedConfigPath() {
|
|
2892
|
+
return _ProviderRegistry.configPath;
|
|
2893
|
+
}
|
|
2894
|
+
/**
|
|
2895
|
+
* Report every source that contributed to the currently-cached registry,
|
|
2896
|
+
* ordered from lowest to highest precedence.
|
|
2897
|
+
*/
|
|
2898
|
+
static getLoadedConfigSources() {
|
|
2899
|
+
return [..._ProviderRegistry.configSources];
|
|
2900
|
+
}
|
|
2901
|
+
/** User model entries the loaded registry ignored as invalid. */
|
|
2902
|
+
static getIgnoredUserModelEntries() {
|
|
2903
|
+
return [..._ProviderRegistry.ignoredUserModelEntries];
|
|
2904
|
+
}
|
|
2905
|
+
/** The ignored entries as report lines, or undefined when there are none. */
|
|
2906
|
+
static describeIgnoredUserModelEntries() {
|
|
2907
|
+
const lines = _ProviderRegistry.ignoredUserModelEntries.map(describeIgnoredUserModelEntry);
|
|
2908
|
+
return lines.length > 0 ? lines.join("\n") : void 0;
|
|
2909
|
+
}
|
|
2910
|
+
/**
|
|
2911
|
+
* Force reload configuration from disk
|
|
2912
|
+
* Useful for testing or when config file has been modified
|
|
2913
|
+
*/
|
|
2914
|
+
/**
|
|
2915
|
+
* Per-provider `concurrency.max` set in USER-scope provider config only.
|
|
2916
|
+
*
|
|
2917
|
+
* Deliberately NOT read through `getProviderConfig()`. That returns the merged
|
|
2918
|
+
* embedded < project < user view, and `concurrency` is in
|
|
2919
|
+
* PROJECT_POLICY_PROVIDER_FIELDS — a list retained even for UNTRUSTED project
|
|
2920
|
+
* snapshots — so a cloned repository's `.build-project/config/providers.yaml` can set
|
|
2921
|
+
* it. The orchestrator raises how many provider processes actually run from
|
|
2922
|
+
* this value, spending the operator's host resources and account quota, so it
|
|
2923
|
+
* must come from config the operator owns. A project may still ship a lower
|
|
2924
|
+
* value for its own planning; it just cannot raise process concurrency.
|
|
2925
|
+
*
|
|
2926
|
+
* Returns raw declared maxima without validation or clamping; the caller owns
|
|
2927
|
+
* normalization and correctness ceilings. Unreadable or malformed user config
|
|
2928
|
+
* yields an empty map rather than failing the run: the shipped baseline is
|
|
2929
|
+
* always a safe fallback.
|
|
2930
|
+
*/
|
|
2931
|
+
static getUserScopeProviderConcurrencyMax(cwd = process.cwd()) {
|
|
2932
|
+
const projectRoot = findProjectRoot(cwd) ?? cwd;
|
|
2933
|
+
const result = {};
|
|
2934
|
+
for (const candidate of getUserProviderRegistryPaths(projectRoot)) {
|
|
2935
|
+
if (!existsSync5(candidate)) continue;
|
|
2936
|
+
let raw;
|
|
2937
|
+
try {
|
|
2938
|
+
raw = yaml.load(readFileSync8(candidate, "utf-8"));
|
|
2939
|
+
} catch {
|
|
2940
|
+
return {};
|
|
2941
|
+
}
|
|
2942
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
|
|
2943
|
+
continue;
|
|
2944
|
+
}
|
|
2945
|
+
const providers = raw.providers;
|
|
2946
|
+
if (!providers || typeof providers !== "object" || Array.isArray(providers)) {
|
|
2947
|
+
return result;
|
|
2948
|
+
}
|
|
2949
|
+
for (const [providerId, providerValue] of Object.entries(
|
|
2950
|
+
providers
|
|
2951
|
+
)) {
|
|
2952
|
+
if (!providerValue || typeof providerValue !== "object" || Array.isArray(providerValue)) {
|
|
2953
|
+
continue;
|
|
2954
|
+
}
|
|
2955
|
+
const concurrency = providerValue.concurrency;
|
|
2956
|
+
if (!concurrency || typeof concurrency !== "object" || Array.isArray(concurrency)) {
|
|
2957
|
+
continue;
|
|
2958
|
+
}
|
|
2959
|
+
const max = concurrency.max;
|
|
2960
|
+
if (typeof max === "number" && Number.isFinite(max)) {
|
|
2961
|
+
result[providerId] = max;
|
|
2962
|
+
}
|
|
2963
|
+
}
|
|
2964
|
+
return result;
|
|
2965
|
+
}
|
|
2966
|
+
return result;
|
|
2967
|
+
}
|
|
2968
|
+
static reload() {
|
|
2969
|
+
_ProviderRegistry.instance = null;
|
|
2970
|
+
_ProviderRegistry.configPath = null;
|
|
2971
|
+
_ProviderRegistry.configSources = [];
|
|
2972
|
+
_ProviderRegistry.ignoredUserModelEntries = [];
|
|
2973
|
+
_ProviderRegistry.cacheKey = null;
|
|
2974
|
+
_ProviderRegistry.cacheMode = null;
|
|
2975
|
+
_ProviderRegistry.cacheProjectRoot = null;
|
|
2976
|
+
runProviderRegistryReloadInvalidators();
|
|
2977
|
+
}
|
|
2978
|
+
static buildEnvOverrideCacheKey() {
|
|
2979
|
+
return fingerprintEnvironment(
|
|
2980
|
+
{ ...process.env, ...getExecutionContext().envOverrides },
|
|
2981
|
+
(name) => name.startsWith("BUILD_PROVIDER_") || /^BUILD_\w+_ENABLED$/.test(name) || // provider-enable-switches.ts inputs
|
|
2982
|
+
[
|
|
2983
|
+
"BUILD_TRUST_PROJECT_PROVIDER_TEMPLATES",
|
|
2984
|
+
"BUILD_CONFIG_DIR",
|
|
2985
|
+
"BUILD_DATA_DIR",
|
|
2986
|
+
"BUILD_HOME",
|
|
2987
|
+
"XDG_DATA_HOME",
|
|
2988
|
+
"BUILD_MODEL_REFRESH_CONTEXT",
|
|
2989
|
+
"AWS_PROFILE",
|
|
2990
|
+
"AWS_REGION",
|
|
2991
|
+
"AWS_DEFAULT_REGION",
|
|
2992
|
+
"GOOGLE_CLOUD_PROJECT",
|
|
2993
|
+
"CLOUD_ML_REGION",
|
|
2994
|
+
"CODEX_HOME",
|
|
2995
|
+
"CLAUDE_CONFIG_DIR",
|
|
2996
|
+
"XDG_CONFIG_HOME",
|
|
2997
|
+
"HOME",
|
|
2998
|
+
"USERPROFILE"
|
|
2999
|
+
].includes(name)
|
|
3000
|
+
);
|
|
3001
|
+
}
|
|
3002
|
+
static buildCacheKey(configPath, envKey, projectRoot) {
|
|
3003
|
+
if (configPath) {
|
|
3004
|
+
return combineCacheFingerprints(
|
|
3005
|
+
`path:${resolve5(configPath)}`,
|
|
3006
|
+
`root:${projectRoot}`,
|
|
3007
|
+
envKey,
|
|
3008
|
+
fingerprintFiles([configPath])
|
|
3009
|
+
);
|
|
3010
|
+
}
|
|
3011
|
+
return combineCacheFingerprints(
|
|
3012
|
+
`root:${projectRoot}`,
|
|
3013
|
+
envKey,
|
|
3014
|
+
enableSwitchCacheKey(projectRoot),
|
|
3015
|
+
fingerprintFiles(getProviderRegistryInputPaths(projectRoot))
|
|
3016
|
+
);
|
|
3017
|
+
}
|
|
3018
|
+
static canReuseExplicitCacheForImplicit(configPath, projectRoot) {
|
|
3019
|
+
return resolve5(configPath) !== resolveProvidersConfigPath({ cwd: projectRoot });
|
|
3020
|
+
}
|
|
3021
|
+
/**
|
|
3022
|
+
* Apply environment variable overrides
|
|
3023
|
+
* Supports: BUILD_PROVIDER_<ID>_<KEY>=value
|
|
3024
|
+
*
|
|
3025
|
+
* Examples:
|
|
3026
|
+
* - BUILD_PROVIDER_CODEX_TIMEOUT_MS=900000
|
|
3027
|
+
* - BUILD_PROVIDER_CLAUDE_ENABLED=false
|
|
3028
|
+
* - BUILD_PROVIDER_GEMINI_MODELS_DEFAULT=gemini-2.5-flash
|
|
3029
|
+
*
|
|
3030
|
+
* @param config - Parsed YAML configuration
|
|
3031
|
+
* @returns Configuration with environment overrides applied
|
|
3032
|
+
*/
|
|
3033
|
+
static applyEnvOverrides(config) {
|
|
3034
|
+
if (!config || typeof config !== "object") {
|
|
3035
|
+
return config;
|
|
3036
|
+
}
|
|
3037
|
+
const result = cloneProviderRegistryValue(config);
|
|
3038
|
+
const runtimeEnv2 = {
|
|
3039
|
+
...process.env,
|
|
3040
|
+
...getExecutionContext().envOverrides
|
|
3041
|
+
};
|
|
3042
|
+
for (const [key, value] of Object.entries(runtimeEnv2)) {
|
|
3043
|
+
if (!key.startsWith("BUILD_PROVIDER_")) {
|
|
3044
|
+
continue;
|
|
3045
|
+
}
|
|
3046
|
+
if (getEnvVarEntry(key)) {
|
|
3047
|
+
continue;
|
|
3048
|
+
}
|
|
3049
|
+
const overrideName = key.substring("BUILD_PROVIDER_".length);
|
|
3050
|
+
if (!overrideName.includes("_")) {
|
|
3051
|
+
continue;
|
|
3052
|
+
}
|
|
3053
|
+
const providers = result.providers;
|
|
3054
|
+
const providerEntries = providers && typeof providers === "object" ? Object.keys(providers) : [];
|
|
3055
|
+
const providerId = providerEntries.filter((id) => overrideName.startsWith(`${id.toUpperCase()}_`)).sort((a, b) => b.length - a.length)[0];
|
|
3056
|
+
if (!providerId) {
|
|
3057
|
+
const claimedProvider = overrideName.split("_")[0]?.toLowerCase() ?? overrideName;
|
|
3058
|
+
throw new InvalidExplicitConfigError(
|
|
3059
|
+
`Environment variable ${key} targets unknown provider '${claimedProvider}'.`
|
|
3060
|
+
);
|
|
3061
|
+
}
|
|
3062
|
+
const configKey = overrideName.slice(providerId.length + 1).toLowerCase();
|
|
3063
|
+
const providerConfig = providers[providerId];
|
|
3064
|
+
if (providerConfig && typeof providerConfig === "object") {
|
|
3065
|
+
_ProviderRegistry.setNestedValue(
|
|
3066
|
+
providerConfig,
|
|
3067
|
+
configKey,
|
|
3068
|
+
String(value ?? ""),
|
|
3069
|
+
key
|
|
3070
|
+
);
|
|
3071
|
+
}
|
|
3072
|
+
}
|
|
3073
|
+
return result;
|
|
3074
|
+
}
|
|
3075
|
+
static dynamicProviderOverrideKeys() {
|
|
3076
|
+
const runtimeEnv2 = {
|
|
3077
|
+
...process.env,
|
|
3078
|
+
...getExecutionContext().envOverrides
|
|
3079
|
+
};
|
|
3080
|
+
return Object.keys(runtimeEnv2).filter((key) => {
|
|
3081
|
+
if (!key.startsWith("BUILD_PROVIDER_") || getEnvVarEntry(key)) return false;
|
|
3082
|
+
return key.substring("BUILD_PROVIDER_".length).includes("_");
|
|
3083
|
+
});
|
|
3084
|
+
}
|
|
3085
|
+
static parseRegistryConfig(config) {
|
|
3086
|
+
try {
|
|
3087
|
+
return ProviderRegistryConfigSchema.parse(config);
|
|
3088
|
+
} catch (error) {
|
|
3089
|
+
if (error instanceof z3.ZodError) {
|
|
3090
|
+
const issues = error.issues.map((issue) => ` - ${issue.path.join(".")}: ${issue.message}`).join("\n");
|
|
3091
|
+
const overrideKeys = _ProviderRegistry.dynamicProviderOverrideKeys();
|
|
3092
|
+
if (overrideKeys.length > 0) {
|
|
3093
|
+
throw new InvalidExplicitConfigError(
|
|
3094
|
+
`Invalid provider environment override (${overrideKeys.join(", ")}):
|
|
3095
|
+
${issues}`,
|
|
3096
|
+
error
|
|
3097
|
+
);
|
|
3098
|
+
}
|
|
3099
|
+
throw new Error(`Unified provider config validation failed:
|
|
3100
|
+
${issues}`);
|
|
3101
|
+
}
|
|
3102
|
+
if (error instanceof TypeError && error.message.includes("_zod")) {
|
|
3103
|
+
throw new Error(
|
|
3104
|
+
`Schema validation failed due to undefined nested schema. This typically indicates incorrect Zod v4 syntax (e.g., z.record() requires two parameters). Original error: ${error.message}
|
|
3105
|
+
|
|
3106
|
+
Fix: Change z.record(z.string()) to z.record(z.string(), z.string()) in schema definitions.`
|
|
3107
|
+
);
|
|
3108
|
+
}
|
|
3109
|
+
throw error;
|
|
3110
|
+
}
|
|
3111
|
+
}
|
|
3112
|
+
/**
|
|
3113
|
+
* Set a nested value in an object using underscore notation
|
|
3114
|
+
*
|
|
3115
|
+
* @param obj - Object to modify
|
|
3116
|
+
* @param path - Underscore-separated path (TIMEOUT_MS -> timeout_ms, MODELS_DEFAULT -> models.default)
|
|
3117
|
+
* @param value - Value to set
|
|
3118
|
+
*/
|
|
3119
|
+
static setNestedValue(obj, path5, value, envKey) {
|
|
3120
|
+
const normalizedPath = path5.toLowerCase();
|
|
3121
|
+
if (normalizedPath in obj) {
|
|
3122
|
+
obj[normalizedPath] = _ProviderRegistry.canonicalizeLegacyApiOverride(
|
|
3123
|
+
normalizedPath,
|
|
3124
|
+
_ProviderRegistry.coerceOverrideValue(value, obj[normalizedPath], envKey)
|
|
3125
|
+
);
|
|
3126
|
+
return;
|
|
3127
|
+
}
|
|
3128
|
+
const parts = normalizedPath.split("_");
|
|
3129
|
+
if (parts[0] === "models" && parts.length > 1) {
|
|
3130
|
+
if (typeof obj.models !== "object" || obj.models === null || Array.isArray(obj.models)) {
|
|
3131
|
+
obj.models = {};
|
|
3132
|
+
}
|
|
3133
|
+
const nestedPath = parts.slice(1).join("_");
|
|
3134
|
+
if (nestedPath === "default" && !("default" in obj.models)) {
|
|
3135
|
+
obj.models.default = value;
|
|
3136
|
+
return;
|
|
3137
|
+
}
|
|
3138
|
+
_ProviderRegistry.setNestedValue(
|
|
3139
|
+
obj.models,
|
|
3140
|
+
nestedPath,
|
|
3141
|
+
value,
|
|
3142
|
+
envKey
|
|
3143
|
+
);
|
|
3144
|
+
return;
|
|
3145
|
+
}
|
|
3146
|
+
for (let i = 1; i < parts.length; i++) {
|
|
3147
|
+
const firstKey = parts.slice(0, i).join("_");
|
|
3148
|
+
const restKey = parts.slice(i).join("_");
|
|
3149
|
+
if (firstKey in obj && typeof obj[firstKey] === "object" && obj[firstKey] !== null) {
|
|
3150
|
+
_ProviderRegistry.setNestedValue(
|
|
3151
|
+
obj[firstKey],
|
|
3152
|
+
restKey,
|
|
3153
|
+
value,
|
|
3154
|
+
envKey
|
|
3155
|
+
);
|
|
3156
|
+
return;
|
|
3157
|
+
}
|
|
3158
|
+
}
|
|
3159
|
+
throw new InvalidExplicitConfigError(
|
|
3160
|
+
`Environment variable ${envKey} targets unknown provider configuration key '${normalizedPath}'.`
|
|
3161
|
+
);
|
|
3162
|
+
}
|
|
3163
|
+
/**
|
|
3164
|
+
* Keep legacy API-shaped env overrides parseable as `api` rather than
|
|
3165
|
+
* converting them to CLI or letting mixed-case `API` fail as a generic
|
|
3166
|
+
* enum/array validation error. Selection still fails closed later.
|
|
3167
|
+
*/
|
|
3168
|
+
static canonicalizeLegacyApiOverride(path5, value) {
|
|
3169
|
+
if (typeof value !== "string" || value.trim().toLowerCase() !== "api") {
|
|
3170
|
+
return value;
|
|
3171
|
+
}
|
|
3172
|
+
if (path5 === "transport") {
|
|
3173
|
+
return "api";
|
|
3174
|
+
}
|
|
3175
|
+
if (path5 === "channels") {
|
|
3176
|
+
return ["api"];
|
|
3177
|
+
}
|
|
3178
|
+
return value;
|
|
3179
|
+
}
|
|
3180
|
+
/**
|
|
3181
|
+
* Parse environment variable value to appropriate type
|
|
3182
|
+
*
|
|
3183
|
+
* @param value - String value from environment
|
|
3184
|
+
* @returns Parsed value (boolean, number, or string)
|
|
3185
|
+
*/
|
|
3186
|
+
static coerceOverrideValue(value, destination, envKey) {
|
|
3187
|
+
if (typeof destination === "boolean") {
|
|
3188
|
+
const normalized = value.trim().toLowerCase();
|
|
3189
|
+
if (["1", "true", "yes", "on"].includes(normalized)) return true;
|
|
3190
|
+
if (["0", "false", "no", "off"].includes(normalized)) return false;
|
|
3191
|
+
throw new InvalidExplicitConfigError(
|
|
3192
|
+
`Environment variable ${envKey} must be a boolean (true/false, yes/no, on/off, or 1/0).`
|
|
3193
|
+
);
|
|
3194
|
+
}
|
|
3195
|
+
if (typeof destination === "number") {
|
|
3196
|
+
const numeric = Number(value);
|
|
3197
|
+
if (Number.isFinite(numeric)) return numeric;
|
|
3198
|
+
throw new InvalidExplicitConfigError(
|
|
3199
|
+
`Environment variable ${envKey} must be a finite number.`
|
|
3200
|
+
);
|
|
3201
|
+
}
|
|
3202
|
+
return value;
|
|
3203
|
+
}
|
|
3204
|
+
/**
|
|
3205
|
+
* Get global defaults
|
|
3206
|
+
*
|
|
3207
|
+
* @returns Global defaults configuration
|
|
3208
|
+
*/
|
|
3209
|
+
static getDefaults() {
|
|
3210
|
+
const registry = _ProviderRegistry.getActiveRegistry();
|
|
3211
|
+
return registry.defaults;
|
|
3212
|
+
}
|
|
3213
|
+
/**
|
|
3214
|
+
* Get configuration metadata
|
|
3215
|
+
*
|
|
3216
|
+
* @returns Configuration metadata
|
|
3217
|
+
*/
|
|
3218
|
+
static getMetadata() {
|
|
3219
|
+
const registry = _ProviderRegistry.getActiveRegistry();
|
|
3220
|
+
return registry.metadata;
|
|
3221
|
+
}
|
|
3222
|
+
/**
|
|
3223
|
+
* Resolve a model name for a specific provider
|
|
3224
|
+
* Applies model mappings and validates against allowed patterns
|
|
3225
|
+
*
|
|
3226
|
+
* @param providerId - Provider identifier
|
|
3227
|
+
* @param model - Model name to resolve (may be generic like 'gpt-4')
|
|
3228
|
+
* @returns Resolved provider-specific model name
|
|
3229
|
+
*/
|
|
3230
|
+
static resolveModel(providerId, model, registryOverride) {
|
|
3231
|
+
const config = _ProviderRegistry.getProviderConfig(providerId, registryOverride);
|
|
3232
|
+
const trimmedModel = !model || model.trim() === "" ? config.models.default : model.trim();
|
|
3233
|
+
if (trimmedModel in config.models.mappings) {
|
|
3234
|
+
const mapped = config.models.mappings[trimmedModel];
|
|
3235
|
+
if (mapped !== void 0) {
|
|
3236
|
+
return mapped;
|
|
3237
|
+
}
|
|
3238
|
+
}
|
|
3239
|
+
if (declaresFamilyAlias(config.models.family_aliases, trimmedModel)) {
|
|
3240
|
+
return trimmedModel;
|
|
3241
|
+
}
|
|
3242
|
+
for (const pattern of config.models.allowed_patterns) {
|
|
3243
|
+
let regex;
|
|
3244
|
+
try {
|
|
3245
|
+
regex = new RegExp(pattern);
|
|
3246
|
+
} catch (error) {
|
|
3247
|
+
debugLog(
|
|
3248
|
+
`Skipping invalid allowed_patterns regex for provider '${providerId}': ${pattern} (${error instanceof Error ? error.message : String(error)})`
|
|
3249
|
+
);
|
|
3250
|
+
continue;
|
|
3251
|
+
}
|
|
3252
|
+
if (regex.test(trimmedModel)) {
|
|
3253
|
+
return trimmedModel;
|
|
3254
|
+
}
|
|
3255
|
+
}
|
|
3256
|
+
const availableModels = config.models.available.map((info) => info.id);
|
|
3257
|
+
if (availableModels.includes(trimmedModel)) {
|
|
3258
|
+
return trimmedModel;
|
|
3259
|
+
}
|
|
3260
|
+
const offered = offeredModelIds(config.models);
|
|
3261
|
+
const validModels = offered.length > 0 ? offered.join(", ") : "None";
|
|
3262
|
+
const validPatterns = config.models.allowed_patterns.length > 0 ? config.models.allowed_patterns.join(", ") : "None";
|
|
3263
|
+
const registrySources = !registryOverride || registryOverride === _ProviderRegistry.instance ? _ProviderRegistry.getLoadedConfigSources() : [];
|
|
3264
|
+
const sourceDetail = registrySources.length > 0 ? ` Registry sources: ${registrySources.join(", ")}.` : "";
|
|
3265
|
+
throw new Error(
|
|
3266
|
+
`Model '${trimmedModel}' is not available for provider '${providerId}'. Available models: ${validModels}. Allowed patterns: ${validPatterns}.${sourceDetail}`
|
|
3267
|
+
);
|
|
3268
|
+
}
|
|
3269
|
+
/**
|
|
3270
|
+
* Get timeout for a specific provider
|
|
3271
|
+
*
|
|
3272
|
+
* @param providerId - Provider identifier
|
|
3273
|
+
* @returns Timeout in milliseconds
|
|
3274
|
+
*/
|
|
3275
|
+
static getTimeout(providerId) {
|
|
3276
|
+
const config = _ProviderRegistry.getProviderConfig(providerId);
|
|
3277
|
+
return config.timeout_ms;
|
|
3278
|
+
}
|
|
3279
|
+
/**
|
|
3280
|
+
* Get pricing configuration for a specific provider
|
|
3281
|
+
*
|
|
3282
|
+
* @param providerId - Provider identifier
|
|
3283
|
+
* @returns Pricing configuration if available, undefined otherwise
|
|
3284
|
+
*/
|
|
3285
|
+
static getProviderPricing(providerId) {
|
|
3286
|
+
const config = _ProviderRegistry.getProviderConfig(providerId);
|
|
3287
|
+
return config.pricing;
|
|
3288
|
+
}
|
|
3289
|
+
/**
|
|
3290
|
+
* Get model pricing for a specific provider and model
|
|
3291
|
+
*
|
|
3292
|
+
* @param providerId - Provider identifier
|
|
3293
|
+
* @param modelId - Model identifier
|
|
3294
|
+
* @returns Model pricing if available, undefined otherwise
|
|
3295
|
+
*/
|
|
3296
|
+
static getModelPricing(providerId, modelId) {
|
|
3297
|
+
const pricing = _ProviderRegistry.getProviderPricing(providerId);
|
|
3298
|
+
if (!pricing || !pricing.models) return void 0;
|
|
3299
|
+
return pricing.models[modelId];
|
|
3300
|
+
}
|
|
3301
|
+
/**
|
|
3302
|
+
* Resolve provider ID from model name using allowed_patterns
|
|
3303
|
+
*
|
|
3304
|
+
* @param model - Model name (e.g., 'gemini-2.5-flash', 'sonnet-4-5')
|
|
3305
|
+
* @param registryOverride - Optional registry snapshot; defaults to the active registry
|
|
3306
|
+
* @returns Provider ID if model matches a pattern, undefined otherwise
|
|
3307
|
+
*/
|
|
3308
|
+
static resolveProviderByModel(model, registryOverride) {
|
|
3309
|
+
if (!model) return void 0;
|
|
3310
|
+
const registry = _ProviderRegistry.getActiveRegistry(registryOverride);
|
|
3311
|
+
const isNonAuthoritativeOwnershipPattern = (pattern) => {
|
|
3312
|
+
const normalized = pattern.trim();
|
|
3313
|
+
return normalized === ".*" || normalized === "^.*$" || normalized === CURSOR_ID_SYNTAX_ADMISSION_PATTERN;
|
|
3314
|
+
};
|
|
3315
|
+
const matches = [];
|
|
3316
|
+
for (const [providerId, provider] of Object.entries(registry.providers)) {
|
|
3317
|
+
if (!provider.enabled) continue;
|
|
3318
|
+
const patterns = provider.models.allowed_patterns || [];
|
|
3319
|
+
let providerMatched = false;
|
|
3320
|
+
for (const pattern of patterns) {
|
|
3321
|
+
try {
|
|
3322
|
+
const regex = new RegExp(pattern, "i");
|
|
3323
|
+
if (regex.test(model)) {
|
|
3324
|
+
if (isNonAuthoritativeOwnershipPattern(pattern)) {
|
|
3325
|
+
continue;
|
|
3326
|
+
}
|
|
3327
|
+
providerMatched = true;
|
|
3328
|
+
break;
|
|
3329
|
+
}
|
|
3330
|
+
} catch (error) {
|
|
3331
|
+
emitWarning(
|
|
3332
|
+
"CFG-003",
|
|
3333
|
+
{
|
|
3334
|
+
taskId: "provider-registry",
|
|
3335
|
+
subsystem: "config",
|
|
3336
|
+
executionPhase: "setup"
|
|
3337
|
+
},
|
|
3338
|
+
{
|
|
3339
|
+
severity: "WARN" /* WARN */,
|
|
3340
|
+
metadata: {
|
|
3341
|
+
providerId,
|
|
3342
|
+
pattern,
|
|
3343
|
+
error: error instanceof Error ? error.message : String(error),
|
|
3344
|
+
operation: "resolveProviderByModel"
|
|
3345
|
+
}
|
|
3346
|
+
}
|
|
3347
|
+
);
|
|
3348
|
+
}
|
|
3349
|
+
}
|
|
3350
|
+
if (providerMatched) {
|
|
3351
|
+
matches.push(providerId);
|
|
3352
|
+
}
|
|
3353
|
+
}
|
|
3354
|
+
if (matches.length === 1) {
|
|
3355
|
+
return matches[0];
|
|
3356
|
+
}
|
|
3357
|
+
return void 0;
|
|
3358
|
+
}
|
|
3359
|
+
/**
|
|
3360
|
+
* Get options for a specific provider
|
|
3361
|
+
*
|
|
3362
|
+
* @param providerId - Provider identifier
|
|
3363
|
+
* @returns Provider options, or empty object if none defined
|
|
3364
|
+
*/
|
|
3365
|
+
static getProviderOptions(providerId) {
|
|
3366
|
+
const config = _ProviderRegistry.getProviderConfig(providerId);
|
|
3367
|
+
return config.options || {};
|
|
3368
|
+
}
|
|
3369
|
+
/**
|
|
3370
|
+
* Get requirements for a specific provider
|
|
3371
|
+
*
|
|
3372
|
+
* @param providerId - Provider identifier
|
|
3373
|
+
* @returns Provider requirements with both unconditional and conditional deps
|
|
3374
|
+
*/
|
|
3375
|
+
static getProviderRequirements(providerId) {
|
|
3376
|
+
const config = _ProviderRegistry.getProviderConfig(providerId);
|
|
3377
|
+
return {
|
|
3378
|
+
requires: config.requires || [],
|
|
3379
|
+
requires_if: config.requires_if || {}
|
|
3380
|
+
};
|
|
3381
|
+
}
|
|
3382
|
+
/**
|
|
3383
|
+
* Get a specific option by key from a provider
|
|
3384
|
+
*
|
|
3385
|
+
* @param providerId - Provider identifier
|
|
3386
|
+
* @param optionKey - Option key
|
|
3387
|
+
* @returns Provider option if found, undefined otherwise
|
|
3388
|
+
*/
|
|
3389
|
+
static getOption(providerId, optionKey) {
|
|
3390
|
+
const options = _ProviderRegistry.getProviderOptions(providerId);
|
|
3391
|
+
return options[optionKey];
|
|
3392
|
+
}
|
|
3393
|
+
/**
|
|
3394
|
+
* Get the default model for a provider, from static registry config.
|
|
3395
|
+
* For runtime-observed defaults, use provider-specific discovery.
|
|
3396
|
+
*
|
|
3397
|
+
* @param providerId - Provider identifier
|
|
3398
|
+
* @returns Default model ID, or undefined if not configured
|
|
3399
|
+
*/
|
|
3400
|
+
static getDefaultModel(providerId, registryOverride) {
|
|
3401
|
+
const config = _ProviderRegistry.getProviderConfig(providerId, registryOverride);
|
|
3402
|
+
return config.models.default || void 0;
|
|
3403
|
+
}
|
|
3404
|
+
/**
|
|
3405
|
+
* Get a model assigned to a provider-specific role, if configured.
|
|
3406
|
+
*
|
|
3407
|
+
* Roles encode product intent such as "quality" or "fast" without assuming
|
|
3408
|
+
* the provider default is suitable for every outcome strategy.
|
|
3409
|
+
*
|
|
3410
|
+
* @param providerId - Provider identifier
|
|
3411
|
+
* @param role - Model role name
|
|
3412
|
+
* @returns Resolved model ID for the role, or undefined if the role is not configured
|
|
3413
|
+
*/
|
|
3414
|
+
static getModelForRole(providerId, role, registryOverride) {
|
|
3415
|
+
const trimmedRole = role.trim();
|
|
3416
|
+
if (!trimmedRole) return void 0;
|
|
3417
|
+
const config = _ProviderRegistry.getProviderConfig(providerId, registryOverride);
|
|
3418
|
+
const configuredModel = config.models.roles?.[trimmedRole];
|
|
3419
|
+
if (!configuredModel) return void 0;
|
|
3420
|
+
return _ProviderRegistry.resolveModel(providerId, configuredModel, registryOverride);
|
|
3421
|
+
}
|
|
3422
|
+
/**
|
|
3423
|
+
* Resolve a reviewer model across all enabled providers, excluding specified providers.
|
|
3424
|
+
*
|
|
3425
|
+
* Implements the cross-provider review rule from the Wave 2 design record:
|
|
3426
|
+
* reviewer != orchestrator provider != executor provider (and any additional
|
|
3427
|
+
* mutation-owner providers the caller passes). Callers pass the provider IDs
|
|
3428
|
+
* already assigned to other stages so this method returns the first remaining
|
|
3429
|
+
* provider, with its model for the first role in the role chain it declares,
|
|
3430
|
+
* else its default model (role `default`). Every eligible provider qualifies.
|
|
3431
|
+
*
|
|
3432
|
+
* Callers that honor a configured `roles.reviewer.modelRole` pass a chain with
|
|
3433
|
+
* that role so automatic selection does not silently ignore it.
|
|
3434
|
+
*
|
|
3435
|
+
* Candidate order: `providerPreference` ids first (skipping excluded, disabled,
|
|
3436
|
+
* unknown and non-`preferenceProviders` entries), then `eligibleProviders` in the
|
|
3437
|
+
* caller's order (the one provider order), else the enabled providers in `order`.
|
|
3438
|
+
*
|
|
3439
|
+
* Returns null when no qualifying provider is found. Pure and static — reads
|
|
3440
|
+
* only from the loaded registry and applies no side effects: `eligibleProviders`
|
|
3441
|
+
* is an eligibility filter the CALLER established (e.g. installed CLIs); this
|
|
3442
|
+
* method never probes the filesystem or a provider CLI itself.
|
|
3443
|
+
*
|
|
3444
|
+
* @param excludeProviders - Provider IDs to skip (e.g. orchestrator + executor + mutation owners)
|
|
3445
|
+
* @param options.roleChain - Model roles tried before the default model (default: none)
|
|
3446
|
+
* @param options.providerPreference - Preferred provider order for selection
|
|
3447
|
+
* @param options.eligibleProviders - When set, only these provider IDs may be
|
|
3448
|
+
* selected (an empty list qualifies nobody). Omit for no eligibility filter.
|
|
3449
|
+
* @param options.preferenceProviders - Ids a preference entry may name (default: eligibleProviders)
|
|
3450
|
+
* @param options.roleModel - Looks up a provider's model for a role, including
|
|
3451
|
+
* `default` (default: its providers.yaml slot or default model); lets the caller
|
|
3452
|
+
* resolve roles that honor user config.
|
|
3453
|
+
* @returns Provider + resolved model + winning role, or null if none qualify
|
|
3454
|
+
*/
|
|
3455
|
+
static resolveReviewerModel(excludeProviders, options = {}, registryOverride) {
|
|
3456
|
+
const toKeys = (ids) => new Set(ids.map((p) => p.trim().toLowerCase()).filter((p) => p.length > 0));
|
|
3457
|
+
const excludeSet = toKeys(excludeProviders);
|
|
3458
|
+
const preferable = options.preferenceProviders ?? options.eligibleProviders;
|
|
3459
|
+
const preferableSet = preferable ? toKeys(preferable) : void 0;
|
|
3460
|
+
const ineligible = (key) => preferableSet?.has(key) === false;
|
|
3461
|
+
const roleChain = [
|
|
3462
|
+
...(options.roleChain ?? []).map((r) => r.trim()).filter((r) => r.length > 0),
|
|
3463
|
+
"default"
|
|
3464
|
+
];
|
|
3465
|
+
const registryRoleModel = (pid, role) => {
|
|
3466
|
+
if (role !== "default") return _ProviderRegistry.getModelForRole(pid, role, registryOverride);
|
|
3467
|
+
try {
|
|
3468
|
+
return _ProviderRegistry.resolveModel(pid, void 0, registryOverride);
|
|
3469
|
+
} catch {
|
|
3470
|
+
return void 0;
|
|
3471
|
+
}
|
|
3472
|
+
};
|
|
3473
|
+
const enabled = _ProviderRegistry.getEnabledProviders(registryOverride);
|
|
3474
|
+
const enabledById = new Map(enabled.map((p) => [p.id.toLowerCase(), p]));
|
|
3475
|
+
const ordered = [];
|
|
3476
|
+
const seen = /* @__PURE__ */ new Set();
|
|
3477
|
+
for (const pref of options.providerPreference ?? []) {
|
|
3478
|
+
const key = pref.trim().toLowerCase();
|
|
3479
|
+
if (!key || seen.has(key) || excludeSet.has(key) || ineligible(key)) continue;
|
|
3480
|
+
const match = enabledById.get(key);
|
|
3481
|
+
if (match) {
|
|
3482
|
+
ordered.push(match);
|
|
3483
|
+
seen.add(key);
|
|
3484
|
+
}
|
|
3485
|
+
}
|
|
3486
|
+
const rest = options.eligibleProviders?.map((id) => enabledById.get(id.trim().toLowerCase()));
|
|
3487
|
+
for (const providerConfig of rest ?? enabled) {
|
|
3488
|
+
const key = providerConfig?.id.toLowerCase();
|
|
3489
|
+
if (!providerConfig || !key || seen.has(key) || excludeSet.has(key)) continue;
|
|
3490
|
+
ordered.push(providerConfig);
|
|
3491
|
+
seen.add(key);
|
|
3492
|
+
}
|
|
3493
|
+
for (const providerConfig of ordered) {
|
|
3494
|
+
const pid = providerConfig.id;
|
|
3495
|
+
for (const role of roleChain) {
|
|
3496
|
+
const model = (options.roleModel ?? registryRoleModel)(pid, role);
|
|
3497
|
+
if (model) {
|
|
3498
|
+
return { provider: pid, model, role };
|
|
3499
|
+
}
|
|
3500
|
+
}
|
|
3501
|
+
}
|
|
3502
|
+
return null;
|
|
3503
|
+
}
|
|
3504
|
+
/**
|
|
3505
|
+
* Get the list of available models for a provider, from static registry config.
|
|
3506
|
+
* `getDiscoveredModels()` currently returns this same static inventory.
|
|
3507
|
+
* For observation-backed IDs, read the provider's discovery cache directly
|
|
3508
|
+
* (for example `getCachedCursorModelIds` or `getCachedOpencodeModelIds`).
|
|
3509
|
+
*
|
|
3510
|
+
* @param providerId - Provider identifier
|
|
3511
|
+
* @returns Array of available model IDs from the static registry
|
|
3512
|
+
*/
|
|
3513
|
+
static getAvailableModels(providerId) {
|
|
3514
|
+
const config = _ProviderRegistry.getProviderConfig(providerId);
|
|
3515
|
+
return config.models.available.map((m) => m.id);
|
|
3516
|
+
}
|
|
3517
|
+
/**
|
|
3518
|
+
* Model ids to offer in listings and pickers: the available rows limited to the
|
|
3519
|
+
* CLI's observed inventory when one was refreshed. Unlisted rows still resolve.
|
|
3520
|
+
*/
|
|
3521
|
+
static getOfferedModels(providerId) {
|
|
3522
|
+
return offeredModelIds(_ProviderRegistry.getProviderConfig(providerId).models);
|
|
3523
|
+
}
|
|
3524
|
+
/**
|
|
3525
|
+
* Get static model mappings for a provider (logical name → native CLI ID).
|
|
3526
|
+
* For Cursor, also check getCachedCanonicalMappings() from
|
|
3527
|
+
* src/core/providers/cursor/model-discovery.ts for discovery-fed mappings.
|
|
3528
|
+
*
|
|
3529
|
+
* @param providerId - Provider identifier
|
|
3530
|
+
* @returns Record mapping logical model names to native CLI IDs
|
|
3531
|
+
*/
|
|
3532
|
+
static getMappings(providerId) {
|
|
3533
|
+
const config = _ProviderRegistry.getProviderConfig(providerId);
|
|
3534
|
+
return cloneProviderRegistryValue(config.models.mappings);
|
|
3535
|
+
}
|
|
3536
|
+
/**
|
|
3537
|
+
* Return the static available-model list from this registry.
|
|
3538
|
+
*
|
|
3539
|
+
* Despite the name, this is not live discovery and does not read an
|
|
3540
|
+
* observation cache. It is equivalent to `getAvailableModels()`.
|
|
3541
|
+
*
|
|
3542
|
+
* Callers that need observation-backed IDs should read the provider's
|
|
3543
|
+
* discovery cache directly (`getCachedCursorModelIds`,
|
|
3544
|
+
* `getCachedOpencodeModelIds`). Those readers return local cache evidence
|
|
3545
|
+
* only (empty when none) and do not fall back to this registry.
|
|
3546
|
+
*
|
|
3547
|
+
* @param providerId - Provider identifier
|
|
3548
|
+
* @returns Array of model IDs from the static registry
|
|
3549
|
+
*/
|
|
3550
|
+
static getDiscoveredModels(providerId) {
|
|
3551
|
+
const normalized = normalizeProviderConfigId(providerId);
|
|
3552
|
+
return _ProviderRegistry.getAvailableModels(normalized);
|
|
3553
|
+
}
|
|
3554
|
+
/**
|
|
3555
|
+
* Read a single capability flag for a provider.
|
|
3556
|
+
*
|
|
3557
|
+
* Returns the boolean value when explicitly set in providers.yaml, or
|
|
3558
|
+
* `undefined` when the flag is absent (caller must decide the default).
|
|
3559
|
+
*
|
|
3560
|
+
* @param providerId - Provider identifier
|
|
3561
|
+
* @param name - Capability key (e.g. 'supports_api_judge')
|
|
3562
|
+
* @returns boolean if set, undefined if not declared
|
|
3563
|
+
*/
|
|
3564
|
+
static getCapability(providerId, name) {
|
|
3565
|
+
const config = _ProviderRegistry.getProviderConfig(providerId);
|
|
3566
|
+
const value = config.capabilities[name];
|
|
3567
|
+
return typeof value === "boolean" ? value : void 0;
|
|
3568
|
+
}
|
|
3569
|
+
};
|
|
3570
|
+
function loadProviderRegistry(configPath) {
|
|
3571
|
+
return ProviderRegistry.load(configPath);
|
|
3572
|
+
}
|
|
3573
|
+
function getProviderConfig(providerId, registryOverride) {
|
|
3574
|
+
return ProviderRegistry.getProviderConfig(providerId, registryOverride);
|
|
3575
|
+
}
|
|
3576
|
+
function getCapability(providerId, name) {
|
|
3577
|
+
return ProviderRegistry.getCapability(providerId, name);
|
|
3578
|
+
}
|
|
3579
|
+
|
|
3580
|
+
export {
|
|
3581
|
+
PROVIDER_CATALOG_SHA256,
|
|
3582
|
+
BEDROCK_CODEX_MODEL_PROVIDER,
|
|
3583
|
+
isCodexBedrockProviderId,
|
|
3584
|
+
isBedrockRuntimeCodexProvider,
|
|
3585
|
+
resolveCodexBackendDetailed,
|
|
3586
|
+
resolveCodexBackend,
|
|
3587
|
+
describeCodexBackendConflict,
|
|
3588
|
+
resolveBedrockCodexWireModel,
|
|
3589
|
+
readCodexConnection,
|
|
3590
|
+
opencodeInventoryContext,
|
|
3591
|
+
REFRESH_OVERLAY_SCHEMA_VERSION,
|
|
3592
|
+
OverlayModelAvailableEntrySchema,
|
|
3593
|
+
OverlayPricingRowSchema,
|
|
3594
|
+
getRefreshOverlayOperatorNotice,
|
|
3595
|
+
emptyRefreshOverlay,
|
|
3596
|
+
serializeRefreshOverlay,
|
|
3597
|
+
parseRefreshOverlay,
|
|
3598
|
+
loadRefreshOverlayFile,
|
|
3599
|
+
withRefreshOrigin,
|
|
3600
|
+
refreshEnvironment,
|
|
3601
|
+
refreshInventoryContext,
|
|
3602
|
+
resolveSharedRefreshPaths,
|
|
3603
|
+
carriedForwardOverlay,
|
|
3604
|
+
readEffectiveRefreshOverlay,
|
|
3605
|
+
fingerprintEnvironment,
|
|
3606
|
+
fingerprintFile,
|
|
3607
|
+
fingerprintFiles,
|
|
3608
|
+
combineCacheFingerprints,
|
|
3609
|
+
InvalidExplicitConfigError,
|
|
3610
|
+
InvalidConfigContentError,
|
|
3611
|
+
isInvalidExplicitConfigError,
|
|
3612
|
+
isConfigValidityError,
|
|
3613
|
+
rethrowConfigValidityError,
|
|
3614
|
+
getEmbeddedProviderConfigPaths,
|
|
3615
|
+
isPackagedCatalogPath,
|
|
3616
|
+
resolveSourceBaseDrift,
|
|
3617
|
+
detectSourceBaseDrift,
|
|
3618
|
+
normalizeModelSelectorForComparison,
|
|
3619
|
+
isOfferedModel,
|
|
3620
|
+
offeredModelRows,
|
|
3621
|
+
offeredModelIds,
|
|
3622
|
+
warnIfModelUnobserved,
|
|
3623
|
+
isTrustedProjectRoot,
|
|
3624
|
+
providerDisableSwitch,
|
|
3625
|
+
disabledBySuffix,
|
|
3626
|
+
ModelPricingSchema,
|
|
3627
|
+
ToolPricingSchema,
|
|
3628
|
+
SubscriptionPricingSchema,
|
|
3629
|
+
InfrastructurePricingSchema,
|
|
3630
|
+
ProviderPricingSchema,
|
|
3631
|
+
registerProviderRegistryReloadInvalidator,
|
|
3632
|
+
catalogAdditions,
|
|
3633
|
+
applyRefreshOverlay,
|
|
3634
|
+
getConfiguredProviderRegistryPaths,
|
|
3635
|
+
getProviderRegistryInputPaths,
|
|
3636
|
+
RetryConfigSchema,
|
|
3637
|
+
CircuitBreakerConfigSchema,
|
|
3638
|
+
RateLimitEntrySchema,
|
|
3639
|
+
RateLimitsConfigSchema,
|
|
3640
|
+
MemoryConfigSchema,
|
|
3641
|
+
PollingConfigSchema,
|
|
3642
|
+
CLIConfigSchema,
|
|
3643
|
+
AuthConfigSchema,
|
|
3644
|
+
TemplatedAuthConfigSchema,
|
|
3645
|
+
ProbeExpectationSchema,
|
|
3646
|
+
CommandProbeSchema,
|
|
3647
|
+
ModelsDiscoverySchema,
|
|
3648
|
+
ModelAccessClassSchema,
|
|
3649
|
+
ModelAccessConfigSchema,
|
|
3650
|
+
ModelsConfigSchema,
|
|
3651
|
+
TemplatedModelsConfigSchema,
|
|
3652
|
+
CapabilitiesConfigSchema,
|
|
3653
|
+
TemplatedCapabilitiesConfigSchema,
|
|
3654
|
+
BotIdentityConfigSchema,
|
|
3655
|
+
EnvConfigSchema,
|
|
3656
|
+
RefreshStrategyConfigSchema,
|
|
3657
|
+
DefaultPricingSchema,
|
|
3658
|
+
ConcurrencyConfigSchema,
|
|
3659
|
+
RouteConfigSchema,
|
|
3660
|
+
WorkspaceEditsConfigSchema,
|
|
3661
|
+
GenerationConfigSchema,
|
|
3662
|
+
TaskSettingsSchema,
|
|
3663
|
+
RequirementSchema,
|
|
3664
|
+
ProviderOptionSchema,
|
|
3665
|
+
ProviderOptionsSchema,
|
|
3666
|
+
ConditionalRequiresSchema,
|
|
3667
|
+
ProviderRequiresSchema,
|
|
3668
|
+
ApiConfigSchema,
|
|
3669
|
+
TemplatedCLIExecutionSchema,
|
|
3670
|
+
NativeProviderConfigSchema,
|
|
3671
|
+
TemplatedProviderConfigSchema,
|
|
3672
|
+
ProviderConfigSchema,
|
|
3673
|
+
DefaultsConfigSchema,
|
|
3674
|
+
MetadataConfigSchema,
|
|
3675
|
+
ProviderRegistryConfigSchema,
|
|
3676
|
+
getProviderFamily,
|
|
3677
|
+
getJudgeCapabilities,
|
|
3678
|
+
ProviderRegistry,
|
|
3679
|
+
loadProviderRegistry,
|
|
3680
|
+
getProviderConfig,
|
|
3681
|
+
getCapability
|
|
3682
|
+
};
|
|
3683
|
+
//# sourceMappingURL=chunk-QJ6OEH4K.js.map
|