@theokit/sdk 5.6.0 → 5.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +105 -0
- package/dist/a2a/index.cjs +6 -6
- package/dist/a2a/index.js +2 -2
- package/dist/{agent-82d_DrCL.d.cts → agent-3RcPVGMo.d.cts} +22 -4
- package/dist/agent-7ERQNV66.js +59 -0
- package/dist/{agent-JJZM2VIK.js.map → agent-7ERQNV66.js.map} +1 -1
- package/dist/agent-LNTR4QH5.cjs +68 -0
- package/dist/{agent-47NS6ZVL.cjs.map → agent-LNTR4QH5.cjs.map} +1 -1
- package/dist/{agent-G6g-uwcB.d.ts → agent-lS68mYIL.d.ts} +22 -4
- package/dist/agent.d.ts +11 -0
- package/dist/auth/index.cjs +32 -32
- package/dist/auth/index.js +5 -5
- package/dist/{batch-US4F6WPK.js → batch-427O54FQ.js} +7 -7
- package/dist/{batch-US4F6WPK.js.map → batch-427O54FQ.js.map} +1 -1
- package/dist/{batch-I6T6MXZO.cjs → batch-U4SO4RLX.cjs} +24 -24
- package/dist/{batch-I6T6MXZO.cjs.map → batch-U4SO4RLX.cjs.map} +1 -1
- package/dist/{chunk-44I6UYVH.js → chunk-26NEAJ6T.js} +4 -4
- package/dist/{chunk-44I6UYVH.js.map → chunk-26NEAJ6T.js.map} +1 -1
- package/dist/{chunk-GCHZMH42.cjs → chunk-2STSX2SY.cjs} +264 -260
- package/dist/chunk-2STSX2SY.cjs.map +1 -0
- package/dist/{chunk-2UXQASTX.js → chunk-3CU5J7V3.js} +38 -34
- package/dist/chunk-3CU5J7V3.js.map +1 -0
- package/dist/{chunk-5NELQ6LB.js → chunk-4QCJAJAG.js} +12 -3
- package/dist/chunk-4QCJAJAG.js.map +1 -0
- package/dist/{chunk-XYFGKVZ7.js → chunk-53RDNK3H.js} +3 -3
- package/dist/{chunk-XYFGKVZ7.js.map → chunk-53RDNK3H.js.map} +1 -1
- package/dist/{chunk-2QKV4CGK.js → chunk-5522X223.js} +3 -3
- package/dist/{chunk-2QKV4CGK.js.map → chunk-5522X223.js.map} +1 -1
- package/dist/{chunk-EH6XD3FY.js → chunk-5DD4NJN3.js} +3 -3
- package/dist/{chunk-EH6XD3FY.js.map → chunk-5DD4NJN3.js.map} +1 -1
- package/dist/{chunk-V22DZIXO.js → chunk-5Q4RTLMP.js} +3 -3
- package/dist/{chunk-V22DZIXO.js.map → chunk-5Q4RTLMP.js.map} +1 -1
- package/dist/{chunk-4A3SKJ53.cjs → chunk-6PB5AQCY.cjs} +14 -14
- package/dist/{chunk-4A3SKJ53.cjs.map → chunk-6PB5AQCY.cjs.map} +1 -1
- package/dist/{chunk-PRZ3BES7.cjs → chunk-72CPLZPC.cjs} +5 -5
- package/dist/{chunk-PRZ3BES7.cjs.map → chunk-72CPLZPC.cjs.map} +1 -1
- package/dist/{chunk-GFFBXSQT.cjs → chunk-76PIKR4P.cjs} +22 -22
- package/dist/{chunk-GFFBXSQT.cjs.map → chunk-76PIKR4P.cjs.map} +1 -1
- package/dist/{chunk-EFMFILPG.js → chunk-7F7XE6CM.js} +3 -3
- package/dist/{chunk-EFMFILPG.js.map → chunk-7F7XE6CM.js.map} +1 -1
- package/dist/{chunk-N2KAIZ5D.js → chunk-7GDHFV2M.js} +4 -20
- package/dist/chunk-7GDHFV2M.js.map +1 -0
- package/dist/{chunk-CA5VUAP3.js → chunk-7HUCU3KK.js} +5 -5
- package/dist/{chunk-CA5VUAP3.js.map → chunk-7HUCU3KK.js.map} +1 -1
- package/dist/{chunk-4MMWFSCD.js → chunk-7JAKO3NM.js} +3 -3
- package/dist/{chunk-4MMWFSCD.js.map → chunk-7JAKO3NM.js.map} +1 -1
- package/dist/{chunk-UADQJBHR.cjs → chunk-7NQ7HJ3E.cjs} +6 -6
- package/dist/{chunk-UADQJBHR.cjs.map → chunk-7NQ7HJ3E.cjs.map} +1 -1
- package/dist/{chunk-HG4UN4MN.cjs → chunk-AOHRKGAA.cjs} +22 -22
- package/dist/{chunk-HG4UN4MN.cjs.map → chunk-AOHRKGAA.cjs.map} +1 -1
- package/dist/{chunk-C4ZQPWXJ.cjs → chunk-ARMFXTY6.cjs} +143 -190
- package/dist/chunk-ARMFXTY6.cjs.map +1 -0
- package/dist/{chunk-5WKQDIGO.js → chunk-AY43232P.js} +4 -4
- package/dist/{chunk-5WKQDIGO.js.map → chunk-AY43232P.js.map} +1 -1
- package/dist/{chunk-7FDKWDA2.cjs → chunk-B3XXQX6L.cjs} +7 -7
- package/dist/{chunk-7FDKWDA2.cjs.map → chunk-B3XXQX6L.cjs.map} +1 -1
- package/dist/{chunk-ALUN2B4W.js → chunk-B5MHRQJZ.js} +9 -3
- package/dist/chunk-B5MHRQJZ.js.map +1 -0
- package/dist/{chunk-TA3K7SBK.js → chunk-BKMDRBJ7.js} +3 -3
- package/dist/{chunk-TA3K7SBK.js.map → chunk-BKMDRBJ7.js.map} +1 -1
- package/dist/{chunk-FUSDYC2B.cjs → chunk-CQYBJOB2.cjs} +4 -4
- package/dist/{chunk-FUSDYC2B.cjs.map → chunk-CQYBJOB2.cjs.map} +1 -1
- package/dist/{chunk-7JJ3A6AT.cjs → chunk-D5KXKBEN.cjs} +5 -5
- package/dist/{chunk-7JJ3A6AT.cjs.map → chunk-D5KXKBEN.cjs.map} +1 -1
- package/dist/{chunk-HUDNLFY4.js → chunk-DDRX4LYS.js} +13 -4
- package/dist/chunk-DDRX4LYS.js.map +1 -0
- package/dist/{chunk-QDM3OHUT.cjs → chunk-ECD6ER3E.cjs} +4 -4
- package/dist/{chunk-QDM3OHUT.cjs.map → chunk-ECD6ER3E.cjs.map} +1 -1
- package/dist/{chunk-JMDDYA22.js → chunk-EJROML3Q.js} +4 -4
- package/dist/{chunk-JMDDYA22.js.map → chunk-EJROML3Q.js.map} +1 -1
- package/dist/{chunk-FPIY5CLV.js → chunk-FRL35MFN.js} +5 -5
- package/dist/{chunk-FPIY5CLV.js.map → chunk-FRL35MFN.js.map} +1 -1
- package/dist/{chunk-EIQFAOFD.js → chunk-GGRPAQ3B.js} +3 -3
- package/dist/{chunk-EIQFAOFD.js.map → chunk-GGRPAQ3B.js.map} +1 -1
- package/dist/{chunk-HCT4HPCL.cjs → chunk-GHHIJEFX.cjs} +4 -4
- package/dist/{chunk-HCT4HPCL.cjs.map → chunk-GHHIJEFX.cjs.map} +1 -1
- package/dist/{chunk-7A6535RA.cjs → chunk-GM54F4FE.cjs} +9 -9
- package/dist/{chunk-7A6535RA.cjs.map → chunk-GM54F4FE.cjs.map} +1 -1
- package/dist/{chunk-6M2OIS4Y.js → chunk-GMRFAX4I.js} +74 -4
- package/dist/chunk-GMRFAX4I.js.map +1 -0
- package/dist/{chunk-O6USDERH.js → chunk-GMSRRJ53.js} +3 -3
- package/dist/{chunk-O6USDERH.js.map → chunk-GMSRRJ53.js.map} +1 -1
- package/dist/{chunk-VE6DFSKU.js → chunk-GTX6FEDP.js} +3 -3
- package/dist/{chunk-VE6DFSKU.js.map → chunk-GTX6FEDP.js.map} +1 -1
- package/dist/{chunk-NJWYQWDL.js → chunk-H3CVJSFC.js} +3 -3
- package/dist/{chunk-NJWYQWDL.js.map → chunk-H3CVJSFC.js.map} +1 -1
- package/dist/{chunk-MYJGWS2J.cjs → chunk-HG5LKFG7.cjs} +16 -16
- package/dist/{chunk-MYJGWS2J.cjs.map → chunk-HG5LKFG7.cjs.map} +1 -1
- package/dist/{chunk-55GB6JYQ.js → chunk-HOHR75KF.js} +5 -5
- package/dist/{chunk-55GB6JYQ.js.map → chunk-HOHR75KF.js.map} +1 -1
- package/dist/{chunk-GBCVPKHE.js → chunk-HV4V63CO.js} +3 -3
- package/dist/{chunk-GBCVPKHE.js.map → chunk-HV4V63CO.js.map} +1 -1
- package/dist/{chunk-I2PWY7VM.cjs → chunk-IIYJMXYW.cjs} +4 -4
- package/dist/{chunk-I2PWY7VM.cjs.map → chunk-IIYJMXYW.cjs.map} +1 -1
- package/dist/chunk-J4SA2ZEJ.cjs +24 -0
- package/dist/chunk-J4SA2ZEJ.cjs.map +1 -0
- package/dist/{chunk-ATT276RD.cjs → chunk-J5623RIV.cjs} +78 -6
- package/dist/chunk-J5623RIV.cjs.map +1 -0
- package/dist/{chunk-KVSAY6NZ.cjs → chunk-J6GXS5A2.cjs} +13 -13
- package/dist/{chunk-KVSAY6NZ.cjs.map → chunk-J6GXS5A2.cjs.map} +1 -1
- package/dist/{chunk-NQTD6QOW.cjs → chunk-JW3GVLM6.cjs} +4 -4
- package/dist/{chunk-NQTD6QOW.cjs.map → chunk-JW3GVLM6.cjs.map} +1 -1
- package/dist/{chunk-TFG5IBZS.cjs → chunk-KGZ66JVZ.cjs} +14 -14
- package/dist/{chunk-TFG5IBZS.cjs.map → chunk-KGZ66JVZ.cjs.map} +1 -1
- package/dist/{chunk-47TF32NQ.js → chunk-KO6SHCEH.js} +3 -3
- package/dist/{chunk-47TF32NQ.js.map → chunk-KO6SHCEH.js.map} +1 -1
- package/dist/{chunk-EIOMN5VA.cjs → chunk-KTA7YTZQ.cjs} +17 -8
- package/dist/chunk-KTA7YTZQ.cjs.map +1 -0
- package/dist/{chunk-D6POWE7E.cjs → chunk-MEUBLCM4.cjs} +11 -11
- package/dist/{chunk-D6POWE7E.cjs.map → chunk-MEUBLCM4.cjs.map} +1 -1
- package/dist/{chunk-VWUXIVEI.js → chunk-MFZODA5Y.js} +5 -5
- package/dist/{chunk-VWUXIVEI.js.map → chunk-MFZODA5Y.js.map} +1 -1
- package/dist/{chunk-4HS6FFGL.cjs → chunk-MPQJE3G4.cjs} +15 -15
- package/dist/{chunk-4HS6FFGL.cjs.map → chunk-MPQJE3G4.cjs.map} +1 -1
- package/dist/{chunk-QRVS2PRE.cjs → chunk-MPR2ISL2.cjs} +4 -4
- package/dist/{chunk-QRVS2PRE.cjs.map → chunk-MPR2ISL2.cjs.map} +1 -1
- package/dist/{chunk-UOLBAPDM.js → chunk-MQGSOKR3.js} +3 -3
- package/dist/{chunk-UOLBAPDM.js.map → chunk-MQGSOKR3.js.map} +1 -1
- package/dist/{chunk-HFEJE7AC.js → chunk-MU7IAA7G.js} +9 -9
- package/dist/{chunk-HFEJE7AC.js.map → chunk-MU7IAA7G.js.map} +1 -1
- package/dist/{chunk-EXTRW7GW.cjs → chunk-NAGPKWOD.cjs} +4 -4
- package/dist/{chunk-EXTRW7GW.cjs.map → chunk-NAGPKWOD.cjs.map} +1 -1
- package/dist/{chunk-KTTHHYEW.cjs → chunk-NJSIAJEK.cjs} +4 -4
- package/dist/{chunk-KTTHHYEW.cjs.map → chunk-NJSIAJEK.cjs.map} +1 -1
- package/dist/{chunk-Z3NTRKIC.cjs → chunk-NKIQTLFA.cjs} +4 -4
- package/dist/{chunk-Z3NTRKIC.cjs.map → chunk-NKIQTLFA.cjs.map} +1 -1
- package/dist/{chunk-KZSKIUXZ.js → chunk-NOO6GZTZ.js} +37 -85
- package/dist/chunk-NOO6GZTZ.js.map +1 -0
- package/dist/{chunk-7IZKTQ5G.cjs → chunk-OCEQ6DW2.cjs} +10 -29
- package/dist/chunk-OCEQ6DW2.cjs.map +1 -0
- package/dist/{chunk-BJUJT5ED.cjs → chunk-OF2CLCTH.cjs} +4 -4
- package/dist/{chunk-BJUJT5ED.cjs.map → chunk-OF2CLCTH.cjs.map} +1 -1
- package/dist/{chunk-HUFSABUZ.cjs → chunk-OLSEWLK5.cjs} +6 -6
- package/dist/{chunk-HUFSABUZ.cjs.map → chunk-OLSEWLK5.cjs.map} +1 -1
- package/dist/{chunk-DQZU7JK6.cjs → chunk-P22BZE7G.cjs} +4 -4
- package/dist/{chunk-DQZU7JK6.cjs.map → chunk-P22BZE7G.cjs.map} +1 -1
- package/dist/{chunk-QWD3CZWE.cjs → chunk-P7NNKEWO.cjs} +4 -4
- package/dist/{chunk-QWD3CZWE.cjs.map → chunk-P7NNKEWO.cjs.map} +1 -1
- package/dist/chunk-PQCTDMUI.js +20 -0
- package/dist/chunk-PQCTDMUI.js.map +1 -0
- package/dist/{chunk-DZG77WU7.cjs → chunk-PSLCVSCS.cjs} +3 -3
- package/dist/{chunk-DZG77WU7.cjs.map → chunk-PSLCVSCS.cjs.map} +1 -1
- package/dist/{chunk-STGSMJMJ.js → chunk-QDQQYRJI.js} +4 -4
- package/dist/{chunk-STGSMJMJ.js.map → chunk-QDQQYRJI.js.map} +1 -1
- package/dist/{chunk-7MMTZBTT.js → chunk-R2C3HXR3.js} +4 -4
- package/dist/{chunk-7MMTZBTT.js.map → chunk-R2C3HXR3.js.map} +1 -1
- package/dist/chunk-R3ZQBPA5.cjs +18 -0
- package/dist/{chunk-ANMJJD6D.cjs.map → chunk-R3ZQBPA5.cjs.map} +1 -1
- package/dist/{chunk-4NLCWGH7.cjs → chunk-RA7IE4NK.cjs} +15 -15
- package/dist/{chunk-4NLCWGH7.cjs.map → chunk-RA7IE4NK.cjs.map} +1 -1
- package/dist/{chunk-UBR5PWD7.js → chunk-SUVCHX4L.js} +3 -3
- package/dist/{chunk-UBR5PWD7.js.map → chunk-SUVCHX4L.js.map} +1 -1
- package/dist/{chunk-LD6HASA5.cjs → chunk-SWALPLFQ.cjs} +12 -2
- package/dist/chunk-SWALPLFQ.cjs.map +1 -0
- package/dist/{chunk-52FDUJSV.cjs → chunk-T5KOSR5Y.cjs} +11 -11
- package/dist/{chunk-52FDUJSV.cjs.map → chunk-T5KOSR5Y.cjs.map} +1 -1
- package/dist/{chunk-BZ3YMAMP.js → chunk-TC4RWP3Y.js} +6 -6
- package/dist/{chunk-BZ3YMAMP.js.map → chunk-TC4RWP3Y.js.map} +1 -1
- package/dist/{chunk-XB4GI5RZ.js → chunk-TE6XVTOA.js} +3 -3
- package/dist/{chunk-XB4GI5RZ.js.map → chunk-TE6XVTOA.js.map} +1 -1
- package/dist/{chunk-VUHXC74Q.cjs → chunk-TTBIQTO5.cjs} +19 -19
- package/dist/{chunk-VUHXC74Q.cjs.map → chunk-TTBIQTO5.cjs.map} +1 -1
- package/dist/{chunk-J7J7J2GN.cjs → chunk-UNFBHV46.cjs} +9 -2
- package/dist/chunk-UNFBHV46.cjs.map +1 -0
- package/dist/{chunk-AAEZSPTC.js → chunk-UNZOJVVC.js} +4 -4
- package/dist/{chunk-AAEZSPTC.js.map → chunk-UNZOJVVC.js.map} +1 -1
- package/dist/{chunk-T3ZDEYTJ.js → chunk-W4VQMXBZ.js} +4 -4
- package/dist/{chunk-T3ZDEYTJ.js.map → chunk-W4VQMXBZ.js.map} +1 -1
- package/dist/{chunk-24SYBZPL.cjs → chunk-WPO3VCY4.cjs} +9 -9
- package/dist/{chunk-24SYBZPL.cjs.map → chunk-WPO3VCY4.cjs.map} +1 -1
- package/dist/{chunk-IUMAQURF.js → chunk-X6DUEDAF.js} +3 -3
- package/dist/{chunk-IUMAQURF.js.map → chunk-X6DUEDAF.js.map} +1 -1
- package/dist/{chunk-CFE6QF2Q.js → chunk-XCQ432OX.js} +3 -3
- package/dist/{chunk-CFE6QF2Q.js.map → chunk-XCQ432OX.js.map} +1 -1
- package/dist/{chunk-QWD4RDZ3.cjs → chunk-XDUGSTYJ.cjs} +15 -15
- package/dist/{chunk-QWD4RDZ3.cjs.map → chunk-XDUGSTYJ.cjs.map} +1 -1
- package/dist/{chunk-K2VMFZQ5.js → chunk-XKMVJ443.js} +5 -5
- package/dist/{chunk-K2VMFZQ5.js.map → chunk-XKMVJ443.js.map} +1 -1
- package/dist/{chunk-RWPLWMCZ.cjs → chunk-XW4POZ6V.cjs} +11 -11
- package/dist/{chunk-RWPLWMCZ.cjs.map → chunk-XW4POZ6V.cjs.map} +1 -1
- package/dist/{chunk-6PWOWXMC.js → chunk-XZHJYSPB.js} +3 -3
- package/dist/{chunk-6PWOWXMC.js.map → chunk-XZHJYSPB.js.map} +1 -1
- package/dist/{chunk-QC55H6RJ.cjs → chunk-YRJA2POB.cjs} +9 -9
- package/dist/{chunk-QC55H6RJ.cjs.map → chunk-YRJA2POB.cjs.map} +1 -1
- package/dist/{chunk-DMRT67Y6.js → chunk-ZJZ7LV3A.js} +3 -3
- package/dist/{chunk-DMRT67Y6.js.map → chunk-ZJZ7LV3A.js.map} +1 -1
- package/dist/{chunk-G7BLGBRN.js → chunk-ZWFTECOE.js} +3 -3
- package/dist/{chunk-G7BLGBRN.js.map → chunk-ZWFTECOE.js.map} +1 -1
- package/dist/compact-session-2N3ZYJTW.js +24 -0
- package/dist/{compact-session-YSEK7NQF.js.map → compact-session-2N3ZYJTW.js.map} +1 -1
- package/dist/compact-session-RBPLUPCK.cjs +65 -0
- package/dist/{compact-session-7FMYJXQ7.cjs.map → compact-session-RBPLUPCK.cjs.map} +1 -1
- package/dist/compaction.cjs +20 -16
- package/dist/compaction.d.cts +2 -0
- package/dist/compaction.d.ts +2 -0
- package/dist/compaction.js +2 -2
- package/dist/concurrency.cjs +5 -5
- package/dist/concurrency.js +3 -3
- package/dist/context/index.cjs +15 -7
- package/dist/context/index.cjs.map +1 -1
- package/dist/context/index.d.cts +2 -0
- package/dist/context/index.d.ts +2 -0
- package/dist/context/index.js +7 -3
- package/dist/context/index.js.map +1 -1
- package/dist/context-SXR2HLHT.js +7 -0
- package/dist/{context-J5BJ3LBS.js.map → context-SXR2HLHT.js.map} +1 -1
- package/dist/context-ZOULM2RB.cjs +24 -0
- package/dist/{context-HR4KMXMA.cjs.map → context-ZOULM2RB.cjs.map} +1 -1
- package/dist/{cron-DWv69ZSD.d.cts → cron-CGxoEKlx.d.cts} +2 -2
- package/dist/{cron-GynWtAax.d.ts → cron-DJv8zMa3.d.ts} +2 -2
- package/dist/cron.cjs +34 -33
- package/dist/cron.d.cts +4 -4
- package/dist/cron.d.ts +4 -4
- package/dist/cron.js +33 -32
- package/dist/{errors-DrDEgyz1.d.cts → errors-BWOJeWTZ.d.cts} +25 -2
- package/dist/{errors-CLOAyuiv.d.ts → errors-DDvG18IB.d.ts} +25 -2
- package/dist/errors.cjs +25 -21
- package/dist/errors.d.cts +2 -2
- package/dist/errors.d.ts +2 -2
- package/dist/errors.js +1 -1
- package/dist/eval.cjs +44 -43
- package/dist/eval.cjs.map +1 -1
- package/dist/eval.js +34 -33
- package/dist/eval.js.map +1 -1
- package/dist/{executor-XQAOQOHD.cjs → executor-2SUGI3ZT.cjs} +21 -21
- package/dist/{executor-XQAOQOHD.cjs.map → executor-2SUGI3ZT.cjs.map} +1 -1
- package/dist/{executor-ZNDQDX6Q.js → executor-3NI7KNL4.js} +6 -6
- package/dist/{executor-ZNDQDX6Q.js.map → executor-3NI7KNL4.js.map} +1 -1
- package/dist/filesystem/index.cjs +11 -11
- package/dist/filesystem/index.js +2 -2
- package/dist/fs-session-store-JHBJFKVV.cjs +19 -0
- package/dist/{fs-session-store-E4U3P56L.cjs.map → fs-session-store-JHBJFKVV.cjs.map} +1 -1
- package/dist/fs-session-store-STZZFXH2.js +10 -0
- package/dist/{fs-session-store-77JU46UZ.js.map → fs-session-store-STZZFXH2.js.map} +1 -1
- package/dist/generate-object-NTKAWE7D.js +7 -0
- package/dist/{generate-object-BXV7BZRP.js.map → generate-object-NTKAWE7D.js.map} +1 -1
- package/dist/generate-object-YHTWG5DB.cjs +20 -0
- package/dist/{generate-object-YBI2TDJ3.cjs.map → generate-object-YHTWG5DB.cjs.map} +1 -1
- package/dist/index-manager-ONQJSWX5.js +17 -0
- package/dist/{index-manager-27WLNQEE.js.map → index-manager-ONQJSWX5.js.map} +1 -1
- package/dist/{index-manager-BBHDKMQS.cjs → index-manager-ZGJN25FD.cjs} +9 -9
- package/dist/{index-manager-BBHDKMQS.cjs.map → index-manager-ZGJN25FD.cjs.map} +1 -1
- package/dist/index.cjs +148 -145
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +57 -10
- package/dist/index.d.ts +57 -10
- package/dist/index.js +49 -48
- package/dist/index.js.map +1 -1
- package/dist/{inject-session-PC73TMP2.cjs → inject-session-3FPXJDJP.cjs} +4 -4
- package/dist/{inject-session-PC73TMP2.cjs.map → inject-session-3FPXJDJP.cjs.map} +1 -1
- package/dist/{inject-session-J4LBWAPH.js → inject-session-YNNOE3O6.js} +3 -3
- package/dist/{inject-session-J4LBWAPH.js.map → inject-session-YNNOE3O6.js.map} +1 -1
- package/dist/interactive/index.cjs +3 -3
- package/dist/interactive/index.js +1 -1
- package/dist/internal/memory/adapters/index.cjs +7 -7
- package/dist/internal/memory/adapters/index.js +6 -6
- package/dist/internal/memory/storage/index.cjs +35 -35
- package/dist/internal/memory/storage/index.js +6 -6
- package/dist/internal/persistence/index.cjs +11 -11
- package/dist/internal/persistence/index.js +3 -3
- package/dist/internal/runtime/compression/compression-model-registry.d.ts +1 -0
- package/dist/internal/runtime/compression/compression-summarizer.d.ts +0 -14
- package/dist/internal/runtime/context/context-discovery.d.ts +42 -0
- package/dist/internal/runtime/context/context-loaders.d.ts +5 -1
- package/dist/internal/security/index.cjs +9 -9
- package/dist/internal/security/index.js +2 -2
- package/dist/internal/session/compact-session.d.ts +36 -0
- package/dist/judge-call-AQQYK6VT.cjs +22 -0
- package/dist/{judge-call-46M2E5FA.cjs.map → judge-call-AQQYK6VT.cjs.map} +1 -1
- package/dist/judge-call-LOL5FQEX.js +5 -0
- package/dist/{judge-call-FGUNNWEI.js.map → judge-call-LOL5FQEX.js.map} +1 -1
- package/dist/mcp-auth.cjs +9 -9
- package/dist/mcp-auth.js +2 -2
- package/dist/models.cjs +15 -15
- package/dist/models.js +6 -6
- package/dist/oauth-transaction-store-NP2YHZ6D.js +5 -0
- package/dist/{oauth-transaction-store-5RIR6D5C.js.map → oauth-transaction-store-NP2YHZ6D.js.map} +1 -1
- package/dist/oauth-transaction-store-ZINDV7AF.cjs +38 -0
- package/dist/{oauth-transaction-store-SXIE57OD.cjs.map → oauth-transaction-store-ZINDV7AF.cjs.map} +1 -1
- package/dist/path-safety.cjs +9 -9
- package/dist/path-safety.js +2 -2
- package/dist/persistence.cjs +16 -16
- package/dist/persistence.js +4 -4
- package/dist/project.cjs +5 -5
- package/dist/project.js +2 -2
- package/dist/providers.cjs +8 -8
- package/dist/providers.js +6 -6
- package/dist/{registry-DMWCJKRF.js → registry-5FK42CRV.js} +6 -6
- package/dist/{registry-DMWCJKRF.js.map → registry-5FK42CRV.js.map} +1 -1
- package/dist/{registry-BZQFYRTL.cjs → registry-BVTNO73E.cjs} +14 -14
- package/dist/{registry-BZQFYRTL.cjs.map → registry-BVTNO73E.cjs.map} +1 -1
- package/dist/retry.cjs +3 -3
- package/dist/retry.js +2 -2
- package/dist/{run-CTAdRU3U.d.cts → run-DsA5Ip2i.d.cts} +1 -1
- package/dist/{run-CTAdRU3U.d.ts → run-DsA5Ip2i.d.ts} +1 -1
- package/dist/sandbox/index.cjs +18 -18
- package/dist/sandbox/index.js +3 -3
- package/dist/{sdk-agent-BOiKqOgL.d.cts → sdk-agent-dNwjwCt5.d.cts} +2 -2
- package/dist/{sdk-agent-D4a_BR_6.d.ts → sdk-agent-wEOLXD3F.d.ts} +2 -2
- package/dist/server/auth/index.cjs +21 -21
- package/dist/server/auth/index.js +6 -6
- package/dist/server/errors-envelope.cjs +13 -13
- package/dist/server/errors-envelope.d.cts +2 -2
- package/dist/server/errors-envelope.d.ts +2 -2
- package/dist/server/errors-envelope.js +2 -2
- package/dist/skills.cjs +7 -7
- package/dist/skills.js +4 -4
- package/dist/stream-object-QAEHG4YO.js +7 -0
- package/dist/{stream-object-HBFMIZLD.js.map → stream-object-QAEHG4YO.js.map} +1 -1
- package/dist/stream-object-TKVGGA54.cjs +20 -0
- package/dist/{stream-object-QSKHISDJ.cjs.map → stream-object-TKVGGA54.cjs.map} +1 -1
- package/dist/subagents-loader-7GE7YUDI.cjs +16 -0
- package/dist/{subagents-loader-MOO7DC4E.cjs.map → subagents-loader-7GE7YUDI.cjs.map} +1 -1
- package/dist/subagents-loader-S2PMZY7J.js +7 -0
- package/dist/{subagents-loader-CJFYQQU2.js.map → subagents-loader-S2PMZY7J.js.map} +1 -1
- package/dist/subagents-loader.cjs +5 -5
- package/dist/subagents-loader.d.cts +3 -3
- package/dist/subagents-loader.d.ts +3 -3
- package/dist/subagents-loader.js +3 -3
- package/dist/subscription/index.cjs +3 -2
- package/dist/subscription/index.d.cts +1 -1
- package/dist/subscription/index.d.ts +1 -1
- package/dist/subscription/index.js +2 -2
- package/dist/task-store.cjs +5 -5
- package/dist/task-store.js +2 -2
- package/dist/types/agent.d.ts +1 -1
- package/dist/workflow.cjs +25 -25
- package/dist/workflow.d.cts +2 -2
- package/dist/workflow.d.ts +2 -2
- package/dist/workflow.js +4 -4
- package/docs/error-codes.md +1 -1
- package/docs/harness-capability-map.md +17 -1
- package/package.json +1 -1
- package/dist/agent-47NS6ZVL.cjs +0 -67
- package/dist/agent-JJZM2VIK.js +0 -58
- package/dist/chunk-2UXQASTX.js.map +0 -1
- package/dist/chunk-5NELQ6LB.js.map +0 -1
- package/dist/chunk-6M2OIS4Y.js.map +0 -1
- package/dist/chunk-7IZKTQ5G.cjs.map +0 -1
- package/dist/chunk-ALUN2B4W.js.map +0 -1
- package/dist/chunk-ANMJJD6D.cjs +0 -18
- package/dist/chunk-ATT276RD.cjs.map +0 -1
- package/dist/chunk-C4ZQPWXJ.cjs.map +0 -1
- package/dist/chunk-EIOMN5VA.cjs.map +0 -1
- package/dist/chunk-GCHZMH42.cjs.map +0 -1
- package/dist/chunk-HUDNLFY4.js.map +0 -1
- package/dist/chunk-J7J7J2GN.cjs.map +0 -1
- package/dist/chunk-KZSKIUXZ.js.map +0 -1
- package/dist/chunk-LD6HASA5.cjs.map +0 -1
- package/dist/chunk-N2KAIZ5D.js.map +0 -1
- package/dist/compact-session-7FMYJXQ7.cjs +0 -61
- package/dist/compact-session-YSEK7NQF.js +0 -24
- package/dist/context-HR4KMXMA.cjs +0 -23
- package/dist/context-J5BJ3LBS.js +0 -6
- package/dist/fs-session-store-77JU46UZ.js +0 -10
- package/dist/fs-session-store-E4U3P56L.cjs +0 -19
- package/dist/generate-object-BXV7BZRP.js +0 -7
- package/dist/generate-object-YBI2TDJ3.cjs +0 -20
- package/dist/index-manager-27WLNQEE.js +0 -17
- package/dist/judge-call-46M2E5FA.cjs +0 -22
- package/dist/judge-call-FGUNNWEI.js +0 -5
- package/dist/oauth-transaction-store-5RIR6D5C.js +0 -5
- package/dist/oauth-transaction-store-SXIE57OD.cjs +0 -38
- package/dist/stream-object-HBFMIZLD.js +0 -7
- package/dist/stream-object-QSKHISDJ.cjs +0 -20
- package/dist/subagents-loader-CJFYQQU2.js +0 -7
- package/dist/subagents-loader-MOO7DC4E.cjs +0 -16
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var chunkYRJA2POB_cjs = require('./chunk-YRJA2POB.cjs');
|
|
4
|
+
|
|
5
|
+
// src/providers.ts
|
|
6
|
+
function listProviders2() {
|
|
7
|
+
chunkYRJA2POB_cjs.registerBuiltins();
|
|
8
|
+
return chunkYRJA2POB_cjs.listProviders();
|
|
9
|
+
}
|
|
10
|
+
function getProviderProfile2(name) {
|
|
11
|
+
chunkYRJA2POB_cjs.registerBuiltins();
|
|
12
|
+
return chunkYRJA2POB_cjs.getProviderProfile(name);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
exports.getProviderProfile = getProviderProfile2;
|
|
16
|
+
exports.listProviders = listProviders2;
|
|
17
|
+
//# sourceMappingURL=chunk-R3ZQBPA5.cjs.map
|
|
18
|
+
//# sourceMappingURL=chunk-R3ZQBPA5.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/providers.ts"],"names":["listProviders","registerBuiltins","getProviderProfile"],"mappings":";;;;;AA8BO,SAASA,cAAAA,GAA4C;AAC1D,EAAAC,kCAAA,EAAiB;AACjB,EAAA,OAAOD,+BAAA,EAAa;AACtB;AAQO,SAASE,oBAAmB,IAAA,EAA2C;AAC5E,EAAAD,kCAAA,EAAiB;AACjB,EAAA,OAAOC,qCAAW,IAAI,CAAA;AACxB","file":"chunk-
|
|
1
|
+
{"version":3,"sources":["../src/providers.ts"],"names":["listProviders","registerBuiltins","getProviderProfile"],"mappings":";;;;;AA8BO,SAASA,cAAAA,GAA4C;AAC1D,EAAAC,kCAAA,EAAiB;AACjB,EAAA,OAAOD,+BAAA,EAAa;AACtB;AAQO,SAASE,oBAAmB,IAAA,EAA2C;AAC5E,EAAAD,kCAAA,EAAiB;AACjB,EAAA,OAAOC,qCAAW,IAAI,CAAA;AACxB","file":"chunk-R3ZQBPA5.cjs","sourcesContent":["/**\n * Published as `@theokit/sdk/providers`.\n *\n * The provider registry, as public API.\n *\n * It was `@internal`, which meant the SDK was the only thing that could answer \"which providers\n * exist, and what does each one need?\". `theokit` consequently kept a hand-written list of three —\n * against the 46 registered here — so an agent declaring `ollama/qwen2.5:3b` routed to whatever\n * key happened to be set instead of to Ollama (usetheokit/theokit#326).\n *\n * A second table that nothing forces to agree with the first is not a cache, it is a future bug.\n * These two functions exist so there is one table.\n *\n * Both ensure the builtins are registered before answering: registration is lazy (it happens when\n * an agent is created, a run is routed, or a provider is defined), so a caller asking early would\n * otherwise get an empty registry and reasonably conclude the SDK knows nothing.\n */\n\nimport { registerBuiltins } from \"./internal/providers/builtin/index.js\";\nimport {\n getProviderProfile as getProfile,\n listProviders as listProfiles,\n} from \"./internal/providers/registry.js\";\nimport type { ProviderProfile } from \"./internal/providers/types.js\";\n\n/**\n * Every registered provider — builtins, the JSON catalog, and anything a plugin registered.\n *\n * @public\n */\nexport function listProviders(): readonly ProviderProfile[] {\n registerBuiltins();\n return listProfiles();\n}\n\n/**\n * One provider by name or alias (`lm-studio` resolves to `lmstudio`), or `undefined` when nothing\n * has registered it.\n *\n * @public\n */\nexport function getProviderProfile(name: string): ProviderProfile | undefined {\n registerBuiltins();\n return getProfile(name);\n}\n"]}
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
var
|
|
3
|
+
var chunkNAGPKWOD_cjs = require('./chunk-NAGPKWOD.cjs');
|
|
4
|
+
var chunkOLSEWLK5_cjs = require('./chunk-OLSEWLK5.cjs');
|
|
5
5
|
|
|
6
6
|
// src/internal/auth/oauth-engine.ts
|
|
7
7
|
var REFRESH_SKEW_MS = 6e4;
|
|
8
8
|
function parseTokenResponse(body, now) {
|
|
9
9
|
const b = body;
|
|
10
10
|
if (typeof b.access_token !== "string" || b.access_token.length === 0) {
|
|
11
|
-
throw new
|
|
11
|
+
throw new chunkOLSEWLK5_cjs.AuthCallbackError(
|
|
12
12
|
"oauth_token_exchange_failed",
|
|
13
13
|
"token response had no access_token"
|
|
14
14
|
);
|
|
15
15
|
}
|
|
16
16
|
if (typeof b.refresh_token !== "string" || b.refresh_token.length === 0) {
|
|
17
|
-
throw new
|
|
17
|
+
throw new chunkOLSEWLK5_cjs.AuthCallbackError(
|
|
18
18
|
"oauth_token_exchange_failed",
|
|
19
19
|
"token response had no refresh_token"
|
|
20
20
|
);
|
|
@@ -36,13 +36,13 @@ async function postGrant(config, form, deps) {
|
|
|
36
36
|
body: new URLSearchParams(form).toString()
|
|
37
37
|
});
|
|
38
38
|
} catch (err) {
|
|
39
|
-
throw new
|
|
39
|
+
throw new chunkOLSEWLK5_cjs.AuthCallbackError(
|
|
40
40
|
"oauth_token_exchange_failed",
|
|
41
41
|
`token endpoint request failed: ${err.message}`
|
|
42
42
|
);
|
|
43
43
|
}
|
|
44
44
|
if (!res.ok) {
|
|
45
|
-
throw new
|
|
45
|
+
throw new chunkOLSEWLK5_cjs.AuthCallbackError(
|
|
46
46
|
"oauth_token_exchange_failed",
|
|
47
47
|
`token endpoint returned HTTP ${res.status}`
|
|
48
48
|
);
|
|
@@ -51,7 +51,7 @@ async function postGrant(config, form, deps) {
|
|
|
51
51
|
try {
|
|
52
52
|
json = await res.json();
|
|
53
53
|
} catch {
|
|
54
|
-
throw new
|
|
54
|
+
throw new chunkOLSEWLK5_cjs.AuthCallbackError("oauth_token_exchange_failed", "token response was not valid JSON");
|
|
55
55
|
}
|
|
56
56
|
return parseTokenResponse(json, deps.now());
|
|
57
57
|
}
|
|
@@ -76,7 +76,7 @@ function refreshOAuthTokens(config, refresh, deps) {
|
|
|
76
76
|
);
|
|
77
77
|
}
|
|
78
78
|
function persistOAuthTokens(provider, tokens, store, env = {}) {
|
|
79
|
-
return
|
|
79
|
+
return chunkNAGPKWOD_cjs.writeCredential(
|
|
80
80
|
{
|
|
81
81
|
type: "oauth",
|
|
82
82
|
provider,
|
|
@@ -97,13 +97,13 @@ async function ensureFreshCredential(resolved, opts, deps) {
|
|
|
97
97
|
return resolved;
|
|
98
98
|
}
|
|
99
99
|
const env = opts.env ?? {};
|
|
100
|
-
const path =
|
|
100
|
+
const path = chunkNAGPKWOD_cjs.authFilePath(opts.store, env);
|
|
101
101
|
let refresh = inFlightRefresh.get(path);
|
|
102
102
|
if (refresh === void 0) {
|
|
103
103
|
refresh = (async () => {
|
|
104
|
-
const stored =
|
|
104
|
+
const stored = chunkNAGPKWOD_cjs.readStoredOAuth(opts.store, env);
|
|
105
105
|
if (stored === void 0) {
|
|
106
|
-
throw new
|
|
106
|
+
throw new chunkOLSEWLK5_cjs.AuthCallbackError(
|
|
107
107
|
"oauth_token_exchange_failed",
|
|
108
108
|
"no stored oauth credential to refresh"
|
|
109
109
|
);
|
|
@@ -151,9 +151,9 @@ async function resolveOAuth(stored, path, opts, env) {
|
|
|
151
151
|
}
|
|
152
152
|
async function resolveCredential(opts) {
|
|
153
153
|
const env = opts.env ?? {};
|
|
154
|
-
const stored =
|
|
154
|
+
const stored = chunkNAGPKWOD_cjs.readAuthFile(opts.store, env);
|
|
155
155
|
if (stored === void 0) return void 0;
|
|
156
|
-
const path =
|
|
156
|
+
const path = chunkNAGPKWOD_cjs.authFilePath(opts.store, env);
|
|
157
157
|
if (stored.type === "oauth") {
|
|
158
158
|
return resolveOAuth(stored, path, opts, env);
|
|
159
159
|
}
|
|
@@ -173,5 +173,5 @@ exports.exchangeCode = exchangeCode;
|
|
|
173
173
|
exports.persistOAuthTokens = persistOAuthTokens;
|
|
174
174
|
exports.refreshOAuthTokens = refreshOAuthTokens;
|
|
175
175
|
exports.resolveCredential = resolveCredential;
|
|
176
|
-
//# sourceMappingURL=chunk-
|
|
177
|
-
//# sourceMappingURL=chunk-
|
|
176
|
+
//# sourceMappingURL=chunk-RA7IE4NK.cjs.map
|
|
177
|
+
//# sourceMappingURL=chunk-RA7IE4NK.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/internal/auth/oauth-engine.ts","../src/internal/auth/resolve-credential.ts"],"names":["AuthCallbackError","writeCredential","authFilePath","readStoredOAuth","fresh","readAuthFile"],"mappings":"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","file":"chunk-4NLCWGH7.cjs","sourcesContent":["/**\n * M42 — the SDK OAuth engine. Promoted DOWN from agent-builder's hardened `agents/lib/oauth.ts` +\n * `oauth-device.ts` (M37), generalized to `provider: string` + a caller-supplied {@link CredentialStoreConfig}\n * (no hardcoded client IDs — the caller declares its provider's endpoints). Ported VERBATIM (ADR D3): the\n * refresh coalescing lock, the no-token-in-error discipline, and the RFC 8628 device grant.\n *\n * Reuses the SDK's typed error taxonomy (`AuthCallbackError` from `server/auth`) for exchange/refresh\n * failures. All network I/O + clock + sleep are INJECTED so the flow is deterministic.\n *\n * The device flows follow their published specs: the RFC 8628 device grant (device_code →\n * authorization_pending / slow_down) and OpenAI's two-step headless flow with JWT-claim account attribution.\n *\n * @internal\n */\nimport { AuthCallbackError } from \"../../server/auth/errors.js\";\nimport { authFilePath, readStoredOAuth, writeCredential } from \"./credential-store.js\";\nimport type {\n CredentialStoreConfig,\n HttpDeps,\n OAuthProviderConfig,\n OAuthTokens,\n ResolvedCredential,\n} from \"./types.js\";\n\n/** Refresh a token this many ms BEFORE it actually expires (avoid a last-second, mid-request expiry). */\nconst REFRESH_SKEW_MS = 60_000;\n\n/** Parse an OAuth token endpoint response into our token triple. Throws a typed error on a bad shape. */\nfunction parseTokenResponse(body: unknown, now: number): OAuthTokens {\n const b = body as {\n access_token?: unknown;\n refresh_token?: unknown;\n expires_in?: unknown;\n account_id?: unknown;\n };\n if (typeof b.access_token !== \"string\" || b.access_token.length === 0) {\n throw new AuthCallbackError(\n \"oauth_token_exchange_failed\",\n \"token response had no access_token\",\n );\n }\n if (typeof b.refresh_token !== \"string\" || b.refresh_token.length === 0) {\n throw new AuthCallbackError(\n \"oauth_token_exchange_failed\",\n \"token response had no refresh_token\",\n );\n }\n const expiresIn = typeof b.expires_in === \"number\" ? b.expires_in : 3600;\n return {\n access: b.access_token,\n refresh: b.refresh_token,\n expires: now + expiresIn * 1000,\n ...(typeof b.account_id === \"string\" ? { accountId: b.account_id } : {}),\n };\n}\n\n/** POST a form-encoded grant to the token endpoint; return the parsed JSON or throw a typed error. */\nasync function postGrant(\n config: OAuthProviderConfig,\n form: Record<string, string>,\n deps: HttpDeps,\n): Promise<OAuthTokens> {\n let res: Response;\n try {\n res = await deps.fetch(config.tokenEndpoint, {\n method: \"POST\",\n headers: { \"content-type\": \"application/x-www-form-urlencoded\", accept: \"application/json\" },\n body: new URLSearchParams(form).toString(),\n });\n } catch (err) {\n throw new AuthCallbackError(\n \"oauth_token_exchange_failed\",\n `token endpoint request failed: ${(err as Error).message}`,\n );\n }\n if (!res.ok) {\n // The body may carry an OAuth `error` code, but never echo it verbatim — it can contain a token in\n // some providers' error payloads. Report the status only.\n throw new AuthCallbackError(\n \"oauth_token_exchange_failed\",\n `token endpoint returned HTTP ${res.status}`,\n );\n }\n let json: unknown;\n try {\n json = await res.json();\n } catch {\n // Do NOT echo the parser message — on a 200 non-JSON body it embeds a snippet of the response, which\n // in a token context can contain access/refresh material.\n throw new AuthCallbackError(\"oauth_token_exchange_failed\", \"token response was not valid JSON\");\n }\n return parseTokenResponse(json, deps.now());\n}\n\n/** Exchange an authorization `code` (+ PKCE verifier) for the token pair. */\nexport function exchangeCode(\n config: OAuthProviderConfig,\n input: { code: string; verifier: string },\n deps: HttpDeps,\n): Promise<OAuthTokens> {\n return postGrant(\n config,\n {\n grant_type: \"authorization_code\",\n code: input.code,\n redirect_uri: config.redirectUri,\n client_id: config.clientId,\n code_verifier: input.verifier,\n },\n deps,\n );\n}\n\n/** Swap a refresh token for a fresh access (and possibly rotated refresh) token. */\nexport function refreshOAuthTokens(\n config: OAuthProviderConfig,\n refresh: string,\n deps: HttpDeps,\n): Promise<OAuthTokens> {\n return postGrant(\n config,\n { grant_type: \"refresh_token\", refresh_token: refresh, client_id: config.clientId },\n deps,\n );\n}\n\n/** Persist a token triple to the store's oauth variant through the hardened 0600 writer. */\nexport function persistOAuthTokens(\n provider: string,\n tokens: OAuthTokens,\n store: CredentialStoreConfig,\n env: Record<string, string | undefined> = {},\n): string {\n return writeCredential(\n {\n type: \"oauth\",\n provider,\n access: tokens.access,\n refresh: tokens.refresh,\n expires: tokens.expires,\n ...(tokens.accountId !== undefined ? { account_id: tokens.accountId } : {}),\n },\n store,\n env,\n );\n}\n\n/**\n * In-flight refreshes, keyed by the auth-file path. Refresh tokens ROTATE (single-use) on many providers,\n * so two concurrent turns must NOT both POST the same refresh token — the second would present an\n * already-consumed token and fail. This coalesces concurrent refreshes of the same store onto one promise.\n * Process-local — the single-credential store is per-user; a cross-process lock would be over-engineering.\n */\nconst inFlightRefresh = new Map<string, Promise<OAuthTokens>>();\n\n/**\n * Return a credential guaranteed fresh enough to use. An `api` credential passes through untouched. An\n * `oauth` credential still valid (beyond the skew window) passes through; an expired one is refreshed,\n * re-persisted 0600, and returned with the new access token. Concurrent refreshes of the same store are\n * coalesced (single-use refresh tokens); the rejected promise is evicted so a failure is not cached-poison.\n */\nexport async function ensureFreshCredential(\n resolved: ResolvedCredential,\n opts: {\n config: OAuthProviderConfig;\n store: CredentialStoreConfig;\n env?: Record<string, string | undefined>;\n },\n deps: HttpDeps,\n): Promise<ResolvedCredential> {\n if (resolved.kind !== \"oauth\") return resolved;\n\n const now = deps.now();\n if (resolved.expiresAt !== undefined && resolved.expiresAt > now + REFRESH_SKEW_MS) {\n return resolved; // still valid — no network, no rewrite\n }\n\n const env = opts.env ?? {};\n const path = authFilePath(opts.store, env);\n let refresh = inFlightRefresh.get(path);\n if (refresh === undefined) {\n refresh = (async (): Promise<OAuthTokens> => {\n const stored = readStoredOAuth(opts.store, env);\n if (stored === undefined) {\n // The resolved credential said oauth but the store no longer holds it — do not fabricate; surface it.\n throw new AuthCallbackError(\n \"oauth_token_exchange_failed\",\n \"no stored oauth credential to refresh\",\n );\n }\n const fresh = await refreshOAuthTokens(opts.config, stored.refresh, deps);\n // M43 D4 fix #1 — the OAuth refresh response returns JWTs, not a top-level `account_id`, so\n // `parseTokenResponse` leaves `fresh.accountId` undefined. Prefer a freshly-derived id, else PRESERVE\n // the stored one (account_id is stable) — otherwise the Codex `ChatGPT-Account-Id` header empties after\n // the first refresh and the backend 401/403s.\n const merged: OAuthTokens = {\n ...fresh,\n accountId: fresh.accountId ?? stored.account_id,\n };\n persistOAuthTokens(resolved.provider, merged, opts.store, env);\n return merged;\n })();\n inFlightRefresh.set(path, refresh);\n refresh.finally(() => inFlightRefresh.delete(path)).catch(() => {});\n }\n\n const fresh = await refresh;\n return {\n kind: \"oauth\",\n provider: resolved.provider,\n apiKey: fresh.access,\n source: resolved.source,\n inferred: false,\n expiresAt: fresh.expires,\n };\n}\n","/**\n * M42 — `resolveCredential`: the public composition entrypoint over the credential store + oauth engine.\n * Given a provider name + a {@link CredentialStoreConfig} (and, for oauth, an {@link OAuthProviderConfig}),\n * read the store and return a FRESH `ResolvedCredential` — an api credential passes through by identity; an\n * oauth credential is transparently refreshed when its access token is within the skew window. Returns\n * `undefined` when the store holds no credential for `provider` (the caller then falls back to env / apiKeys).\n *\n * Mirrors agent-builder's `resolveFreshCredential` composition (store read → oauth → ensureFreshCredential),\n * defaulting `fetch`/`now` to globals. This is the async surface an oauth provider's M41 `transform.fetch`\n * calls at stream time, so a mid-turn token expiry refreshes without rebuilding the agent.\n *\n * Re-exported from `@theokit/sdk/auth`, and therefore PUBLIC, under semver.\n *\n * NOTE — no internal-visibility tag in this block. `tsconfig.base.json` sets `stripInternal: true`,\n * and TypeScript scans EVERY leading comment range of the declaration that follows, including the\n * import right below this one. The tag that used to sit here deleted that import from the emitted\n * `.d.ts`, leaving the types it binds unresolvable for any consumer running type-aware lint\n * (usetheodev/theokit-sdk#283 records the same trap on a declaration).\n */\n\nimport { authFilePath, readAuthFile } from \"./credential-store.js\";\nimport { ensureFreshCredential } from \"./oauth-engine.js\";\nimport type {\n CredentialStoreConfig,\n HttpDeps,\n OAuthProviderConfig,\n ResolvedCredential,\n} from \"./types.js\";\n\n/**\n * Input to `resolveCredential`: which provider, which store, and what to inject.\n *\n * `env` and `deps` exist so nothing here reads ambient state. Omitting `env` does NOT fall back to\n * `process.env` — the store's `homeEnvVar` override simply goes unread, so a credential written\n * under a relocated home resolves as absent rather than as an error.\n *\n * `oauth` is required only to REFRESH an oauth credential. Without it an expired oauth entry cannot\n * be renewed, and an api-key-only store needs it never.\n *\n * PUBLIC and under semver, despite the `internal/` directory: `src/auth/index.ts` re-exports this\n * type, and `package.json` publishes that barrel as the '@theokit/sdk/auth' subpath. The directory\n * name is not the authority — the `exports` map is. The semver-exempt class is the sub-paths\n * declared under '@theokit/sdk/internal/*' ('internal/persistence', 'internal/security',\n * 'internal/memory-adapters'); no `exports` entry reaches this file that way.\n */\nexport interface ResolveCredentialOptions {\n /** The provider whose stored credential to resolve. */\n provider: string;\n /** Where the credential store lives. */\n store: CredentialStoreConfig;\n /** Env for the store's optional `homeEnvVar` override. Never an ambient read. */\n env?: Record<string, string | undefined>;\n /** Required to refresh an oauth credential; omit for an api-only store. */\n oauth?: OAuthProviderConfig;\n /** Injected HTTP + clock for deterministic tests; default globals. */\n deps?: { fetch?: typeof fetch; now?: () => number };\n}\n\n/** Resolve (and, when a config is supplied, refresh) the oauth variant for the requested provider. */\nasync function resolveOAuth(\n stored: { provider: string; access: string; expires: number },\n path: string,\n opts: ResolveCredentialOptions,\n env: Record<string, string | undefined>,\n): Promise<ResolvedCredential | undefined> {\n if (stored.provider !== opts.provider) return undefined;\n const base: ResolvedCredential = {\n kind: \"oauth\",\n provider: opts.provider,\n apiKey: stored.access,\n source: path,\n inferred: false,\n expiresAt: stored.expires,\n };\n if (opts.oauth === undefined) return base; // no config to refresh with — return the stored access token\n const deps: HttpDeps = {\n fetch: opts.deps?.fetch ?? fetch,\n now: opts.deps?.now ?? (() => Date.now()),\n };\n return ensureFreshCredential(base, { config: opts.oauth, store: opts.store, env }, deps);\n}\n\n/**\n * Resolve a fresh credential for `provider` from the store, or `undefined` if the store holds none for it.\n * oauth credentials are auto-refreshed when `opts.oauth` is supplied; api credentials pass through.\n */\nexport async function resolveCredential(\n opts: ResolveCredentialOptions,\n): Promise<ResolvedCredential | undefined> {\n const env = opts.env ?? {};\n const stored = readAuthFile(opts.store, env);\n if (stored === undefined) return undefined;\n\n const path = authFilePath(opts.store, env);\n\n if (stored.type === \"oauth\") {\n return resolveOAuth(stored, path, opts, env);\n }\n\n // api variant: require the stored `provider` to MATCH the requested provider (M42 review MEDIUM-2).\n // The generic SDK cannot infer a provider from a key prefix (that was agent-builder app policy), so a\n // provider-less or mismatched stored key is NOT attributed to the requested provider — otherwise a legacy\n // `{api_key:\"sk-ant-…\"}` file could be POSTed to the wrong vendor's endpoint (cross-vendor key exposure).\n // Fail-closed: credential resolution never attributes a key across providers.\n if (stored.api_key.length === 0) return undefined;\n if (stored.provider !== opts.provider) return undefined;\n return {\n kind: \"api\",\n provider: opts.provider,\n apiKey: stored.api_key,\n source: path,\n inferred: false,\n };\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/internal/auth/oauth-engine.ts","../src/internal/auth/resolve-credential.ts"],"names":["AuthCallbackError","writeCredential","authFilePath","readStoredOAuth","fresh","readAuthFile"],"mappings":"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","file":"chunk-RA7IE4NK.cjs","sourcesContent":["/**\n * M42 — the SDK OAuth engine. Promoted DOWN from agent-builder's hardened `agents/lib/oauth.ts` +\n * `oauth-device.ts` (M37), generalized to `provider: string` + a caller-supplied {@link CredentialStoreConfig}\n * (no hardcoded client IDs — the caller declares its provider's endpoints). Ported VERBATIM (ADR D3): the\n * refresh coalescing lock, the no-token-in-error discipline, and the RFC 8628 device grant.\n *\n * Reuses the SDK's typed error taxonomy (`AuthCallbackError` from `server/auth`) for exchange/refresh\n * failures. All network I/O + clock + sleep are INJECTED so the flow is deterministic.\n *\n * The device flows follow their published specs: the RFC 8628 device grant (device_code →\n * authorization_pending / slow_down) and OpenAI's two-step headless flow with JWT-claim account attribution.\n *\n * @internal\n */\nimport { AuthCallbackError } from \"../../server/auth/errors.js\";\nimport { authFilePath, readStoredOAuth, writeCredential } from \"./credential-store.js\";\nimport type {\n CredentialStoreConfig,\n HttpDeps,\n OAuthProviderConfig,\n OAuthTokens,\n ResolvedCredential,\n} from \"./types.js\";\n\n/** Refresh a token this many ms BEFORE it actually expires (avoid a last-second, mid-request expiry). */\nconst REFRESH_SKEW_MS = 60_000;\n\n/** Parse an OAuth token endpoint response into our token triple. Throws a typed error on a bad shape. */\nfunction parseTokenResponse(body: unknown, now: number): OAuthTokens {\n const b = body as {\n access_token?: unknown;\n refresh_token?: unknown;\n expires_in?: unknown;\n account_id?: unknown;\n };\n if (typeof b.access_token !== \"string\" || b.access_token.length === 0) {\n throw new AuthCallbackError(\n \"oauth_token_exchange_failed\",\n \"token response had no access_token\",\n );\n }\n if (typeof b.refresh_token !== \"string\" || b.refresh_token.length === 0) {\n throw new AuthCallbackError(\n \"oauth_token_exchange_failed\",\n \"token response had no refresh_token\",\n );\n }\n const expiresIn = typeof b.expires_in === \"number\" ? b.expires_in : 3600;\n return {\n access: b.access_token,\n refresh: b.refresh_token,\n expires: now + expiresIn * 1000,\n ...(typeof b.account_id === \"string\" ? { accountId: b.account_id } : {}),\n };\n}\n\n/** POST a form-encoded grant to the token endpoint; return the parsed JSON or throw a typed error. */\nasync function postGrant(\n config: OAuthProviderConfig,\n form: Record<string, string>,\n deps: HttpDeps,\n): Promise<OAuthTokens> {\n let res: Response;\n try {\n res = await deps.fetch(config.tokenEndpoint, {\n method: \"POST\",\n headers: { \"content-type\": \"application/x-www-form-urlencoded\", accept: \"application/json\" },\n body: new URLSearchParams(form).toString(),\n });\n } catch (err) {\n throw new AuthCallbackError(\n \"oauth_token_exchange_failed\",\n `token endpoint request failed: ${(err as Error).message}`,\n );\n }\n if (!res.ok) {\n // The body may carry an OAuth `error` code, but never echo it verbatim — it can contain a token in\n // some providers' error payloads. Report the status only.\n throw new AuthCallbackError(\n \"oauth_token_exchange_failed\",\n `token endpoint returned HTTP ${res.status}`,\n );\n }\n let json: unknown;\n try {\n json = await res.json();\n } catch {\n // Do NOT echo the parser message — on a 200 non-JSON body it embeds a snippet of the response, which\n // in a token context can contain access/refresh material.\n throw new AuthCallbackError(\"oauth_token_exchange_failed\", \"token response was not valid JSON\");\n }\n return parseTokenResponse(json, deps.now());\n}\n\n/** Exchange an authorization `code` (+ PKCE verifier) for the token pair. */\nexport function exchangeCode(\n config: OAuthProviderConfig,\n input: { code: string; verifier: string },\n deps: HttpDeps,\n): Promise<OAuthTokens> {\n return postGrant(\n config,\n {\n grant_type: \"authorization_code\",\n code: input.code,\n redirect_uri: config.redirectUri,\n client_id: config.clientId,\n code_verifier: input.verifier,\n },\n deps,\n );\n}\n\n/** Swap a refresh token for a fresh access (and possibly rotated refresh) token. */\nexport function refreshOAuthTokens(\n config: OAuthProviderConfig,\n refresh: string,\n deps: HttpDeps,\n): Promise<OAuthTokens> {\n return postGrant(\n config,\n { grant_type: \"refresh_token\", refresh_token: refresh, client_id: config.clientId },\n deps,\n );\n}\n\n/** Persist a token triple to the store's oauth variant through the hardened 0600 writer. */\nexport function persistOAuthTokens(\n provider: string,\n tokens: OAuthTokens,\n store: CredentialStoreConfig,\n env: Record<string, string | undefined> = {},\n): string {\n return writeCredential(\n {\n type: \"oauth\",\n provider,\n access: tokens.access,\n refresh: tokens.refresh,\n expires: tokens.expires,\n ...(tokens.accountId !== undefined ? { account_id: tokens.accountId } : {}),\n },\n store,\n env,\n );\n}\n\n/**\n * In-flight refreshes, keyed by the auth-file path. Refresh tokens ROTATE (single-use) on many providers,\n * so two concurrent turns must NOT both POST the same refresh token — the second would present an\n * already-consumed token and fail. This coalesces concurrent refreshes of the same store onto one promise.\n * Process-local — the single-credential store is per-user; a cross-process lock would be over-engineering.\n */\nconst inFlightRefresh = new Map<string, Promise<OAuthTokens>>();\n\n/**\n * Return a credential guaranteed fresh enough to use. An `api` credential passes through untouched. An\n * `oauth` credential still valid (beyond the skew window) passes through; an expired one is refreshed,\n * re-persisted 0600, and returned with the new access token. Concurrent refreshes of the same store are\n * coalesced (single-use refresh tokens); the rejected promise is evicted so a failure is not cached-poison.\n */\nexport async function ensureFreshCredential(\n resolved: ResolvedCredential,\n opts: {\n config: OAuthProviderConfig;\n store: CredentialStoreConfig;\n env?: Record<string, string | undefined>;\n },\n deps: HttpDeps,\n): Promise<ResolvedCredential> {\n if (resolved.kind !== \"oauth\") return resolved;\n\n const now = deps.now();\n if (resolved.expiresAt !== undefined && resolved.expiresAt > now + REFRESH_SKEW_MS) {\n return resolved; // still valid — no network, no rewrite\n }\n\n const env = opts.env ?? {};\n const path = authFilePath(opts.store, env);\n let refresh = inFlightRefresh.get(path);\n if (refresh === undefined) {\n refresh = (async (): Promise<OAuthTokens> => {\n const stored = readStoredOAuth(opts.store, env);\n if (stored === undefined) {\n // The resolved credential said oauth but the store no longer holds it — do not fabricate; surface it.\n throw new AuthCallbackError(\n \"oauth_token_exchange_failed\",\n \"no stored oauth credential to refresh\",\n );\n }\n const fresh = await refreshOAuthTokens(opts.config, stored.refresh, deps);\n // M43 D4 fix #1 — the OAuth refresh response returns JWTs, not a top-level `account_id`, so\n // `parseTokenResponse` leaves `fresh.accountId` undefined. Prefer a freshly-derived id, else PRESERVE\n // the stored one (account_id is stable) — otherwise the Codex `ChatGPT-Account-Id` header empties after\n // the first refresh and the backend 401/403s.\n const merged: OAuthTokens = {\n ...fresh,\n accountId: fresh.accountId ?? stored.account_id,\n };\n persistOAuthTokens(resolved.provider, merged, opts.store, env);\n return merged;\n })();\n inFlightRefresh.set(path, refresh);\n refresh.finally(() => inFlightRefresh.delete(path)).catch(() => {});\n }\n\n const fresh = await refresh;\n return {\n kind: \"oauth\",\n provider: resolved.provider,\n apiKey: fresh.access,\n source: resolved.source,\n inferred: false,\n expiresAt: fresh.expires,\n };\n}\n","/**\n * M42 — `resolveCredential`: the public composition entrypoint over the credential store + oauth engine.\n * Given a provider name + a {@link CredentialStoreConfig} (and, for oauth, an {@link OAuthProviderConfig}),\n * read the store and return a FRESH `ResolvedCredential` — an api credential passes through by identity; an\n * oauth credential is transparently refreshed when its access token is within the skew window. Returns\n * `undefined` when the store holds no credential for `provider` (the caller then falls back to env / apiKeys).\n *\n * Mirrors agent-builder's `resolveFreshCredential` composition (store read → oauth → ensureFreshCredential),\n * defaulting `fetch`/`now` to globals. This is the async surface an oauth provider's M41 `transform.fetch`\n * calls at stream time, so a mid-turn token expiry refreshes without rebuilding the agent.\n *\n * Re-exported from `@theokit/sdk/auth`, and therefore PUBLIC, under semver.\n *\n * NOTE — no internal-visibility tag in this block. `tsconfig.base.json` sets `stripInternal: true`,\n * and TypeScript scans EVERY leading comment range of the declaration that follows, including the\n * import right below this one. The tag that used to sit here deleted that import from the emitted\n * `.d.ts`, leaving the types it binds unresolvable for any consumer running type-aware lint\n * (usetheodev/theokit-sdk#283 records the same trap on a declaration).\n */\n\nimport { authFilePath, readAuthFile } from \"./credential-store.js\";\nimport { ensureFreshCredential } from \"./oauth-engine.js\";\nimport type {\n CredentialStoreConfig,\n HttpDeps,\n OAuthProviderConfig,\n ResolvedCredential,\n} from \"./types.js\";\n\n/**\n * Input to `resolveCredential`: which provider, which store, and what to inject.\n *\n * `env` and `deps` exist so nothing here reads ambient state. Omitting `env` does NOT fall back to\n * `process.env` — the store's `homeEnvVar` override simply goes unread, so a credential written\n * under a relocated home resolves as absent rather than as an error.\n *\n * `oauth` is required only to REFRESH an oauth credential. Without it an expired oauth entry cannot\n * be renewed, and an api-key-only store needs it never.\n *\n * PUBLIC and under semver, despite the `internal/` directory: `src/auth/index.ts` re-exports this\n * type, and `package.json` publishes that barrel as the '@theokit/sdk/auth' subpath. The directory\n * name is not the authority — the `exports` map is. The semver-exempt class is the sub-paths\n * declared under '@theokit/sdk/internal/*' ('internal/persistence', 'internal/security',\n * 'internal/memory-adapters'); no `exports` entry reaches this file that way.\n */\nexport interface ResolveCredentialOptions {\n /** The provider whose stored credential to resolve. */\n provider: string;\n /** Where the credential store lives. */\n store: CredentialStoreConfig;\n /** Env for the store's optional `homeEnvVar` override. Never an ambient read. */\n env?: Record<string, string | undefined>;\n /** Required to refresh an oauth credential; omit for an api-only store. */\n oauth?: OAuthProviderConfig;\n /** Injected HTTP + clock for deterministic tests; default globals. */\n deps?: { fetch?: typeof fetch; now?: () => number };\n}\n\n/** Resolve (and, when a config is supplied, refresh) the oauth variant for the requested provider. */\nasync function resolveOAuth(\n stored: { provider: string; access: string; expires: number },\n path: string,\n opts: ResolveCredentialOptions,\n env: Record<string, string | undefined>,\n): Promise<ResolvedCredential | undefined> {\n if (stored.provider !== opts.provider) return undefined;\n const base: ResolvedCredential = {\n kind: \"oauth\",\n provider: opts.provider,\n apiKey: stored.access,\n source: path,\n inferred: false,\n expiresAt: stored.expires,\n };\n if (opts.oauth === undefined) return base; // no config to refresh with — return the stored access token\n const deps: HttpDeps = {\n fetch: opts.deps?.fetch ?? fetch,\n now: opts.deps?.now ?? (() => Date.now()),\n };\n return ensureFreshCredential(base, { config: opts.oauth, store: opts.store, env }, deps);\n}\n\n/**\n * Resolve a fresh credential for `provider` from the store, or `undefined` if the store holds none for it.\n * oauth credentials are auto-refreshed when `opts.oauth` is supplied; api credentials pass through.\n */\nexport async function resolveCredential(\n opts: ResolveCredentialOptions,\n): Promise<ResolvedCredential | undefined> {\n const env = opts.env ?? {};\n const stored = readAuthFile(opts.store, env);\n if (stored === undefined) return undefined;\n\n const path = authFilePath(opts.store, env);\n\n if (stored.type === \"oauth\") {\n return resolveOAuth(stored, path, opts, env);\n }\n\n // api variant: require the stored `provider` to MATCH the requested provider (M42 review MEDIUM-2).\n // The generic SDK cannot infer a provider from a key prefix (that was agent-builder app policy), so a\n // provider-less or mismatched stored key is NOT attributed to the requested provider — otherwise a legacy\n // `{api_key:\"sk-ant-…\"}` file could be POSTed to the wrong vendor's endpoint (cross-vendor key exposure).\n // Fail-closed: credential resolution never attributes a key across providers.\n if (stored.api_key.length === 0) return undefined;\n if (stored.provider !== opts.provider) return undefined;\n return {\n kind: \"api\",\n provider: opts.provider,\n apiKey: stored.api_key,\n source: path,\n inferred: false,\n };\n}\n"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { sleepWithAbort } from './chunk-24MGQDK3.js';
|
|
2
2
|
import { withCwdMutex } from './chunk-Q5EWJPRY.js';
|
|
3
|
-
import { ConfigurationError } from './chunk-
|
|
3
|
+
import { ConfigurationError } from './chunk-B5MHRQJZ.js';
|
|
4
4
|
import { AsyncLocalStorage } from 'async_hooks';
|
|
5
5
|
|
|
6
6
|
// src/internal/llm/credential-pool-types.ts
|
|
@@ -271,5 +271,5 @@ function currentCredentialPool(provider) {
|
|
|
271
271
|
}
|
|
272
272
|
|
|
273
273
|
export { CredentialPool, currentCredentialPool, newPooledCredential, withCredentialPool };
|
|
274
|
-
//# sourceMappingURL=chunk-
|
|
275
|
-
//# sourceMappingURL=chunk-
|
|
274
|
+
//# sourceMappingURL=chunk-SUVCHX4L.js.map
|
|
275
|
+
//# sourceMappingURL=chunk-SUVCHX4L.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/internal/llm/credential-pool-types.ts","../src/internal/llm/credential-pool.ts","../src/internal/llm/credential-pool-context.ts"],"names":["picked"],"mappings":"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","file":"chunk-UBR5PWD7.js","sourcesContent":["/**\n * Types for the credential pool subsystem (ADRs D123-D133).\n *\n * Pool a developer's multiple API keys for the SAME provider so the SDK\n * can rotate transparently on HTTP 429/402/401 instead of jumping\n * straight to a different provider via `FallbackLlmClient`.\n *\n * @internal\n */\n\n/**\n * Rotation strategy when picking the next credential from a pool.\n *\n * - `fill_first` (default): use entries[0] until exhausted, then [1]…\n * - `round_robin`: rotate after each `select()`\n * - `least_used`: pick the entry with the lowest `requestCount`\n * - `random`: random pick among healthy entries\n *\n * Closed enum per ADR D124 — adding a strategy is an explicit semver\n * minor that updates `selectByStrategy` exhaustively.\n *\n * @internal\n */\nexport type CredentialPoolStrategy = \"fill_first\" | \"round_robin\" | \"least_used\" | \"random\";\n\n/** Health flag tracked per credential. */\nexport type CredentialStatus = \"ok\" | \"exhausted\";\n\n/**\n * Provenance of a credential — where it came from when seeded.\n * Free-form string; conventional prefixes:\n *\n * - `env:<VAR_NAME>` — auto-discovered from environment variable\n * - `manual` — added via explicit `apiKeys` config\n * - `explicit-apikey` — wrapped from `AgentOptions.apiKey` single-key path (D132)\n */\nexport type CredentialSource = string;\n\n/**\n * Single credential entry inside a {@link CredentialPool}.\n *\n * `accessToken` is the sensitive field — must never be logged unredacted.\n * The lint gate `tests/lint/no-unredacted-pool-token.test.ts` enforces this.\n *\n * @internal\n */\nexport interface PooledCredential {\n /** Stable identifier (uuid v4) for log lines + telemetry. */\n id: string;\n /** Human-readable label for `Theokit.credentialPool.list()`. */\n label: string;\n /** Provider name (matches `ProviderProfile.name`). */\n provider: string;\n /** Sort key; lower = earlier in fill_first. Unique within a pool. */\n priority: number;\n /** Provenance string. */\n source: CredentialSource;\n /** Sensitive API key. NEVER LOG UNREDACTED. */\n accessToken: string;\n /** Current health. */\n lastStatus: CredentialStatus;\n /** Epoch ms of the last status change. */\n lastStatusAt: number | undefined;\n /** HTTP code that caused exhaustion (401/402/429). */\n lastErrorCode: number | undefined;\n /** Provider-supplied \"retry after this epoch ms\" hint. Overrides cooldown defaults. */\n lastErrorResetAt: number | undefined;\n /** Bumped per successful `select()` for `least_used` strategy. Lazy-persisted. */\n requestCount: number;\n}\n\n/**\n * Serializable snapshot of a single provider's pool. Used by the\n * persistence layer (T2.1) to read/write `~/.theokit/credential-pool.json`.\n *\n * @internal\n */\nexport interface CredentialPoolSnapshot {\n provider: string;\n strategy: CredentialPoolStrategy;\n entries: PooledCredential[];\n}\n\n/**\n * Cooldown ladder by HTTP error code (ADR D125). Provider-supplied\n * `lastErrorResetAt` overrides these defaults when present.\n *\n * @internal\n */\nexport const COOLDOWN_MS: Readonly<Record<number, number>> = {\n 401: 5 * 60 * 1000, // 5 minutes — OAuth refresh can recover quickly\n 402: 60 * 60 * 1000, // 1 hour — billing quota typically hourly+\n 429: 60 * 60 * 1000, // 1 hour — daily-rate-limit windows\n};\n\n/** Default cooldown when no specific code matches. */\nexport const DEFAULT_COOLDOWN_MS = 60 * 60 * 1000;\n","/**\n * In-memory credential pool with strategy-based rotation (ADRs D123-D133).\n *\n * Pure logic. No I/O — persistence lives in `internal/persistence/\n * credential-pool-store.ts`. The pool is the single source of truth for\n * rotation state within a process; if it diverges from disk (e.g.,\n * process killed mid-rotation per EC-I), the next save heals the\n * inconsistency — at the cost of one extra HTTP 429 per crash.\n *\n * Thread safety: the pool uses an in-process async-aware mutex\n * (`cwd-mutex` D9 keyed by `credential-pool:${provider}`). Cross-process\n * safety happens at the persistence layer via `withFileLock` (D61).\n * Two Node processes sharing the same file may double-pick momentarily\n * (worst case = 1 extra 429 per race) — acceptable per ADR D128.\n *\n * @internal\n */\n\nimport { ConfigurationError } from \"../../errors.js\";\nimport { withCwdMutex } from \"../persistence/cwd-mutex.js\";\nimport {\n COOLDOWN_MS,\n type CredentialPoolSnapshot,\n type CredentialPoolStrategy,\n DEFAULT_COOLDOWN_MS,\n type PooledCredential,\n} from \"./credential-pool-types.js\";\nimport { sleepWithAbort } from \"./retry.js\";\n\n/**\n * Construct a `PooledCredential` with sane defaults.\n *\n * @internal\n */\nexport function newPooledCredential(args: {\n provider: string;\n accessToken: string;\n priority: number;\n source: string;\n label?: string;\n}): PooledCredential {\n return {\n id: globalThis.crypto.randomUUID(),\n label: args.label ?? labelFromSource(args.source, args.accessToken),\n provider: args.provider,\n priority: args.priority,\n source: args.source,\n accessToken: args.accessToken,\n lastStatus: \"ok\",\n lastStatusAt: undefined,\n lastErrorCode: undefined,\n lastErrorResetAt: undefined,\n requestCount: 0,\n };\n}\n\n/**\n * Build a human-readable label from the credential source. Used for\n * `Theokit.credentialPool.list()` UX. NEVER includes the raw token.\n *\n * @internal\n */\nfunction labelFromSource(source: string, accessToken: string): string {\n if (source.startsWith(\"env:\")) return source.slice(4);\n const masked =\n accessToken.length > 8 ? `${accessToken.slice(0, 4)}…${accessToken.slice(-4)}` : \"***\";\n return `${source}:${masked}`;\n}\n\n/**\n * Per-provider credential pool. Construct with one or more entries\n * sorted by priority. Throws `ConfigurationError` on empty input.\n *\n * EC-C: identical `accessToken`s are deduplicated during construction\n * (3 copies of \"k1\" → 1 entry). Otherwise an exhaustion event would\n * mark \"k1\" exhausted 3× wastefully.\n *\n * @internal\n */\nexport class CredentialPool {\n readonly provider: string;\n private readonly strategy: CredentialPoolStrategy;\n private entries: PooledCredential[];\n\n constructor(\n provider: string,\n entries: PooledCredential[],\n strategy: CredentialPoolStrategy = \"fill_first\",\n ) {\n if (entries.length === 0) {\n throw new ConfigurationError(\n `credential-pool: cannot construct empty pool for provider \"${provider}\"`,\n { code: \"credential_pool_empty\" },\n );\n }\n this.provider = provider;\n this.strategy = strategy;\n // EC-C: dedupe by accessToken before sort.\n this.entries = dedupeByToken(entries).sort((a, b) => a.priority - b.priority);\n }\n\n /** True if the pool was seeded with at least one entry. */\n hasCredentials(): boolean {\n return this.entries.length > 0;\n }\n\n /** True iff at least one entry is healthy (auto-healed if cooldown expired). */\n hasAvailable(): boolean {\n return this.availableEntries().length > 0;\n }\n\n /**\n * Earliest `lastErrorResetAt` across all entries, or `undefined` if no\n * entry is in cooldown. Used by `waitForAvailable` to compute the\n * upper bound of each jittered sleep window.\n *\n * @internal\n */\n earliestResetAt(): number | undefined {\n let earliest: number | undefined;\n for (const entry of this.entries) {\n if (entry.lastStatus === \"ok\") continue;\n if (entry.lastErrorResetAt === undefined) continue;\n if (earliest === undefined || entry.lastErrorResetAt < earliest) {\n earliest = entry.lastErrorResetAt;\n }\n }\n return earliest;\n }\n\n /**\n * Wait until at least one entry becomes healthy OR `maxWaitMs` elapses\n * OR `signal` aborts. Returns `true` if a healthy entry is available\n * when the call returns, `false` otherwise.\n *\n * T3.9 — Reconnect storm prevention. Concurrent callers each sleep a\n * random fraction of the window to the earliest cooldown reset (full\n * jitter — AWS Brooker 2015) so they do not all wake at the exact\n * instant cooldown expires and hammer the upstream simultaneously.\n *\n * The `sleeper` parameter is a dependency-injection seam for tests:\n * callers in production omit it and the default `setTimeout`-based\n * sleeper is used. The seam avoids the `vi.useFakeTimers()` mismatch\n * that blocked T3.4's wiring.\n *\n * @internal\n */\n async waitForAvailable(\n signal: AbortSignal,\n opts: {\n maxWaitMs: number;\n sleeper?: (ms: number, signal: AbortSignal) => Promise<void>;\n /**\n * Clock seam, the companion to `sleeper`. Production omits it and gets `Date.now`.\n *\n * `sleeper` alone was not enough to make this loop testable: a test could replace the SLEEP\n * but the deadline check still read real wall-clock, so the one case that exercises timeout\n * had to set `maxWaitMs: 5` and race the scheduler — with a comment in the committed file\n * saying so (\"we can't easily ... spec is wall-clock based\"). A sleeper that also advances a\n * virtual clock closes the loop deterministically, which is what `rules/testing.md` § 6 asks\n * for when it says to inject the clock rather than sleep.\n */\n now?: () => number;\n },\n ): Promise<boolean> {\n if (signal.aborted) return false;\n if (this.hasAvailable()) return true;\n const now = opts.now ?? Date.now;\n return await this.pollUntilAvailable(\n signal,\n now() + opts.maxWaitMs,\n opts.sleeper ?? sleepWithAbort,\n now,\n );\n }\n\n /**\n * The polling half of `waitForAvailable`, with both seams already resolved.\n *\n * Its own method because resolving two optional seams and running the loop in one body put the\n * function over the cognitive-complexity gate. The split is also the honest one: everything above\n * is a guard, everything here is the wait.\n */\n private async pollUntilAvailable(\n signal: AbortSignal,\n deadline: number,\n sleeper: (ms: number, signal: AbortSignal) => Promise<void>,\n now: () => number,\n ): Promise<boolean> {\n while (now() < deadline) {\n if (signal.aborted) return false;\n await sleeper(this.computeJitteredSleepMs(deadline, now), signal);\n if (signal.aborted) return false;\n if (this.hasAvailable()) return true;\n }\n return this.hasAvailable();\n }\n\n /**\n * Compute the next jittered sleep window (ms) for `waitForAvailable`.\n * Full-jitter cap: at most (a) time until the earliest reset (plus a\n * 50 ms grace so the entry actually heals before re-probe), or (b) the\n * remaining wait window, whichever is smaller. When no entry has a\n * known reset (rare — only if `markExhaustedAndRotate` was called\n * without `resetAtMs`), fall back to a 250 ms ceiling so we stay\n * responsive without hot-looping.\n */\n private computeJitteredSleepMs(deadline: number, now: () => number = Date.now): number {\n const resetAt = this.earliestResetAt();\n const remaining = deadline - now();\n const ceiling =\n resetAt === undefined\n ? Math.min(remaining, 250)\n : Math.min(remaining, Math.max(0, resetAt - now()) + 50);\n return Math.max(0, Math.floor(Math.random() * ceiling));\n }\n\n /** Live (frozen) view of all entries. */\n list(): readonly PooledCredential[] {\n return this.entries;\n }\n\n /**\n * Pick a healthy entry according to the configured strategy.\n * Mutates `requestCount` and (for round_robin) entry order.\n * Returns null if every entry is in cooldown.\n *\n * @internal\n */\n async select(): Promise<PooledCredential | null> {\n return withCwdMutex(`credential-pool:${this.provider}`, async () => this.selectLocked());\n }\n\n /**\n * Mark the entry whose id matches `entryId` as exhausted with the\n * appropriate cooldown, then return the next healthy entry (or null).\n * If `entryId` is undefined, marks all currently-active entries (rare —\n * only used by admin reset scenarios).\n *\n * @internal\n */\n async markExhaustedAndRotate(args: {\n entryId: string;\n statusCode: number;\n resetAtMs?: number;\n }): Promise<PooledCredential | null> {\n return withCwdMutex(`credential-pool:${this.provider}`, async () => {\n const entry = this.entries.find((e) => e.id === args.entryId);\n if (entry !== undefined) {\n const now = Date.now();\n const cooldown = COOLDOWN_MS[args.statusCode] ?? DEFAULT_COOLDOWN_MS;\n entry.lastStatus = \"exhausted\";\n entry.lastStatusAt = now;\n entry.lastErrorCode = args.statusCode;\n // EC-5: negative or stale resetAt → ignore, fall through to default.\n entry.lastErrorResetAt =\n args.resetAtMs !== undefined && args.resetAtMs > now ? args.resetAtMs : now + cooldown;\n }\n return this.selectLocked();\n });\n }\n\n /** Admin escape hatch: clear all cooldowns. */\n async resetAll(): Promise<void> {\n await withCwdMutex(`credential-pool:${this.provider}`, async () => {\n for (const e of this.entries) {\n e.lastStatus = \"ok\";\n e.lastStatusAt = undefined;\n e.lastErrorCode = undefined;\n e.lastErrorResetAt = undefined;\n }\n });\n }\n\n /** Materialize for persistence. */\n toSnapshot(): CredentialPoolSnapshot {\n return {\n provider: this.provider,\n strategy: this.strategy,\n entries: this.entries.map((e) => ({ ...e })),\n };\n }\n\n /** Hydrate from a previously-saved snapshot. */\n static fromSnapshot(snapshot: CredentialPoolSnapshot): CredentialPool {\n return new CredentialPool(snapshot.provider, snapshot.entries, snapshot.strategy);\n }\n\n // ─── Internal helpers (always called inside the mutex) ───\n\n // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: strategy dispatch must branch on 4 enum values (random/least_used/round_robin/fill_first) with 1-entry short-circuits per strategy. Each branch is 5-10 lines of focused logic; extracting per-strategy methods fragments the linear narrative.\n private selectLocked(): PooledCredential | null {\n const available = this.availableEntries();\n if (available.length === 0) return null;\n\n if (this.strategy === \"random\") {\n const idx = Math.floor(Math.random() * available.length);\n const picked = available[idx];\n if (picked === undefined) return null; // unreachable; satisfies strict\n picked.requestCount += 1;\n return picked;\n }\n\n if (this.strategy === \"least_used\" && available.length > 1) {\n // EC-3: tie-break by priority ascending (first wins).\n const picked = [...available].sort(\n (a, b) => a.requestCount - b.requestCount || a.priority - b.priority,\n )[0];\n if (picked === undefined) return null;\n picked.requestCount += 1;\n return picked;\n }\n\n if (this.strategy === \"round_robin\" && available.length > 1) {\n // Pick head; move it to the end of `entries` so next call picks the next.\n const picked = available[0];\n if (picked === undefined) return null;\n picked.requestCount += 1;\n const rest = this.entries.filter((e) => e.id !== picked.id);\n // Re-assign priorities: rotated entry gets the highest priority value\n // so it sorts last after `fromSnapshot` rehydration. This makes EC-F\n // (round-robin state survives save/load) work without a separate field.\n const maxPriority = this.entries.length - 1;\n rest.forEach((e, i) => {\n e.priority = i;\n });\n picked.priority = maxPriority;\n this.entries = [...rest, picked];\n return picked;\n }\n\n // fill_first (default) and 1-entry edge case for round_robin/least_used\n const picked = available[0];\n if (picked === undefined) return null;\n picked.requestCount += 1;\n return picked;\n }\n\n private availableEntries(): PooledCredential[] {\n const now = Date.now();\n const out: PooledCredential[] = [];\n for (const entry of this.entries) {\n if (entry.lastStatus === \"ok\") {\n out.push(entry);\n continue;\n }\n // EC-1: auto-heal expired cooldowns inline.\n const resetAt = entry.lastErrorResetAt;\n if (resetAt !== undefined && now >= resetAt) {\n entry.lastStatus = \"ok\";\n entry.lastStatusAt = undefined;\n entry.lastErrorCode = undefined;\n entry.lastErrorResetAt = undefined;\n out.push(entry);\n }\n }\n return out;\n }\n}\n\n/**\n * Drop duplicates by `accessToken`. Keeps the first occurrence (lowest\n * priority wins after sort). EC-C from the edge-case review.\n */\nfunction dedupeByToken(entries: PooledCredential[]): PooledCredential[] {\n const seen = new Set<string>();\n const out: PooledCredential[] = [];\n for (const e of entries) {\n if (seen.has(e.accessToken)) continue;\n seen.add(e.accessToken);\n out.push(e);\n }\n return out;\n}\n","/**\n * Per-fork credential-pool inheritance via `AsyncLocalStorage` (ADR D131).\n *\n * Mirrors the whitelist context pattern from D111\n * (`runtime/async-local-storage.ts`). Forked sub-agents inherit the\n * parent's pool *by reference* so concurrent rotations all observe\n * the same cooldown state — the desired behavior per Hermes parity.\n *\n * @internal\n */\n\nimport { AsyncLocalStorage } from \"node:async_hooks\";\n\nimport type { CredentialPool } from \"./credential-pool.js\";\n\n/** ALS slot — keyed by provider name → pool. */\nconst credentialPoolStore = new AsyncLocalStorage<Map<string, CredentialPool>>();\n\n/**\n * Run `fn` with `pools` as the active credential-pool registry for the\n * current async context. Nested calls shadow the outer map (parent\n * pools are not visible to children when the child sets its own).\n *\n * @internal\n */\nexport async function withCredentialPool<T>(\n pools: Map<string, CredentialPool>,\n fn: () => Promise<T>,\n): Promise<T> {\n return credentialPoolStore.run(pools, fn);\n}\n\n/**\n * Pool registered for `provider` in the current async context, or\n * `undefined` when no `withCredentialPool(...)` scope is active.\n *\n * @internal\n */\nexport function currentCredentialPool(provider: string): CredentialPool | undefined {\n return credentialPoolStore.getStore()?.get(provider);\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/internal/llm/credential-pool-types.ts","../src/internal/llm/credential-pool.ts","../src/internal/llm/credential-pool-context.ts"],"names":["picked"],"mappings":";;;;;;AAyFO,IAAM,WAAA,GAAgD;AAAA,EAC3D,GAAA,EAAK,IAAI,EAAA,GAAK,GAAA;AAAA;AAAA,EACd,GAAA,EAAK,KAAK,EAAA,GAAK,GAAA;AAAA;AAAA,EACf,GAAA,EAAK,KAAK,EAAA,GAAK;AAAA;AACjB,CAAA;AAGO,IAAM,mBAAA,GAAsB,KAAK,EAAA,GAAK,GAAA;;;AC9DtC,SAAS,oBAAoB,IAAA,EAMf;AACnB,EAAA,OAAO;AAAA,IACL,EAAA,EAAI,UAAA,CAAW,MAAA,CAAO,UAAA,EAAW;AAAA,IACjC,OAAO,IAAA,CAAK,KAAA,IAAS,gBAAgB,IAAA,CAAK,MAAA,EAAQ,KAAK,WAAW,CAAA;AAAA,IAClE,UAAU,IAAA,CAAK,QAAA;AAAA,IACf,UAAU,IAAA,CAAK,QAAA;AAAA,IACf,QAAQ,IAAA,CAAK,MAAA;AAAA,IACb,aAAa,IAAA,CAAK,WAAA;AAAA,IAClB,UAAA,EAAY,IAAA;AAAA,IACZ,YAAA,EAAc,MAAA;AAAA,IACd,aAAA,EAAe,MAAA;AAAA,IACf,gBAAA,EAAkB,MAAA;AAAA,IAClB,YAAA,EAAc;AAAA,GAChB;AACF;AAQA,SAAS,eAAA,CAAgB,QAAgB,WAAA,EAA6B;AACpE,EAAA,IAAI,OAAO,UAAA,CAAW,MAAM,GAAG,OAAO,MAAA,CAAO,MAAM,CAAC,CAAA;AACpD,EAAA,MAAM,MAAA,GACJ,WAAA,CAAY,MAAA,GAAS,CAAA,GAAI,GAAG,WAAA,CAAY,KAAA,CAAM,CAAA,EAAG,CAAC,CAAC,CAAA,MAAA,EAAI,WAAA,CAAY,KAAA,CAAM,EAAE,CAAC,CAAA,CAAA,GAAK,KAAA;AACnF,EAAA,OAAO,CAAA,EAAG,MAAM,CAAA,CAAA,EAAI,MAAM,CAAA,CAAA;AAC5B;AAYO,IAAM,cAAA,GAAN,MAAM,eAAA,CAAe;AAAA,EACjB,QAAA;AAAA,EACQ,QAAA;AAAA,EACT,OAAA;AAAA,EAER,WAAA,CACE,QAAA,EACA,OAAA,EACA,QAAA,GAAmC,YAAA,EACnC;AACA,IAAA,IAAI,OAAA,CAAQ,WAAW,CAAA,EAAG;AACxB,MAAA,MAAM,IAAI,kBAAA;AAAA,QACR,8DAA8D,QAAQ,CAAA,CAAA,CAAA;AAAA,QACtE,EAAE,MAAM,uBAAA;AAAwB,OAClC;AAAA,IACF;AACA,IAAA,IAAA,CAAK,QAAA,GAAW,QAAA;AAChB,IAAA,IAAA,CAAK,QAAA,GAAW,QAAA;AAEhB,IAAA,IAAA,CAAK,OAAA,GAAU,aAAA,CAAc,OAAO,CAAA,CAAE,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,KAAM,CAAA,CAAE,QAAA,GAAW,CAAA,CAAE,QAAQ,CAAA;AAAA,EAC9E;AAAA;AAAA,EAGA,cAAA,GAA0B;AACxB,IAAA,OAAO,IAAA,CAAK,QAAQ,MAAA,GAAS,CAAA;AAAA,EAC/B;AAAA;AAAA,EAGA,YAAA,GAAwB;AACtB,IAAA,OAAO,IAAA,CAAK,gBAAA,EAAiB,CAAE,MAAA,GAAS,CAAA;AAAA,EAC1C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,eAAA,GAAsC;AACpC,IAAA,IAAI,QAAA;AACJ,IAAA,KAAA,MAAW,KAAA,IAAS,KAAK,OAAA,EAAS;AAChC,MAAA,IAAI,KAAA,CAAM,eAAe,IAAA,EAAM;AAC/B,MAAA,IAAI,KAAA,CAAM,qBAAqB,MAAA,EAAW;AAC1C,MAAA,IAAI,QAAA,KAAa,MAAA,IAAa,KAAA,CAAM,gBAAA,GAAmB,QAAA,EAAU;AAC/D,QAAA,QAAA,GAAW,KAAA,CAAM,gBAAA;AAAA,MACnB;AAAA,IACF;AACA,IAAA,OAAO,QAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAmBA,MAAM,gBAAA,CACJ,MAAA,EACA,IAAA,EAekB;AAClB,IAAA,IAAI,MAAA,CAAO,SAAS,OAAO,KAAA;AAC3B,IAAA,IAAI,IAAA,CAAK,YAAA,EAAa,EAAG,OAAO,IAAA;AAChC,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,GAAA,IAAO,IAAA,CAAK,GAAA;AAC7B,IAAA,OAAO,MAAM,IAAA,CAAK,kBAAA;AAAA,MAChB,MAAA;AAAA,MACA,GAAA,KAAQ,IAAA,CAAK,SAAA;AAAA,MACb,KAAK,OAAA,IAAW,cAAA;AAAA,MAChB;AAAA,KACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAc,kBAAA,CACZ,MAAA,EACA,QAAA,EACA,SACA,GAAA,EACkB;AAClB,IAAA,OAAO,GAAA,KAAQ,QAAA,EAAU;AACvB,MAAA,IAAI,MAAA,CAAO,SAAS,OAAO,KAAA;AAC3B,MAAA,MAAM,QAAQ,IAAA,CAAK,sBAAA,CAAuB,QAAA,EAAU,GAAG,GAAG,MAAM,CAAA;AAChE,MAAA,IAAI,MAAA,CAAO,SAAS,OAAO,KAAA;AAC3B,MAAA,IAAI,IAAA,CAAK,YAAA,EAAa,EAAG,OAAO,IAAA;AAAA,IAClC;AACA,IAAA,OAAO,KAAK,YAAA,EAAa;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWQ,sBAAA,CAAuB,QAAA,EAAkB,GAAA,GAAoB,IAAA,CAAK,GAAA,EAAa;AACrF,IAAA,MAAM,OAAA,GAAU,KAAK,eAAA,EAAgB;AACrC,IAAA,MAAM,SAAA,GAAY,WAAW,GAAA,EAAI;AACjC,IAAA,MAAM,UACJ,OAAA,KAAY,MAAA,GACR,KAAK,GAAA,CAAI,SAAA,EAAW,GAAG,CAAA,GACvB,IAAA,CAAK,GAAA,CAAI,SAAA,EAAW,KAAK,GAAA,CAAI,CAAA,EAAG,UAAU,GAAA,EAAK,IAAI,EAAE,CAAA;AAC3D,IAAA,OAAO,IAAA,CAAK,IAAI,CAAA,EAAG,IAAA,CAAK,MAAM,IAAA,CAAK,MAAA,EAAO,GAAI,OAAO,CAAC,CAAA;AAAA,EACxD;AAAA;AAAA,EAGA,IAAA,GAAoC;AAClC,IAAA,OAAO,IAAA,CAAK,OAAA;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,MAAA,GAA2C;AAC/C,IAAA,OAAO,YAAA,CAAa,mBAAmB,IAAA,CAAK,QAAQ,IAAI,YAAY,IAAA,CAAK,cAAc,CAAA;AAAA,EACzF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,uBAAuB,IAAA,EAIQ;AACnC,IAAA,OAAO,YAAA,CAAa,CAAA,gBAAA,EAAmB,IAAA,CAAK,QAAQ,IAAI,YAAY;AAClE,MAAA,MAAM,KAAA,GAAQ,KAAK,OAAA,CAAQ,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,EAAA,KAAO,IAAA,CAAK,OAAO,CAAA;AAC5D,MAAA,IAAI,UAAU,MAAA,EAAW;AACvB,QAAA,MAAM,GAAA,GAAM,KAAK,GAAA,EAAI;AACrB,QAAA,MAAM,QAAA,GAAW,WAAA,CAAY,IAAA,CAAK,UAAU,CAAA,IAAK,mBAAA;AACjD,QAAA,KAAA,CAAM,UAAA,GAAa,WAAA;AACnB,QAAA,KAAA,CAAM,YAAA,GAAe,GAAA;AACrB,QAAA,KAAA,CAAM,gBAAgB,IAAA,CAAK,UAAA;AAE3B,QAAA,KAAA,CAAM,gBAAA,GACJ,KAAK,SAAA,KAAc,MAAA,IAAa,KAAK,SAAA,GAAY,GAAA,GAAM,IAAA,CAAK,SAAA,GAAY,GAAA,GAAM,QAAA;AAAA,MAClF;AACA,MAAA,OAAO,KAAK,YAAA,EAAa;AAAA,IAC3B,CAAC,CAAA;AAAA,EACH;AAAA;AAAA,EAGA,MAAM,QAAA,GAA0B;AAC9B,IAAA,MAAM,YAAA,CAAa,CAAA,gBAAA,EAAmB,IAAA,CAAK,QAAQ,IAAI,YAAY;AACjE,MAAA,KAAA,MAAW,CAAA,IAAK,KAAK,OAAA,EAAS;AAC5B,QAAA,CAAA,CAAE,UAAA,GAAa,IAAA;AACf,QAAA,CAAA,CAAE,YAAA,GAAe,MAAA;AACjB,QAAA,CAAA,CAAE,aAAA,GAAgB,MAAA;AAClB,QAAA,CAAA,CAAE,gBAAA,GAAmB,MAAA;AAAA,MACvB;AAAA,IACF,CAAC,CAAA;AAAA,EACH;AAAA;AAAA,EAGA,UAAA,GAAqC;AACnC,IAAA,OAAO;AAAA,MACL,UAAU,IAAA,CAAK,QAAA;AAAA,MACf,UAAU,IAAA,CAAK,QAAA;AAAA,MACf,OAAA,EAAS,KAAK,OAAA,CAAQ,GAAA,CAAI,CAAC,CAAA,MAAO,EAAE,GAAG,CAAA,EAAE,CAAE;AAAA,KAC7C;AAAA,EACF;AAAA;AAAA,EAGA,OAAO,aAAa,QAAA,EAAkD;AACpE,IAAA,OAAO,IAAI,eAAA,CAAe,QAAA,CAAS,UAAU,QAAA,CAAS,OAAA,EAAS,SAAS,QAAQ,CAAA;AAAA,EAClF;AAAA;AAAA;AAAA,EAKQ,YAAA,GAAwC;AAC9C,IAAA,MAAM,SAAA,GAAY,KAAK,gBAAA,EAAiB;AACxC,IAAA,IAAI,SAAA,CAAU,MAAA,KAAW,CAAA,EAAG,OAAO,IAAA;AAEnC,IAAA,IAAI,IAAA,CAAK,aAAa,QAAA,EAAU;AAC9B,MAAA,MAAM,MAAM,IAAA,CAAK,KAAA,CAAM,KAAK,MAAA,EAAO,GAAI,UAAU,MAAM,CAAA;AACvD,MAAA,MAAMA,OAAAA,GAAS,UAAU,GAAG,CAAA;AAC5B,MAAA,IAAIA,OAAAA,KAAW,QAAW,OAAO,IAAA;AACjC,MAAAA,QAAO,YAAA,IAAgB,CAAA;AACvB,MAAA,OAAOA,OAAAA;AAAA,IACT;AAEA,IAAA,IAAI,IAAA,CAAK,QAAA,KAAa,YAAA,IAAgB,SAAA,CAAU,SAAS,CAAA,EAAG;AAE1D,MAAA,MAAMA,OAAAA,GAAS,CAAC,GAAG,SAAS,CAAA,CAAE,IAAA;AAAA,QAC5B,CAAC,GAAG,CAAA,KAAM,CAAA,CAAE,eAAe,CAAA,CAAE,YAAA,IAAgB,CAAA,CAAE,QAAA,GAAW,CAAA,CAAE;AAAA,QAC5D,CAAC,CAAA;AACH,MAAA,IAAIA,OAAAA,KAAW,QAAW,OAAO,IAAA;AACjC,MAAAA,QAAO,YAAA,IAAgB,CAAA;AACvB,MAAA,OAAOA,OAAAA;AAAA,IACT;AAEA,IAAA,IAAI,IAAA,CAAK,QAAA,KAAa,aAAA,IAAiB,SAAA,CAAU,SAAS,CAAA,EAAG;AAE3D,MAAA,MAAMA,OAAAA,GAAS,UAAU,CAAC,CAAA;AAC1B,MAAA,IAAIA,OAAAA,KAAW,QAAW,OAAO,IAAA;AACjC,MAAAA,QAAO,YAAA,IAAgB,CAAA;AACvB,MAAA,MAAM,IAAA,GAAO,KAAK,OAAA,CAAQ,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,EAAA,KAAOA,OAAAA,CAAO,EAAE,CAAA;AAI1D,MAAA,MAAM,WAAA,GAAc,IAAA,CAAK,OAAA,CAAQ,MAAA,GAAS,CAAA;AAC1C,MAAA,IAAA,CAAK,OAAA,CAAQ,CAAC,CAAA,EAAG,CAAA,KAAM;AACrB,QAAA,CAAA,CAAE,QAAA,GAAW,CAAA;AAAA,MACf,CAAC,CAAA;AACD,MAAAA,QAAO,QAAA,GAAW,WAAA;AAClB,MAAA,IAAA,CAAK,OAAA,GAAU,CAAC,GAAG,IAAA,EAAMA,OAAM,CAAA;AAC/B,MAAA,OAAOA,OAAAA;AAAA,IACT;AAGA,IAAA,MAAM,MAAA,GAAS,UAAU,CAAC,CAAA;AAC1B,IAAA,IAAI,MAAA,KAAW,QAAW,OAAO,IAAA;AACjC,IAAA,MAAA,CAAO,YAAA,IAAgB,CAAA;AACvB,IAAA,OAAO,MAAA;AAAA,EACT;AAAA,EAEQ,gBAAA,GAAuC;AAC7C,IAAA,MAAM,GAAA,GAAM,KAAK,GAAA,EAAI;AACrB,IAAA,MAAM,MAA0B,EAAC;AACjC,IAAA,KAAA,MAAW,KAAA,IAAS,KAAK,OAAA,EAAS;AAChC,MAAA,IAAI,KAAA,CAAM,eAAe,IAAA,EAAM;AAC7B,QAAA,GAAA,CAAI,KAAK,KAAK,CAAA;AACd,QAAA;AAAA,MACF;AAEA,MAAA,MAAM,UAAU,KAAA,CAAM,gBAAA;AACtB,MAAA,IAAI,OAAA,KAAY,MAAA,IAAa,GAAA,IAAO,OAAA,EAAS;AAC3C,QAAA,KAAA,CAAM,UAAA,GAAa,IAAA;AACnB,QAAA,KAAA,CAAM,YAAA,GAAe,MAAA;AACrB,QAAA,KAAA,CAAM,aAAA,GAAgB,MAAA;AACtB,QAAA,KAAA,CAAM,gBAAA,GAAmB,MAAA;AACzB,QAAA,GAAA,CAAI,KAAK,KAAK,CAAA;AAAA,MAChB;AAAA,IACF;AACA,IAAA,OAAO,GAAA;AAAA,EACT;AACF;AAMA,SAAS,cAAc,OAAA,EAAiD;AACtE,EAAA,MAAM,IAAA,uBAAW,GAAA,EAAY;AAC7B,EAAA,MAAM,MAA0B,EAAC;AACjC,EAAA,KAAA,MAAW,KAAK,OAAA,EAAS;AACvB,IAAA,IAAI,IAAA,CAAK,GAAA,CAAI,CAAA,CAAE,WAAW,CAAA,EAAG;AAC7B,IAAA,IAAA,CAAK,GAAA,CAAI,EAAE,WAAW,CAAA;AACtB,IAAA,GAAA,CAAI,KAAK,CAAC,CAAA;AAAA,EACZ;AACA,EAAA,OAAO,GAAA;AACT;ACrWA,IAAM,mBAAA,GAAsB,IAAI,iBAAA,EAA+C;AAS/E,eAAsB,kBAAA,CACpB,OACA,EAAA,EACY;AACZ,EAAA,OAAO,mBAAA,CAAoB,GAAA,CAAI,KAAA,EAAO,EAAE,CAAA;AAC1C;AAQO,SAAS,sBAAsB,QAAA,EAA8C;AAClF,EAAA,OAAO,mBAAA,CAAoB,QAAA,EAAS,EAAG,GAAA,CAAI,QAAQ,CAAA;AACrD","file":"chunk-SUVCHX4L.js","sourcesContent":["/**\n * Types for the credential pool subsystem (ADRs D123-D133).\n *\n * Pool a developer's multiple API keys for the SAME provider so the SDK\n * can rotate transparently on HTTP 429/402/401 instead of jumping\n * straight to a different provider via `FallbackLlmClient`.\n *\n * @internal\n */\n\n/**\n * Rotation strategy when picking the next credential from a pool.\n *\n * - `fill_first` (default): use entries[0] until exhausted, then [1]…\n * - `round_robin`: rotate after each `select()`\n * - `least_used`: pick the entry with the lowest `requestCount`\n * - `random`: random pick among healthy entries\n *\n * Closed enum per ADR D124 — adding a strategy is an explicit semver\n * minor that updates `selectByStrategy` exhaustively.\n *\n * @internal\n */\nexport type CredentialPoolStrategy = \"fill_first\" | \"round_robin\" | \"least_used\" | \"random\";\n\n/** Health flag tracked per credential. */\nexport type CredentialStatus = \"ok\" | \"exhausted\";\n\n/**\n * Provenance of a credential — where it came from when seeded.\n * Free-form string; conventional prefixes:\n *\n * - `env:<VAR_NAME>` — auto-discovered from environment variable\n * - `manual` — added via explicit `apiKeys` config\n * - `explicit-apikey` — wrapped from `AgentOptions.apiKey` single-key path (D132)\n */\nexport type CredentialSource = string;\n\n/**\n * Single credential entry inside a {@link CredentialPool}.\n *\n * `accessToken` is the sensitive field — must never be logged unredacted.\n * The lint gate `tests/lint/no-unredacted-pool-token.test.ts` enforces this.\n *\n * @internal\n */\nexport interface PooledCredential {\n /** Stable identifier (uuid v4) for log lines + telemetry. */\n id: string;\n /** Human-readable label for `Theokit.credentialPool.list()`. */\n label: string;\n /** Provider name (matches `ProviderProfile.name`). */\n provider: string;\n /** Sort key; lower = earlier in fill_first. Unique within a pool. */\n priority: number;\n /** Provenance string. */\n source: CredentialSource;\n /** Sensitive API key. NEVER LOG UNREDACTED. */\n accessToken: string;\n /** Current health. */\n lastStatus: CredentialStatus;\n /** Epoch ms of the last status change. */\n lastStatusAt: number | undefined;\n /** HTTP code that caused exhaustion (401/402/429). */\n lastErrorCode: number | undefined;\n /** Provider-supplied \"retry after this epoch ms\" hint. Overrides cooldown defaults. */\n lastErrorResetAt: number | undefined;\n /** Bumped per successful `select()` for `least_used` strategy. Lazy-persisted. */\n requestCount: number;\n}\n\n/**\n * Serializable snapshot of a single provider's pool. Used by the\n * persistence layer (T2.1) to read/write `~/.theokit/credential-pool.json`.\n *\n * @internal\n */\nexport interface CredentialPoolSnapshot {\n provider: string;\n strategy: CredentialPoolStrategy;\n entries: PooledCredential[];\n}\n\n/**\n * Cooldown ladder by HTTP error code (ADR D125). Provider-supplied\n * `lastErrorResetAt` overrides these defaults when present.\n *\n * @internal\n */\nexport const COOLDOWN_MS: Readonly<Record<number, number>> = {\n 401: 5 * 60 * 1000, // 5 minutes — OAuth refresh can recover quickly\n 402: 60 * 60 * 1000, // 1 hour — billing quota typically hourly+\n 429: 60 * 60 * 1000, // 1 hour — daily-rate-limit windows\n};\n\n/** Default cooldown when no specific code matches. */\nexport const DEFAULT_COOLDOWN_MS = 60 * 60 * 1000;\n","/**\n * In-memory credential pool with strategy-based rotation (ADRs D123-D133).\n *\n * Pure logic. No I/O — persistence lives in `internal/persistence/\n * credential-pool-store.ts`. The pool is the single source of truth for\n * rotation state within a process; if it diverges from disk (e.g.,\n * process killed mid-rotation per EC-I), the next save heals the\n * inconsistency — at the cost of one extra HTTP 429 per crash.\n *\n * Thread safety: the pool uses an in-process async-aware mutex\n * (`cwd-mutex` D9 keyed by `credential-pool:${provider}`). Cross-process\n * safety happens at the persistence layer via `withFileLock` (D61).\n * Two Node processes sharing the same file may double-pick momentarily\n * (worst case = 1 extra 429 per race) — acceptable per ADR D128.\n *\n * @internal\n */\n\nimport { ConfigurationError } from \"../../errors.js\";\nimport { withCwdMutex } from \"../persistence/cwd-mutex.js\";\nimport {\n COOLDOWN_MS,\n type CredentialPoolSnapshot,\n type CredentialPoolStrategy,\n DEFAULT_COOLDOWN_MS,\n type PooledCredential,\n} from \"./credential-pool-types.js\";\nimport { sleepWithAbort } from \"./retry.js\";\n\n/**\n * Construct a `PooledCredential` with sane defaults.\n *\n * @internal\n */\nexport function newPooledCredential(args: {\n provider: string;\n accessToken: string;\n priority: number;\n source: string;\n label?: string;\n}): PooledCredential {\n return {\n id: globalThis.crypto.randomUUID(),\n label: args.label ?? labelFromSource(args.source, args.accessToken),\n provider: args.provider,\n priority: args.priority,\n source: args.source,\n accessToken: args.accessToken,\n lastStatus: \"ok\",\n lastStatusAt: undefined,\n lastErrorCode: undefined,\n lastErrorResetAt: undefined,\n requestCount: 0,\n };\n}\n\n/**\n * Build a human-readable label from the credential source. Used for\n * `Theokit.credentialPool.list()` UX. NEVER includes the raw token.\n *\n * @internal\n */\nfunction labelFromSource(source: string, accessToken: string): string {\n if (source.startsWith(\"env:\")) return source.slice(4);\n const masked =\n accessToken.length > 8 ? `${accessToken.slice(0, 4)}…${accessToken.slice(-4)}` : \"***\";\n return `${source}:${masked}`;\n}\n\n/**\n * Per-provider credential pool. Construct with one or more entries\n * sorted by priority. Throws `ConfigurationError` on empty input.\n *\n * EC-C: identical `accessToken`s are deduplicated during construction\n * (3 copies of \"k1\" → 1 entry). Otherwise an exhaustion event would\n * mark \"k1\" exhausted 3× wastefully.\n *\n * @internal\n */\nexport class CredentialPool {\n readonly provider: string;\n private readonly strategy: CredentialPoolStrategy;\n private entries: PooledCredential[];\n\n constructor(\n provider: string,\n entries: PooledCredential[],\n strategy: CredentialPoolStrategy = \"fill_first\",\n ) {\n if (entries.length === 0) {\n throw new ConfigurationError(\n `credential-pool: cannot construct empty pool for provider \"${provider}\"`,\n { code: \"credential_pool_empty\" },\n );\n }\n this.provider = provider;\n this.strategy = strategy;\n // EC-C: dedupe by accessToken before sort.\n this.entries = dedupeByToken(entries).sort((a, b) => a.priority - b.priority);\n }\n\n /** True if the pool was seeded with at least one entry. */\n hasCredentials(): boolean {\n return this.entries.length > 0;\n }\n\n /** True iff at least one entry is healthy (auto-healed if cooldown expired). */\n hasAvailable(): boolean {\n return this.availableEntries().length > 0;\n }\n\n /**\n * Earliest `lastErrorResetAt` across all entries, or `undefined` if no\n * entry is in cooldown. Used by `waitForAvailable` to compute the\n * upper bound of each jittered sleep window.\n *\n * @internal\n */\n earliestResetAt(): number | undefined {\n let earliest: number | undefined;\n for (const entry of this.entries) {\n if (entry.lastStatus === \"ok\") continue;\n if (entry.lastErrorResetAt === undefined) continue;\n if (earliest === undefined || entry.lastErrorResetAt < earliest) {\n earliest = entry.lastErrorResetAt;\n }\n }\n return earliest;\n }\n\n /**\n * Wait until at least one entry becomes healthy OR `maxWaitMs` elapses\n * OR `signal` aborts. Returns `true` if a healthy entry is available\n * when the call returns, `false` otherwise.\n *\n * T3.9 — Reconnect storm prevention. Concurrent callers each sleep a\n * random fraction of the window to the earliest cooldown reset (full\n * jitter — AWS Brooker 2015) so they do not all wake at the exact\n * instant cooldown expires and hammer the upstream simultaneously.\n *\n * The `sleeper` parameter is a dependency-injection seam for tests:\n * callers in production omit it and the default `setTimeout`-based\n * sleeper is used. The seam avoids the `vi.useFakeTimers()` mismatch\n * that blocked T3.4's wiring.\n *\n * @internal\n */\n async waitForAvailable(\n signal: AbortSignal,\n opts: {\n maxWaitMs: number;\n sleeper?: (ms: number, signal: AbortSignal) => Promise<void>;\n /**\n * Clock seam, the companion to `sleeper`. Production omits it and gets `Date.now`.\n *\n * `sleeper` alone was not enough to make this loop testable: a test could replace the SLEEP\n * but the deadline check still read real wall-clock, so the one case that exercises timeout\n * had to set `maxWaitMs: 5` and race the scheduler — with a comment in the committed file\n * saying so (\"we can't easily ... spec is wall-clock based\"). A sleeper that also advances a\n * virtual clock closes the loop deterministically, which is what `rules/testing.md` § 6 asks\n * for when it says to inject the clock rather than sleep.\n */\n now?: () => number;\n },\n ): Promise<boolean> {\n if (signal.aborted) return false;\n if (this.hasAvailable()) return true;\n const now = opts.now ?? Date.now;\n return await this.pollUntilAvailable(\n signal,\n now() + opts.maxWaitMs,\n opts.sleeper ?? sleepWithAbort,\n now,\n );\n }\n\n /**\n * The polling half of `waitForAvailable`, with both seams already resolved.\n *\n * Its own method because resolving two optional seams and running the loop in one body put the\n * function over the cognitive-complexity gate. The split is also the honest one: everything above\n * is a guard, everything here is the wait.\n */\n private async pollUntilAvailable(\n signal: AbortSignal,\n deadline: number,\n sleeper: (ms: number, signal: AbortSignal) => Promise<void>,\n now: () => number,\n ): Promise<boolean> {\n while (now() < deadline) {\n if (signal.aborted) return false;\n await sleeper(this.computeJitteredSleepMs(deadline, now), signal);\n if (signal.aborted) return false;\n if (this.hasAvailable()) return true;\n }\n return this.hasAvailable();\n }\n\n /**\n * Compute the next jittered sleep window (ms) for `waitForAvailable`.\n * Full-jitter cap: at most (a) time until the earliest reset (plus a\n * 50 ms grace so the entry actually heals before re-probe), or (b) the\n * remaining wait window, whichever is smaller. When no entry has a\n * known reset (rare — only if `markExhaustedAndRotate` was called\n * without `resetAtMs`), fall back to a 250 ms ceiling so we stay\n * responsive without hot-looping.\n */\n private computeJitteredSleepMs(deadline: number, now: () => number = Date.now): number {\n const resetAt = this.earliestResetAt();\n const remaining = deadline - now();\n const ceiling =\n resetAt === undefined\n ? Math.min(remaining, 250)\n : Math.min(remaining, Math.max(0, resetAt - now()) + 50);\n return Math.max(0, Math.floor(Math.random() * ceiling));\n }\n\n /** Live (frozen) view of all entries. */\n list(): readonly PooledCredential[] {\n return this.entries;\n }\n\n /**\n * Pick a healthy entry according to the configured strategy.\n * Mutates `requestCount` and (for round_robin) entry order.\n * Returns null if every entry is in cooldown.\n *\n * @internal\n */\n async select(): Promise<PooledCredential | null> {\n return withCwdMutex(`credential-pool:${this.provider}`, async () => this.selectLocked());\n }\n\n /**\n * Mark the entry whose id matches `entryId` as exhausted with the\n * appropriate cooldown, then return the next healthy entry (or null).\n * If `entryId` is undefined, marks all currently-active entries (rare —\n * only used by admin reset scenarios).\n *\n * @internal\n */\n async markExhaustedAndRotate(args: {\n entryId: string;\n statusCode: number;\n resetAtMs?: number;\n }): Promise<PooledCredential | null> {\n return withCwdMutex(`credential-pool:${this.provider}`, async () => {\n const entry = this.entries.find((e) => e.id === args.entryId);\n if (entry !== undefined) {\n const now = Date.now();\n const cooldown = COOLDOWN_MS[args.statusCode] ?? DEFAULT_COOLDOWN_MS;\n entry.lastStatus = \"exhausted\";\n entry.lastStatusAt = now;\n entry.lastErrorCode = args.statusCode;\n // EC-5: negative or stale resetAt → ignore, fall through to default.\n entry.lastErrorResetAt =\n args.resetAtMs !== undefined && args.resetAtMs > now ? args.resetAtMs : now + cooldown;\n }\n return this.selectLocked();\n });\n }\n\n /** Admin escape hatch: clear all cooldowns. */\n async resetAll(): Promise<void> {\n await withCwdMutex(`credential-pool:${this.provider}`, async () => {\n for (const e of this.entries) {\n e.lastStatus = \"ok\";\n e.lastStatusAt = undefined;\n e.lastErrorCode = undefined;\n e.lastErrorResetAt = undefined;\n }\n });\n }\n\n /** Materialize for persistence. */\n toSnapshot(): CredentialPoolSnapshot {\n return {\n provider: this.provider,\n strategy: this.strategy,\n entries: this.entries.map((e) => ({ ...e })),\n };\n }\n\n /** Hydrate from a previously-saved snapshot. */\n static fromSnapshot(snapshot: CredentialPoolSnapshot): CredentialPool {\n return new CredentialPool(snapshot.provider, snapshot.entries, snapshot.strategy);\n }\n\n // ─── Internal helpers (always called inside the mutex) ───\n\n // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: strategy dispatch must branch on 4 enum values (random/least_used/round_robin/fill_first) with 1-entry short-circuits per strategy. Each branch is 5-10 lines of focused logic; extracting per-strategy methods fragments the linear narrative.\n private selectLocked(): PooledCredential | null {\n const available = this.availableEntries();\n if (available.length === 0) return null;\n\n if (this.strategy === \"random\") {\n const idx = Math.floor(Math.random() * available.length);\n const picked = available[idx];\n if (picked === undefined) return null; // unreachable; satisfies strict\n picked.requestCount += 1;\n return picked;\n }\n\n if (this.strategy === \"least_used\" && available.length > 1) {\n // EC-3: tie-break by priority ascending (first wins).\n const picked = [...available].sort(\n (a, b) => a.requestCount - b.requestCount || a.priority - b.priority,\n )[0];\n if (picked === undefined) return null;\n picked.requestCount += 1;\n return picked;\n }\n\n if (this.strategy === \"round_robin\" && available.length > 1) {\n // Pick head; move it to the end of `entries` so next call picks the next.\n const picked = available[0];\n if (picked === undefined) return null;\n picked.requestCount += 1;\n const rest = this.entries.filter((e) => e.id !== picked.id);\n // Re-assign priorities: rotated entry gets the highest priority value\n // so it sorts last after `fromSnapshot` rehydration. This makes EC-F\n // (round-robin state survives save/load) work without a separate field.\n const maxPriority = this.entries.length - 1;\n rest.forEach((e, i) => {\n e.priority = i;\n });\n picked.priority = maxPriority;\n this.entries = [...rest, picked];\n return picked;\n }\n\n // fill_first (default) and 1-entry edge case for round_robin/least_used\n const picked = available[0];\n if (picked === undefined) return null;\n picked.requestCount += 1;\n return picked;\n }\n\n private availableEntries(): PooledCredential[] {\n const now = Date.now();\n const out: PooledCredential[] = [];\n for (const entry of this.entries) {\n if (entry.lastStatus === \"ok\") {\n out.push(entry);\n continue;\n }\n // EC-1: auto-heal expired cooldowns inline.\n const resetAt = entry.lastErrorResetAt;\n if (resetAt !== undefined && now >= resetAt) {\n entry.lastStatus = \"ok\";\n entry.lastStatusAt = undefined;\n entry.lastErrorCode = undefined;\n entry.lastErrorResetAt = undefined;\n out.push(entry);\n }\n }\n return out;\n }\n}\n\n/**\n * Drop duplicates by `accessToken`. Keeps the first occurrence (lowest\n * priority wins after sort). EC-C from the edge-case review.\n */\nfunction dedupeByToken(entries: PooledCredential[]): PooledCredential[] {\n const seen = new Set<string>();\n const out: PooledCredential[] = [];\n for (const e of entries) {\n if (seen.has(e.accessToken)) continue;\n seen.add(e.accessToken);\n out.push(e);\n }\n return out;\n}\n","/**\n * Per-fork credential-pool inheritance via `AsyncLocalStorage` (ADR D131).\n *\n * Mirrors the whitelist context pattern from D111\n * (`runtime/async-local-storage.ts`). Forked sub-agents inherit the\n * parent's pool *by reference* so concurrent rotations all observe\n * the same cooldown state — the desired behavior per Hermes parity.\n *\n * @internal\n */\n\nimport { AsyncLocalStorage } from \"node:async_hooks\";\n\nimport type { CredentialPool } from \"./credential-pool.js\";\n\n/** ALS slot — keyed by provider name → pool. */\nconst credentialPoolStore = new AsyncLocalStorage<Map<string, CredentialPool>>();\n\n/**\n * Run `fn` with `pools` as the active credential-pool registry for the\n * current async context. Nested calls shadow the outer map (parent\n * pools are not visible to children when the child sets its own).\n *\n * @internal\n */\nexport async function withCredentialPool<T>(\n pools: Map<string, CredentialPool>,\n fn: () => Promise<T>,\n): Promise<T> {\n return credentialPoolStore.run(pools, fn);\n}\n\n/**\n * Pool registered for `provider` in the current async context, or\n * `undefined` when no `withCredentialPool(...)` scope is active.\n *\n * @internal\n */\nexport function currentCredentialPool(provider: string): CredentialPool | undefined {\n return credentialPoolStore.getStore()?.get(provider);\n}\n"]}
|
|
@@ -10,9 +10,15 @@ function admittedSpecs(specs, declaredKinds) {
|
|
|
10
10
|
const granted = new Set(declaredKinds);
|
|
11
11
|
return specs.filter((spec) => spec.dialect === void 0 || granted.has(spec.dialect));
|
|
12
12
|
}
|
|
13
|
+
function withheldSpecs(specs, declaredKinds) {
|
|
14
|
+
if (declaredKinds === void 0) return [];
|
|
15
|
+
const granted = new Set(declaredKinds);
|
|
16
|
+
return specs.filter((spec) => spec.dialect !== void 0 && !granted.has(spec.dialect)).map((spec) => ({ id: spec.id, pattern: spec.pattern, grant: String(spec.dialect) }));
|
|
17
|
+
}
|
|
13
18
|
var DEFAULT_DISCOVERY_SPECS = [
|
|
14
19
|
{
|
|
15
20
|
id: "AGENTS.md",
|
|
21
|
+
dialect: "agents",
|
|
16
22
|
pattern: "AGENTS.md",
|
|
17
23
|
scope: "git-root-walk",
|
|
18
24
|
parser: "plain-markdown",
|
|
@@ -21,6 +27,7 @@ var DEFAULT_DISCOVERY_SPECS = [
|
|
|
21
27
|
},
|
|
22
28
|
{
|
|
23
29
|
id: "GEMINI.md",
|
|
30
|
+
dialect: "gemini",
|
|
24
31
|
pattern: "GEMINI.md",
|
|
25
32
|
scope: "git-root-walk",
|
|
26
33
|
parser: "plain-markdown",
|
|
@@ -29,6 +36,7 @@ var DEFAULT_DISCOVERY_SPECS = [
|
|
|
29
36
|
},
|
|
30
37
|
{
|
|
31
38
|
id: "CLAUDE.md",
|
|
39
|
+
dialect: "claude-code",
|
|
32
40
|
pattern: "CLAUDE.md",
|
|
33
41
|
scope: "git-root-walk",
|
|
34
42
|
parser: "plain-markdown",
|
|
@@ -37,6 +45,7 @@ var DEFAULT_DISCOVERY_SPECS = [
|
|
|
37
45
|
},
|
|
38
46
|
{
|
|
39
47
|
id: "cursor-rules",
|
|
48
|
+
dialect: "cursor",
|
|
40
49
|
pattern: ".cursor/rules/*.mdc",
|
|
41
50
|
scope: "globbed",
|
|
42
51
|
parser: "mdc",
|
|
@@ -237,5 +246,6 @@ exports.findGitRoot = findGitRoot;
|
|
|
237
246
|
exports.isSafePattern = isSafePattern;
|
|
238
247
|
exports.walkUpForFile = walkUpForFile;
|
|
239
248
|
exports.walkUpForGlob = walkUpForGlob;
|
|
240
|
-
|
|
241
|
-
//# sourceMappingURL=chunk-
|
|
249
|
+
exports.withheldSpecs = withheldSpecs;
|
|
250
|
+
//# sourceMappingURL=chunk-SWALPLFQ.cjs.map
|
|
251
|
+
//# sourceMappingURL=chunk-SWALPLFQ.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/internal/runtime/context/context-discovery.ts"],"names":["isAbsolute","resolve","existsSync","join","dirname","realpathSync","glob"],"mappings":"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","file":"chunk-SWALPLFQ.cjs","sourcesContent":["/**\n * Context file discovery (T1.1, ADRs D150 / D151).\n *\n * Discovers context files via three scopes:\n * - `cwd-only` — single dir, single path lookup\n * - `git-root-walk` — walk cwd → git-root, collect every directory's match\n * (nearest-first ordering)\n * - `globbed` — glob pattern relative to cwd (e.g. `.cursor/rules/*.mdc`)\n *\n * Pure `existsSync` checks — **no `.gitignore` parsing** (EC-A, KISS) and\n * **no invented `.theokitignore`** (EC-B). Paths normalized via\n * `realpath` to dedup symlink chains pointing to the same physical file\n * (EC-F). Git worktrees work transparently because `.git` exists as a\n * file in that case (EC-N).\n *\n * @internal\n */\n\nimport { existsSync, realpathSync } from \"node:fs\";\nimport { glob } from \"node:fs/promises\";\nimport { dirname, isAbsolute, join, resolve } from \"node:path\";\n\n/** Single filename (\"AGENTS.md\") or relative glob (\".cursor/rules/*.mdc\"). */\nexport type DiscoveryScope = \"cwd-only\" | \"git-root-walk\" | \"globbed\";\n\n/** Parser to apply once file is read. */\nexport type DiscoveryParser = \"plain-markdown\" | \"mdc\" | \"frontmatter-zod\" | \"rules-frontmatter\";\n\n/**\n * One kind of context file the runner knows how to find and read. The shipped registry is\n * `DEFAULT_DISCOVERY_SPECS`; a caller supplies its own array to change the set.\n *\n * `scope` decides how `pattern` is used and how many files a single spec can yield:\n * `cwd-only` looks for one path and stops, `git-root-walk` collects a match in every directory\n * from `cwd` up to the git root (nearest first), and `globbed` expands `pattern` as a glob\n * relative to `cwd`. So `pattern` is a filename for the first two and a glob for the third —\n * putting a glob on a walk scope silently finds nothing.\n *\n * `priority` orders the merged prompt, ascending, and is a plain number rather than an index, so\n * a new spec can be slotted between two existing ones. Lower means earlier and therefore more\n * general; later content wins on conflict.\n *\n * `parser` must match the file format — `plain-markdown` reads the whole file, `mdc` and\n * `rules-frontmatter` parse frontmatter and can DECLINE the file when its activation conditions\n * do not hold, and `frontmatter-zod` is the legacy path the runner currently skips entirely.\n *\n * `followImports` is honored only by `plain-markdown`, and turns `@path` directives in the body\n * into inlined content bounded by the import root. Setting it on a frontmatter parser does\n * nothing.\n *\n * `id` names the source in `<source name=\"\">` and in telemetry. When one spec matches files in\n * several directories, the runner suffixes it with the path relative to the git root to keep them\n * apart.\n *\n * @public — re-exported from `@theokit/sdk/context`, and therefore under semver.\n */\nexport interface DiscoverySpec {\n /** Stable identifier — used as `<source name=\"\">` and telemetry key. */\n readonly id: string;\n /** Priority for merge (lower = earlier in prompt). */\n readonly priority: number;\n /** Filename (cwd-only/git-root-walk) or glob (globbed). */\n readonly pattern: string;\n readonly scope: DiscoveryScope;\n readonly parser: DiscoveryParser;\n /** Whether to follow `@path` import directives (CLAUDE.md / GEMINI.md). */\n readonly followImports: boolean;\n /**\n * The `CompatSource` kind whose grant gates this file — the name a consumer writes in\n * `local.compatSources` to receive it.\n *\n * Absent means UNGATED, and that covers two different situations which the field deliberately does\n * not distinguish, because the gate treats them identically:\n *\n * 1. **Native.** theokit's own roots. Declaring theokit is what running theokit means, so there is\n * no separate grant to ask for.\n * 2. **A repo-root instruction file.** `AGENTS.md`, `GEMINI.md`, `CLAUDE.md` and\n * `.cursor/rules/*.mdc` are every bit as foreign as `.claude/` is, and every one of them puts\n * a cloned repository's prose into the system prompt. They are ungated anyway, for a reason\n * that is a limit rather than a judgement: `adaptersFor` registers ONE foreign adapter,\n * `claude-code`, so `compatSources` has no spelling that admits `agents`, `gemini` or\n * `cursor`. Labelling them would gate them on a grant nobody can write, making three formats\n * permanently unreachable — a silent loss of capability with no way to restore it, which is a\n * worse defect than the one being fixed and the exact shape this codebase already paid for in\n * usetheokit/theokit-sdk#524.\n *\n * `CLAUDE.md` is ungated for the adjacent reason, and this one IS a judgement: the grant gates\n * the foreign ROOT — the `.claude/` directory whose hooks, skills, subagents and plugins\n * already require it — and `CLAUDE.md` does not live there. It sits at the repository root\n * beside the other three, is widely used as a generic agent-instructions file by projects that\n * have no `.claude/` at all, and gating it would take it from them.\n *\n * So this field closes the door the grant vocabulary already has a key for, and leaves three\n * named. Whether a repo-root instruction file should require an opt-in at all is a product\n * decision affecting every consumer, not a bug fix, and it is tracked separately — writing it\n * down is the point, because an undocumented gap reads as an oversight.\n *\n * Optional because this interface is `@public` and under semver: a caller passing its own array\n * keeps working, and its specs read as ungated — the behaviour they had before this field existed.\n *\n * On the SPEC rather than as a condition at the call site, because the table MIXES dialects.\n * Adding one is adding a row, not editing a branch somebody else has to find.\n */\n readonly dialect?: string;\n}\n\n/**\n * The specs a consumer's declared compat sources admit.\n *\n * The half that turns {@link DiscoverySpec.dialect} from a label into a gate. A field nobody consults\n * is a control that is declared, exported, documented and wired to nothing — which is the failure\n * this whole change exists to close, and it would be a poor joke to reproduce it here.\n *\n * Three rules, and each is a decision rather than a convenience:\n *\n * - **A spec with no `dialect` is always admitted.** Absent means native, and a caller's own array\n * predates this field: filtering it by a question it never answered would remove content nobody\n * asked to remove.\n * - **`undefined` sources admit everything.** That is every consumer before this field existed. This\n * is the back-compatibility floor and the reason the change is a minor rather than a breaking one.\n * - **A declared list admits only the dialects it names.** This is the fix: a consumer who grants\n * `theokit` for its own roots and never declares `claude-code` stops receiving that repository's\n * `.claude/rules/*.md` in its prompt.\n *\n * `@internal`, deliberately. The docblock claimed `@public — re-exported from\n * '@theokit/sdk/context'` and the barrel exported no such name: a reach asserted and not given,\n * which is the defect this whole change is about, committed in the fix for it. A consumer building\n * its own `specs` array does not need this function — it passes `declaredCompatKinds` to\n * `runDiscovery` and gets the same filtering, through a public option on a public interface. So the\n * honest correction is to narrow the claim rather than widen the surface.\n *\n * @internal — exported from the module so the gate is testable at its boundary rather than only\n * through a whole agent, and not re-exported from any public entry point.\n */\nexport function admittedSpecs(\n specs: ReadonlyArray<DiscoverySpec>,\n declaredKinds: ReadonlyArray<string> | undefined,\n): ReadonlyArray<DiscoverySpec> {\n if (declaredKinds === undefined) return specs;\n const granted = new Set(declaredKinds);\n return specs.filter((spec) => spec.dialect === undefined || granted.has(spec.dialect));\n}\n\n/**\n * A spec a declaration did not admit, with the grant that would.\n *\n * A NAMED type rather than the inline shape it replaced, and that is not style. The DTS rollup only\n * pulls a symbol into a chunk when a public type references it — with an anonymous return type\n * nothing referenced `withheldSpecs`, the re-export dangled, and the build failed with TS2305 in\n * whichever file carried it. Naming the return value is what makes the function reachable, and it\n * also gives a consumer something to write in their own signature.\n *\n * @public\n */\nexport interface WithheldSpec {\n /** The spec's stable id, as it appears in telemetry. */\n readonly id: string;\n /** The filename or glob that was not loaded. */\n readonly pattern: string;\n /** The `compatSources` grant that would admit it. */\n readonly grant: string;\n}\n\n/**\n * The mirror of {@link admittedSpecs}: the specs a declaration did NOT admit.\n *\n * It exists because `runDiscovery`'s own docblock admits the gap it closes — *\"a shorter result\n * than expected means 'nothing qualified', and this function will not tell you which of those it\n * was\"*. After B-081 gates the four repo-root instruction files, a consumer who declares nothing\n * goes from receiving four files to receiving none, and that has to be legible.\n *\n * Returned as a VALUE rather than only logged, because a log line cannot be asserted by a\n * consumer's test, and this repository does not ship controls that cannot be observed. The loud\n * half is the `warnOnce` the caller emits from this list.\n *\n * Each entry carries the grant that WOULD admit it — being told you lost something, without being\n * told what would bring it back, is a diagnosis with no remedy.\n *\n * `undefined` declaredKinds means \"no gate configured\", which admits everything and therefore\n * withholds nothing. That is NOT the same as `[]`, which is a real declaration of no foreign\n * dialect and withholds every gated spec — the distinction `declaredCompatKinds` already carries,\n * preserved here rather than re-decided.\n *\n * @public — re-exported from `@theokit/sdk/context`, and therefore under semver.\n */\nexport function withheldSpecs(\n specs: ReadonlyArray<DiscoverySpec>,\n declaredKinds: ReadonlyArray<string> | undefined,\n): ReadonlyArray<WithheldSpec> {\n if (declaredKinds === undefined) return [];\n const granted = new Set(declaredKinds);\n return specs\n .filter((spec) => spec.dialect !== undefined && !granted.has(spec.dialect))\n .map((spec) => ({ id: spec.id, pattern: spec.pattern, grant: String(spec.dialect) }));\n}\n\n/**\n * The context files theokit looks for out of the box, in the order they are concatenated.\n *\n * Two things follow from the ordering. `AGENTS.md` comes first at priority 10 and `THEO.md` last,\n * so theokit-specific instruction wins over the vendor-neutral file on conflict. And the array is\n * consumed in the order written — the runner does not re-sort it — so a caller passing its own\n * array is responsible for keeping `priority` and array position consistent.\n *\n * `CLAUDE.md` and `GEMINI.md` are the only two entries with `followImports: true`, which means\n * they are the only files whose `@path` directives pull other files into the prompt. Those\n * imports cannot escape the import root.\n *\n * Frozen only by type: `ReadonlyArray` is a compile-time constraint, and the array and its\n * elements are not deep-frozen at runtime. Build a new array rather than mutating this one.\n *\n * @public — re-exported from `@theokit/sdk/context`, and therefore under semver.\n */\nexport const DEFAULT_DISCOVERY_SPECS: ReadonlyArray<DiscoverySpec> = [\n {\n id: \"AGENTS.md\",\n dialect: \"agents\",\n pattern: \"AGENTS.md\",\n scope: \"git-root-walk\",\n parser: \"plain-markdown\",\n followImports: false,\n priority: 10,\n },\n {\n id: \"GEMINI.md\",\n dialect: \"gemini\",\n pattern: \"GEMINI.md\",\n scope: \"git-root-walk\",\n parser: \"plain-markdown\",\n followImports: true,\n priority: 20,\n },\n {\n id: \"CLAUDE.md\",\n dialect: \"claude-code\",\n pattern: \"CLAUDE.md\",\n scope: \"git-root-walk\",\n parser: \"plain-markdown\",\n followImports: true,\n priority: 30,\n },\n {\n id: \"cursor-rules\",\n dialect: \"cursor\",\n pattern: \".cursor/rules/*.mdc\",\n scope: \"globbed\",\n parser: \"mdc\",\n followImports: false,\n priority: 40,\n },\n {\n id: \"theokit-rules\",\n pattern: \".theokit/rules/*.md\",\n scope: \"globbed\",\n parser: \"rules-frontmatter\",\n followImports: false,\n priority: 45,\n },\n {\n // Rules written for the Claude Code CLI. Measured 2026-08-26 over this repository's 32 rule\n // files: none carries frontmatter, and `rules-frontmatter` already reads a file without it as\n // `alwaysApply: true` — the format needed nothing, only a spec pointing at the directory.\n //\n // 47, not 46. Specs sort ascending and a context budget drops the tail first, so it must land\n // AFTER `.theokit/rules` (45) — the explicit namespace should survive a squeeze the borrowed one\n // does not. It must also leave a slot on BOTH sides: B-127 makes these numbers a public contract\n // precisely so a consumer can place its own source between two defaults, and 46 would have left\n // no room between 45 and itself. 47 keeps 46 free below and 48–49 free above.\n //\n // The reckoning B-127's docblock asks for: no published priority MOVES, so a consumer that chose\n // 46, 48 or 49 is unaffected. A consumer that had chosen 47 now collides — that is the cost of\n // an eighth default, paid once and recorded here rather than discovered later.\n id: \"claude-rules\",\n dialect: \"claude-code\",\n pattern: \".claude/rules/*.md\",\n scope: \"globbed\",\n parser: \"rules-frontmatter\",\n followImports: false,\n priority: 47,\n },\n {\n id: \"theokit-context\",\n pattern: \".theokit/context/*.md\",\n scope: \"globbed\",\n parser: \"frontmatter-zod\",\n followImports: false,\n priority: 50,\n },\n {\n // usetheokit/theokit-sdk#531 — THEO.md was the only context file that could not live at the\n // project root: every sibling here is `git-root-walk`, and this one was `cwd-only` pointed\n // at `.theokit/THEO.md` specifically, with no warning that a root THEO.md was inert.\n //\n // ADDED rather than moving the existing entry below: a project already using\n // `.theokit/THEO.md` keeps working unchanged. 55 sits between `theokit-context` (50) and the\n // existing `THEO.md` (60), leaving room on both sides — the numbering discipline\n // `claude-rules` (47) already established for this array.\n //\n // `followImports: true`, unlike the existing entry (`false`) and unlike `AGENTS.md`. This is\n // a DELIBERATE divergence between the two THEO.md specs, not an inconsistency: a root-level\n // file is edited by the same people, in the same place, as CLAUDE.md/GEMINI.md — the two\n // other root-level, human-facing files that both carry `followImports: true` — so it belongs\n // in their category rather than AGENTS.md's vendor-neutral, import-free one. Because this is a\n // NEW spec, choosing `true` here changes nothing for `.theokit/THEO.md`, which keeps `false`.\n id: \"THEO.md.root\",\n pattern: \"THEO.md\",\n scope: \"git-root-walk\",\n parser: \"plain-markdown\",\n followImports: true,\n priority: 55,\n },\n {\n id: \"THEO.md\",\n pattern: \".theokit/THEO.md\",\n scope: \"cwd-only\",\n parser: \"plain-markdown\",\n followImports: false,\n priority: 60,\n },\n\n // ── The private chain (B-023) ───────────────────────────────────────────────────────────────\n //\n // `*.local.md` is the gitignored companion where an operator keeps the standing corrections too\n // personal or too situational to commit. Nothing read it: measured 2026-09-12, a grep for the four\n // `.local` spellings returned 0 files across this package's source, against a control of 23 for\n // `CLAUDE.md`. The file exists, it is named the documented way, and the agent behaves exactly as\n // it would if the operator had written nothing.\n //\n // ORDER. They sit ABOVE every public spec because a correction has to be composed after the rule\n // it corrects, and they keep the public chain's relative order among themselves (AGENTS, CLAUDE,\n // THEO) so the two halves read the same way.\n //\n // THE COST OF THAT, stated rather than discovered later: `applyAggregateCap` fills the budget in\n // ascending priority, so the HIGHEST numbers are the first dropped when the total cap is reached.\n // Placing the private chain last therefore makes it the first to go under pressure. The\n // alternative — a low number, to protect it — would compose the operator's refinement BEFORE the\n // general rule, which inverts its meaning and is the defect this item is about. The existing table\n // already accepts that trade: `.theokit/THEO.md`, the project's most specific instructions, is at\n // 60 and is equally droppable. This follows the convention rather than inventing an exception.\n //\n // WHY THESE THREE AND NOT SIX. A private companion pairs with a public file THIS seam reads, and\n // the documented convention is THEO / AGENTS / CLAUDE. `GEMINI.local.md` and a private\n // `.cursor/rules` are not part of it, and inventing them would publish a convention nobody writes.\n // Note the rule lands differently in `@theokit/agents`' `DEFAULT_FILE_NAMES`, which has no\n // `CLAUDE.md` and therefore gets no `CLAUDE.local.md` — same rule, two seams, stated at both ends.\n //\n // UNGATED, like the public repo-root files beside them. `CLAUDE.local.md` is a repo-root file, not\n // a `.claude/` one, so it follows `CLAUDE.md` rather than `claude-rules` — see `dialect`'s\n // docblock for why the grant gates the foreign ROOT and not the files beside it.\n {\n id: \"AGENTS.local.md\",\n pattern: \"AGENTS.local.md\",\n scope: \"git-root-walk\",\n parser: \"plain-markdown\",\n followImports: false,\n priority: 70,\n },\n {\n id: \"CLAUDE.local.md\",\n pattern: \"CLAUDE.local.md\",\n scope: \"git-root-walk\",\n parser: \"plain-markdown\",\n // Mirrors `CLAUDE.md`, which follows imports. A private file that could not `@import` while its\n // public sibling can would be a difference nobody declared.\n followImports: true,\n priority: 75,\n },\n {\n id: \"THEO.local.md\",\n pattern: \"THEO.local.md\",\n scope: \"git-root-walk\",\n parser: \"plain-markdown\",\n // Mirrors `THEO.md.root`, which follows imports.\n followImports: true,\n priority: 80,\n },\n];\n\nconst SAFE_FILENAME = /^[a-zA-Z0-9_.\\-/*]+$/;\nconst TRAVERSAL_RE = /(^|\\/)\\.\\.(\\/|$)/;\n\n/**\n * Reject patterns that contain path traversal (`..`) or non-allowed\n * characters (D81 parity, EC-4).\n *\n * @internal\n */\nexport function isSafePattern(pattern: string): boolean {\n if (typeof pattern !== \"string\" || pattern.length === 0) return false;\n if (TRAVERSAL_RE.test(pattern)) return false;\n if (isAbsolute(pattern)) return false;\n return SAFE_FILENAME.test(pattern);\n}\n\n/**\n * Walk upward from `cwd` looking for the closest directory containing\n * a `.git` entry (file OR directory — worktrees use a `.git` FILE,\n * EC-N). Returns the absolute path of that directory, or `undefined`\n * when no git root exists at or above `cwd`.\n *\n * @internal\n */\nexport function findGitRoot(cwd: string): string | undefined {\n if (typeof cwd !== \"string\" || cwd.length === 0) return undefined;\n let current = resolve(cwd);\n // Guard against infinite loops on weird filesystems.\n for (let i = 0; i < 64; i += 1) {\n if (existsSync(join(current, \".git\"))) return current;\n const parent = dirname(current);\n if (parent === current) return undefined;\n current = parent;\n }\n return undefined;\n}\n\n/**\n * Walk `cwd` upward to `stopDir` (inclusive) collecting every existing\n * occurrence of `filename`. Returns absolute, realpath-deduped paths in\n * nearest-first order (innermost dir first).\n *\n * No `.gitignore` parsing (EC-A). Realpath collapses symlink chains\n * pointing to the same physical file (EC-F). Filesystem races (file\n * deleted mid-walk) are skipped silently (EC-5).\n *\n * @internal\n */\n// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: walk-up loop combines validation + realpath dedup + FS-race handling + stopDir guard in a single bounded loop; splitting fragments the dedup invariant.\nexport function walkUpForFile(\n cwd: string,\n filename: string,\n stopDir: string | undefined,\n): string[] {\n if (!isSafePattern(filename)) {\n return [];\n }\n const start = resolve(cwd);\n const stop = stopDir !== undefined ? resolve(stopDir) : undefined;\n const found: string[] = [];\n const seenReal = new Set<string>();\n let current = start;\n // 64-level depth cap.\n for (let i = 0; i < 64; i += 1) {\n const candidate = join(current, filename);\n if (existsSync(candidate)) {\n let real: string;\n try {\n real = realpathSync(candidate);\n } catch {\n // FS race (deleted mid-walk) — skip.\n real = candidate;\n }\n if (!seenReal.has(real)) {\n seenReal.add(real);\n found.push(real);\n }\n }\n if (stop !== undefined && current === stop) break;\n const parent = dirname(current);\n if (parent === current) break;\n current = parent;\n }\n return found;\n}\n\n/**\n * Glob-style discovery under `cwd` (e.g. `.cursor/rules/*.mdc`, `.theokit/rules/**\\/*.md`).\n * Returns absolute, lex-sorted paths.\n *\n * `*` matches within one path segment and `**` spans any depth, including zero — so\n * `.theokit/rules/**\\/*.md` finds `rules/top.md` as well as `rules/deep/nested/inner.md`, while\n * `.theokit/rules/*.md` keeps its flat meaning and finds only the first. That distinction is the\n * compatibility contract: every existing spec uses a single `*`, and widening it would silently\n * start absorbing nested files nobody chose to expose.\n *\n * ## Why this used to be flat, and what changed (B-119)\n *\n * The previous implementation split the pattern at its LAST `/`, treated the prefix as a literal\n * directory and did one `readdir` — documented as \"nested directories deferred to v2\" (EC-R). The\n * deferral was deliberate; what made it a defect was measured from a consumer. TheoCode's own rule\n * loader descends recursively, so migrating it onto the `theokit-rules` spec would have silently\n * dropped every nested rule — on the path that decides whether a repository's hooks execute. And a\n * pattern written to say so, `.theokit/rules/**\\/*.md`, resolved its directory part to a literal\n * `**` and matched NOTHING, not even the top-level file it matched before the globstar was added.\n *\n * ## Why the stdlib rather than a walker\n *\n * `fs.promises.glob` (Node ≥ 22, and this package requires ≥ 22.12) implements exactly these\n * semantics, verified against a fixture before adoption: `**\\/*.md` returns all three depths,\n * `*.md` returns one, and it emits no experimental warning. Writing a recursive walker here would\n * have been a third implementation of matching inside one package — the same duplication that let\n * the enumerator and the compiler in `context-glob.ts` disagree in the first place. `globToRegex`\n * stays where it belongs: deciding whether a rule APPLIES to a set of paths, which is a different\n * question from which files exist.\n *\n * `isSafePattern` still runs first and is unchanged, so `..` is refused before any I/O.\n *\n * @internal\n */\nexport async function walkUpForGlob(cwd: string, pattern: string): Promise<string[]> {\n if (!isSafePattern(pattern)) return [];\n const found: string[] = [];\n try {\n for await (const entry of glob(pattern, { cwd })) {\n found.push(resolve(cwd, entry));\n }\n } catch {\n // A pattern whose directory does not exist is the ordinary case — most projects have no\n // `.cursor/rules/`. Same outcome as matching nothing.\n return [];\n }\n // Sorted, because discovery order becomes prompt order and must not vary with the filesystem.\n //\n // The comparator is explicit and deliberately NOT `localeCompare`, which is the usual suggestion\n // for a bare `.sort()`. `localeCompare` orders by the machine's locale, so the same tree would\n // assemble a different prompt on a differently-configured machine — trading one source of\n // non-determinism for a subtler one. Code-unit ordering is what a bare `.sort()` already does for\n // strings; writing it out states the intent and keeps the result machine-independent.\n return found.sort((a, b) => (a < b ? -1 : a > b ? 1 : 0));\n}\n"]}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunk76PIKR4P_cjs = require('./chunk-76PIKR4P.cjs');
|
|
4
4
|
var chunkJLRLCBJ4_cjs = require('./chunk-JLRLCBJ4.cjs');
|
|
5
|
-
var
|
|
5
|
+
var chunkUNFBHV46_cjs = require('./chunk-UNFBHV46.cjs');
|
|
6
6
|
var chunk6LHQPOMI_cjs = require('./chunk-6LHQPOMI.cjs');
|
|
7
7
|
var crypto = require('crypto');
|
|
8
8
|
var promises = require('fs/promises');
|
|
@@ -51,9 +51,9 @@ function entryHash(entry) {
|
|
|
51
51
|
).digest("hex");
|
|
52
52
|
}
|
|
53
53
|
async function readAllSqliteFacts(root) {
|
|
54
|
-
const dbPath =
|
|
54
|
+
const dbPath = chunk76PIKR4P_cjs.defaultIndexPath(root);
|
|
55
55
|
if (!fs.existsSync(dbPath)) return [];
|
|
56
|
-
const db = await
|
|
56
|
+
const db = await chunk76PIKR4P_cjs.openMemoryDb({ filePath: dbPath });
|
|
57
57
|
try {
|
|
58
58
|
const stmt = db.prepare("SELECT id, path, source, start_line, end_line, text FROM chunks");
|
|
59
59
|
const rows = stmt.all();
|
|
@@ -73,7 +73,7 @@ function nfcEqual(a, b) {
|
|
|
73
73
|
function assertUsableBatchSize(batchSize) {
|
|
74
74
|
if (batchSize === void 0) return;
|
|
75
75
|
if (!Number.isInteger(batchSize) || batchSize < 1) {
|
|
76
|
-
throw new
|
|
76
|
+
throw new chunkUNFBHV46_cjs.ConfigurationError(
|
|
77
77
|
`migrateSqliteToLance: batchSize must be a whole number of at least 1; received ${String(batchSize)}.`,
|
|
78
78
|
{ code: "invalid_batch_size" }
|
|
79
79
|
);
|
|
@@ -82,13 +82,13 @@ function assertUsableBatchSize(batchSize) {
|
|
|
82
82
|
async function migrateSqliteToLance(opts) {
|
|
83
83
|
assertUsableBatchSize(opts.batchSize);
|
|
84
84
|
const cwd = opts.cwd;
|
|
85
|
-
const memoryRoot =
|
|
86
|
-
const finalPath =
|
|
85
|
+
const memoryRoot = chunk76PIKR4P_cjs.resolveMemoryRoot(cwd, { directory: opts.directory });
|
|
86
|
+
const finalPath = chunk76PIKR4P_cjs.lanceStoragePath(memoryRoot);
|
|
87
87
|
const newPath = path.join(memoryRoot, "lance-new");
|
|
88
88
|
const rawLog = opts.logger ?? ((m) => console.log(m));
|
|
89
89
|
const log = (m) => rawLog(chunk6LHQPOMI_cjs.redactSecrets(m));
|
|
90
90
|
if (fs.existsSync(finalPath)) {
|
|
91
|
-
throw new
|
|
91
|
+
throw new chunkUNFBHV46_cjs.ConfigurationError(
|
|
92
92
|
`Destination already exists: ${finalPath}. Remove it manually (\`rm -rf ${finalPath}\`) and re-run.`,
|
|
93
93
|
{ code: "migration_destination_exists" }
|
|
94
94
|
);
|
|
@@ -127,7 +127,7 @@ async function migrateSqliteToLance(opts) {
|
|
|
127
127
|
};
|
|
128
128
|
fs.mkdirSync(newPath, { recursive: true });
|
|
129
129
|
log(`Writing Lance index to ${newPath} ...`);
|
|
130
|
-
const lance = await
|
|
130
|
+
const lance = await chunk76PIKR4P_cjs.LanceIndex.open({
|
|
131
131
|
cwd,
|
|
132
132
|
embedding: placeholderEmbedding,
|
|
133
133
|
storagePath: newPath
|
|
@@ -207,5 +207,5 @@ exports.entryHash = entryHash;
|
|
|
207
207
|
exports.migrateSqliteToLance = migrateSqliteToLance;
|
|
208
208
|
exports.readAllSqliteFacts = readAllSqliteFacts;
|
|
209
209
|
exports.renderDiaryEntry = renderDiaryEntry;
|
|
210
|
-
//# sourceMappingURL=chunk-
|
|
211
|
-
//# sourceMappingURL=chunk-
|
|
210
|
+
//# sourceMappingURL=chunk-T5KOSR5Y.cjs.map
|
|
211
|
+
//# sourceMappingURL=chunk-T5KOSR5Y.cjs.map
|