@theokit/sdk 4.38.0 → 4.39.1
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 +285 -0
- package/dist/a2a/index.cjs +3 -3
- package/dist/a2a/index.js +1 -1
- package/dist/a2a/subagent.d.cts +1 -0
- package/dist/a2a/subagent.d.ts +1 -0
- package/dist/agent-6ULDAQT7.js +46 -0
- package/dist/{agent-3H3UKD6U.js.map → agent-6ULDAQT7.js.map} +1 -1
- package/dist/{agent-U3lBX-5t.d.cts → agent-D7bRK9Kg.d.cts} +70 -5
- package/dist/agent-PVUKI3BB.cjs +55 -0
- package/dist/{agent-2GZC4W2A.cjs.map → agent-PVUKI3BB.cjs.map} +1 -1
- package/dist/{agent-C3AEtM-W.d.ts → agent-ZCZa7YQv.d.ts} +70 -5
- package/dist/agent-session-store-N4TVKHBU.cjs +23 -0
- package/dist/agent-session-store-N4TVKHBU.cjs.map +1 -0
- package/dist/agent-session-store-RHMHP5DG.js +6 -0
- package/dist/agent-session-store-RHMHP5DG.js.map +1 -0
- package/dist/agent.d.ts +37 -1
- package/dist/auth/index.cjs +15 -15
- package/dist/auth/index.js +4 -4
- package/dist/{batch-LXSALQC3.js → batch-6KQM3EBA.js} +12 -12
- package/dist/batch-6KQM3EBA.js.map +1 -0
- package/dist/{batch-NZGN6SFV.cjs → batch-X6JKGDPK.cjs} +26 -26
- package/dist/batch-X6JKGDPK.cjs.map +1 -0
- package/dist/chunk-2RW7K6FN.cjs +34 -0
- package/dist/chunk-2RW7K6FN.cjs.map +1 -0
- package/dist/chunk-3I4B3OIX.js +105 -0
- package/dist/chunk-3I4B3OIX.js.map +1 -0
- package/dist/{chunk-KWXC6ERT.js → chunk-42IFCKQZ.js} +5 -5
- package/dist/{chunk-KWXC6ERT.js.map → chunk-42IFCKQZ.js.map} +1 -1
- package/dist/{chunk-4APWS2YF.js → chunk-4F7JQZOX.js} +9 -36
- package/dist/chunk-4F7JQZOX.js.map +1 -0
- package/dist/{chunk-VYD6BGKK.js → chunk-4JSZYSGW.js} +3 -3
- package/dist/{chunk-VYD6BGKK.js.map → chunk-4JSZYSGW.js.map} +1 -1
- package/dist/{chunk-A6GXYF2Q.js → chunk-65ONFZWM.js} +7 -6
- package/dist/chunk-65ONFZWM.js.map +1 -0
- package/dist/{chunk-SGTMDQ4O.js → chunk-6EEYRFJC.js} +5 -5
- package/dist/{chunk-SGTMDQ4O.js.map → chunk-6EEYRFJC.js.map} +1 -1
- package/dist/{chunk-M4OGSS66.cjs → chunk-6LGQECT7.cjs} +11 -11
- package/dist/{chunk-M4OGSS66.cjs.map → chunk-6LGQECT7.cjs.map} +1 -1
- package/dist/{chunk-KTXOHCAE.cjs → chunk-6NEHIHFU.cjs} +4 -4
- package/dist/{chunk-KTXOHCAE.cjs.map → chunk-6NEHIHFU.cjs.map} +1 -1
- package/dist/chunk-6YNYA7GD.cjs +103 -0
- package/dist/chunk-6YNYA7GD.cjs.map +1 -0
- package/dist/{chunk-2R6NBT5F.cjs → chunk-74D7KSBP.cjs} +11 -11
- package/dist/{chunk-2R6NBT5F.cjs.map → chunk-74D7KSBP.cjs.map} +1 -1
- package/dist/{chunk-6OIO4FYX.cjs → chunk-75DSEWTJ.cjs} +7 -7
- package/dist/{chunk-6OIO4FYX.cjs.map → chunk-75DSEWTJ.cjs.map} +1 -1
- package/dist/{chunk-3XRXORBS.cjs → chunk-7OLG7VI4.cjs} +4 -4
- package/dist/{chunk-3XRXORBS.cjs.map → chunk-7OLG7VI4.cjs.map} +1 -1
- package/dist/chunk-7U2HAAWB.cjs +199 -0
- package/dist/chunk-7U2HAAWB.cjs.map +1 -0
- package/dist/{chunk-QJQ2MAZF.cjs → chunk-7YBJZS5P.cjs} +8 -8
- package/dist/{chunk-QJQ2MAZF.cjs.map → chunk-7YBJZS5P.cjs.map} +1 -1
- package/dist/{chunk-A4XXV2C6.js → chunk-7YSRCQDE.js} +5 -72
- package/dist/chunk-7YSRCQDE.js.map +1 -0
- package/dist/{chunk-ZFZYPLQI.js → chunk-AECV3G5Z.js} +4 -4
- package/dist/{chunk-ZFZYPLQI.js.map → chunk-AECV3G5Z.js.map} +1 -1
- package/dist/{chunk-QFWQLXCL.js → chunk-AR5MQZ3J.js} +3 -3
- package/dist/{chunk-QFWQLXCL.js.map → chunk-AR5MQZ3J.js.map} +1 -1
- package/dist/{chunk-G2F67XUR.cjs → chunk-B4YA6BRS.cjs} +13 -14
- package/dist/chunk-B4YA6BRS.cjs.map +1 -0
- package/dist/{chunk-BE3W4HYV.cjs → chunk-BCQ3E2ZG.cjs} +12 -3
- package/dist/chunk-BCQ3E2ZG.cjs.map +1 -0
- package/dist/{chunk-XJ5TMOGA.js → chunk-BQDUEG4C.js} +3 -3
- package/dist/{chunk-XJ5TMOGA.js.map → chunk-BQDUEG4C.js.map} +1 -1
- package/dist/{chunk-OFWU6UKF.cjs → chunk-C7OP3FAK.cjs} +47 -11
- package/dist/chunk-C7OP3FAK.cjs.map +1 -0
- package/dist/{chunk-UZBA6YYP.cjs → chunk-CAFV7WPQ.cjs} +540 -534
- package/dist/chunk-CAFV7WPQ.cjs.map +1 -0
- package/dist/{chunk-BUGVDCI5.cjs → chunk-CEIHCKTO.cjs} +4 -4
- package/dist/chunk-CEIHCKTO.cjs.map +1 -0
- package/dist/{chunk-3BSP7LSG.cjs → chunk-CN6UX5EV.cjs} +28 -56
- package/dist/chunk-CN6UX5EV.cjs.map +1 -0
- package/dist/{chunk-5BVBNE2F.js → chunk-D7IULBF2.js} +3 -3
- package/dist/{chunk-5BVBNE2F.js.map → chunk-D7IULBF2.js.map} +1 -1
- package/dist/{chunk-G7X2Y7Y2.cjs → chunk-DAXEQELR.cjs} +186 -236
- package/dist/chunk-DAXEQELR.cjs.map +1 -0
- package/dist/{chunk-YVI4YPUP.cjs → chunk-DGLLVCNB.cjs} +4 -4
- package/dist/{chunk-YVI4YPUP.cjs.map → chunk-DGLLVCNB.cjs.map} +1 -1
- package/dist/{chunk-JI34KBNC.js → chunk-DKFGUOWL.js} +3 -3
- package/dist/{chunk-JI34KBNC.js.map → chunk-DKFGUOWL.js.map} +1 -1
- package/dist/{chunk-ZET34IZE.cjs → chunk-DMTZ3FII.cjs} +5 -5
- package/dist/{chunk-ZET34IZE.cjs.map → chunk-DMTZ3FII.cjs.map} +1 -1
- package/dist/{chunk-6XZBKFQ7.js → chunk-DU7DE543.js} +3 -3
- package/dist/{chunk-6XZBKFQ7.js.map → chunk-DU7DE543.js.map} +1 -1
- package/dist/{chunk-VVMLMKYZ.cjs → chunk-DWY25VLP.cjs} +9 -9
- package/dist/{chunk-VVMLMKYZ.cjs.map → chunk-DWY25VLP.cjs.map} +1 -1
- package/dist/{chunk-R4AMI7KD.cjs → chunk-E4IUN3JB.cjs} +15 -15
- package/dist/{chunk-R4AMI7KD.cjs.map → chunk-E4IUN3JB.cjs.map} +1 -1
- package/dist/{chunk-TKDWD3MU.cjs → chunk-ECHGWE47.cjs} +4 -4
- package/dist/{chunk-TKDWD3MU.cjs.map → chunk-ECHGWE47.cjs.map} +1 -1
- package/dist/{chunk-KL7E244K.cjs → chunk-ECW2MLEW.cjs} +4 -4
- package/dist/{chunk-KL7E244K.cjs.map → chunk-ECW2MLEW.cjs.map} +1 -1
- package/dist/{chunk-EDI7DBWO.js → chunk-ET6PHZRX.js} +3 -3
- package/dist/{chunk-EDI7DBWO.js.map → chunk-ET6PHZRX.js.map} +1 -1
- package/dist/{chunk-HLK35TD7.cjs → chunk-FOZC5H7V.cjs} +24 -24
- package/dist/{chunk-HLK35TD7.cjs.map → chunk-FOZC5H7V.cjs.map} +1 -1
- package/dist/{chunk-SRIF7HMN.cjs → chunk-FWBSDQZ7.cjs} +5 -5
- package/dist/{chunk-SRIF7HMN.cjs.map → chunk-FWBSDQZ7.cjs.map} +1 -1
- package/dist/{chunk-XKBJT7WI.cjs → chunk-G2Q3ZC6C.cjs} +4 -4
- package/dist/{chunk-XKBJT7WI.cjs.map → chunk-G2Q3ZC6C.cjs.map} +1 -1
- package/dist/{chunk-4MWBKBS4.cjs → chunk-G4XUXSRN.cjs} +12 -12
- package/dist/{chunk-4MWBKBS4.cjs.map → chunk-G4XUXSRN.cjs.map} +1 -1
- package/dist/{chunk-EE24WJJR.js → chunk-GTVJIGAH.js} +5 -5
- package/dist/{chunk-EE24WJJR.js.map → chunk-GTVJIGAH.js.map} +1 -1
- package/dist/{chunk-VUDH4D2M.js → chunk-H3BOKK42.js} +282 -276
- package/dist/chunk-H3BOKK42.js.map +1 -0
- package/dist/{chunk-BT6DFWZB.cjs → chunk-HIQFVHC6.cjs} +9 -9
- package/dist/{chunk-BT6DFWZB.cjs.map → chunk-HIQFVHC6.cjs.map} +1 -1
- package/dist/{chunk-HI6G3SNY.js → chunk-HSPVMV6T.js} +76 -125
- package/dist/chunk-HSPVMV6T.js.map +1 -0
- package/dist/{chunk-UWEALKAN.js → chunk-HWNVAUK4.js} +3 -3
- package/dist/{chunk-UWEALKAN.js.map → chunk-HWNVAUK4.js.map} +1 -1
- package/dist/{chunk-3VKTDQMX.cjs → chunk-I53ZQHU6.cjs} +4 -4
- package/dist/{chunk-3VKTDQMX.cjs.map → chunk-I53ZQHU6.cjs.map} +1 -1
- package/dist/{chunk-A3MHE2MQ.cjs → chunk-IHFNRNTJ.cjs} +8 -8
- package/dist/{chunk-A3MHE2MQ.cjs.map → chunk-IHFNRNTJ.cjs.map} +1 -1
- package/dist/{chunk-KCZW75PI.js → chunk-IVSD7L22.js} +12 -4
- package/dist/chunk-IVSD7L22.js.map +1 -0
- package/dist/{chunk-JCXIDFRI.js → chunk-J3UK2GMN.js} +3 -3
- package/dist/{chunk-JCXIDFRI.js.map → chunk-J3UK2GMN.js.map} +1 -1
- package/dist/{chunk-IBDE4R5L.cjs → chunk-J6T5LWJ4.cjs} +10 -9
- package/dist/chunk-J6T5LWJ4.cjs.map +1 -0
- package/dist/{chunk-AOZYORH7.js → chunk-JRLXEYR4.js} +21 -5
- package/dist/chunk-JRLXEYR4.js.map +1 -0
- package/dist/{chunk-EUB7YLU2.js → chunk-JZUPMTJY.js} +3 -3
- package/dist/{chunk-EUB7YLU2.js.map → chunk-JZUPMTJY.js.map} +1 -1
- package/dist/{chunk-ZK3BJ4XQ.js → chunk-KE6XKRLQ.js} +3 -3
- package/dist/{chunk-ZK3BJ4XQ.js.map → chunk-KE6XKRLQ.js.map} +1 -1
- package/dist/{chunk-4NVV3GRU.js → chunk-KGRIHEDT.js} +5 -5
- package/dist/{chunk-4NVV3GRU.js.map → chunk-KGRIHEDT.js.map} +1 -1
- package/dist/{chunk-LGCEYEU2.js → chunk-KX7JV5KM.js} +3 -3
- package/dist/{chunk-LGCEYEU2.js.map → chunk-KX7JV5KM.js.map} +1 -1
- package/dist/{chunk-2K7PRHDB.cjs → chunk-LALG2K33.cjs} +8 -8
- package/dist/{chunk-2K7PRHDB.cjs.map → chunk-LALG2K33.cjs.map} +1 -1
- package/dist/{chunk-4WIJSKFA.js → chunk-LGILIGV3.js} +3 -3
- package/dist/{chunk-4WIJSKFA.js.map → chunk-LGILIGV3.js.map} +1 -1
- package/dist/{chunk-7QDTZJRV.js → chunk-LJX2SQV2.js} +6 -6
- package/dist/{chunk-7QDTZJRV.js.map → chunk-LJX2SQV2.js.map} +1 -1
- package/dist/{chunk-ACHGT3D2.js → chunk-MC5EINBV.js} +44 -8
- package/dist/chunk-MC5EINBV.js.map +1 -0
- package/dist/{chunk-M6UUTNDT.js → chunk-ML5A5DOJ.js} +4 -4
- package/dist/{chunk-M6UUTNDT.js.map → chunk-ML5A5DOJ.js.map} +1 -1
- package/dist/{chunk-3MUIYMUG.cjs → chunk-N475ETD6.cjs} +17 -17
- package/dist/{chunk-3MUIYMUG.cjs.map → chunk-N475ETD6.cjs.map} +1 -1
- package/dist/chunk-OXNYIMZZ.js +31 -0
- package/dist/chunk-OXNYIMZZ.js.map +1 -0
- package/dist/{chunk-YCHC45BY.js → chunk-PI4RO4GR.js} +3 -3
- package/dist/{chunk-YCHC45BY.js.map → chunk-PI4RO4GR.js.map} +1 -1
- package/dist/chunk-QKE556YD.js +197 -0
- package/dist/chunk-QKE556YD.js.map +1 -0
- package/dist/{chunk-FV3YEMQ7.js → chunk-RP5HQVLD.js} +13 -14
- package/dist/chunk-RP5HQVLD.js.map +1 -0
- package/dist/chunk-SCFW5MJZ.js +100 -0
- package/dist/chunk-SCFW5MJZ.js.map +1 -0
- package/dist/{chunk-ZYOHF37V.js → chunk-SG5ZWT6C.js} +3 -3
- package/dist/{chunk-ZYOHF37V.js.map → chunk-SG5ZWT6C.js.map} +1 -1
- package/dist/{chunk-ED7ANP6W.cjs → chunk-TIMPJL5V.cjs} +4 -4
- package/dist/{chunk-ED7ANP6W.cjs.map → chunk-TIMPJL5V.cjs.map} +1 -1
- package/dist/{chunk-3XKVRLR2.js → chunk-TOTP24P6.js} +4 -4
- package/dist/{chunk-3XKVRLR2.js.map → chunk-TOTP24P6.js.map} +1 -1
- package/dist/{chunk-PG3QQLWS.cjs → chunk-USZTVNUQ.cjs} +5 -5
- package/dist/{chunk-PG3QQLWS.cjs.map → chunk-USZTVNUQ.cjs.map} +1 -1
- package/dist/{chunk-XS7SKY2F.js → chunk-V2RBCCN5.js} +3 -3
- package/dist/chunk-V2RBCCN5.js.map +1 -0
- package/dist/{chunk-D3SJLXYZ.cjs → chunk-VJYSQXN6.cjs} +10 -10
- package/dist/{chunk-D3SJLXYZ.cjs.map → chunk-VJYSQXN6.cjs.map} +1 -1
- package/dist/{chunk-6ZGD7R27.cjs → chunk-VWI3CDEW.cjs} +8 -75
- package/dist/chunk-VWI3CDEW.cjs.map +1 -0
- package/dist/{chunk-MXRBNJ6D.cjs → chunk-W4WKVOOQ.cjs} +11 -11
- package/dist/{chunk-MXRBNJ6D.cjs.map → chunk-W4WKVOOQ.cjs.map} +1 -1
- package/dist/chunk-XYOHKCYG.cjs +109 -0
- package/dist/chunk-XYOHKCYG.cjs.map +1 -0
- package/dist/{chunk-UD2T7ISG.js → chunk-YP67XZES.js} +4 -4
- package/dist/{chunk-UD2T7ISG.js.map → chunk-YP67XZES.js.map} +1 -1
- package/dist/{chunk-HHUDNTZC.js → chunk-YRXY2A5L.js} +4 -4
- package/dist/{chunk-HHUDNTZC.js.map → chunk-YRXY2A5L.js.map} +1 -1
- package/dist/{chunk-6OKPJZMX.cjs → chunk-Z2CUEBXV.cjs} +25 -9
- package/dist/chunk-Z2CUEBXV.cjs.map +1 -0
- package/dist/compact-session-GKA7GFVT.js +18 -0
- package/dist/{compact-session-RR3ILTES.js.map → compact-session-GKA7GFVT.js.map} +1 -1
- package/dist/compact-session-XMP6OGY3.cjs +55 -0
- package/dist/{compact-session-YOWJJPPB.cjs.map → compact-session-XMP6OGY3.cjs.map} +1 -1
- package/dist/compaction.cjs +16 -16
- package/dist/compaction.js +3 -3
- package/dist/concurrency.cjs +6 -6
- package/dist/concurrency.js +4 -4
- package/dist/context-2FZSC6VQ.cjs +22 -0
- package/dist/{context-Q6ISOCN2.cjs.map → context-2FZSC6VQ.cjs.map} +1 -1
- package/dist/context-ATJJAFOS.js +5 -0
- package/dist/{context-ZDBBPIHY.js.map → context-ATJJAFOS.js.map} +1 -1
- package/dist/{cron-ChQ6zcW2.d.ts → cron-Bx7tzm5R.d.ts} +54 -2
- package/dist/{cron-BdXOZco9.d.cts → cron-D-DVjGQe.d.cts} +54 -2
- package/dist/cron.cjs +33 -29
- package/dist/cron.d.cts +3 -3
- package/dist/cron.d.ts +3 -3
- package/dist/cron.js +32 -28
- package/dist/{errors-BUVjJGJA.d.cts → errors-DMY-gLSK.d.cts} +1 -1
- package/dist/{errors-CZIUKLHt.d.ts → errors-DjBQ4Tn8.d.ts} +1 -1
- package/dist/errors.cjs +21 -21
- package/dist/errors.d.cts +2 -2
- package/dist/errors.d.ts +2 -2
- package/dist/errors.js +2 -2
- package/dist/eval.cjs +41 -36
- package/dist/eval.cjs.map +1 -1
- package/dist/eval.js +37 -32
- package/dist/eval.js.map +1 -1
- package/dist/{executor-DPCBSI35.cjs → executor-BMRICN46.cjs} +26 -25
- package/dist/executor-BMRICN46.cjs.map +1 -0
- package/dist/{executor-ASDDIM2X.js → executor-T65PPOPT.js} +10 -9
- package/dist/executor-T65PPOPT.js.map +1 -0
- package/dist/filesystem/index.cjs +7 -7
- package/dist/filesystem/index.js +3 -3
- package/dist/fs-session-store-J5MCFFUM.cjs +19 -0
- package/dist/{fs-session-store-T5ZLQX42.cjs.map → fs-session-store-J5MCFFUM.cjs.map} +1 -1
- package/dist/fs-session-store-O6FNHECD.js +10 -0
- package/dist/{fs-session-store-K5QUPNJZ.js.map → fs-session-store-O6FNHECD.js.map} +1 -1
- package/dist/generate-object-UF6WIZLF.cjs +20 -0
- package/dist/{generate-object-F56VIZ6U.cjs.map → generate-object-UF6WIZLF.cjs.map} +1 -1
- package/dist/generate-object-XDCBYVK3.js +7 -0
- package/dist/{generate-object-LPSO6GVW.js.map → generate-object-XDCBYVK3.js.map} +1 -1
- package/dist/index-manager-N7RQYUKT.cjs +20 -0
- package/dist/{index-manager-DBJ55ZSO.cjs.map → index-manager-N7RQYUKT.cjs.map} +1 -1
- package/dist/index-manager-ZVZUHPP7.js +11 -0
- package/dist/{index-manager-F2H2RCZU.js.map → index-manager-ZVZUHPP7.js.map} +1 -1
- package/dist/index.cjs +138 -132
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +167 -9
- package/dist/index.d.ts +167 -9
- package/dist/index.js +47 -44
- package/dist/index.js.map +1 -1
- package/dist/{inject-session-RKNLUE72.js → inject-session-7P4CZGDT.js} +7 -6
- package/dist/inject-session-7P4CZGDT.js.map +1 -0
- package/dist/{inject-session-25EC74WV.cjs → inject-session-CC4KBYF6.cjs} +9 -8
- package/dist/inject-session-CC4KBYF6.cjs.map +1 -0
- package/dist/internal/agent-loop/loop-thinking-steps.d.ts +28 -0
- package/dist/internal/agent-loop/message-builders.d.ts +12 -3
- package/dist/internal/diagnostics.d.ts +24 -11
- package/dist/internal/llm/anthropic-shared.d.ts +4 -4
- package/dist/internal/llm/types.d.ts +49 -9
- package/dist/internal/local-agent/mcp-pool.d.ts +7 -3
- package/dist/internal/memory/adapters/azure-openai-embedding.d.cts +2 -0
- package/dist/internal/memory/adapters/catalog.d.cts +1 -0
- package/dist/internal/memory/adapters/cohere-embedding.d.cts +2 -0
- package/dist/internal/memory/adapters/deepinfra-embedding.d.cts +2 -0
- package/dist/internal/memory/adapters/gemini-embedding.d.cts +2 -0
- package/dist/internal/memory/adapters/index.cjs +28 -0
- package/dist/internal/memory/adapters/index.cjs.map +1 -0
- package/dist/internal/memory/adapters/index.d.cts +16 -0
- package/dist/internal/memory/adapters/index.d.ts +16 -0
- package/dist/internal/memory/adapters/index.js +11 -0
- package/dist/internal/memory/adapters/index.js.map +1 -0
- package/dist/internal/memory/adapters/jina-embedding.d.cts +2 -0
- package/dist/internal/memory/adapters/mistral-embedding.d.cts +2 -0
- package/dist/internal/memory/adapters/ollama-embedding.d.cts +34 -0
- package/dist/internal/memory/adapters/openai-compatible.d.cts +51 -0
- package/dist/internal/memory/adapters/openai-compatible.d.ts +28 -0
- package/dist/internal/memory/adapters/openai-embedding.d.cts +2 -0
- package/dist/internal/memory/adapters/openrouter-embedding.d.cts +2 -0
- package/dist/internal/memory/adapters/voyage-embedding.d.cts +2 -0
- package/dist/internal/memory/dreaming/diary.d.ts +4 -0
- package/dist/internal/memory/dreaming/phases.d.ts +15 -0
- package/dist/internal/memory/dreaming/run.d.ts +10 -0
- package/dist/internal/memory/migrate-sqlite-to-lance.d.ts +15 -0
- package/dist/internal/memory/sdk-memory-peer-loader.d.ts +21 -0
- package/dist/internal/persistence/index.cjs +25 -25
- package/dist/internal/persistence/index.js +6 -6
- package/dist/internal/persistence/session-transcript.d.cts +6 -0
- package/dist/internal/persistence/session-transcript.d.ts +6 -0
- package/dist/internal/runtime/concurrency/subagent-credentials.d.ts +35 -0
- package/dist/internal/security/index.cjs +13 -13
- package/dist/internal/security/index.js +3 -3
- package/dist/internal/session/agent-session-store.d.ts +1 -0
- package/dist/internal/session/session-types.d.ts +6 -1
- package/dist/judge-call-NA2G6ZMJ.js +5 -0
- package/dist/{judge-call-3S3T6O2Z.js.map → judge-call-NA2G6ZMJ.js.map} +1 -1
- package/dist/judge-call-U2D33JOW.cjs +22 -0
- package/dist/{judge-call-XIQJ5GIE.cjs.map → judge-call-U2D33JOW.cjs.map} +1 -1
- package/dist/models.cjs +20 -20
- package/dist/models.js +5 -5
- package/dist/path-safety.cjs +10 -10
- package/dist/path-safety.js +3 -3
- package/dist/persistence.cjs +35 -35
- package/dist/persistence.js +7 -7
- package/dist/project.cjs +5 -5
- package/dist/project.js +3 -3
- package/dist/registry-CAS6Y5ZY.js +9 -0
- package/dist/{registry-KMI5RA22.js.map → registry-CAS6Y5ZY.js.map} +1 -1
- package/dist/registry-JSDI4WKA.cjs +46 -0
- package/dist/{registry-BA3SLAN7.cjs.map → registry-JSDI4WKA.cjs.map} +1 -1
- package/dist/retry.cjs +4 -4
- package/dist/retry.js +3 -3
- package/dist/{run-vJHg2eGw.d.cts → run-i2-fUohR.d.cts} +16 -0
- package/dist/{run-vJHg2eGw.d.ts → run-i2-fUohR.d.ts} +16 -0
- package/dist/sandbox/index.cjs +6 -6
- package/dist/sandbox/index.js +2 -2
- package/dist/server/errors-envelope.cjs +14 -14
- package/dist/server/errors-envelope.d.cts +3 -3
- package/dist/server/errors-envelope.d.ts +3 -3
- package/dist/server/errors-envelope.js +3 -3
- package/dist/session-transcript-3B52DKTG.js +5 -0
- package/dist/{session-transcript-MMPWCESR.js.map → session-transcript-3B52DKTG.js.map} +1 -1
- package/dist/session-transcript-H7NUFXXM.cjs +50 -0
- package/dist/{session-transcript-DFGX6WNL.cjs.map → session-transcript-H7NUFXXM.cjs.map} +1 -1
- package/dist/skills.cjs +7 -7
- package/dist/skills.js +5 -5
- package/dist/stream-object-4FDU76YW.cjs +20 -0
- package/dist/{stream-object-YPXZ4F5P.cjs.map → stream-object-4FDU76YW.cjs.map} +1 -1
- package/dist/stream-object-HWDEEQN4.js +7 -0
- package/dist/{stream-object-AFERZU63.js.map → stream-object-HWDEEQN4.js.map} +1 -1
- package/dist/subagents-loader-A4W6C3QP.cjs +15 -0
- package/dist/subagents-loader-A4W6C3QP.cjs.map +1 -0
- package/dist/subagents-loader-X33KH2SZ.js +6 -0
- package/dist/subagents-loader-X33KH2SZ.js.map +1 -0
- package/dist/subagents-loader.cjs +6 -6
- package/dist/subagents-loader.d.cts +2 -2
- package/dist/subagents-loader.d.ts +2 -2
- package/dist/subagents-loader.js +4 -4
- package/dist/subscription/index.cjs +3 -3
- package/dist/subscription/index.js +2 -2
- package/dist/task-store.cjs +7 -7
- package/dist/task-store.js +4 -4
- package/dist/types/agent.d.ts +68 -3
- package/dist/types/conversation.d.ts +7 -0
- package/dist/types/messages.d.ts +9 -0
- package/dist/types/session-message.d.ts +59 -0
- package/dist/types/workflow.d.ts +36 -0
- package/dist/workflow.cjs +27 -27
- package/dist/workflow.d.cts +17 -1
- package/dist/workflow.d.ts +17 -1
- package/dist/workflow.js +6 -6
- package/docs/harness-capability-map.md +22 -0
- package/package.json +11 -1
- package/dist/agent-2GZC4W2A.cjs +0 -51
- package/dist/agent-3H3UKD6U.js +0 -42
- package/dist/batch-LXSALQC3.js.map +0 -1
- package/dist/batch-NZGN6SFV.cjs.map +0 -1
- package/dist/chunk-3BSP7LSG.cjs.map +0 -1
- package/dist/chunk-4APWS2YF.js.map +0 -1
- package/dist/chunk-6OKPJZMX.cjs.map +0 -1
- package/dist/chunk-6ZGD7R27.cjs.map +0 -1
- package/dist/chunk-A4XXV2C6.js.map +0 -1
- package/dist/chunk-A6GXYF2Q.js.map +0 -1
- package/dist/chunk-ACHGT3D2.js.map +0 -1
- package/dist/chunk-AOZYORH7.js.map +0 -1
- package/dist/chunk-BE3W4HYV.cjs.map +0 -1
- package/dist/chunk-BUGVDCI5.cjs.map +0 -1
- package/dist/chunk-FV3YEMQ7.js.map +0 -1
- package/dist/chunk-G2F67XUR.cjs.map +0 -1
- package/dist/chunk-G7X2Y7Y2.cjs.map +0 -1
- package/dist/chunk-HI6G3SNY.js.map +0 -1
- package/dist/chunk-IBDE4R5L.cjs.map +0 -1
- package/dist/chunk-KCZW75PI.js.map +0 -1
- package/dist/chunk-OFWU6UKF.cjs.map +0 -1
- package/dist/chunk-UZBA6YYP.cjs.map +0 -1
- package/dist/chunk-VUDH4D2M.js.map +0 -1
- package/dist/chunk-XS7SKY2F.js.map +0 -1
- package/dist/compact-session-RR3ILTES.js +0 -17
- package/dist/compact-session-YOWJJPPB.cjs +0 -54
- package/dist/context-Q6ISOCN2.cjs +0 -22
- package/dist/context-ZDBBPIHY.js +0 -5
- package/dist/executor-ASDDIM2X.js.map +0 -1
- package/dist/executor-DPCBSI35.cjs.map +0 -1
- package/dist/fs-session-store-K5QUPNJZ.js +0 -10
- package/dist/fs-session-store-T5ZLQX42.cjs +0 -19
- package/dist/generate-object-F56VIZ6U.cjs +0 -20
- package/dist/generate-object-LPSO6GVW.js +0 -7
- package/dist/index-manager-DBJ55ZSO.cjs +0 -19
- package/dist/index-manager-F2H2RCZU.js +0 -10
- package/dist/inject-session-25EC74WV.cjs.map +0 -1
- package/dist/inject-session-RKNLUE72.js.map +0 -1
- package/dist/judge-call-3S3T6O2Z.js +0 -5
- package/dist/judge-call-XIQJ5GIE.cjs +0 -22
- package/dist/registry-BA3SLAN7.cjs +0 -46
- package/dist/registry-KMI5RA22.js +0 -9
- package/dist/session-transcript-DFGX6WNL.cjs +0 -50
- package/dist/session-transcript-MMPWCESR.js +0 -5
- package/dist/stream-object-AFERZU63.js +0 -7
- package/dist/stream-object-YPXZ4F5P.cjs +0 -20
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/internal/auth/credential-store.ts","../src/internal/auth/oauth-engine.ts","../src/internal/auth/resolve-credential.ts"],"names":["join","AuthenticationError","z","statSync","readFileSync","mkdirSync","chmodSync","randomBytes","openSync","writeFileSync","fsyncSync","closeSync","renameSync","unlinkSync","AuthCallbackError","fresh"],"mappings":"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","file":"chunk-KTXOHCAE.cjs","sourcesContent":["import { randomBytes } from \"node:crypto\";\nimport {\n chmodSync,\n closeSync,\n fsyncSync,\n mkdirSync,\n openSync,\n readFileSync,\n renameSync,\n statSync,\n unlinkSync,\n writeFileSync,\n} from \"node:fs\";\nimport { join } from \"node:path\";\n\nimport { z } from \"zod\";\n\nimport { AuthenticationError } from \"../../errors.js\";\n\n/**\n * M42 — the SDK credential store. Promoted DOWN from agent-builder's hardened `agents/lib/credentials.ts`\n * (M37), generalized from a closed `openrouter|anthropic|openai` union to an open `provider: string` and\n * driven by a caller-supplied {@link CredentialStoreConfig} (no hardcoded `.agent-builder`/`auth.json` /\n * `AGENT_BUILDER_HOME`). The security-critical file mechanics are ported VERBATIM (ADR D3 of the M42 plan):\n * atomic O_EXCL + rename + fsync write, 0700/0600 mode gates, `env` is always a PARAMETER (never an ambient\n * `process.env` read). Contract SHAPE adapted from OpenCode's provider `auth.loader` (MIT © 2025 opencode).\n *\n * The env-precedence + key-prefix-inference + declared-provider rungs of the agent-builder resolver are\n * APP POLICY and deliberately stay UP in the consumer; this module owns only the on-disk store + the\n * `api|oauth` discriminated union. See {@link resolveCredential} (SDK) for the store-read + refresh path.\n *\n * @internal\n */\nimport type {\n CredentialStoreConfig,\n StoredCredential,\n StoredOAuthCredential,\n} from \"./auth-types.js\";\n\n/** The store directory, honoring an optional `homeEnvVar` override. */\nexport function credentialHome(\n config: CredentialStoreConfig,\n env: Record<string, string | undefined> = {},\n): string {\n const override = config.homeEnvVar !== undefined ? env[config.homeEnvVar]?.trim() : undefined;\n return override !== undefined && override.length > 0\n ? override\n : join(config.home, config.dirName);\n}\n\n/** The credential file path inside the (possibly overridden) store directory. */\nexport function authFilePath(\n config: CredentialStoreConfig,\n env: Record<string, string | undefined> = {},\n): string {\n return join(credentialHome(config, env), config.fileName);\n}\n\n/**\n * A credential problem the caller can act on. Never carries the key value.\n *\n * M78 — this used to extend bare `Error`, which quietly disabled classification for the entire auth\n * path: `isTransientError` is `err instanceof TheokitAgentError && err.isRetryable === true`\n * (`errors.ts:443`), so a credential failure could never be judged transient OR permanent. The\n * predicate was not \"forgotten\" downstream — it was unusable there by construction.\n *\n * Extending `AuthenticationError` is ADDITIVE: the class still exists, still reports\n * `name: \"CredentialError\"`, and every existing `instanceof CredentialError` stays true. It only\n * gains ancestors. `AuthenticationError` pins `isRetryable: false`, so gaining the ability to be\n * classified does NOT turn a revoked credential into a retry loop.\n *\n * The single reference does the same thing with one root type: Codex routes every domain failure\n * through `CodexErr` with `is_retryable()` as a method (`protocol/src/error.rs:176`), rather than\n * parallel classes extending the language's `Error`.\n */\nexport class CredentialError extends AuthenticationError {\n // Field, not an assignment in the constructor: `AuthenticationError.name` is `override readonly`\n // (`errors.ts:174`), so `this.name = …` does not compile. Caught by `tsc`, not by vitest — the\n // suite was green with the broken assignment because the transpiler strips the type.\n override readonly name: string = \"CredentialError\";\n}\n\n/**\n * The on-disk store — a discriminated union on `type` (OpenCode `Info` shape). A legacy file with NO\n * `type` (or `type: 'api'`) is the API-key variant — read unchanged, no migration. The `oauth` variant\n * carries the token pair + expiry.\n */\nconst apiFileSchema = z\n .object({\n type: z.literal(\"api\").optional(),\n provider: z.string().min(1).optional(),\n api_key: z.string(),\n })\n .strict();\n\nconst oauthFileSchema = z\n .object({\n type: z.literal(\"oauth\"),\n provider: z.string().min(1),\n access: z.string().min(1),\n refresh: z.string().min(1),\n expires: z.number(),\n account_id: z.string().optional(),\n })\n .strict();\n\n// oauth first (it requires `type: 'oauth'`); a legacy `{provider?, api_key}` falls through to api.\nconst fileSchema = z.union([oauthFileSchema, apiFileSchema]);\n\n/**\n * Read the credential file. Absent ⇒ `undefined` (the normal case). Present-but-wrong is a typed error\n * naming the file: a malformed credential store must not surface as a raw parse crash. Enforces the\n * 0700 dir / 0600 file mode gates (ported verbatim — a writable dir lets an attacker swap the file for a\n * symlink to their own account).\n */\n/**\n * The 0700-dir / 0600-file mode gates (ported verbatim). The DIRECTORY matters as much as the file:\n * `mkdirSync(mode)` applies only at creation, so a pre-existing store dir keeps whatever mode it had, and a\n * writable dir lets an attacker replace the credential file with a symlink to their own 0600 file — the\n * agent then runs on THEIR account.\n */\nfunction assertSecureModes(dirPath: string, path: string): void {\n const dirMode = statSync(dirPath).mode & 0o777;\n if ((dirMode & 0o022) !== 0) {\n throw new CredentialError(\n `${dirPath} is writable by other users (mode ${dirMode.toString(8)}), so the credential file ` +\n `inside it can be replaced. Fix it with: chmod 700 ${dirPath}`,\n );\n }\n const mode = statSync(path).mode & 0o777;\n if ((mode & 0o077) !== 0) {\n throw new CredentialError(\n `${path} is readable by other users (mode ${mode.toString(8)}). ` +\n `A credential file must not be. Fix it with: chmod 600 ${path}`,\n );\n }\n}\n\n/**\n * A `z.union` reports a generic \"Invalid input\" at the root, hiding WHAT is wrong. Pick the sub-schema the\n * file was CLEARLY aiming at (by its `type` discriminant) and surface that schema's specific issue.\n */\nfunction describeUnionError(parsed: unknown, err: unknown, path: string): CredentialError {\n const looksOAuth =\n typeof parsed === \"object\" &&\n parsed !== null &&\n (parsed as { type?: unknown }).type === \"oauth\";\n const specific = looksOAuth ? oauthFileSchema.safeParse(parsed) : apiFileSchema.safeParse(parsed);\n let issue: z.ZodIssue | undefined;\n if (!specific.success) {\n issue = specific.error.issues[0];\n } else if (err instanceof z.ZodError) {\n issue = err.issues[0];\n }\n return new CredentialError(\n `${path}: ${issue?.message ?? String(err)} [${issue?.path.join(\".\") || \"root\"}]`,\n );\n}\n\n/** Parse the raw file into the store union, surfacing the SPECIFIC sub-schema issue (not a generic union error). */\nfunction parseStoredFile(raw: string, path: string): StoredCredential {\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n // The parser's message embeds a snippet of the INPUT — up to the raw key when a user pastes the bare\n // key instead of JSON. The position is not actionable anyway, so the expected shape is more useful.\n throw new CredentialError(\n `${path} is not valid JSON. Expected: {\"provider\": \"<name>\", \"api_key\": \"...\"}`,\n );\n }\n try {\n return fileSchema.parse(parsed);\n } catch (err) {\n throw describeUnionError(parsed, err, path);\n }\n}\n\nexport function readAuthFile(\n config: CredentialStoreConfig,\n env: Record<string, string | undefined> = {},\n): StoredCredential | undefined {\n const path = authFilePath(config, env);\n\n let raw: string;\n try {\n raw = readFileSync(path, \"utf8\");\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") return undefined;\n throw new CredentialError(`cannot read ${path}: ${(err as Error).message}`);\n }\n\n assertSecureModes(credentialHome(config, env), path);\n return parseStoredFile(raw, path);\n}\n\n/**\n * Read the stored OAuth credential (with its refresh token), or `undefined` when the store is absent or\n * holds an api credential. The oauth engine needs the refresh token, which the resolved bearer does not\n * carry. Enforces the same 0600/0700 gates as every other read.\n */\nexport function readStoredOAuth(\n config: CredentialStoreConfig,\n env: Record<string, string | undefined> = {},\n): StoredOAuthCredential | undefined {\n const stored = readAuthFile(config, env);\n return stored !== undefined && stored.type === \"oauth\" ? stored : undefined;\n}\n\n/** Narrows a writable credential to the oauth variant. */\nfunction isOAuthWrite(\n c: { provider: string; apiKey: string } | StoredOAuthCredential,\n): c is StoredOAuthCredential {\n return \"type\" in c && c.type === \"oauth\";\n}\n\n/**\n * Persist a credential atomically at mode `0600`. Ported VERBATIM (ADR D3): write to a random-named temp\n * file in the same directory with `wx` (O_EXCL), fsync, close, chmod, then `rename` (atomic on POSIX) —\n * so a crash mid-write leaves whatever was there untouched, and a pre-planted symlink cannot capture the\n * key. The api variant persists the unchanged `{provider, api_key}` (back-compat, no `type` key); the\n * oauth variant persists `{type:'oauth', provider, access, refresh, expires, account_id?}`.\n */\n/** Build the on-disk JSON payload for the credential variant, validating non-empty tokens. */\nfunction buildStorePayload(\n cred: { provider: string; apiKey: string } | StoredOAuthCredential,\n): Record<string, unknown> {\n if (isOAuthWrite(cred)) {\n if (cred.access.length === 0 || cred.refresh.length === 0) {\n throw new CredentialError(\n \"refusing to write an oauth credential with an empty access/refresh token\",\n );\n }\n return {\n type: \"oauth\",\n provider: cred.provider,\n access: cred.access,\n refresh: cred.refresh,\n expires: cred.expires,\n ...(cred.account_id !== undefined ? { account_id: cred.account_id } : {}),\n };\n }\n if (typeof cred.apiKey !== \"string\" || cred.apiKey.length === 0) {\n throw new CredentialError(\"refusing to write an empty API key\");\n }\n return { provider: cred.provider, api_key: cred.apiKey };\n}\n\nexport function writeCredential(\n cred: { provider: string; apiKey: string } | StoredOAuthCredential,\n config: CredentialStoreConfig,\n env: Record<string, string | undefined> = {},\n): string {\n const payload = buildStorePayload(cred);\n\n const dir = credentialHome(config, env);\n mkdirSync(dir, { recursive: true, mode: 0o700 });\n chmodSync(dir, 0o700); // unconditional: mkdirSync's mode applies only at creation\n\n const path = authFilePath(config, env);\n // RANDOM name + `wx` (O_EXCL): a predictable temp name with a plain write follows a pre-planted SYMLINK,\n // landing the key in an attacker's file while reporting success. O_EXCL refuses any pre-existing file or\n // link; the random suffix also removes the pid collision two containers sharing a bind-mounted home make.\n const tmp = `${path}.tmp-${randomBytes(8).toString(\"hex\")}`;\n try {\n const fd = openSync(tmp, \"wx\", 0o600);\n try {\n writeFileSync(fd, `${JSON.stringify(payload, null, 2)}\\n`);\n fsyncSync(fd);\n } finally {\n closeSync(fd);\n }\n chmodSync(tmp, 0o600); // explicit: the mode argument is subject to umask\n renameSync(tmp, path);\n } catch (err) {\n try {\n unlinkSync(tmp);\n } catch {\n // the temp file may not exist; its absence is not a failure of the write\n }\n throw new CredentialError(`cannot write ${path}: ${(err as Error).message}`);\n }\n return path;\n}\n","/**\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 * ─── ADAPTED FROM OpenCode (MIT License, Copyright (c) 2025 opencode — https://github.com/sst/opencode) ───\n * - the device-grant poll loop (device_code → authorization_pending / slow_down) is adapted from\n * `packages/opencode/src/plugin/github-copilot/copilot.ts`;\n * - the JWT-claim / account-id extraction + the OpenAI two-step headless flow are adapted from\n * `packages/opencode/src/plugin/openai/codex.ts`.\n * The MIT license permits this reuse with attribution; this notice + the NOTICE file are that attribution.\n *\n * @internal\n */\nimport { AuthCallbackError } from \"../../server/auth/errors.js\";\n\nimport type {\n CredentialStoreConfig,\n HttpDeps,\n OAuthProviderConfig,\n OAuthTokens,\n ResolvedCredential,\n} from \"./auth-types.js\";\nimport { authFilePath, readStoredOAuth, writeCredential } from \"./credential-store.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 * @internal (re-exported from the package barrel as public)\n */\nimport type {\n CredentialStoreConfig,\n HttpDeps,\n OAuthProviderConfig,\n ResolvedCredential,\n} from \"./auth-types.js\";\nimport { authFilePath, readAuthFile } from \"./credential-store.js\";\nimport { ensureFreshCredential } from \"./oauth-engine.js\";\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/**\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 */\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\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, mirroring OpenCode, whose 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/credential-store.ts","../src/internal/auth/oauth-engine.ts","../src/internal/auth/resolve-credential.ts"],"names":["join","AuthenticationError","z","statSync","readFileSync","mkdirSync","chmodSync","randomBytes","openSync","writeFileSync","fsyncSync","closeSync","renameSync","unlinkSync","AuthCallbackError","fresh"],"mappings":"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","file":"chunk-6NEHIHFU.cjs","sourcesContent":["import { randomBytes } from \"node:crypto\";\nimport {\n chmodSync,\n closeSync,\n fsyncSync,\n mkdirSync,\n openSync,\n readFileSync,\n renameSync,\n statSync,\n unlinkSync,\n writeFileSync,\n} from \"node:fs\";\nimport { join } from \"node:path\";\n\nimport { z } from \"zod\";\n\nimport { AuthenticationError } from \"../../errors.js\";\n\n/**\n * M42 — the SDK credential store. Promoted DOWN from agent-builder's hardened `agents/lib/credentials.ts`\n * (M37), generalized from a closed `openrouter|anthropic|openai` union to an open `provider: string` and\n * driven by a caller-supplied {@link CredentialStoreConfig} (no hardcoded `.agent-builder`/`auth.json` /\n * `AGENT_BUILDER_HOME`). The security-critical file mechanics are ported VERBATIM (ADR D3 of the M42 plan):\n * atomic O_EXCL + rename + fsync write, 0700/0600 mode gates, `env` is always a PARAMETER (never an ambient\n * `process.env` read). Contract SHAPE adapted from OpenCode's provider `auth.loader` (MIT © 2025 opencode).\n *\n * The env-precedence + key-prefix-inference + declared-provider rungs of the agent-builder resolver are\n * APP POLICY and deliberately stay UP in the consumer; this module owns only the on-disk store + the\n * `api|oauth` discriminated union. See {@link resolveCredential} (SDK) for the store-read + refresh path.\n *\n * @internal\n */\nimport type {\n CredentialStoreConfig,\n StoredCredential,\n StoredOAuthCredential,\n} from \"./auth-types.js\";\n\n/** The store directory, honoring an optional `homeEnvVar` override. */\nexport function credentialHome(\n config: CredentialStoreConfig,\n env: Record<string, string | undefined> = {},\n): string {\n const override = config.homeEnvVar !== undefined ? env[config.homeEnvVar]?.trim() : undefined;\n return override !== undefined && override.length > 0\n ? override\n : join(config.home, config.dirName);\n}\n\n/** The credential file path inside the (possibly overridden) store directory. */\nexport function authFilePath(\n config: CredentialStoreConfig,\n env: Record<string, string | undefined> = {},\n): string {\n return join(credentialHome(config, env), config.fileName);\n}\n\n/**\n * A credential problem the caller can act on. Never carries the key value.\n *\n * M78 — this used to extend bare `Error`, which quietly disabled classification for the entire auth\n * path: `isTransientError` is `err instanceof TheokitAgentError && err.isRetryable === true`\n * (`errors.ts:443`), so a credential failure could never be judged transient OR permanent. The\n * predicate was not \"forgotten\" downstream — it was unusable there by construction.\n *\n * Extending `AuthenticationError` is ADDITIVE: the class still exists, still reports\n * `name: \"CredentialError\"`, and every existing `instanceof CredentialError` stays true. It only\n * gains ancestors. `AuthenticationError` pins `isRetryable: false`, so gaining the ability to be\n * classified does NOT turn a revoked credential into a retry loop.\n *\n * The single reference does the same thing with one root type: Codex routes every domain failure\n * through `CodexErr` with `is_retryable()` as a method (`protocol/src/error.rs:176`), rather than\n * parallel classes extending the language's `Error`.\n */\nexport class CredentialError extends AuthenticationError {\n // Field, not an assignment in the constructor: `AuthenticationError.name` is `override readonly`\n // (`errors.ts:174`), so `this.name = …` does not compile. Caught by `tsc`, not by vitest — the\n // suite was green with the broken assignment because the transpiler strips the type.\n override readonly name: string = \"CredentialError\";\n}\n\n/**\n * The on-disk store — a discriminated union on `type` (OpenCode `Info` shape). A legacy file with NO\n * `type` (or `type: 'api'`) is the API-key variant — read unchanged, no migration. The `oauth` variant\n * carries the token pair + expiry.\n */\nconst apiFileSchema = z\n .object({\n type: z.literal(\"api\").optional(),\n provider: z.string().min(1).optional(),\n api_key: z.string(),\n })\n .strict();\n\nconst oauthFileSchema = z\n .object({\n type: z.literal(\"oauth\"),\n provider: z.string().min(1),\n access: z.string().min(1),\n refresh: z.string().min(1),\n expires: z.number(),\n account_id: z.string().optional(),\n })\n .strict();\n\n// oauth first (it requires `type: 'oauth'`); a legacy `{provider?, api_key}` falls through to api.\nconst fileSchema = z.union([oauthFileSchema, apiFileSchema]);\n\n/**\n * Read the credential file. Absent ⇒ `undefined` (the normal case). Present-but-wrong is a typed error\n * naming the file: a malformed credential store must not surface as a raw parse crash. Enforces the\n * 0700 dir / 0600 file mode gates (ported verbatim — a writable dir lets an attacker swap the file for a\n * symlink to their own account).\n */\n/**\n * The 0700-dir / 0600-file mode gates (ported verbatim). The DIRECTORY matters as much as the file:\n * `mkdirSync(mode)` applies only at creation, so a pre-existing store dir keeps whatever mode it had, and a\n * writable dir lets an attacker replace the credential file with a symlink to their own 0600 file — the\n * agent then runs on THEIR account.\n */\nfunction assertSecureModes(dirPath: string, path: string): void {\n const dirMode = statSync(dirPath).mode & 0o777;\n if ((dirMode & 0o022) !== 0) {\n throw new CredentialError(\n `${dirPath} is writable by other users (mode ${dirMode.toString(8)}), so the credential file ` +\n `inside it can be replaced. Fix it with: chmod 700 ${dirPath}`,\n );\n }\n const mode = statSync(path).mode & 0o777;\n if ((mode & 0o077) !== 0) {\n throw new CredentialError(\n `${path} is readable by other users (mode ${mode.toString(8)}). ` +\n `A credential file must not be. Fix it with: chmod 600 ${path}`,\n );\n }\n}\n\n/**\n * A `z.union` reports a generic \"Invalid input\" at the root, hiding WHAT is wrong. Pick the sub-schema the\n * file was CLEARLY aiming at (by its `type` discriminant) and surface that schema's specific issue.\n */\nfunction describeUnionError(parsed: unknown, err: unknown, path: string): CredentialError {\n const looksOAuth =\n typeof parsed === \"object\" &&\n parsed !== null &&\n (parsed as { type?: unknown }).type === \"oauth\";\n const specific = looksOAuth ? oauthFileSchema.safeParse(parsed) : apiFileSchema.safeParse(parsed);\n let issue: z.ZodIssue | undefined;\n if (!specific.success) {\n issue = specific.error.issues[0];\n } else if (err instanceof z.ZodError) {\n issue = err.issues[0];\n }\n return new CredentialError(\n `${path}: ${issue?.message ?? String(err)} [${issue?.path.join(\".\") || \"root\"}]`,\n );\n}\n\n/** Parse the raw file into the store union, surfacing the SPECIFIC sub-schema issue (not a generic union error). */\nfunction parseStoredFile(raw: string, path: string): StoredCredential {\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n // The parser's message embeds a snippet of the INPUT — up to the raw key when a user pastes the bare\n // key instead of JSON. The position is not actionable anyway, so the expected shape is more useful.\n throw new CredentialError(\n `${path} is not valid JSON. Expected: {\"provider\": \"<name>\", \"api_key\": \"...\"}`,\n );\n }\n try {\n return fileSchema.parse(parsed);\n } catch (err) {\n throw describeUnionError(parsed, err, path);\n }\n}\n\nexport function readAuthFile(\n config: CredentialStoreConfig,\n env: Record<string, string | undefined> = {},\n): StoredCredential | undefined {\n const path = authFilePath(config, env);\n\n let raw: string;\n try {\n raw = readFileSync(path, \"utf8\");\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") return undefined;\n throw new CredentialError(`cannot read ${path}: ${(err as Error).message}`);\n }\n\n assertSecureModes(credentialHome(config, env), path);\n return parseStoredFile(raw, path);\n}\n\n/**\n * Read the stored OAuth credential (with its refresh token), or `undefined` when the store is absent or\n * holds an api credential. The oauth engine needs the refresh token, which the resolved bearer does not\n * carry. Enforces the same 0600/0700 gates as every other read.\n */\nexport function readStoredOAuth(\n config: CredentialStoreConfig,\n env: Record<string, string | undefined> = {},\n): StoredOAuthCredential | undefined {\n const stored = readAuthFile(config, env);\n return stored !== undefined && stored.type === \"oauth\" ? stored : undefined;\n}\n\n/** Narrows a writable credential to the oauth variant. */\nfunction isOAuthWrite(\n c: { provider: string; apiKey: string } | StoredOAuthCredential,\n): c is StoredOAuthCredential {\n return \"type\" in c && c.type === \"oauth\";\n}\n\n/**\n * Persist a credential atomically at mode `0600`. Ported VERBATIM (ADR D3): write to a random-named temp\n * file in the same directory with `wx` (O_EXCL), fsync, close, chmod, then `rename` (atomic on POSIX) —\n * so a crash mid-write leaves whatever was there untouched, and a pre-planted symlink cannot capture the\n * key. The api variant persists the unchanged `{provider, api_key}` (back-compat, no `type` key); the\n * oauth variant persists `{type:'oauth', provider, access, refresh, expires, account_id?}`.\n */\n/** Build the on-disk JSON payload for the credential variant, validating non-empty tokens. */\nfunction buildStorePayload(\n cred: { provider: string; apiKey: string } | StoredOAuthCredential,\n): Record<string, unknown> {\n if (isOAuthWrite(cred)) {\n if (cred.access.length === 0 || cred.refresh.length === 0) {\n throw new CredentialError(\n \"refusing to write an oauth credential with an empty access/refresh token\",\n );\n }\n return {\n type: \"oauth\",\n provider: cred.provider,\n access: cred.access,\n refresh: cred.refresh,\n expires: cred.expires,\n ...(cred.account_id !== undefined ? { account_id: cred.account_id } : {}),\n };\n }\n if (typeof cred.apiKey !== \"string\" || cred.apiKey.length === 0) {\n throw new CredentialError(\"refusing to write an empty API key\");\n }\n return { provider: cred.provider, api_key: cred.apiKey };\n}\n\nexport function writeCredential(\n cred: { provider: string; apiKey: string } | StoredOAuthCredential,\n config: CredentialStoreConfig,\n env: Record<string, string | undefined> = {},\n): string {\n const payload = buildStorePayload(cred);\n\n const dir = credentialHome(config, env);\n mkdirSync(dir, { recursive: true, mode: 0o700 });\n chmodSync(dir, 0o700); // unconditional: mkdirSync's mode applies only at creation\n\n const path = authFilePath(config, env);\n // RANDOM name + `wx` (O_EXCL): a predictable temp name with a plain write follows a pre-planted SYMLINK,\n // landing the key in an attacker's file while reporting success. O_EXCL refuses any pre-existing file or\n // link; the random suffix also removes the pid collision two containers sharing a bind-mounted home make.\n const tmp = `${path}.tmp-${randomBytes(8).toString(\"hex\")}`;\n try {\n const fd = openSync(tmp, \"wx\", 0o600);\n try {\n writeFileSync(fd, `${JSON.stringify(payload, null, 2)}\\n`);\n fsyncSync(fd);\n } finally {\n closeSync(fd);\n }\n chmodSync(tmp, 0o600); // explicit: the mode argument is subject to umask\n renameSync(tmp, path);\n } catch (err) {\n try {\n unlinkSync(tmp);\n } catch {\n // the temp file may not exist; its absence is not a failure of the write\n }\n throw new CredentialError(`cannot write ${path}: ${(err as Error).message}`);\n }\n return path;\n}\n","/**\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 * ─── ADAPTED FROM OpenCode (MIT License, Copyright (c) 2025 opencode — https://github.com/sst/opencode) ───\n * - the device-grant poll loop (device_code → authorization_pending / slow_down) is adapted from\n * `packages/opencode/src/plugin/github-copilot/copilot.ts`;\n * - the JWT-claim / account-id extraction + the OpenAI two-step headless flow are adapted from\n * `packages/opencode/src/plugin/openai/codex.ts`.\n * The MIT license permits this reuse with attribution; this notice + the NOTICE file are that attribution.\n *\n * @internal\n */\nimport { AuthCallbackError } from \"../../server/auth/errors.js\";\n\nimport type {\n CredentialStoreConfig,\n HttpDeps,\n OAuthProviderConfig,\n OAuthTokens,\n ResolvedCredential,\n} from \"./auth-types.js\";\nimport { authFilePath, readStoredOAuth, writeCredential } from \"./credential-store.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 * @internal (re-exported from the package barrel as public)\n */\nimport type {\n CredentialStoreConfig,\n HttpDeps,\n OAuthProviderConfig,\n ResolvedCredential,\n} from \"./auth-types.js\";\nimport { authFilePath, readAuthFile } from \"./credential-store.js\";\nimport { ensureFreshCredential } from \"./oauth-engine.js\";\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/**\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 */\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\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, mirroring OpenCode, whose 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"]}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var chunkIHFNRNTJ_cjs = require('./chunk-IHFNRNTJ.cjs');
|
|
4
|
+
var chunkBCQ3E2ZG_cjs = require('./chunk-BCQ3E2ZG.cjs');
|
|
5
|
+
|
|
6
|
+
// src/internal/error-mappers/shared.ts
|
|
7
|
+
var RAW_MAX_BYTES = 2048;
|
|
8
|
+
function parseRetryAfter(headers) {
|
|
9
|
+
if (headers === void 0) return void 0;
|
|
10
|
+
const raw = headers.get("retry-after");
|
|
11
|
+
if (raw === null) return void 0;
|
|
12
|
+
const n = Number(raw);
|
|
13
|
+
if (Number.isFinite(n) && n >= 0) return Math.ceil(n);
|
|
14
|
+
const dateMs = Date.parse(raw);
|
|
15
|
+
if (Number.isFinite(dateMs)) return Math.max(0, Math.ceil((dateMs - Date.now()) / 1e3));
|
|
16
|
+
return void 0;
|
|
17
|
+
}
|
|
18
|
+
function truncateRaw(body) {
|
|
19
|
+
if (body === null || body === void 0) return void 0;
|
|
20
|
+
const s = typeof body === "string" ? body : JSON.stringify(body);
|
|
21
|
+
const truncated = s.length <= RAW_MAX_BYTES ? s : `${s.slice(0, RAW_MAX_BYTES)}\u2026`;
|
|
22
|
+
return chunkBCQ3E2ZG_cjs.redactSecrets(truncated);
|
|
23
|
+
}
|
|
24
|
+
function buildErrorMetadata(args) {
|
|
25
|
+
const retryAfter = parseRetryAfter(args.headers);
|
|
26
|
+
const raw = truncateRaw(args.body);
|
|
27
|
+
return {
|
|
28
|
+
provider: args.provider,
|
|
29
|
+
endpoint: args.endpoint,
|
|
30
|
+
code: args.code,
|
|
31
|
+
statusCode: args.status,
|
|
32
|
+
...retryAfter !== void 0 ? { retryAfter } : {},
|
|
33
|
+
...raw !== void 0 ? { raw } : {}
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// src/internal/error-mappers/openai-compatible.ts
|
|
38
|
+
function mapOpenAICompatibleError(args) {
|
|
39
|
+
const { providerId, status, body, headers, endpoint } = args;
|
|
40
|
+
const code = mapOpenAiStatusToCode(status, body);
|
|
41
|
+
const message = formatMessage(providerId, status, code);
|
|
42
|
+
const metadata = buildErrorMetadata({
|
|
43
|
+
provider: providerId,
|
|
44
|
+
endpoint,
|
|
45
|
+
code,
|
|
46
|
+
status,
|
|
47
|
+
headers,
|
|
48
|
+
body
|
|
49
|
+
});
|
|
50
|
+
if (status === 401 || status === 403) {
|
|
51
|
+
return new chunkIHFNRNTJ_cjs.AuthenticationError(message, { code: `${providerId}_auth_failed`, metadata });
|
|
52
|
+
}
|
|
53
|
+
if (status === 429) {
|
|
54
|
+
return new chunkIHFNRNTJ_cjs.RateLimitError(message, { code: `${providerId}_rate_limit`, metadata });
|
|
55
|
+
}
|
|
56
|
+
if (status === 400) {
|
|
57
|
+
return new chunkIHFNRNTJ_cjs.ConfigurationError(message, { code: `${providerId}_${code}`, metadata });
|
|
58
|
+
}
|
|
59
|
+
if (status === 408) {
|
|
60
|
+
return new chunkIHFNRNTJ_cjs.NetworkError(message, { code: `${providerId}_timeout`, metadata });
|
|
61
|
+
}
|
|
62
|
+
if (status >= 500 && status < 600) {
|
|
63
|
+
return new chunkIHFNRNTJ_cjs.NetworkError(message, { code: `${providerId}_server_error`, metadata });
|
|
64
|
+
}
|
|
65
|
+
return new chunkIHFNRNTJ_cjs.UnknownAgentError(message, { code: `${providerId}_unknown`, metadata });
|
|
66
|
+
}
|
|
67
|
+
function extractOpenAiErrorCode(body) {
|
|
68
|
+
if (body === null || typeof body !== "object") return void 0;
|
|
69
|
+
const err = body.error;
|
|
70
|
+
if (err === void 0 || err === null) return void 0;
|
|
71
|
+
if (typeof err.code === "string") return err.code;
|
|
72
|
+
if (typeof err.type === "string") return err.type;
|
|
73
|
+
return void 0;
|
|
74
|
+
}
|
|
75
|
+
function mapOpenAiStatusToCode(status, body) {
|
|
76
|
+
const rawCode = extractOpenAiErrorCode(body)?.toLowerCase() ?? "";
|
|
77
|
+
if (rawCode.includes("context_length") || rawCode.includes("context_window") || rawCode.includes("too_many_tokens") || rawCode.includes("max_tokens")) {
|
|
78
|
+
return "context_too_long";
|
|
79
|
+
}
|
|
80
|
+
if (rawCode.includes("content_filter") || rawCode.includes("content_policy") || rawCode.includes("safety")) {
|
|
81
|
+
return "content_filtered";
|
|
82
|
+
}
|
|
83
|
+
if (rawCode.includes("model_not_found") || rawCode.includes("model_unavailable") || rawCode.includes("invalid_model")) {
|
|
84
|
+
return "model_unavailable";
|
|
85
|
+
}
|
|
86
|
+
if (status === 402 || rawCode.includes("insufficient_quota") || rawCode.includes("quota_exceeded")) {
|
|
87
|
+
return "quota_exceeded";
|
|
88
|
+
}
|
|
89
|
+
if (status === 401 || status === 403) return "auth_failed";
|
|
90
|
+
if (status === 429) return "rate_limit";
|
|
91
|
+
if (status === 408) return "timeout";
|
|
92
|
+
if (status === 400) return "invalid_request";
|
|
93
|
+
if (status >= 500 && status < 600) return "server_error";
|
|
94
|
+
return "unknown";
|
|
95
|
+
}
|
|
96
|
+
function formatMessage(providerId, status, code) {
|
|
97
|
+
return `${providerId} API error: ${code} (HTTP ${status})`;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
exports.buildErrorMetadata = buildErrorMetadata;
|
|
101
|
+
exports.mapOpenAICompatibleError = mapOpenAICompatibleError;
|
|
102
|
+
//# sourceMappingURL=chunk-6YNYA7GD.cjs.map
|
|
103
|
+
//# sourceMappingURL=chunk-6YNYA7GD.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/internal/error-mappers/shared.ts","../src/internal/error-mappers/openai-compatible.ts"],"names":["redactSecrets","AuthenticationError","RateLimitError","ConfigurationError","NetworkError","UnknownAgentError"],"mappings":"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","file":"chunk-6YNYA7GD.cjs","sourcesContent":["/**\n * Helpers shared between provider HTTP error mappers (ADR D67).\n *\n * Extracted to dedupe identical logic in `anthropic.ts` and\n * `openai-compatible.ts` — retry-after parsing, raw-body truncation,\n * and metadata assembly are dialect-agnostic.\n *\n * @internal\n */\n\nimport type { ErrorCode, ErrorMetadata } from \"../../errors.js\";\nimport { redactSecrets } from \"../security/index.js\";\n\nconst RAW_MAX_BYTES = 2048;\n\n/**\n * Parse the `Retry-After` header (RFC 7231) into seconds. Both forms are\n * supported: numeric-seconds (`Retry-After: 30`) and HTTP-date\n * (`Retry-After: Wed, 21 Oct 2025 07:28:00 GMT` → seconds until that instant,\n * clamped at 0 for a past date). Garbage / missing header → `undefined`.\n *\n * @internal\n */\nexport function parseRetryAfter(headers: Headers | undefined): number | undefined {\n if (headers === undefined) return undefined;\n const raw = headers.get(\"retry-after\");\n if (raw === null) return undefined;\n const n = Number(raw);\n if (Number.isFinite(n) && n >= 0) return Math.ceil(n);\n // HTTP-date form — seconds until the given instant (0 if already elapsed).\n const dateMs = Date.parse(raw);\n if (Number.isFinite(dateMs)) return Math.max(0, Math.ceil((dateMs - Date.now()) / 1000));\n return undefined;\n}\n\n/**\n * Truncate raw response body to ~2KB and redact known credential\n * patterns so it can ride inside `ErrorMetadata.raw` without\n * ballooning logs OR leaking tokens. Returns `undefined` for\n * null/undefined input.\n *\n * Post T1.1 (secret-redaction-discipline, ADR D68): every error metadata\n * goes through `redactSecrets` before exposure. Note the shape change —\n * pre-T1.1 the function preserved the original `body` shape when ≤2KB;\n * now it always returns a (possibly redacted) string, because redaction\n * coerces non-strings to JSON. Consumers who used to do `err.metadata.raw.foo`\n * must now `JSON.parse(err.metadata.raw)` first — but a workspace-wide\n * grep at T1.1 land time confirmed zero such callers.\n *\n * @internal\n */\nexport function truncateRaw(body: unknown): unknown {\n if (body === null || body === undefined) return undefined;\n const s = typeof body === \"string\" ? body : JSON.stringify(body);\n const truncated = s.length <= RAW_MAX_BYTES ? s : `${s.slice(0, RAW_MAX_BYTES)}…`;\n return redactSecrets(truncated);\n}\n\n/**\n * Build an `ErrorMetadata` object with all optional fields included\n * conditionally (no `undefined` keys in the output). Caller passes\n * dialect-specific fields (`provider`, `endpoint`, `code`); shared\n * fields (`statusCode`, `retryAfter`, `raw`) are derived here.\n *\n * @internal\n */\nexport function buildErrorMetadata(args: {\n provider: string;\n endpoint: string;\n code: ErrorCode;\n status: number;\n headers: Headers | undefined;\n body: unknown;\n}): ErrorMetadata {\n const retryAfter = parseRetryAfter(args.headers);\n const raw = truncateRaw(args.body);\n return {\n provider: args.provider,\n endpoint: args.endpoint,\n code: args.code,\n statusCode: args.status,\n ...(retryAfter !== undefined ? { retryAfter } : {}),\n ...(raw !== undefined ? { raw } : {}),\n };\n}\n\n/**\n * D314: extract the provider's request id (`x-request-id` is OpenAI/most;\n * `request-id` is Anthropic). Returns `undefined` when neither is present.\n *\n * @internal\n */\nexport function parseRequestId(headers: Headers | undefined): string | undefined {\n if (headers === undefined) return undefined;\n return headers.get(\"x-request-id\") ?? headers.get(\"request-id\") ?? undefined;\n}\n","/**\n * OpenAI-compatible HTTP error mapper (ADR D67).\n *\n * Translates OpenAI-shaped API error responses (covers OpenAI, OpenRouter,\n * DeepSeek, Together, Mistral, Voyage, DeepInfra, etc.) into typed\n * `TheokitAgentError` subclasses with full `ErrorMetadata`.\n *\n * Body inspection: looks at `body.error.code` / `body.error.type` to detect\n * `context_too_long`, `content_filtered`, `model_unavailable` semantics.\n * Falls back to status-based mapping when body doesn't expose `.error`\n * (e.g., HTML server error page, DeepInfra's `{message: \"...\"}` shape).\n *\n * Never throws — caller is already in an error path.\n *\n * @internal\n */\n\nimport {\n AuthenticationError,\n ConfigurationError,\n type ErrorCode,\n NetworkError,\n RateLimitError,\n type TheokitAgentError,\n UnknownAgentError,\n} from \"../../errors.js\";\nimport { buildErrorMetadata } from \"./shared.js\";\n\ninterface MapOpenAiErrorArgs {\n providerId: string;\n status: number;\n body: unknown;\n headers: Headers | undefined;\n endpoint: string;\n}\n\nexport function mapOpenAICompatibleError(args: MapOpenAiErrorArgs): TheokitAgentError {\n const { providerId, status, body, headers, endpoint } = args;\n const code = mapOpenAiStatusToCode(status, body);\n const message = formatMessage(providerId, status, code);\n const metadata = buildErrorMetadata({\n provider: providerId,\n endpoint,\n code,\n status,\n headers,\n body,\n });\n\n if (status === 401 || status === 403) {\n return new AuthenticationError(message, { code: `${providerId}_auth_failed`, metadata });\n }\n if (status === 429) {\n return new RateLimitError(message, { code: `${providerId}_rate_limit`, metadata });\n }\n if (status === 400) {\n return new ConfigurationError(message, { code: `${providerId}_${code}`, metadata });\n }\n if (status === 408) {\n return new NetworkError(message, { code: `${providerId}_timeout`, metadata });\n }\n if (status >= 500 && status < 600) {\n return new NetworkError(message, { code: `${providerId}_server_error`, metadata });\n }\n return new UnknownAgentError(message, { code: `${providerId}_unknown`, metadata });\n}\n\nfunction extractOpenAiErrorCode(body: unknown): string | undefined {\n if (body === null || typeof body !== \"object\") return undefined;\n const err = (body as { error?: { code?: unknown; type?: unknown } }).error;\n if (err === undefined || err === null) return undefined;\n if (typeof err.code === \"string\") return err.code;\n if (typeof err.type === \"string\") return err.type;\n return undefined;\n}\n\n// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: explicit branch table is clearer than splitting\nfunction mapOpenAiStatusToCode(status: number, body: unknown): ErrorCode {\n const rawCode = extractOpenAiErrorCode(body)?.toLowerCase() ?? \"\";\n\n if (\n rawCode.includes(\"context_length\") ||\n rawCode.includes(\"context_window\") ||\n rawCode.includes(\"too_many_tokens\") ||\n rawCode.includes(\"max_tokens\")\n ) {\n return \"context_too_long\";\n }\n if (\n rawCode.includes(\"content_filter\") ||\n rawCode.includes(\"content_policy\") ||\n rawCode.includes(\"safety\")\n ) {\n return \"content_filtered\";\n }\n if (\n rawCode.includes(\"model_not_found\") ||\n rawCode.includes(\"model_unavailable\") ||\n rawCode.includes(\"invalid_model\")\n ) {\n return \"model_unavailable\";\n }\n // T3.7 — OpenAI 402 / OpenRouter \"Insufficient credits\" / `insufficient_quota`\n // body code now flow to canonical `quota_exceeded`. Pre-T3.7 we returned\n // `invalid_request` because the ErrorCode union lacked the bucket; T3.7\n // added it. AgentRunError.code (KnownAgentRunErrorCode, post-T1.1) has\n // always carried this value; this fix closes the metadata.code surface.\n if (\n status === 402 ||\n rawCode.includes(\"insufficient_quota\") ||\n rawCode.includes(\"quota_exceeded\")\n ) {\n return \"quota_exceeded\";\n }\n\n if (status === 401 || status === 403) return \"auth_failed\";\n if (status === 429) return \"rate_limit\";\n if (status === 408) return \"timeout\";\n if (status === 400) return \"invalid_request\";\n if (status >= 500 && status < 600) return \"server_error\";\n return \"unknown\";\n}\n\nfunction formatMessage(providerId: string, status: number, code: ErrorCode): string {\n return `${providerId} API error: ${code} (HTTP ${status})`;\n}\n"]}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
var
|
|
5
|
-
var
|
|
3
|
+
var chunkI53ZQHU6_cjs = require('./chunk-I53ZQHU6.cjs');
|
|
4
|
+
var chunkZ2CUEBXV_cjs = require('./chunk-Z2CUEBXV.cjs');
|
|
5
|
+
var chunkDMTZ3FII_cjs = require('./chunk-DMTZ3FII.cjs');
|
|
6
6
|
var promises = require('fs/promises');
|
|
7
7
|
var path = require('path');
|
|
8
8
|
|
|
@@ -13,7 +13,7 @@ async function acquireShared(path) {
|
|
|
13
13
|
existing.refs++;
|
|
14
14
|
return createProxy(path);
|
|
15
15
|
}
|
|
16
|
-
const lease = await
|
|
16
|
+
const lease = await chunkI53ZQHU6_cjs.acquireSessionWriter(path);
|
|
17
17
|
sharedLeases.set(path, { lease, refs: 1 });
|
|
18
18
|
return createProxy(path);
|
|
19
19
|
}
|
|
@@ -50,14 +50,14 @@ var FsSessionStore = class {
|
|
|
50
50
|
this.#cwd = options.cwd;
|
|
51
51
|
}
|
|
52
52
|
async readRecords(agentId) {
|
|
53
|
-
return
|
|
53
|
+
return chunkZ2CUEBXV_cjs.readTranscript(chunkZ2CUEBXV_cjs.transcriptPath(this.#baseDir, this.#cwd, agentId));
|
|
54
54
|
}
|
|
55
55
|
async appendRecords(agentId, records) {
|
|
56
56
|
if (records.length === 0) return;
|
|
57
|
-
const path$1 =
|
|
57
|
+
const path$1 = chunkZ2CUEBXV_cjs.transcriptPath(this.#baseDir, this.#cwd, agentId);
|
|
58
58
|
await promises.mkdir(path.dirname(path$1), { recursive: true });
|
|
59
|
-
await
|
|
60
|
-
for (const record of records)
|
|
59
|
+
await chunkDMTZ3FII_cjs.withFileLock(path$1, async () => {
|
|
60
|
+
for (const record of records) chunkDMTZ3FII_cjs.appendJsonl(path$1, record);
|
|
61
61
|
});
|
|
62
62
|
}
|
|
63
63
|
/**
|
|
@@ -76,7 +76,7 @@ var FsSessionStore = class {
|
|
|
76
76
|
*/
|
|
77
77
|
async acquire(agentId) {
|
|
78
78
|
if (this.#leases.has(agentId)) return;
|
|
79
|
-
const path$1 =
|
|
79
|
+
const path$1 = chunkZ2CUEBXV_cjs.transcriptPath(this.#baseDir, this.#cwd, agentId);
|
|
80
80
|
await promises.mkdir(path.dirname(path$1), { recursive: true });
|
|
81
81
|
this.#leases.set(agentId, await acquireShared(path$1));
|
|
82
82
|
}
|
|
@@ -108,5 +108,5 @@ var FsSessionStore = class {
|
|
|
108
108
|
};
|
|
109
109
|
|
|
110
110
|
exports.FsSessionStore = FsSessionStore;
|
|
111
|
-
//# sourceMappingURL=chunk-
|
|
112
|
-
//# sourceMappingURL=chunk-
|
|
111
|
+
//# sourceMappingURL=chunk-74D7KSBP.cjs.map
|
|
112
|
+
//# sourceMappingURL=chunk-74D7KSBP.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/internal/persistence/fs-session-store.ts"],"names":["acquireSessionWriter","readTranscript","transcriptPath","path","mkdir","dirname","withFileLock","appendJsonl"],"mappings":"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","file":"chunk-2R6NBT5F.cjs","sourcesContent":["/**\n * SE41 — `FsSessionStore`, the DEFAULT reference implementation of the pluggable\n * {@link SessionStore} seam. It reads and append-writes the native Claude-shaped\n * `.jsonl` transcript at `<baseDir>/projects/<encoded-cwd>/<agentId>.jsonl` — the\n * exact on-disk format SE40 introduced (the file the Claude Code CLI can\n * `--continue`). Omitting `local.sessionStore` resolves to this store, so the\n * default persistence path is byte-identical to SE40 behavior.\n *\n * `readRecords` is `readTranscript(transcriptPath(...))` (a missing session →\n * `[]`, not an error — a fresh agent has no history). `appendRecords` is a TRUE\n * append: it reads the prior records, concatenates the new-turn delta, and\n * rewrites the whole line set atomically under the SE40 cross-process file lock\n * (`writeTranscript` never shrinks — the native format is an append-only\n * `parentUuid` DAG). The parent dir is created BEFORE acquiring the lock because\n * the lock's companion `<path>.lock` file needs an existing parent dir (the SE40\n * `mkdir(dirname)`-before-lock fix).\n *\n * @internal\n */\n\nimport { mkdir } from \"node:fs/promises\";\nimport { dirname } from \"node:path\";\nimport type { SessionStore } from \"../../types/session-store.js\";\nimport { withFileLock } from \"./file-lock.js\";\nimport { appendJsonl } from \"./jsonl.js\";\nimport { readTranscript, type SessionRecord, transcriptPath } from \"./session-transcript.js\";\nimport { acquireSessionWriter, type SessionWriterLease } from \"./session-writer.js\";\n\n/** Options identifying the on-disk transcript location for the FS default store. */\nexport interface FsSessionStoreOptions {\n /** Transcript base dir (`~/.theokit` default, `~/.claude` for CLI interop) — already `~`-expanded. */\n baseDir: string;\n /** The workspace cwd whose encoded form is the transcript project dir. */\n cwd: string;\n}\n\n/**\n * The default `SessionStore` — reads/append-writes the native `.jsonl` transcript.\n *\n * @internal\n */\n/**\n * Reference-counted leases, shared per path.\n *\n * `acquireSessionWriter` is STRICT on purpose: two concurrent acquisitions of the same path, and\n * exactly one wins — \"a lease that let both through would be decorative\" (the M81 test says exactly\n * that, and it is right). That is the primitive's contract, and it does not change.\n *\n * But within ONE process it is normal to have more than one store over the same session: the golden\n * compaction tests and the concurrent-send tests do exactly that, and they record real runtime\n * behavior. Applying the raw primitive there would turn a legitimate pattern into a\n * `SessionBusyError`.\n *\n * The reconciliation belongs here, in the primitive's consumer: the process takes ONE lease per path\n * and counts how many stores use it. The last to release actually frees it. Cross-process stays\n * strict — which is the problem M81 states (\"`exec resume --last` can write into the TUI's live\n * session\").\n */\nconst sharedLeases = new Map<string, { lease: SessionWriterLease; refs: number }>();\n\nasync function acquireShared(path: string): Promise<SessionWriterLease> {\n const existing = sharedLeases.get(path);\n if (existing !== undefined) {\n existing.refs++;\n return createProxy(path);\n }\n const lease = await acquireSessionWriter(path);\n sharedLeases.set(path, { lease, refs: 1 });\n return createProxy(path);\n}\n\n/** A handle that decrements the count; the last to release frees the real lease. */\nfunction createProxy(path: string): SessionWriterLease {\n let released = false;\n return {\n sessionPath: path,\n // The proxy forwards the renewal to the ONE real lease this path shares. Renewing through any\n // holder is correct and is the point: the record must say \"someone in this process is still\n // writing\", and the refcount already guarantees they are all the same owner.\n renew: (): void => {\n if (released) return;\n sharedLeases.get(path)?.lease.renew();\n },\n release: async (): Promise<void> => {\n if (released) return;\n released = true;\n const entry = sharedLeases.get(path);\n if (entry === undefined) return;\n entry.refs--;\n if (entry.refs > 0) return;\n sharedLeases.delete(path);\n await entry.lease.release();\n },\n };\n}\n\nexport class FsSessionStore implements SessionStore {\n readonly #baseDir: string;\n readonly #cwd: string;\n /** One lease per `agentId` — a store serves more than one session over the process lifetime. */\n readonly #leases = new Map<string, SessionWriterLease>();\n\n constructor(options: FsSessionStoreOptions) {\n this.#baseDir = options.baseDir;\n this.#cwd = options.cwd;\n }\n\n async readRecords(agentId: string): Promise<SessionRecord[]> {\n return readTranscript(transcriptPath(this.#baseDir, this.#cwd, agentId));\n }\n\n async appendRecords(agentId: string, records: readonly SessionRecord[]): Promise<void> {\n // Empty delta → nothing to persist (avoids an unnecessary lock + rewrite).\n if (records.length === 0) return;\n const path = transcriptPath(this.#baseDir, this.#cwd, agentId);\n // mkdir BEFORE the lock: withFileLock's companion `<path>.lock` needs the parent dir.\n await mkdir(dirname(path), { recursive: true });\n\n await withFileLock(path, async () => {\n // M93 — appends the DELTA instead of rewriting the whole file.\n //\n // Before: `readTranscript` + `writeTranscript` of everything, per turn. O(n) of I/O **and** of\n // parsing on every turn, O(n^2) per session — the consumer note in\n // `agents/lib/session/backtrack.ts` records 1.4 MB / 3000 lines over 200 turns.\n //\n // Correct because the format **is already append-only**: the `parentUuid` DAG does not depend\n // on line order, and every record carries its own parent. `appendJsonl` **already existed in\n // the package** and had a single caller (`eval/runner.ts`) — the primitive was there, it was\n // the store that ignored it (rung 4).\n //\n // `withFileLock` stays — but the earlier claim that \"it is what serializes two concurrent\n // `appendRecords`\" was too strong, and M93's adversarial review measured it: removing it fails\n // no test. The reason is the paragraph above — the `parentUuid` DAG does not depend on line\n // order, so two interleaved batches reconstruct identically. The work the lock was doing\n // (protecting a read-modify-write) disappeared along with the rewrite.\n //\n // What it still covers is the TOCTOU window in `needsLineBreakBefore` (read the last byte,\n // then write): without it, two processes can both conclude \"a \\n is missing\" and produce a\n // blank line — which the reader discards, i.e. benign. It stays as a **declared, not\n // mechanized** defense (the discipline in `error-handling.md` § 4: enumerate the residue\n // rather than let a missing test pass for coverage).\n //\n // `writeTranscript` still exists for **compaction**, the one operation that legitimately\n // rewrites the file.\n for (const record of records) appendJsonl(path, record);\n });\n }\n\n /**\n * Takes the session's writer lease. Throws `SessionBusyError` when another process holds it.\n *\n * **Explicit, and NOT inside `appendRecords`** — M95's adversarial review measured why that\n * matters: the `SessionStore` contract states that \"an `appendRecords` rejection is logged to\n * stderr, NOT thrown to the caller (best-effort write)\". Acquiring there made the\n * `SessionBusyError` get **swallowed**, and the result was worse than the original problem:\n * instead of two writers interleaving lines, the loser **lost the turn silently** — nothing on\n * disk, a stderr warning invisible under the TUI, and no way for the caller to react.\n *\n * At init the error reaches someone who can act: `exec` forks to a new id, which is exactly what\n * the error message itself prescribes. It is the difference between failing where a decision is\n * possible and failing where only loss is.\n */\n async acquire(agentId: string): Promise<void> {\n if (this.#leases.has(agentId)) return;\n const path = transcriptPath(this.#baseDir, this.#cwd, agentId);\n await mkdir(dirname(path), { recursive: true });\n this.#leases.set(agentId, await acquireShared(path));\n }\n\n /**\n * Releases ONE agent's lease.\n *\n * It exists because `dispose()` releases **every** lease the store holds, and a store injected by\n * the consumer may serve several agents: an init that fails for agent B must not free agent A's\n * lease, which is still live and writing.\n */\n async release(agentId: string): Promise<void> {\n const lease = this.#leases.get(agentId);\n if (lease === undefined) return;\n this.#leases.delete(agentId);\n await lease.release();\n }\n\n /**\n * Releases every lease this store holds.\n *\n * Without it the `.writer.lock` outlives the process and the next open would have to wait out the\n * heartbeat window — recoverable, but 30 s of waiting after a CLEAN shutdown would be an avoidable\n * defect. Idempotent: calling it twice is not an error.\n */\n async dispose(): Promise<void> {\n const leases = [...this.#leases.values()];\n this.#leases.clear();\n for (const lease of leases) await lease.release();\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/internal/persistence/fs-session-store.ts"],"names":["acquireSessionWriter","readTranscript","transcriptPath","path","mkdir","dirname","withFileLock","appendJsonl"],"mappings":"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","file":"chunk-74D7KSBP.cjs","sourcesContent":["/**\n * SE41 — `FsSessionStore`, the DEFAULT reference implementation of the pluggable\n * {@link SessionStore} seam. It reads and append-writes the native Claude-shaped\n * `.jsonl` transcript at `<baseDir>/projects/<encoded-cwd>/<agentId>.jsonl` — the\n * exact on-disk format SE40 introduced (the file the Claude Code CLI can\n * `--continue`). Omitting `local.sessionStore` resolves to this store, so the\n * default persistence path is byte-identical to SE40 behavior.\n *\n * `readRecords` is `readTranscript(transcriptPath(...))` (a missing session →\n * `[]`, not an error — a fresh agent has no history). `appendRecords` is a TRUE\n * append: it reads the prior records, concatenates the new-turn delta, and\n * rewrites the whole line set atomically under the SE40 cross-process file lock\n * (`writeTranscript` never shrinks — the native format is an append-only\n * `parentUuid` DAG). The parent dir is created BEFORE acquiring the lock because\n * the lock's companion `<path>.lock` file needs an existing parent dir (the SE40\n * `mkdir(dirname)`-before-lock fix).\n *\n * @internal\n */\n\nimport { mkdir } from \"node:fs/promises\";\nimport { dirname } from \"node:path\";\nimport type { SessionStore } from \"../../types/session-store.js\";\nimport { withFileLock } from \"./file-lock.js\";\nimport { appendJsonl } from \"./jsonl.js\";\nimport { readTranscript, type SessionRecord, transcriptPath } from \"./session-transcript.js\";\nimport { acquireSessionWriter, type SessionWriterLease } from \"./session-writer.js\";\n\n/** Options identifying the on-disk transcript location for the FS default store. */\nexport interface FsSessionStoreOptions {\n /** Transcript base dir (`~/.theokit` default, `~/.claude` for CLI interop) — already `~`-expanded. */\n baseDir: string;\n /** The workspace cwd whose encoded form is the transcript project dir. */\n cwd: string;\n}\n\n/**\n * The default `SessionStore` — reads/append-writes the native `.jsonl` transcript.\n *\n * @internal\n */\n/**\n * Reference-counted leases, shared per path.\n *\n * `acquireSessionWriter` is STRICT on purpose: two concurrent acquisitions of the same path, and\n * exactly one wins — \"a lease that let both through would be decorative\" (the M81 test says exactly\n * that, and it is right). That is the primitive's contract, and it does not change.\n *\n * But within ONE process it is normal to have more than one store over the same session: the golden\n * compaction tests and the concurrent-send tests do exactly that, and they record real runtime\n * behavior. Applying the raw primitive there would turn a legitimate pattern into a\n * `SessionBusyError`.\n *\n * The reconciliation belongs here, in the primitive's consumer: the process takes ONE lease per path\n * and counts how many stores use it. The last to release actually frees it. Cross-process stays\n * strict — which is the problem M81 states (\"`exec resume --last` can write into the TUI's live\n * session\").\n */\nconst sharedLeases = new Map<string, { lease: SessionWriterLease; refs: number }>();\n\nasync function acquireShared(path: string): Promise<SessionWriterLease> {\n const existing = sharedLeases.get(path);\n if (existing !== undefined) {\n existing.refs++;\n return createProxy(path);\n }\n const lease = await acquireSessionWriter(path);\n sharedLeases.set(path, { lease, refs: 1 });\n return createProxy(path);\n}\n\n/** A handle that decrements the count; the last to release frees the real lease. */\nfunction createProxy(path: string): SessionWriterLease {\n let released = false;\n return {\n sessionPath: path,\n // The proxy forwards the renewal to the ONE real lease this path shares. Renewing through any\n // holder is correct and is the point: the record must say \"someone in this process is still\n // writing\", and the refcount already guarantees they are all the same owner.\n renew: (): void => {\n if (released) return;\n sharedLeases.get(path)?.lease.renew();\n },\n release: async (): Promise<void> => {\n if (released) return;\n released = true;\n const entry = sharedLeases.get(path);\n if (entry === undefined) return;\n entry.refs--;\n if (entry.refs > 0) return;\n sharedLeases.delete(path);\n await entry.lease.release();\n },\n };\n}\n\nexport class FsSessionStore implements SessionStore {\n readonly #baseDir: string;\n readonly #cwd: string;\n /** One lease per `agentId` — a store serves more than one session over the process lifetime. */\n readonly #leases = new Map<string, SessionWriterLease>();\n\n constructor(options: FsSessionStoreOptions) {\n this.#baseDir = options.baseDir;\n this.#cwd = options.cwd;\n }\n\n async readRecords(agentId: string): Promise<SessionRecord[]> {\n return readTranscript(transcriptPath(this.#baseDir, this.#cwd, agentId));\n }\n\n async appendRecords(agentId: string, records: readonly SessionRecord[]): Promise<void> {\n // Empty delta → nothing to persist (avoids an unnecessary lock + rewrite).\n if (records.length === 0) return;\n const path = transcriptPath(this.#baseDir, this.#cwd, agentId);\n // mkdir BEFORE the lock: withFileLock's companion `<path>.lock` needs the parent dir.\n await mkdir(dirname(path), { recursive: true });\n\n await withFileLock(path, async () => {\n // M93 — appends the DELTA instead of rewriting the whole file.\n //\n // Before: `readTranscript` + `writeTranscript` of everything, per turn. O(n) of I/O **and** of\n // parsing on every turn, O(n^2) per session — the consumer note in\n // `agents/lib/session/backtrack.ts` records 1.4 MB / 3000 lines over 200 turns.\n //\n // Correct because the format **is already append-only**: the `parentUuid` DAG does not depend\n // on line order, and every record carries its own parent. `appendJsonl` **already existed in\n // the package** and had a single caller (`eval/runner.ts`) — the primitive was there, it was\n // the store that ignored it (rung 4).\n //\n // `withFileLock` stays — but the earlier claim that \"it is what serializes two concurrent\n // `appendRecords`\" was too strong, and M93's adversarial review measured it: removing it fails\n // no test. The reason is the paragraph above — the `parentUuid` DAG does not depend on line\n // order, so two interleaved batches reconstruct identically. The work the lock was doing\n // (protecting a read-modify-write) disappeared along with the rewrite.\n //\n // What it still covers is the TOCTOU window in `needsLineBreakBefore` (read the last byte,\n // then write): without it, two processes can both conclude \"a \\n is missing\" and produce a\n // blank line — which the reader discards, i.e. benign. It stays as a **declared, not\n // mechanized** defense (the discipline in `error-handling.md` § 4: enumerate the residue\n // rather than let a missing test pass for coverage).\n //\n // `writeTranscript` still exists for **compaction**, the one operation that legitimately\n // rewrites the file.\n for (const record of records) appendJsonl(path, record);\n });\n }\n\n /**\n * Takes the session's writer lease. Throws `SessionBusyError` when another process holds it.\n *\n * **Explicit, and NOT inside `appendRecords`** — M95's adversarial review measured why that\n * matters: the `SessionStore` contract states that \"an `appendRecords` rejection is logged to\n * stderr, NOT thrown to the caller (best-effort write)\". Acquiring there made the\n * `SessionBusyError` get **swallowed**, and the result was worse than the original problem:\n * instead of two writers interleaving lines, the loser **lost the turn silently** — nothing on\n * disk, a stderr warning invisible under the TUI, and no way for the caller to react.\n *\n * At init the error reaches someone who can act: `exec` forks to a new id, which is exactly what\n * the error message itself prescribes. It is the difference between failing where a decision is\n * possible and failing where only loss is.\n */\n async acquire(agentId: string): Promise<void> {\n if (this.#leases.has(agentId)) return;\n const path = transcriptPath(this.#baseDir, this.#cwd, agentId);\n await mkdir(dirname(path), { recursive: true });\n this.#leases.set(agentId, await acquireShared(path));\n }\n\n /**\n * Releases ONE agent's lease.\n *\n * It exists because `dispose()` releases **every** lease the store holds, and a store injected by\n * the consumer may serve several agents: an init that fails for agent B must not free agent A's\n * lease, which is still live and writing.\n */\n async release(agentId: string): Promise<void> {\n const lease = this.#leases.get(agentId);\n if (lease === undefined) return;\n this.#leases.delete(agentId);\n await lease.release();\n }\n\n /**\n * Releases every lease this store holds.\n *\n * Without it the `.writer.lock` outlives the process and the next open would have to wait out the\n * heartbeat window — recoverable, but 30 s of waiting after a CLEAN shutdown would be an avoidable\n * defect. Idempotent: calling it twice is not an error.\n */\n async dispose(): Promise<void> {\n const leases = [...this.#leases.values()];\n this.#leases.clear();\n for (const lease of leases) await lease.release();\n }\n}\n"]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
var
|
|
3
|
+
var chunkIHFNRNTJ_cjs = require('./chunk-IHFNRNTJ.cjs');
|
|
4
|
+
var chunkBCQ3E2ZG_cjs = require('./chunk-BCQ3E2ZG.cjs');
|
|
5
5
|
var promises = require('fs/promises');
|
|
6
6
|
var path = require('path');
|
|
7
7
|
|
|
@@ -69,7 +69,7 @@ function applyWalWithFallback(db, label) {
|
|
|
69
69
|
function logFallback(label, reason) {
|
|
70
70
|
if (warnedLabels.has(label)) return;
|
|
71
71
|
warnedLabels.add(label);
|
|
72
|
-
|
|
72
|
+
chunkBCQ3E2ZG_cjs.diag(
|
|
73
73
|
`[theokit-sdk] ${label}: WAL unavailable (${reason}); using DELETE journal mode. This is normal on NFS/SMB/FUSE; expect slightly slower concurrent access.
|
|
74
74
|
`
|
|
75
75
|
);
|
|
@@ -141,7 +141,7 @@ async function loadDriver(filePath) {
|
|
|
141
141
|
} catch (nodeSqliteCause) {
|
|
142
142
|
const b = betterSqliteCause instanceof Error ? betterSqliteCause.message : String(betterSqliteCause);
|
|
143
143
|
const n = nodeSqliteCause instanceof Error ? nodeSqliteCause.message : String(nodeSqliteCause);
|
|
144
|
-
throw new
|
|
144
|
+
throw new chunkIHFNRNTJ_cjs.ConfigurationError(
|
|
145
145
|
`Failed to load SQLite driver. Install \`better-sqlite3\` or run on Node 22.5+ for built-in \`node:sqlite\`. better-sqlite3: ${b}; node:sqlite: ${n}`,
|
|
146
146
|
{ code: "sqlite_driver_unavailable", cause: nodeSqliteCause }
|
|
147
147
|
);
|
|
@@ -157,7 +157,7 @@ async function renameAside(filePath, label) {
|
|
|
157
157
|
await promises.rename(filePath, asidePath).catch(() => void 0);
|
|
158
158
|
await promises.rename(`${filePath}-wal`, `${asidePath}-wal`).catch(() => void 0);
|
|
159
159
|
await promises.rename(`${filePath}-shm`, `${asidePath}-shm`).catch(() => void 0);
|
|
160
|
-
|
|
160
|
+
chunkBCQ3E2ZG_cjs.diag(
|
|
161
161
|
`[theokit-sdk] ${label} database corrupt; renamed aside to ${asidePath} and rebuilt schema
|
|
162
162
|
`
|
|
163
163
|
);
|
|
@@ -168,5 +168,5 @@ exports.containsCjk = containsCjk;
|
|
|
168
168
|
exports.isCorruptionError = isCorruptionError;
|
|
169
169
|
exports.openSqliteResilient = openSqliteResilient;
|
|
170
170
|
exports.sanitizeFts5Query = sanitizeFts5Query;
|
|
171
|
-
//# sourceMappingURL=chunk-
|
|
172
|
-
//# sourceMappingURL=chunk-
|
|
171
|
+
//# sourceMappingURL=chunk-75DSEWTJ.cjs.map
|
|
172
|
+
//# sourceMappingURL=chunk-75DSEWTJ.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/internal/persistence/fts5-sanitize.ts","../src/internal/persistence/sqlite-wal.ts","../src/internal/persistence/sqlite-open.ts"],"names":["diag","mkdir","dirname","ConfigurationError","rename"],"mappings":"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","file":"chunk-6OIO4FYX.cjs","sourcesContent":["/**\n * FTS5 query sanitization + CJK detection (ADR D64).\n *\n * Port of Hermes' 6-step sanitizer (`hermes_state.py:1797-1847`). Prevents\n * crashes on user inputs with hyphens, dots, underscores, and unmatched\n * specials. Auto-quotes identifier-shaped tokens so `error-code` finds\n * literal `error-code` instead of `error AND code`.\n *\n * CJK detection returns true for inputs containing characters in the main\n * CJK Unicode ranges (Chinese, Japanese, Korean). CJK trigram routing is\n * deferred to v1.4 — callers receiving `containsCjk === true` should\n * short-circuit to an empty result or LIKE fallback for v1.3.\n *\n * @internal\n */\n\n// Control-char sentinels for the phrase-preservation placeholder. U+0001\n// and U+0002 are essentially never present in real user queries, and\n// crucially do NOT form word boundaries / `\\w` characters, so Step 5's\n// auto-quote regex (`\\b\\w+[-._]\\w[\\w\\-._]*\\b`) cannot match them.\n// Choosing `__PHRASE_N__` instead would re-trigger Step 5 on the second\n// sanitize pass and break idempotence.\nconst PHRASE_OPEN = \"\u0001\";\nconst PHRASE_CLOSE = \"\u0002\";\n\n/**\n * Six-step FTS5 query sanitizer. Returns a query string safe for passing\n * to `WHERE <fts5_table> MATCH ?` as a parameter.\n *\n * Returns empty string when the input contains only specials (caller MUST\n * short-circuit to avoid runtime SQL error — EC-3).\n *\n * @internal\n */\nexport function sanitizeFts5Query(query: string): string {\n if (query.length === 0) return query;\n\n // Step 1: preserve \"quoted phrases\" via control-char placeholders.\n const phrases: string[] = [];\n let text = query.replace(/\"[^\"]+\"/g, (match) => {\n phrases.push(match);\n return `${PHRASE_OPEN}${phrases.length - 1}${PHRASE_CLOSE}`;\n });\n\n // Step 2: strip unmatched specials (brackets, braces, parens, double quotes, caret).\n text = text.replace(/[[\\]{}()\"^]/g, \" \");\n\n // Step 3: collapse repeated asterisks (FTS5 prefix operator is single `*`).\n text = text.replace(/\\*+/g, \"*\");\n\n // Step 4: strip dangling boolean operators (AND/OR/NOT) at start/end.\n text = text.replace(/^\\s*(AND|OR|NOT)\\s+/i, \"\");\n text = text.replace(/\\s+(AND|OR|NOT)\\s*$/i, \"\");\n\n // Step 5: auto-quote identifier-shaped tokens that contain `-`, `.`, or `_`.\n // FTS5 tokenizer would otherwise split them as boolean conjunctions.\n text = text.replace(/\\b\\w+[-._]\\w[\\w\\-._]*\\b/g, (match) => `\"${match}\"`);\n\n // Step 6: restore preserved phrases.\n for (let i = 0; i < phrases.length; i += 1) {\n text = text.replace(`${PHRASE_OPEN}${i}${PHRASE_CLOSE}`, phrases[i] ?? \"\");\n }\n\n return text.trim();\n}\n\n// CJK code-point ranges. Coverage matches Hermes' coarse detection for v1.3;\n// fine-grained trigram routing comes in v1.4.\nconst CJK_RANGES: ReadonlyArray<readonly [number, number]> = [\n [0x3000, 0x303f], // CJK Symbols and Punctuation\n [0x3040, 0x309f], // Hiragana\n [0x30a0, 0x30ff], // Katakana\n [0x3400, 0x4dbf], // CJK Unified Ideographs Extension A\n [0x4e00, 0x9fff], // CJK Unified Ideographs\n [0xac00, 0xd7af], // Hangul Syllables\n];\n\n/**\n * Returns true if `text` contains at least one character in the main CJK\n * Unicode ranges.\n *\n * @internal\n */\nexport function containsCjk(text: string): boolean {\n for (const char of text) {\n const cp = char.codePointAt(0);\n if (cp === undefined) continue;\n for (const [lo, hi] of CJK_RANGES) {\n if (cp >= lo && cp <= hi) return true;\n }\n }\n return false;\n}\n","import { diag } from \"../diagnostics.js\";\n\n/**\n * SQLite WAL mode helper with NFS/SMB/FUSE fallback to DELETE (ADR D63).\n *\n * WAL is faster (concurrent readers + one writer) but unsupported on some\n * network/FUSE filesystems. Try WAL; if the pragma returns something else\n * or throws, fall back to DELETE journal mode. Warn one time per label.\n *\n * @internal\n */\n\ninterface PragmaCapable {\n pragma: (statement: string, options?: { simple?: boolean }) => unknown;\n}\n\n/**\n * Result of `applyWalWithFallback`.\n *\n * @internal\n */\nexport interface WalApplyResult {\n /** Final journal_mode actually in effect. */\n mode: \"wal\" | \"delete\";\n /** True if we wanted WAL but the filesystem refused. */\n fellBack: boolean;\n}\n\nconst warnedLabels = new Set<string>();\n\n/**\n * Apply WAL mode with DELETE fallback. Idempotent — safe to call multiple\n * times on the same connection.\n *\n * @param db any `pragma()`-capable SQLite handle (e.g., `better-sqlite3`)\n * @param label short identifier used in the warning (e.g., \"memory-index\")\n *\n * @internal\n */\nexport function applyWalWithFallback(db: PragmaCapable, label: string): WalApplyResult {\n try {\n const result = db.pragma(\"journal_mode = WAL\", { simple: true });\n if (typeof result === \"string\" && result.toLowerCase() === \"wal\") {\n return { mode: \"wal\", fellBack: false };\n }\n logFallback(label, `got \"${String(result)}\" instead of \"wal\"`);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n logFallback(label, msg);\n }\n\n db.pragma(\"journal_mode = DELETE\");\n return { mode: \"delete\", fellBack: true };\n}\n\nfunction logFallback(label: string, reason: string): void {\n if (warnedLabels.has(label)) return;\n warnedLabels.add(label);\n diag(\n `[theokit-sdk] ${label}: WAL unavailable (${reason}); using DELETE journal mode. ` +\n \"This is normal on NFS/SMB/FUSE; expect slightly slower concurrent access.\\n\",\n );\n}\n\n/**\n * Test helper — clears the warn-once registry.\n *\n * @internal\n */\nexport function _resetWalWarnings(): void {\n warnedLabels.clear();\n}\n","/**\n * Resilient SQLite open (plan m0-foundation-expose-primitives, M0-5).\n *\n * Generalizes the driver-load + WAL-apply + corruption-recovery logic that was\n * duplicated (byte-identical) across `sdk/internal/memory/index-db.ts` and\n * `sdk-memory/internal/index/index-db.ts`. Schema-agnostic: the caller applies\n * its own PRAGMA/SCHEMA via the `onOpen` callback.\n *\n * Corruption recovery (EC-7): when opening fails with a \"malformed\" / \"not a\n * database\" / \"encrypted\" error and `recoverCorrupt` is not false, the file is\n * renamed aside to `<path>.corrupt-<ts>` (plus its WAL/SHM siblings) and a fresh\n * DB is opened. The corrupt file is renamed, NOT backed up — the timestamped\n * `.corrupt-*` file is kept for manual recovery.\n *\n * @internal — public via `@theokit/sdk/internal/persistence` (semver-exempt)\n */\n\nimport { mkdir, rename } from \"node:fs/promises\";\nimport { dirname } from \"node:path\";\n\nimport { ConfigurationError } from \"../../errors.js\";\nimport { diag } from \"../diagnostics.js\";\nimport { applyWalWithFallback } from \"./sqlite-wal.js\";\n\n/** Minimal SQLite handle surface every driver (`better-sqlite3`) exposes. */\nexport interface ResilientSqliteDb {\n /** SQLite `pragma()` access (used by `applyWalWithFallback`). */\n pragma(statement: string, options?: { simple?: boolean }): unknown;\n exec(sql: string): void;\n close(): void;\n}\n\nexport interface OpenSqliteResilientOptions<T extends ResilientSqliteDb> {\n /** Absolute path to the SQLite file. Parent directories are created. */\n filePath: string;\n /**\n * Called after the driver is open and WAL is applied, before the handle is\n * returned. Apply PRAGMA/SCHEMA statements here. Errors propagate.\n */\n onOpen?: (db: T) => void | Promise<void>;\n /** Label used in the WAL-fallback warning and corruption-recovery log. Default \"sqlite\". */\n label?: string;\n /** When true (default) a corruption error renames the file aside and rebuilds. */\n recoverCorrupt?: boolean;\n}\n\n/**\n * Open a SQLite file with WAL (+ DELETE fallback) and corruption recovery.\n *\n * @typeParam T - the concrete DB handle type the driver returns (defaults to the\n * minimal {@link ResilientSqliteDb} surface)\n */\nexport async function openSqliteResilient<T extends ResilientSqliteDb = ResilientSqliteDb>(\n options: OpenSqliteResilientOptions<T>,\n): Promise<T> {\n await mkdir(dirname(options.filePath), { recursive: true });\n try {\n return await openConcrete(options);\n } catch (cause) {\n if (options.recoverCorrupt !== false && isCorruptionError(cause)) {\n await renameAside(options.filePath, options.label ?? \"sqlite\");\n return await openConcrete(options);\n }\n throw cause;\n }\n}\n\nasync function openConcrete<T extends ResilientSqliteDb>(\n options: OpenSqliteResilientOptions<T>,\n): Promise<T> {\n const db = await loadDriver<T>(options.filePath);\n // Apply WAL with NFS/SMB/FUSE fallback BEFORE schema so the journal mode is\n // set for the whole session.\n applyWalWithFallback(db, options.label ?? \"sqlite\");\n await options.onOpen?.(db);\n return db;\n}\n\n/** Injectable driver loaders (tests simulate a consumer env without better-sqlite3). */\ninterface DriverLoaders {\n betterSqlite3?: () => Promise<unknown>;\n nodeSqlite?: () => Promise<unknown>;\n}\nlet driverLoaderOverrides: DriverLoaders | undefined;\n\n/** Test-only. @internal */\nexport function _setDriverLoadersForTests(overrides: DriverLoaders | undefined): void {\n driverLoaderOverrides = overrides;\n}\n\n/**\n * Adapt `node:sqlite`'s `DatabaseSync` to the better-sqlite3 surface this module's callers use\n * (`prepare/get/all/run`, `exec`, `close`, `pragma`, `loadExtension`). The error message below has\n * ALWAYS promised this fallback (\"or run on Node 22.5+ for built-in node:sqlite\") — before the\n * flicker-bug fix the promise was fabricated: only better-sqlite3 was ever tried, so every consumer\n * without the optional native dep lost memory tools AND got a per-turn stderr WARN.\n */\nfunction adaptNodeSqlite(db: {\n prepare(sql: string): unknown;\n exec(sql: string): void;\n close(): void;\n loadExtension?: (path: string) => void;\n}): ResilientSqliteDb {\n const pragma = (statement: string, options?: { simple?: boolean }): unknown => {\n const stmt = db.prepare(`PRAGMA ${statement}`) as {\n get(): Record<string, unknown> | undefined;\n };\n const row = stmt.get();\n if (options?.simple === true) {\n return row === undefined ? undefined : Object.values(row)[0];\n }\n return row === undefined ? [] : [row];\n };\n return new Proxy(db as unknown as ResilientSqliteDb, {\n get(target, prop, receiver) {\n if (prop === \"pragma\") return pragma;\n if (prop === \"loadExtension\" && typeof db.loadExtension !== \"function\") {\n return () => {\n throw new Error(\n \"SQLite extension loading is unavailable on the node:sqlite fallback — install better-sqlite3 for sqlite-vec\",\n );\n };\n }\n const value = Reflect.get(target, prop, receiver) as unknown;\n return typeof value === \"function\"\n ? (value as (...a: unknown[]) => unknown).bind(target)\n : value;\n },\n });\n}\n\n// PRE-EXISTING debt, exposed when M75 fixed the Biome config that used to abort before\n// sweeping these files (a nested root under refactor/). It is not new code and was not touched\n// by M75; refactoring SDK internals without review would trade a visible problem for a diff\n// arriscado. Rastreado em usetheodev/theokit-sdk#151.\n// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: see the reason just above\nasync function loadDriver<T extends ResilientSqliteDb>(filePath: string): Promise<T> {\n let betterSqliteCause: unknown;\n try {\n const mod = (await (driverLoaderOverrides?.betterSqlite3?.() ?? import(\"better-sqlite3\"))) as {\n default?: unknown;\n };\n const Ctor = mod.default ?? mod;\n if (typeof Ctor !== \"function\") {\n throw new Error(`better-sqlite3 export is not a constructor (got ${typeof Ctor})`);\n }\n return new (Ctor as new (path: string) => unknown)(filePath) as T;\n } catch (cause) {\n betterSqliteCause = cause;\n }\n // Fallback: the Node 22.5+ built-in driver (the path the error message documents).\n // `process.getBuiltinModule` (Node 22.3+) instead of `import(\"node:sqlite\")` — bundlers that\n // predate the sqlite builtin rewrite the import specifier to a bare \"sqlite\" package (proven in\n // the published dist: \"Cannot find package 'sqlite'\"), while getBuiltinModule is opaque to them.\n try {\n const mod = (await (driverLoaderOverrides?.nodeSqlite?.() ??\n Promise.resolve(\n (process as { getBuiltinModule?: (id: string) => unknown }).getBuiltinModule?.(\n \"node:sqlite\",\n ) ??\n (() => {\n throw new Error(\"node:sqlite built-in unavailable (Node < 22.3)\");\n })(),\n ))) as {\n DatabaseSync: new (\n path: string,\n ) => {\n prepare(sql: string): unknown;\n exec(sql: string): void;\n close(): void;\n };\n };\n return adaptNodeSqlite(new mod.DatabaseSync(filePath)) as T;\n } catch (nodeSqliteCause) {\n const b =\n betterSqliteCause instanceof Error ? betterSqliteCause.message : String(betterSqliteCause);\n const n = nodeSqliteCause instanceof Error ? nodeSqliteCause.message : String(nodeSqliteCause);\n throw new ConfigurationError(\n `Failed to load SQLite driver. Install \\`better-sqlite3\\` or run on Node 22.5+ for built-in \\`node:sqlite\\`. better-sqlite3: ${b}; node:sqlite: ${n}`,\n { code: \"sqlite_driver_unavailable\", cause: nodeSqliteCause },\n );\n }\n}\n\n/** True when an open error indicates an unreadable / corrupt database file. */\nexport function isCorruptionError(cause: unknown): boolean {\n if (!(cause instanceof Error)) return false;\n const msg = cause.message.toLowerCase();\n return (\n msg.includes(\"malformed\") ||\n msg.includes(\"not a database\") ||\n msg.includes(\"encrypted\") ||\n msg.includes(\"disk image is malformed\")\n );\n}\n\nasync function renameAside(filePath: string, label: string): Promise<void> {\n const asidePath = `${filePath}.corrupt-${Date.now()}`;\n await rename(filePath, asidePath).catch(() => undefined);\n await rename(`${filePath}-wal`, `${asidePath}-wal`).catch(() => undefined);\n await rename(`${filePath}-shm`, `${asidePath}-shm`).catch(() => undefined);\n diag(\n `[theokit-sdk] ${label} database corrupt; renamed aside to ${asidePath} and rebuilt schema\\n`,\n );\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/internal/persistence/fts5-sanitize.ts","../src/internal/persistence/sqlite-wal.ts","../src/internal/persistence/sqlite-open.ts"],"names":["diag","mkdir","dirname","ConfigurationError","rename"],"mappings":"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","file":"chunk-75DSEWTJ.cjs","sourcesContent":["/**\n * FTS5 query sanitization + CJK detection (ADR D64).\n *\n * Port of Hermes' 6-step sanitizer (`hermes_state.py:1797-1847`). Prevents\n * crashes on user inputs with hyphens, dots, underscores, and unmatched\n * specials. Auto-quotes identifier-shaped tokens so `error-code` finds\n * literal `error-code` instead of `error AND code`.\n *\n * CJK detection returns true for inputs containing characters in the main\n * CJK Unicode ranges (Chinese, Japanese, Korean). CJK trigram routing is\n * deferred to v1.4 — callers receiving `containsCjk === true` should\n * short-circuit to an empty result or LIKE fallback for v1.3.\n *\n * @internal\n */\n\n// Control-char sentinels for the phrase-preservation placeholder. U+0001\n// and U+0002 are essentially never present in real user queries, and\n// crucially do NOT form word boundaries / `\\w` characters, so Step 5's\n// auto-quote regex (`\\b\\w+[-._]\\w[\\w\\-._]*\\b`) cannot match them.\n// Choosing `__PHRASE_N__` instead would re-trigger Step 5 on the second\n// sanitize pass and break idempotence.\nconst PHRASE_OPEN = \"\u0001\";\nconst PHRASE_CLOSE = \"\u0002\";\n\n/**\n * Six-step FTS5 query sanitizer. Returns a query string safe for passing\n * to `WHERE <fts5_table> MATCH ?` as a parameter.\n *\n * Returns empty string when the input contains only specials (caller MUST\n * short-circuit to avoid runtime SQL error — EC-3).\n *\n * @internal\n */\nexport function sanitizeFts5Query(query: string): string {\n if (query.length === 0) return query;\n\n // Step 1: preserve \"quoted phrases\" via control-char placeholders.\n const phrases: string[] = [];\n let text = query.replace(/\"[^\"]+\"/g, (match) => {\n phrases.push(match);\n return `${PHRASE_OPEN}${phrases.length - 1}${PHRASE_CLOSE}`;\n });\n\n // Step 2: strip unmatched specials (brackets, braces, parens, double quotes, caret).\n text = text.replace(/[[\\]{}()\"^]/g, \" \");\n\n // Step 3: collapse repeated asterisks (FTS5 prefix operator is single `*`).\n text = text.replace(/\\*+/g, \"*\");\n\n // Step 4: strip dangling boolean operators (AND/OR/NOT) at start/end.\n text = text.replace(/^\\s*(AND|OR|NOT)\\s+/i, \"\");\n text = text.replace(/\\s+(AND|OR|NOT)\\s*$/i, \"\");\n\n // Step 5: auto-quote identifier-shaped tokens that contain `-`, `.`, or `_`.\n // FTS5 tokenizer would otherwise split them as boolean conjunctions.\n text = text.replace(/\\b\\w+[-._]\\w[\\w\\-._]*\\b/g, (match) => `\"${match}\"`);\n\n // Step 6: restore preserved phrases.\n for (let i = 0; i < phrases.length; i += 1) {\n text = text.replace(`${PHRASE_OPEN}${i}${PHRASE_CLOSE}`, phrases[i] ?? \"\");\n }\n\n return text.trim();\n}\n\n// CJK code-point ranges. Coverage matches Hermes' coarse detection for v1.3;\n// fine-grained trigram routing comes in v1.4.\nconst CJK_RANGES: ReadonlyArray<readonly [number, number]> = [\n [0x3000, 0x303f], // CJK Symbols and Punctuation\n [0x3040, 0x309f], // Hiragana\n [0x30a0, 0x30ff], // Katakana\n [0x3400, 0x4dbf], // CJK Unified Ideographs Extension A\n [0x4e00, 0x9fff], // CJK Unified Ideographs\n [0xac00, 0xd7af], // Hangul Syllables\n];\n\n/**\n * Returns true if `text` contains at least one character in the main CJK\n * Unicode ranges.\n *\n * @internal\n */\nexport function containsCjk(text: string): boolean {\n for (const char of text) {\n const cp = char.codePointAt(0);\n if (cp === undefined) continue;\n for (const [lo, hi] of CJK_RANGES) {\n if (cp >= lo && cp <= hi) return true;\n }\n }\n return false;\n}\n","import { diag } from \"../diagnostics.js\";\n\n/**\n * SQLite WAL mode helper with NFS/SMB/FUSE fallback to DELETE (ADR D63).\n *\n * WAL is faster (concurrent readers + one writer) but unsupported on some\n * network/FUSE filesystems. Try WAL; if the pragma returns something else\n * or throws, fall back to DELETE journal mode. Warn one time per label.\n *\n * @internal\n */\n\ninterface PragmaCapable {\n pragma: (statement: string, options?: { simple?: boolean }) => unknown;\n}\n\n/**\n * Result of `applyWalWithFallback`.\n *\n * @internal\n */\nexport interface WalApplyResult {\n /** Final journal_mode actually in effect. */\n mode: \"wal\" | \"delete\";\n /** True if we wanted WAL but the filesystem refused. */\n fellBack: boolean;\n}\n\nconst warnedLabels = new Set<string>();\n\n/**\n * Apply WAL mode with DELETE fallback. Idempotent — safe to call multiple\n * times on the same connection.\n *\n * @param db any `pragma()`-capable SQLite handle (e.g., `better-sqlite3`)\n * @param label short identifier used in the warning (e.g., \"memory-index\")\n *\n * @internal\n */\nexport function applyWalWithFallback(db: PragmaCapable, label: string): WalApplyResult {\n try {\n const result = db.pragma(\"journal_mode = WAL\", { simple: true });\n if (typeof result === \"string\" && result.toLowerCase() === \"wal\") {\n return { mode: \"wal\", fellBack: false };\n }\n logFallback(label, `got \"${String(result)}\" instead of \"wal\"`);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n logFallback(label, msg);\n }\n\n db.pragma(\"journal_mode = DELETE\");\n return { mode: \"delete\", fellBack: true };\n}\n\nfunction logFallback(label: string, reason: string): void {\n if (warnedLabels.has(label)) return;\n warnedLabels.add(label);\n diag(\n `[theokit-sdk] ${label}: WAL unavailable (${reason}); using DELETE journal mode. ` +\n \"This is normal on NFS/SMB/FUSE; expect slightly slower concurrent access.\\n\",\n );\n}\n\n/**\n * Test helper — clears the warn-once registry.\n *\n * @internal\n */\nexport function _resetWalWarnings(): void {\n warnedLabels.clear();\n}\n","/**\n * Resilient SQLite open (plan m0-foundation-expose-primitives, M0-5).\n *\n * Generalizes the driver-load + WAL-apply + corruption-recovery logic that was\n * duplicated (byte-identical) across `sdk/internal/memory/index-db.ts` and\n * `sdk-memory/internal/index/index-db.ts`. Schema-agnostic: the caller applies\n * its own PRAGMA/SCHEMA via the `onOpen` callback.\n *\n * Corruption recovery (EC-7): when opening fails with a \"malformed\" / \"not a\n * database\" / \"encrypted\" error and `recoverCorrupt` is not false, the file is\n * renamed aside to `<path>.corrupt-<ts>` (plus its WAL/SHM siblings) and a fresh\n * DB is opened. The corrupt file is renamed, NOT backed up — the timestamped\n * `.corrupt-*` file is kept for manual recovery.\n *\n * @internal — public via `@theokit/sdk/internal/persistence` (semver-exempt)\n */\n\nimport { mkdir, rename } from \"node:fs/promises\";\nimport { dirname } from \"node:path\";\n\nimport { ConfigurationError } from \"../../errors.js\";\nimport { diag } from \"../diagnostics.js\";\nimport { applyWalWithFallback } from \"./sqlite-wal.js\";\n\n/** Minimal SQLite handle surface every driver (`better-sqlite3`) exposes. */\nexport interface ResilientSqliteDb {\n /** SQLite `pragma()` access (used by `applyWalWithFallback`). */\n pragma(statement: string, options?: { simple?: boolean }): unknown;\n exec(sql: string): void;\n close(): void;\n}\n\nexport interface OpenSqliteResilientOptions<T extends ResilientSqliteDb> {\n /** Absolute path to the SQLite file. Parent directories are created. */\n filePath: string;\n /**\n * Called after the driver is open and WAL is applied, before the handle is\n * returned. Apply PRAGMA/SCHEMA statements here. Errors propagate.\n */\n onOpen?: (db: T) => void | Promise<void>;\n /** Label used in the WAL-fallback warning and corruption-recovery log. Default \"sqlite\". */\n label?: string;\n /** When true (default) a corruption error renames the file aside and rebuilds. */\n recoverCorrupt?: boolean;\n}\n\n/**\n * Open a SQLite file with WAL (+ DELETE fallback) and corruption recovery.\n *\n * @typeParam T - the concrete DB handle type the driver returns (defaults to the\n * minimal {@link ResilientSqliteDb} surface)\n */\nexport async function openSqliteResilient<T extends ResilientSqliteDb = ResilientSqliteDb>(\n options: OpenSqliteResilientOptions<T>,\n): Promise<T> {\n await mkdir(dirname(options.filePath), { recursive: true });\n try {\n return await openConcrete(options);\n } catch (cause) {\n if (options.recoverCorrupt !== false && isCorruptionError(cause)) {\n await renameAside(options.filePath, options.label ?? \"sqlite\");\n return await openConcrete(options);\n }\n throw cause;\n }\n}\n\nasync function openConcrete<T extends ResilientSqliteDb>(\n options: OpenSqliteResilientOptions<T>,\n): Promise<T> {\n const db = await loadDriver<T>(options.filePath);\n // Apply WAL with NFS/SMB/FUSE fallback BEFORE schema so the journal mode is\n // set for the whole session.\n applyWalWithFallback(db, options.label ?? \"sqlite\");\n await options.onOpen?.(db);\n return db;\n}\n\n/** Injectable driver loaders (tests simulate a consumer env without better-sqlite3). */\ninterface DriverLoaders {\n betterSqlite3?: () => Promise<unknown>;\n nodeSqlite?: () => Promise<unknown>;\n}\nlet driverLoaderOverrides: DriverLoaders | undefined;\n\n/** Test-only. @internal */\nexport function _setDriverLoadersForTests(overrides: DriverLoaders | undefined): void {\n driverLoaderOverrides = overrides;\n}\n\n/**\n * Adapt `node:sqlite`'s `DatabaseSync` to the better-sqlite3 surface this module's callers use\n * (`prepare/get/all/run`, `exec`, `close`, `pragma`, `loadExtension`). The error message below has\n * ALWAYS promised this fallback (\"or run on Node 22.5+ for built-in node:sqlite\") — before the\n * flicker-bug fix the promise was fabricated: only better-sqlite3 was ever tried, so every consumer\n * without the optional native dep lost memory tools AND got a per-turn stderr WARN.\n */\nfunction adaptNodeSqlite(db: {\n prepare(sql: string): unknown;\n exec(sql: string): void;\n close(): void;\n loadExtension?: (path: string) => void;\n}): ResilientSqliteDb {\n const pragma = (statement: string, options?: { simple?: boolean }): unknown => {\n const stmt = db.prepare(`PRAGMA ${statement}`) as {\n get(): Record<string, unknown> | undefined;\n };\n const row = stmt.get();\n if (options?.simple === true) {\n return row === undefined ? undefined : Object.values(row)[0];\n }\n return row === undefined ? [] : [row];\n };\n return new Proxy(db as unknown as ResilientSqliteDb, {\n get(target, prop, receiver) {\n if (prop === \"pragma\") return pragma;\n if (prop === \"loadExtension\" && typeof db.loadExtension !== \"function\") {\n return () => {\n throw new Error(\n \"SQLite extension loading is unavailable on the node:sqlite fallback — install better-sqlite3 for sqlite-vec\",\n );\n };\n }\n const value = Reflect.get(target, prop, receiver) as unknown;\n return typeof value === \"function\"\n ? (value as (...a: unknown[]) => unknown).bind(target)\n : value;\n },\n });\n}\n\n// PRE-EXISTING debt, exposed when M75 fixed the Biome config that used to abort before\n// sweeping these files (a nested root under refactor/). It is not new code and was not touched\n// by M75; refactoring SDK internals without review would trade a visible problem for a diff\n// arriscado. Rastreado em usetheodev/theokit-sdk#151.\n// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: see the reason just above\nasync function loadDriver<T extends ResilientSqliteDb>(filePath: string): Promise<T> {\n let betterSqliteCause: unknown;\n try {\n const mod = (await (driverLoaderOverrides?.betterSqlite3?.() ?? import(\"better-sqlite3\"))) as {\n default?: unknown;\n };\n const Ctor = mod.default ?? mod;\n if (typeof Ctor !== \"function\") {\n throw new Error(`better-sqlite3 export is not a constructor (got ${typeof Ctor})`);\n }\n return new (Ctor as new (path: string) => unknown)(filePath) as T;\n } catch (cause) {\n betterSqliteCause = cause;\n }\n // Fallback: the Node 22.5+ built-in driver (the path the error message documents).\n // `process.getBuiltinModule` (Node 22.3+) instead of `import(\"node:sqlite\")` — bundlers that\n // predate the sqlite builtin rewrite the import specifier to a bare \"sqlite\" package (proven in\n // the published dist: \"Cannot find package 'sqlite'\"), while getBuiltinModule is opaque to them.\n try {\n const mod = (await (driverLoaderOverrides?.nodeSqlite?.() ??\n Promise.resolve(\n (process as { getBuiltinModule?: (id: string) => unknown }).getBuiltinModule?.(\n \"node:sqlite\",\n ) ??\n (() => {\n throw new Error(\"node:sqlite built-in unavailable (Node < 22.3)\");\n })(),\n ))) as {\n DatabaseSync: new (\n path: string,\n ) => {\n prepare(sql: string): unknown;\n exec(sql: string): void;\n close(): void;\n };\n };\n return adaptNodeSqlite(new mod.DatabaseSync(filePath)) as T;\n } catch (nodeSqliteCause) {\n const b =\n betterSqliteCause instanceof Error ? betterSqliteCause.message : String(betterSqliteCause);\n const n = nodeSqliteCause instanceof Error ? nodeSqliteCause.message : String(nodeSqliteCause);\n throw new ConfigurationError(\n `Failed to load SQLite driver. Install \\`better-sqlite3\\` or run on Node 22.5+ for built-in \\`node:sqlite\\`. better-sqlite3: ${b}; node:sqlite: ${n}`,\n { code: \"sqlite_driver_unavailable\", cause: nodeSqliteCause },\n );\n }\n}\n\n/** True when an open error indicates an unreadable / corrupt database file. */\nexport function isCorruptionError(cause: unknown): boolean {\n if (!(cause instanceof Error)) return false;\n const msg = cause.message.toLowerCase();\n return (\n msg.includes(\"malformed\") ||\n msg.includes(\"not a database\") ||\n msg.includes(\"encrypted\") ||\n msg.includes(\"disk image is malformed\")\n );\n}\n\nasync function renameAside(filePath: string, label: string): Promise<void> {\n const asidePath = `${filePath}.corrupt-${Date.now()}`;\n await rename(filePath, asidePath).catch(() => undefined);\n await rename(`${filePath}-wal`, `${asidePath}-wal`).catch(() => undefined);\n await rename(`${filePath}-shm`, `${asidePath}-shm`).catch(() => undefined);\n diag(\n `[theokit-sdk] ${label} database corrupt; renamed aside to ${asidePath} and rebuilt schema\\n`,\n );\n}\n"]}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkTIMPJL5V_cjs = require('./chunk-TIMPJL5V.cjs');
|
|
4
4
|
|
|
5
5
|
// src/internal/runtime/concurrency/map-with-concurrency.ts
|
|
6
6
|
var NEVER_ABORT = new AbortController().signal;
|
|
7
7
|
async function mapWithConcurrency(items, concurrency, fn, options) {
|
|
8
|
-
const semaphore =
|
|
8
|
+
const semaphore = chunkTIMPJL5V_cjs.createSemaphore(concurrency);
|
|
9
9
|
const signal = options?.signal ?? NEVER_ABORT;
|
|
10
10
|
return Promise.all(
|
|
11
11
|
items.map(async (item, index) => {
|
|
@@ -23,5 +23,5 @@ async function mapWithConcurrency(items, concurrency, fn, options) {
|
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
exports.mapWithConcurrency = mapWithConcurrency;
|
|
26
|
-
//# sourceMappingURL=chunk-
|
|
27
|
-
//# sourceMappingURL=chunk-
|
|
26
|
+
//# sourceMappingURL=chunk-7OLG7VI4.cjs.map
|
|
27
|
+
//# sourceMappingURL=chunk-7OLG7VI4.cjs.map
|