@yolk-sdk/agent 0.0.1-canary.8 → 0.1.0-canary.100

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 (816) hide show
  1. package/README.md +929 -34
  2. package/dist/background-execution-internal.d.mts +8 -0
  3. package/dist/background-execution-internal.d.mts.map +1 -0
  4. package/dist/background-execution-internal.mjs +8 -0
  5. package/dist/background-execution-internal.mjs.map +1 -0
  6. package/dist/classification/errors.d.mts +57 -0
  7. package/dist/classification/errors.d.mts.map +1 -0
  8. package/dist/classification/errors.mjs +56 -0
  9. package/dist/classification/errors.mjs.map +1 -0
  10. package/dist/classification/index.d.mts +4 -0
  11. package/dist/classification/index.mjs +4 -0
  12. package/dist/classification/model.d.mts +74 -0
  13. package/dist/classification/model.d.mts.map +1 -0
  14. package/dist/classification/model.mjs +136 -0
  15. package/dist/classification/model.mjs.map +1 -0
  16. package/dist/classification/schema.d.mts +172 -0
  17. package/dist/classification/schema.d.mts.map +1 -0
  18. package/dist/classification/schema.mjs +104 -0
  19. package/dist/classification/schema.mjs.map +1 -0
  20. package/dist/client/attachments.d.mts +10 -0
  21. package/dist/client/attachments.d.mts.map +1 -0
  22. package/dist/client/attachments.mjs +58 -0
  23. package/dist/client/attachments.mjs.map +1 -0
  24. package/dist/client/index.d.mts +4 -3
  25. package/dist/client/index.mjs +4 -3
  26. package/dist/client/state.d.mts +452 -5
  27. package/dist/client/state.d.mts.map +1 -1
  28. package/dist/client/state.mjs +221 -172
  29. package/dist/client/state.mjs.map +1 -1
  30. package/dist/client/transport.d.mts +54 -20
  31. package/dist/client/transport.d.mts.map +1 -1
  32. package/dist/client/transport.mjs +487 -58
  33. package/dist/client/transport.mjs.map +1 -1
  34. package/dist/compaction/budget.d.mts +22 -0
  35. package/dist/compaction/budget.d.mts.map +1 -0
  36. package/dist/compaction/budget.mjs +23 -0
  37. package/dist/compaction/budget.mjs.map +1 -0
  38. package/dist/compaction/checkpoint.d.mts +25 -0
  39. package/dist/compaction/checkpoint.d.mts.map +1 -0
  40. package/dist/compaction/checkpoint.mjs +34 -0
  41. package/dist/compaction/checkpoint.mjs.map +1 -0
  42. package/dist/compaction/estimator.d.mts +21 -0
  43. package/dist/compaction/estimator.d.mts.map +1 -0
  44. package/dist/compaction/estimator.mjs +22 -0
  45. package/dist/compaction/estimator.mjs.map +1 -0
  46. package/dist/compaction/index.d.mts +8 -0
  47. package/dist/compaction/index.mjs +8 -0
  48. package/dist/compaction/retry.d.mts +142 -0
  49. package/dist/compaction/retry.d.mts.map +1 -0
  50. package/dist/compaction/retry.mjs +43 -0
  51. package/dist/compaction/retry.mjs.map +1 -0
  52. package/dist/compaction/summary.d.mts +26 -0
  53. package/dist/compaction/summary.d.mts.map +1 -0
  54. package/dist/compaction/summary.mjs +59 -0
  55. package/dist/compaction/summary.mjs.map +1 -0
  56. package/dist/compaction/transformer.d.mts +21 -0
  57. package/dist/compaction/transformer.d.mts.map +1 -0
  58. package/dist/compaction/transformer.mjs +24 -0
  59. package/dist/compaction/transformer.mjs.map +1 -0
  60. package/dist/compaction/window.d.mts +184 -0
  61. package/dist/compaction/window.d.mts.map +1 -0
  62. package/dist/compaction/window.mjs +75 -0
  63. package/dist/compaction/window.mjs.map +1 -0
  64. package/dist/loop/accumulator.d.mts +4 -2
  65. package/dist/loop/accumulator.d.mts.map +1 -1
  66. package/dist/loop/accumulator.mjs +39 -25
  67. package/dist/loop/accumulator.mjs.map +1 -1
  68. package/dist/loop/collect.d.mts +38 -0
  69. package/dist/loop/collect.d.mts.map +1 -0
  70. package/dist/loop/collect.mjs +94 -0
  71. package/dist/loop/collect.mjs.map +1 -0
  72. package/dist/loop/error.d.mts +7 -3
  73. package/dist/loop/error.d.mts.map +1 -1
  74. package/dist/loop/error.mjs +49 -46
  75. package/dist/loop/error.mjs.map +1 -1
  76. package/dist/loop/index.d.mts +7 -5
  77. package/dist/loop/index.mjs +5 -3
  78. package/dist/loop/layer.d.mts +17 -0
  79. package/dist/loop/layer.d.mts.map +1 -0
  80. package/dist/loop/layer.mjs +15 -0
  81. package/dist/loop/layer.mjs.map +1 -0
  82. package/dist/loop/llm-event.d.mts.map +1 -1
  83. package/dist/loop/llm-event.mjs.map +1 -1
  84. package/dist/loop/run.d.mts +49 -6
  85. package/dist/loop/run.d.mts.map +1 -1
  86. package/dist/loop/run.mjs +407 -175
  87. package/dist/loop/run.mjs.map +1 -1
  88. package/dist/loop/services/llm-provider.d.mts +3 -0
  89. package/dist/loop/services/llm-provider.d.mts.map +1 -1
  90. package/dist/loop/services/llm-provider.mjs.map +1 -1
  91. package/dist/loop/services/loop-config.d.mts +4 -4
  92. package/dist/loop/services/loop-config.d.mts.map +1 -1
  93. package/dist/loop/services/loop-config.mjs +1 -1
  94. package/dist/loop/services/loop-config.mjs.map +1 -1
  95. package/dist/loop/services/tool-executor.d.mts +16 -5
  96. package/dist/loop/services/tool-executor.d.mts.map +1 -1
  97. package/dist/loop/services/tool-executor.mjs +11 -3
  98. package/dist/loop/services/tool-executor.mjs.map +1 -1
  99. package/dist/loop/testing/faux-provider.d.mts.map +1 -1
  100. package/dist/loop/testing/faux-provider.mjs +1 -1
  101. package/dist/loop/testing/faux-provider.mjs.map +1 -1
  102. package/dist/oauth/error.d.mts +15 -0
  103. package/dist/oauth/error.d.mts.map +1 -0
  104. package/dist/oauth/error.mjs +19 -0
  105. package/dist/oauth/error.mjs.map +1 -0
  106. package/dist/oauth/index.d.mts +4 -0
  107. package/dist/oauth/index.mjs +4 -0
  108. package/dist/oauth/source.d.mts +19 -0
  109. package/dist/oauth/source.d.mts.map +1 -0
  110. package/dist/oauth/source.mjs +12 -0
  111. package/dist/oauth/source.mjs.map +1 -0
  112. package/dist/oauth/token.d.mts +30 -0
  113. package/dist/oauth/token.d.mts.map +1 -0
  114. package/dist/oauth/token.mjs +27 -0
  115. package/dist/oauth/token.mjs.map +1 -0
  116. package/dist/protocol/bounded-text.d.mts +20 -0
  117. package/dist/protocol/bounded-text.d.mts.map +1 -0
  118. package/dist/protocol/bounded-text.mjs +48 -0
  119. package/dist/protocol/bounded-text.mjs.map +1 -0
  120. package/dist/protocol/content.d.mts +76 -17
  121. package/dist/protocol/content.d.mts.map +1 -1
  122. package/dist/protocol/content.mjs +155 -45
  123. package/dist/protocol/content.mjs.map +1 -1
  124. package/dist/protocol/event.d.mts +98 -9
  125. package/dist/protocol/event.d.mts.map +1 -1
  126. package/dist/protocol/event.mjs +245 -78
  127. package/dist/protocol/event.mjs.map +1 -1
  128. package/dist/protocol/index.d.mts +8 -6
  129. package/dist/protocol/index.d.mts.map +1 -1
  130. package/dist/protocol/index.mjs +9 -7
  131. package/dist/protocol/message.d.mts +129 -25
  132. package/dist/protocol/message.d.mts.map +1 -1
  133. package/dist/protocol/message.mjs +153 -23
  134. package/dist/protocol/message.mjs.map +1 -1
  135. package/dist/protocol/nested-tool-calls.d.mts +116 -0
  136. package/dist/protocol/nested-tool-calls.d.mts.map +1 -0
  137. package/dist/protocol/nested-tool-calls.mjs +143 -0
  138. package/dist/protocol/nested-tool-calls.mjs.map +1 -0
  139. package/dist/protocol/reasoning.d.mts.map +1 -1
  140. package/dist/protocol/reasoning.mjs.map +1 -1
  141. package/dist/protocol/session.d.mts +19 -5
  142. package/dist/protocol/session.d.mts.map +1 -1
  143. package/dist/protocol/session.mjs +17 -3
  144. package/dist/protocol/session.mjs.map +1 -1
  145. package/dist/protocol/tool-argument-hints.d.mts +12 -0
  146. package/dist/protocol/tool-argument-hints.d.mts.map +1 -0
  147. package/dist/protocol/tool-argument-hints.mjs +60 -0
  148. package/dist/protocol/tool-argument-hints.mjs.map +1 -0
  149. package/dist/protocol/tool.d.mts +851 -64
  150. package/dist/protocol/tool.d.mts.map +1 -1
  151. package/dist/protocol/tool.mjs +593 -41
  152. package/dist/protocol/tool.mjs.map +1 -1
  153. package/dist/protocol/usage.mjs +11 -11
  154. package/dist/protocol/usage.mjs.map +1 -1
  155. package/dist/providers/anthropic/claude-provider.d.mts +84 -0
  156. package/dist/providers/anthropic/claude-provider.d.mts.map +1 -0
  157. package/dist/providers/anthropic/claude-provider.mjs +9 -0
  158. package/dist/providers/anthropic/claude-provider.mjs.map +1 -0
  159. package/dist/providers/anthropic/claude.d.mts +55 -0
  160. package/dist/providers/anthropic/claude.d.mts.map +1 -0
  161. package/dist/providers/anthropic/claude.mjs +96 -0
  162. package/dist/providers/anthropic/claude.mjs.map +1 -0
  163. package/dist/providers/anthropic/conformance/cases.d.mts +50 -0
  164. package/dist/providers/anthropic/conformance/cases.d.mts.map +1 -0
  165. package/dist/providers/anthropic/conformance/cases.mjs +248 -0
  166. package/dist/providers/anthropic/conformance/cases.mjs.map +1 -0
  167. package/dist/providers/anthropic/conformance/claude-usage-cases.d.mts +27 -0
  168. package/dist/providers/anthropic/conformance/claude-usage-cases.d.mts.map +1 -0
  169. package/dist/providers/anthropic/conformance/claude-usage-cases.mjs +55 -0
  170. package/dist/providers/anthropic/conformance/claude-usage-cases.mjs.map +1 -0
  171. package/dist/providers/anthropic/conformance/claude-usage-snapshot.d.mts +14 -0
  172. package/dist/providers/anthropic/conformance/claude-usage-snapshot.d.mts.map +1 -0
  173. package/dist/providers/anthropic/conformance/claude-usage-snapshot.mjs +33 -0
  174. package/dist/providers/anthropic/conformance/claude-usage-snapshot.mjs.map +1 -0
  175. package/dist/providers/anthropic/conformance/error-envelope.d.mts +15 -0
  176. package/dist/providers/anthropic/conformance/error-envelope.d.mts.map +1 -0
  177. package/dist/providers/anthropic/conformance/error-envelope.mjs +51 -0
  178. package/dist/providers/anthropic/conformance/error-envelope.mjs.map +1 -0
  179. package/dist/providers/anthropic/conformance/index.d.mts +18 -0
  180. package/dist/providers/anthropic/conformance/index.d.mts.map +1 -0
  181. package/dist/providers/anthropic/conformance/index.mjs +23 -0
  182. package/dist/providers/anthropic/conformance/index.mjs.map +1 -0
  183. package/dist/providers/anthropic/conformance/max-tokens.d.mts +15 -0
  184. package/dist/providers/anthropic/conformance/max-tokens.d.mts.map +1 -0
  185. package/dist/providers/anthropic/conformance/max-tokens.mjs +60 -0
  186. package/dist/providers/anthropic/conformance/max-tokens.mjs.map +1 -0
  187. package/dist/providers/anthropic/conformance/plain-text.d.mts +17 -0
  188. package/dist/providers/anthropic/conformance/plain-text.d.mts.map +1 -0
  189. package/dist/providers/anthropic/conformance/plain-text.mjs +63 -0
  190. package/dist/providers/anthropic/conformance/plain-text.mjs.map +1 -0
  191. package/dist/providers/anthropic/conformance/thinking-before-text.d.mts +16 -0
  192. package/dist/providers/anthropic/conformance/thinking-before-text.d.mts.map +1 -0
  193. package/dist/providers/anthropic/conformance/thinking-before-text.mjs +70 -0
  194. package/dist/providers/anthropic/conformance/thinking-before-text.mjs.map +1 -0
  195. package/dist/providers/anthropic/conformance/tool-use-input-deltas.d.mts +17 -0
  196. package/dist/providers/anthropic/conformance/tool-use-input-deltas.d.mts.map +1 -0
  197. package/dist/providers/anthropic/conformance/tool-use-input-deltas.mjs +79 -0
  198. package/dist/providers/anthropic/conformance/tool-use-input-deltas.mjs.map +1 -0
  199. package/dist/providers/anthropic/index.d.mts +2 -0
  200. package/dist/providers/anthropic/index.mjs +2 -0
  201. package/dist/providers/anthropic/usage.d.mts +21 -0
  202. package/dist/providers/anthropic/usage.d.mts.map +1 -0
  203. package/dist/providers/anthropic/usage.mjs +76 -0
  204. package/dist/providers/anthropic/usage.mjs.map +1 -0
  205. package/dist/providers/anthropic-messages-provider-internal.d.mts +22 -0
  206. package/dist/providers/anthropic-messages-provider-internal.d.mts.map +1 -0
  207. package/dist/providers/anthropic-messages-provider-internal.mjs +71 -0
  208. package/dist/providers/anthropic-messages-provider-internal.mjs.map +1 -0
  209. package/dist/providers/anthropic-provider-internal.d.mts +89 -0
  210. package/dist/providers/anthropic-provider-internal.d.mts.map +1 -0
  211. package/dist/providers/anthropic-provider-internal.mjs +1006 -0
  212. package/dist/providers/anthropic-provider-internal.mjs.map +1 -0
  213. package/dist/providers/openai/codex-provider.d.mts +82 -0
  214. package/dist/providers/openai/codex-provider.d.mts.map +1 -0
  215. package/dist/providers/openai/codex-provider.mjs +58 -0
  216. package/dist/providers/openai/codex-provider.mjs.map +1 -0
  217. package/dist/providers/openai/codex-usage.d.mts +21 -0
  218. package/dist/providers/openai/codex-usage.d.mts.map +1 -0
  219. package/dist/providers/openai/codex-usage.mjs +87 -0
  220. package/dist/providers/openai/codex-usage.mjs.map +1 -0
  221. package/dist/providers/openai/codex.d.mts +52 -0
  222. package/dist/providers/openai/codex.d.mts.map +1 -0
  223. package/dist/providers/openai/codex.mjs +53 -0
  224. package/dist/providers/openai/codex.mjs.map +1 -0
  225. package/dist/providers/openai/conformance/cases.d.mts +36 -0
  226. package/dist/providers/openai/conformance/cases.d.mts.map +1 -0
  227. package/dist/providers/openai/conformance/cases.mjs +165 -0
  228. package/dist/providers/openai/conformance/cases.mjs.map +1 -0
  229. package/dist/providers/openai/conformance/codex-cases.d.mts +37 -0
  230. package/dist/providers/openai/conformance/codex-cases.d.mts.map +1 -0
  231. package/dist/providers/openai/conformance/codex-cases.mjs +64 -0
  232. package/dist/providers/openai/conformance/codex-cases.mjs.map +1 -0
  233. package/dist/providers/openai/conformance/codex-error-envelope.d.mts +13 -0
  234. package/dist/providers/openai/conformance/codex-error-envelope.d.mts.map +1 -0
  235. package/dist/providers/openai/conformance/codex-error-envelope.mjs +50 -0
  236. package/dist/providers/openai/conformance/codex-error-envelope.mjs.map +1 -0
  237. package/dist/providers/openai/conformance/codex-function-call-arguments.d.mts +13 -0
  238. package/dist/providers/openai/conformance/codex-function-call-arguments.d.mts.map +1 -0
  239. package/dist/providers/openai/conformance/codex-function-call-arguments.mjs +79 -0
  240. package/dist/providers/openai/conformance/codex-function-call-arguments.mjs.map +1 -0
  241. package/dist/providers/openai/conformance/codex-plain-text.d.mts +13 -0
  242. package/dist/providers/openai/conformance/codex-plain-text.d.mts.map +1 -0
  243. package/dist/providers/openai/conformance/codex-plain-text.mjs +70 -0
  244. package/dist/providers/openai/conformance/codex-plain-text.mjs.map +1 -0
  245. package/dist/providers/openai/conformance/codex-terminal-event.d.mts +13 -0
  246. package/dist/providers/openai/conformance/codex-terminal-event.d.mts.map +1 -0
  247. package/dist/providers/openai/conformance/codex-terminal-event.mjs +67 -0
  248. package/dist/providers/openai/conformance/codex-terminal-event.mjs.map +1 -0
  249. package/dist/providers/openai/conformance/codex-usage-cases.d.mts +28 -0
  250. package/dist/providers/openai/conformance/codex-usage-cases.d.mts.map +1 -0
  251. package/dist/providers/openai/conformance/codex-usage-cases.mjs +55 -0
  252. package/dist/providers/openai/conformance/codex-usage-cases.mjs.map +1 -0
  253. package/dist/providers/openai/conformance/codex-usage-snapshot.d.mts +15 -0
  254. package/dist/providers/openai/conformance/codex-usage-snapshot.d.mts.map +1 -0
  255. package/dist/providers/openai/conformance/codex-usage-snapshot.mjs +34 -0
  256. package/dist/providers/openai/conformance/codex-usage-snapshot.mjs.map +1 -0
  257. package/dist/providers/openai/conformance/error-envelope.d.mts +14 -0
  258. package/dist/providers/openai/conformance/error-envelope.d.mts.map +1 -0
  259. package/dist/providers/openai/conformance/error-envelope.mjs +50 -0
  260. package/dist/providers/openai/conformance/error-envelope.mjs.map +1 -0
  261. package/dist/providers/openai/conformance/index.d.mts +24 -0
  262. package/dist/providers/openai/conformance/index.d.mts.map +1 -0
  263. package/dist/providers/openai/conformance/index.mjs +33 -0
  264. package/dist/providers/openai/conformance/index.mjs.map +1 -0
  265. package/dist/providers/openai/conformance/json-plain-text.d.mts +14 -0
  266. package/dist/providers/openai/conformance/json-plain-text.d.mts.map +1 -0
  267. package/dist/providers/openai/conformance/json-plain-text.mjs +49 -0
  268. package/dist/providers/openai/conformance/json-plain-text.mjs.map +1 -0
  269. package/dist/providers/openai/conformance/plain-text.d.mts +15 -0
  270. package/dist/providers/openai/conformance/plain-text.d.mts.map +1 -0
  271. package/dist/providers/openai/conformance/plain-text.mjs +60 -0
  272. package/dist/providers/openai/conformance/plain-text.mjs.map +1 -0
  273. package/dist/providers/openai/conformance/responses-cases-internal.d.mts +40 -0
  274. package/dist/providers/openai/conformance/responses-cases-internal.d.mts.map +1 -0
  275. package/dist/providers/openai/conformance/responses-cases-internal.mjs +271 -0
  276. package/dist/providers/openai/conformance/responses-cases-internal.mjs.map +1 -0
  277. package/dist/providers/openai/conformance/subscription-usage-cases-internal.d.mts +37 -0
  278. package/dist/providers/openai/conformance/subscription-usage-cases-internal.d.mts.map +1 -0
  279. package/dist/providers/openai/conformance/subscription-usage-cases-internal.mjs +85 -0
  280. package/dist/providers/openai/conformance/subscription-usage-cases-internal.mjs.map +1 -0
  281. package/dist/providers/openai/conformance/tool-call-deltas.d.mts +15 -0
  282. package/dist/providers/openai/conformance/tool-call-deltas.d.mts.map +1 -0
  283. package/dist/providers/openai/conformance/tool-call-deltas.mjs +77 -0
  284. package/dist/providers/openai/conformance/tool-call-deltas.mjs.map +1 -0
  285. package/dist/providers/openai/index.d.mts +2 -0
  286. package/dist/providers/openai/index.mjs +2 -0
  287. package/dist/providers/openai/provider.d.mts +121 -0
  288. package/dist/providers/openai/provider.d.mts.map +1 -0
  289. package/dist/providers/openai/provider.mjs +793 -0
  290. package/dist/providers/openai/provider.mjs.map +1 -0
  291. package/dist/providers/openai/realtime/client-codec.d.mts +18 -0
  292. package/dist/providers/openai/realtime/client-codec.d.mts.map +1 -0
  293. package/dist/providers/openai/realtime/client-codec.mjs +52 -0
  294. package/dist/providers/openai/realtime/client-codec.mjs.map +1 -0
  295. package/dist/providers/openai/realtime/events.d.mts +131 -0
  296. package/dist/providers/openai/realtime/events.d.mts.map +1 -0
  297. package/dist/providers/openai/realtime/events.mjs +213 -0
  298. package/dist/providers/openai/realtime/events.mjs.map +1 -0
  299. package/dist/providers/openai/realtime/index.d.mts +5 -0
  300. package/dist/providers/openai/realtime/index.mjs +5 -0
  301. package/dist/providers/openai/realtime/session-config.d.mts +96 -0
  302. package/dist/providers/openai/realtime/session-config.d.mts.map +1 -0
  303. package/dist/providers/openai/realtime/session-config.mjs +181 -0
  304. package/dist/providers/openai/realtime/session-config.mjs.map +1 -0
  305. package/dist/providers/openai/realtime/to-voice.d.mts +14 -0
  306. package/dist/providers/openai/realtime/to-voice.d.mts.map +1 -0
  307. package/dist/providers/openai/realtime/to-voice.mjs +44 -0
  308. package/dist/providers/openai/realtime/to-voice.mjs.map +1 -0
  309. package/dist/providers/openai/speech.d.mts +35 -0
  310. package/dist/providers/openai/speech.d.mts.map +1 -0
  311. package/dist/providers/openai/speech.mjs +132 -0
  312. package/dist/providers/openai/speech.mjs.map +1 -0
  313. package/dist/providers/openai-responses-provider-internal.d.mts +128 -0
  314. package/dist/providers/openai-responses-provider-internal.d.mts.map +1 -0
  315. package/dist/providers/openai-responses-provider-internal.mjs +708 -0
  316. package/dist/providers/openai-responses-provider-internal.mjs.map +1 -0
  317. package/dist/providers/opencode/conformance/cases.d.mts +47 -0
  318. package/dist/providers/opencode/conformance/cases.d.mts.map +1 -0
  319. package/dist/providers/opencode/conformance/cases.mjs +208 -0
  320. package/dist/providers/opencode/conformance/cases.mjs.map +1 -0
  321. package/dist/providers/opencode/conformance/chat-plain-text.d.mts +13 -0
  322. package/dist/providers/opencode/conformance/chat-plain-text.d.mts.map +1 -0
  323. package/dist/providers/opencode/conformance/chat-plain-text.mjs +58 -0
  324. package/dist/providers/opencode/conformance/chat-plain-text.mjs.map +1 -0
  325. package/dist/providers/opencode/conformance/index.d.mts +14 -0
  326. package/dist/providers/opencode/conformance/index.d.mts.map +1 -0
  327. package/dist/providers/opencode/conformance/index.mjs +19 -0
  328. package/dist/providers/opencode/conformance/index.mjs.map +1 -0
  329. package/dist/providers/opencode/conformance/messages-plain-text.d.mts +13 -0
  330. package/dist/providers/opencode/conformance/messages-plain-text.d.mts.map +1 -0
  331. package/dist/providers/opencode/conformance/messages-plain-text.mjs +60 -0
  332. package/dist/providers/opencode/conformance/messages-plain-text.mjs.map +1 -0
  333. package/dist/providers/opencode/conformance/responses-commentary-replay.d.mts +13 -0
  334. package/dist/providers/opencode/conformance/responses-commentary-replay.d.mts.map +1 -0
  335. package/dist/providers/opencode/conformance/responses-commentary-replay.mjs +89 -0
  336. package/dist/providers/opencode/conformance/responses-commentary-replay.mjs.map +1 -0
  337. package/dist/providers/opencode/conformance/responses-plain-text.d.mts +13 -0
  338. package/dist/providers/opencode/conformance/responses-plain-text.d.mts.map +1 -0
  339. package/dist/providers/opencode/conformance/responses-plain-text.mjs +60 -0
  340. package/dist/providers/opencode/conformance/responses-plain-text.mjs.map +1 -0
  341. package/dist/providers/opencode/conformance/usage-snapshot.d.mts +13 -0
  342. package/dist/providers/opencode/conformance/usage-snapshot.d.mts.map +1 -0
  343. package/dist/providers/opencode/conformance/usage-snapshot.mjs +32 -0
  344. package/dist/providers/opencode/conformance/usage-snapshot.mjs.map +1 -0
  345. package/dist/providers/opencode/go-provider.d.mts +21 -0
  346. package/dist/providers/opencode/go-provider.d.mts.map +1 -0
  347. package/dist/providers/opencode/go-provider.mjs +87 -0
  348. package/dist/providers/opencode/go-provider.mjs.map +1 -0
  349. package/dist/providers/opencode/usage.d.mts +22 -0
  350. package/dist/providers/opencode/usage.d.mts.map +1 -0
  351. package/dist/providers/opencode/usage.mjs +75 -0
  352. package/dist/providers/opencode/usage.mjs.map +1 -0
  353. package/dist/providers/provider-error.d.mts +35 -0
  354. package/dist/providers/provider-error.d.mts.map +1 -0
  355. package/dist/providers/provider-error.mjs +99 -0
  356. package/dist/providers/provider-error.mjs.map +1 -0
  357. package/dist/providers/subscription-usage-internal.d.mts +26 -0
  358. package/dist/providers/subscription-usage-internal.d.mts.map +1 -0
  359. package/dist/providers/subscription-usage-internal.mjs +62 -0
  360. package/dist/providers/subscription-usage-internal.mjs.map +1 -0
  361. package/dist/providers/subscription-usage.d.mts +49 -0
  362. package/dist/providers/subscription-usage.d.mts.map +1 -0
  363. package/dist/providers/subscription-usage.mjs +58 -0
  364. package/dist/providers/subscription-usage.mjs.map +1 -0
  365. package/dist/providers/transcript.d.mts +9 -0
  366. package/dist/providers/transcript.d.mts.map +1 -0
  367. package/dist/providers/transcript.mjs +13 -0
  368. package/dist/providers/transcript.mjs.map +1 -0
  369. package/dist/providers/vercel/ai-gateway-classifier.d.mts +45 -0
  370. package/dist/providers/vercel/ai-gateway-classifier.d.mts.map +1 -0
  371. package/dist/providers/vercel/ai-gateway-classifier.mjs +253 -0
  372. package/dist/providers/vercel/ai-gateway-classifier.mjs.map +1 -0
  373. package/dist/providers/vercel/ai-gateway-credential-internal.d.mts +12 -0
  374. package/dist/providers/vercel/ai-gateway-credential-internal.d.mts.map +1 -0
  375. package/dist/providers/vercel/ai-gateway-credential-internal.mjs +12 -0
  376. package/dist/providers/vercel/ai-gateway-credential-internal.mjs.map +1 -0
  377. package/dist/providers/vercel/ai-gateway-provider.d.mts +52 -0
  378. package/dist/providers/vercel/ai-gateway-provider.d.mts.map +1 -0
  379. package/dist/providers/vercel/ai-gateway-provider.mjs +56 -0
  380. package/dist/providers/vercel/ai-gateway-provider.mjs.map +1 -0
  381. package/dist/providers/vercel/conformance/cases.d.mts +41 -0
  382. package/dist/providers/vercel/conformance/cases.d.mts.map +1 -0
  383. package/dist/providers/vercel/conformance/cases.mjs +182 -0
  384. package/dist/providers/vercel/conformance/cases.mjs.map +1 -0
  385. package/dist/providers/vercel/conformance/classifier-boolean.d.mts +13 -0
  386. package/dist/providers/vercel/conformance/classifier-boolean.d.mts.map +1 -0
  387. package/dist/providers/vercel/conformance/classifier-boolean.mjs +48 -0
  388. package/dist/providers/vercel/conformance/classifier-boolean.mjs.map +1 -0
  389. package/dist/providers/vercel/conformance/classifier-cases.d.mts +32 -0
  390. package/dist/providers/vercel/conformance/classifier-cases.d.mts.map +1 -0
  391. package/dist/providers/vercel/conformance/classifier-cases.mjs +193 -0
  392. package/dist/providers/vercel/conformance/classifier-cases.mjs.map +1 -0
  393. package/dist/providers/vercel/conformance/classifier-choice.d.mts +16 -0
  394. package/dist/providers/vercel/conformance/classifier-choice.d.mts.map +1 -0
  395. package/dist/providers/vercel/conformance/classifier-choice.mjs +55 -0
  396. package/dist/providers/vercel/conformance/classifier-choice.mjs.map +1 -0
  397. package/dist/providers/vercel/conformance/classifier-error-envelope.d.mts +13 -0
  398. package/dist/providers/vercel/conformance/classifier-error-envelope.d.mts.map +1 -0
  399. package/dist/providers/vercel/conformance/classifier-error-envelope.mjs +48 -0
  400. package/dist/providers/vercel/conformance/classifier-error-envelope.mjs.map +1 -0
  401. package/dist/providers/vercel/conformance/classifier-score.d.mts +16 -0
  402. package/dist/providers/vercel/conformance/classifier-score.d.mts.map +1 -0
  403. package/dist/providers/vercel/conformance/classifier-score.mjs +56 -0
  404. package/dist/providers/vercel/conformance/classifier-score.mjs.map +1 -0
  405. package/dist/providers/vercel/conformance/deepseek-reasoning.d.mts +13 -0
  406. package/dist/providers/vercel/conformance/deepseek-reasoning.d.mts.map +1 -0
  407. package/dist/providers/vercel/conformance/deepseek-reasoning.mjs +64 -0
  408. package/dist/providers/vercel/conformance/deepseek-reasoning.mjs.map +1 -0
  409. package/dist/providers/vercel/conformance/error-envelope.d.mts +13 -0
  410. package/dist/providers/vercel/conformance/error-envelope.d.mts.map +1 -0
  411. package/dist/providers/vercel/conformance/error-envelope.mjs +49 -0
  412. package/dist/providers/vercel/conformance/error-envelope.mjs.map +1 -0
  413. package/dist/providers/vercel/conformance/index.d.mts +20 -0
  414. package/dist/providers/vercel/conformance/index.d.mts.map +1 -0
  415. package/dist/providers/vercel/conformance/index.mjs +29 -0
  416. package/dist/providers/vercel/conformance/index.mjs.map +1 -0
  417. package/dist/providers/vercel/conformance/plain-text.d.mts +13 -0
  418. package/dist/providers/vercel/conformance/plain-text.d.mts.map +1 -0
  419. package/dist/providers/vercel/conformance/plain-text.mjs +53 -0
  420. package/dist/providers/vercel/conformance/plain-text.mjs.map +1 -0
  421. package/dist/providers/vercel/conformance/tool-call-deltas.d.mts +13 -0
  422. package/dist/providers/vercel/conformance/tool-call-deltas.d.mts.map +1 -0
  423. package/dist/providers/vercel/conformance/tool-call-deltas.mjs +63 -0
  424. package/dist/providers/vercel/conformance/tool-call-deltas.mjs.map +1 -0
  425. package/dist/providers/xai/conformance/cases.d.mts +43 -0
  426. package/dist/providers/xai/conformance/cases.d.mts.map +1 -0
  427. package/dist/providers/xai/conformance/cases.mjs +70 -0
  428. package/dist/providers/xai/conformance/cases.mjs.map +1 -0
  429. package/dist/providers/xai/conformance/error-envelope.d.mts +14 -0
  430. package/dist/providers/xai/conformance/error-envelope.d.mts.map +1 -0
  431. package/dist/providers/xai/conformance/error-envelope.mjs +48 -0
  432. package/dist/providers/xai/conformance/error-envelope.mjs.map +1 -0
  433. package/dist/providers/xai/conformance/function-call-arguments.d.mts +14 -0
  434. package/dist/providers/xai/conformance/function-call-arguments.d.mts.map +1 -0
  435. package/dist/providers/xai/conformance/function-call-arguments.mjs +70 -0
  436. package/dist/providers/xai/conformance/function-call-arguments.mjs.map +1 -0
  437. package/dist/providers/xai/conformance/index.d.mts +17 -0
  438. package/dist/providers/xai/conformance/index.d.mts.map +1 -0
  439. package/dist/providers/xai/conformance/index.mjs +21 -0
  440. package/dist/providers/xai/conformance/index.mjs.map +1 -0
  441. package/dist/providers/xai/conformance/plain-text.d.mts +14 -0
  442. package/dist/providers/xai/conformance/plain-text.d.mts.map +1 -0
  443. package/dist/providers/xai/conformance/plain-text.mjs +61 -0
  444. package/dist/providers/xai/conformance/plain-text.mjs.map +1 -0
  445. package/dist/providers/xai/conformance/terminal-event.d.mts +14 -0
  446. package/dist/providers/xai/conformance/terminal-event.d.mts.map +1 -0
  447. package/dist/providers/xai/conformance/terminal-event.mjs +59 -0
  448. package/dist/providers/xai/conformance/terminal-event.mjs.map +1 -0
  449. package/dist/providers/xai/conformance/usage-cases.d.mts +29 -0
  450. package/dist/providers/xai/conformance/usage-cases.d.mts.map +1 -0
  451. package/dist/providers/xai/conformance/usage-cases.mjs +81 -0
  452. package/dist/providers/xai/conformance/usage-cases.mjs.map +1 -0
  453. package/dist/providers/xai/conformance/usage-snapshot.d.mts +15 -0
  454. package/dist/providers/xai/conformance/usage-snapshot.d.mts.map +1 -0
  455. package/dist/providers/xai/conformance/usage-snapshot.mjs +34 -0
  456. package/dist/providers/xai/conformance/usage-snapshot.mjs.map +1 -0
  457. package/dist/providers/xai/grok-provider.d.mts +85 -0
  458. package/dist/providers/xai/grok-provider.d.mts.map +1 -0
  459. package/dist/providers/xai/grok-provider.mjs +35 -0
  460. package/dist/providers/xai/grok-provider.mjs.map +1 -0
  461. package/dist/providers/xai/grok.d.mts +60 -0
  462. package/dist/providers/xai/grok.d.mts.map +1 -0
  463. package/dist/providers/xai/grok.mjs +104 -0
  464. package/dist/providers/xai/grok.mjs.map +1 -0
  465. package/dist/providers/xai/index.d.mts +2 -0
  466. package/dist/providers/xai/index.mjs +2 -0
  467. package/dist/providers/xai/usage.d.mts +23 -0
  468. package/dist/providers/xai/usage.d.mts.map +1 -0
  469. package/dist/providers/xai/usage.mjs +134 -0
  470. package/dist/providers/xai/usage.mjs.map +1 -0
  471. package/dist/react/chat-actions.d.mts +418 -0
  472. package/dist/react/chat-actions.d.mts.map +1 -0
  473. package/dist/react/chat-actions.mjs +12 -0
  474. package/dist/react/chat-actions.mjs.map +1 -0
  475. package/dist/react/chat-core.d.mts +95 -0
  476. package/dist/react/chat-core.d.mts.map +1 -0
  477. package/dist/react/chat-core.mjs +170 -0
  478. package/dist/react/chat-core.mjs.map +1 -0
  479. package/dist/react/chat-items.d.mts +781 -0
  480. package/dist/react/chat-items.d.mts.map +1 -0
  481. package/dist/react/chat-items.mjs +179 -0
  482. package/dist/react/chat-items.mjs.map +1 -0
  483. package/dist/react/chat-messages.d.mts +821 -0
  484. package/dist/react/chat-messages.d.mts.map +1 -0
  485. package/dist/react/chat-messages.mjs +679 -0
  486. package/dist/react/chat-messages.mjs.map +1 -0
  487. package/dist/react/chat-session-events.d.mts +33 -0
  488. package/dist/react/chat-session-events.d.mts.map +1 -0
  489. package/dist/react/chat-session-events.mjs +29 -0
  490. package/dist/react/chat-session-events.mjs.map +1 -0
  491. package/dist/react/index.d.mts +7 -0
  492. package/dist/react/index.mjs +7 -0
  493. package/dist/react/use-agent-chat.d.mts +98 -0
  494. package/dist/react/use-agent-chat.d.mts.map +1 -0
  495. package/dist/react/use-agent-chat.mjs +245 -0
  496. package/dist/react/use-agent-chat.mjs.map +1 -0
  497. package/dist/runtime/error.d.mts.map +1 -1
  498. package/dist/runtime/error.mjs +25 -36
  499. package/dist/runtime/error.mjs.map +1 -1
  500. package/dist/runtime/index.d.mts +1 -1
  501. package/dist/runtime/index.d.mts.map +1 -1
  502. package/dist/runtime/index.mjs +2 -2
  503. package/dist/runtime/run-runtime.d.mts +150 -20
  504. package/dist/runtime/run-runtime.d.mts.map +1 -1
  505. package/dist/runtime/run-runtime.mjs +26 -35
  506. package/dist/runtime/run-runtime.mjs.map +1 -1
  507. package/dist/runtime/session-event-store.d.mts +19 -19
  508. package/dist/runtime/session-event-store.d.mts.map +1 -1
  509. package/dist/runtime/session-event-store.mjs +28 -56
  510. package/dist/runtime/session-event-store.mjs.map +1 -1
  511. package/dist/skillset/command.d.mts +53 -0
  512. package/dist/skillset/command.d.mts.map +1 -0
  513. package/dist/skillset/command.mjs +137 -0
  514. package/dist/skillset/command.mjs.map +1 -0
  515. package/dist/skillset/errors.d.mts +13 -0
  516. package/dist/skillset/errors.d.mts.map +1 -0
  517. package/dist/skillset/errors.mjs +18 -0
  518. package/dist/skillset/errors.mjs.map +1 -0
  519. package/dist/skillset/index.d.mts +8 -0
  520. package/dist/skillset/index.mjs +8 -0
  521. package/dist/skillset/manifest.d.mts +33 -0
  522. package/dist/skillset/manifest.d.mts.map +1 -0
  523. package/dist/skillset/manifest.mjs +18 -0
  524. package/dist/skillset/manifest.mjs.map +1 -0
  525. package/dist/skillset/markdown.d.mts +17 -0
  526. package/dist/skillset/markdown.d.mts.map +1 -0
  527. package/dist/skillset/markdown.mjs +41 -0
  528. package/dist/skillset/markdown.mjs.map +1 -0
  529. package/dist/skillset/merge.d.mts +42 -0
  530. package/dist/skillset/merge.d.mts.map +1 -0
  531. package/dist/skillset/merge.mjs +32 -0
  532. package/dist/skillset/merge.mjs.map +1 -0
  533. package/dist/skillset/name.d.mts +10 -0
  534. package/dist/skillset/name.d.mts.map +1 -0
  535. package/dist/skillset/name.mjs +18 -0
  536. package/dist/skillset/name.mjs.map +1 -0
  537. package/dist/skillset/skill.d.mts +30 -0
  538. package/dist/skillset/skill.d.mts.map +1 -0
  539. package/dist/skillset/skill.mjs +47 -0
  540. package/dist/skillset/skill.mjs.map +1 -0
  541. package/dist/tools/arguments.d.mts +40 -0
  542. package/dist/tools/arguments.d.mts.map +1 -0
  543. package/dist/tools/arguments.mjs +364 -0
  544. package/dist/tools/arguments.mjs.map +1 -0
  545. package/dist/tools/background.d.mts +37 -0
  546. package/dist/tools/background.d.mts.map +1 -0
  547. package/dist/tools/background.mjs +130 -0
  548. package/dist/tools/background.mjs.map +1 -0
  549. package/dist/tools/index.d.mts +11 -4
  550. package/dist/tools/index.mjs +10 -4
  551. package/dist/tools/input.d.mts +41 -0
  552. package/dist/tools/input.d.mts.map +1 -0
  553. package/dist/tools/input.mjs +85 -0
  554. package/dist/tools/input.mjs.map +1 -0
  555. package/dist/tools/interaction.d.mts +55 -0
  556. package/dist/tools/interaction.d.mts.map +1 -0
  557. package/dist/tools/interaction.mjs +139 -0
  558. package/dist/tools/interaction.mjs.map +1 -0
  559. package/dist/tools/ledger.d.mts +452 -0
  560. package/dist/tools/ledger.d.mts.map +1 -0
  561. package/dist/tools/ledger.mjs +471 -0
  562. package/dist/tools/ledger.mjs.map +1 -0
  563. package/dist/tools/question.d.mts +1 -1
  564. package/dist/tools/question.d.mts.map +1 -1
  565. package/dist/tools/question.mjs +4 -3
  566. package/dist/tools/question.mjs.map +1 -1
  567. package/dist/tools/registry.d.mts +176 -17
  568. package/dist/tools/registry.d.mts.map +1 -1
  569. package/dist/tools/registry.mjs +489 -52
  570. package/dist/tools/registry.mjs.map +1 -1
  571. package/dist/tools/sha256.d.mts +6 -0
  572. package/dist/tools/sha256.d.mts.map +1 -0
  573. package/dist/tools/sha256.mjs +138 -0
  574. package/dist/tools/sha256.mjs.map +1 -0
  575. package/dist/tools/subagent.d.mts +102 -0
  576. package/dist/tools/subagent.d.mts.map +1 -0
  577. package/dist/tools/subagent.mjs +332 -0
  578. package/dist/tools/subagent.mjs.map +1 -0
  579. package/dist/voice/browser/index.d.mts +2 -0
  580. package/dist/voice/browser/index.mjs +2 -0
  581. package/dist/voice/browser/webrtc.d.mts +72 -0
  582. package/dist/voice/browser/webrtc.d.mts.map +1 -0
  583. package/dist/voice/browser/webrtc.mjs +163 -0
  584. package/dist/voice/browser/webrtc.mjs.map +1 -0
  585. package/dist/voice/client-codec.d.mts +18 -0
  586. package/dist/voice/client-codec.d.mts.map +1 -0
  587. package/dist/voice/client-codec.mjs +1 -0
  588. package/dist/voice/controller.d.mts +55 -0
  589. package/dist/voice/controller.d.mts.map +1 -0
  590. package/dist/voice/controller.mjs +120 -0
  591. package/dist/voice/controller.mjs.map +1 -0
  592. package/dist/voice/index.d.mts +13 -0
  593. package/dist/voice/index.mjs +12 -0
  594. package/dist/voice/outbox.d.mts +40 -0
  595. package/dist/voice/outbox.d.mts.map +1 -0
  596. package/dist/voice/outbox.mjs +71 -0
  597. package/dist/voice/outbox.mjs.map +1 -0
  598. package/dist/voice/projection.d.mts +103 -0
  599. package/dist/voice/projection.d.mts.map +1 -0
  600. package/dist/voice/projection.mjs +196 -0
  601. package/dist/voice/projection.mjs.map +1 -0
  602. package/dist/voice/protocol.d.mts +217 -0
  603. package/dist/voice/protocol.d.mts.map +1 -0
  604. package/dist/voice/protocol.mjs +197 -0
  605. package/dist/voice/protocol.mjs.map +1 -0
  606. package/dist/voice/react.d.mts +56 -0
  607. package/dist/voice/react.d.mts.map +1 -0
  608. package/dist/voice/react.mjs +226 -0
  609. package/dist/voice/react.mjs.map +1 -0
  610. package/dist/voice/session-log.d.mts +77 -0
  611. package/dist/voice/session-log.d.mts.map +1 -0
  612. package/dist/voice/session-log.mjs +137 -0
  613. package/dist/voice/session-log.mjs.map +1 -0
  614. package/dist/voice/session.d.mts +56 -0
  615. package/dist/voice/session.d.mts.map +1 -0
  616. package/dist/voice/session.mjs +48 -0
  617. package/dist/voice/session.mjs.map +1 -0
  618. package/dist/voice/speech.d.mts +70 -0
  619. package/dist/voice/speech.d.mts.map +1 -0
  620. package/dist/voice/speech.mjs +57 -0
  621. package/dist/voice/speech.mjs.map +1 -0
  622. package/dist/voice/tool-bridge.d.mts +24 -0
  623. package/dist/voice/tool-bridge.d.mts.map +1 -0
  624. package/dist/voice/tool-bridge.mjs +46 -0
  625. package/dist/voice/tool-bridge.mjs.map +1 -0
  626. package/dist/voice/tool-server.d.mts +111 -0
  627. package/dist/voice/tool-server.d.mts.map +1 -0
  628. package/dist/voice/tool-server.mjs +88 -0
  629. package/dist/voice/tool-server.mjs.map +1 -0
  630. package/dist/voice/transport.d.mts +19 -0
  631. package/dist/voice/transport.d.mts.map +1 -0
  632. package/dist/voice/transport.mjs +7 -0
  633. package/dist/voice/transport.mjs.map +1 -0
  634. package/dist/voice/websocket.d.mts +30 -0
  635. package/dist/voice/websocket.d.mts.map +1 -0
  636. package/dist/voice/websocket.mjs +79 -0
  637. package/dist/voice/websocket.mjs.map +1 -0
  638. package/package.json +177 -3
  639. package/src/background-execution-internal.ts +10 -0
  640. package/src/classification/errors.ts +79 -0
  641. package/src/classification/index.ts +53 -0
  642. package/src/classification/model.ts +270 -0
  643. package/src/classification/schema.ts +154 -0
  644. package/src/client/README.md +13 -0
  645. package/src/client/attachments.ts +85 -0
  646. package/src/client/index.ts +27 -8
  647. package/src/client/state.ts +585 -169
  648. package/src/client/transport.ts +975 -123
  649. package/src/compaction/budget.ts +55 -0
  650. package/src/compaction/checkpoint.ts +69 -0
  651. package/src/compaction/estimator.ts +91 -0
  652. package/src/compaction/index.ts +92 -0
  653. package/src/compaction/retry.ts +167 -0
  654. package/src/compaction/summary.ts +214 -0
  655. package/src/compaction/transformer.ts +55 -0
  656. package/src/compaction/window.ts +191 -0
  657. package/src/loop/README.md +15 -0
  658. package/src/loop/accumulator.ts +75 -26
  659. package/src/loop/collect.ts +268 -0
  660. package/src/loop/error.ts +64 -34
  661. package/src/loop/index.ts +40 -3
  662. package/src/loop/layer.ts +32 -0
  663. package/src/loop/llm-event.ts +1 -0
  664. package/src/loop/run.ts +871 -254
  665. package/src/loop/services/llm-provider.ts +3 -0
  666. package/src/loop/services/loop-config.ts +4 -4
  667. package/src/loop/services/tool-executor.ts +31 -6
  668. package/src/loop/testing/faux-provider.ts +2 -0
  669. package/src/loop/testing/index.ts +2 -0
  670. package/src/oauth/error.ts +18 -0
  671. package/src/oauth/index.ts +14 -0
  672. package/src/oauth/source.ts +36 -0
  673. package/src/oauth/token.ts +31 -0
  674. package/src/protocol/README.md +1 -1
  675. package/src/protocol/bounded-text.ts +78 -0
  676. package/src/protocol/content.ts +324 -34
  677. package/src/protocol/event.ts +357 -23
  678. package/src/protocol/index.ts +172 -3
  679. package/src/protocol/message.ts +318 -6
  680. package/src/protocol/nested-tool-calls.ts +261 -0
  681. package/src/protocol/reasoning.ts +1 -0
  682. package/src/protocol/session.ts +31 -2
  683. package/src/protocol/tool-argument-hints.ts +113 -0
  684. package/src/protocol/tool.ts +1265 -17
  685. package/src/providers/anthropic/claude-provider.ts +96 -0
  686. package/src/providers/anthropic/claude.ts +154 -0
  687. package/src/providers/anthropic/conformance/cases.ts +467 -0
  688. package/src/providers/anthropic/conformance/claude-usage-cases.ts +85 -0
  689. package/src/providers/anthropic/conformance/claude-usage-snapshot.ts +36 -0
  690. package/src/providers/anthropic/conformance/error-envelope.ts +56 -0
  691. package/src/providers/anthropic/conformance/index.ts +89 -0
  692. package/src/providers/anthropic/conformance/max-tokens.ts +65 -0
  693. package/src/providers/anthropic/conformance/plain-text.ts +68 -0
  694. package/src/providers/anthropic/conformance/thinking-before-text.ts +75 -0
  695. package/src/providers/anthropic/conformance/tool-use-input-deltas.ts +90 -0
  696. package/src/providers/anthropic/index.ts +21 -0
  697. package/src/providers/anthropic/usage.ts +175 -0
  698. package/src/providers/anthropic-messages-provider-internal.ts +147 -0
  699. package/src/providers/anthropic-provider-internal.ts +2103 -0
  700. package/src/providers/openai/codex-provider.ts +236 -0
  701. package/src/providers/openai/codex-usage.ts +213 -0
  702. package/src/providers/openai/codex.ts +85 -0
  703. package/src/providers/openai/conformance/cases.ts +290 -0
  704. package/src/providers/openai/conformance/codex-cases.ts +103 -0
  705. package/src/providers/openai/conformance/codex-error-envelope.ts +53 -0
  706. package/src/providers/openai/conformance/codex-function-call-arguments.ts +88 -0
  707. package/src/providers/openai/conformance/codex-plain-text.ts +73 -0
  708. package/src/providers/openai/conformance/codex-terminal-event.ts +70 -0
  709. package/src/providers/openai/conformance/codex-usage-cases.ts +87 -0
  710. package/src/providers/openai/conformance/codex-usage-snapshot.ts +37 -0
  711. package/src/providers/openai/conformance/error-envelope.ts +56 -0
  712. package/src/providers/openai/conformance/index.ts +126 -0
  713. package/src/providers/openai/conformance/json-plain-text.ts +53 -0
  714. package/src/providers/openai/conformance/plain-text.ts +66 -0
  715. package/src/providers/openai/conformance/responses-cases-internal.ts +580 -0
  716. package/src/providers/openai/conformance/subscription-usage-cases-internal.ts +199 -0
  717. package/src/providers/openai/conformance/tool-call-deltas.ts +91 -0
  718. package/src/providers/openai/index.ts +19 -0
  719. package/src/providers/openai/provider.ts +1892 -0
  720. package/src/providers/openai/realtime/client-codec.ts +84 -0
  721. package/src/providers/openai/realtime/events.ts +371 -0
  722. package/src/providers/openai/realtime/index.ts +56 -0
  723. package/src/providers/openai/realtime/session-config.ts +394 -0
  724. package/src/providers/openai/realtime/to-voice.ts +75 -0
  725. package/src/providers/openai/speech.ts +276 -0
  726. package/src/providers/openai-responses-provider-internal.ts +1692 -0
  727. package/src/providers/opencode/conformance/cases.ts +372 -0
  728. package/src/providers/opencode/conformance/chat-plain-text.ts +64 -0
  729. package/src/providers/opencode/conformance/index.ts +63 -0
  730. package/src/providers/opencode/conformance/messages-plain-text.ts +65 -0
  731. package/src/providers/opencode/conformance/responses-commentary-replay.ts +96 -0
  732. package/src/providers/opencode/conformance/responses-plain-text.ts +63 -0
  733. package/src/providers/opencode/conformance/usage-snapshot.ts +35 -0
  734. package/src/providers/opencode/go-provider.ts +144 -0
  735. package/src/providers/opencode/usage.ts +159 -0
  736. package/src/providers/provider-error.ts +267 -0
  737. package/src/providers/subscription-usage-internal.ts +128 -0
  738. package/src/providers/subscription-usage.ts +97 -0
  739. package/src/providers/transcript.ts +20 -0
  740. package/src/providers/vercel/ai-gateway-classifier.ts +492 -0
  741. package/src/providers/vercel/ai-gateway-credential-internal.ts +10 -0
  742. package/src/providers/vercel/ai-gateway-provider.ts +157 -0
  743. package/src/providers/vercel/conformance/cases.ts +319 -0
  744. package/src/providers/vercel/conformance/classifier-boolean.ts +51 -0
  745. package/src/providers/vercel/conformance/classifier-cases.ts +333 -0
  746. package/src/providers/vercel/conformance/classifier-choice.ts +58 -0
  747. package/src/providers/vercel/conformance/classifier-error-envelope.ts +51 -0
  748. package/src/providers/vercel/conformance/classifier-score.ts +56 -0
  749. package/src/providers/vercel/conformance/deepseek-reasoning.ts +72 -0
  750. package/src/providers/vercel/conformance/error-envelope.ts +55 -0
  751. package/src/providers/vercel/conformance/index.ts +99 -0
  752. package/src/providers/vercel/conformance/plain-text.ts +59 -0
  753. package/src/providers/vercel/conformance/tool-call-deltas.ts +78 -0
  754. package/src/providers/xai/conformance/cases.ts +115 -0
  755. package/src/providers/xai/conformance/error-envelope.ts +51 -0
  756. package/src/providers/xai/conformance/function-call-arguments.ts +79 -0
  757. package/src/providers/xai/conformance/index.ts +81 -0
  758. package/src/providers/xai/conformance/plain-text.ts +64 -0
  759. package/src/providers/xai/conformance/terminal-event.ts +62 -0
  760. package/src/providers/xai/conformance/usage-cases.ts +145 -0
  761. package/src/providers/xai/conformance/usage-snapshot.ts +37 -0
  762. package/src/providers/xai/grok-provider.ts +138 -0
  763. package/src/providers/xai/grok.ts +171 -0
  764. package/src/providers/xai/index.ts +22 -0
  765. package/src/providers/xai/usage.ts +302 -0
  766. package/src/react/chat-actions.ts +33 -0
  767. package/src/react/chat-core.ts +419 -0
  768. package/src/react/chat-items.ts +446 -0
  769. package/src/react/chat-messages.ts +1990 -0
  770. package/src/react/chat-session-events.ts +48 -0
  771. package/src/react/index.ts +81 -0
  772. package/src/react/use-agent-chat.ts +472 -0
  773. package/src/runtime/error.ts +35 -36
  774. package/src/runtime/index.ts +6 -2
  775. package/src/runtime/run-runtime.ts +143 -101
  776. package/src/runtime/session-event-store.ts +42 -48
  777. package/src/skillset/command.ts +227 -0
  778. package/src/skillset/errors.ts +17 -0
  779. package/src/skillset/index.ts +29 -0
  780. package/src/skillset/manifest.ts +17 -0
  781. package/src/skillset/markdown.ts +75 -0
  782. package/src/skillset/merge.ts +61 -0
  783. package/src/skillset/name.ts +29 -0
  784. package/src/skillset/skill.ts +75 -0
  785. package/src/tools/README.md +222 -18
  786. package/src/tools/arguments.ts +743 -0
  787. package/src/tools/background.ts +214 -0
  788. package/src/tools/index.ts +115 -17
  789. package/src/tools/input.ts +197 -0
  790. package/src/tools/interaction.ts +365 -0
  791. package/src/tools/ledger.ts +1068 -0
  792. package/src/tools/question.ts +8 -3
  793. package/src/tools/registry.ts +1288 -81
  794. package/src/tools/sha256.ts +98 -0
  795. package/src/tools/subagent.ts +806 -0
  796. package/src/voice/browser/index.ts +14 -0
  797. package/src/voice/browser/webrtc.ts +341 -0
  798. package/src/voice/client-codec.ts +23 -0
  799. package/src/voice/controller.ts +318 -0
  800. package/src/voice/index.ts +128 -0
  801. package/src/voice/outbox.ts +165 -0
  802. package/src/voice/projection.ts +394 -0
  803. package/src/voice/protocol.ts +351 -0
  804. package/src/voice/react.ts +419 -0
  805. package/src/voice/session-log.ts +200 -0
  806. package/src/voice/session.ts +138 -0
  807. package/src/voice/speech.ts +100 -0
  808. package/src/voice/tool-bridge.ts +97 -0
  809. package/src/voice/tool-server.ts +182 -0
  810. package/src/voice/transport.ts +17 -0
  811. package/src/voice/websocket.ts +156 -0
  812. package/dist/tools/task.d.mts +0 -53
  813. package/dist/tools/task.d.mts.map +0 -1
  814. package/dist/tools/task.mjs +0 -110
  815. package/dist/tools/task.mjs.map +0 -1
  816. package/src/tools/task.ts +0 -200
