@theokit/sdk 5.11.1 → 5.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (408) hide show
  1. package/CHANGELOG.md +87 -0
  2. package/dist/a2a/index.cjs +8 -8
  3. package/dist/a2a/index.js +3 -3
  4. package/dist/agent-BVKIUP7F.cjs +71 -0
  5. package/dist/{agent-OKP4LHG2.cjs.map → agent-BVKIUP7F.cjs.map} +1 -1
  6. package/dist/{agent-CmKwSyyD.d.ts → agent-CVzDy_Oj.d.ts} +17 -8
  7. package/dist/{agent-XMkGzff_.d.cts → agent-Cn0sphpA.d.cts} +17 -8
  8. package/dist/agent-IG7BP6GN.js +62 -0
  9. package/dist/{agent-DFV52V6E.js.map → agent-IG7BP6GN.js.map} +1 -1
  10. package/dist/agent-prims-CZyxfCmS.d.cts +206 -0
  11. package/dist/agent-prims-CZyxfCmS.d.ts +206 -0
  12. package/dist/agent-session-store-22GKA7O4.js +6 -0
  13. package/dist/{agent-session-store-ODD3IZCW.js.map → agent-session-store-22GKA7O4.js.map} +1 -1
  14. package/dist/agent-session-store-WP6NGDVX.cjs +23 -0
  15. package/dist/{agent-session-store-SVEJHSUA.cjs.map → agent-session-store-WP6NGDVX.cjs.map} +1 -1
  16. package/dist/auth/index.cjs +33 -33
  17. package/dist/auth/index.js +6 -6
  18. package/dist/{batch-427O54FQ.js → batch-EP3FCL6D.js} +9 -9
  19. package/dist/{batch-427O54FQ.js.map → batch-EP3FCL6D.js.map} +1 -1
  20. package/dist/{batch-U4SO4RLX.cjs → batch-IZ5EDKJ5.cjs} +29 -29
  21. package/dist/{batch-U4SO4RLX.cjs.map → batch-IZ5EDKJ5.cjs.map} +1 -1
  22. package/dist/{chunk-IIYJMXYW.cjs → chunk-27V5I2WW.cjs} +4 -4
  23. package/dist/{chunk-IIYJMXYW.cjs.map → chunk-27V5I2WW.cjs.map} +1 -1
  24. package/dist/{chunk-DPY2M74T.js → chunk-2C24NSNV.js} +5 -5
  25. package/dist/{chunk-DPY2M74T.js.map → chunk-2C24NSNV.js.map} +1 -1
  26. package/dist/{chunk-7F7XE6CM.js → chunk-2S4HQCDF.js} +3 -3
  27. package/dist/{chunk-7F7XE6CM.js.map → chunk-2S4HQCDF.js.map} +1 -1
  28. package/dist/{chunk-LZJXEPEQ.js → chunk-2SFLLOMN.js} +3 -3
  29. package/dist/{chunk-LZJXEPEQ.js.map → chunk-2SFLLOMN.js.map} +1 -1
  30. package/dist/{chunk-RGQICWFU.js → chunk-354F3OF5.js} +3 -3
  31. package/dist/{chunk-RGQICWFU.js.map → chunk-354F3OF5.js.map} +1 -1
  32. package/dist/{chunk-TX56N7FR.js → chunk-3FSBE4PS.js} +4 -4
  33. package/dist/{chunk-TX56N7FR.js.map → chunk-3FSBE4PS.js.map} +1 -1
  34. package/dist/{chunk-RQMCOFAI.cjs → chunk-3HA7N2BB.cjs} +8 -8
  35. package/dist/{chunk-RQMCOFAI.cjs.map → chunk-3HA7N2BB.cjs.map} +1 -1
  36. package/dist/{chunk-GM54F4FE.cjs → chunk-3KIUY67P.cjs} +9 -9
  37. package/dist/{chunk-GM54F4FE.cjs.map → chunk-3KIUY67P.cjs.map} +1 -1
  38. package/dist/{chunk-CZJ6Q7CW.js → chunk-3OY6H3I7.js} +66 -7
  39. package/dist/chunk-3OY6H3I7.js.map +1 -0
  40. package/dist/{chunk-ZWACQM5U.cjs → chunk-3WKWBYPO.cjs} +9 -9
  41. package/dist/{chunk-ZWACQM5U.cjs.map → chunk-3WKWBYPO.cjs.map} +1 -1
  42. package/dist/{chunk-Q34EBNYG.js → chunk-4GUFNDZR.js} +5 -5
  43. package/dist/{chunk-Q34EBNYG.js.map → chunk-4GUFNDZR.js.map} +1 -1
  44. package/dist/{chunk-XDUGSTYJ.cjs → chunk-4YD2WI57.cjs} +15 -15
  45. package/dist/{chunk-XDUGSTYJ.cjs.map → chunk-4YD2WI57.cjs.map} +1 -1
  46. package/dist/{chunk-SKDNCTXG.cjs → chunk-5A4UFBHW.cjs} +15 -15
  47. package/dist/{chunk-SKDNCTXG.cjs.map → chunk-5A4UFBHW.cjs.map} +1 -1
  48. package/dist/{chunk-SUVCHX4L.js → chunk-5AR6O7GW.js} +3 -3
  49. package/dist/{chunk-SUVCHX4L.js.map → chunk-5AR6O7GW.js.map} +1 -1
  50. package/dist/{chunk-SVCPJRUB.js → chunk-5HSMH2ZZ.js} +6 -6
  51. package/dist/{chunk-SVCPJRUB.js.map → chunk-5HSMH2ZZ.js.map} +1 -1
  52. package/dist/{chunk-GTX6FEDP.js → chunk-5IRDK5BC.js} +3 -3
  53. package/dist/{chunk-GTX6FEDP.js.map → chunk-5IRDK5BC.js.map} +1 -1
  54. package/dist/{chunk-H3CVJSFC.js → chunk-5IUDICRK.js} +3 -3
  55. package/dist/{chunk-H3CVJSFC.js.map → chunk-5IUDICRK.js.map} +1 -1
  56. package/dist/{chunk-FYEHYQ7T.cjs → chunk-6CXRYPG7.cjs} +15 -15
  57. package/dist/{chunk-FYEHYQ7T.cjs.map → chunk-6CXRYPG7.cjs.map} +1 -1
  58. package/dist/{chunk-NQVWSSX2.cjs → chunk-6OCJWGVD.cjs} +12 -12
  59. package/dist/{chunk-NQVWSSX2.cjs.map → chunk-6OCJWGVD.cjs.map} +1 -1
  60. package/dist/{chunk-MPR2ISL2.cjs → chunk-6XQLTQB6.cjs} +4 -4
  61. package/dist/{chunk-MPR2ISL2.cjs.map → chunk-6XQLTQB6.cjs.map} +1 -1
  62. package/dist/{chunk-72CPLZPC.cjs → chunk-7INPXUJI.cjs} +5 -5
  63. package/dist/{chunk-72CPLZPC.cjs.map → chunk-7INPXUJI.cjs.map} +1 -1
  64. package/dist/{chunk-HG5LKFG7.cjs → chunk-7WARNHWW.cjs} +16 -16
  65. package/dist/{chunk-HG5LKFG7.cjs.map → chunk-7WARNHWW.cjs.map} +1 -1
  66. package/dist/{chunk-KIKKTW5O.cjs → chunk-7YUPSBDV.cjs} +4 -4
  67. package/dist/{chunk-KIKKTW5O.cjs.map → chunk-7YUPSBDV.cjs.map} +1 -1
  68. package/dist/{chunk-IZDDSLL2.js → chunk-AB4OPJLD.js} +6 -6
  69. package/dist/{chunk-IZDDSLL2.js.map → chunk-AB4OPJLD.js.map} +1 -1
  70. package/dist/{chunk-XERM7PDQ.js → chunk-AGO5S5WD.js} +3 -3
  71. package/dist/{chunk-XERM7PDQ.js.map → chunk-AGO5S5WD.js.map} +1 -1
  72. package/dist/{chunk-ZWFTECOE.js → chunk-AHKS3DKI.js} +3 -3
  73. package/dist/{chunk-ZWFTECOE.js.map → chunk-AHKS3DKI.js.map} +1 -1
  74. package/dist/{chunk-ECD6ER3E.cjs → chunk-AIZ6WXSL.cjs} +4 -4
  75. package/dist/{chunk-ECD6ER3E.cjs.map → chunk-AIZ6WXSL.cjs.map} +1 -1
  76. package/dist/{chunk-KO6SHCEH.js → chunk-AQW54OWQ.js} +3 -3
  77. package/dist/{chunk-KO6SHCEH.js.map → chunk-AQW54OWQ.js.map} +1 -1
  78. package/dist/{chunk-P22BZE7G.cjs → chunk-AT2PESXB.cjs} +7 -7
  79. package/dist/{chunk-P22BZE7G.cjs.map → chunk-AT2PESXB.cjs.map} +1 -1
  80. package/dist/{chunk-MHIBYKWA.js → chunk-BJ7BPLQK.js} +131 -72
  81. package/dist/chunk-BJ7BPLQK.js.map +1 -0
  82. package/dist/{chunk-HV4V63CO.js → chunk-BO3PV3OP.js} +4 -4
  83. package/dist/{chunk-HV4V63CO.js.map → chunk-BO3PV3OP.js.map} +1 -1
  84. package/dist/{chunk-7NQ7HJ3E.cjs → chunk-BRWI4HLK.cjs} +6 -6
  85. package/dist/{chunk-7NQ7HJ3E.cjs.map → chunk-BRWI4HLK.cjs.map} +1 -1
  86. package/dist/{chunk-GHHIJEFX.cjs → chunk-BWYC7RZG.cjs} +9 -9
  87. package/dist/{chunk-GHHIJEFX.cjs.map → chunk-BWYC7RZG.cjs.map} +1 -1
  88. package/dist/{chunk-UNFBHV46.cjs → chunk-CEGU5AVD.cjs} +9 -9
  89. package/dist/chunk-CEGU5AVD.cjs.map +1 -0
  90. package/dist/{chunk-JV7JA7BM.cjs → chunk-CGH4BCIY.cjs} +11 -11
  91. package/dist/{chunk-JV7JA7BM.cjs.map → chunk-CGH4BCIY.cjs.map} +1 -1
  92. package/dist/{chunk-L3C6CCBG.cjs → chunk-CWQPQTUZ.cjs} +21 -21
  93. package/dist/{chunk-L3C6CCBG.cjs.map → chunk-CWQPQTUZ.cjs.map} +1 -1
  94. package/dist/{chunk-X3LOJJMO.js → chunk-DF77RBF4.js} +9 -9
  95. package/dist/{chunk-X3LOJJMO.js.map → chunk-DF77RBF4.js.map} +1 -1
  96. package/dist/{chunk-GMSRRJ53.js → chunk-EEK7S77K.js} +3 -3
  97. package/dist/{chunk-GMSRRJ53.js.map → chunk-EEK7S77K.js.map} +1 -1
  98. package/dist/{chunk-NKIQTLFA.cjs → chunk-EQ5IDL6W.cjs} +4 -4
  99. package/dist/{chunk-NKIQTLFA.cjs.map → chunk-EQ5IDL6W.cjs.map} +1 -1
  100. package/dist/{chunk-D5KXKBEN.cjs → chunk-FEAWEBWN.cjs} +5 -5
  101. package/dist/{chunk-D5KXKBEN.cjs.map → chunk-FEAWEBWN.cjs.map} +1 -1
  102. package/dist/{chunk-NJSIAJEK.cjs → chunk-FLDMPVUC.cjs} +4 -4
  103. package/dist/{chunk-NJSIAJEK.cjs.map → chunk-FLDMPVUC.cjs.map} +1 -1
  104. package/dist/{chunk-ASK2OQM5.cjs → chunk-G7XBVM3T.cjs} +5 -5
  105. package/dist/{chunk-ASK2OQM5.cjs.map → chunk-G7XBVM3T.cjs.map} +1 -1
  106. package/dist/{chunk-U27XHOEF.js → chunk-H7G65PNI.js} +5 -5
  107. package/dist/{chunk-U27XHOEF.js.map → chunk-H7G65PNI.js.map} +1 -1
  108. package/dist/{chunk-JW3GVLM6.cjs → chunk-H7HD6RXO.cjs} +4 -4
  109. package/dist/{chunk-JW3GVLM6.cjs.map → chunk-H7HD6RXO.cjs.map} +1 -1
  110. package/dist/{chunk-ZHWKT2NI.js → chunk-HJ2LV464.js} +3 -3
  111. package/dist/{chunk-ZHWKT2NI.js.map → chunk-HJ2LV464.js.map} +1 -1
  112. package/dist/{chunk-KGZ66JVZ.cjs → chunk-HN4IKB6X.cjs} +14 -14
  113. package/dist/{chunk-KGZ66JVZ.cjs.map → chunk-HN4IKB6X.cjs.map} +1 -1
  114. package/dist/{chunk-XKMVJ443.js → chunk-HWMGR3HA.js} +6 -6
  115. package/dist/{chunk-XKMVJ443.js.map → chunk-HWMGR3HA.js.map} +1 -1
  116. package/dist/{chunk-EQ5NCH2Y.cjs → chunk-IO4RI5ZJ.cjs} +24 -24
  117. package/dist/{chunk-EQ5NCH2Y.cjs.map → chunk-IO4RI5ZJ.cjs.map} +1 -1
  118. package/dist/{chunk-OLSEWLK5.cjs → chunk-IOFMRS6T.cjs} +6 -6
  119. package/dist/{chunk-OLSEWLK5.cjs.map → chunk-IOFMRS6T.cjs.map} +1 -1
  120. package/dist/{chunk-7QJYKVP6.js → chunk-KCM3RMKR.js} +3 -3
  121. package/dist/{chunk-7QJYKVP6.js.map → chunk-KCM3RMKR.js.map} +1 -1
  122. package/dist/{chunk-7KIN3L2S.js → chunk-KU5O7WPK.js} +3 -3
  123. package/dist/{chunk-7KIN3L2S.js.map → chunk-KU5O7WPK.js.map} +1 -1
  124. package/dist/{chunk-J5623RIV.cjs → chunk-KX5QXLBS.cjs} +10 -10
  125. package/dist/{chunk-J5623RIV.cjs.map → chunk-KX5QXLBS.cjs.map} +1 -1
  126. package/dist/{chunk-J6GXS5A2.cjs → chunk-L7JPXZ2C.cjs} +17 -17
  127. package/dist/{chunk-J6GXS5A2.cjs.map → chunk-L7JPXZ2C.cjs.map} +1 -1
  128. package/dist/{chunk-P7NNKEWO.cjs → chunk-L7V4DDIE.cjs} +4 -4
  129. package/dist/{chunk-P7NNKEWO.cjs.map → chunk-L7V4DDIE.cjs.map} +1 -1
  130. package/dist/chunk-LO6LIUZ6.cjs +18 -0
  131. package/dist/{chunk-SGC7LSHF.cjs.map → chunk-LO6LIUZ6.cjs.map} +1 -1
  132. package/dist/{chunk-P5N3Q2NH.cjs → chunk-LSWHDOCL.cjs} +192 -148
  133. package/dist/chunk-LSWHDOCL.cjs.map +1 -0
  134. package/dist/{chunk-3JHIFQ4I.js → chunk-M4U24U6G.js} +3 -3
  135. package/dist/{chunk-3JHIFQ4I.js.map → chunk-M4U24U6G.js.map} +1 -1
  136. package/dist/{chunk-GGRPAQ3B.js → chunk-MLGETTYX.js} +5 -5
  137. package/dist/{chunk-GGRPAQ3B.js.map → chunk-MLGETTYX.js.map} +1 -1
  138. package/dist/{chunk-XZHJYSPB.js → chunk-MLJDW2YK.js} +4 -4
  139. package/dist/{chunk-XZHJYSPB.js.map → chunk-MLJDW2YK.js.map} +1 -1
  140. package/dist/{chunk-5Q4RTLMP.js → chunk-MS3TQSXU.js} +3 -3
  141. package/dist/{chunk-5Q4RTLMP.js.map → chunk-MS3TQSXU.js.map} +1 -1
  142. package/dist/{chunk-W2ZVTEOD.js → chunk-MSEL5E5P.js} +6 -6
  143. package/dist/{chunk-W2ZVTEOD.js.map → chunk-MSEL5E5P.js.map} +1 -1
  144. package/dist/{chunk-ZAM7BJXJ.cjs → chunk-MSW7LB2V.cjs} +5 -5
  145. package/dist/{chunk-ZAM7BJXJ.cjs.map → chunk-MSW7LB2V.cjs.map} +1 -1
  146. package/dist/{chunk-7HUCU3KK.js → chunk-NHOEXFZT.js} +5 -5
  147. package/dist/{chunk-7HUCU3KK.js.map → chunk-NHOEXFZT.js.map} +1 -1
  148. package/dist/{chunk-6G4IRQUD.js → chunk-NJBJ3CUG.js} +6 -6
  149. package/dist/{chunk-6G4IRQUD.js.map → chunk-NJBJ3CUG.js.map} +1 -1
  150. package/dist/{chunk-I2ORT6QD.js → chunk-NKQVLWDF.js} +3 -3
  151. package/dist/{chunk-I2ORT6QD.js.map → chunk-NKQVLWDF.js.map} +1 -1
  152. package/dist/{chunk-N7KS3TIR.cjs → chunk-NP362THY.cjs} +28 -15
  153. package/dist/chunk-NP362THY.cjs.map +1 -0
  154. package/dist/{chunk-NWS2CS3Y.cjs → chunk-NWWTYBD3.cjs} +5 -5
  155. package/dist/{chunk-NWS2CS3Y.cjs.map → chunk-NWWTYBD3.cjs.map} +1 -1
  156. package/dist/{chunk-SVQIW5RJ.js → chunk-OLJOI4LK.js} +4 -4
  157. package/dist/{chunk-SVQIW5RJ.js.map → chunk-OLJOI4LK.js.map} +1 -1
  158. package/dist/{chunk-7JAKO3NM.js → chunk-ORLTGPOS.js} +3 -3
  159. package/dist/{chunk-7JAKO3NM.js.map → chunk-ORLTGPOS.js.map} +1 -1
  160. package/dist/{chunk-5DD4NJN3.js → chunk-PKRPV3R7.js} +3 -3
  161. package/dist/{chunk-5DD4NJN3.js.map → chunk-PKRPV3R7.js.map} +1 -1
  162. package/dist/{chunk-R5YPDAKD.cjs → chunk-POBZXULR.cjs} +4 -4
  163. package/dist/{chunk-R5YPDAKD.cjs.map → chunk-POBZXULR.cjs.map} +1 -1
  164. package/dist/{chunk-35KBC4BX.cjs → chunk-Q6WT5535.cjs} +446 -387
  165. package/dist/chunk-Q6WT5535.cjs.map +1 -0
  166. package/dist/{chunk-MQGSOKR3.js → chunk-Q7UG242V.js} +3 -3
  167. package/dist/{chunk-MQGSOKR3.js.map → chunk-Q7UG242V.js.map} +1 -1
  168. package/dist/{chunk-XKZFIP7Z.cjs → chunk-QG4SXZ2A.cjs} +4 -4
  169. package/dist/{chunk-XKZFIP7Z.cjs.map → chunk-QG4SXZ2A.cjs.map} +1 -1
  170. package/dist/{chunk-NAGPKWOD.cjs → chunk-QISSETTG.cjs} +4 -4
  171. package/dist/{chunk-NAGPKWOD.cjs.map → chunk-QISSETTG.cjs.map} +1 -1
  172. package/dist/{chunk-OR6XIWLB.js → chunk-QK2ERTO3.js} +4 -4
  173. package/dist/{chunk-OR6XIWLB.js.map → chunk-QK2ERTO3.js.map} +1 -1
  174. package/dist/{chunk-ZDYDBXSD.js → chunk-RN3XDZGS.js} +6 -6
  175. package/dist/{chunk-ZDYDBXSD.js.map → chunk-RN3XDZGS.js.map} +1 -1
  176. package/dist/{chunk-6LHQPOMI.cjs → chunk-RNXXYF22.cjs} +66 -7
  177. package/dist/chunk-RNXXYF22.cjs.map +1 -0
  178. package/dist/{chunk-TMKTSYDS.cjs → chunk-RS7YQR4X.cjs} +6 -6
  179. package/dist/{chunk-TMKTSYDS.cjs.map → chunk-RS7YQR4X.cjs.map} +1 -1
  180. package/dist/{chunk-HU666T3Q.cjs → chunk-S46WJTDL.cjs} +14 -14
  181. package/dist/{chunk-HU666T3Q.cjs.map → chunk-S46WJTDL.cjs.map} +1 -1
  182. package/dist/{chunk-ZD66GFH5.cjs → chunk-SDZ4XDWS.cjs} +35 -35
  183. package/dist/{chunk-ZD66GFH5.cjs.map → chunk-SDZ4XDWS.cjs.map} +1 -1
  184. package/dist/{chunk-ZJZ7LV3A.js → chunk-SV63WTA2.js} +3 -3
  185. package/dist/{chunk-ZJZ7LV3A.js.map → chunk-SV63WTA2.js.map} +1 -1
  186. package/dist/{chunk-CQYBJOB2.cjs → chunk-SXH37C7X.cjs} +4 -4
  187. package/dist/{chunk-CQYBJOB2.cjs.map → chunk-SXH37C7X.cjs.map} +1 -1
  188. package/dist/{chunk-GMRFAX4I.js → chunk-SZQFCHU6.js} +4 -4
  189. package/dist/{chunk-GMRFAX4I.js.map → chunk-SZQFCHU6.js.map} +1 -1
  190. package/dist/{chunk-6PB5AQCY.cjs → chunk-TLVI2OQK.cjs} +16 -16
  191. package/dist/{chunk-6PB5AQCY.cjs.map → chunk-TLVI2OQK.cjs.map} +1 -1
  192. package/dist/{chunk-B5MHRQJZ.js → chunk-TNFOU6SB.js} +3 -3
  193. package/dist/chunk-TNFOU6SB.js.map +1 -0
  194. package/dist/{chunk-N6OEX5TN.cjs → chunk-UDAKAE4Z.cjs} +16 -16
  195. package/dist/{chunk-N6OEX5TN.cjs.map → chunk-UDAKAE4Z.cjs.map} +1 -1
  196. package/dist/{chunk-26NEAJ6T.js → chunk-VVGFZQZC.js} +4 -4
  197. package/dist/{chunk-26NEAJ6T.js.map → chunk-VVGFZQZC.js.map} +1 -1
  198. package/dist/{chunk-XCQ432OX.js → chunk-VZGE7NAI.js} +3 -3
  199. package/dist/{chunk-XCQ432OX.js.map → chunk-VZGE7NAI.js.map} +1 -1
  200. package/dist/{chunk-C7GKRGKN.cjs → chunk-WDVG5R2Q.cjs} +19 -19
  201. package/dist/{chunk-C7GKRGKN.cjs.map → chunk-WDVG5R2Q.cjs.map} +1 -1
  202. package/dist/{chunk-FTZTZBCU.js → chunk-XESYJ4JC.js} +4 -4
  203. package/dist/{chunk-FTZTZBCU.js.map → chunk-XESYJ4JC.js.map} +1 -1
  204. package/dist/{chunk-OPAKPEPG.js → chunk-XJ3WU5CZ.js} +5 -5
  205. package/dist/{chunk-OPAKPEPG.js.map → chunk-XJ3WU5CZ.js.map} +1 -1
  206. package/dist/{chunk-BBJ77S62.js → chunk-XJ4C4NFX.js} +64 -20
  207. package/dist/chunk-XJ4C4NFX.js.map +1 -0
  208. package/dist/{chunk-AY43232P.js → chunk-XRPMZ7TO.js} +4 -4
  209. package/dist/{chunk-AY43232P.js.map → chunk-XRPMZ7TO.js.map} +1 -1
  210. package/dist/{chunk-X6DUEDAF.js → chunk-XZKIAENA.js} +3 -3
  211. package/dist/{chunk-X6DUEDAF.js.map → chunk-XZKIAENA.js.map} +1 -1
  212. package/dist/{chunk-X7EUUHXU.js → chunk-YMVTUV5K.js} +3 -3
  213. package/dist/{chunk-X7EUUHXU.js.map → chunk-YMVTUV5K.js.map} +1 -1
  214. package/dist/{chunk-3JANYJYS.cjs → chunk-YOVZMN4P.cjs} +8 -8
  215. package/dist/{chunk-3JANYJYS.cjs.map → chunk-YOVZMN4P.cjs.map} +1 -1
  216. package/dist/{chunk-TY56BKSK.cjs → chunk-YQ3XC6C2.cjs} +4 -4
  217. package/dist/{chunk-TY56BKSK.cjs.map → chunk-YQ3XC6C2.cjs.map} +1 -1
  218. package/dist/{chunk-JLIRFWUG.js → chunk-ZJAYFSVI.js} +22 -9
  219. package/dist/chunk-ZJAYFSVI.js.map +1 -0
  220. package/dist/{chunk-MU7IAA7G.js → chunk-ZLFFDPXC.js} +9 -9
  221. package/dist/{chunk-MU7IAA7G.js.map → chunk-ZLFFDPXC.js.map} +1 -1
  222. package/dist/{chunk-JLRLCBJ4.cjs → chunk-ZOFRNNZD.cjs} +4 -4
  223. package/dist/{chunk-JLRLCBJ4.cjs.map → chunk-ZOFRNNZD.cjs.map} +1 -1
  224. package/dist/{chunk-MPQJE3G4.cjs → chunk-ZWLFHSON.cjs} +15 -15
  225. package/dist/{chunk-MPQJE3G4.cjs.map → chunk-ZWLFHSON.cjs.map} +1 -1
  226. package/dist/compact-session-3U2JYTVG.js +25 -0
  227. package/dist/{compact-session-4HAUP3HK.js.map → compact-session-3U2JYTVG.js.map} +1 -1
  228. package/dist/{compact-session-Y56D3S57.cjs → compact-session-NM56BREJ.cjs} +24 -24
  229. package/dist/{compact-session-Y56D3S57.cjs.map → compact-session-NM56BREJ.cjs.map} +1 -1
  230. package/dist/compaction.cjs +18 -18
  231. package/dist/compaction.js +3 -3
  232. package/dist/concurrency.cjs +6 -6
  233. package/dist/concurrency.js +4 -4
  234. package/dist/context/index.cjs +9 -9
  235. package/dist/context/index.js +6 -6
  236. package/dist/context-4RSI3AXT.cjs +24 -0
  237. package/dist/{context-B5J4GX2F.cjs.map → context-4RSI3AXT.cjs.map} +1 -1
  238. package/dist/context-7EBZST3L.js +7 -0
  239. package/dist/{context-3FZRAO5K.js.map → context-7EBZST3L.js.map} +1 -1
  240. package/dist/{cron-Blj6wMYg.d.cts → cron-BWDYetbq.d.cts} +2 -2
  241. package/dist/{cron-BPccQCO8.d.ts → cron-CHn-F0fC.d.ts} +2 -2
  242. package/dist/cron.cjs +42 -42
  243. package/dist/cron.d.cts +4 -4
  244. package/dist/cron.d.ts +4 -4
  245. package/dist/cron.js +41 -41
  246. package/dist/{errors-BWOJeWTZ.d.cts → errors-BiDQFWTG.d.cts} +10 -7
  247. package/dist/{errors-DDvG18IB.d.ts → errors-Pf22PJJ-.d.ts} +10 -7
  248. package/dist/errors.cjs +23 -23
  249. package/dist/errors.d.cts +2 -3
  250. package/dist/errors.d.ts +2 -3
  251. package/dist/errors.js +2 -2
  252. package/dist/eval.cjs +54 -54
  253. package/dist/eval.js +42 -42
  254. package/dist/{executor-3NI7KNL4.js → executor-3D2UDJHW.js} +8 -8
  255. package/dist/{executor-3NI7KNL4.js.map → executor-3D2UDJHW.js.map} +1 -1
  256. package/dist/{executor-2SUGI3ZT.cjs → executor-HKHT4CWS.cjs} +26 -26
  257. package/dist/{executor-2SUGI3ZT.cjs.map → executor-HKHT4CWS.cjs.map} +1 -1
  258. package/dist/filesystem/index.cjs +12 -12
  259. package/dist/filesystem/index.js +3 -3
  260. package/dist/fs-session-store-6ZCCJX3K.js +11 -0
  261. package/dist/{fs-session-store-3VI4CPTX.js.map → fs-session-store-6ZCCJX3K.js.map} +1 -1
  262. package/dist/fs-session-store-S2AXVJIX.cjs +20 -0
  263. package/dist/{fs-session-store-IQ6PEHYF.cjs.map → fs-session-store-S2AXVJIX.cjs.map} +1 -1
  264. package/dist/generate-object-S7MNVF2V.js +7 -0
  265. package/dist/{generate-object-NTKAWE7D.js.map → generate-object-S7MNVF2V.js.map} +1 -1
  266. package/dist/generate-object-XBWD2PU7.cjs +20 -0
  267. package/dist/{generate-object-YHTWG5DB.cjs.map → generate-object-XBWD2PU7.cjs.map} +1 -1
  268. package/dist/index-manager-HO456AVW.cjs +27 -0
  269. package/dist/{index-manager-YGXRFJMZ.cjs.map → index-manager-HO456AVW.cjs.map} +1 -1
  270. package/dist/index-manager-QDH56FER.js +18 -0
  271. package/dist/{index-manager-JVYIVTZG.js.map → index-manager-QDH56FER.js.map} +1 -1
  272. package/dist/index.cjs +172 -172
  273. package/dist/index.d.cts +9 -9
  274. package/dist/index.d.ts +9 -9
  275. package/dist/index.js +59 -59
  276. package/dist/{inject-session-R73PRM7B.cjs → inject-session-JVTZNQF6.cjs} +9 -9
  277. package/dist/{inject-session-R73PRM7B.cjs.map → inject-session-JVTZNQF6.cjs.map} +1 -1
  278. package/dist/{inject-session-LJX5JGV5.js → inject-session-THABTKJY.js} +7 -7
  279. package/dist/{inject-session-LJX5JGV5.js.map → inject-session-THABTKJY.js.map} +1 -1
  280. package/dist/interactive/index.cjs +4 -4
  281. package/dist/interactive/index.js +2 -2
  282. package/dist/internal/budget/normalize-usage.d.ts +5 -1
  283. package/dist/internal/error-mappers/openai-compatible.d.ts +3 -1
  284. package/dist/internal/memory/adapters/index.cjs +8 -8
  285. package/dist/internal/memory/adapters/index.js +7 -7
  286. package/dist/internal/memory/storage/index.cjs +42 -42
  287. package/dist/internal/memory/storage/index.js +10 -10
  288. package/dist/internal/persistence/index.cjs +25 -25
  289. package/dist/internal/persistence/index.js +8 -8
  290. package/dist/internal/providers/catalog-schema.d.ts +1 -1
  291. package/dist/internal/runtime/lifecycle/throw-on-error-run.d.ts +18 -0
  292. package/dist/internal/runtime/model-selection.d.ts +1 -1
  293. package/dist/internal/runtime/system-prompt/native-reasoning.d.ts +2 -2
  294. package/dist/internal/runtime/typed-run-error.d.ts +16 -0
  295. package/dist/internal/security/index.cjs +13 -13
  296. package/dist/internal/security/index.js +3 -3
  297. package/dist/judge-call-4LR4IFVT.js +5 -0
  298. package/dist/{judge-call-LOL5FQEX.js.map → judge-call-4LR4IFVT.js.map} +1 -1
  299. package/dist/judge-call-ZTUQMQRL.cjs +22 -0
  300. package/dist/{judge-call-AQQYK6VT.cjs.map → judge-call-ZTUQMQRL.cjs.map} +1 -1
  301. package/dist/mcp-auth.cjs +14 -14
  302. package/dist/mcp-auth.js +4 -4
  303. package/dist/models.cjs +22 -22
  304. package/dist/models.js +8 -8
  305. package/dist/oauth-transaction-store-OMX436YB.cjs +38 -0
  306. package/dist/{oauth-transaction-store-ZINDV7AF.cjs.map → oauth-transaction-store-OMX436YB.cjs.map} +1 -1
  307. package/dist/oauth-transaction-store-U34YLEGP.js +5 -0
  308. package/dist/{oauth-transaction-store-NP2YHZ6D.js.map → oauth-transaction-store-U34YLEGP.js.map} +1 -1
  309. package/dist/path-safety.cjs +10 -10
  310. package/dist/path-safety.js +3 -3
  311. package/dist/persistence.cjs +31 -31
  312. package/dist/persistence.js +10 -10
  313. package/dist/project.cjs +5 -5
  314. package/dist/project.js +3 -3
  315. package/dist/providers.cjs +9 -9
  316. package/dist/providers.js +7 -7
  317. package/dist/registry-5TDAF7RK.js +9 -0
  318. package/dist/{registry-5FK42CRV.js.map → registry-5TDAF7RK.js.map} +1 -1
  319. package/dist/registry-W7TSCLQO.cjs +46 -0
  320. package/dist/{registry-BVTNO73E.cjs.map → registry-W7TSCLQO.cjs.map} +1 -1
  321. package/dist/retry.cjs +4 -4
  322. package/dist/retry.js +3 -3
  323. package/dist/{run-until-DG2KXWB2.cjs → run-until-4KHVF7YC.cjs} +8 -4
  324. package/dist/run-until-4KHVF7YC.cjs.map +1 -0
  325. package/dist/{run-until-6D6TQ4JN.js → run-until-G6BW2DWM.js} +8 -4
  326. package/dist/run-until-G6BW2DWM.js.map +1 -0
  327. package/dist/sandbox/index.cjs +22 -22
  328. package/dist/sandbox/index.js +4 -4
  329. package/dist/{run-DsA5Ip2i.d.cts → sdk-agent-4-dXI2GS.d.cts} +1500 -753
  330. package/dist/{run-DsA5Ip2i.d.ts → sdk-agent-CTOJlWA_.d.ts} +1500 -753
  331. package/dist/server/auth/index.cjs +22 -22
  332. package/dist/server/auth/index.js +7 -7
  333. package/dist/server/errors-envelope.cjs +14 -14
  334. package/dist/server/errors-envelope.d.cts +2 -3
  335. package/dist/server/errors-envelope.d.ts +2 -3
  336. package/dist/server/errors-envelope.js +3 -3
  337. package/dist/session-transcript-7TZ6HXSX.cjs +62 -0
  338. package/dist/{session-transcript-RACG7BK2.cjs.map → session-transcript-7TZ6HXSX.cjs.map} +1 -1
  339. package/dist/session-transcript-BSHZYYY6.js +5 -0
  340. package/dist/{session-transcript-AR7IBICT.js.map → session-transcript-BSHZYYY6.js.map} +1 -1
  341. package/dist/skills.cjs +8 -8
  342. package/dist/skills.js +5 -5
  343. package/dist/stream-object-R6SMYV4R.js +7 -0
  344. package/dist/{stream-object-QAEHG4YO.js.map → stream-object-R6SMYV4R.js.map} +1 -1
  345. package/dist/stream-object-TEEK3CAX.cjs +20 -0
  346. package/dist/{stream-object-TKVGGA54.cjs.map → stream-object-TEEK3CAX.cjs.map} +1 -1
  347. package/dist/subagents-loader-TXOA5EJJ.cjs +16 -0
  348. package/dist/{subagents-loader-5TZCAIYQ.cjs.map → subagents-loader-TXOA5EJJ.cjs.map} +1 -1
  349. package/dist/subagents-loader-Z744TAKD.js +7 -0
  350. package/dist/{subagents-loader-PEV3PD4Q.js.map → subagents-loader-Z744TAKD.js.map} +1 -1
  351. package/dist/subagents-loader.cjs +7 -7
  352. package/dist/subagents-loader.d.cts +4 -3
  353. package/dist/subagents-loader.d.ts +4 -3
  354. package/dist/subagents-loader.js +5 -5
  355. package/dist/subscription/index.cjs +3 -3
  356. package/dist/subscription/index.js +2 -2
  357. package/dist/task-store.cjs +7 -7
  358. package/dist/task-store.js +4 -4
  359. package/dist/types/agent-prims.d.ts +16 -0
  360. package/dist/types/agent.d.ts +15 -6
  361. package/dist/types/run.d.ts +14 -14
  362. package/dist/workflow.cjs +27 -27
  363. package/dist/workflow.d.cts +2 -2
  364. package/dist/workflow.d.ts +2 -2
  365. package/dist/workflow.js +6 -6
  366. package/docs/error-codes.md +24 -23
  367. package/docs/harness-capability-map.md +4 -4
  368. package/package.json +1 -1
  369. package/dist/agent-DFV52V6E.js +0 -62
  370. package/dist/agent-OKP4LHG2.cjs +0 -71
  371. package/dist/agent-session-store-ODD3IZCW.js +0 -6
  372. package/dist/agent-session-store-SVEJHSUA.cjs +0 -23
  373. package/dist/chunk-35KBC4BX.cjs.map +0 -1
  374. package/dist/chunk-6LHQPOMI.cjs.map +0 -1
  375. package/dist/chunk-B5MHRQJZ.js.map +0 -1
  376. package/dist/chunk-BBJ77S62.js.map +0 -1
  377. package/dist/chunk-CZJ6Q7CW.js.map +0 -1
  378. package/dist/chunk-JLIRFWUG.js.map +0 -1
  379. package/dist/chunk-MHIBYKWA.js.map +0 -1
  380. package/dist/chunk-N7KS3TIR.cjs.map +0 -1
  381. package/dist/chunk-P5N3Q2NH.cjs.map +0 -1
  382. package/dist/chunk-SGC7LSHF.cjs +0 -18
  383. package/dist/chunk-UNFBHV46.cjs.map +0 -1
  384. package/dist/compact-session-4HAUP3HK.js +0 -25
  385. package/dist/context-3FZRAO5K.js +0 -7
  386. package/dist/context-B5J4GX2F.cjs +0 -24
  387. package/dist/fs-session-store-3VI4CPTX.js +0 -11
  388. package/dist/fs-session-store-IQ6PEHYF.cjs +0 -20
  389. package/dist/generate-object-NTKAWE7D.js +0 -7
  390. package/dist/generate-object-YHTWG5DB.cjs +0 -20
  391. package/dist/index-manager-JVYIVTZG.js +0 -18
  392. package/dist/index-manager-YGXRFJMZ.cjs +0 -27
  393. package/dist/judge-call-AQQYK6VT.cjs +0 -22
  394. package/dist/judge-call-LOL5FQEX.js +0 -5
  395. package/dist/oauth-transaction-store-NP2YHZ6D.js +0 -5
  396. package/dist/oauth-transaction-store-ZINDV7AF.cjs +0 -38
  397. package/dist/registry-5FK42CRV.js +0 -9
  398. package/dist/registry-BVTNO73E.cjs +0 -46
  399. package/dist/run-until-6D6TQ4JN.js.map +0 -1
  400. package/dist/run-until-DG2KXWB2.cjs.map +0 -1
  401. package/dist/sdk-agent-dNwjwCt5.d.cts +0 -940
  402. package/dist/sdk-agent-wEOLXD3F.d.ts +0 -940
  403. package/dist/session-transcript-AR7IBICT.js +0 -5
  404. package/dist/session-transcript-RACG7BK2.cjs +0 -62
  405. package/dist/stream-object-QAEHG4YO.js +0 -7
  406. package/dist/stream-object-TKVGGA54.cjs +0 -20
  407. package/dist/subagents-loader-5TZCAIYQ.cjs +0 -16
  408. package/dist/subagents-loader-PEV3PD4Q.js +0 -7