package/README.md CHANGED
@@ -1,49 +1,147 @@
1
1
  # @yolk-sdk/agent
2
2
 
3
- Domain-free agent protocol, loop, runtime, client, and tool primitives.
3
+ Domain-free agent protocol, loop, runtime, Effect-native client, compaction, classifier models, tools, React, providers, OAuth, skillset, and voice primitives.
4
4
 
5
- Root export is intentionally tiny. Import feature APIs from explicit subpaths.
5
+ Root export is intentionally empty. Import feature APIs from explicit subpaths.
6
6
 
7
7
  ## Install
8
8
 
9
9
  ```bash
10
- pnpm add @yolk-sdk/agent@canary effect
10
+ pnpm add @yolk-sdk/agent@canary effect@4.0.0
11
11
  ```
12
12
 
13
+ Add `react` if you use `@yolk-sdk/agent/react` or `@yolk-sdk/agent/voice/react`.
14
+
15
+ Running the experimental `@yolk-sdk/agent/providers/*/conformance` cases? Also add `@yolk-sdk/conformance@canary` (usually as a dev dependency); the cases run through `@yolk-sdk/conformance/runner`.
16
+
13
17
  Canary APIs are unstable. Keep all `@yolk-sdk/*` packages on the same version.
18
+ Use the SDK's matching Effect version (`4.0.0`) in host code.
19
+ Published package metadata requires Node.js 22+.
14
20
 
15
21
  ## Subpaths
16
22
 
17
- | Subpath | Purpose |
18
- | ------------------------------ | -------------------------------------------------------------- |
19
- | `@yolk-sdk/agent/protocol` | Wire messages, events, content, usage, tool schemas |
20
- | `@yolk-sdk/agent/loop` | Stateless LLM/tool loop |
21
- | `@yolk-sdk/agent/loop/testing` | Faux provider and tool executor test helpers |
22
- | `@yolk-sdk/agent/runtime` | Transcript or append-backed runtime orchestration |
23
- | `@yolk-sdk/agent/client` | HTTP/NDJSON transport and client state helpers |
24
- | `@yolk-sdk/agent/tools` | Tool module registry, `makeTool`, task/question tool contracts |
23
+ | Subpath | Purpose |
24
+ | -------------------------------------------------------- | --------------------------------------------------------------------------------------------- |
25
+ | `@yolk-sdk/agent/protocol` | Wire messages, events, content, usage, tool schemas |
26
+ | `@yolk-sdk/agent/loop` | Stateless LLM/tool loop |
27
+ | `@yolk-sdk/agent/loop/testing` | Faux provider and tool executor test helpers |
28
+ | `@yolk-sdk/agent/runtime` | Transcript or append-backed runtime orchestration |
29
+ | `@yolk-sdk/agent/client` | HTTP/NDJSON transport, HITL resume, retry/error state helpers |
30
+ | `@yolk-sdk/agent/compaction` | Host-owned compaction budgets, checkpoints, formatting, retry |
31
+ | `@yolk-sdk/agent/classification` | Classifier model contract: typed questions, answers, usage, errors |
32
+ | `@yolk-sdk/agent/tools` | Tool registry, typed inputs, interactions, subagents/questions, durable tool ledger |
33
+ | `@yolk-sdk/agent/react` | Headless React chat hook, reducer, selectors, and render model |
34
+ | `@yolk-sdk/agent/oauth` | Provider-neutral OAuth token and broker contracts |
35
+ | `@yolk-sdk/agent/providers/openai` | OpenAI/Codex OAuth and broker helpers |
36
+ | `@yolk-sdk/agent/providers/openai/codex` | OpenAI Codex request and auth helpers |
37
+ | `@yolk-sdk/agent/providers/openai/codex-usage` | Codex subscription-allowance snapshots |
38
+ | `@yolk-sdk/agent/providers/openai/codex-provider` | Codex LLM provider factory |
39
+ | `@yolk-sdk/agent/providers/openai/provider` | OpenAI-compatible LLM provider factory |
40
+ | `@yolk-sdk/agent/providers/openai/conformance` | Synthetic OpenAI chat, Codex Responses, and Codex usage fixtures and conformance cases |
41
+ | `@yolk-sdk/agent/providers/openai/realtime` | OpenAI Realtime session config and event codecs |
42
+ | `@yolk-sdk/agent/providers/openai/speech` | OpenAI text-to-speech and transcription adapters |
43
+ | `@yolk-sdk/agent/providers/vercel/ai-gateway-provider` | Vercel AI Gateway Chat Completions provider factory |
44
+ | `@yolk-sdk/agent/providers/vercel/ai-gateway-classifier` | Vercel AI Gateway classifier (`POST /v1/evaluate`) layer |
45
+ | `@yolk-sdk/agent/providers/vercel/conformance` | Verified Gateway chat fixtures, synthetic classifier fixtures, and conformance cases |
46
+ | `@yolk-sdk/agent/providers/opencode/go-provider` | OpenCode Go Chat Completions, Messages, and Responses provider |
47
+ | `@yolk-sdk/agent/providers/opencode/usage` | OpenCode Go subscription-allowance snapshots |
48
+ | `@yolk-sdk/agent/providers/opencode/conformance` | Synthetic OpenCode Go (per protocol, commentary replay, usage) fixtures and conformance cases |
49
+ | `@yolk-sdk/agent/providers/anthropic` | Anthropic/Claude OAuth and broker helpers |
50
+ | `@yolk-sdk/agent/providers/anthropic/claude` | Claude request and auth helpers |
51
+ | `@yolk-sdk/agent/providers/anthropic/usage` | Claude subscription-allowance snapshots |
52
+ | `@yolk-sdk/agent/providers/anthropic/claude-provider` | Claude LLM provider factory |
53
+ | `@yolk-sdk/agent/providers/anthropic/conformance` | Synthetic Anthropic Messages and Claude usage fixtures and conformance cases |
54
+ | `@yolk-sdk/agent/providers/xai` | Grok subscription OAuth and token broker helpers |
55
+ | `@yolk-sdk/agent/providers/xai/grok` | Grok subscription request and auth helpers |
56
+ | `@yolk-sdk/agent/providers/xai/grok-provider` | Grok subscription LLM provider factory |
57
+ | `@yolk-sdk/agent/providers/xai/usage` | Grok subscription-allowance snapshots |
58
+ | `@yolk-sdk/agent/providers/xai/conformance` | Synthetic Grok Responses and Grok usage fixtures and conformance cases |
59
+ | `@yolk-sdk/agent/providers/subscription-usage` | Shared allowance snapshot and safe error schemas |
60
+ | `@yolk-sdk/agent/skillset` | Portable skill and slash-command parsing/catalogs |
61
+ | `@yolk-sdk/agent/voice` | Voice protocol, controller, tool handler, projection, speech |
62
+ | `@yolk-sdk/agent/voice/browser` | Browser WebRTC voice transport |
63
+ | `@yolk-sdk/agent/voice/react` | Headless browser voice React hook |
25
64
 