@@ -1,1088 +1,1503 @@
1
+ import { M as ModelSelection, b as TextBlock, C as CustomTool, P as PermissionMode, R as RunOperation } from './agent-prims-CZyxfCmS.js';
1
2
  import * as zod from 'zod';
3
+ import { T as TheokitAgentError } from './errors-base-B5g01neU.js';
2
4
 
3
5
  /**
4
- * Owner: `types/` (2 of 2 importers: conversation.ts, updates.ts). The only module in this folder
5
- * whose owner IS the layer — it exists to break a type-only cycle BETWEEN two of its siblings, so
6
- * pointing it at a subsystem would name something that does not use it.
6
+ * Owner: `internal/local-agent/` (2 of 4 importers). Derived from the import graph, not declared —
7
+ * `tests/lint/types-name-their-owner.test.ts` re-derives it.
7
8
  *
8
- * Type-leaf — base message types shared between `conversation.ts` and
9
- * `updates.ts`. Extracted to break LOW type-only cycle #6 (audit
10
- * `architecture-output/final_report.md`) per plan arch-review-fixes-2026-06-06
11
- * § Phase 4 / T4.1 (D438).
9
+ * Public `MemoryAdapter` contract (T1.1, ADRs D141 / D147).
12
10
  *
13
- * Public surface unchanged — `types/conversation.ts` re-exports `UserMessage`
14
- * from this leaf so `import type { UserMessage } from "@theokit/sdk"` keeps
15
- * resolving.
11
+ * The plugin extension point `{ kind: "memory" }` (ADR D98) declares a
12
+ * `createProvider` factory; this file types its return value formally.
13
+ * Adapters implement `write` / `recall` / `delete` plus optional methods
14
+ * gated by `capabilities`. `MemoryId` is a branded string prefixed with
15
+ * the adapter id so cross-adapter use throws on `extractRawId` (EC-B).
16
+ *
17
+ * Each provider-specific package (`@theokit-memory-supermemory`, etc)
18
+ * exports a factory returning a `Plugin { kind: "memory" }` whose
19
+ * `createProvider` resolves to a `MemoryAdapter` instance.
16
20
  *
17
21
  * @public
18
22
  */
19
23
  /**
20
- * User-authored message in a conversation history.
24
+ * Branded provider memory ID. Format: `${adapterId}:${rawProviderId}`.
25
+ * Use `mkMemoryId` / `extractRawId` from `../memory-adapter-helpers.js`
26
+ * to construct and unwrap with cross-adapter safety (EC-B).
21
27
  *
22
28
  * @public
23
29
  */
24
- interface UserMessage {
25
- text: string;
26
- }
27
-
30
+ type MemoryId = string & {
31
+ readonly __brand: "MemoryId";
32
+ };
28
33
  /**
29
- * Owner: `internal/agent-loop/` (1 of 1 importers). Derived from the import graph, not declared —
30
- * `tests/lint/types-name-their-owner.test.ts` re-derives it.
34
+ * Portable identity context. `userId` is the only required field —
35
+ * the lowest common denominator across Supermemory / Honcho / Mem0.
36
+ * Adapter implementations translate the optional fields to their
37
+ * provider's native primitives (Honcho session, Mem0 run_id, etc).
31
38
  *
39
+ * @public
32
40
  */
33
-
41
+ interface MemoryContext {
42
+ /** End-user identity. */
43
+ userId: string;
44
+ /** Agent / persona writing the memory. */
45
+ agentId?: string;
46
+ /** Logical conversation / run boundary. */
47
+ sessionId?: string;
48
+ /** Tenant / workspace partition. */
49
+ tenantId?: string;
50
+ /** Free-form tags for filtering / categorization. */
51
+ tags?: string[];
52
+ /** Provider-passthrough metadata. */
53
+ metadata?: Record<string, unknown>;
54
+ }
34
55
  /**
35
- * Single tool call event. The internal `args` and `result` shapes are NOT stable.
56
+ * A single memory fact returned by `recall` or `get`.
36
57
  *
37
58
  * @public
38
59
  */