26
65
  ## Imports
27
66
 
28
67
  ```ts
29
- import { makeSubagentRunId, UserMessage } from '@yolk-sdk/agent/protocol'
68
+ import {
69
+ danglingHostToolCalls,
70
+ hitlResponseEvent,
71
+ isTerminalAgentEvent,
72
+ makeSubagentRunId,
73
+ ProviderErrorInfo,
74
+ PlainHitlResponse,
75
+ questionResponseStructuredContent,
76
+ repairDanglingHostToolCalls,
77
+ UserMessage,
78
+ validateNoDanglingHostToolCalls
79
+ } from '@yolk-sdk/agent/protocol'
30
80
  import { run } from '@yolk-sdk/agent/loop'
31
- import { runRuntime } from '@yolk-sdk/agent/runtime'
32
- import { initialAgentClientState } from '@yolk-sdk/agent/client'
81
+ import { runRuntime, RuntimeRequest } from '@yolk-sdk/agent/runtime'
82
+ import {
83
+ documentPartFromTextFile,
84
+ initialAgentClientState,
85
+ streamAgentEventStreamUntilTerminal,
86
+ toolRunsFromHitlRequests
87
+ } from '@yolk-sdk/agent/client'
33
88
  import {
34
- makeNonRecursiveTaskToolModule,
35
- makeTaskToolResult,
89
+ makeContextBudget,
90
+ makePreviewSummaryMessage,
91
+ makeWindowCompactionTransformer
92
+ } from '@yolk-sdk/agent/compaction'
93
+ import {
94
+ makeInteractionTool,
95
+ makeNonRecursiveSubagentToolModule,
96
+ makeSubagentToolResult,
97
+ modelVisibleToolError,
98
+ modelVisibleToolErrorStructuredContent,
36
99
  makeQuestionToolModule,
37
- resolveTools
100
+ omitNullOptionalToolArguments,
101
+ resolveTools,
102
+ withToolArgumentsErrorHint
38
103
  } from '@yolk-sdk/agent/tools'
104
+ import {
105
+ AgentChatAction,
106
+ AgentChatPart,
107
+ applyAgentEventToChatProjection,
108
+ makeAgentChatEventProjectionState,
109
+ useAgentChat
110
+ } from '@yolk-sdk/agent/react'
111
+ import { makeVercelAiGatewayProviderLayer } from '@yolk-sdk/agent/providers/vercel/ai-gateway-provider'
39
112
  ```
40
113
 
114
+ `RuntimeRequest` is a value on `@yolk-sdk/agent/runtime` (`Transcript`, `AppendInput`, `AppendHitlResponse`). Pass `RuntimeRequest.Transcript({ sessionId, messages })` into `runRuntime`. For append requests, omitted or `undefined` `expectedRevision` still means use the loaded log revision (`??`).
115
+
41
116
  Test helpers live behind their own subpath:
42
117
 
43
118
  ```ts
44
119
  import { FauxProvider, Reply, TestToolExecutor } from '@yolk-sdk/agent/loop/testing'
45
120
  ```
46
121
 
122
+ ## Headless React chat
123
+
124
+ `useAgentChat` exposes protocol messages, render-oriented chat messages, run/error/waiting state,
125
+ and actions for submit, stop, edit, regenerate, delete, tool approval, question, and typed input responses. The
126
+ package supplies no components, styling, auth, or route ownership, and React remains an optional
127
+ peer used only by React subpaths.
128
+
129
+ Chat ADTs on `@yolk-sdk/agent/react` are value constructors: `AgentChatPart`, `ChatToolState`,
130
+ `DeleteChatTurnResult`, `EditChatUserMessageResult`, `RegenerateChatMessagesResult`, `AgentChatItem`,
131
+ `ToolRunState`, `AgentChatAction`, and hook results such as `AgentChatSubmitResult`. They are
132
+ `Data.taggedEnum` plain objects (`_tag` last), not Equal/Hash classes. Duration descriptors use
133
+ `ToolDurationKnown` / `ToolDurationUnknown` (`Schema.TaggedStruct.make` validates those plains).
134
+ Prefer `AgentChatPart.Text({ ... })` over handwritten `{ _tag: 'Text', ... }`, omit absent optionals,
135
+ and discriminate with `$is` (for example `AgentChatSubmitResult.$is('Submitted')(result)`).
136
+ `useAgentChat` dispatches `AgentChatAction` constructors and returns those hook-result values.
137
+
138
+ By default the hook streams HTTP/NDJSON through `@yolk-sdk/agent/client`. Pass an
139
+ `AgentChatTransport` through the `transport` option to use another runtime. A custom transport
140
+ receives the transcript, session/model options, HITL responses, and an `AbortSignal`, and returns an
141
+ `AsyncIterable<AgentEvent>`; the host still owns endpoint auth and persistence. Custom transport
142
+ rejections are normalized to `AgentTransportError` internally while retaining the original cause.
143
+ Native abort causes stop quietly; other non-Error rejections display `Agent request failed`.
144
+
47
145
  ## Quick start
48
146
 
49
147
  ```ts
@@ -61,60 +159,857 @@ const program = run({
61
159
  // Provide LLM provider, loop config, context transformer, and tool executor layers in the host app.
62
160
  ```
63
161
 