39
- interface ToolCall {
40
- callId: string;
41
- name: string;
42
- args?: unknown;
43
- result?: unknown;
60
+ interface MemoryFact {
61
+ id: MemoryId;
62
+ content: string;
63
+ /** Semantic relevance score (provider-defined scale) when result of `recall`. */
64
+ score?: number;
65
+ /** ISO 8601 timestamp of creation. */
66
+ createdAt?: string;
67
+ metadata?: Record<string, unknown>;
44
68
  }
45
69
  /**
46
- * Incremental text token from the assistant.
70
+ * Versioned snapshot of a memory's history. Only emitted by providers
71
+ * with `capabilities.history === true` (Mem0 today).
47
72
  *
48
73
  * @public
49
74
  */
50
- interface TextDeltaUpdate {
51
- type: "text-delta";
52
- text: string;
75
+ interface MemoryRevision {
76
+ id: MemoryId;
77
+ content: string;
78
+ version: number;
79
+ changedAt: string;
53
80
  }
54
81
  /**
55
- * Incremental reasoning token.
82
+ * Statically declared adapter feature flags. Consumers feature-detect
83
+ * at compile time via `if (adapter.capabilities.history)`.
56
84
  *
57
85
  * @public
58
86
  */
59
- interface ThinkingDeltaUpdate {
60
- type: "thinking-delta";
61
- text: string;
87
+ interface MemoryAdapterCapabilities {
88
+ /** Returns prior versions of a memory via `history(id)`. */
89
+ history: boolean;
90
+ /** First-class `sessionId` scoping. */
91
+ sessions: boolean;
92
+ /** First-class `tenantId` scoping. */
93
+ tenancy: boolean;
94
+ /** Provider performs reasoning over memory (e.g., Honcho dialectic). */
95
+ reasoning: boolean;
96
+ /** Exposes LLM-callable function-calling schemas. */
97
+ toolSchemas: boolean;
98
+ /** Supports background prefetch (currently informational). */
99
+ prefetch: boolean;
62
100
  }
63
101
  /**
64
- * Emitted when a reasoning block completes.
102
+ * One assistant-turn message in the canonical `{role, content}` shape
103
+ * an adapter may receive instead of a flat string when writing a turn.
65
104
  *
66
105
  * @public
67
106
  */
68
- interface ThinkingCompletedUpdate {
69
- type: "thinking-completed";
70
- thinkingDurationMs: number;
107
+ interface MemoryTurnMessage {
108
+ role: "user" | "assistant" | "system";
109
+ content: string;
71
110
  }
72
111
  /**
73
- * Tool call started — args committed.
112
+ * OpenAI-format function-calling schema exposed to the LLM.
74
113
  *
75
114
  * @public
76
115
  */
77
- interface ToolCallStartedUpdate {
78
- type: "tool-call-started";
79
- callId: string;
80
- toolCall: ToolCall;
81
- modelCallId: string;
116
+ interface MemoryToolSchema {
117
+ name: string;
118
+ description: string;
119
+ parameters: Record<string, unknown>;
82
120
  }
83
121
  /**
84
- * Tool call arguments streaming in incrementally.
122
+ * Portable third-party memory adapter contract. Implementations live
123
+ * in `@theokit-memory-*` packages; the SDK never imports them.
85
124
  *
86
125
  * @public
87
126
  */
88
- interface PartialToolCallUpdate {
89
- type: "partial-tool-call";
90
- callId: string;
91
- toolCall: ToolCall;
92
- modelCallId: string;
127
+ interface MemoryAdapter {
128
+ /** Short identifier — matches the `${adapterId}` prefix in `MemoryId`. */
129
+ readonly id: string;
130
+ readonly capabilities: MemoryAdapterCapabilities;
131
+ /**
132
+ * Synchronous availability probe — no network, no I/O. Typically "do I have the credentials I
133
+ * need".
134
+ *
135
+ * `false` DISABLES the adapter: the runtime skips it when building the agent's memory, warns
136
+ * naming this `id`, and carries on with whatever other adapters said yes. When every registered
137
+ * adapter declines, a `write` or `recall` fails with `no_memory_adapter` and a message saying so,
138
+ * rather than resolving without storing anything.
139
+ *
140
+ * It was mandatory and consulted by nothing until #360, which made it a contract that read as a
141
+ * guarantee and provided none — a missing key surfaced mid-conversation as `auth_failed` instead.
142
+ */
143
+ isAvailable(): boolean;
144
+ /** One-shot initialization. Idempotent: safe to call multiple times. */
145
+ initialize?(): Promise<void>;
146
+ /**
147
+ * Persist a fact or full turn to memory. Returns the stored
148
+ * `MemoryId`. Throws `MemoryAdapterError(code: "invalid_input")` on
149
+ * empty content or invalid identifiers in `ctx`.
150
+ */
151
+ write(content: string | MemoryTurnMessage[], ctx: MemoryContext): Promise<MemoryId>;
152
+ /**
153
+ * Semantic recall — top-`k` facts ordered by relevance. Returns
154
+ * empty array when `k === 0` or no matches.
155
+ */
156
+ recall(query: string, ctx: MemoryContext, k?: number): Promise<MemoryFact[]>;
157
+ /**
158
+ * Delete a memory by id. Throws `MemoryAdapterError(code:
159
+ * "invalid_input")` when the id was minted by a different adapter
160
+ * (EC-B). Throws `code: "not_found"` when the id does not exist.
161
+ */
162
+ delete(id: MemoryId): Promise<void>;
163
+ list?(ctx: MemoryContext, opts?: {
164
+ cursor?: string;
165
+ limit?: number;
166
+ }): AsyncIterable<MemoryFact>;
167
+ get?(id: MemoryId): Promise<MemoryFact | null>;
168
+ history?(id: MemoryId): Promise<MemoryRevision[]>;
169
+ /** Empty array when `capabilities.toolSchemas === false`. */
170
+ getToolSchemas?(): MemoryToolSchema[];
171
+ handleToolCall?(name: string, args: Record<string, unknown>, ctx: MemoryContext): Promise<string>;
172
+ /** Graceful shutdown — flush queues, close connections. */
173
+ shutdown?(): Promise<void>;
93
174
  }
94
175
  /**
95
- * Tool call completed.
176
+ * Direct memory API exposed on `SDKAgent.memory`. Resolves to whichever
177
+ * memory adapter(s) are registered via `Agent.create({ plugins: [...] })`.
96
178
  *
97
179
  * @public
98
180
  */
99
- interface ToolCallCompletedUpdate {
100
- type: "tool-call-completed";
101
- callId: string;
102
- toolCall: ToolCall;
103
- modelCallId: string;
181
+ interface AgentMemory {
182
+ /**
183
+ * Persist a fact. Returns the first adapter's id; in multi-adapter
184
+ * setups all adapters receive the write (fan-out).
185
+ */
186
+ write(content: string | MemoryTurnMessage[], ctx?: Partial<MemoryContext>): Promise<MemoryId>;
187
+ /** Semantic recall — merged + deduped across registered adapters. */
188
+ recall(query: string, ctx?: Partial<MemoryContext>, k?: number): Promise<MemoryFact[]>;
189
+ /** Delete a memory by id — routes to the owning adapter via prefix. */
190
+ delete(id: MemoryId): Promise<void>;
191
+ /** Returns the first registered adapter or `null` when none exists. */
192
+ adapter(): MemoryAdapter | null;
104
193
  }
194
+
105
195
  /**
106
- * Token count delta for usage tracking.
196
+ * Owner: `internal/runtime/processors/` (3 of 4 importers). Derived from the import graph, not declared —
197
+ * `tests/lint/types-name-their-owner.test.ts` re-derives it.
198
+ *
199
+ * SE24 — guardrail processor pipeline. A `Processor` inspects/transforms/blocks
200
+ * the user message (input) or the model's final text (output). Processors run in
201
+ * order; each may rewrite its payload, `abort(reason)` to stop the run (surfaced
202
+ * as {@link RunResult.tripwire} + a `tripwire` run-event), or `warn()` to report
203
+ * a non-blocking violation. The pipeline is provider-agnostic and carries NO LLM
204
+ * — an LLM-classifier processor is the consumer's (delegated, see the guardrails
205
+ * ADR). Mirrors a peer framework's `inputProcessors` / `outputProcessors`.
107
206
  *
108
207
  * @public
109
208
  */
110
- interface TokenDeltaUpdate {
111
- type: "token-delta";
112
- tokens: number;
113
- }
114
209
  /**
115
- * Conversation step started.
210
+ * A policy violation surfaced to a processor's {@link Processor.onViolation}
211
+ * callback — on `abort()` (blocking) AND on `warn()` (non-blocking).
116
212
  *
117
213
  * @public
118
214
  */
119
- interface StepStartedUpdate {
120
- type: "step-started";
121
- stepId: number;
215
+ interface ProcessorViolation {
216
+ processorId: string;
217
+ message: string;
218
+ detail?: unknown;
122
219
  }
123
220
  /**
124
- * Conversation step completed.
221
+ * Controls available to a processor while it runs: `abort()` stops the run with
222
+ * a tripwire; `warn()` reports a non-blocking violation and continues.
125
223
  *
126
224
  * @public
127
225
  */
128
- interface StepCompletedUpdate {
129
- type: "step-completed";
130
- stepId: number;
131
- stepDurationMs: number;
226
+ interface ProcessorControls {
227
+ /** Stop the run immediately with a tripwire. Throws — code after it never runs. */
228
+ abort(reason: string): never;
229
+ /** Report a non-blocking violation (fires `onViolation`); the run continues. */
230
+ warn(message: string, detail?: unknown): void;
231
+ }
232
+ /** Context passed to {@link Processor.processInput}. @public */
233
+ interface InputProcessorContext extends ProcessorControls {
234
+ /** The user message text for this send. */
235
+ message: string;
236
+ agentId: string;
237
+ }
238
+ /** Context passed to {@link Processor.processOutput}. @public */
239
+ interface OutputProcessorContext extends ProcessorControls {
240
+ /** The model's final assistant text for this run. */
241
+ text: string;
242
+ agentId: string;
132
243
  }
133
244
  /**
134
- * Turn ended with usage summary.
245
+ * A guardrail processor. Provide `processInput` (runs before the LLM) and/or
246
+ * `processOutput` (runs on the final text). A processor's `strategy` (block /
247
+ * rewrite / redact / warn) is expressed via the {@link ProcessorControls}:
248
+ * return the transformed payload to rewrite/redact, `abort()` to block, `warn()`
249
+ * to report without blocking. The core ships no strategy enum — strategies are a
250
+ * processor-level convention over these primitives.
135
251
  *
136
252
  * @public
137
253
  */
138
- interface TurnEndedUpdate {
139
- type: "turn-ended";
140
- usage?: {
141
- inputTokens: number;
142
- outputTokens: number;
143
- cacheReadTokens: number;
144
- cacheWriteTokens: number;
145
- };
254
+ interface Processor {
255
+ /** Stable id — surfaced on {@link ProcessorViolation} and {@link RunResult.tripwire}. */
256
+ id: string;
257
+ /**
258
+ * Transform or block the user message before it reaches the model. Return the
259
+ * (possibly rewritten) text; returning nothing (void) preserves the message
260
+ * unchanged. May be `async`.
261
+ */
262
+ processInput?(ctx: InputProcessorContext): string | Promise<string> | void;
263
+ /**
264
+ * Transform or block the model's final text before it reaches the caller.
265
+ * Return the (possibly redacted) text; returning nothing (void) preserves the
266
+ * text unchanged. May be `async`.
267
+ */
268
+ processOutput?(ctx: OutputProcessorContext): string | Promise<string> | void;
269
+ /** Fires on `abort()` and `warn()`. Errors thrown here are swallowed (never break the pipeline). */
270
+ onViolation?(violation: ProcessorViolation): void;
146
271
  }
147
272
  /**
148
- * User message appended to the conversation.
273
+ * The tripwire detail attached to {@link RunResult.tripwire} when a processor
274
+ * aborts, and carried by the `tripwire` run-event.
149
275
  *
150
276
  * @public
151
277
  */
152
- interface UserMessageAppendedUpdate {
153
- type: "user-message-appended";
154
- userMessage: UserMessage;
278
+ interface ProcessorTripwire {
279
+ reason: string;
280
+ processorId: string;
155
281
  }
282
+
156
283
  /**
157
- * A conversation summary produced during a run, delivered through `SendOptions.onDelta`.
284
+ * Owner: `src/` (1 of 2 importers). Derived from the import graph, not declared —
285
+ * `tests/lint/types-name-their-owner.test.ts` re-derives it.
158
286
  *
159
- * Nothing in this package emits it. It is declared so an exhaustive `switch` over
160
- * {@link InteractionUpdate} compiles, and so a runtime that does produce summaries has a typed
161
- * channel — do not build a feature that waits on it against the local runtime.
287
+ * Context manager backend.
288
+ *
289
+ * - `"file"` — Read `.theokit/context.json` from the workspace (local) or the
290
+ * cloned repo (cloud).
162
291
  *
163
292
  * @public
164
293
  */
165
- interface SummaryUpdate {
166
- type: "summary";
167
- summary: string;
168
- }
294
+ type ContextManagerKind = "file";
169
295
  /**
170
- * Opens the bracket around a {@link SummaryUpdate}, for a UI that wants to show a pending state
171
- * before the summary text exists. Paired with {@link SummaryCompletedUpdate}.
172
- *
173
- * Like the summary variants around it, nothing in this package emits it.
296
+ * Context configuration accepted by `Agent.create()` via {@link AgentOptions.context}.
174
297
  *
175
298
  * @public
176
299
  */
177
- interface SummaryStartedUpdate {
178
- type: "summary-started";
300
+ interface ContextSettings {
301
+ /** Which backend reads context. Defaults to `"file"`. */
302
+ manager?: ContextManagerKind;
303
+ /** Hard cap on tokens emitted into the agent's system prompt. */
304
+ maxTokens?: number;
305
+ /**
306
+ * Per-file truncation cap in characters. Default 40_000 (~10k tokens).
307
+ * Larger files are truncated with 70%/20% head/tail + marker (ADR D155).
308
+ *
309
+ * @public
310
+ */
311
+ maxBytesPerFile?: number;
312
+ /**
313
+ * Aggregate cap across all context files in characters. Default 120_000.
314
+ * When total exceeds this, lower-priority sources are dropped (ADR D155).
315
+ *
316
+ * Note: context snapshot is **refresh-time** (EC-T); modifying context
317
+ * files mid-flight does not auto-update. Call `agent.reload()` to pick
318
+ * up changes.
319
+ *
320
+ * @public
321
+ */
322
+ maxBytesTotal?: number;
179
323
  }
180
324
  /**
181
- * Closes the bracket opened by {@link SummaryStartedUpdate}. Carries no payload — the summary text
182
- * itself arrives as {@link SummaryUpdate}.
325
+ * Inclusion state of a single context source in a {@link ContextSnapshot}.
183
326
  *
184
- * Like the summary variants around it, nothing in this package emits it.
327
+ * @public
328
+ */
329
+ type ContextSourceStatus = "included" | "excluded" | "summarized";
330
+ /**
331
+ * A single context source resolved by the context manager.
185
332
  *
186
333
  * @public
187
334
  */
188
- interface SummaryCompletedUpdate {
189
- type: "summary-completed";
335
+ interface ContextSource {
336
+ /** Stable identifier — usually the filename without extension. */
337
+ name: string;
338
+ /** Path relative to the workspace root, when applicable. */
339
+ path?: string;
340
+ /** Whether the source was included, dropped, or summarized to fit the budget. */
341
+ status: ContextSourceStatus;
342
+ /** Free-text reason when `status !== "included"`. */
343
+ reason?: string;
190
344
  }
191
345
  /**
192
- * Incremental output from a shell command running inside a run.
346
+ * Token budget used by the context manager for a single agent.
193
347
  *
194
- * `event` is an untyped bag on purpose: this package neither produces nor narrows it, so a consumer
195
- * that receives one should treat it as unvalidated input and check for the fields it needs rather
196
- * than casting. As with the summary variants, nothing here emits this — it exists so the
197
- * {@link InteractionUpdate} union covers a runtime that does.
348
+ * @public
349
+ */
350
+ interface ContextBudget {
351
+ maxTokens?: number;
352
+ /**
353
+ * Either a token count or a list of token strings extracted from source
354
+ * content. Normalized to `<tokens>` in golden comparisons.
355
+ */
356
+ usedTokens?: number | string[];
357
+ }
358
+ /**
359
+ * Result of `agent.context.snapshot()`. Public and secret-free by design — safe
360
+ * to log and persist. Raw secrets, local absolute paths, and exact token values
361
+ * are never present.
198
362
  *
199
363
  * @public
200
364
  */
201
- interface ShellOutputDeltaUpdate {
202
- type: "shell-output-delta";
203
- event: Record<string, unknown>;
365
+ interface ContextSnapshot {
366
+ runtime: "local" | "cloud";
367
+ sources: ContextSource[];
368
+ budget?: ContextBudget;
204
369
  }
205
370
  /**
206
- * Lowest-level raw update from a run. Pass `onDelta` to `agent.send()` to
207
- * consume these. Finer-grained than `SDKMessage` events.
371
+ * Public context manager handle exposed as `agent.context`.
208
372
  *
209
373
  * @public
210
374
  */
211
- type InteractionUpdate = TextDeltaUpdate | ThinkingDeltaUpdate | ThinkingCompletedUpdate | ToolCallStartedUpdate | ToolCallCompletedUpdate | PartialToolCallUpdate | TokenDeltaUpdate | StepStartedUpdate | StepCompletedUpdate | TurnEndedUpdate | UserMessageAppendedUpdate | SummaryUpdate | SummaryStartedUpdate | SummaryCompletedUpdate | ShellOutputDeltaUpdate;
375
+ interface SDKContextManager {
376
+ /** Inspect what the context manager actually loaded for the agent. */
377
+ snapshot(): Promise<ContextSnapshot>;
378
+ }
212
379
 
213
380
  /**
214
- * Owner: `internal/agent-loop/` (3 of 11 importers). Derived from the import graph, not declared —
215
- * `tests/lint/types-name-their-owner.test.ts` re-derives it.
381
+ * Owner: `sandbox/` (1 of 2 importers). Derived from the import graph, not
382
+ * declared — `tests/lint/types-name-their-owner.test.ts` re-derives it.
216
383
  *
217
- * SE2 — typed runtime EVENT stream, ADDITIVE to the `SDKMessage` content stream.
384
+ * Child-process environment policy contract (#54).
218
385
  *
219
- * `Run.stream()` yields `SDKMessage`s (the conversation content). `RunEvent`s are
220
- * out-of-band runtime-OBSERVABILITY signals — the model's content is unaffected —
221
- * delivered opt-in via `SendOptions.onRunEvent`. Discriminate on `type`. Mirrors
222
- * the Anthropic `SDKMessage`-union approach (rate-limit, permission-denied, task
223
- * lifecycle, compaction boundary).
386
+ * The DIP-correct home for the `EnvPolicy` contract type: the domain `types/`
387
+ * layer owns the contract, and the application-layer implementation
388
+ * (`internal/runtime/lifecycle/env-policy.ts`) re-exports it for back-compat
389
+ * while owning the runtime logic (`resolveChildEnv`, secret patterns, …).
224
390
  *
225
- * The union is the forward-compatible CONTRACT (discriminate exhaustively). The
226
- * runtime EMITS every variant end-to-end: `tool_progress` + `permission_denied`
227
- * (agent-loop tool-dispatch seam), `rate_limit` (pool-aware LLM client 429 retry),
228
- * `compact_boundary` (session auto-compaction), and `task_*` (opt-in bridge from a
229
- * `Task.submit({ onRunEvent })` task's lifecycle). A consumer switching on `type`
230
- * sees the real signal.
391
+ * Modes:
392
+ * - `inherit-scrubbed` (DEFAULT) — inherit all parent vars EXCEPT secret-like
393
+ * names (`*KEY*`, `*SECRET*`, `*TOKEN*`, `*PASSWORD*`, `*_AUTH*`). Non-breaking:
394
+ * existing spawns keep every non-secret var; only secrets stop leaking.
395
+ * - `core` — inherit ONLY a safe base allowlist (PATH/HOME/…); strongest scrub.
396
+ * - `all` — explicit opt-out: inherit everything, secrets included.
231
397
  *
232
398
  * @public
233
399
  */
234
- type RunEvent = RunToolProgressEvent | RunRateLimitEvent | RunPermissionDeniedEvent | RunTaskStartedEvent | RunTaskUpdatedEvent | RunTaskCompletedEvent | RunCompactBoundaryEvent | RunCompactionFallbackEvent | RunTripwireEvent | RunCompletionCheckEvent | RunMcpServerFailedEvent | RunMcpServerReadyEvent | RunMemoryDegradedEvent;
400
+ type EnvPolicy = "inherit-scrubbed" | "core" | "all";
401
+
235
402
  /**
236
- * theokit#188 — an MCP server was configured but its tools could not be listed, so NONE of its
237
- * tools exist for this run.
403
+ * Owner: `internal/mcp/` (2 of 5 importers). Derived from the import graph, not declared —
404
+ * `tests/lint/types-name-their-owner.test.ts` re-derives it.
238
405
  *
239
- * The failure was always caught (`safeListTools` returns `[]` so one broken server cannot take the
240
- * turn down) and always DIAGNOSED — to `diag()`, i.e. the SDK's stderr. Nothing reached the
241
- * consumer, so a UI listing configured servers could show one as present while every tool it
242
- * provides had silently vanished. Degrading gracefully is right; degrading INVISIBLY is not.
243
- *
244
- * Emitted once per failing server per run, on the same catch path that already had both the name
245
- * and the reason.
246
406
  */
247
- interface RunMcpServerFailedEvent {
248
- readonly type: "mcp_server_failed";
249
- /** The server as named in the MCP configuration, so the consumer can match it to what it lists. */
250
- readonly serverName: string;
251
- /** Why listing failed — a spawn error, a handshake timeout, a protocol error. */
252
- readonly message: string;
253
- }
407
+
254
408
  /**
255
- * usetheokit/theokit#426 — an MCP server came up, and these are the tools it delivered.
256
- *
257
- * The sibling of {@link RunMcpServerFailedEvent}, emitted from the same function, on the other
258
- * branch. Without it a consumer could see what was CONFIGURED and what BROKE, and could not tell a
259
- * server that came up with twelve tools from one that came up with none — which is exactly the case
260
- * an operator opens a server-status panel to find. `tools: []` on a healthy server is a real and
261
- * previously unreportable state.
262
- *
263
- * An EVENT rather than a getter, because the state is scoped to the run: with
264
- * `mcpLifecycle: "run"` a server may not exist by the time anyone asks, so a getter would have to
265
- * answer about something already gone. This says what was true when the run started.
409
+ * MCP server configuration accepted by `Agent.create()` and `agent.send()`.
266
410
  *
267
- * Emitted once per successfully-listed server per run.
411
+ * @public
268
412
  */
269
- interface RunMcpServerReadyEvent {
270
- readonly type: "mcp_server_ready";
271
- /** The server as named in the MCP configuration — the key a consumer already lists it under. */
272
- readonly serverName: string;
413
+ type McpStdioServerConfig = {
414
+ type?: "stdio";
415
+ command: string;
416
+ args?: string[];
417
+ env?: Record<string, string>;
418
+ /** Local agents only. Cloud rejects this field. */
419
+ cwd?: string;
273
420
  /**
274
- * The tool names the server reported, as IT names them.
275
- *
276
- * Not the `mcp_<server>_<tool>` form the model sees: that spelling is sanitized for the provider,
277
- * and a consumer matching it back to a server's own documentation would have to undo the mangling.
421
+ * #59 — per-request timeout in ms. A request that gets no reply within this
422
+ * window rejects with a typed `NetworkError` (`code: "mcp_timeout"`) instead
423
+ * of hanging the agent loop forever. Default 30_000.
278
424
  */
279
- readonly tools: readonly string[];
280
- }
425
+ requestTimeoutMs?: number;
426
+ /**
427
+ * #54 — env inherit/scrub policy for the spawned MCP server process. Defaults
428
+ * to `"inherit-scrubbed"` (drop secret-like host vars: `*KEY*`/`*SECRET*`/
429
+ * `*TOKEN*`/`*PASSWORD*`/`*_AUTH*`/…) so a third-party MCP server binary cannot
430
+ * exfiltrate host secrets via the environment. `env` above is merged AFTER the
431
+ * policy and always wins. Pass `"all"` to restore full inheritance.
432
+ */
433
+ envPolicy?: EnvPolicy;
434
+ };
281
435
  /**
282
- * SE24 — a guardrail processor called `abort()`; the run stops with a tripwire.
283
- * Delivered via {@link SendOptions.onRunEvent} (mirrors the `RunResult.tripwire`
284
- * surfaced on `wait()`).
436
+ * OAuth-style auth bundle for HTTP/SSE MCP servers.
437
+ *
438
+ * @public
285
439
  */
286
- interface RunTripwireEvent {
287
- readonly type: "tripwire";
288
- readonly reason: string;
289
- readonly processorId: string;
290
- }
291
- /** A tool call is being dispatched (before its result). */
292
- interface RunToolProgressEvent {
293
- readonly type: "tool_progress";
294
- readonly toolName: string;
295
- readonly toolCallId: string;
296
- }
297
- /** The provider returned a rate-limit (HTTP 429); the loop will back off + retry. */
298
- interface RunRateLimitEvent {
299
- readonly type: "rate_limit";
300
- /** Retry attempt number (1-based) about to be delayed. */
301
- readonly attempt: number;
302
- /** Delay in ms before the retry, when the provider/policy supplied one. */
303
- readonly retryAfterMs?: number;
440
+ interface McpAuthConfig {
441
+ CLIENT_ID: string;
442
+ CLIENT_SECRET?: string;
443
+ scopes?: string[];
444
+ /**
445
+ * OAuth 2.1 PKCE flow configuration (ADR D41, v1.2+). When present, the
446
+ * SDK runs the PKCE flow on first use and stores tokens via keychain or
447
+ * file. Without this, the SDK relies on `CLIENT_SECRET` + manual headers.
448
+ */
449
+ oauth?: McpOAuthConfig;
304
450
  }
305
451
  /**
306
- * A tool call was DENIED before dispatch — by the permission gate/plugin (SE1),
307
- * an operator file-hook `preToolUse`, or the fork tool-whitelist. `source`
308
- * discriminates which. `toolCallId` joins the event to the tool-call log.
452
+ * OAuth 2.1 PKCE flow descriptor. See ADR D41.
453
+ *
454
+ * @public
309
455
  */
310
- interface RunPermissionDeniedEvent {
311
- readonly type: "permission_denied";
312
- readonly toolName: string;
313
- readonly toolCallId: string;
314
- /** Which layer blocked the call. */
315
- readonly source: "plugin" | "file_hook" | "fork_whitelist";
316
- /** The rejection message surfaced to the model. */
317
- readonly message: string;
318
- }
319
- /** A background task/subagent started. */
320
- interface RunTaskStartedEvent {
321
- readonly type: "task_started";
322
- readonly taskId: string;
323
- readonly description?: string;
324
- }
325
- /** A background task/subagent changed state. */
326
- interface RunTaskUpdatedEvent {
327
- readonly type: "task_updated";
328
- readonly taskId: string;
329
- readonly status: string;
330
- }
331
- /** A background task/subagent finished. */
332
- interface RunTaskCompletedEvent {
333
- readonly type: "task_completed";
334
- readonly taskId: string;
335
- readonly status: "completed" | "failed" | "stopped";
456
+ interface McpOAuthConfig {
457
+ /** Authorization endpoint (e.g. https://api.notion.com/v1/oauth/authorize). */
458
+ authorizationEndpoint: string;
459
+ /** Token endpoint (e.g. https://api.notion.com/v1/oauth/token). */
460
+ tokenEndpoint: string;
461
+ /** Where the OAuth `code` is received. */
462
+ redirectMode: "manual" | "localhost";
463
+ /** Localhost callback port (0 = random free port, default). */
464
+ localhostPort?: number;
465
+ /** Flow timeout in ms (default 300_000 = 5min). */
466
+ timeoutMs?: number;
336
467
  }
337
468
  /**
338
- * SE34 — the per-send completion check (`isTaskComplete`) produced a verdict.
339
- * Emitted once, after a finished run's reply is judged against
340
- * {@link SendOptions.completionCheck}. Distinct from `task_completed` (which is
341
- * background-task/subagent lifecycle). Mirrors {@link RunResult.completionCheck}.
469
+ * HTTP or SSE MCP server.
470
+ *
471
+ * @public
342
472
  */
343
- interface RunCompletionCheckEvent {
344
- readonly type: "completion_check";
345
- readonly complete: boolean;
346
- readonly reason: string;
347
- }
348
- /** The conversation crossed a compaction boundary (history was summarized). */
349
- interface RunCompactBoundaryEvent {
350
- readonly type: "compact_boundary";
351
- readonly trigger: "manual" | "auto";
352
- /** Token count before compaction, when known. */
353
- readonly preTokens?: number;
354
- }
473
+ type McpHttpServerConfig = {
474
+ type?: "http" | "sse";
475
+ url: string;
476
+ /** Passed through. `Authorization` works here. */
477
+ headers?: Record<string, string>;
478
+ auth?: McpAuthConfig;
479
+ /**
480
+ * #59 — per-request timeout in ms, enforced via `AbortSignal.timeout`. A
481
+ * fetch that does not respond within this window rejects with a typed
482
+ * `NetworkError` (`code: "mcp_timeout"`). Default 30_000.
483
+ */
484
+ requestTimeoutMs?: number;
485
+ };
355
486
  /**
356
- * M77 — auto-compaction is budgeting against a FLOOR, because neither the catalog nor the caller
357
- * supplied a context window for this model.
358
- *
359
- * The prior behaviour was to disable auto-compaction entirely and write one line to stderr per
360
- * process. That is fail-OPEN: the conversation grows until the provider rejects it. This event exists
361
- * so a surface can say "I am running without a real budget" instead of the user discovering it at the
362
- * moment of failure.
487
+ * Union of MCP server configs.
363
488
  *
364
- * Not emitted when the window came from the catalog (the normal path) or from an explicit caller
365
- * override (the caller already knows).
489
+ * @public
366
490
  */
367
- interface RunCompactionFallbackEvent {
368
- readonly type: "compaction_fallback";
369
- /** The model whose window is unknown — what the user needs to fix in configuration. */
370
- readonly model: string;
371
- /** The floor being budgeted against, after the safety margin. */
372
- readonly window: number;
373
- }
491
+ type McpServerConfig = McpStdioServerConfig | McpHttpServerConfig;
492
+
374
493
  /**
375
- * A memory stage failed and the run continued without it.
376
- *
377
- * The same shape of gap {@link RunMcpServerFailedEvent} closed for MCP, in the module next door.
378
- * `initLoopContext` had three bare `catch { <field> = <empty> }` blocks: an init failure meant no
379
- * memory tool was registered, a `buildTools` failure meant no provider tools, and a `runActivePass`
380
- * failure meant no recalled context in the system prompt. The agent then answered without the memory
381
- * it was configured with, and nothing recorded it — not stderr, not this sink, not the span in scope.
494
+ * Owner: `src/` (4 of 9 importers). Derived from the import graph, not declared —
495
+ * `tests/lint/types-name-their-owner.test.ts` re-derives it.
382
496
  *
383
- * Degrading to a working agent is the right BEHAVIOUR. This event exists because the degradation was
384
- * unobservable, so a host UI showed a healthy run.
497
+ * Capability slot a provider can fulfill.
385
498
  *
386
- * Emitted once per failing stage per run.
499
+ * @public
500
+ */
501
+ type ProviderCapability = "chat" | "web_search" | "image" | "embedding";
502
+ /**
503
+ * A single user-declared routing rule. Maps a capability to a provider, and
504
+ * optionally pins a specific model.
387
505
  *
388
506
  * @public
389
507
  */
390
- interface RunMemoryDegradedEvent {
391
- readonly type: "memory_degraded";
392
- /** Which stage failed: `init`, `buildTools`, or `activePass`. */
393
- readonly stage: string;
394
- /** Why it failed, as the provider reported it. */
395
- readonly message: string;
508
+ interface ProviderRoute {
509
+ capability: ProviderCapability;
510
+ provider: string;
511
+ model?: string;
512
+ /**
513
+ * Opt-in leaked-dialect safe-parse for this route's provider (theokit#58
514
+ * follow-up). When `true`, a `chat_completions` finish that carries ZERO
515
+ * native `tool_calls` has its assistant text scanned for the Hermes
516
+ * `<function=…></tool_call>` dialect, and any recovered calls are surfaced as
517
+ * real `tool_calls` so the loop executes them — for models (qwen3-coder via
518
+ * OpenRouter) that intermittently leak tool calls as text. Default `false`;
519
+ * fail-open (a partial/unclosed block never fabricates a call). Scoped to the
520
+ * resolved chat chain, so a non-leaking route is unaffected.
521
+ */
522
+ extractToolCallsFromContent?: boolean;
396
523
  }
397
524
  /**
398
- * Receives every {@link RunEvent} a run emits, in emission order.
399
- *
400
- * Wired through `onRunEvent` on the run options. The sink is observability, never control flow: it
401
- * cannot cancel, alter, or delay the run, and {@link emitRunEvent} swallows anything it throws — a
402
- * broken sink degrades what you can see, never what the agent does.
403
- *
404
- * Synchronous by signature, so a slow sink slows the run. Hand work off rather than awaiting inside
405
- * it; returning a promise here would be ignored, not awaited.
525
+ * Provider routing configuration accepted by `Agent.create()` via
526
+ * {@link AgentOptions.providers}.
406
527
  *
407
528
  * @public
408
529
  */
409
- type RunEventSink = (event: RunEvent) => void;
410
-
530
+ interface ProviderRoutingSettings {
531
+ /** Explicit `{ capability → provider }` map. First match wins per capability. */
532
+ routes: ProviderRoute[];
533
+ /** Provider names to try in order when a route has no provider available. */
534
+ fallback?: string[];
535
+ /**
536
+ * Multiple API keys per provider for same-provider key rotation
537
+ * (credential pool — ADRs D123-D133). When a key hits HTTP 429, 402,
538
+ * or 401, the SDK rotates to the next entry transparently before
539
+ * falling back to a different provider.
540
+ *
541
+ * Example:
542
+ * ```ts
543
+ * apiKeys: { openrouter: ["sk-or-...", "sk-or-..."], anthropic: ["..."] }
544
+ * ```
545
+ *
546
+ * Empty arrays and empty strings are filtered out. If a provider has
547
+ * exactly 1 effective key, the pool is transparent (no rotation behavior).
548
+ *
549
+ * Conflicts with the single-key shape `AgentOptions.apiKey: "..."` —
550
+ * use one OR the other, not both.
551
+ *
552
+ * @public
553
+ */
554
+ apiKeys?: Record<string, string[]>;
555
+ /**
556
+ * Rotation strategy per provider for the credential pool. Default is
557
+ * `"fill_first"` (use entries[0] until exhausted). Only consulted when
558
+ * `apiKeys[provider]` has ≥2 entries.
559
+ *
560
+ * @public
561
+ */
562
+ credentialPoolStrategy?: Record<string, "fill_first" | "round_robin" | "least_used" | "random">;
563
+ }
411
564
  /**
412
- * Owner: `internal/runtime/processors/` (3 of 4 importers). Derived from the import graph, not declared —
413
- * `tests/lint/types-name-their-owner.test.ts` re-derives it.
414
- *
415
- * SE24 — guardrail processor pipeline. A `Processor` inspects/transforms/blocks
416
- * the user message (input) or the model's final text (output). Processors run in
417
- * order; each may rewrite its payload, `abort(reason)` to stop the run (surfaced
418
- * as {@link RunResult.tripwire} + a `tripwire` run-event), or `warn()` to report
419
- * a non-blocking violation. The pipeline is provider-agnostic and carries NO LLM
420
- * — an LLM-classifier processor is the consumer's (delegated, see the guardrails
421
- * ADR). Mirrors a peer framework's `inputProcessors` / `outputProcessors`.
565
+ * Plugins configuration accepted by `Agent.create()` via
566
+ * {@link AgentOptions.plugins}.
422
567
  *
423
568
  * @public
424
569
  */
570
+ interface PluginsSettings {
571
+ /** Plugin names to enable. Plugin discovery is plugin-provider specific. */
572
+ enabled?: string[];
573
+ }
425
574
  /**
426
- * A policy violation surfaced to a processor's {@link Processor.onViolation}
427
- * callback — on `abort()` (blocking) AND on `warn()` (non-blocking).
575
+ * Resolved routing decision returned by `agent.providers.routes()`. Public and
576
+ * secret-free by design — safe to log.
428
577
  *
429
578
  * @public
430
579
  */
431
- interface ProcessorViolation {
432
- processorId: string;
433
- message: string;
434
- detail?: unknown;
580
+ interface ResolvedProviderRoute {
581
+ capability: string;
582
+ provider: string;
583
+ model?: string;
584
+ /** Why the runtime picked this provider (e.g. `"explicit-model-provider"`). */
585
+ reason: string;
435
586
  }
436
587
  /**
437
- * Controls available to a processor while it runs: `abort()` stops the run with
438
- * a tripwire; `warn()` reports a non-blocking violation and continues.
588
+ * Public providers manager handle exposed as `agent.providers`.
439
589
  *
440
590
  * @public
441
591
  */
442
- interface ProcessorControls {
443
- /** Stop the run immediately with a tripwire. Throws — code after it never runs. */
444
- abort(reason: string): never;
445
- /** Report a non-blocking violation (fires `onViolation`); the run continues. */
446
- warn(message: string, detail?: unknown): void;
592
+ interface SDKProvidersManager {
593
+ /** Inspect which provider serves each capability for this agent. */
594
+ routes(): Promise<ResolvedProviderRoute[]>;
447
595
  }
448
- /** Context passed to {@link Processor.processInput}. @public */
449
- interface InputProcessorContext extends ProcessorControls {
450
- /** The user message text for this send. */
451
- message: string;
452
- agentId: string;
453
- }
454
- /** Context passed to {@link Processor.processOutput}. @public */
455
- interface OutputProcessorContext extends ProcessorControls {
456
- /** The model's final assistant text for this run. */
457
- text: string;
458
- agentId: string;
596
+ /**
597
+ * Provider catalog entry returned by `Theokit.providers.list()`.
598
+ *
599
+ * @public
600
+ */
601
+ interface SDKProvider {
602
+ name: string;
603
+ displayName: string;
604
+ capabilities: string[];
605
+ isAvailable: boolean;
606
+ /** JSON Schema describing the env vars / fields needed to enable this provider. */
607
+ setupSchema: object;
459
608
  }
609
+
460
610
  /**
461
- * A guardrail processor. Provide `processInput` (runs before the LLM) and/or
462
- * `processOutput` (runs on the final text). A processor's `strategy` (block /
463
- * rewrite / redact / warn) is expressed via the {@link ProcessorControls}:
464
- * return the transformed payload to rewrite/redact, `abort()` to block, `warn()`
465
- * to report without blocking. The core ships no strategy enum — strategies are a
466
- * processor-level convention over these primitives.
611
+ * Owner: `internal/agent-loop/` (4 of 16 importers). Derived from the import graph, not declared —
612
+ * `tests/lint/types-name-their-owner.test.ts` re-derives it.
613
+ *
614
+ */
615
+
616
+ /**
617
+ * Tool invocation block emitted by the assistant.
467
618
  *
468
619
  * @public
469
620
  */
470
- interface Processor {
471
- /** Stable id — surfaced on {@link ProcessorViolation} and {@link RunResult.tripwire}. */
621
+ interface ToolUseBlock {
622
+ type: "tool_use";
472
623
  id: string;
473
- /**
474
- * Transform or block the user message before it reaches the model. Return the
475
- * (possibly rewritten) text; returning nothing (void) preserves the message
476
- * unchanged. May be `async`.
477
- */
478
- processInput?(ctx: InputProcessorContext): string | Promise<string> | void;
479
- /**
480
- * Transform or block the model's final text before it reaches the caller.
481
- * Return the (possibly redacted) text; returning nothing (void) preserves the
482
- * text unchanged. May be `async`.
483
- */
484
- processOutput?(ctx: OutputProcessorContext): string | Promise<string> | void;
485
- /** Fires on `abort()` and `warn()`. Errors thrown here are swallowed (never break the pipeline). */
486
- onViolation?(violation: ProcessorViolation): void;
624
+ name: string;
625
+ /** Tool args are not part of the stable schema. Treat as unknown and parse defensively. */
626
+ input: unknown;
487
627
  }
488
628
  /**
489
- * The tripwire detail attached to {@link RunResult.tripwire} when a processor
490
- * aborts, and carried by the `tripwire` run-event.
629
+ * Init metadata. Emitted once at the start of a run.
491
630
  *
492
631
  * @public
493
632
  */
494
- interface ProcessorTripwire {
495
- reason: string;
496
- processorId: string;
633
+ interface SDKSystemMessage {
634
+ type: "system";
635
+ subtype?: "init";
636
+ agent_id: string;
637
+ run_id: string;
638
+ model?: ModelSelection;
639
+ tools?: string[];
497
640
  }
498
-
499
641
  /**
500
- * Owner: `src/` (2 of 7 importers). Derived from the import graph, not declared —
501
- * `tests/lint/types-name-their-owner.test.ts` re-derives it.
642
+ * Echo of the user prompt for this run.
502
643
  *
503
- * Leaf module for content-block types shared by `messages.ts` (assistant/user
504
- * content) and `agent-prims.ts` (`CustomTool` handler results). Kept
505
- * import-free so both can depend on it WITHOUT the `agent-prims ↔ messages`
506
- * cycle (#7).
644
+ * @public
645
+ */
646
+ interface SDKUserMessageEvent {
647
+ type: "user";
648
+ agent_id: string;
649
+ run_id: string;
650
+ message: {
651
+ role: "user";
652
+ content: TextBlock[];
653
+ };
654
+ }
655
+ /**
656
+ * Model text output for this run.
507
657
  *
508
658
  * @public
509
659
  */
660
+ interface SDKAssistantMessage {
661
+ type: "assistant";
662
+ agent_id: string;
663
+ run_id: string;
664
+ message: {
665
+ role: "assistant";
666
+ content: Array<TextBlock | ToolUseBlock>;
667
+ };
668
+ }
510
669
  /**
511
- * Plain text content block emitted by the assistant or user, or returned by a
512
- * tool.
670
+ * Reasoning content.
513
671
  *
514
672
  * @public
515
673
  */
516
- interface TextBlock {
517
- type: "text";
674
+ interface SDKThinkingMessage {
675
+ type: "thinking";
676
+ agent_id: string;
677
+ run_id: string;
518
678
  text: string;
679
+ thinking_duration_ms?: number;
680
+ /**
681
+ * theokit#122 — the provider's cryptographic signature for this thinking block, when it issued
682
+ * one. Anthropic requires a resumed conversation to replay each thinking block WITH its
683
+ * signature; without it the next request fails with `400 "thinking blocks cannot be modified"`,
684
+ * which made an extended-thinking session unresumable.
685
+ *
686
+ * Absent for providers that stream reasoning text unsigned (the OpenAI-compatible wire).
687
+ */
688
+ signature?: string;
519
689
  }
520
690
  /**
521
- * SE7 — a base64-encoded image block a tool can hand back as (part of) its
522
- * result or its `ToolError`. `media_type` is a MIME type (e.g. `"image/png"`);
523
- * `data` is the base64 payload without a data-URL prefix.
691
+ * Tool invocation lifecycle event. Emitted at start with `args`, then again on
692
+ * completion with `result`.
524
693
  *
525
- * Note: when a tool builds this from model- or user-influenced input, treat
526
- * `media_type` as UNTRUSTED — validate/allow-list it before rendering it in a
527
- * log or UI (it could carry newlines / control chars). The SDK only forwards it
528
- * (JSON-serialized onto the wire) and never executes or path-joins it.
694
+ * Tool `args` and `result` are NOT part of the stable schema — treat as unknown.
529
695
  *
530
696
  * @public
531
697
  */
532
- interface ImageBlock {
533
- type: "image";
534
- source: {
535
- type: "base64";
536
- media_type: string;
537
- data: string;
698
+ interface SDKToolUseMessage {
699
+ type: "tool_call";
700
+ agent_id: string;
701
+ run_id: string;
702
+ call_id: string;
703
+ name: string;
704
+ status: "running" | "completed" | "error";
705
+ args?: unknown;
706
+ result?: unknown;
707
+ truncated?: {
708
+ args?: boolean;
709
+ result?: boolean;
538
710
  };
539
711
  }
540
712
  /**
541
- * SE7 — structured content a tool result may carry: text and/or images. A tool
542
- * `handler` may return this (success) and a `ToolError` may carry it (failure).
543
- * Block-capable provider wires forward it natively; string-only provider wires
544
- * flatten text and fail fast on an image.
713
+ * Cloud run lifecycle transitions.
545
714
  *
546
715
  * @public
547
716
  */
548
- type ToolResultContentBlock = TextBlock | ImageBlock;
549
-
717
+ interface SDKStatusMessage {
718
+ type: "status";
719
+ agent_id: string;
720
+ run_id: string;
721
+ status: "CREATING" | "RUNNING" | "FINISHED" | "ERROR" | "CANCELLED" | "EXPIRED";
722
+ message?: string;
723
+ }
550
724
  /**
551
- * Owner: `internal/agent-loop/` (3 of 11 importers). Derived from the import graph, not
552
- * declared — `tests/lint/types-name-their-owner.test.ts` re-derives it.
553
- *
554
- * Type-leaf — primitives shared between `agent.ts`, `run.ts`, and
555
- * `messages.ts`. Extracted to break LOW type-only cycles #5 and #7
556
- * (audit `architecture-output/final_report.md`) per plan
557
- * arch-review-fixes-2026-06-06 § Phase 4 / T4.1 (D438).
558
- *
559
- * Public surface unchanged — `types/agent.ts` re-exports these from this
560
- * leaf so `import type { ModelSelection, CustomTool } from "@theokit/sdk"`
561
- * keeps resolving.
725
+ * Task-level milestones and summaries.
562
726
  *
563
727
  * @public
564
728
  */
729
+ interface SDKTaskMessage {
730
+ type: "task";
731
+ agent_id: string;
732
+ run_id: string;
733
+ status?: string;
734
+ text?: string;
735
+ }
565
736
  /**
566
- * One slot in a {@link ModelSelection.params} array.
737
+ * Awaiting user input or approval.
567
738
  *
568
739
  * @public
569
740
  */
570
- interface ModelParameterValue {
571
- id: string;
572
- value: string;
741
+ interface SDKRequestMessage {
742
+ type: "request";
743
+ agent_id: string;
744
+ run_id: string;
745
+ request_id: string;
573
746
  }
574
747
  /**
575
- * Identifies a model plus optional per-model parameters (e.g. reasoning effort).
576
- *
577
- * Use `Theokit.models.list()` to discover valid ids and parameter definitions.
748
+ * Partial object emitted during `Agent.streamObject<T>` streaming (ADR D45).
749
+ * `partial` is `DeepPartial<z.infer<T>>` at the typed iterator level but
750
+ * erased to `unknown` here because SDKMessage union is non-generic.
578
751
  *
579
752
  * @public
580
753
  */
581
- interface ModelSelection {
582
- id: string;
583
- params?: ModelParameterValue[];
584
- /**
585
- * M94 — the model's context window, in tokens. Becomes the window resolver's `override`.
586
- *
587
- * It exists for models with NO catalog entry: without it, a 400k model was budgeted against the
588
- * 128k floor and compacted ~3x more than it needed to. A value above what the catalog knows is
589
- * clamped — declaring 10M does not blow past the provider.
590
- */
591
- contextWindow?: number;
592
- /**
593
- * #332 — the endpoint THIS model should reach, for OpenAI-compatible and local servers.
594
- *
595
- * Without it the base URL came only from a process-wide env var (`OLLAMA_HOST`) or the provider
596
- * profile's shipped default, so every `ollama/*` model in a process shared one host — an app
597
- * could not run a small model on localhost and a large one on a GPU box.
598
- *
599
- * It outranks the env var deliberately: with the env var winning, whoever set it for one model
600
- * would keep hijacking every other one, which is the same bug wearing a hat.
601
- *
602
- * Leaving it unset keeps the zero-config path exactly as it was — `ollama/qwen2.5:3b` still
603
- * resolves to `http://localhost:11434` from the profile, with no key and no setup.
604
- */
605
- url?: string;
754
+ interface SDKObjectDelta {
755
+ type: "object_delta";
756
+ agent_id: string;
757
+ run_id: string;
758
+ partial: unknown;
759
+ attempt: number;
606
760
  }
607
761
  /**
608
- * SE12 — a read-only, text-only projection of one turn of the run's conversation,
609
- * exposed to a tool handler via `ctx.messages`. Content is flattened to text; tool
610
- * calls / results and non-text parts are dropped, and turns that project to empty
611
- * text are omitted. Consumed by `defineSubAgent`'s `messageFilter` to forward
612
- * (a subset of) the supervisor transcript to a subagent.
762
+ * Discriminated union of all stream events. Discriminate on `type`.
613
763
  *
614
- * `role` includes `"system"` for type-completeness with the wire message shape,
615
- * but the system prompt travels on a separate request field — a `"system"` entry
616
- * does NOT appear in the current projection.
764
+ * All events include `agent_id` and `run_id`.
617
765
  *
618
766
  * @public
619
767
  */
620
- interface ToolContextMessage {
621
- role: "system" | "user" | "assistant";
622
- content: string;
623
- }
768
+ type SDKMessage = SDKSystemMessage | SDKUserMessageEvent | SDKAssistantMessage | SDKThinkingMessage | SDKToolUseMessage | SDKStatusMessage | SDKTaskMessage | SDKRequestMessage | SDKObjectDelta;
769
+
624
770
  /**
625
- * Local function tool declared per-agent via {@link AgentOptions.tools}. The
626
- * handler runs in-process; no MCP server is involved. The SDK serializes
627
- * `name`, `description`, and `inputSchema` into the model's tool catalog.
771
+ * Owner: `internal/runtime/lifecycle/` (1 of 1 importers). Derived from the import graph, not
772
+ * declared — `tests/lint/types-name-their-owner.test.ts` re-derives it.
628
773
  *
629
- * Handlers MUST be re-passed on `Agent.resume()` because closures cannot be
630
- * persisted. The tool catalog (name + description + schema) is NOT serialized.
774
+ * Fork primitive public type contracts (T1.2, ADRs D110-D114).
775
+ *
776
+ * Extracted into a leaf type module (arch-review ADR 0001) so the public
777
+ * `types/agent.ts` barrel can reference `ForkOptions`/`ForkResult` without
778
+ * importing the `internal/runtime/lifecycle/fork-agent.ts` implementation — which in
779
+ * turn imports back from `types/agent.ts`. That mutual reference created a
780
+ * type-only `madge` cycle. These interfaces are self-contained (no SDKAgent
781
+ * / AgentOptions references), so co-locating them here breaks the cycle with
782
+ * no runtime change. `fork-agent.ts` re-exports them for back-compat.
783
+ */
784
+ /**
785
+ * Caller-supplied fork configuration. See `forkAgentImpl`.
631
786
  *
632
787
  * @public
633
788
  */
634
- interface CustomTool {
789
+ interface ForkOptions {
635
790
  /**
636
- * Tool name surfaced to the LLM. Must match `^[a-zA-Z][a-zA-Z0-9_-]{0,63}$`
637
- * and must not collide with `shell`, `memory_search`, `memory_get`, or any
638
- * `mcp_*` prefix (reserved for the SDK's built-in tools).
791
+ * Tool subset visible to the fork. Names must match the canonical (post-repair)
792
+ * tool name — typically lowercase. Tools not in this set return a `tool_result`
793
+ * with `"Tool blocked by fork whitelist"` content (EC-H).
639
794
  */
640
- name: string;
641
- /** Description surfaced to the LLM. Required — drives tool-selection accuracy. */
642
- description: string;
643
- /** JSON Schema (Draft-7 subset) describing the `input` argument. Must be `type: "object"`. */
644
- inputSchema: Record<string, unknown>;
645
- /**
646
- * Local handler invoked when the model emits `tool_use` for this tool.
647
- * Returns a string OR structured content blocks (SE7 — text + image, e.g. a
648
- * screenshot) that become the `tool_result.content` surfaced back to the
649
- * model. Throws → SDK converts to `tool_result` with `isError: true` and the
650
- * error `message` as content; throw a `ToolError` to carry a clean message or
651
- * multimodal error content. #65 — an optional 2nd `ToolContext` argument
652
- * carries the run's `AbortSignal`; single-argument handlers are unaffected. M7
653
- * — the same `ctx` also carries an optional user `context` (provided once via
654
- * `SendOptions.context`), so shared config like a `projectRoot` is read by
655
- * every tool instead of baked into each factory. SE12 — `ctx.messages` is a
656
- * read-only, text-only projection of the current turn's transcript (see
657
- * {@link ToolContextMessage}); `defineSubAgent`'s `messageFilter` consumes it.
658
- * #119 — `ctx.threadId` is the run's session identity (the key passed to
659
- * `Agent.getOrCreate(sessionId, …)`, or the agent's own id), so a stateful tool
660
- * shared across sessions can scope its state per session instead of leaking it.
661
- */
662
- handler: (input: Record<string, unknown>, ctx?: {
663
- signal?: AbortSignal;
664
- context?: unknown;
665
- messages?: readonly ToolContextMessage[];
666
- threadId?: string;
667
- }) => string | ToolResultContentBlock[] | Promise<string | ToolResultContentBlock[]>;
668
- }
669
- /**
670
- * How the permission engine treats the UNMATCHED verdict.
671
- *
672
- * - `default` — ask.
673
- * - `plan` — read-only.
674
- * - `acceptEdits` — auto-approve the unmatched verdict, but still honour an explicit `ask` rule.
675
- * - `bypass` (alias `bypassPermissions`, the Anthropic-exact name) — everything allowed EXCEPT an
676
- * explicit `deny`. Never asks.
677
- *
678
- * G7 / DIP — defined in this type leaf rather than in `permission-engine.ts`, which is a RUNTIME
679
- * module. `types/agent.ts`, `types/run.ts` and `types/plugin.ts` all need the union, and each one
680
- * used to reach into the engine for it: three of the nine violations the `types-dont-import-runtime`
681
- * rule reported the moment it was able to see type-only edges at all. The engine re-exports it, so
682
- * `import type { PermissionMode } from "@theokit/sdk"` is unchanged.
683
- *
684
- * @public
685
- */
686
- type PermissionMode = "default" | "plan" | "acceptEdits" | "bypass" | "bypassPermissions";
687
-
795
+ allowedTools: Set<string>;
796
+ /** Task prompt sent to the fork. */
797
+ prompt: string;
798
+ /** Override system prompt. Default: byte-identical inheritance from parent (D112). */
799
+ systemPrompt?: string;
800
+ /** Memory write provenance tag (D114). Default `"fork"`. */
801
+ forkOrigin?: string;
802
+ }
688
803
  /**
689
- * Owner: `internal/agent-loop/` (4 of 8 importers). Derived from the import graph, not
690
- * declared — `tests/lint/types-name-their-owner.test.ts` re-derives it.
804
+ * Outcome of a fork run.
691
805
  *
806
+ * @public
692
807
  */
808
+ interface ForkResult {
809
+ /** Final agent response text (`undefined` when the fork produced no result). */
810
+ result: string | undefined;
811
+ /** Tool calls executed inside the fork. */
812
+ toolCalls: ReadonlyArray<{
813
+ name: string;
814
+ input: Record<string, unknown>;
815
+ }>;
816
+ /** Aggregate token usage reported by the run. */
817
+ usage: {
818
+ inputTokens: number;
819
+ outputTokens: number;
820
+ };
821
+ }
693
822
 
694
823
  /**
695
- * Plain assistant message in a conversation history.
824
+ * Owner: `internal/judge/` (3 of 8 importers). Derived from the import graph, not declared —
825
+ * `tests/lint/types-name-their-owner.test.ts` re-derives it.
826
+ *
827
+ * M80 — the terminal verdicts a judge can return.
828
+ *
829
+ * `"blocked"` was added here in this milestone. `GoalResult.status` already carried it, but the
830
+ * judge had no way to EMIT it: its vocabulary was `done | continue | skipped`, so facing a real
831
+ * blocker it could only say `continue` — and the loop repeated the same turn until it blew the
832
+ * budget, reporting `failed` on a limit rather than `blocked` on impossibility. Two different causes
833
+ * with the same visible outcome.
696
834
  *
697
835
  * @public
698
836
  */
699
- interface AssistantMessage {
700
- text: string;
701
- }
837
+ type Verdict = "done" | "continue" | "skipped" | "blocked";
702
838
  /**
703
- * Reasoning step in a conversation history.
839
+ * M80 — the result of a judge call, now public.
840
+ *
841
+ * It was `internal/`, so a consumer wanting to type the return — to react to `blocked` without a
842
+ * magic string — had to redeclare the shape. It is the same duplication M78 closed for the error
843
+ * hierarchy: without a public surface, reimplementing is the only legal way out for anyone behind
844
+ * the layer boundary.
704
845
  *
705
846
  * @public
706
847
  */
707
- interface ThinkingMessage {
708
- text: string;
709
- thinkingDurationMs?: number;
848
+ interface JudgeResult {
849
+ verdict: Verdict;
850
+ reason: string;
710
851
  /**
711
- * theokit#122 — the provider's cryptographic signature for this thinking block, when it issued
712
- * one. Persisted with the block so a resumed conversation can replay it byte-identically;
713
- * Anthropic rejects a modified or unsigned thinking block with
714
- * `400 "thinking blocks cannot be modified"`.
852
+ * `true` when the text did not start with one of the canonical prefixes. The verdict becomes
853
+ * `"continue"` (fail-safe) so the loop does not stop too early; the caller counts consecutive
854
+ * failures and gives up via `maxConsecutiveJudgeFailures`.
715
855
  */
716
- signature?: string;
856
+ parseFailed: boolean;
717
857
  }
718
858
  /**
719
- * Shell command executed during a run.
859
+ * Single event emitted while iterating a goal-driven loop — the public event type of
860
+ * {@link SDKAgent.runUntil} (ADRs D115-D117). Discriminated union by the `type` field so
861
+ * consumers can `switch (event.type)` with full TypeScript exhaustiveness; mirrors the
862
+ * {@link import("../stream-object.js").StreamObjectEvent} pattern (ADR D39).
863
+ *
864
+ * Five variants:
865
+ *
866
+ * - `turn_start` — the agent is about to invoke `send()`. Emitted once
867
+ * per turn.
868
+ * - `agent_response` — the agent's `send()` resolved; carries the text
869
+ * reply.
870
+ * - `judge_verdict` — the auxiliary judge model evaluated the response.
871
+ * `parseFailed: true` indicates the judge returned a malformed reply
872
+ * (fail-safe verdict = `continue`, see ADR D121).
873
+ * - `continuation` — the judge ruled `continue`; carries the prompt that
874
+ * was sent on THIS turn (i.e., the input that produced the agent
875
+ * response just yielded). Useful for consumers who want to audit the
876
+ * exact continuation message that drove each iteration. The prompt
877
+ * for the NEXT turn is composed lazily at the start of that turn
878
+ * from the latest `agent_response.content`.
879
+ * - `status_change` — transition of the overall goal state. Always
880
+ * emitted once at start (`active`) and once at end
881
+ * (`completed | failed | paused`).
882
+ *
883
+ * @public
884
+ */
885
+ type GoalEvent = {
886
+ type: "turn_start";
887
+ turn: number;
888
+ goal: string;
889
+ } | {
890
+ type: "agent_response";
891
+ turn: number;
892
+ content: string;
893
+ } | {
894
+ type: "judge_verdict";
895
+ turn: number;
896
+ /** M80 — `"blocked"` was added: the judge can declare impossibility, not just "continue". */
897
+ verdict: "done" | "continue" | "skipped" | "blocked";
898
+ reason: string;
899
+ parseFailed: boolean;
900
+ } | {
901
+ type: "continuation";
902
+ turn: number;
903
+ prompt: string;
904
+ } | {
905
+ type: "status_change";
906
+ status: "active" | "paused" | "completed" | "failed" | "budget_limited" | "blocked";
907
+ reason: string;
908
+ };
909
+ /**
910
+ * Return value of the `runUntil` async generator. Consumer reads via
911
+ * `const { value } = await gen.next()` (when `done: true`).
720
912
  *
721
913
  * @public
722
914
  */
723
- interface ShellCommand {
724
- command: string;
725
- workingDirectory?: string;
915
+ interface GoalResult {
916
+ status: "completed" | "failed" | "paused" | "budget_limited" | "blocked";
917
+ turnsUsed: number;
918
+ /** M55 — tokens summed across the loop (0 when `usage` was absent — fail-open). */
919
+ tokensUsed: number;
920
+ finalResponse: string | undefined;
726
921
  }
727
922
  /**
728
- * Output of a shell command.
923
+ * Return type of {@link import("../internal/local-agent/local-agent.js").LocalAgent.runUntil}.
924
+ * Extracted so the LocalAgent method signature stays a single line (G8 LoC budget).
729
925
  *
730
926
  * @public
731
927
  */
732
- interface ShellOutput {
733
- stdout: string;
734
- stderr: string;
735
- exitCode: number;
736
- }
928
+ type RunUntilIterator = AsyncGenerator<GoalEvent, GoalResult, void>;
737
929
  /**
738
- * Result of a tool invocation. Pairs with the preceding `toolCall` step
739
- * by `callId`. `isError: true` when the tool returned a failure result.
740
- *
741
- * T2.3 — added so `Run.conversation()` surfaces the full interaction
742
- * including tool results (parity with OpenAI Agents `RunResult.new_items`).
930
+ * Per-call configuration for `Agent.runUntil`.
743
931
  *
744
932
  * @public
745
933
  */
746
- interface ToolResult {
747
- callId: string;
748
- name: string;
749
- result: string;
750
- isError: boolean;
934
+ interface GoalOptions {
935
+ /** Hard cap on iterations (safety net against runaway). Default `20`. */
936
+ maxTurns?: number;
937
+ /**
938
+ * M55 — token budget (Codex ext/goal parity, tool.rs:454-465). Sums `run.wait().usage.totalTokens`
939
+ * per turn; on crossing it, the loop stops with status `budget_limited`. Omitted => unlimited (only
940
+ * maxTurns). A missing `usage` never blows the budget (fail-open).
941
+ */
942
+ tokenBudget?: number;
943
+ /** Bail after N consecutive judge parse failures. Default `3` (ADR D121). */
944
+ maxConsecutiveJudgeFailures?: number;
945
+ /** Judge model identifier. Default `"openai/gpt-4o-mini"` (ADR D119). */
946
+ judgeModel?: string;
947
+ /** Override env for the judge auxiliary agent. Default `OPENROUTER_API_KEY` (EC-A). */
948
+ judgeApiKey?: string;
949
+ /**
950
+ * M80 — the model of the DRIVEN agent, the basis for deriving the judge when `judgeModel` is
951
+ * omitted.
952
+ *
953
+ * It exists because the fixed default (`openai/gpt-4o-mini`) only resolves on OpenRouter: an
954
+ * Anthropic key gives 404, an OAuth bearer gives 401, and the goal burned 3 turns before failing
955
+ * with a misleading reason. A judge running on the chat's own model works wherever chat works.
956
+ */
957
+ agentModel?: string;
958
+ /** Optional subgoals fed to the judge prompt. */
959
+ subgoals?: string[];
960
+ /**
961
+ * Cancel mid-loop via `AbortController.signal`. The generator yields
962
+ * a `status_change: paused` event and returns at the next turn
963
+ * boundary (ADR D117).
964
+ */
965
+ signal?: AbortSignal;
751
966
  }
967
+
752
968
  /**
753
- * A single step inside an agent turn, discriminated by `type`: an assistant message, a tool call, the
754
- * tool result that pairs with it, or a thinking block.
969
+ * Owner: `types/` (2 of 2 importers: conversation.ts, updates.ts). The only module in this folder
970
+ * whose owner IS the layer — it exists to break a type-only cycle BETWEEN two of its siblings, so
971
+ * pointing it at a subsystem would name something that does not use it.
755
972
  *
756
- * It reaches a caller by two routes that are NOT the same set. `Run.conversation()` returns the
757
- * accumulated steps of a finished turn and includes `thinkingMessage`. `SendOptions.onStep` fires
758
- * live while the turn runs and emits `assistantMessage`, `toolCall` and `toolResult` — but never
759
- * `thinkingMessage`, which the loop builds only into the accumulated conversation. A UI that wants
760
- * reasoning as it happens should read the `thinking-delta` / `thinking-completed` variants of
761
- * `InteractionUpdate` through `onDelta` instead.
762
- *
763
- * `toolCall` and its `toolResult` arrive as an ordered pair matched by `callId`; a call whose result
764
- * never came back has no `toolResult` step, so do not assume they alternate. Where a
765
- * `thinkingMessage` exists it precedes the `assistantMessage` of the same turn — that is the order
766
- * the provider requires of the message the block belongs to, not a presentation choice.
973
+ * Type-leaf — base message types shared between `conversation.ts` and
974
+ * `updates.ts`. Extracted to break LOW type-only cycle #6 (audit
975
+ * `architecture-output/final_report.md`) per plan arch-review-fixes-2026-06-06
976
+ * § Phase 4 / T4.1 (D438).
767
977
  *
768
- * @public
769
- */
770
- type ConversationStep = {
771
- type: "assistantMessage";
772
- message: AssistantMessage;
773
- } | {
774
- type: "toolCall";
775
- message: ToolCall;
776
- } | {
777
- type: "toolResult";
778
- message: ToolResult;
779
- } | {
780
- type: "thinkingMessage";
781
- message: ThinkingMessage;
782
- };
783
- /**
784
- * Agent turn: user message + assistant/tool/thinking steps.
978
+ * Public surface unchanged — `types/conversation.ts` re-exports `UserMessage`
979
+ * from this leaf so `import type { UserMessage } from "@theokit/sdk"` keeps
980
+ * resolving.
785
981
  *
786
982
  * @public
787
983
  */
788
- interface AgentConversationTurn {
789
- userMessage?: UserMessage;
790
- steps: ConversationStep[];
791
- }
792
984
  /**
793
- * Shell turn: a command and its output.
985
+ * User-authored message in a conversation history.
794
986
  *
795
987
  * @public
796
988
  */
797
- interface ShellConversationTurn {
798
- shellCommand?: ShellCommand;
799
- shellOutput?: ShellOutput;
989
+ interface UserMessage {
990
+ text: string;
800
991
  }
992
+
801
993
  /**
802
- * Structured per-turn view of a run.
994
+ * Owner: `internal/agent-loop/` (1 of 1 importers). Derived from the import graph, not declared —
995
+ * `tests/lint/types-name-their-owner.test.ts` re-derives it.
803
996
  *
804
- * @public
805
997
  */
806
- type ConversationTurn = {
807
- type: "agentConversationTurn";
808
- turn: AgentConversationTurn;
809
- } | {
810
- type: "shellConversationTurn";
811
- turn: ShellConversationTurn;
812
- };
813
998
 
814
999
  /**
815
- * Owner: `sandbox/` (1 of 2 importers). Derived from the import graph, not
816
- * declared — `tests/lint/types-name-their-owner.test.ts` re-derives it.
817
- *
818
- * Child-process environment policy contract (#54).
819
- *
820
- * The DIP-correct home for the `EnvPolicy` contract type: the domain `types/`
821
- * layer owns the contract, and the application-layer implementation
822
- * (`internal/runtime/lifecycle/env-policy.ts`) re-exports it for back-compat
823
- * while owning the runtime logic (`resolveChildEnv`, secret patterns, …).
824
- *
825
- * Modes:
826
- * - `inherit-scrubbed` (DEFAULT) — inherit all parent vars EXCEPT secret-like
827
- * names (`*KEY*`, `*SECRET*`, `*TOKEN*`, `*PASSWORD*`, `*_AUTH*`). Non-breaking:
828
- * existing spawns keep every non-secret var; only secrets stop leaking.
829
- * - `core` — inherit ONLY a safe base allowlist (PATH/HOME/…); strongest scrub.
830
- * - `all` — explicit opt-out: inherit everything, secrets included.
1000
+ * Single tool call event. The internal `args` and `result` shapes are NOT stable.
831
1001
  *
832
1002
  * @public
833
1003
  */
834
- type EnvPolicy = "inherit-scrubbed" | "core" | "all";
835
-
1004
+ interface ToolCall {
1005
+ callId: string;
1006
+ name: string;
1007
+ args?: unknown;
1008
+ result?: unknown;
1009
+ }
836
1010
  /**
837
- * Owner: `internal/mcp/` (2 of 5 importers). Derived from the import graph, not declared —
838
- * `tests/lint/types-name-their-owner.test.ts` re-derives it.
1011
+ * Incremental text token from the assistant.
839
1012
  *
1013
+ * @public
840
1014
  */
841
-
1015
+ interface TextDeltaUpdate {
1016
+ type: "text-delta";
1017
+ text: string;
1018
+ }
842
1019
  /**
843
- * MCP server configuration accepted by `Agent.create()` and `agent.send()`.
1020
+ * Incremental reasoning token.
844
1021
  *
845
1022
  * @public
846
1023
  */
847
- type McpStdioServerConfig = {
848
- type?: "stdio";
849
- command: string;
850
- args?: string[];
851
- env?: Record<string, string>;
852
- /** Local agents only. Cloud rejects this field. */
853
- cwd?: string;
854
- /**
855
- * #59 — per-request timeout in ms. A request that gets no reply within this
856
- * window rejects with a typed `NetworkError` (`code: "mcp_timeout"`) instead
857
- * of hanging the agent loop forever. Default 30_000.
858
- */
859
- requestTimeoutMs?: number;
860
- /**
861
- * #54 — env inherit/scrub policy for the spawned MCP server process. Defaults
862
- * to `"inherit-scrubbed"` (drop secret-like host vars: `*KEY*`/`*SECRET*`/
863
- * `*TOKEN*`/`*PASSWORD*`/`*_AUTH*`/…) so a third-party MCP server binary cannot
864
- * exfiltrate host secrets via the environment. `env` above is merged AFTER the
865
- * policy and always wins. Pass `"all"` to restore full inheritance.
866
- */
867
- envPolicy?: EnvPolicy;
868
- };
1024
+ interface ThinkingDeltaUpdate {
1025
+ type: "thinking-delta";
1026
+ text: string;
1027
+ }
869
1028
  /**
870
- * OAuth-style auth bundle for HTTP/SSE MCP servers.
1029
+ * Emitted when a reasoning block completes.
871
1030
  *
872
1031
  * @public
873
1032
  */
874
- interface McpAuthConfig {
875
- CLIENT_ID: string;
876
- CLIENT_SECRET?: string;
877
- scopes?: string[];
878
- /**
879
- * OAuth 2.1 PKCE flow configuration (ADR D41, v1.2+). When present, the
880
- * SDK runs the PKCE flow on first use and stores tokens via keychain or
881
- * file. Without this, the SDK relies on `CLIENT_SECRET` + manual headers.
882
- */
883
- oauth?: McpOAuthConfig;
1033
+ interface ThinkingCompletedUpdate {
1034
+ type: "thinking-completed";
1035
+ thinkingDurationMs: number;
884
1036
  }
885
1037
  /**
886
- * OAuth 2.1 PKCE flow descriptor. See ADR D41.
1038
+ * Tool call started — args committed.
887
1039
  *
888
1040
  * @public
889
1041
  */
890
- interface McpOAuthConfig {
891
- /** Authorization endpoint (e.g. https://api.notion.com/v1/oauth/authorize). */
892
- authorizationEndpoint: string;
893
- /** Token endpoint (e.g. https://api.notion.com/v1/oauth/token). */
894
- tokenEndpoint: string;
895
- /** Where the OAuth `code` is received. */
896
- redirectMode: "manual" | "localhost";
897
- /** Localhost callback port (0 = random free port, default). */
898
- localhostPort?: number;
899
- /** Flow timeout in ms (default 300_000 = 5min). */
900
- timeoutMs?: number;
1042
+ interface ToolCallStartedUpdate {
1043
+ type: "tool-call-started";
1044
+ callId: string;
1045
+ toolCall: ToolCall;
1046
+ modelCallId: string;
901
1047
  }
902
1048
  /**
903
- * HTTP or SSE MCP server.
1049
+ * Tool call arguments streaming in incrementally.
904
1050
  *
905
1051
  * @public
906
1052
  */
907
- type McpHttpServerConfig = {
908
- type?: "http" | "sse";
909
- url: string;
910
- /** Passed through. `Authorization` works here. */
911
- headers?: Record<string, string>;
912
- auth?: McpAuthConfig;
913
- /**
914
- * #59 — per-request timeout in ms, enforced via `AbortSignal.timeout`. A
915
- * fetch that does not respond within this window rejects with a typed
916
- * `NetworkError` (`code: "mcp_timeout"`). Default 30_000.
917
- */
918
- requestTimeoutMs?: number;
919
- };
1053
+ interface PartialToolCallUpdate {
1054
+ type: "partial-tool-call";
1055
+ callId: string;
1056
+ toolCall: ToolCall;
1057
+ modelCallId: string;
1058
+ }
920
1059
  /**
921
- * Union of MCP server configs.
1060
+ * Tool call completed.
922
1061
  *
923
1062
  * @public
924
1063
  */
925
- type McpServerConfig = McpStdioServerConfig | McpHttpServerConfig;
926
-
1064
+ interface ToolCallCompletedUpdate {
1065
+ type: "tool-call-completed";
1066
+ callId: string;
1067
+ toolCall: ToolCall;
1068
+ modelCallId: string;
1069
+ }
927
1070
  /**
928
- * Owner: `internal/agent-loop/` (4 of 16 importers). Derived from the import graph, not declared —
929
- * `tests/lint/types-name-their-owner.test.ts` re-derives it.
1071
+ * Token count delta for usage tracking.
930
1072
  *
1073
+ * @public
931
1074
  */
932
-
1075
+ interface TokenDeltaUpdate {
1076
+ type: "token-delta";
1077
+ tokens: number;
1078
+ }
933
1079
  /**
934
- * Tool invocation block emitted by the assistant.
1080
+ * Conversation step started.
935
1081
  *
936
1082
  * @public
937
1083
  */
938
- interface ToolUseBlock {
939
- type: "tool_use";
940
- id: string;
941
- name: string;
942
- /** Tool args are not part of the stable schema. Treat as unknown and parse defensively. */
943
- input: unknown;
1084
+ interface StepStartedUpdate {
1085
+ type: "step-started";
1086
+ stepId: number;
944
1087
  }
945
1088
  /**
946
- * Init metadata. Emitted once at the start of a run.
1089
+ * Conversation step completed.
947
1090
  *
948
1091
  * @public
949
1092
  */
950
- interface SDKSystemMessage {
951
- type: "system";
952
- subtype?: "init";
953
- agent_id: string;
954
- run_id: string;
955
- model?: ModelSelection;
956
- tools?: string[];
1093
+ interface StepCompletedUpdate {
1094
+ type: "step-completed";
1095
+ stepId: number;
1096
+ stepDurationMs: number;
957
1097
  }
958
1098
  /**
959
- * Echo of the user prompt for this run.
1099
+ * Turn ended with usage summary.
960
1100
  *
961
1101
  * @public
962
1102
  */
963
- interface SDKUserMessageEvent {
964
- type: "user";
965
- agent_id: string;
966
- run_id: string;
967
- message: {
968
- role: "user";
969
- content: TextBlock[];
1103
+ interface TurnEndedUpdate {
1104
+ type: "turn-ended";
1105
+ usage?: {
1106
+ inputTokens: number;
1107
+ outputTokens: number;
1108
+ cacheReadTokens: number;
1109
+ cacheWriteTokens: number;
970
1110
  };
971
1111
  }
972
1112
  /**
973
- * Model text output for this run.
1113
+ * User message appended to the conversation.
974
1114
  *
975
1115
  * @public
976
1116
  */
977
- interface SDKAssistantMessage {
978
- type: "assistant";
979
- agent_id: string;
980
- run_id: string;
981
- message: {
982
- role: "assistant";
983
- content: Array<TextBlock | ToolUseBlock>;
984
- };
1117
+ interface UserMessageAppendedUpdate {
1118
+ type: "user-message-appended";
1119
+ userMessage: UserMessage;
985
1120
  }
986
1121
  /**
987
- * Reasoning content.
1122
+ * A conversation summary produced during a run, delivered through `SendOptions.onDelta`.
1123
+ *
1124
+ * Nothing in this package emits it. It is declared so an exhaustive `switch` over
1125
+ * {@link InteractionUpdate} compiles, and so a runtime that does produce summaries has a typed
1126
+ * channel — do not build a feature that waits on it against the local runtime.
988
1127
  *
989
1128
  * @public
990
1129
  */
991
- interface SDKThinkingMessage {
992
- type: "thinking";
993
- agent_id: string;
994
- run_id: string;
995
- text: string;
996
- thinking_duration_ms?: number;
997
- /**
998
- * theokit#122 — the provider's cryptographic signature for this thinking block, when it issued
999
- * one. Anthropic requires a resumed conversation to replay each thinking block WITH its
1000
- * signature; without it the next request fails with `400 "thinking blocks cannot be modified"`,
1001
- * which made an extended-thinking session unresumable.
1130
+ interface SummaryUpdate {
1131
+ type: "summary";
1132
+ summary: string;
1133
+ }
1134
+ /**
1135
+ * Opens the bracket around a {@link SummaryUpdate}, for a UI that wants to show a pending state
1136
+ * before the summary text exists. Paired with {@link SummaryCompletedUpdate}.
1137
+ *
1138
+ * Like the summary variants around it, nothing in this package emits it.
1139
+ *
1140
+ * @public
1141
+ */
1142
+ interface SummaryStartedUpdate {
1143
+ type: "summary-started";
1144
+ }
1145
+ /**
1146
+ * Closes the bracket opened by {@link SummaryStartedUpdate}. Carries no payload — the summary text
1147
+ * itself arrives as {@link SummaryUpdate}.
1148
+ *
1149
+ * Like the summary variants around it, nothing in this package emits it.
1150
+ *
1151
+ * @public
1152
+ */
1153
+ interface SummaryCompletedUpdate {
1154
+ type: "summary-completed";
1155
+ }
1156
+ /**
1157
+ * Incremental output from a shell command running inside a run.
1158
+ *
1159
+ * `event` is an untyped bag on purpose: this package neither produces nor narrows it, so a consumer
1160
+ * that receives one should treat it as unvalidated input and check for the fields it needs rather
1161
+ * than casting. As with the summary variants, nothing here emits this — it exists so the
1162
+ * {@link InteractionUpdate} union covers a runtime that does.
1163
+ *
1164
+ * @public
1165
+ */
1166
+ interface ShellOutputDeltaUpdate {
1167
+ type: "shell-output-delta";
1168
+ event: Record<string, unknown>;
1169
+ }
1170
+ /**
1171
+ * Lowest-level raw update from a run. Pass `onDelta` to `agent.send()` to
1172
+ * consume these. Finer-grained than `SDKMessage` events.
1173
+ *
1174
+ * @public
1175
+ */
1176
+ type InteractionUpdate = TextDeltaUpdate | ThinkingDeltaUpdate | ThinkingCompletedUpdate | ToolCallStartedUpdate | ToolCallCompletedUpdate | PartialToolCallUpdate | TokenDeltaUpdate | StepStartedUpdate | StepCompletedUpdate | TurnEndedUpdate | UserMessageAppendedUpdate | SummaryUpdate | SummaryStartedUpdate | SummaryCompletedUpdate | ShellOutputDeltaUpdate;
1177
+
1178
+ /**
1179
+ * Owner: `internal/agent-loop/` (3 of 11 importers). Derived from the import graph, not declared —
1180
+ * `tests/lint/types-name-their-owner.test.ts` re-derives it.
1181
+ *
1182
+ * SE2 — typed runtime EVENT stream, ADDITIVE to the `SDKMessage` content stream.
1183
+ *
1184
+ * `Run.stream()` yields `SDKMessage`s (the conversation content). `RunEvent`s are
1185
+ * out-of-band runtime-OBSERVABILITY signals — the model's content is unaffected —
1186
+ * delivered opt-in via `SendOptions.onRunEvent`. Discriminate on `type`. Mirrors
1187
+ * the Anthropic `SDKMessage`-union approach (rate-limit, permission-denied, task
1188
+ * lifecycle, compaction boundary).
1189
+ *
1190
+ * The union is the forward-compatible CONTRACT (discriminate exhaustively). The
1191
+ * runtime EMITS every variant end-to-end: `tool_progress` + `permission_denied`
1192
+ * (agent-loop tool-dispatch seam), `rate_limit` (pool-aware LLM client 429 retry),
1193
+ * `compact_boundary` (session auto-compaction), and `task_*` (opt-in bridge from a
1194
+ * `Task.submit({ onRunEvent })` task's lifecycle). A consumer switching on `type`
1195
+ * sees the real signal.
1196
+ *
1197
+ * @public
1198
+ */
1199
+ type RunEvent = RunToolProgressEvent | RunRateLimitEvent | RunPermissionDeniedEvent | RunTaskStartedEvent | RunTaskUpdatedEvent | RunTaskCompletedEvent | RunCompactBoundaryEvent | RunCompactionFallbackEvent | RunTripwireEvent | RunCompletionCheckEvent | RunMcpServerFailedEvent | RunMcpServerReadyEvent | RunMemoryDegradedEvent;
1200
+ /**
1201
+ * theokit#188 — an MCP server was configured but its tools could not be listed, so NONE of its
1202
+ * tools exist for this run.
1203
+ *
1204
+ * The failure was always caught (`safeListTools` returns `[]` so one broken server cannot take the
1205
+ * turn down) and always DIAGNOSED — to `diag()`, i.e. the SDK's stderr. Nothing reached the
1206
+ * consumer, so a UI listing configured servers could show one as present while every tool it
1207
+ * provides had silently vanished. Degrading gracefully is right; degrading INVISIBLY is not.
1208
+ *
1209
+ * Emitted once per failing server per run, on the same catch path that already had both the name
1210
+ * and the reason.
1211
+ */
1212
+ interface RunMcpServerFailedEvent {
1213
+ readonly type: "mcp_server_failed";
1214
+ /** The server as named in the MCP configuration, so the consumer can match it to what it lists. */
1215
+ readonly serverName: string;
1216
+ /** Why listing failed — a spawn error, a handshake timeout, a protocol error. */
1217
+ readonly message: string;
1218
+ }
1219
+ /**
1220
+ * usetheokit/theokit#426 — an MCP server came up, and these are the tools it delivered.
1221
+ *
1222
+ * The sibling of {@link RunMcpServerFailedEvent}, emitted from the same function, on the other
1223
+ * branch. Without it a consumer could see what was CONFIGURED and what BROKE, and could not tell a
1224
+ * server that came up with twelve tools from one that came up with none — which is exactly the case
1225
+ * an operator opens a server-status panel to find. `tools: []` on a healthy server is a real and
1226
+ * previously unreportable state.
1227
+ *
1228
+ * An EVENT rather than a getter, because the state is scoped to the run: with
1229
+ * `mcpLifecycle: "run"` a server may not exist by the time anyone asks, so a getter would have to
1230
+ * answer about something already gone. This says what was true when the run started.
1231
+ *
1232
+ * Emitted once per successfully-listed server per run.
1233
+ */
1234
+ interface RunMcpServerReadyEvent {
1235
+ readonly type: "mcp_server_ready";
1236
+ /** The server as named in the MCP configuration — the key a consumer already lists it under. */
1237
+ readonly serverName: string;
1238
+ /**
1239
+ * The tool names the server reported, as IT names them.
1002
1240
  *
1003
- * Absent for providers that stream reasoning text unsigned (the OpenAI-compatible wire).
1241
+ * Not the `mcp_<server>_<tool>` form the model sees: that spelling is sanitized for the provider,
1242
+ * and a consumer matching it back to a server's own documentation would have to undo the mangling.
1243
+ */
1244
+ readonly tools: readonly string[];
1245
+ }
1246
+ /**
1247
+ * SE24 — a guardrail processor called `abort()`; the run stops with a tripwire.
1248
+ * Delivered via {@link SendOptions.onRunEvent} (mirrors the `RunResult.tripwire`
1249
+ * surfaced on `wait()`).
1250
+ */
1251
+ interface RunTripwireEvent {
1252
+ readonly type: "tripwire";
1253
+ readonly reason: string;
1254
+ readonly processorId: string;
1255
+ }
1256
+ /** A tool call is being dispatched (before its result). */
1257
+ interface RunToolProgressEvent {
1258
+ readonly type: "tool_progress";
1259
+ readonly toolName: string;
1260
+ readonly toolCallId: string;
1261
+ }
1262
+ /** The provider returned a rate-limit (HTTP 429); the loop will back off + retry. */
1263
+ interface RunRateLimitEvent {
1264
+ readonly type: "rate_limit";
1265
+ /** Retry attempt number (1-based) about to be delayed. */
1266
+ readonly attempt: number;
1267
+ /** Delay in ms before the retry, when the provider/policy supplied one. */
1268
+ readonly retryAfterMs?: number;
1269
+ }
1270
+ /**
1271
+ * A tool call was DENIED before dispatch — by the permission gate/plugin (SE1),
1272
+ * an operator file-hook `preToolUse`, or the fork tool-whitelist. `source`
1273
+ * discriminates which. `toolCallId` joins the event to the tool-call log.
1274
+ */
1275
+ interface RunPermissionDeniedEvent {
1276
+ readonly type: "permission_denied";
1277
+ readonly toolName: string;
1278
+ readonly toolCallId: string;
1279
+ /** Which layer blocked the call. */
1280
+ readonly source: "plugin" | "file_hook" | "fork_whitelist";
1281
+ /** The rejection message surfaced to the model. */
1282
+ readonly message: string;
1283
+ }
1284
+ /** A background task/subagent started. */
1285
+ interface RunTaskStartedEvent {
1286
+ readonly type: "task_started";
1287
+ readonly taskId: string;
1288
+ readonly description?: string;
1289
+ }
1290
+ /** A background task/subagent changed state. */
1291
+ interface RunTaskUpdatedEvent {
1292
+ readonly type: "task_updated";
1293
+ readonly taskId: string;
1294
+ readonly status: string;
1295
+ }
1296
+ /** A background task/subagent finished. */
1297
+ interface RunTaskCompletedEvent {
1298
+ readonly type: "task_completed";
1299
+ readonly taskId: string;
1300
+ readonly status: "completed" | "failed" | "stopped";
1301
+ }
1302
+ /**
1303
+ * SE34 — the per-send completion check (`isTaskComplete`) produced a verdict.
1304
+ * Emitted once, after a finished run's reply is judged against
1305
+ * {@link SendOptions.completionCheck}. Distinct from `task_completed` (which is
1306
+ * background-task/subagent lifecycle). Mirrors {@link RunResult.completionCheck}.
1307
+ */
1308
+ interface RunCompletionCheckEvent {
1309
+ readonly type: "completion_check";
1310
+ readonly complete: boolean;
1311
+ readonly reason: string;
1312
+ }
1313
+ /** The conversation crossed a compaction boundary (history was summarized). */
1314
+ interface RunCompactBoundaryEvent {
1315
+ readonly type: "compact_boundary";
1316
+ readonly trigger: "manual" | "auto";
1317
+ /** Token count before compaction, when known. */
1318
+ readonly preTokens?: number;
1319
+ }
1320
+ /**
1321
+ * M77 — auto-compaction is budgeting against a FLOOR, because neither the catalog nor the caller
1322
+ * supplied a context window for this model.
1323
+ *
1324
+ * The prior behaviour was to disable auto-compaction entirely and write one line to stderr per
1325
+ * process. That is fail-OPEN: the conversation grows until the provider rejects it. This event exists
1326
+ * so a surface can say "I am running without a real budget" instead of the user discovering it at the
1327
+ * moment of failure.
1328
+ *
1329
+ * Not emitted when the window came from the catalog (the normal path) or from an explicit caller
1330
+ * override (the caller already knows).
1331
+ */
1332
+ interface RunCompactionFallbackEvent {
1333
+ readonly type: "compaction_fallback";
1334
+ /** The model whose window is unknown — what the user needs to fix in configuration. */
1335
+ readonly model: string;
1336
+ /** The floor being budgeted against, after the safety margin. */
1337
+ readonly window: number;
1338
+ }
1339
+ /**
1340
+ * A memory stage failed and the run continued without it.
1341
+ *
1342
+ * The same shape of gap {@link RunMcpServerFailedEvent} closed for MCP, in the module next door.
1343
+ * `initLoopContext` had three bare `catch { <field> = <empty> }` blocks: an init failure meant no
1344
+ * memory tool was registered, a `buildTools` failure meant no provider tools, and a `runActivePass`
1345
+ * failure meant no recalled context in the system prompt. The agent then answered without the memory
1346
+ * it was configured with, and nothing recorded it — not stderr, not this sink, not the span in scope.
1347
+ *
1348
+ * Degrading to a working agent is the right BEHAVIOUR. This event exists because the degradation was
1349
+ * unobservable, so a host UI showed a healthy run.
1350
+ *
1351
+ * Emitted once per failing stage per run.
1352
+ *
1353
+ * @public
1354
+ */
1355
+ interface RunMemoryDegradedEvent {
1356
+ readonly type: "memory_degraded";
1357
+ /** Which stage failed: `init`, `buildTools`, or `activePass`. */
1358
+ readonly stage: string;
1359
+ /** Why it failed, as the provider reported it. */
1360
+ readonly message: string;
1361
+ }
1362
+ /**
1363
+ * Receives every {@link RunEvent} a run emits, in emission order.
1364
+ *
1365
+ * Wired through `onRunEvent` on the run options. The sink is observability, never control flow: it
1366
+ * cannot cancel, alter, or delay the run, and {@link emitRunEvent} swallows anything it throws — a
1367
+ * broken sink degrades what you can see, never what the agent does.
1368
+ *
1369
+ * Synchronous by signature, so a slow sink slows the run. Hand work off rather than awaiting inside
1370
+ * it; returning a promise here would be ignored, not awaited.
1371
+ *
1372
+ * @public
1373
+ */
1374
+ type RunEventSink = (event: RunEvent) => void;
1375
+
1376
+ /**
1377
+ * Owner: `internal/agent-loop/` (4 of 8 importers). Derived from the import graph, not
1378
+ * declared — `tests/lint/types-name-their-owner.test.ts` re-derives it.
1379
+ *
1380
+ */
1381
+
1382
+ /**
1383
+ * Plain assistant message in a conversation history.
1384
+ *
1385
+ * @public
1386
+ */
1387
+ interface AssistantMessage {
1388
+ text: string;
1389
+ }
1390
+ /**
1391
+ * Reasoning step in a conversation history.
1392
+ *
1393
+ * @public
1394
+ */
1395
+ interface ThinkingMessage {
1396
+ text: string;
1397
+ thinkingDurationMs?: number;
1398
+ /**
1399
+ * theokit#122 — the provider's cryptographic signature for this thinking block, when it issued
1400
+ * one. Persisted with the block so a resumed conversation can replay it byte-identically;
1401
+ * Anthropic rejects a modified or unsigned thinking block with
1402
+ * `400 "thinking blocks cannot be modified"`.
1004
1403
  */
1005
1404
  signature?: string;
1006
1405
  }
1007
1406
  /**
1008
- * Tool invocation lifecycle event. Emitted at start with `args`, then again on
1009
- * completion with `result`.
1010
- *
1011
- * Tool `args` and `result` are NOT part of the stable schema — treat as unknown.
1407
+ * Shell command executed during a run.
1012
1408
  *
1013
1409
  * @public
1014
1410
  */
1015
- interface SDKToolUseMessage {
1016
- type: "tool_call";
1017
- agent_id: string;
1018
- run_id: string;
1019
- call_id: string;
1020
- name: string;
1021
- status: "running" | "completed" | "error";
1022
- args?: unknown;
1023
- result?: unknown;
1024
- truncated?: {
1025
- args?: boolean;
1026
- result?: boolean;
1027
- };
1411
+ interface ShellCommand {
1412
+ command: string;
1413
+ workingDirectory?: string;
1028
1414
  }
1029
1415
  /**
1030
- * Cloud run lifecycle transitions.
1416
+ * Output of a shell command.
1031
1417
  *
1032
1418
  * @public
1033
1419
  */
1034
- interface SDKStatusMessage {
1035
- type: "status";
1036
- agent_id: string;
1037
- run_id: string;
1038
- status: "CREATING" | "RUNNING" | "FINISHED" | "ERROR" | "CANCELLED" | "EXPIRED";
1039
- message?: string;
1420
+ interface ShellOutput {
1421
+ stdout: string;
1422
+ stderr: string;
1423
+ exitCode: number;
1040
1424
  }
1041
1425
  /**
1042
- * Task-level milestones and summaries.
1426
+ * Result of a tool invocation. Pairs with the preceding `toolCall` step
1427
+ * by `callId`. `isError: true` when the tool returned a failure result.
1428
+ *
1429
+ * T2.3 — added so `Run.conversation()` surfaces the full interaction
1430
+ * including tool results (parity with OpenAI Agents `RunResult.new_items`).
1043
1431
  *
1044
1432
  * @public
1045
1433
  */
1046
- interface SDKTaskMessage {
1047
- type: "task";
1048
- agent_id: string;
1049
- run_id: string;
1050
- status?: string;
1051
- text?: string;
1434
+ interface ToolResult {
1435
+ callId: string;
1436
+ name: string;
1437
+ result: string;
1438
+ isError: boolean;
1052
1439
  }
1053
1440
  /**
1054
- * Awaiting user input or approval.
1441
+ * A single step inside an agent turn, discriminated by `type`: an assistant message, a tool call, the
1442
+ * tool result that pairs with it, or a thinking block.
1443
+ *
1444
+ * It reaches a caller by two routes that are NOT the same set. `Run.conversation()` returns the
1445
+ * accumulated steps of a finished turn and includes `thinkingMessage`. `SendOptions.onStep` fires
1446
+ * live while the turn runs and emits `assistantMessage`, `toolCall` and `toolResult` — but never
1447
+ * `thinkingMessage`, which the loop builds only into the accumulated conversation. A UI that wants
1448
+ * reasoning as it happens should read the `thinking-delta` / `thinking-completed` variants of
1449
+ * `InteractionUpdate` through `onDelta` instead.
1450
+ *
1451
+ * `toolCall` and its `toolResult` arrive as an ordered pair matched by `callId`; a call whose result
1452
+ * never came back has no `toolResult` step, so do not assume they alternate. Where a
1453
+ * `thinkingMessage` exists it precedes the `assistantMessage` of the same turn — that is the order
1454
+ * the provider requires of the message the block belongs to, not a presentation choice.
1055
1455
  *
1056
1456
  * @public
1057
1457
  */
1058
- interface SDKRequestMessage {
1059
- type: "request";
1060
- agent_id: string;
1061
- run_id: string;
1062
- request_id: string;
1063
- }
1458
+ type ConversationStep = {
1459
+ type: "assistantMessage";
1460
+ message: AssistantMessage;
1461
+ } | {
1462
+ type: "toolCall";
1463
+ message: ToolCall;
1464
+ } | {
1465
+ type: "toolResult";
1466
+ message: ToolResult;
1467
+ } | {
1468
+ type: "thinkingMessage";
1469
+ message: ThinkingMessage;
1470
+ };
1064
1471
  /**
1065
- * Partial object emitted during `Agent.streamObject<T>` streaming (ADR D45).
1066
- * `partial` is `DeepPartial<z.infer<T>>` at the typed iterator level but
1067
- * erased to `unknown` here because SDKMessage union is non-generic.
1472
+ * Agent turn: user message + assistant/tool/thinking steps.
1068
1473
  *
1069
1474
  * @public
1070
1475
  */
1071
- interface SDKObjectDelta {
1072
- type: "object_delta";
1073
- agent_id: string;
1074
- run_id: string;
1075
- partial: unknown;
1076
- attempt: number;
1476
+ interface AgentConversationTurn {
1477
+ userMessage?: UserMessage;
1478
+ steps: ConversationStep[];
1077
1479
  }
1078
1480
  /**
1079
- * Discriminated union of all stream events. Discriminate on `type`.
1481
+ * Shell turn: a command and its output.
1080
1482
  *
1081
- * All events include `agent_id` and `run_id`.
1483
+ * @public
1484
+ */
1485
+ interface ShellConversationTurn {
1486
+ shellCommand?: ShellCommand;
1487
+ shellOutput?: ShellOutput;
1488
+ }
1489
+ /**
1490
+ * Structured per-turn view of a run.
1082
1491
  *
1083
1492
  * @public
1084
1493
  */
1085
- type SDKMessage = SDKSystemMessage | SDKUserMessageEvent | SDKAssistantMessage | SDKThinkingMessage | SDKToolUseMessage | SDKStatusMessage | SDKTaskMessage | SDKRequestMessage | SDKObjectDelta;
1494
+ type ConversationTurn = {
1495
+ type: "agentConversationTurn";
1496
+ turn: AgentConversationTurn;
1497
+ } | {
1498
+ type: "shellConversationTurn";
1499
+ turn: ShellConversationTurn;
1500
+ };
1086
1501
 
1087
1502
  /**
1088
1503
  * Owner: `internal/budget/` (3 of 8 importers). Derived from the import graph, not declared —
@@ -1168,16 +1583,6 @@ interface ToolResultGuardOptions {
1168
1583
  * @public
1169
1584
  */
1170
1585
  type RunStatus = "running" | "finished" | "error" | "cancelled";
1171
- /**
1172
- * Operations that may or may not be supported on a given {@link Run}, or on
1173
- * its parent agent.
1174
- *
1175
- * Runtime-specific availability — query at runtime with `run.supports(op)` and
1176
- * read the human reason via `run.unsupportedReason(op)`.
1177
- *
1178
- * @public
1179
- */
1180
- type RunOperation = "stream" | "wait" | "cancel" | "conversation" | "listArtifacts" | "downloadArtifact" | "runUntil" | "runToCompletion" | "streamToCompletion" | "fork" | "usePersonality" | "workflow";
1181
1586
  /**
1182
1587
  * Git metadata attached to cloud runs.
1183
1588
  *
@@ -1408,15 +1813,23 @@ type StreamToCompletionResult = RunToCompletionResult;
1408
1813
  * Structured error attached to a {@link RunResult} when the underlying run
1409
1814
  * transitioned to `"error"` status. `message` is always present; `code` is
1410
1815
  * a stable identifier suitable for branching (e.g. `"llm_4xx"`,
1411
- * `"tool_dispatch_failed"`, `"mcp_init_failed"`); `cause` is the raw error
1412
- * for further inspection when available.
1816
+ * `"tool_dispatch_failed"`, `"mcp_init_failed"`); `cause` is the typed
1817
+ * {@link TheokitAgentError} behind the failure, so `instanceof` works on it
1818
+ * directly (e.g. `result.error?.cause instanceof AuthenticationError`).
1819
+ *
1820
+ * A failure whose original cause was missing or not an SDK error carries an
1821
+ * `UnknownAgentError` with the same message and code, holding the original
1822
+ * value at its own `cause`.
1823
+ *
1824
+ * With `AgentOptions.throwOnError`, `run.wait()` rejects with this same `cause`
1825
+ * instead of resolving.
1413
1826
  *
1414
1827
  * @public
1415
1828
  */
1416
1829
  interface RunErrorDetail {
1417
1830
  message: string;
1418
1831
  code?: string;
1419
- cause?: unknown;
1832
+ cause?: TheokitAgentError;
1420
1833
  }
1421
1834
  /**
1422
1835
  * Dimensions of an inline image attachment.
@@ -1810,4 +2223,338 @@ interface GenerateRunResult<O> {
1810
2223
  };
1811
2224
  }
1812
2225
 
1813
- export type { RunToolProgressEvent as $, AgentConversationTurn as A, RunCompletionCheckEvent as B, CustomTool as C, DoomLoopThresholds as D, EnvPolicy as E, RunErrorDetail as F, GenerateOptions as G, RunEvent as H, ImageBlock as I, RunGitInfo as J, RunMemoryDegradedEvent as K, RunOperation as L, ModelSelection as M, RunPermissionDeniedEvent as N, OutputProcessorContext as O, Processor as P, RunRateLimitEvent as Q, RunResult as R, SDKMessage as S, ToolResultContentBlock as T, RunStatus as U, RunTaskCompletedEvent as V, RunTaskStartedEvent as W, RunTaskUpdatedEvent as X, RunTimelineEvent as Y, RunToCompletionOptions as Z, RunToCompletionResult as _, McpServerConfig as a, RunTripwireEvent as a0, SDKAssistantMessage as a1, SDKImage as a2, SDKImageDimension as a3, SDKObjectDelta as a4, SDKRequestMessage as a5, SDKStatusMessage as a6, SDKSystemMessage as a7, SDKTaskMessage as a8, SDKThinkingMessage as a9, ToolResultGuardOptions as aA, ToolUseBlock as aB, TurnEndedUpdate as aC, UserMessage as aD, UserMessageAppendedUpdate as aE, SDKToolUseMessage as aa, SDKUserMessage as ab, SDKUserMessageEvent as ac, SendOptions as ad, ShellCommand as ae, ShellConversationTurn as af, ShellOutput as ag, ShellOutputDeltaUpdate as ah, StepCompletedUpdate as ai, StepStartedUpdate as aj, StreamToCompletionResult as ak, SummaryCompletedUpdate as al, SummaryStartedUpdate as am, SummaryUpdate as an, TextBlock as ao, TextDeltaUpdate as ap, ThinkingCompletedUpdate as aq, ThinkingDeltaUpdate as ar, ThinkingMessage as as, TokenDeltaUpdate as at, TokenUsage as au, ToolCall as av, ToolCallCompletedUpdate as aw, ToolCallStartedUpdate as ax, ToolContextMessage as ay, ToolResult as az, Run as b, PermissionMode as c, RunEventSink as d, AssistantMessage as e, CompletionCheck as f, CompletionCheckResult as g, ConversationStep as h, ConversationTurn as i, CostBreakdown as j, CostSource as k, CostStatus as l, GenerateRunResult as m, InputProcessorContext as n, InteractionUpdate as o, McpAuthConfig as p, McpHttpServerConfig as q, McpOAuthConfig as r, McpStdioServerConfig as s, MessageOrigin as t, ModelParameterValue as u, PartialToolCallUpdate as v, ProcessorControls as w, ProcessorTripwire as x, ProcessorViolation as y, RunCompactBoundaryEvent as z };
2226
+ /**
2227
+ * Public skill metadata exposed to the system-prompt resolver. Mirrors the
2228
+ * shape returned by `agent.skills.list()` — name + description only, never
2229
+ * full skill bodies.
2230
+ *
2231
+ * @public
2232
+ */
2233
+ interface SystemPromptSkillRef {
2234
+ name: string;
2235
+ description: string;
2236
+ /**
2237
+ * Where this skill came from: the absolute path to its `SKILL.md` for a skill read from disk,
2238
+ * or the synthetic `inline://<name>` marker `createSkill` stamps on a code-defined one (see
2239
+ * `create-skill.ts`) — there is no third case, so this is populated for every skill `list()`
2240
+ * returns.
2241
+ *
2242
+ * It is the ORIGIN and NOT the body: `list()` stays lean by contract, and a skill's instructions
2243
+ * are reachable only through {@link SDKAgentSkills.get}. What this adds is the answer to
2244
+ * usetheokit/theokit-sdk#524's visibility question — which root a skill came from, so a listing
2245
+ * can show that one arrived from `.claude/skills/` rather than the project's own directory, or
2246
+ * that it was never on disk at all.
2247
+ *
2248
+ * Typed optional rather than required because {@link SystemPromptSkillRef} is the shape any
2249
+ * future skill producer returns, and this SDK should not assert every one of them can name an
2250
+ * origin.
2251
+ */
2252
+ source?: string;
2253
+ }
2254
+ /**
2255
+ * A skill resolved WITH its body, returned by {@link SDKAgentSkills.get}. Unlike
2256
+ * {@link SystemPromptSkillRef}, which carries metadata only, this carries the full
2257
+ * `instructions` — read from the SKILL.md for filesystem skills or the inline
2258
+ * `createSkill` body. @public
2259
+ */
2260
+ interface SDKAgentSkillDetail {
2261
+ name: string;
2262
+ description: string;
2263
+ instructions: string;
2264
+ /** SE21 — supporting documents bundled with the skill (filename → content), when present. */
2265
+ references?: Record<string, string>;
2266
+ }
2267
+ /**
2268
+ * The skill handle exposed as `agent.skills`, present only when project-scoped skills are enabled
2269
+ * (`settingSources: ["project"]`) or `skills.enabled` is set. The property is optional on the agent,
2270
+ * and `undefined` there means skills were never turned on — not that none were found.
2271
+ *
2272
+ * The split between its two methods is the choice it asks of a caller. `list()` returns name and
2273
+ * description only, which is what belongs in a system prompt: it stays cheap and it keeps skill
2274
+ * bodies out of the context window. `get(name)` resolves one skill WITH its `instructions` — the
2275
+ * SKILL.md body for a filesystem skill, the inline body for one built with `createSkill` — and
2276
+ * returns `undefined` when no enabled skill matches that name. Ask for a body only when you are
2277
+ * about to use it.
2278
+ *
2279
+ * @public
2280
+ */
2281
+ interface SDKAgentSkills {
2282
+ list(): Promise<ReadonlyArray<SystemPromptSkillRef>>;
2283
+ /**
2284
+ * SE20 — resolve a skill by name INCLUDING its body (`instructions`). Returns
2285
+ * `undefined` when no enabled skill matches. `list()` stays lean (name +
2286
+ * description); full bodies come only through `get`.
2287
+ */
2288
+ get(name: string): Promise<SDKAgentSkillDetail | undefined>;
2289
+ }
2290
+ /**
2291
+ * Public plugin metadata returned by `agent.plugins.list()`. Mirrors the
2292
+ * `.theokit/plugins/<name>/MANIFEST.json` allow-listed shape; never exposes
2293
+ * raw plugin bodies, credentials, or internal hooks.
2294
+ *
2295
+ * @public
2296
+ */
2297
+ interface SDKPluginMetadata {
2298
+ name: string;
2299
+ description?: string;
2300
+ /**
2301
+ * Absolute path the plugin manifest was read from.
2302
+ *
2303
+ * The runtime has ALWAYS returned this — `agent.plugins.list()` hands back the internal
2304
+ * `PluginMetadata`, whose own docblock says it carries provenance "so callers can audit where the
2305
+ * plugin came from". This type simply did not declare it, so the caller received the field and
2306
+ * the compiler denied it existed. Declaring it is what makes the audit usetheokit/theokit-sdk#524
2307
+ * asks for reachable in typed code.
2308
+ */
2309
+ source?: string;
2310
+ }
2311
+ /**
2312
+ * Public plugin listing handle exposed as `agent.plugins`. Populated when
2313
+ * `settingSources` includes `"plugins"` OR when `plugins.enabled` is set
2314
+ * on the agent options.
2315
+ *
2316
+ * @public
2317
+ */
2318
+ interface SDKAgentPlugins {
2319
+ list(): Promise<ReadonlyArray<SDKPluginMetadata>>;
2320
+ }
2321
+ /**
2322
+ * Artifact produced inside an agent's workspace. Cloud-only.
2323
+ *
2324
+ * @public
2325
+ */
2326
+ interface SDKArtifact {
2327
+ path: string;
2328
+ sizeBytes: number;
2329
+ updatedAt: string;
2330
+ }
2331
+ /**
2332
+ * An operation a consumer may ask an {@link SDKAgent} about via `supports()`.
2333
+ *
2334
+ * Deliberately the members whose availability DIFFERS between runtimes, plus the core ones a caller
2335
+ * may want to assert positively. A union rather than `string` so a typo is a compile error instead
2336
+ * of a silent `false`.
2337
+ *
2338
+ * @public
2339
+ */
2340
+ type AgentOperation = "send" | "generate" | "listArtifacts" | "downloadArtifact" | "runUntil" | "fork" | "runToCompletion" | "streamToCompletion" | "usePersonality" | "invalidateCache";
2341
+ /**
2342
+ * Handle returned by `Agent.create()` and `Agent.resume()`.
2343
+ *
2344
+ * @public
2345
+ */
2346
+ interface SDKAgent {
2347
+ readonly agentId: string;
2348
+ readonly model: ModelSelection | undefined;
2349
+ /**
2350
+ * Context manager for this agent. Populated when context is enabled via
2351
+ * {@link AgentOptions.context}. See {@link SDKContextManager}.
2352
+ */
2353
+ readonly context?: SDKContextManager;
2354
+ /**
2355
+ * Provider routing inspector for this agent. Populated when at least one
2356
+ * provider route is configured (via {@link AgentOptions.providers}, plugins,
2357
+ * or model-implied providers). See {@link SDKProvidersManager}.
2358
+ */
2359
+ readonly providers?: SDKProvidersManager;
2360
+ /**
2361
+ * Skill listing for this agent. Populated when project-scoped skills are
2362
+ * enabled (`settingSources: ["project"]`) or when `skills.enabled` is set.
2363
+ * See {@link SDKAgentSkills}.
2364
+ */
2365
+ readonly skills?: SDKAgentSkills;
2366
+ /**
2367
+ * Plugin listing for this agent. Populated when project-scoped plugins are
2368
+ * enabled (`settingSources: ["plugins"]`) or when `plugins.enabled` is set.
2369
+ * See {@link SDKAgentPlugins}.
2370
+ */
2371
+ readonly plugins?: SDKAgentPlugins;
2372
+ send(message: string | SDKUserMessage, options?: SendOptions): Promise<Run>;
2373
+ /**
2374
+ * SE9 — integrated structured output. Runs the normal tool loop (the tools run
2375
+ * first) then coerces the final answer into the `output` Zod schema, returning a
2376
+ * validated, inferred-typed object. Sugar over `Agent.generateObject` (ADR D33).
2377
+ */
2378
+ generate<T extends zod.ZodType>(message: string | SDKUserMessage, options: GenerateOptions<T>): Promise<GenerateRunResult<zod.z.infer<T>>>;
2379
+ /** Fire-and-forget disposal. */
2380
+ close(): void;
2381
+ /** Re-read filesystem config (context, hooks, project MCP, subagents) without disposing. */
2382
+ reload(): Promise<void>;
2383
+ /**
2384
+ * Async disposal. Idempotent — calling more than once is a no-op (per ADR D5).
2385
+ * Prefer `await using agent = await Agent.create(...)` over explicit
2386
+ * `dispose()` for resource safety.
2387
+ */
2388
+ dispose(): Promise<void>;
2389
+ /**
2390
+ * `await using` support per ADR D5. Identical semantics to `dispose()` —
2391
+ * idempotent across both surfaces.
2392
+ */
2393
+ [Symbol.asyncDispose](): Promise<void>;
2394
+ /**
2395
+ * Which operations this agent's runtime actually performs.
2396
+ *
2397
+ * `SDKAgent` is one handle over two runtimes that do not offer the same operations, and the type
2398
+ * does not model the difference: `downloadArtifact` is a REQUIRED member that rejects for every
2399
+ * input on a local agent, and five optional members are present-but-throwing on a cloud one, so
2400
+ * `typeof agent.fork === "function"` is true and calling it throws. Neither requiredness nor
2401
+ * optionality expresses "exists here, not there".
2402
+ *
2403
+ * Ask before calling. Mirrors `Run.supports(op)` / `Run.unsupportedReason(op)`, which solved the
2404
+ * same problem one layer down over the `RunOperation` union.
2405
+ *
2406
+ * This is a MITIGATION. The structural fix is to split this interface into a common core plus
2407
+ * `LocalCapableAgent` / `CloudCapableAgent`, so the compiler refuses the call instead of the
2408
+ * runtime and a consumer narrows once instead of asking per call. That is breaking on a published
2409
+ * surface and is deliberately not done here.
2410
+ *
2411
+ * @public
2412
+ */
2413
+ supports(operation: AgentOperation): boolean;
2414
+ /**
2415
+ * Human-readable reason `supports(operation)` returned `false`, or `undefined` when it returned
2416
+ * `true`. The message names the runtime, so an operator reading a log knows which half of the
2417
+ * union they are holding.
2418
+ *
2419
+ * @public
2420
+ */
2421
+ unsupportedReason(operation: AgentOperation): string | undefined;
2422
+ /** Cloud-only. Local returns an empty array. */
2423
+ listArtifacts(): Promise<SDKArtifact[]>;
2424
+ /** Cloud-only. Local throws `UnsupportedRunOperationError`. */
2425
+ downloadArtifact(path: string): Promise<Buffer>;
2426
+ /**
2427
+ * Signal that prompt cache should be invalidated. By default deferred —
2428
+ * applied at the start of the next `send()`. Pass `{ applyNow: true }` to
2429
+ * force immediate disposal (caller must `Agent.create()` again to use).
2430
+ *
2431
+ * Cache invalidation is a cost regression (provider charges full price
2432
+ * for the rebuilt cache; see ADRs D94-D95). Use sparingly and deliberately.
2433
+ *
2434
+ * Cloud agents: no-op (cloud runtime reconstructs state per request).
2435
+ *
2436
+ * @public
2437
+ */
2438
+ invalidateCache?(reason: string, options?: InvalidateCacheOptions): Promise<void>;
2439
+ /**
2440
+ * Goal-driven Ralph loop (ADRs D115-D121). Iterates `agent.send` →
2441
+ * judge → continuation until the auxiliary judge model returns `done`,
2442
+ * the judge fails too many times in a row, max turns are exhausted,
2443
+ * or the caller aborts via `AbortSignal`.
2444
+ *
2445
+ * Yields {@link import("./goal-events.js").GoalEvent} per state
2446
+ * transition; returns a {@link import("./goal-events.js").GoalResult}
2447
+ * summary as the generator's final value.
2448
+ *
2449
+ * Cloud agents throw {@link import("../errors.js").UnsupportedRunOperationError}
2450
+ * **synchronously** (no AsyncGenerator returned) — wrap in try/catch
2451
+ * if you support both runtimes.
2452
+ *
2453
+ * Caveat: do not call `agent.dispose()` mid-iteration; the next `send`
2454
+ * propagates the disposal error through the generator to the consumer.
2455
+ *
2456
+ * @public
2457
+ */
2458
+ runUntil?(goal?: string, options?: GoalOptions): RunUntilIterator;
2459
+ /**
2460
+ * Fork a short-lived sub-agent with parent's credentials + system
2461
+ * prompt byte-identical (ADR D112 — cache hit) and a restricted tool
2462
+ * whitelist (ADR D111 — AsyncLocalStorage isolation).
2463
+ *
2464
+ * Cloud agents throw {@link import("../errors.js").UnsupportedRunOperationError}.
2465
+ *
2466
+ * @public
2467
+ */
2468
+ fork?(options: ForkOptions): Promise<ForkResult>;
2469
+ /**
2470
+ * Drive `send` to completion across iteration-ceiling truncations (M1 Phase 3).
2471
+ * When a `send` stops at the loop's iteration cap (`RunResult.stoppedAtIterationLimit`),
2472
+ * this re-sends a short continuation prompt — the agent's stateful session
2473
+ * preserves the conversation — until a genuine terminal: `done` (finished),
2474
+ * `step_limit` (`maxRounds` exhausted), or `no_progress` (two empty rounds).
2475
+ *
2476
+ * Local agents only. Cloud agents throw
2477
+ * {@link import("../errors.js").UnsupportedRunOperationError} (the cloud
2478
+ * runtime manages its own continuation policy server-side).
2479
+ *
2480
+ * @public
2481
+ */
2482
+ runToCompletion?(message: string, options?: RunToCompletionOptions): Promise<RunToCompletionResult>;
2483
+ /**
2484
+ * STREAMING continuation driver (V3-4) — the streaming twin of
2485
+ * {@link SDKAgent.runToCompletion}. Returns an `AsyncGenerator` that yields each
2486
+ * round's {@link import("./messages.js").SDKMessage}s LIVE (for a UI), reusing the
2487
+ * same terminal policy (`done`/`step_limit`/`no_progress` + bounded re-prompt).
2488
+ *
2489
+ * The {@link import("./run.js").StreamToCompletionResult} is the generator's RETURN
2490
+ * value — read it via a manual `gen.next()` loop (`while (!res.done) res = await
2491
+ * gen.next()` → `res.value`); a plain `for await...of` consumes the yielded
2492
+ * messages but discards the return value.
2493
+ *
2494
+ * Local agents only. Cloud agents throw
2495
+ * {@link import("../errors.js").UnsupportedRunOperationError}.
2496
+ *
2497
+ * @public
2498
+ */
2499
+ streamToCompletion?(message: string, options?: RunToCompletionOptions): AsyncGenerator<SDKMessage, StreamToCompletionResult>;
2500
+ /**
2501
+ * Direct API to third-party memory adapter(s) registered via
2502
+ * `plugins: [...]` (ADR D141 / D142). Returns `null` when no adapter
2503
+ * is registered. In multi-adapter setups `write` fans out to all;
2504
+ * `recall` merges + dedupes; `delete` routes by `MemoryId` prefix.
2505
+ *
2506
+ * @public
2507
+ */
2508
+ memory?: AgentMemory;
2509
+ /**
2510
+ * Activate a personality preset for the next `send` (Hermes #26).
2511
+ * Reserved names `"none"`, `"default"`, and `"neutral"` clear the
2512
+ * active preset. Returns the resolved preset (or `null` when cleared).
2513
+ *
2514
+ * Persistence: pass `{ save: true }` to persist across process
2515
+ * restarts (stored under `$THEOKIT_HOME/personality.json`).
2516
+ *
2517
+ * History: by default the conversation history is preserved across
2518
+ * the switch. Pass `{ reset: true }` to also clear the session.
2519
+ *
2520
+ * Cloud agents throw {@link import("../errors.js").UnsupportedRunOperationError}.
2521
+ *
2522
+ * @public
2523
+ */
2524
+ usePersonality?(name: string, opts?: {
2525
+ save?: boolean;
2526
+ reset?: boolean;
2527
+ }): Promise<PersonalityPreset | null>;
2528
+ }
2529
+ /**
2530
+ * Resolved personality preset surfaced via {@link SDKAgent.usePersonality}
2531
+ * (Hermes #26, ADRs D160-D169). Re-declared here so the public DTS bundle
2532
+ * never crosses the `internal/` path boundary. The implementation type in
2533
+ * `internal/personality/types.ts` is structurally identical.
2534
+ *
2535
+ * @public
2536
+ */
2537
+ interface PersonalityPreset {
2538
+ readonly name: string;
2539
+ readonly description: string | undefined;
2540
+ readonly tools: ReadonlyArray<string> | undefined;
2541
+ readonly model: string | undefined;
2542
+ readonly tags: ReadonlyArray<string> | undefined;
2543
+ readonly systemPrompt: string;
2544
+ readonly source: "project" | "user";
2545
+ readonly sourcePath: string;
2546
+ }
2547
+ /**
2548
+ * Options for {@link SDKAgent.invalidateCache}.
2549
+ *
2550
+ * @public
2551
+ */
2552
+ interface InvalidateCacheOptions {
2553
+ /**
2554
+ * When `true`, dispose the agent immediately so caller must recreate it
2555
+ * to continue. Default `false` (deferred — applied on next `send()`).
2556
+ */
2557
+ applyNow?: boolean;
2558
+ }
2559
+
2560
+ export type { OutputProcessorContext as $, AgentConversationTurn as A, GenerateRunResult as B, ContextSettings as C, DoomLoopThresholds as D, EnvPolicy as E, ForkOptions as F, GoalOptions as G, InteractionUpdate as H, InputProcessorContext as I, JudgeResult as J, InvalidateCacheOptions as K, McpAuthConfig as L, McpServerConfig as M, McpHttpServerConfig as N, McpOAuthConfig as O, ProviderRoutingSettings as P, McpStdioServerConfig as Q, RunResult as R, SDKAgent as S, MemoryAdapter as T, MemoryAdapterCapabilities as U, MemoryContext as V, MemoryFact as W, MemoryRevision as X, MemoryToolSchema as Y, MemoryTurnMessage as Z, MessageOrigin as _, PluginsSettings as a, ToolCall as a$, PartialToolCallUpdate as a0, PersonalityPreset as a1, ProcessorControls as a2, ProcessorTripwire as a3, ProcessorViolation as a4, ProviderCapability as a5, ProviderRoute as a6, ResolvedProviderRoute as a7, RunCompactBoundaryEvent as a8, RunCompletionCheckEvent as a9, SDKProvidersManager as aA, SDKRequestMessage as aB, SDKStatusMessage as aC, SDKSystemMessage as aD, SDKTaskMessage as aE, SDKThinkingMessage as aF, SDKToolUseMessage as aG, SDKUserMessage as aH, SDKUserMessageEvent as aI, SendOptions as aJ, ShellCommand as aK, ShellConversationTurn as aL, ShellOutput as aM, ShellOutputDeltaUpdate as aN, StepCompletedUpdate as aO, StepStartedUpdate as aP, StreamToCompletionResult as aQ, SummaryCompletedUpdate as aR, SummaryStartedUpdate as aS, SummaryUpdate as aT, SystemPromptSkillRef as aU, TextDeltaUpdate as aV, ThinkingCompletedUpdate as aW, ThinkingDeltaUpdate as aX, ThinkingMessage as aY, TokenDeltaUpdate as aZ, TokenUsage as a_, RunErrorDetail as aa, RunEvent as ab, RunGitInfo as ac, RunMemoryDegradedEvent as ad, RunPermissionDeniedEvent as ae, RunRateLimitEvent as af, RunStatus as ag, RunTaskCompletedEvent as ah, RunTaskStartedEvent as ai, RunTaskUpdatedEvent as aj, RunTimelineEvent as ak, RunToCompletionOptions as al, RunToCompletionResult as am, RunToolProgressEvent as an, RunTripwireEvent as ao, RunUntilIterator as ap, SDKAgentPlugins as aq, SDKAgentSkillDetail as ar, SDKAgentSkills as as, SDKArtifact as at, SDKAssistantMessage as au, SDKContextManager as av, SDKImage as aw, SDKImageDimension as ax, SDKObjectDelta as ay, SDKPluginMetadata as az, Run as b, ToolCallCompletedUpdate as b0, ToolCallStartedUpdate as b1, ToolResult as b2, ToolResultGuardOptions as b3, ToolUseBlock as b4, TurnEndedUpdate as b5, UserMessage as b6, UserMessageAppendedUpdate as b7, Verdict as b8, Processor as c, GoalEvent as d, GoalResult as e, MemoryId as f, RunEventSink as g, SDKProvider as h, SDKMessage as i, AgentMemory as j, AgentOperation as k, AssistantMessage as l, CompletionCheck as m, CompletionCheckResult as n, ContextBudget as o, ContextManagerKind as p, ContextSnapshot as q, ContextSource as r, ContextSourceStatus as s, ConversationStep as t, ConversationTurn as u, CostBreakdown as v, CostSource as w, CostStatus as x, ForkResult as y, GenerateOptions as z };