162
+ Loop composition is those four Layers plus `run` / `runModelTurn` / `runToolBatch`.
163
+ Merge them with `makeAgentLoopLayer`. Omitted tools use `ToolExecutor.unavailable`; omitted transformer/config use identity and `LoopConfig.defaultLayer`.
164
+ Intercept by decorating a service (`decorateLLMProvider`), not with hooks.
165
+ Durable hosts fold model-turn steps with `collectModelTurn`. Use `collectModelTurnAttempt` when the fold must retain partial output after a failed stream. Kernel incomplete streams (zero `Done` events) set optional `LLMError.responseIssue: 'missing_done'` and stay `invalid_response` / `retryable: false`.
166
+
167
+ ```ts
168
+ import { makeAgentLoopLayer } from '@yolk-sdk/agent/loop'
169
+ import { FauxProvider, Reply } from '@yolk-sdk/agent/loop/testing'
170
+
171
+ const LoopLayer = makeAgentLoopLayer({
172
+ provider: FauxProvider.layer(Reply.text('ok'))
173
+ })
174
+ ```
175
+
176
+ Guide source: [Loop and runtime](https://github.com/magoz/yolk-sdk/blob/main/apps/docs/content/docs/agent/loop-runtime.mdx#compose-the-loop-layer).
177
+
178
+ ## OAuth credentials
179
+
180
+ `@yolk-sdk/agent/oauth` defines provider-neutral access-token, broker, freshness, and credential-source
181
+ contracts. Provider subpaths add vendor request/response conversion without owning persistence.
182
+
183
+ ```ts
184
+ import { credentialSourceFromBroker, type TokenBrokerClient } from '@yolk-sdk/agent/oauth'
185
+
186
+ const makeTokenProgram = (hostBroker: TokenBrokerClient) =>
187
+ credentialSourceFromBroker(hostBroker, {
188
+ provider: 'openai-codex',
189
+ subjectId: 'host-user-id'
190
+ }).getAccessToken({ minTtlSeconds: 300 })
191
+ ```
192
+
193
+ `hostBroker` is a host implementation of `TokenBrokerClient`. The host stores, refreshes, revokes,
194
+ and authorizes credentials; the package receives short-lived access tokens and never persists
195
+ secrets.
196
+
197
+ ## Provider configuration
198
+
199
+ Provider output limits are host-owned when the endpoint supports them. Yolk does not infer model
200
+ limits or apply hidden fallbacks.
201
+
202
+ | Provider factory | Output-limit field |
203
+ | ---------------------------------- | --------------------- |
204
+ | `makeOpenAiProviderLayer` | `maxCompletionTokens` |
205
+ | `makeVercelAiGatewayProviderLayer` | `maxCompletionTokens` |
206
+ | `makeOpenCodeGoProviderLayer` | `maxOutputTokens` |
207
+ | `makeOpenAiCodexProviderLayer` | none |
208
+ | `makeAnthropicClaudeProviderLayer` | `maxTokens` |
209
+ | `makeXAiGrokProviderLayer` | `maxOutputTokens` |
210
+
211
+ The public `toOpenAiRequestBody`, `toAnthropicClaudeRequestBody`, and `toXAiGrokRequestBody` helpers
212
+ require the matching limit configuration. ChatGPT subscription Codex rejects vendor
213
+ `max_output_tokens`, so `makeOpenAiCodexProviderLayer` and `toOpenAiCodexRequestBody` ignore the
214
+ optional deprecated `maxOutputTokens` compatibility field. `OpenAiProviderLayer` reads both
215
+ `OPENAI_API_KEY` and integer `OPENAI_MAX_COMPLETION_TOKENS` through Effect Config.
216
+
217
+ OpenCode Go uses API-key authentication with an explicit host-selected `protocol`:
218
+ `chat-completions`, `messages`, or `responses`. Model IDs stay opaque: pass the Go API model ID
219
+ without OpenCode's `opencode-go/` CLI prefix. The SDK does not fetch a catalog or guess the protocol
220
+ from a model name. Check the [Go endpoint catalog](https://opencode.ai/docs/go/#endpoints).
221
+
222
+ Server-side configuration fragment (the host supplies credentials and model policy):
223
+
224
+ ```ts
225
+ import { Layer, Redacted } from 'effect'
226
+ import { FetchHttpClient } from 'effect/http'
227
+ import { makeOpenCodeGoProviderLayer } from '@yolk-sdk/agent/providers/opencode/go-provider'
228
+
229
+ const GoLayer = makeOpenCodeGoProviderLayer({
230
+ apiKey: Redacted.make(hostOpenCodeGoApiKey),
231
+ protocol: 'messages',
232
+ maxOutputTokens: hostModelConfig.maxOutputTokens
233
+ }).pipe(Layer.provide(FetchHttpClient.layer))
234
+ ```
235
+
236
+ The default base URL is `https://opencode.ai/zen/go/v1`. Chat streams SSE (the Go adapter sets
237
+ `streaming: true`) with Bearer auth; Messages uses SSE and `x-api-key`; Responses uses SSE and Bearer
238
+ auth. All normalize to `LLMEvent`s.
239
+ Messages retains native tool names and system instructions, without Claude OAuth fingerprinting.
240
+ Responses sends `max_output_tokens`, unlike Codex. Go requires a nonempty key and positive safe-integer
241
+ limit at layer construction. `extraHeaders` cannot override required protocol headers, regardless of
242
+ case. Only override `baseUrl` with a trusted proxy because it receives the credential.
243
+
244
+ Request `reasoningEffort` becomes chat `reasoning_effort`, Messages `output_config.effort` (omitting
245
+ `minimal`), or Responses `reasoning.effort` with `summary: 'auto'`. `reasoningSummary` changes the
246
+ Responses summary mode. Hosts must offer only model-supported efforts and media capabilities.
247
+ Chat preserves provider `reasoning_content` in events and assistant replay. No OAuth, model discovery,
248
+ automatic polling, or example-app UI integration is included.
249
+
250
+ Read Go subscription allowance separately from per-request token usage (server-side fragment):
251
+
252
+ ```ts
253
+ import { Effect, Redacted } from 'effect'
254
+ import { FetchHttpClient } from 'effect/http'
255
+ import { fetchOpenCodeGoSubscriptionUsage } from '@yolk-sdk/agent/providers/opencode/usage'
256
+
257
+ const usageEffect = fetchOpenCodeGoSubscriptionUsage(Redacted.make(hostOpenCodeGoApiKey), {
258
+ requestTimeoutMs: 10_000
259
+ }).pipe(Effect.provide(FetchHttpClient.layer))
260
+ ```
261
+
262
+ The API-key endpoint (default `openCodeGoSubscriptionUsageUrl`) returns used percentages/reset instants for `five-hour`, `seven-day`, and
263
+ `monthly` windows. Monthly resets follow the subscription's anniversary, not the first of the month;
264
+ the adapter preserves the provider's timestamp. Missing/invalid percentages are omitted, not treated
265
+ as zero. Treat snapshots as best-effort; hosts own polling, stale-data policy, persistence, and UI.
266
+ The fetcher blocks redirects and sanitizes failures using the shared subscription-usage error types.
267
+
268
+ Vercel AI Gateway uses its OpenAI-compatible Chat Completions endpoint, with a single JSON
269
+ completion by default. Native PDF `DocumentPart` inputs are lowered to Gateway file parts by
270
+ default; the selected Gateway model must advertise PDF input. Set factory option `streaming: true`
271
+ for SSE deltas and independently set `reasoningContent: true` to preserve compatible models'
272
+ `reasoning_content` output and assistant
273
+ replay. Both default to false; replayed reasoning spends input tokens. Pass either an AI
274
+ Gateway API key or Vercel OIDC token as `apiKey`; `maxCompletionTokens` is sent as Gateway
275
+ `max_tokens`. The env-backed `VercelAiGatewayProviderLayer` tries `AI_GATEWAY_API_KEY` first, then
276
+ `VERCEL_OIDC_TOKEN`, and requires integer
277
+ `AI_GATEWAY_MAX_COMPLETION_TOKENS`. Model ids are opaque `provider/model` strings. Hosts may set
278
+ `fallbackModels`, provider `routing`, and optional `http-referer` / `x-title` attribution headers.
279
+ A request `reasoningEffort` is sent as Gateway `{ reasoning: { effort } }` by default; `reasoningEffortFormat: 'reasoning-effort'` sends the literal field instead (e.g. for DeepSeek-style hosts, with an optional `thinking` toggle merged into the request body). Hosts remain responsible for offering only efforts supported by the selected model. Required
280
+ authorization and JSON headers cannot be replaced through `extraHeaders`. Only override
281
+ `chatCompletionsUrl` with a trusted proxy because it receives the bearer credential.
282
+
283
+ Grok subscription access uses `https://cli-chat-proxy.grok.com/v1/responses`, not the xAI developer
284
+ API-key endpoint. The adapter sends the required CLI-session and model-routing headers and rejects
285
+ mismatched or expired access-token envelopes before HTTP. `makeXAiGrokProviderLayer` also requires
286
+ a truthful host-owned `clientVersion`, sent as `x-grok-client-version`, because the xAI CLI proxy
287
+ version-gates requests and rejects missing or outdated versions with HTTP 426; required headers
288
+ stay non-overridable through `extraHeaders`. The package exports browser-PKCE and
289
+ device-flow constants; hosts own the callback listener or device polling, token exchange/refresh,
290
+ secure storage, and model discovery. Only set `responsesUrl` to a trusted proxy because it receives
291
+ the OAuth bearer. xAI controls the public CLI OAuth client and private, unsupported proxy contract,
292
+ so hosts should treat those surfaces as changeable and confirm that their use complies with xAI
293
+ terms.
294
+
295
+ Set optional `reasoningEffort` on `run` or `runRuntime`; provider adapters lower it to vendor
296
+ configuration. Anthropic Claude forwards `low`, `medium`, `high`, and `xhigh` through
297
+ `output_config.effort`. It omits `minimal`, which Anthropic does not support. Hosts remain
298
+ responsible for choosing an effort accepted by the selected provider and model.
299
+
300
+ ### Anthropic tool schemas
301
+
302
+ Claude subscription OAuth rejects some valid JSON Schema constructs that Effect Schema can emit
303
+ for unions, refinements, and tuples. The Claude adapter therefore projects tool parameters to a
304
+ provider-compatible object schema without `anyOf`, `oneOf`, `allOf`, or tuple-only `prefixItems`.
305
+ When a constraint cannot be represented faithfully, the projection widens the model-facing schema
306
+ rather than excluding a valid call. Tool execution remains safe because `makeTool` validates the
307
+ returned arguments against the original Effect Schema (through its JSON codec) before invoking the
308
+ executor.
309
+
310
+ Before projection, `toAnthropicClaudeRequestBody` and the Claude provider decode `ToolDef.parameters`
311
+ and `ToolCall.params` as `Schema.Json`. Non-JSON values fail as non-retryable `LLMError` with
312
+ `cause: 'provider_error'`. `ToolDef.parameters` now admits `ToolJsonSchema` at construction;
313
+ `ToolCall.params` stays opaque. Provider admission also catches post-construction forgeries.
314
+ After lone-surrogate rewrite, the request
315
+ body is decoded as JSON again and fails rather than skipping serialization. HTTP error bodies that
316
+ are not JSON still classify from status. Tool-result blocks omit `is_error` when the result carries
317
+ no flag, so follow-up request bodies stay valid; an explicit boolean `isError` is still serialized.
318
+
319
+ ### Tool parameter documents
320
+
321
+ `ToolDef.parameters` uses `ToolJsonSchema` from `@yolk-sdk/agent/protocol`: a boolean schema or
322
+ plain JSON object. `ToolJsonSchemaObject` is the object arm; `decodeToolJsonSchema` and
323
+ `decodeToolJsonSchemaObject` return `Option`. This checks representation, not JSON Schema semantics.
324
+ Construction/decode preserve admitted identity and accept finite primitives, dense ordinary arrays,
325
+ plain/null-prototype objects, own `__proto__`/`constructor` keys and DAG aliases. Accessors are
326
+ rejected unread; exotic prototypes, hidden/symbol keys, undefined, nonfinite values and cycles fail.
327
+ No Proxy side-effect immunity or immutability is promised. Tool call parameters/results and HITL
328
+ remain opaque. Background wrapping preserves boolean `true`/`false` as the arguments schema;
329
+ reference/resource restrictions still apply at activation. `makeTool` may add root `type: "object"`
330
+ to typeless `anyOf`/`oneOf` unions whose members are all object schemas, as required by strict
331
+ OpenAI-compatible upstreams; primitives, unknown, and already-typed roots are unchanged, and call
332
+ validation still decodes through the original Effect Schema's JSON codec. Effect 4.0.0 exports
333
+ `Schema.isPattern` to JSON Schema only for `u`-flag regexes (optionally with `d`, `g`, or `y`);
334
+ add `u` to keep model-visible `pattern` hints.
335
+
336
+ ### Tool arguments: `null` and unknown keys
337
+
338
+ Tool arguments are accepted exactly as advertised: unambiguous `null`s are normalized, and keys
339
+ that would be silently lost are rejected. `ToolDef.parameters` describes the schema's canonical JSON codec, so `Schema.optional(X)` is
340
+ advertised as `X | null`. `makeTool` (validate and execute), `makeInputTool`/`makeInteractionTool`
341
+ call params, and the loop `question` decode model arguments with `Schema.toCodecJson(parameters)`:
342
+ `null` on `Schema.optional(X)` decodes as absent and `withDecodingDefault` still applies,
343
+ `Schema.optional(Schema.NullOr(X))` keeps `null`, and required non-nullable fields still reject it.
344
+ `undefined`-valued keys from in-process callers count as absent.
345
+ Non-finite numbers (the codec's `"NaN"`/`"Infinity"` strings) are validation errors. Objects are
346
+ advertised closed (`additionalProperties: false`), so unknown keys at any depth are model-visible
347
+ validation errors instead of being stripped (also through closed-input declarations whose JSON codec
348
+ bypasses their own parser). Their error message names each unknown key and lists the allowed keys at that path; this includes
349
+ a `null` on another union member's field.
350
+ `resolveTools` also drops `null` where the advertised schema declares a property optional without
351
+ admitting `null` (for example `Schema.optionalKey(X)`, the subagent `model`, or raw MCP schemas)
352
+ before any registration sees the call; `omitNullOptionalToolArguments` (`@yolk-sdk/agent/tools`) exposes that step for hosts
353
+ that dispatch registrations themselves. User-submitted input/interaction responses are unchanged.
354
+
355
+ ### OpenAI Chat Completions, Responses, and extraBody
356
+
357
+ OpenAI Chat Completions and Responses lowering (including Codex) likewise admits
358
+ `ToolDef.parameters` and tool-call `params` as `Schema.Json` before they are copied onto the request
359
+ body. Non-JSON tool documents and arguments fail as non-retryable `LLMError` `provider_error` before
360
+ transport. `ToolDef.parameters` admits `ToolJsonSchema`; `ToolCall.params` stays opaque. Public Codex wrapper
361
+ `OpenAiCodexTool.parameters` remains `unknown`; that field is not a `Schema.Json` input type.
362
+
363
+ Optional request-body fields such as `max_output_tokens`, `tools`, `parallel_tool_calls`, and
364
+ `reasoning` are omitted unless present — they are not own-property `undefined`. After lone-surrogate
365
+ rewrite, Chat Completions and Responses request bodies are decoded as `Schema.Json` again and fail
366
+ rather than skipping serialization. Inbound HTTP JSON bodies admit `Schema.Json` before class/helper
367
+ consumption (`invalid_response` on failure). Responses SSE event JSON admits `Schema.Json`;
368
+ non-object JSON events are ignored (not failed), while malformed non-JSON event text still fails
369
+ `invalid_response`. First `response.completed` remains terminal. HTTP error bodies stay raw text for
370
+ `classifyProviderFailure`.
371
+
372
+ Chat Completions transport defaults to one JSON body. Set `OpenAiProviderConfig.streaming: true` to
373
+ request incremental `chat.completion.chunk` SSE deltas with `stream_options.include_usage`, folded
374
+ into text/reasoning/tool-call events plus terminal and usage events. Unterminated streams fail
375
+ `invalid_response` and never emit `Done`. Hosts must only enable streaming against endpoints that
376
+ serve chat SSE; OpenCode Go `chat-completions` always sets it.
377
+
378
+ `OpenAiProviderConfig.extraBody` takes `OpenAiRequestExtras` (JSON-object input). Lowering
379
+ projects enumerable own string fields into an independent portable-data snapshot. Canonical
380
+ `model`, `messages`, `stream`, `tools`, `parallel_tool_calls`, `max_completion_tokens`, and
381
+ `max_tokens` are discarded **without reading their values**; `reasoning` is also discarded when
382
+ `reasoningEffortFormat` is `reasoning-object`. Root symbols/non-enumerable fields are not projected.
383
+ Surviving accessors are rejected unread. Nested values must be finite JSON data with plain/null
384
+ prototypes or dense ordinary arrays; exotic objects, cycles, hidden/symbol keys and extra array
385
+ properties fail. DAG aliases remain aliases in the snapshot; the input is not mutated or retained.
386
+ Invalid extras fail with non-retryable `provider_error`, fixed message
387
+ `Invalid … extraBody JSON: expected a JSON object`, and no HTTP request. Messages never echo values.
388
+ The composed request still passes final `Schema.Json` admission after lone-surrogate rewriting.
389
+ This is not a guarantee against Proxy traps. Gateway routing projects its declared `order`, `only`
390
+ and `sort` fields into JSON; canonical headers and provider identity stay host-owned.
391
+
392
+ ### OpenAI Realtime tool JSON
393
+
394
+ Public `OpenAiRealtimeFunctionTool.parameters` and `openAiRealtimeToolParameters(parameters: Schema.Json)`
395
+ now require admitted JSON. Non-JSON advertisement fails `VoiceToolBridgeError` before transport:
396
+ synchronous `toOpenAiRealtimeTool`, `makeOpenAiRealtimeSessionConfig`, and
397
+ `openAiRealtimeSessionConfigFromVoice` throw; `toOpenAiRealtimeToolEffect`,
398
+ `makeOpenAiRealtimeSessionConfigEffect`, and `openAiRealtimeSessionConfigFromVoiceEffect` fail in the
399
+ Effect error channel. Unexpected mapper defects (for example throwing getters) remain defects via
400
+ `Effect.suspend` / `Result`, not `VoiceToolBridgeError`.
401
+
402
+ Union-root lowering uses `Map<string, Schema.Json>` plus `Object.fromEntries` so own `__proto__` /
403
+ `constructor` fields merge (first-seen / string-enum union) instead of prototype assignment or
404
+ inherited `constructor` masquerading as Schema.Json. Required intersection, empty-required omission,
405
+ and object-root identity are unchanged.
406
+
407
+ ## Provider failures and retries
408
+
409
+ Provider adapters classify safe failure metadata at the boundary. The loop owns bounded retry
410
+ policy and emits protocol-visible retry/error state:
411
+
412
+ - `ProviderErrorInfo` carries safe provider id, failure kind, HTTP status, provider code, optional
413
+ `retryAfterMs`, and optional `stream` diagnostics (`ProviderStreamDiagnostics`) on chat
414
+ `unexpected_content_type` / `incomplete_stream` failures. Diagnostics contain counters and
415
+ milestones, never transcript content, raw headers, or body fragments. See the
416
+ [stream diagnostics guide](https://github.com/magoz/yolk-sdk/blob/main/apps/docs/content/docs/troubleshooting.mdx#diagnose-chat-stream-failures-with-stream-diagnostics).
417
+ - Chat Completions and Responses HTTP failures copy the envelope string `code` (falling back to
418
+ `type`) into `provider.providerCode`; free-text upstream bodies stay out of `LLMError`.
419
+ - `AgentRetry.provider` exposes current retry metadata and chosen `delayMs`.
420
+ - `AgentError.provider` preserves final terminal metadata.
421
+ - `AgentErrorCode` includes `rate_limit`, `overloaded`, `context_overflow`, and generic
422
+ `provider_error`.
423
+ - Client and React state keep `error: string | null` for compatibility and add typed `errorInfo` /
424
+ `retryInfo`.
425
+ - `buildAgentChatItems` can project active retry state as an `AgentChatItem` with `_tag: 'Retry'`.
426
+ - Anthropic prompt-too-long responses become non-retryable `context_overflow`; the host-owned
427
+ compaction wrapper may compact and retry once.
428
+ - Anthropic `max_tokens` and OpenAI-compatible `finish_reason: "length"` / `"content_filter"`
429
+ completions fail as non-retryable `invalid_response` instead of reporting truncated or filtered
430
+ output as complete.
431
+
432
+ Raw provider response bodies stay out of protocol/UI. Hosts own durable persistence and display of
433
+ typed retry/error state.
434
+
435
+ ## Subscription allowance snapshots
436
+
437
+ The Claude, Codex, and Grok usage adapters read best-effort consumer subscription allowance
438
+ percentages and reset windows. Claude normalizes its aggregate five-hour and seven-day windows;
439
+ Codex normalizes primary and secondary rate-limit windows; Grok normalizes its aggregate shared
440
+ credit allowance. Additional provider-specific buckets are ignored. These private provider
441
+ endpoints may change without notice. Pass a fresh host-owned `OAuthAccessToken` and provide an
442
+ Effect `HttpClient`:
443
+
444
+ ```ts
445
+ import { Effect } from 'effect'
446
+ import { FetchHttpClient } from 'effect/http'
447
+ import { fetchOpenAiCodexSubscriptionUsage } from '@yolk-sdk/agent/providers/openai/codex-usage'
448
+
449
+ const snapshot = await fetchOpenAiCodexSubscriptionUsage(hostOAuthAccessToken).pipe(
450
+ Effect.provide(FetchHttpClient.layer),
451
+ Effect.runPromise
452
+ )
453
+ ```
454
+
455
+ Use `fetchAnthropicClaudeSubscriptionUsage` from
456
+ `@yolk-sdk/agent/providers/anthropic/usage` for Claude. Use
457
+ `fetchXAiGrokSubscriptionUsage` from `@yolk-sdk/agent/providers/xai/usage` for Grok and pass the
458
+ actual authenticated xAI `user_id` as `xAiUserId`. The generic token `accountId` is not interpreted
459
+ as an xAI user id. Also pass your host integration's truthful version as `clientVersion`; the
460
+ adapter sends it with `x-grok-client-mode: headless` and never claims an official Grok client
461
+ version.
462
+
463
+ Provider adapters return an immutable Effect `Chunk` of semantic window ids, percentages, and
464
+ optional reset/duration fields; hosts own labels, polling, persistence, stale-data policy, alert
465
+ thresholds, billing interpretation, and UI. Configure `requestTimeoutMs` at the server integration
466
+ boundary. Each fetcher defaults to its exported URL constant; the optional `url` override is only
467
+ for a trusted proxy or local emulator, because the credential is sent to it. `FetchHttpClient.layer` is configured for manual
468
+ redirects. A custom `HttpClient` must not follow redirects for these credential-bearing requests.
469
+
470
+ Subscription allowance snapshots are separate from protocol `AgentUsage`, which accounts for tokens
471
+ used by model requests and nested model work.
472
+
473
+ ## Usage accounting
474
+
475
+ Provider `LLMUsage` events are additive deltas. Adapters normalize vendor counters before emitting;
476
+ for example, Anthropic stream snapshots become deltas and cached input tokens count toward input
477
+ totals. The loop aggregates usage and emits protocol `UsageUpdate` / terminal usage for hosts to
478
+ persist or display.
479
+
480
+ ## Context compaction
481
+
482
+ `@yolk-sdk/agent/compaction` provides pure budgeting, planning, estimation, checkpoint, and
483
+ formatting utilities plus Effect-native context-transformer and provider-retry adapters. It does
484
+ not summarize or persist checkpoints. Hosts own thresholds, summary policy, durable storage, and
485
+ active-run guards. The one-shot context-overflow wrapper calls your host compactor.
486
+
487
+ ```ts
488
+ import {
489
+ makeContextBudget,
490
+ makePreviewSummaryMessage,
491
+ makeWindowCompactionTransformer
492
+ } from '@yolk-sdk/agent/compaction'
493
+
494
+ const budget = makeContextBudget({
495
+ contextWindowTokens: 200_000,
496
+ reservedOutputTokens: 20_000,
497
+ warningRatio: 0.8,
498
+ compactionRatio: 1
499
+ })
500
+
501
+ const ContextLayer = makeWindowCompactionTransformer({
502
+ strategy: 'window-summary-v1',
503
+ thresholdTokens: budget.compactionInputTokens,
504
+ tailMessageCount: 16,
505
+ makeSummaryMessage: messages => makePreviewSummaryMessage(messages)
506
+ })
507
+ ```
508
+
509
+ The default estimator uses provider-neutral character and media heuristics. Pass
510
+ `TokenEstimateOptions.countTextTokens` to improve estimates for selected message text, reasoning,
511
+ and host tool-call identifiers, or pass a whole-transcript `estimateTokens` to planners and
512
+ transformers. Exact provider-request accounting must also include system prompts, tool definitions,
513
+ vendor framing, and a safety margin. Reuse one estimator for warnings, planning, and before/after
514
+ checks; tokenizer dependencies remain host-owned.
515
+
516
+ ## Skillsets
517
+
518
+ `@yolk-sdk/agent/skillset` parses skill Markdown and slash-command Markdown into portable
519
+ `SkillInfo`, `CommandInfo`, and `SkillsetManifest` data. Use `parseSkillMarkdown` /
520
+ `parseCommandMarkdown` at file or database boundaries, `renderCommand` for command invocation, and
521
+ `mergeSkillsets` to combine host sources. Earlier sources win name conflicts; duplicate names
522
+ inside one source fail validation. Hosts own file discovery, storage, enablement, and source order.
523
+
64
524
  ## Protocol content
65
525
 
66
526
  `Content` is either plain text or ordered parts:
67
527
 
68
528
  - `TextPart`
69
- - `ImagePart`
70
- - `DocumentPart`
71
- - `AudioPart`
529
+ - `ImagePart` with `InlineBase64`, `Url`, or host-owned `Ref` source
530
+ - `DocumentPart` with `InlineBase64`, `Url`, or host-owned `Ref` source
531
+ - `AudioPart` with `InlineBase64`, `Url`, or host-owned `Ref` source
532
+
533
+ Build sources with `inlineBase64AttachmentSource`, `urlAttachmentSource`, or
534
+ `refAttachmentSource`. OpenAI-compatible Chat Completions providers support inline text documents;
535
+ native PDF `DocumentPart` lowering is opt-in through `supportsPdfAttachments`, while Vercel AI
536
+ Gateway enables it by default (set `supportsPdfAttachments: false` to disable it). For URL-backed
537
+ user-message PDFs, both opted-in generic OpenAI chat and Gateway use the host-provided `HttpClient`
538
+ to fetch and buffer the PDF before sending inline file data; the provider does not fetch the URL.
539
+ Hosts must authorize attachment URLs and enforce destination and redirect policy, streamed-byte
540
+ limits, timeouts, safe logging, and credential isolation so provider credentials are never attached
541
+ to attachment destinations. The SDK resolver does not establish those guarantees. Prefer validated
542
+ inline bytes when the host cannot provide a bounded attachment transport. OpenAI Chat and Vercel AI
543
+ Gateway support image URLs; OpenAI Codex supports image
544
+ and document URLs; Anthropic supports image and PDF URLs. The Grok
545
+ Responses lowerer can encode image URLs/data URLs, but hosts should enable image capability only for
546
+ subscription models they have verified accept image input. Use
547
+ inline base64 for simple apps, durable URLs for app-owned uploads, or persist opaque `Ref` values and
548
+ resolve them immediately before each provider attempt. `resolveContentAttachmentSources` handles one
549
+ `Content`; `resolveMessageAttachmentSources` and `resolveMessagesAttachmentSources` also walk assistant
550
+ text and nested provider tool results, preserving metadata and ordering without mutating history.
551
+ All accept `AttachmentSourceResolver<E, R>`, preserve typed Effect errors/services, and leave opaque
552
+ tool/provider payloads alone. Resolution does not add provider media capabilities or cache sources.
553
+
554
+ Host apps own upload, authorization, byte/MIME limits, retention, and fresh signing. Put a host
555
+ resolving provider wrapper inside `makeContextOverflowRetryProvider` so compaction sees refs and each
556
+ retry signs the effective context afresh. Never persist the resolved copy. See the
557
+ [private attachment guide](https://github.com/magoz/yolk-sdk/blob/main/apps/docs/content/docs/guides/private-attachments.mdx) for the
558
+ host-owned composition and bounded connector transport.
559
+
560
+ OpenAI Codex preserves text, image, and document `ToolResultMessage` parts as native function output
561
+ content. Anthropic Claude preserves text, images, inline text documents, and URL/base64 PDFs as
562
+ nested tool-result content. OpenAI-compatible Chat Completions, including Vercel AI Gateway, keep
563
+ tool-result text in the tool message and lower images, readable text documents, and opted-in PDFs to
564
+ origin-labeled supplementary user content after the complete tool-result block. Canonical history is
565
+ unchanged. Audio, unresolved references, and other document formats still fail before the provider
566
+ request.
567
+
568
+ ```ts
569
+ import { ImagePart, UserMessage, urlAttachmentSource } from '@yolk-sdk/agent/protocol'
570
+
571
+ const message = UserMessage.make({
572
+ content: [
573
+ ImagePart.make({
574
+ source: urlAttachmentSource('https://cdn.example.com/image.webp'),
575
+ mimeType: 'image/webp'
576
+ })
577
+ ]
578
+ })
579
+ ```
580
+
581
+ For text files, use `documentPartFromText`, `inferTextDocumentMimeType`, and the client helper
582
+ `documentPartFromTextFile` to create UTF-8 inline
583
+ `DocumentPart` values without trusting filename extensions over explicit non-text MIME types.
72
584
 
73
585
  Use model capabilities like `textOnlyModelCapabilities`, `textImageModelCapabilities`, or
74
586
  `textImageDocumentModelCapabilities` so the loop rejects unsupported inputs before provider calls.
75
587
 
588
+ ## Message envelope
589
+
590
+ Messages may carry model-visible envelope facts without polluting authored `content`:
591
+
592
+ ```ts
593
+ UserMessage.make({
594
+ content: 'Can you summarize this?',
595
+ createdAtMs: 1781260200000,
596
+ author: { displayName: 'Magoz' },
597
+ annotations: {
598
+ source: 'web',
599
+ ui_origin: 'document_toolbar',
600
+ timezone: 'Europe/Madrid',
601
+ locale: 'en-US',
602
+ input_method: 'keyboard',
603
+ message_kind: 'question',
604
+ client_sent_at: '2026-06-12T10:30:00.000Z'
605
+ }
606
+ })
607
+ ```
608
+
609
+ - `content`: authored message body only.
610
+ - `createdAtMs`: message creation/sent time; providers render it as ISO `sent_at` context.
611
+ - `author.displayName`: presentation label only; not identity, auth, or a stable id.
612
+ - `annotations`: app-owned JSON object; context only, not instructions.
613
+
614
+ Provider adapters can use `messageContextText` and `prependMessageContextToContent` to render
615
+ envelopes into model input while keeping `content` authored-only.
616
+
617
+ Annotations must be JSON-compatible. Use stable app-owned keys, preferably `snake_case`. Use ISO
618
+ strings for dates inside annotations. Never put secrets, credentials, private ids, auth state, or
619
+ hidden policy in annotations, author, or timestamps; providers may send them to models.
620
+
621
+ ## Replay-safe chat projection
622
+
623
+ Durable transports may reconnect or replay overlapping chunks. Protocol events can carry optional
624
+ `eventId`; `LLMTextDelta` and `LLMReasoningDelta` can also carry `textSoFar` / `reasoningSoFar`
625
+ snapshots when a host can provide cumulative text.
626
+
627
+ Use `applyAgentEventToChatProjection` for replayable event logs:
628
+
629
+ ```ts
630
+ import {
631
+ applyAgentEventToChatProjection,
632
+ makeAgentChatEventProjectionState
633
+ } from '@yolk-sdk/agent/react'
634
+
635
+ const projection = events.reduce(
636
+ (state, event) => applyAgentEventToChatProjection(state, event),
637
+ makeAgentChatEventProjectionState()
638
+ )
639
+ ```
640
+
641
+ Use `applyAgentEventToChatMessages` only for ephemeral local streams where append-only deltas cannot
642
+ replay.
643
+
644
+ When the host promotes queued user input into a durable stream, emit a replay-safe user event:
645
+
646
+ ```ts
647
+ import { UserMessage, UserMessageEvent } from '@yolk-sdk/agent/protocol'
648
+
649
+ const event = UserMessageEvent.make({
650
+ eventId: 'session_1:user-message_42',
651
+ message: UserMessage.make({ content: 'Please also compare the alternatives.' })
652
+ })
653
+ ```
654
+
655
+ The host owns queueing and promotion policy and must assign a stable `eventId` so reconnects do not
656
+ project the same promoted message twice.
657
+
658
+ ## Parallel tool calls
659
+
660
+ OpenAI, Vercel AI Gateway, OpenAI Codex, and Grok requests enable vendor parallel tool calls when tools are available. The
661
+ Codex stream adapter preserves every sibling function call and suppresses final-response replays
662
+ by call id. The loop executes calls emitted in the same model turn concurrently, bounded by the
663
+ host-configured `LoopConfig.toolConcurrency`; dependent work waits for the next model turn.
664
+
665
+ ## Transcript invariants
666
+
667
+ Every assistant host tool call must be followed by a matching `ToolResultMessage` before the next
668
+ non-tool message/provider request. Use `validateNoDanglingHostToolCalls` for preflight checks,
669
+ `danglingHostToolCalls` for diagnostics, and `repairDanglingHostToolCalls` only when loading older
670
+ persisted transcripts that already have gaps. Built-in providers reject dangling host tool calls
671
+ before vendor lowering with a non-retryable validation error.
672
+
76
673
  ## Human-in-the-loop
77
674
 
78
675
  HITL is protocol-level, not UI-level:
79
676
 
80
677
  - Add `approval: { mode: 'manual' }` to a `ToolDef` to pause before execution.
81
678
  - `run` / `runRuntime` emit `ToolApprovalRequested` then `AgentAwaitingInput`.
82
- - Resume by passing `hitlResponses` or using client helpers like `submitToolApprovalResponse`.
679
+ - Resume by passing `hitlResponses`, using `useAgentChat` methods like
680
+ `submitToolApprovalResponse` / `submitQuestionResponse`, or using client stream helpers like
681
+ `streamToolApprovalResponseEventStream`.
83
682
  - Denials become model-visible `ToolResult` messages with `isError = true`.
84
- - Use `makeQuestionToolModule` to expose the package-owned `question` tool; answers resume as structured tool results and model-visible text with selected labels.
683
+ - Use `makeQuestionToolModule` to expose the package-owned `question` tool; answers resume as structured tool results and model-visible text with selected labels. The loop intercepts questions only when the tool is enabled in `tools`; omitted questions return an unavailable result without HITL or executor dispatch, even if a provider emits one.
684
+ - Use `makeInputTool({ name, description, response, renderer })` for custom typed input. Apps own the response Effect schema and renderer; the SDK carries JSON data only. Pass `resolveTools(...).inputs` alongside `tools` to loop/runtime configs. The original `callParameters` and `response` schemas validate server-side, including refinements; display JSON Schema is not the validator. Invalid calls fail before prompting; invalid submissions remain pending for correction. The first valid submission or cancellation settles the request and cannot be overwritten by stale responses.
685
+ - Resume custom inputs with `submitInputResponse`, `streamInputResponseEventStream`, or WebSocket `InputResponseInput`. Echo request/call IDs; do not reconstruct them. Input collection is not authorization: a draft composer never grants permission to send. Input tools cannot carry approval/background policy or execute directly.
686
+ - Use `makeInteractionTool` when a person must edit proposed values and authorize one server-defined action. Unlike data-only inputs, interactions execute the selected action on the exact validated values before the next model turn. Hosts own renderers, authentication, scoped immutable receipt storage, and atomic acceptance; browser responses alone never authorize execution. Pass `interactionHost` to `resolveTools`, then both `toolSet.interactions` and `toolSet.interactionHost` to loop/runtime configs. Durable hosts load `loadInteractionReceipts` before passing `interactionReceipts` to `prepareToolBatch`.
687
+ - Submit interactions with `submitInteractionResponse`, `streamInteractionResponseEventStream`, or WebSocket `InteractionResponseInput`; the host must authenticate and atomically accept the response server-side before SDK resume. Submission is not completion; only real server results settle the UI. An `unknown` outcome needs host reconciliation, never automatic action retry. Voice/realtime and background activation are unsupported. See [action-backed interactions](https://github.com/magoz/yolk-sdk/blob/main/packages/agent/src/tools/README.md#action-backed-interactions) for registration and host-boundary details.
688
+ - Use `questionResponseStructuredContent` / `plainHitlResponse` before storing durable HITL payloads that must be plain JSON. `PlainHitlResponse` is a `Data.taggedEnum` value (`QuestionResponse` / `ToolApprovalResponse` / `InputResponse` / `InteractionResponse`); the helpers omit absent optionals then call those constructors (`_tag` last, plain objects, not Schema classes).
689
+ - Use `toolRunsFromHitlRequests` to hydrate paused UI state from `AgentAwaitingInput.requests`.
690
+ - Use `hitlResponseEvent` when a client needs optimistic approval/question UI updates before resumed stream events arrive. Typed input and interaction submissions stay pending until server acceptance; accepted interactions stay active until the actual outcome. Never synthesize an interaction result from local submission or acceptance.
85
691
  - Approval is a host-enforced per-call gate for normal tools, not a model-callable permission tool or persisted allow-always system.
86
692
 
87
- ## Task subagents
693
+ HTTP client helpers treat `AgentEnd`, `AgentError`, and `AgentAwaitingInput` as logical stream
694
+ end for consumers. Use `isTerminalAgentEvent` when projecting generic protocol streams. After a
695
+ terminal event the response body drains to EOF; cancellation before a terminal event still aborts
696
+ the active body reader.
697
+ Durable Workflow clients can use `streamAgentEventStreamUntilTerminal`,
698
+ `streamAgentRunEventStreamUntilTerminal`, and `streamAgentRunHitlResponseEventStreamUntilTerminal` to follow
699
+ continuation chunks by `x-workflow-run-id` and `x-workflow-stream-tail-index` headers. These helpers
700
+ fail with `AgentTransportError` if no terminal event is reached before the continuation limit.
701
+ Empty non-terminal continuation chunks are polling gaps: the client waits briefly, retries from the
702
+ same `startIndex`, and respects the request `signal` while waiting.
703
+ Outbound `startIndex` values must be non-negative safe integers; invalid values fail before the
704
+ HTTP request is sent.
705
+ For HITL resume responses, `x-workflow-stream-tail-index` means the stream tail before the returned
706
+ body. The returned body starts at `tail + 1`; the next continuation starts after all returned
707
+ events. `continuationLimit: 0` disables follow-up chunks, so any non-terminal response fails
708
+ immediately.
709
+
710
+ ```ts
711
+ import { Stream } from 'effect'
712
+ import { streamAgentEventStreamUntilTerminal } from '@yolk-sdk/agent/client'
713
+ import { UserMessage } from '@yolk-sdk/agent/protocol'
714
+
715
+ const events = Stream.toAsyncIterable(
716
+ streamAgentEventStreamUntilTerminal({
717
+ endpoint: '/api/agent/workflow',
718
+ sessionId: 'session_1',
719
+ messages: [UserMessage.make({ content: 'Hello' })],
720
+ runEndpoint: runId => `/api/agent/workflow/${encodeURIComponent(runId)}`
721
+ })
722
+ )
723
+
724
+ for await (const event of events) {
725
+ // Apply AgentEvent to app state.
726
+ }
727
+ ```
728
+
729
+ The SDK client does not own durable route auth, run ownership, Workflow hook-token routing, or HITL
730
+ request matching. Hosts expose the run endpoints and validate access/response identity server-side.
731
+
732
+ ## Voice
733
+
734
+ `VoiceSession.layer` (`@yolk-sdk/agent/voice`) composes a supplied `VoiceTransport` layer,
735
+ `VoiceController`, and an optional `VoiceEventOutbox`. Configured `eventLog` captures events without
736
+ an external stream consumer; omitting it never captures an ambient outbox. The returned event stream
737
+ has one queue consumer and is not a broadcast subscription. Without a consumer, events accumulate
738
+ in memory; hosts should normally drain it. Seeds run during acquisition.
739
+
740
+ Breaking 0.x migration: `makeVoiceController` no longer takes `options.transport`; provide
741
+ `VoiceTransport` with `Effect.provideService`, or use `VoiceSession.layer`.
742
+ `webRtcVoiceTransportLayer` (`voice/browser`) and `webSocketVoiceTransportLayer` (`voice`) acquire
743
+ scoped transports. `Layer.succeed(VoiceTransport, transport)` injects a caller-owned value; it does
744
+ not allocate/finalize it or guarantee fresh resources. Keep the entire usage effect inside a
745
+ provided layer, or use `Layer.buildWithScope` when an explicit session scope owns its lifetime.
746
+ `useYolkVoice` builds each attempt in that attempt's scope and retains stop/unmount cleanup.
747
+
748
+ Voice is a first-class modality: browser WebRTC transport, client controller, server tool
749
+ handler, approval HITL, transcript projection, and one-shot TTS/STT contracts.
750
+
751
+ - `useYolkVoice` (`@yolk-sdk/agent/voice/react`) owns browser session lifecycle, user drafts,
752
+ and pending approvals; provider codecs come from `@yolk-sdk/agent/providers/openai/realtime`.
753
+ - Tools execute server-side only: the controller forwards the normalized
754
+ `VoiceSessionToolCallRequest` JSON envelope to your endpoint; `handleVoiceToolCall` returns a
755
+ JSON-compatible `VoiceToolCallOutcome` envelope, applies `ToolDef.approval` policy, and never runs
756
+ approval-gated tools without a matching approved response.
757
+ - Approval-gated calls pause with `AwaitingInput`; approvals/denials resume through
758
+ `submitHitlResponse`. Voice questions and custom typed inputs are unsupported in v1.
759
+ - `projectVoiceEvent` turns voice events into protocol messages with no dangling host tool
760
+ calls. Assistant drafts are keyed per provider output item (falling back to response id), so
761
+ back-to-back responses, multi-item responses, and duplicate final transcript event families
762
+ never concatenate, wipe, or duplicate messages. `sequenceVoiceEvent`/`dedupeStoredVoiceEvents`
763
+ give replay-safe durable event ids; `voiceSeedTextsFromMessages` seeds new provider sessions
764
+ after reconnect, optionally prefixing user seeds with author display names via
765
+ `{ includeAuthors: true }` for multi-user transcripts.
766
+ - `makeWebSocketVoiceTransport` covers Node/server realtime sessions and requires a host-provided
767
+ `Socket.WebSocketConstructor` layer, such as `Socket.layerWebSocketConstructorGlobal`;
768
+ `@yolk-sdk/agent/providers/openai/speech` provides `makeOpenAiSpeechSynthesizerLayer` and
769
+ `makeOpenAiTranscriberLayer` for the provider-neutral voice services.
770
+ `VoiceSpeechRequest.instructions` steers delivery style only, and
771
+ provider 429s (rate limit or exhausted credits) surface as `VoiceSpeechError` code
772
+ `rate_limited` so hosts can distinguish quota from outage.
773
+ - Browser WebRTC hosts that implement `WebRtcPeerConnectionLike`
774
+ (`@yolk-sdk/agent/voice/browser`) treat `addTrack(track, stream)` as a void command. The
775
+ transport discards the DOM `RTCRtpSender`. Hosts and fakes must not read a sender from this
776
+ capability. Real `RTCPeerConnection.addTrack` remains assignable.
777
+ - `protocolToolCallFromVoice` still returns `ToolCall`. Voice raw argument JSON admits finite
778
+ JSON (`Schema.Json`). Actual `null`, `false`, and `0` still admit as those values. Non-JSON
779
+ and non-finite numbers fail admission: raw text `1e999` projects as the argument string
780
+ `'1e999'`, and `decideVoiceToolCall` approval display params are `{ argumentsJson: '1e999' }`
781
+ (not `Infinity`; do not demonstrate with `JSON.stringify(Infinity)`, which is `null`). Nested
782
+ overflow such as `{"n":1e999}` takes the same mapper-specific fallbacks. Approval identifiers,
783
+ gates, deny, and execution schema validation are unchanged.
784
+
785
+ ## Classifier models
786
+
787
+ `@yolk-sdk/agent/classification` is a provider-neutral contract for classifier models such as
788
+ TypeSafe's Jev: one `state` (a string, JSON object, or JSON array) and named `boolean`, `choice`
789
+ (2-255 options), or `score` (2-10 levels, lowest first) questions, answered together with
790
+ probabilities. `classify` types each answer from its question (a choice answer's `choice` is the
791
+ union of its option keys) and checks every answer against its question. Probabilities are kept as
792
+ returned, never renormalized. Failures are typed (`ClassificationRequestInvalid`,
793
+ `ClassificationProviderError`, `ClassificationResponseInvalid`); a response that fails to decode
794
+ keeps the billed `usage`. Classification is a read; authorization stays host policy.
795
+
796
+ `@yolk-sdk/agent/providers/vercel/ai-gateway-classifier` calls AI Gateway `POST /v1/evaluate`
797
+ (Gateway calls this evaluation) with `typesafe-ai/jev` by default and the same Gateway credential
798
+ as the chat provider:
88
799
 
89
- `task` is the package-owned contract for subagent delegation. The SDK provides schema,
90
- validation, non-recursive module wiring, subagent result extraction, and structured task result
91
- metadata. Host apps provide the actual nested runtime.
800
+ ```ts
801
+ import { Effect, Redacted } from 'effect'
802
+ import { FetchHttpClient } from 'effect/http'
803
+ import { classify } from '@yolk-sdk/agent/classification'
804
+ import { makeVercelAiGatewayClassifierLayer } from '@yolk-sdk/agent/providers/vercel/ai-gateway-classifier'
805
+
806
+ const program = classify({
807
+ state: { subject: 'Invoice question', body: 'I was charged twice.' },
808
+ questions: {
809
+ route: {
810
+ type: 'choice',
811
+ instructions: 'Which team should handle this ticket?',
812
+ criteria: { billing: 'Payments and refunds.', bug: 'Product defects.' }
813
+ }
814
+ }
815
+ }).pipe(
816
+ Effect.map(result => result.answers.route.choice), // 'billing' | 'bug'
817
+ Effect.provide(makeVercelAiGatewayClassifierLayer({ apiKey: Redacted.make(gatewayKey) })),
818
+ Effect.provide(FetchHttpClient.layer)
819
+ )
820
+ ```
821
+
822
+ `providerOptions` passes through unchanged (for example `{ gateway: { zeroDataRetention: true } }`).
823
+ `providerMetadata.gateway.cost` becomes `usage.costUsd`, and `x-ai-gateway-evaluation-fallback-*`
824
+ response headers are kept in `providerMetadata.evaluationFallbackHeaders`.
825
+
826
+ ## Subagents
827
+
828
+ `subagent` is the package-owned contract for child-agent delegation. The SDK provides schema,
829
+ validation, non-recursive module wiring, subagent result extraction, and structured result
830
+ metadata. Host apps provide inline or independently durable child execution.
92
831
 
93
832
  Recommended setup:
94
833
 
95
- - expose `makeNonRecursiveTaskToolModule` only to the top-level agent
834
+ - expose `makeNonRecursiveSubagentToolModule` only to the top-level agent
96
835
  - resolve subagent tools with `subagent: true`
97
- - omit `task` from subagent toolsets
836
+ - omit `subagent` from subagent toolsets
98
837
  - include only tools that are safe for autonomous delegated work
99
838
  - use `makeSubagentRunId(call.id)` for protocol-aligned run ids
100
- - return `makeTaskToolResult(...)` so UI can show subagent id, type, status, model, and timing
101
-
102
- See `examples/next/lib/agents/workflow-runtime/text-response.ts` for host-owned execution wiring.
839
+ - optionally configure model and reasoning-effort choices so the parent can select child runtime settings
840
+ - treat omitted `model` and `reasoning_effort` parameters as inheritance of host runtime settings
841
+ - return `makeSubagentToolResult(...)` so UI can show subagent id, type, status, model, reasoning effort, timing, optional usage/turns, and typed failure metadata
842
+ - use `subagentUsageFromToolResult(...)` when a host must add child usage to cumulative workflow usage
843
+
844
+ Durable hosts may opt into `background: true` in the tool registration options. This advertises
845
+ an optional model parameter `background`; inline hosts keep their existing schema and behavior.
846
+ Return `makeSubagentAcceptedToolResult({ callId, workflowRunId, parentRunId })` for background acceptance.
847
+ The optional parent identity lets a later conversation run address the original child. Keep
848
+ acceptance independent of how quickly the child finishes.
849
+ It emits normal tool completion but **not** `SubagentCompleted`, and carries no usage. Keep the
850
+ logical `subagent:<toolCallId>` identity separate from the physical Workflow id. Never append a
851
+ second tool result for the original launch. Hosts may deliver findings automatically or expose
852
+ host-owned status/wait tools whose observations do not masquerade as fresh child usage. The SDK
853
+ registers none of those observation tools and promises no automatic delivery. Its default background
854
+ parameter and acceptance text therefore defer to host instructions instead of naming unavailable
855
+ tools. Hosts should describe their actual completion policy in model-visible instructions and retain
856
+ lookup identities in accepted-result text if they customize it; structured metadata alone may not
857
+ survive provider lowering. Host-owned storage must remain readable after parent end.
858
+
859
+ A lost control response or exhausted observation budget is not a terminal child failure. Hosts
860
+ can return a `ToolResult` with `structuredContent.type: 'subagent_observation'` and a matching
861
+ `subagent_run_id: makeSubagentRunId(call.id)`. The loop completes the tool observation but suppresses
862
+ `SubagentCompleted`; nested results do not contribute child usage. Include truthful status and an
863
+ owned recovery handle in the observation. Use normal final results for genuine terminal outcomes,
864
+ not this marker. These child observations are separate from generic background tool `acceptance`.
865
+
866
+ `prepareToolBatch` from `@yolk-sdk/agent/loop` exposes the same HITL preflight used by the loop.
867
+ Durable orchestration must check `pendingRequests` before dispatching **any** tool, even calls
868
+ listed in `callsToExecute`. Preserve synthetic results and original call ordering when committing.
869
+
870
+ Keep host-owned subagent execution wiring outside this package; pass only the package subagent contract across the boundary.
871
+
872
+ ## Background tool calls
873
+
874
+ Any `makeTool` registration can opt into model-chosen background execution with `background: true`.
875
+ The flag is inert until `resolveTools(modules, context, { backgroundHost })` receives a
876
+ `BackgroundToolHost`, which asserts a real lifecycle owner (durable run, queue, or session) exists.
877
+ Without a host, definitions, approval ids, and inline behavior are unchanged.
878
+
879
+ - Activated tools advertise a required `{ execution: 'foreground' | 'background', arguments }`
880
+ envelope; the original parameter schema nests under `arguments` and `$defs` stay at the root.
881
+ Only document-root `#/$defs/...` references (without percent-encoded fragments) are supported.
882
+ Other reference forms and resource/anchor keywords (`$id`, legacy `id`, `$anchor`, `$dynamicAnchor`,
883
+ `$dynamicRef`, `$recursiveAnchor`, `$recursiveRef`) fail activation with
884
+ `ToolRegistryError.cause: 'background_unsupported_schema'`. Literal defaults/examples/const/enum
885
+ data are not traversed as schemas.
886
+ - The registry validates the envelope and original parameters without business effects, strips the
887
+ control fields, then executes inline or calls `host.accept({ call, request, context })`.
888
+ `makeTool` invalid business arguments still return structured model-visible errors in either
889
+ mode, without business/admission effects. Raw validator and host errors remain typed failures.
890
+ - `accept` returns a versioned `BackgroundToolAccepted` receipt (`{ version: 1, executionId }`),
891
+ never a closure. Make it idempotent per call id; fail with a `ToolError` to decline. The registry
892
+ never falls back to inline execution.
893
+ - Use protocol `toolResultMessageFromResult(result, envelope?)` to preserve every result field and
894
+ receipt when creating transcript messages; timestamps/authors remain explicit host inputs.
895
+ - The result is one acknowledgement `ToolResult` with typed `acceptance` metadata; the loop emits
896
+ `ToolExecutionAccepted` (no `ToolExecutionCompleted`, no usage). Client state, chat projection,
897
+ and tool cards treat `Accepted` as settled but not completed; active input/approval/Started
898
+ replays cannot replace accepted calls or receipts, including across turn cleanup and hydration.
899
+ - Activated definitions are unsupported in voice/realtime, including foreground envelope calls.
900
+ Resolve voice toolsets without a background host. Synchronous realtime tool/config mappers throw
901
+ `VoiceToolBridgeError` for unsupported activation **and** for non-JSON tool `parameters`; use
902
+ `toOpenAiRealtimeToolEffect`, `makeOpenAiRealtimeSessionConfigEffect`, or
903
+ `openAiRealtimeSessionConfigFromVoiceEffect` inside Effect programs to catch that typed error.
904
+ Unexpected mapper defects stay defects, not `VoiceToolBridgeError`. Voice handlers deny before
905
+ approval matching, and the low-level bridge rejects activated registry dispatch before validation,
906
+ inline execution, or admission.
907
+ - Raw `ToolRegistration` objects need a side-effect-free `validate` to activate; the loop-owned
908
+ `question` and `subagent` tools cannot activate (subagents keep `makeSubagentAcceptedToolResult`).
909
+ - Manual approval fences the whole batch; activated calls bind the approval `requestId` to the tool
910
+ name, mode, and canonical arguments, and malformed envelopes are rejected before any prompt.
911
+ IDs intentionally contain the full canonical payload: hosts must accommodate opaque, potentially
912
+ long IDs or enforce input bounds before admission; never truncate or rebuild them.
913
+ - Hosts own authorization, status/wait tools, cancellation, terminal storage, usage, and delivery.
914
+ Never append a second result for the original call.
915
+
916
+ ## Code mode tool contract
917
+
918
+ These options are the tool contract that [`@yolk-sdk/codemode`](https://github.com/magoz/yolk-sdk/blob/main/packages/codemode/README.md) builds on.
919
+ This package declares them; it does not run scripts.
920
+
921
+ - `makeTool({ output })` adds declaration-only `ToolDef.outputSchema`, lowered like `parameters`.
922
+ - `callableBy: 'all' | 'model' | 'codemode'` (default `all`) decides who may call a tool. For
923
+ `codemode` only, `discovery: 'listed' | 'search'` (default `listed`) decides how scripts find it.
924
+ Codemode-only tools never reach providers. Approval, input, interaction, activated background,
925
+ `question`, `subagent`, and nested-access tools never run from code mode; `resolveTools` rejects
926
+ `callableBy: 'codemode'` on them.
927
+ - `nestedToolAccess: true` gives a registration's `execute` a `nested` executor over the other
928
+ code-mode-callable tools of the same resolution and host context. Nested calls run through the
929
+ resolved execute path and fail closed with model-visible error results. Assign nested call ids as
930
+ `<parentToolCallId>/<seq>`.
931
+ - `describe: ({ tools }) => string` on a nested-access registration computes its resolved
932
+ description from those nested tools; `def.description` stays the static fallback.
933
+ - Report nested calls with protocol `recordNestedToolCall` and `nestedToolCallResultFields`. The
934
+ bounded `ToolResult.nestedCalls` record and summed `ToolResult.usage` never reach the model:
935
+ `toolResultMessageFromResult` drops both, and the loop does not add `ToolResult.usage` to run
936
+ usage. Capture them from the `ToolResult` or tool events when you need audit or billing records.
937
+ Size the record with `makeNestedToolCallRecorder({ maxCalls })`; per-status `counts` cover
938
+ every call, dropped ones included.
939
+
940
+ ## Durable tool ledger
941
+
942
+ Steps that hosts re-execute (Vercel Workflow's queue is at-least-once) must not repeat writes.
943
+ Pass `resolveTools(modules, context, { ledger: { store } })` with a host-implemented durable
944
+ `ToolLedgerStore` scoped to the run: every ledgered call (by default every non-`read` call plus the
945
+ built-in `subagent` tool, top-level or nested in code mode) runs at most once per ledger key. Add
946
+ custom delegation tools with `isLedgered`. Input and interaction tools are never ledgered; their
947
+ at-most-once guarantee is the host's `InteractionHost` receipts. A different call under the same key (tool name or a
948
+ SHA-256 `argsDigest` of the full arguments, a stable format hosts persist) is a conflict, never a
949
+ replay. Completed calls return their stored result, concurrent duplicates wait, and calls abandoned
950
+ by a crash are never re-run (the model is told to verify). Executors receive a stable
951
+ `idempotencyKey`. Stores get the lease length (`leaseMs`) so they can use database time, and must
952
+ keep their operations interruptible (the ledger's timeouts cannot cut uninterruptible store work).
953
+ `deadline` bounds only waiting for a duplicate; recording an outcome can take about 15 s more.
954
+ `onLedgerDecision` reports each call's decision (`fresh`, `completed`, `in_flight_wait`, ...) for
955
+ logs and metrics. Without the option behavior is unchanged. See
956
+ [the tools README](https://github.com/magoz/yolk-sdk/blob/main/packages/agent/src/tools/README.md#durable-tool-ledger).
957
+
958
+ ## Tool failures
959
+
960
+ Use `modelVisibleToolError(...)` for expected tool-domain failures the model can recover
961
+ from, such as invalid arguments, not-found resources, denied policy, or unavailable upstream
962
+ data. `makeTool` converts these failures into `ToolResult.isError = true` so the agent can
963
+ see the message and continue. The result includes structured content with `type`, `tool`,
964
+ `reason`, `message`, and optional `details` for UI/runtime handling.
965
+
966
+ Optional `makeTool({ invalidParamsMessage })` receives the `Schema.SchemaError` produced by
967
+ decoding `parameters` through its JSON codec (validate and execute). The decode error is passed
968
+ through unwrapped. Default text is `Invalid ${name} arguments: ${String(error)}`, which keeps the
969
+ `SchemaError(...)` wrapper, followed by one line per object (path and allowed-key set) naming its unknown keys and
970
+ listing the allowed keys. Custom callbacks can append the same hint with `withToolArgumentsErrorHint(message, error)`. In Effect 4, `SchemaError` extends native `Error`, but the
971
+ wrapper remains part of this tool-message contract; do not default to `.message`.
972
+ Existing `(error: unknown) => string` callbacks remain assignable.
973
+
974
+ Thrown `ToolError`s become model-visible failed tool results plus `ToolExecutionError` events,
975
+ so keep messages safe and non-secret. Reserve stream failure for provider/runtime defects,
976
+ aborts, and implementation bugs outside typed tool execution.
103
977
 
104
978
  ## Host responsibilities
105
979
 
106
- - Choose models/providers and map provider streams into protocol events.
980
+ - Choose models/providers and provide an LLM provider layer, using SDK provider subpaths or host adapters.
981
+ - Store, refresh, revoke, and authorize OAuth credentials; expose only runtime access tokens.
982
+ - Configure model-specific provider output-token limits.
983
+ - Build UI components and styling, own auth, and wire headless React hooks to host transports.
107
984
  - Persist sessions, transcripts, and append logs.
985
+ - Persist/return one `ToolResultMessage` for every host tool call, including `isError` failures.
986
+ - Persist terminal provider failures and clear active run ids where applicable.
108
987
  - Provide tools, approval policy, auth, storage, and observability.
988
+ - When steps can re-execute, implement a durable `ToolLedgerStore` scoped to one run (plus the turn
989
+ or step when call ids can repeat), keep its operations interruptible, and reserve about 15 s of
990
+ the step budget after `deadline` for recording outcomes.
991
+ - If you send `ToolDef`s to providers yourself (outside `run`/`runModelTurn`), filter them with
992
+ protocol `providerToolDefs`; codemode-only tools must never reach providers. Executor decorators
993
+ outside `ResolvedToolSet.execute` do not see nested code mode calls.
109
994
  - Compact context and decide memory/search policy.
110
995
 
111
996
  ## Boundaries
112
997
 
113
- - No React, Next.js, provider SDKs, auth, storage drivers, or app concepts.
998
+ - Core loop/protocol/runtime/tools have no React, Next.js, provider SDKs, auth, storage drivers, or app concepts.
999
+ - `@yolk-sdk/agent/compaction` combines pure planning/formatting helpers with Effect-native transformer and retry adapters; hosts own thresholds, summaries, compaction payloads, and durable compactor policy.
1000
+ - `@yolk-sdk/agent/classification` is provider-neutral (no Node, React, or provider code); provider subpaths supply `ClassifierModel` layers.
1001
+ - `@yolk-sdk/agent/react` is headless and uses React as an optional peer.
1002
+ - Provider subpaths own vendor wire/auth mechanics only; hosts own token storage, refresh, routing, and policy.
1003
+ - `@yolk-sdk/agent/providers/openai/speech` is server integration requiring runtime
1004
+ `FormData`/`Blob`, a host `HttpClient` layer, and a secret API key; do not invoke it from browser
1005
+ code.
114
1006
  - Loop stays stateless: transcript in, events out.
115
1007
  - Runtime owns generic session orchestration only; host apps own persistence adapters and policy.
1008
+ - Client HTTP helpers are runtime-portable with a host `HttpClient` layer. Attachment helpers need
1009
+ `Blob`/`File` and may use `FileReader`; the Cloudflare WebSocket transport needs the global
1010
+ `WebSocket` constructor when its stream runs. None read browser globals at import time.
116
1011
  - Tools model generic metadata/execution; host apps own concrete tool catalogs.
117
- - `task` is the standard subagent delegation tool. Packages define the schema; host apps execute subagents and omit `task` from subagent toolsets in v1.
1012
+ - `subagent` is the standard delegation tool. Packages define the schema; host apps execute subagents and omit `subagent` from child toolsets in v1.
118
1013
 
119
1014
  ## Testing
120
1015