@yolk-sdk/agent 0.1.0-canary.95 → 0.1.0-canary.96

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 (397) hide show
  1. package/README.md +114 -37
  2. package/dist/classification/errors.d.mts +57 -0
  3. package/dist/classification/errors.d.mts.map +1 -0
  4. package/dist/classification/errors.mjs +56 -0
  5. package/dist/classification/errors.mjs.map +1 -0
  6. package/dist/classification/index.d.mts +4 -0
  7. package/dist/classification/index.mjs +4 -0
  8. package/dist/classification/model.d.mts +74 -0
  9. package/dist/classification/model.d.mts.map +1 -0
  10. package/dist/classification/model.mjs +136 -0
  11. package/dist/classification/model.mjs.map +1 -0
  12. package/dist/classification/schema.d.mts +172 -0
  13. package/dist/classification/schema.d.mts.map +1 -0
  14. package/dist/classification/schema.mjs +104 -0
  15. package/dist/classification/schema.mjs.map +1 -0
  16. package/dist/client/state.d.mts +82 -82
  17. package/dist/client/state.d.mts.map +1 -1
  18. package/dist/client/transport.d.mts +1 -1
  19. package/dist/client/transport.mjs +1 -1
  20. package/dist/loop/error.d.mts +1 -1
  21. package/dist/loop/error.mjs +1 -1
  22. package/dist/loop/llm-event.d.mts +1 -1
  23. package/dist/loop/llm-event.mjs +1 -1
  24. package/dist/loop/run.d.mts.map +1 -1
  25. package/dist/loop/run.mjs +16 -5
  26. package/dist/loop/run.mjs.map +1 -1
  27. package/dist/loop/services/llm-provider.d.mts +3 -0
  28. package/dist/loop/services/llm-provider.d.mts.map +1 -1
  29. package/dist/loop/services/llm-provider.mjs.map +1 -1
  30. package/dist/protocol/event.d.mts +1 -1
  31. package/dist/protocol/event.mjs +1 -1
  32. package/dist/protocol/index.d.mts +4 -3
  33. package/dist/protocol/index.d.mts.map +1 -1
  34. package/dist/protocol/index.mjs +4 -3
  35. package/dist/protocol/nested-tool-calls.d.mts +67 -0
  36. package/dist/protocol/nested-tool-calls.d.mts.map +1 -0
  37. package/dist/protocol/nested-tool-calls.mjs +118 -0
  38. package/dist/protocol/nested-tool-calls.mjs.map +1 -0
  39. package/dist/protocol/tool.d.mts +47 -1
  40. package/dist/protocol/tool.d.mts.map +1 -1
  41. package/dist/protocol/tool.mjs +44 -2
  42. package/dist/protocol/tool.mjs.map +1 -1
  43. package/dist/providers/anthropic/conformance/cases.d.mts +50 -0
  44. package/dist/providers/anthropic/conformance/cases.d.mts.map +1 -0
  45. package/dist/providers/anthropic/conformance/cases.mjs +248 -0
  46. package/dist/providers/anthropic/conformance/cases.mjs.map +1 -0
  47. package/dist/providers/anthropic/conformance/claude-usage-cases.d.mts +27 -0
  48. package/dist/providers/anthropic/conformance/claude-usage-cases.d.mts.map +1 -0
  49. package/dist/providers/anthropic/conformance/claude-usage-cases.mjs +55 -0
  50. package/dist/providers/anthropic/conformance/claude-usage-cases.mjs.map +1 -0
  51. package/dist/providers/anthropic/conformance/claude-usage-snapshot.d.mts +14 -0
  52. package/dist/providers/anthropic/conformance/claude-usage-snapshot.d.mts.map +1 -0
  53. package/dist/providers/anthropic/conformance/claude-usage-snapshot.mjs +33 -0
  54. package/dist/providers/anthropic/conformance/claude-usage-snapshot.mjs.map +1 -0
  55. package/dist/providers/anthropic/conformance/error-envelope.d.mts +15 -0
  56. package/dist/providers/anthropic/conformance/error-envelope.d.mts.map +1 -0
  57. package/dist/providers/anthropic/conformance/error-envelope.mjs +51 -0
  58. package/dist/providers/anthropic/conformance/error-envelope.mjs.map +1 -0
  59. package/dist/providers/anthropic/conformance/index.d.mts +18 -0
  60. package/dist/providers/anthropic/conformance/index.d.mts.map +1 -0
  61. package/dist/providers/anthropic/conformance/index.mjs +23 -0
  62. package/dist/providers/anthropic/conformance/index.mjs.map +1 -0
  63. package/dist/providers/anthropic/conformance/max-tokens.d.mts +15 -0
  64. package/dist/providers/anthropic/conformance/max-tokens.d.mts.map +1 -0
  65. package/dist/providers/anthropic/conformance/max-tokens.mjs +60 -0
  66. package/dist/providers/anthropic/conformance/max-tokens.mjs.map +1 -0
  67. package/dist/providers/anthropic/conformance/plain-text.d.mts +17 -0
  68. package/dist/providers/anthropic/conformance/plain-text.d.mts.map +1 -0
  69. package/dist/providers/anthropic/conformance/plain-text.mjs +63 -0
  70. package/dist/providers/anthropic/conformance/plain-text.mjs.map +1 -0
  71. package/dist/providers/anthropic/conformance/thinking-before-text.d.mts +16 -0
  72. package/dist/providers/anthropic/conformance/thinking-before-text.d.mts.map +1 -0
  73. package/dist/providers/anthropic/conformance/thinking-before-text.mjs +70 -0
  74. package/dist/providers/anthropic/conformance/thinking-before-text.mjs.map +1 -0
  75. package/dist/providers/anthropic/conformance/tool-use-input-deltas.d.mts +17 -0
  76. package/dist/providers/anthropic/conformance/tool-use-input-deltas.d.mts.map +1 -0
  77. package/dist/providers/anthropic/conformance/tool-use-input-deltas.mjs +79 -0
  78. package/dist/providers/anthropic/conformance/tool-use-input-deltas.mjs.map +1 -0
  79. package/dist/providers/anthropic/usage.d.mts +6 -0
  80. package/dist/providers/anthropic/usage.d.mts.map +1 -1
  81. package/dist/providers/anthropic/usage.mjs +1 -1
  82. package/dist/providers/anthropic/usage.mjs.map +1 -1
  83. package/dist/providers/anthropic-messages-provider-internal.d.mts +6 -0
  84. package/dist/providers/anthropic-messages-provider-internal.d.mts.map +1 -1
  85. package/dist/providers/anthropic-messages-provider-internal.mjs +5 -2
  86. package/dist/providers/anthropic-messages-provider-internal.mjs.map +1 -1
  87. package/dist/providers/anthropic-provider-internal.mjs +1 -1
  88. package/dist/providers/openai/codex-usage.d.mts +6 -0
  89. package/dist/providers/openai/codex-usage.d.mts.map +1 -1
  90. package/dist/providers/openai/codex-usage.mjs +1 -1
  91. package/dist/providers/openai/codex-usage.mjs.map +1 -1
  92. package/dist/providers/openai/conformance/cases.d.mts +36 -0
  93. package/dist/providers/openai/conformance/cases.d.mts.map +1 -0
  94. package/dist/providers/openai/conformance/cases.mjs +165 -0
  95. package/dist/providers/openai/conformance/cases.mjs.map +1 -0
  96. package/dist/providers/openai/conformance/codex-cases.d.mts +37 -0
  97. package/dist/providers/openai/conformance/codex-cases.d.mts.map +1 -0
  98. package/dist/providers/openai/conformance/codex-cases.mjs +64 -0
  99. package/dist/providers/openai/conformance/codex-cases.mjs.map +1 -0
  100. package/dist/providers/openai/conformance/codex-error-envelope.d.mts +13 -0
  101. package/dist/providers/openai/conformance/codex-error-envelope.d.mts.map +1 -0
  102. package/dist/providers/openai/conformance/codex-error-envelope.mjs +50 -0
  103. package/dist/providers/openai/conformance/codex-error-envelope.mjs.map +1 -0
  104. package/dist/providers/openai/conformance/codex-function-call-arguments.d.mts +13 -0
  105. package/dist/providers/openai/conformance/codex-function-call-arguments.d.mts.map +1 -0
  106. package/dist/providers/openai/conformance/codex-function-call-arguments.mjs +79 -0
  107. package/dist/providers/openai/conformance/codex-function-call-arguments.mjs.map +1 -0
  108. package/dist/providers/openai/conformance/codex-plain-text.d.mts +13 -0
  109. package/dist/providers/openai/conformance/codex-plain-text.d.mts.map +1 -0
  110. package/dist/providers/openai/conformance/codex-plain-text.mjs +70 -0
  111. package/dist/providers/openai/conformance/codex-plain-text.mjs.map +1 -0
  112. package/dist/providers/openai/conformance/codex-terminal-event.d.mts +13 -0
  113. package/dist/providers/openai/conformance/codex-terminal-event.d.mts.map +1 -0
  114. package/dist/providers/openai/conformance/codex-terminal-event.mjs +67 -0
  115. package/dist/providers/openai/conformance/codex-terminal-event.mjs.map +1 -0
  116. package/dist/providers/openai/conformance/codex-usage-cases.d.mts +28 -0
  117. package/dist/providers/openai/conformance/codex-usage-cases.d.mts.map +1 -0
  118. package/dist/providers/openai/conformance/codex-usage-cases.mjs +55 -0
  119. package/dist/providers/openai/conformance/codex-usage-cases.mjs.map +1 -0
  120. package/dist/providers/openai/conformance/codex-usage-snapshot.d.mts +15 -0
  121. package/dist/providers/openai/conformance/codex-usage-snapshot.d.mts.map +1 -0
  122. package/dist/providers/openai/conformance/codex-usage-snapshot.mjs +34 -0
  123. package/dist/providers/openai/conformance/codex-usage-snapshot.mjs.map +1 -0
  124. package/dist/providers/openai/conformance/error-envelope.d.mts +14 -0
  125. package/dist/providers/openai/conformance/error-envelope.d.mts.map +1 -0
  126. package/dist/providers/openai/conformance/error-envelope.mjs +50 -0
  127. package/dist/providers/openai/conformance/error-envelope.mjs.map +1 -0
  128. package/dist/providers/openai/conformance/index.d.mts +24 -0
  129. package/dist/providers/openai/conformance/index.d.mts.map +1 -0
  130. package/dist/providers/openai/conformance/index.mjs +33 -0
  131. package/dist/providers/openai/conformance/index.mjs.map +1 -0
  132. package/dist/providers/openai/conformance/json-plain-text.d.mts +14 -0
  133. package/dist/providers/openai/conformance/json-plain-text.d.mts.map +1 -0
  134. package/dist/providers/openai/conformance/json-plain-text.mjs +49 -0
  135. package/dist/providers/openai/conformance/json-plain-text.mjs.map +1 -0
  136. package/dist/providers/openai/conformance/plain-text.d.mts +15 -0
  137. package/dist/providers/openai/conformance/plain-text.d.mts.map +1 -0
  138. package/dist/providers/openai/conformance/plain-text.mjs +60 -0
  139. package/dist/providers/openai/conformance/plain-text.mjs.map +1 -0
  140. package/dist/providers/openai/conformance/responses-cases-internal.d.mts +40 -0
  141. package/dist/providers/openai/conformance/responses-cases-internal.d.mts.map +1 -0
  142. package/dist/providers/openai/conformance/responses-cases-internal.mjs +271 -0
  143. package/dist/providers/openai/conformance/responses-cases-internal.mjs.map +1 -0
  144. package/dist/providers/openai/conformance/subscription-usage-cases-internal.d.mts +37 -0
  145. package/dist/providers/openai/conformance/subscription-usage-cases-internal.d.mts.map +1 -0
  146. package/dist/providers/openai/conformance/subscription-usage-cases-internal.mjs +85 -0
  147. package/dist/providers/openai/conformance/subscription-usage-cases-internal.mjs.map +1 -0
  148. package/dist/providers/openai/conformance/tool-call-deltas.d.mts +15 -0
  149. package/dist/providers/openai/conformance/tool-call-deltas.d.mts.map +1 -0
  150. package/dist/providers/openai/conformance/tool-call-deltas.mjs +77 -0
  151. package/dist/providers/openai/conformance/tool-call-deltas.mjs.map +1 -0
  152. package/dist/providers/openai/provider.d.mts +1 -1
  153. package/dist/providers/openai/provider.mjs +1 -1
  154. package/dist/providers/openai/realtime/client-codec.mjs +1 -1
  155. package/dist/providers/openai/realtime/session-config.d.mts +7 -3
  156. package/dist/providers/openai/realtime/session-config.d.mts.map +1 -1
  157. package/dist/providers/openai/realtime/session-config.mjs +9 -4
  158. package/dist/providers/openai/realtime/session-config.mjs.map +1 -1
  159. package/dist/providers/openai-responses-provider-internal.d.mts +1 -1
  160. package/dist/providers/openai-responses-provider-internal.mjs +1 -1
  161. package/dist/providers/opencode/conformance/cases.d.mts +47 -0
  162. package/dist/providers/opencode/conformance/cases.d.mts.map +1 -0
  163. package/dist/providers/opencode/conformance/cases.mjs +208 -0
  164. package/dist/providers/opencode/conformance/cases.mjs.map +1 -0
  165. package/dist/providers/opencode/conformance/chat-plain-text.d.mts +13 -0
  166. package/dist/providers/opencode/conformance/chat-plain-text.d.mts.map +1 -0
  167. package/dist/providers/opencode/conformance/chat-plain-text.mjs +58 -0
  168. package/dist/providers/opencode/conformance/chat-plain-text.mjs.map +1 -0
  169. package/dist/providers/opencode/conformance/index.d.mts +14 -0
  170. package/dist/providers/opencode/conformance/index.d.mts.map +1 -0
  171. package/dist/providers/opencode/conformance/index.mjs +19 -0
  172. package/dist/providers/opencode/conformance/index.mjs.map +1 -0
  173. package/dist/providers/opencode/conformance/messages-plain-text.d.mts +13 -0
  174. package/dist/providers/opencode/conformance/messages-plain-text.d.mts.map +1 -0
  175. package/dist/providers/opencode/conformance/messages-plain-text.mjs +60 -0
  176. package/dist/providers/opencode/conformance/messages-plain-text.mjs.map +1 -0
  177. package/dist/providers/opencode/conformance/responses-commentary-replay.d.mts +13 -0
  178. package/dist/providers/opencode/conformance/responses-commentary-replay.d.mts.map +1 -0
  179. package/dist/providers/opencode/conformance/responses-commentary-replay.mjs +89 -0
  180. package/dist/providers/opencode/conformance/responses-commentary-replay.mjs.map +1 -0
  181. package/dist/providers/opencode/conformance/responses-plain-text.d.mts +13 -0
  182. package/dist/providers/opencode/conformance/responses-plain-text.d.mts.map +1 -0
  183. package/dist/providers/opencode/conformance/responses-plain-text.mjs +60 -0
  184. package/dist/providers/opencode/conformance/responses-plain-text.mjs.map +1 -0
  185. package/dist/providers/opencode/conformance/usage-snapshot.d.mts +13 -0
  186. package/dist/providers/opencode/conformance/usage-snapshot.d.mts.map +1 -0
  187. package/dist/providers/opencode/conformance/usage-snapshot.mjs +32 -0
  188. package/dist/providers/opencode/conformance/usage-snapshot.mjs.map +1 -0
  189. package/dist/providers/opencode/usage.d.mts +7 -1
  190. package/dist/providers/opencode/usage.d.mts.map +1 -1
  191. package/dist/providers/opencode/usage.mjs +2 -2
  192. package/dist/providers/opencode/usage.mjs.map +1 -1
  193. package/dist/providers/provider-error.d.mts +5 -3
  194. package/dist/providers/provider-error.d.mts.map +1 -1
  195. package/dist/providers/provider-error.mjs +6 -5
  196. package/dist/providers/provider-error.mjs.map +1 -1
  197. package/dist/providers/vercel/ai-gateway-classifier.d.mts +45 -0
  198. package/dist/providers/vercel/ai-gateway-classifier.d.mts.map +1 -0
  199. package/dist/providers/vercel/ai-gateway-classifier.mjs +253 -0
  200. package/dist/providers/vercel/ai-gateway-classifier.mjs.map +1 -0
  201. package/dist/providers/vercel/ai-gateway-credential-internal.d.mts +12 -0
  202. package/dist/providers/vercel/ai-gateway-credential-internal.d.mts.map +1 -0
  203. package/dist/providers/vercel/ai-gateway-credential-internal.mjs +12 -0
  204. package/dist/providers/vercel/ai-gateway-credential-internal.mjs.map +1 -0
  205. package/dist/providers/vercel/ai-gateway-provider.d.mts.map +1 -1
  206. package/dist/providers/vercel/ai-gateway-provider.mjs +2 -1
  207. package/dist/providers/vercel/ai-gateway-provider.mjs.map +1 -1
  208. package/dist/providers/vercel/conformance/cases.d.mts +41 -0
  209. package/dist/providers/vercel/conformance/cases.d.mts.map +1 -0
  210. package/dist/providers/vercel/conformance/cases.mjs +182 -0
  211. package/dist/providers/vercel/conformance/cases.mjs.map +1 -0
  212. package/dist/providers/vercel/conformance/classifier-boolean.d.mts +13 -0
  213. package/dist/providers/vercel/conformance/classifier-boolean.d.mts.map +1 -0
  214. package/dist/providers/vercel/conformance/classifier-boolean.mjs +48 -0
  215. package/dist/providers/vercel/conformance/classifier-boolean.mjs.map +1 -0
  216. package/dist/providers/vercel/conformance/classifier-cases.d.mts +32 -0
  217. package/dist/providers/vercel/conformance/classifier-cases.d.mts.map +1 -0
  218. package/dist/providers/vercel/conformance/classifier-cases.mjs +193 -0
  219. package/dist/providers/vercel/conformance/classifier-cases.mjs.map +1 -0
  220. package/dist/providers/vercel/conformance/classifier-choice.d.mts +16 -0
  221. package/dist/providers/vercel/conformance/classifier-choice.d.mts.map +1 -0
  222. package/dist/providers/vercel/conformance/classifier-choice.mjs +55 -0
  223. package/dist/providers/vercel/conformance/classifier-choice.mjs.map +1 -0
  224. package/dist/providers/vercel/conformance/classifier-error-envelope.d.mts +13 -0
  225. package/dist/providers/vercel/conformance/classifier-error-envelope.d.mts.map +1 -0
  226. package/dist/providers/vercel/conformance/classifier-error-envelope.mjs +48 -0
  227. package/dist/providers/vercel/conformance/classifier-error-envelope.mjs.map +1 -0
  228. package/dist/providers/vercel/conformance/classifier-score.d.mts +16 -0
  229. package/dist/providers/vercel/conformance/classifier-score.d.mts.map +1 -0
  230. package/dist/providers/vercel/conformance/classifier-score.mjs +56 -0
  231. package/dist/providers/vercel/conformance/classifier-score.mjs.map +1 -0
  232. package/dist/providers/vercel/conformance/deepseek-reasoning.d.mts +13 -0
  233. package/dist/providers/vercel/conformance/deepseek-reasoning.d.mts.map +1 -0
  234. package/dist/providers/vercel/conformance/deepseek-reasoning.mjs +64 -0
  235. package/dist/providers/vercel/conformance/deepseek-reasoning.mjs.map +1 -0
  236. package/dist/providers/vercel/conformance/error-envelope.d.mts +13 -0
  237. package/dist/providers/vercel/conformance/error-envelope.d.mts.map +1 -0
  238. package/dist/providers/vercel/conformance/error-envelope.mjs +49 -0
  239. package/dist/providers/vercel/conformance/error-envelope.mjs.map +1 -0
  240. package/dist/providers/vercel/conformance/index.d.mts +20 -0
  241. package/dist/providers/vercel/conformance/index.d.mts.map +1 -0
  242. package/dist/providers/vercel/conformance/index.mjs +29 -0
  243. package/dist/providers/vercel/conformance/index.mjs.map +1 -0
  244. package/dist/providers/vercel/conformance/plain-text.d.mts +13 -0
  245. package/dist/providers/vercel/conformance/plain-text.d.mts.map +1 -0
  246. package/dist/providers/vercel/conformance/plain-text.mjs +53 -0
  247. package/dist/providers/vercel/conformance/plain-text.mjs.map +1 -0
  248. package/dist/providers/vercel/conformance/tool-call-deltas.d.mts +13 -0
  249. package/dist/providers/vercel/conformance/tool-call-deltas.d.mts.map +1 -0
  250. package/dist/providers/vercel/conformance/tool-call-deltas.mjs +63 -0
  251. package/dist/providers/vercel/conformance/tool-call-deltas.mjs.map +1 -0
  252. package/dist/providers/xai/conformance/cases.d.mts +43 -0
  253. package/dist/providers/xai/conformance/cases.d.mts.map +1 -0
  254. package/dist/providers/xai/conformance/cases.mjs +70 -0
  255. package/dist/providers/xai/conformance/cases.mjs.map +1 -0
  256. package/dist/providers/xai/conformance/error-envelope.d.mts +14 -0
  257. package/dist/providers/xai/conformance/error-envelope.d.mts.map +1 -0
  258. package/dist/providers/xai/conformance/error-envelope.mjs +48 -0
  259. package/dist/providers/xai/conformance/error-envelope.mjs.map +1 -0
  260. package/dist/providers/xai/conformance/function-call-arguments.d.mts +14 -0
  261. package/dist/providers/xai/conformance/function-call-arguments.d.mts.map +1 -0
  262. package/dist/providers/xai/conformance/function-call-arguments.mjs +70 -0
  263. package/dist/providers/xai/conformance/function-call-arguments.mjs.map +1 -0
  264. package/dist/providers/xai/conformance/index.d.mts +17 -0
  265. package/dist/providers/xai/conformance/index.d.mts.map +1 -0
  266. package/dist/providers/xai/conformance/index.mjs +21 -0
  267. package/dist/providers/xai/conformance/index.mjs.map +1 -0
  268. package/dist/providers/xai/conformance/plain-text.d.mts +14 -0
  269. package/dist/providers/xai/conformance/plain-text.d.mts.map +1 -0
  270. package/dist/providers/xai/conformance/plain-text.mjs +61 -0
  271. package/dist/providers/xai/conformance/plain-text.mjs.map +1 -0
  272. package/dist/providers/xai/conformance/terminal-event.d.mts +14 -0
  273. package/dist/providers/xai/conformance/terminal-event.d.mts.map +1 -0
  274. package/dist/providers/xai/conformance/terminal-event.mjs +59 -0
  275. package/dist/providers/xai/conformance/terminal-event.mjs.map +1 -0
  276. package/dist/providers/xai/conformance/usage-cases.d.mts +29 -0
  277. package/dist/providers/xai/conformance/usage-cases.d.mts.map +1 -0
  278. package/dist/providers/xai/conformance/usage-cases.mjs +81 -0
  279. package/dist/providers/xai/conformance/usage-cases.mjs.map +1 -0
  280. package/dist/providers/xai/conformance/usage-snapshot.d.mts +15 -0
  281. package/dist/providers/xai/conformance/usage-snapshot.d.mts.map +1 -0
  282. package/dist/providers/xai/conformance/usage-snapshot.mjs +34 -0
  283. package/dist/providers/xai/conformance/usage-snapshot.mjs.map +1 -0
  284. package/dist/providers/xai/usage.d.mts +6 -0
  285. package/dist/providers/xai/usage.d.mts.map +1 -1
  286. package/dist/providers/xai/usage.mjs +1 -1
  287. package/dist/providers/xai/usage.mjs.map +1 -1
  288. package/dist/react/chat-items.d.mts +68 -68
  289. package/dist/react/chat-items.d.mts.map +1 -1
  290. package/dist/react/chat-items.mjs +1 -1
  291. package/dist/react/chat-messages.d.mts +96 -96
  292. package/dist/react/chat-messages.d.mts.map +1 -1
  293. package/dist/react/chat-session-events.d.mts +1 -1
  294. package/dist/react/chat-session-events.mjs +1 -1
  295. package/dist/runtime/error.d.mts +1 -1
  296. package/dist/runtime/error.mjs +1 -1
  297. package/dist/runtime/session-event-store.d.mts +1 -1
  298. package/dist/runtime/session-event-store.mjs +1 -1
  299. package/dist/skillset/merge.d.mts +1 -1
  300. package/dist/tools/background.d.mts +1 -1
  301. package/dist/tools/background.mjs +1 -1
  302. package/dist/tools/index.d.mts +2 -2
  303. package/dist/tools/input.d.mts +1 -1
  304. package/dist/tools/input.mjs +1 -1
  305. package/dist/tools/interaction.d.mts +1 -1
  306. package/dist/tools/interaction.mjs +1 -1
  307. package/dist/tools/registry.d.mts +53 -7
  308. package/dist/tools/registry.d.mts.map +1 -1
  309. package/dist/tools/registry.mjs +111 -39
  310. package/dist/tools/registry.mjs.map +1 -1
  311. package/dist/tools/subagent.mjs +1 -1
  312. package/dist/voice/projection.d.mts +1 -1
  313. package/dist/voice/projection.mjs +1 -1
  314. package/dist/voice/protocol.d.mts +1 -1
  315. package/dist/voice/protocol.mjs +1 -1
  316. package/dist/voice/session-log.d.mts +1 -1
  317. package/dist/voice/session-log.mjs +1 -1
  318. package/dist/voice/speech.d.mts +1 -1
  319. package/dist/voice/speech.mjs +1 -1
  320. package/dist/voice/tool-bridge.mjs +1 -1
  321. package/dist/voice/tool-server.d.mts.map +1 -1
  322. package/dist/voice/tool-server.mjs +2 -1
  323. package/dist/voice/tool-server.mjs.map +1 -1
  324. package/package.json +39 -3
  325. package/src/classification/errors.ts +79 -0
  326. package/src/classification/index.ts +53 -0
  327. package/src/classification/model.ts +270 -0
  328. package/src/classification/schema.ts +154 -0
  329. package/src/loop/run.ts +31 -3
  330. package/src/loop/services/llm-provider.ts +3 -0
  331. package/src/protocol/index.ts +28 -1
  332. package/src/protocol/nested-tool-calls.ts +230 -0
  333. package/src/protocol/tool.ts +64 -1
  334. package/src/providers/anthropic/conformance/cases.ts +467 -0
  335. package/src/providers/anthropic/conformance/claude-usage-cases.ts +85 -0
  336. package/src/providers/anthropic/conformance/claude-usage-snapshot.ts +36 -0
  337. package/src/providers/anthropic/conformance/error-envelope.ts +56 -0
  338. package/src/providers/anthropic/conformance/index.ts +89 -0
  339. package/src/providers/anthropic/conformance/max-tokens.ts +65 -0
  340. package/src/providers/anthropic/conformance/plain-text.ts +68 -0
  341. package/src/providers/anthropic/conformance/thinking-before-text.ts +75 -0
  342. package/src/providers/anthropic/conformance/tool-use-input-deltas.ts +90 -0
  343. package/src/providers/anthropic/usage.ts +7 -1
  344. package/src/providers/anthropic-messages-provider-internal.ts +8 -1
  345. package/src/providers/openai/codex-usage.ts +7 -1
  346. package/src/providers/openai/conformance/cases.ts +290 -0
  347. package/src/providers/openai/conformance/codex-cases.ts +103 -0
  348. package/src/providers/openai/conformance/codex-error-envelope.ts +53 -0
  349. package/src/providers/openai/conformance/codex-function-call-arguments.ts +88 -0
  350. package/src/providers/openai/conformance/codex-plain-text.ts +73 -0
  351. package/src/providers/openai/conformance/codex-terminal-event.ts +70 -0
  352. package/src/providers/openai/conformance/codex-usage-cases.ts +87 -0
  353. package/src/providers/openai/conformance/codex-usage-snapshot.ts +37 -0
  354. package/src/providers/openai/conformance/error-envelope.ts +56 -0
  355. package/src/providers/openai/conformance/index.ts +126 -0
  356. package/src/providers/openai/conformance/json-plain-text.ts +53 -0
  357. package/src/providers/openai/conformance/plain-text.ts +66 -0
  358. package/src/providers/openai/conformance/responses-cases-internal.ts +580 -0
  359. package/src/providers/openai/conformance/subscription-usage-cases-internal.ts +199 -0
  360. package/src/providers/openai/conformance/tool-call-deltas.ts +91 -0
  361. package/src/providers/openai/realtime/session-config.ts +12 -5
  362. package/src/providers/opencode/conformance/cases.ts +372 -0
  363. package/src/providers/opencode/conformance/chat-plain-text.ts +64 -0
  364. package/src/providers/opencode/conformance/index.ts +63 -0
  365. package/src/providers/opencode/conformance/messages-plain-text.ts +65 -0
  366. package/src/providers/opencode/conformance/responses-commentary-replay.ts +96 -0
  367. package/src/providers/opencode/conformance/responses-plain-text.ts +63 -0
  368. package/src/providers/opencode/conformance/usage-snapshot.ts +35 -0
  369. package/src/providers/opencode/usage.ts +8 -2
  370. package/src/providers/provider-error.ts +8 -5
  371. package/src/providers/vercel/ai-gateway-classifier.ts +492 -0
  372. package/src/providers/vercel/ai-gateway-credential-internal.ts +10 -0
  373. package/src/providers/vercel/ai-gateway-provider.ts +2 -3
  374. package/src/providers/vercel/conformance/cases.ts +319 -0
  375. package/src/providers/vercel/conformance/classifier-boolean.ts +51 -0
  376. package/src/providers/vercel/conformance/classifier-cases.ts +333 -0
  377. package/src/providers/vercel/conformance/classifier-choice.ts +58 -0
  378. package/src/providers/vercel/conformance/classifier-error-envelope.ts +51 -0
  379. package/src/providers/vercel/conformance/classifier-score.ts +56 -0
  380. package/src/providers/vercel/conformance/deepseek-reasoning.ts +72 -0
  381. package/src/providers/vercel/conformance/error-envelope.ts +55 -0
  382. package/src/providers/vercel/conformance/index.ts +99 -0
  383. package/src/providers/vercel/conformance/plain-text.ts +59 -0
  384. package/src/providers/vercel/conformance/tool-call-deltas.ts +78 -0
  385. package/src/providers/xai/conformance/cases.ts +115 -0
  386. package/src/providers/xai/conformance/error-envelope.ts +51 -0
  387. package/src/providers/xai/conformance/function-call-arguments.ts +79 -0
  388. package/src/providers/xai/conformance/index.ts +81 -0
  389. package/src/providers/xai/conformance/plain-text.ts +64 -0
  390. package/src/providers/xai/conformance/terminal-event.ts +62 -0
  391. package/src/providers/xai/conformance/usage-cases.ts +145 -0
  392. package/src/providers/xai/conformance/usage-snapshot.ts +37 -0
  393. package/src/providers/xai/usage.ts +7 -1
  394. package/src/tools/README.md +19 -0
  395. package/src/tools/index.ts +3 -0
  396. package/src/tools/registry.ts +307 -59
  397. package/src/voice/tool-server.ts +5 -0
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @yolk-sdk/agent
2
2
 
3
- Domain-free agent protocol, loop, runtime, Effect-native client, compaction, tools, React, providers, OAuth, skillset, and voice 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
5
  Root export is intentionally empty. Import feature APIs from explicit subpaths.
6
6
 
@@ -12,46 +12,55 @@ pnpm add @yolk-sdk/agent@canary effect@4.0.0-rc.115
12
12
 
13
13
  Add `react` if you use `@yolk-sdk/agent/react` or `@yolk-sdk/agent/voice/react`.
14
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
+
15
17
  Canary APIs are unstable. Keep all `@yolk-sdk/*` packages on the same version.
16
18
  Use the SDK's matching Effect version (`4.0.0-rc.115`) in host code.
17
19
  Published package metadata requires Node.js 22+.
18
20
 
19
21
  ## Subpaths
20
22
 
21
- | Subpath | Purpose |
22
- | ------------------------------------------------------ | -------------------------------------------------------------- |
23
- | `@yolk-sdk/agent/protocol` | Wire messages, events, content, usage, tool schemas |
24
- | `@yolk-sdk/agent/loop` | Stateless LLM/tool loop |
25
- | `@yolk-sdk/agent/loop/testing` | Faux provider and tool executor test helpers |
26
- | `@yolk-sdk/agent/runtime` | Transcript or append-backed runtime orchestration |
27
- | `@yolk-sdk/agent/client` | HTTP/NDJSON transport, HITL resume, retry/error state helpers |
28
- | `@yolk-sdk/agent/compaction` | Host-owned compaction budgets, checkpoints, formatting, retry |
29
- | `@yolk-sdk/agent/tools` | Tool registry, typed inputs, interactions, subagents/questions |
30
- | `@yolk-sdk/agent/react` | Headless React chat hook, reducer, selectors, and render model |
31
- | `@yolk-sdk/agent/oauth` | Provider-neutral OAuth token and broker contracts |
32
- | `@yolk-sdk/agent/providers/openai` | OpenAI/Codex OAuth and broker helpers |
33
- | `@yolk-sdk/agent/providers/openai/codex` | OpenAI Codex request and auth helpers |
34
- | `@yolk-sdk/agent/providers/openai/codex-usage` | Codex subscription-allowance snapshots |
35
- | `@yolk-sdk/agent/providers/openai/codex-provider` | Codex LLM provider factory |
36
- | `@yolk-sdk/agent/providers/openai/provider` | OpenAI-compatible LLM provider factory |
37
- | `@yolk-sdk/agent/providers/openai/realtime` | OpenAI Realtime session config and event codecs |
38
- | `@yolk-sdk/agent/providers/openai/speech` | OpenAI text-to-speech and transcription adapters |
39
- | `@yolk-sdk/agent/providers/vercel/ai-gateway-provider` | Vercel AI Gateway Chat Completions provider factory |
40
- | `@yolk-sdk/agent/providers/opencode/go-provider` | OpenCode Go Chat Completions, Messages, and Responses provider |
41
- | `@yolk-sdk/agent/providers/opencode/usage` | OpenCode Go subscription-allowance snapshots |
42
- | `@yolk-sdk/agent/providers/anthropic` | Anthropic/Claude OAuth and broker helpers |
43
- | `@yolk-sdk/agent/providers/anthropic/claude` | Claude request and auth helpers |
44
- | `@yolk-sdk/agent/providers/anthropic/usage` | Claude subscription-allowance snapshots |
45
- | `@yolk-sdk/agent/providers/anthropic/claude-provider` | Claude LLM provider factory |
46
- | `@yolk-sdk/agent/providers/xai` | Grok subscription OAuth and token broker helpers |
47
- | `@yolk-sdk/agent/providers/xai/grok` | Grok subscription request and auth helpers |
48
- | `@yolk-sdk/agent/providers/xai/grok-provider` | Grok subscription LLM provider factory |
49
- | `@yolk-sdk/agent/providers/xai/usage` | Grok subscription-allowance snapshots |
50
- | `@yolk-sdk/agent/providers/subscription-usage` | Shared allowance snapshot and safe error schemas |
51
- | `@yolk-sdk/agent/skillset` | Portable skill and slash-command parsing/catalogs |
52
- | `@yolk-sdk/agent/voice` | Voice protocol, controller, tool handler, projection, speech |
53
- | `@yolk-sdk/agent/voice/browser` | Browser WebRTC voice transport |
54
- | `@yolk-sdk/agent/voice/react` | Headless browser voice React hook |
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 |
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 |
55
64
 
56
65
  ## Imports
57
66
 
@@ -248,7 +257,7 @@ const usageEffect = fetchOpenCodeGoSubscriptionUsage(Redacted.make(hostOpenCodeG
248
257
  }).pipe(Effect.provide(FetchHttpClient.layer))
249
258
  ```
250
259
 
251
- The fixed API-key endpoint returns used percentages/reset instants for `five-hour`, `seven-day`, and
260
+ The API-key endpoint (default `openCodeGoSubscriptionUsageUrl`) returns used percentages/reset instants for `five-hour`, `seven-day`, and
252
261
  `monthly` windows. Monthly resets follow the subscription's anniversary, not the first of the month;
253
262
  the adapter preserves the provider's timestamp. Missing/invalid percentages are omitted, not treated
254
263
  as zero. Treat snapshots as best-effort; hosts own polling, stale-data policy, persistence, and UI.
@@ -430,7 +439,8 @@ version.
430
439
  Provider adapters return an immutable Effect `Chunk` of semantic window ids, percentages, and
431
440
  optional reset/duration fields; hosts own labels, polling, persistence, stale-data policy, alert
432
441
  thresholds, billing interpretation, and UI. Configure `requestTimeoutMs` at the server integration
433
- boundary. Endpoint origins stay fixed, and `FetchHttpClient.layer` is configured for manual
442
+ boundary. Each fetcher defaults to its exported URL constant; the optional `url` override is only
443
+ for a trusted proxy or local emulator, because the credential is sent to it. `FetchHttpClient.layer` is configured for manual
434
444
  redirects. A custom `HttpClient` must not follow redirects for these credential-bearing requests.
435
445
 
436
446
  Subscription allowance snapshots are separate from protocol `AgentUsage`, which accounts for tokens
@@ -748,6 +758,47 @@ handler, approval HITL, transcript projection, and one-shot TTS/STT contracts.
748
758
  overflow such as `{"n":1e999}` takes the same mapper-specific fallbacks. Approval identifiers,
749
759
  gates, deny, and execution schema validation are unchanged.
750
760
 
761
+ ## Classifier models
762
+
763
+ `@yolk-sdk/agent/classification` is a provider-neutral contract for classifier models such as
764
+ TypeSafe's Jev: one `state` (a string, JSON object, or JSON array) and named `boolean`, `choice`
765
+ (2-255 options), or `score` (2-10 levels, lowest first) questions, answered together with
766
+ probabilities. `classify` types each answer from its question (a choice answer's `choice` is the
767
+ union of its option keys) and checks every answer against its question. Probabilities are kept as
768
+ returned, never renormalized. Failures are typed (`ClassificationRequestInvalid`,
769
+ `ClassificationProviderError`, `ClassificationResponseInvalid`); a response that fails to decode
770
+ keeps the billed `usage`. Classification is a read; authorization stays host policy.
771
+
772
+ `@yolk-sdk/agent/providers/vercel/ai-gateway-classifier` calls AI Gateway `POST /v1/evaluate`
773
+ (Gateway calls this evaluation) with `typesafe-ai/jev` by default and the same Gateway credential
774
+ as the chat provider:
775
+
776
+ ```ts
777
+ import { Effect, Redacted } from 'effect'
778
+ import { FetchHttpClient } from 'effect/unstable/http'
779
+ import { classify } from '@yolk-sdk/agent/classification'
780
+ import { makeVercelAiGatewayClassifierLayer } from '@yolk-sdk/agent/providers/vercel/ai-gateway-classifier'
781
+
782
+ const program = classify({
783
+ state: { subject: 'Invoice question', body: 'I was charged twice.' },
784
+ questions: {
785
+ route: {
786
+ type: 'choice',
787
+ instructions: 'Which team should handle this ticket?',
788
+ criteria: { billing: 'Payments and refunds.', bug: 'Product defects.' }
789
+ }
790
+ }
791
+ }).pipe(
792
+ Effect.map(result => result.answers.route.choice), // 'billing' | 'bug'
793
+ Effect.provide(makeVercelAiGatewayClassifierLayer({ apiKey: Redacted.make(gatewayKey) })),
794
+ Effect.provide(FetchHttpClient.layer)
795
+ )
796
+ ```
797
+
798
+ `providerOptions` passes through unchanged (for example `{ gateway: { zeroDataRetention: true } }`).
799
+ `providerMetadata.gateway.cost` becomes `usage.costUsd`, and `x-ai-gateway-evaluation-fallback-*`
800
+ response headers are kept in `providerMetadata.evaluationFallbackHeaders`.
801
+
751
802
  ## Subagents
752
803
 
753
804
  `subagent` is the package-owned contract for child-agent delegation. The SDK provides schema,
@@ -838,6 +889,28 @@ Without a host, definitions, approval ids, and inline behavior are unchanged.
838
889
  - Hosts own authorization, status/wait tools, cancellation, terminal storage, usage, and delivery.
839
890
  Never append a second result for the original call.
840
891
 
892
+ ## Code mode tool contract
893
+
894
+ These options are the tool contract that [`@yolk-sdk/codemode`](../codemode/README.md) builds on.
895
+ This package declares them; it does not run scripts.
896
+
897
+ - `makeTool({ output })` adds declaration-only `ToolDef.outputSchema`, lowered like `parameters`.
898
+ - `callableBy: 'all' | 'model' | 'codemode'` (default `all`) decides who may call a tool. For
899
+ `codemode` only, `discovery: 'listed' | 'search'` (default `listed`) decides how scripts find it.
900
+ Codemode-only tools never reach providers. Approval, input, interaction, activated background,
901
+ `question`, `subagent`, and nested-access tools never run from code mode; `resolveTools` rejects
902
+ `callableBy: 'codemode'` on them.
903
+ - `nestedToolAccess: true` gives a registration's `execute` a `nested` executor over the other
904
+ code-mode-callable tools of the same resolution and host context. Nested calls run through the
905
+ resolved execute path and fail closed with model-visible error results. Assign nested call ids as
906
+ `<parentToolCallId>/<seq>`.
907
+ - `describe: ({ tools }) => string` on a nested-access registration computes its resolved
908
+ description from those nested tools; `def.description` stays the static fallback.
909
+ - Report nested calls with protocol `recordNestedToolCall` and `nestedToolCallResultFields`. The
910
+ bounded `ToolResult.nestedCalls` record and summed `ToolResult.usage` never reach the model:
911
+ `toolResultMessageFromResult` drops both, and the loop does not add `ToolResult.usage` to run
912
+ usage. Capture them from the `ToolResult` or tool events when you need audit or billing records.
913
+
841
914
  ## Tool failures
842
915
 
843
916
  Use `modelVisibleToolError(...)` for expected tool-domain failures the model can recover
@@ -867,12 +940,16 @@ aborts, and implementation bugs outside typed tool execution.
867
940
  - Persist/return one `ToolResultMessage` for every host tool call, including `isError` failures.
868
941
  - Persist terminal provider failures and clear active run ids where applicable.
869
942
  - Provide tools, approval policy, auth, storage, and observability.
943
+ - If you send `ToolDef`s to providers yourself (outside `run`/`runModelTurn`), filter them with
944
+ protocol `providerToolDefs`; codemode-only tools must never reach providers. Executor decorators
945
+ outside `ResolvedToolSet.execute` do not see nested code mode calls.
870
946
  - Compact context and decide memory/search policy.
871
947
 
872
948
  ## Boundaries
873
949
 
874
950
  - Core loop/protocol/runtime/tools have no React, Next.js, provider SDKs, auth, storage drivers, or app concepts.
875
951
  - `@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.
952
+ - `@yolk-sdk/agent/classification` is provider-neutral (no Node, React, or provider code); provider subpaths supply `ClassifierModel` layers.
876
953
  - `@yolk-sdk/agent/react` is headless and uses React as an optional peer.
877
954
  - Provider subpaths own vendor wire/auth mechanics only; hosts own token storage, refresh, routing, and policy.
878
955
  - `@yolk-sdk/agent/providers/openai/speech` is server integration requiring runtime
@@ -0,0 +1,57 @@
1
+ import * as Schema from "effect/Schema";
2
+ import { ProviderErrorInfo } from "@yolk-sdk/agent/protocol";
3
+
4
+ //#region src/classification/errors.d.ts
5
+ /**
6
+ * Why an answer does not fit its question:
7
+ *
8
+ * - `missing_answer`: a question has no answer.
9
+ * - `unexpected_answer`: an answer names no question that was asked.
10
+ * - `type_mismatch`: the answer's `type` is not the question's.
11
+ * - `invalid_probability`: a probability is missing, not a number, non-finite, or outside `[0, 1]`.
12
+ * - `invalid_confidence`: a confidence is not a finite number in `[0, 1]`.
13
+ * - `invalid_choice`: a choice answer names no option of its question.
14
+ * - `invalid_score`: a score answer has no finite `score`.
15
+ * - `malformed_answer`: the answer is not an object.
16
+ */
17
+ declare const ClassificationAnswerIssueReason: Schema.Literals<readonly ["missing_answer", "unexpected_answer", "type_mismatch", "invalid_probability", "invalid_confidence", "invalid_choice", "invalid_score", "malformed_answer"]>;
18
+ type ClassificationAnswerIssueReason = typeof ClassificationAnswerIssueReason.Type;
19
+ /** `malformed_response`: the response body is not the provider's documented envelope. */
20
+ declare const ClassificationResponseIssue: Schema.Literals<readonly ["malformed_response", "missing_answer", "unexpected_answer", "type_mismatch", "invalid_probability", "invalid_confidence", "invalid_choice", "invalid_score", "malformed_answer"]>;
21
+ type ClassificationResponseIssue = typeof ClassificationResponseIssue.Type;
22
+ declare const ClassificationRequestInvalid_base: Schema.Class<ClassificationRequestInvalid, Schema.TaggedStruct<"ClassificationRequestInvalid", {
23
+ readonly message: Schema.String;
24
+ }>, import("effect/Cause").YieldableError>;
25
+ /** The request does not satisfy the classification contract; nothing was sent. */
26
+ declare class ClassificationRequestInvalid extends ClassificationRequestInvalid_base {}
27
+ declare const ClassificationProviderError_base: Schema.Class<ClassificationProviderError, Schema.TaggedStruct<"ClassificationProviderError", {
28
+ readonly message: Schema.String;
29
+ readonly retryable: Schema.Boolean;
30
+ readonly provider: typeof ProviderErrorInfo;
31
+ }>, import("effect/Cause").YieldableError>;
32
+ /**
33
+ * The provider could not be reached or rejected the request. `message` is safe to show: it never
34
+ * carries provider bodies, headers, or credentials. `provider` classifies the failure (status,
35
+ * provider error code, retry delay).
36
+ */
37
+ declare class ClassificationProviderError extends ClassificationProviderError_base {}
38
+ declare const ClassificationResponseInvalid_base: Schema.Class<ClassificationResponseInvalid, Schema.TaggedStruct<"ClassificationResponseInvalid", {
39
+ readonly message: Schema.String; /** Provider id, when a provider (not the typed `classify` check) found the issue. */
40
+ readonly provider: Schema.optional<Schema.String>;
41
+ readonly reason: Schema.Literals<readonly ["malformed_response", "missing_answer", "unexpected_answer", "type_mismatch", "invalid_probability", "invalid_confidence", "invalid_choice", "invalid_score", "malformed_answer"]>;
42
+ readonly questionId: Schema.optional<Schema.String>;
43
+ readonly usage: Schema.optional<Schema.Struct<{
44
+ readonly inputTokens: Schema.Int;
45
+ readonly outputTokens: Schema.Int;
46
+ readonly costUsd: Schema.optionalKey<Schema.Finite>;
47
+ }>>;
48
+ }>, import("effect/Cause").YieldableError>;
49
+ /**
50
+ * The provider answered, but the response or one of its answers does not fit the request.
51
+ * `usage` is kept when the provider reported it, because the request was billed.
52
+ */
53
+ declare class ClassificationResponseInvalid extends ClassificationResponseInvalid_base {}
54
+ type ClassificationError = ClassificationRequestInvalid | ClassificationProviderError | ClassificationResponseInvalid;
55
+ //#endregion
56
+ export { ClassificationAnswerIssueReason, ClassificationError, ClassificationProviderError, ClassificationRequestInvalid, ClassificationResponseInvalid, ClassificationResponseIssue };
57
+ //# sourceMappingURL=errors.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.mts","names":[],"sources":["../../src/classification/errors.ts"],"mappings":";;;;;;AAgBA;;;;AAA4C;AAW5C;;;;AAAyF;cAX5E,+BAAA,EAA+B,MAAA,CAAA,QAAA;AAAA,KAWhC,+BAAA,UAAyC,+BAAA,CAAgC,IAAI;;cAG5E,2BAAA,EAA2B,MAAA,CAAA,QAAA;AAAA,KAK5B,2BAAA,UAAqC,2BAAA,CAA4B,IAAI;AAAA,cAAA,iCAAA;;;;cAGpE,4BAAA,SAAqC,iCAKjD;AAAA,cAAG,gCAAA;;;;;;;;;;cAOS,2BAAA,SAAoC,gCAOhD;AAAA,cAAG,kCAAA;;;;;;;;;;;AAdA;;;;AAAA,cAoBS,6BAAA,SAAsC,kCAUlD;AAAA,KAEW,mBAAA,GACR,4BAAA,GACA,2BAAA,GACA,6BAAA"}
@@ -0,0 +1,56 @@
1
+ import { ClassificationUsage } from "./schema.mjs";
2
+ import * as Schema from "effect/Schema";
3
+ import { ProviderErrorInfo } from "@yolk-sdk/agent/protocol";
4
+ //#region src/classification/errors.ts
5
+ /**
6
+ * Why an answer does not fit its question:
7
+ *
8
+ * - `missing_answer`: a question has no answer.
9
+ * - `unexpected_answer`: an answer names no question that was asked.
10
+ * - `type_mismatch`: the answer's `type` is not the question's.
11
+ * - `invalid_probability`: a probability is missing, not a number, non-finite, or outside `[0, 1]`.
12
+ * - `invalid_confidence`: a confidence is not a finite number in `[0, 1]`.
13
+ * - `invalid_choice`: a choice answer names no option of its question.
14
+ * - `invalid_score`: a score answer has no finite `score`.
15
+ * - `malformed_answer`: the answer is not an object.
16
+ */
17
+ const ClassificationAnswerIssueReason = Schema.Literals([
18
+ "missing_answer",
19
+ "unexpected_answer",
20
+ "type_mismatch",
21
+ "invalid_probability",
22
+ "invalid_confidence",
23
+ "invalid_choice",
24
+ "invalid_score",
25
+ "malformed_answer"
26
+ ]);
27
+ /** `malformed_response`: the response body is not the provider's documented envelope. */
28
+ const ClassificationResponseIssue = Schema.Literals(["malformed_response", ...ClassificationAnswerIssueReason.literals]);
29
+ /** The request does not satisfy the classification contract; nothing was sent. */
30
+ var ClassificationRequestInvalid = class extends Schema.TaggedError()("ClassificationRequestInvalid", { message: Schema.String }) {};
31
+ /**
32
+ * The provider could not be reached or rejected the request. `message` is safe to show: it never
33
+ * carries provider bodies, headers, or credentials. `provider` classifies the failure (status,
34
+ * provider error code, retry delay).
35
+ */
36
+ var ClassificationProviderError = class extends Schema.TaggedError()("ClassificationProviderError", {
37
+ message: Schema.String,
38
+ retryable: Schema.Boolean,
39
+ provider: ProviderErrorInfo
40
+ }) {};
41
+ /**
42
+ * The provider answered, but the response or one of its answers does not fit the request.
43
+ * `usage` is kept when the provider reported it, because the request was billed.
44
+ */
45
+ var ClassificationResponseInvalid = class extends Schema.TaggedError()("ClassificationResponseInvalid", {
46
+ message: Schema.String,
47
+ /** Provider id, when a provider (not the typed `classify` check) found the issue. */
48
+ provider: Schema.optional(Schema.String),
49
+ reason: ClassificationResponseIssue,
50
+ questionId: Schema.optional(Schema.String),
51
+ usage: Schema.optional(ClassificationUsage)
52
+ }) {};
53
+ //#endregion
54
+ export { ClassificationAnswerIssueReason, ClassificationProviderError, ClassificationRequestInvalid, ClassificationResponseInvalid, ClassificationResponseIssue };
55
+
56
+ //# sourceMappingURL=errors.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.mjs","names":[],"sources":["../../src/classification/errors.ts"],"sourcesContent":["import * as Schema from 'effect/Schema'\nimport { ProviderErrorInfo } from '@yolk-sdk/agent/protocol'\nimport { ClassificationUsage } from './schema.ts'\n\n/**\n * Why an answer does not fit its question:\n *\n * - `missing_answer`: a question has no answer.\n * - `unexpected_answer`: an answer names no question that was asked.\n * - `type_mismatch`: the answer's `type` is not the question's.\n * - `invalid_probability`: a probability is missing, not a number, non-finite, or outside `[0, 1]`.\n * - `invalid_confidence`: a confidence is not a finite number in `[0, 1]`.\n * - `invalid_choice`: a choice answer names no option of its question.\n * - `invalid_score`: a score answer has no finite `score`.\n * - `malformed_answer`: the answer is not an object.\n */\nexport const ClassificationAnswerIssueReason = Schema.Literals([\n 'missing_answer',\n 'unexpected_answer',\n 'type_mismatch',\n 'invalid_probability',\n 'invalid_confidence',\n 'invalid_choice',\n 'invalid_score',\n 'malformed_answer'\n])\n\nexport type ClassificationAnswerIssueReason = typeof ClassificationAnswerIssueReason.Type\n\n/** `malformed_response`: the response body is not the provider's documented envelope. */\nexport const ClassificationResponseIssue = Schema.Literals([\n 'malformed_response',\n ...ClassificationAnswerIssueReason.literals\n])\n\nexport type ClassificationResponseIssue = typeof ClassificationResponseIssue.Type\n\n/** The request does not satisfy the classification contract; nothing was sent. */\nexport class ClassificationRequestInvalid extends Schema.TaggedError<ClassificationRequestInvalid>()(\n 'ClassificationRequestInvalid',\n {\n message: Schema.String\n }\n) {}\n\n/**\n * The provider could not be reached or rejected the request. `message` is safe to show: it never\n * carries provider bodies, headers, or credentials. `provider` classifies the failure (status,\n * provider error code, retry delay).\n */\nexport class ClassificationProviderError extends Schema.TaggedError<ClassificationProviderError>()(\n 'ClassificationProviderError',\n {\n message: Schema.String,\n retryable: Schema.Boolean,\n provider: ProviderErrorInfo\n }\n) {}\n\n/**\n * The provider answered, but the response or one of its answers does not fit the request.\n * `usage` is kept when the provider reported it, because the request was billed.\n */\nexport class ClassificationResponseInvalid extends Schema.TaggedError<ClassificationResponseInvalid>()(\n 'ClassificationResponseInvalid',\n {\n message: Schema.String,\n /** Provider id, when a provider (not the typed `classify` check) found the issue. */\n provider: Schema.optional(Schema.String),\n reason: ClassificationResponseIssue,\n questionId: Schema.optional(Schema.String),\n usage: Schema.optional(ClassificationUsage)\n }\n) {}\n\nexport type ClassificationError =\n | ClassificationRequestInvalid\n | ClassificationProviderError\n | ClassificationResponseInvalid\n"],"mappings":";;;;;;;;;;;;;;;;AAgBA,MAAa,kCAAkC,OAAO,SAAS;CAC7D;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF,CAAC;;AAKD,MAAa,8BAA8B,OAAO,SAAS,CACzD,sBACA,GAAG,gCAAgC,QACrC,CAAC;;AAKD,IAAa,+BAAb,cAAkD,OAAO,YAA0C,EACjG,gCACA,EACE,SAAS,OAAO,OAClB,CACF,EAAE,CAAC;;;;;;AAOH,IAAa,8BAAb,cAAiD,OAAO,YAAyC,EAC/F,+BACA;CACE,SAAS,OAAO;CAChB,WAAW,OAAO;CAClB,UAAU;AACZ,CACF,EAAE,CAAC;;;;;AAMH,IAAa,gCAAb,cAAmD,OAAO,YAA2C,EACnG,iCACA;CACE,SAAS,OAAO;;CAEhB,UAAU,OAAO,SAAS,OAAO,MAAM;CACvC,QAAQ;CACR,YAAY,OAAO,SAAS,OAAO,MAAM;CACzC,OAAO,OAAO,SAAS,mBAAmB;AAC5C,CACF,EAAE,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { ClassificationAnswerIssueReason, ClassificationError, ClassificationProviderError, ClassificationRequestInvalid, ClassificationResponseInvalid, ClassificationResponseIssue } from "./errors.mjs";
2
+ import { BooleanClassifierAnswer, BooleanClassifierQuestion, ChoiceClassifierAnswer, ChoiceClassifierQuestion, ClassificationRequest, ClassificationResult, ClassificationUsage, ClassifierAnswer, ClassifierCriterion, ClassifierProbabilities, ClassifierProbability, ClassifierQuestion, ClassifierQuestionType, ClassifierQuestions, ClassifierState, ScoreClassifierAnswer, ScoreClassifierQuestion, maxClassifierChoiceOptions, maxClassifierScoreLevels, minClassifierChoiceOptions, minClassifierScoreLevels } from "./schema.mjs";
3
+ import { ClassificationAnswerIssue, ClassificationRequestFor, ClassificationResultFor, ClassifierAnswerFor, ClassifierAnswersFor, ClassifierModel, ClassifierQuestionsInput, classificationAnswersIssue, classify, decodeClassificationRequest, decodeClassifierAnswer, decodeClassifierAnswers, isClassificationResultFor } from "./model.mjs";
4
+ export { BooleanClassifierAnswer, BooleanClassifierQuestion, ChoiceClassifierAnswer, ChoiceClassifierQuestion, type ClassificationAnswerIssue, ClassificationAnswerIssueReason, type ClassificationError, ClassificationProviderError, ClassificationRequest, type ClassificationRequestFor, ClassificationRequestInvalid, ClassificationResponseInvalid, ClassificationResponseIssue, ClassificationResult, type ClassificationResultFor, ClassificationUsage, ClassifierAnswer, type ClassifierAnswerFor, type ClassifierAnswersFor, ClassifierCriterion, ClassifierModel, ClassifierProbabilities, ClassifierProbability, ClassifierQuestion, type ClassifierQuestionType, ClassifierQuestions, type ClassifierQuestionsInput, ClassifierState, ScoreClassifierAnswer, ScoreClassifierQuestion, classificationAnswersIssue, classify, decodeClassificationRequest, decodeClassifierAnswer, decodeClassifierAnswers, isClassificationResultFor, maxClassifierChoiceOptions, maxClassifierScoreLevels, minClassifierChoiceOptions, minClassifierScoreLevels };
@@ -0,0 +1,4 @@
1
+ import { BooleanClassifierAnswer, BooleanClassifierQuestion, ChoiceClassifierAnswer, ChoiceClassifierQuestion, ClassificationRequest, ClassificationResult, ClassificationUsage, ClassifierAnswer, ClassifierCriterion, ClassifierProbabilities, ClassifierProbability, ClassifierQuestion, ClassifierQuestions, ClassifierState, ScoreClassifierAnswer, ScoreClassifierQuestion, maxClassifierChoiceOptions, maxClassifierScoreLevels, minClassifierChoiceOptions, minClassifierScoreLevels } from "./schema.mjs";
2
+ import { ClassificationAnswerIssueReason, ClassificationProviderError, ClassificationRequestInvalid, ClassificationResponseInvalid, ClassificationResponseIssue } from "./errors.mjs";
3
+ import { ClassifierModel, classificationAnswersIssue, classify, decodeClassificationRequest, decodeClassifierAnswer, decodeClassifierAnswers, isClassificationResultFor } from "./model.mjs";
4
+ export { BooleanClassifierAnswer, BooleanClassifierQuestion, ChoiceClassifierAnswer, ChoiceClassifierQuestion, ClassificationAnswerIssueReason, ClassificationProviderError, ClassificationRequest, ClassificationRequestInvalid, ClassificationResponseInvalid, ClassificationResponseIssue, ClassificationResult, ClassificationUsage, ClassifierAnswer, ClassifierCriterion, ClassifierModel, ClassifierProbabilities, ClassifierProbability, ClassifierQuestion, ClassifierQuestions, ClassifierState, ScoreClassifierAnswer, ScoreClassifierQuestion, classificationAnswersIssue, classify, decodeClassificationRequest, decodeClassifierAnswer, decodeClassifierAnswers, isClassificationResultFor, maxClassifierChoiceOptions, maxClassifierScoreLevels, minClassifierChoiceOptions, minClassifierScoreLevels };
@@ -0,0 +1,74 @@
1
+ import { ClassificationAnswerIssueReason, ClassificationError, ClassificationRequestInvalid } from "./errors.mjs";
2
+ import { BooleanClassifierAnswer, ChoiceClassifierAnswer, ClassificationRequest, ClassificationResult, ClassifierAnswer, ClassifierQuestion, ScoreClassifierAnswer } from "./schema.mjs";
3
+ import { Context, Effect, Result } from "effect";
4
+
5
+ //#region src/classification/model.d.ts
6
+ declare const ClassifierModel_base: Context.ServiceClass<ClassifierModel, "@yolk-sdk/agent/classification/ClassifierModel", {
7
+ readonly classify: (request: ClassificationRequest) => Effect.Effect<ClassificationResult, ClassificationError>;
8
+ }>;
9
+ /**
10
+ * Answers typed questions about one state. Classification is a read: it has no side effects.
11
+ * Providers supply layers; `classify` is the typed entry point.
12
+ */
13
+ declare class ClassifierModel extends ClassifierModel_base {}
14
+ /** Named questions, typed for inference. */
15
+ type ClassifierQuestionsInput = {
16
+ readonly [questionId: string]: ClassifierQuestion;
17
+ };
18
+ /** The answer type a question gets; a choice answer's `choice` is the union of its option keys. */
19
+ type ClassifierAnswerFor<Q extends ClassifierQuestion> = Q extends {
20
+ readonly type: 'boolean';
21
+ } ? BooleanClassifierAnswer : Q extends {
22
+ readonly type: 'choice';
23
+ readonly criteria: infer Criteria;
24
+ } ? ChoiceClassifierAnswer & {
25
+ readonly choice: Extract<keyof Criteria, string>;
26
+ } : ScoreClassifierAnswer;
27
+ type ClassifierAnswersFor<Q extends ClassifierQuestionsInput> = { readonly [K in keyof Q]: ClassifierAnswerFor<Q[K]> };
28
+ type ClassificationRequestFor<Q extends ClassifierQuestionsInput> = Omit<ClassificationRequest, 'questions'> & {
29
+ readonly questions: Q;
30
+ };
31
+ type ClassificationResultFor<Q extends ClassifierQuestionsInput> = ClassificationResult & {
32
+ readonly answers: ClassifierAnswersFor<Q>;
33
+ };
34
+ /** Where an answer leaves its question. */
35
+ type ClassificationAnswerIssue = {
36
+ readonly reason: ClassificationAnswerIssueReason;
37
+ readonly questionId: string;
38
+ };
39
+ /**
40
+ * Decode one raw provider answer against the question it answers. The answer must be an object
41
+ * whose `type` is the question's; probabilities and confidence must be finite numbers in `[0, 1]`
42
+ * and are kept exactly as given (never renormalized); a choice must name one of the question's
43
+ * options; a score must be finite. Only the contract fields are kept.
44
+ */
45
+ declare const decodeClassifierAnswer: (question: ClassifierQuestion, raw: unknown) => Result.Result<ClassifierAnswer, ClassificationAnswerIssueReason>;
46
+ /**
47
+ * Decode raw provider answers (a JSON object keyed by question id) against the questions asked:
48
+ * every question needs exactly one answer of its type, and no answer may name a question that was
49
+ * not asked. Fails with the first issue, in question order (then unexpected answers); answers that
50
+ * are not an object fail as the first question's `malformed_answer`.
51
+ */
52
+ declare const decodeClassifierAnswers: (questions: ClassifierQuestionsInput, raw: unknown) => Result.Result<Record<string, ClassifierAnswer>, ClassificationAnswerIssue>;
53
+ /** The first way `answers` leaves `questions`, or undefined when every answer fits its question. */
54
+ declare const classificationAnswersIssue: (questions: ClassifierQuestionsInput, answers: {
55
+ readonly [questionId: string]: ClassifierAnswer;
56
+ }) => ClassificationAnswerIssue | undefined;
57
+ /** Narrow a result to the answer types its questions infer, after checking every answer. */
58
+ declare const isClassificationResultFor: <const Q extends ClassifierQuestionsInput>(questions: Q, result: ClassificationResult) => result is ClassificationResultFor<Q>;
59
+ /**
60
+ * Validate a request against the classification contract before anything is sent. Fails with
61
+ * `ClassificationRequestInvalid` (for example a choice with more than 255 options, or a score with
62
+ * more than 10 levels).
63
+ */
64
+ declare const decodeClassificationRequest: (request: unknown) => Effect.Effect<ClassificationRequest, ClassificationRequestInvalid>;
65
+ /**
66
+ * Classify with the `ClassifierModel` in context, typing each answer from its question: a choice
67
+ * answer's `choice` is the union of that question's option keys. Every answer is checked against
68
+ * its question; a provider that returns a mismatching answer fails with
69
+ * `ClassificationResponseInvalid` (keeping usage).
70
+ */
71
+ declare const classify: <const Q extends ClassifierQuestionsInput>(request: ClassificationRequestFor<Q>) => Effect.Effect<ClassificationResultFor<Q>, ClassificationError, ClassifierModel>;
72
+ //#endregion
73
+ export { ClassificationAnswerIssue, ClassificationRequestFor, ClassificationResultFor, ClassifierAnswerFor, ClassifierAnswersFor, ClassifierModel, ClassifierQuestionsInput, classificationAnswersIssue, classify, decodeClassificationRequest, decodeClassifierAnswer, decodeClassifierAnswers, isClassificationResultFor };
74
+ //# sourceMappingURL=model.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model.d.mts","names":[],"sources":["../../src/classification/model.ts"],"mappings":";;;;;cAiBoB,oBAAA;sBAUd,OAAA,EAAS,qBAAA,KACN,MAAA,CAAO,MAAA,CAAO,oBAAA,EAAsB,mBAAA;AAAA;;;;;cALhC,eAAA,SAAwB,oBAOgB;;KAGzC,wBAAA;EAAA,UAAuC,UAAA,WAAqB,kBAAkB;AAAA;;KAG9E,mBAAA,WAA8B,kBAAA,IAAsB,CAAA;EAAA,SACrD,IAAA;AAAA,IAEP,uBAAA,GACA,CAAA;EAAA,SAAqB,IAAA;EAAA,SAAyB,QAAA;AAAA,IAC5C,sBAAA;EAAA,SAAoC,MAAA,EAAQ,OAAA,OAAc,QAAA;AAAA,IAC1D,qBAAA;AAAA,KAEM,oBAAA,WAA+B,wBAAA,2BACpB,CAAA,GAAI,mBAAA,CAAoB,CAAA,CAAE,CAAA;AAAA,KAGrC,wBAAA,WAAmC,wBAAA,IAA4B,IAAA,CACzE,qBAAA;EAAA,SAEa,SAAA,EAAW,CAAA;AAAA;AAAA,KAEd,uBAAA,WAAkC,wBAAA,IAA4B,oBAAA;EAAA,SAC/D,OAAA,EAAS,oBAAA,CAAqB,CAAA;AAAA;;KAI7B,yBAAA;EAAA,SACD,MAAA,EAAQ,+BAA+B;EAAA,SACvC,UAAA;AAAA;;;;;;;cAuDE,sBAAA,GACX,QAAA,EAAU,kBAAA,EACV,GAAA,cACC,MAAA,CAAO,MAAA,CAAO,gBAAA,EAAkB,+BAAA;;;;;;;cAwDtB,uBAAA,GACX,SAAA,EAAW,wBAAA,EACX,GAAA,cACC,MAAA,CAAO,MAAA,CAAO,MAAA,SAAe,gBAAA,GAAmB,yBAAA;;cAkCtC,0BAAA,GACX,SAAA,EAAW,wBAAA,EACX,OAAA;EAAA,UAAqB,UAAA,WAAqB,gBAAA;AAAA,MACzC,yBAAA;;cAOU,yBAAA,mBAA6C,wBAAA,EACxD,SAAA,EAAW,CAAA,EACX,MAAA,EAAQ,oBAAA,KACP,MAAA,IAAU,uBAAA,CAAwB,CAAA;;;;;;cAQxB,2BAAA,GACX,OAAA,cACC,MAAA,CAAO,MAAA,CAAO,qBAAA,EAAuB,4BAAA;;AAhMb;AAE3B;;;;cA6Ma,QAAA,mBAA4B,wBAAA,EACvC,OAAA,EAAS,wBAAA,CAAyB,CAAA,MACjC,MAAA,CAAO,MAAA,CAAO,uBAAA,CAAwB,CAAA,GAAI,mBAAA,EAAqB,eAAA"}
@@ -0,0 +1,136 @@
1
+ import { ClassificationRequest } from "./schema.mjs";
2
+ import { ClassificationRequestInvalid, ClassificationResponseInvalid } from "./errors.mjs";
3
+ import { Context, Effect, Predicate, Result } from "effect";
4
+ import * as Schema$1 from "effect/Schema";
5
+ //#region src/classification/model.ts
6
+ /**
7
+ * Answers typed questions about one state. Classification is a read: it has no side effects.
8
+ * Providers supply layers; `classify` is the typed entry point.
9
+ */
10
+ var ClassifierModel = class extends Context.Service()("@yolk-sdk/agent/classification/ClassifierModel") {};
11
+ const isProbability = (value) => Predicate.isNumber(value) && Number.isFinite(value) && value >= 0 && value <= 1;
12
+ const isFieldObject = (value) => Predicate.isObject(value) && !Array.isArray(value);
13
+ /** An own field of a JSON object, never an inherited one (`toString`, `__proto__`). */
14
+ const ownField = (value, key) => Object.hasOwn(value, key) && Predicate.hasProperty(value, key) ? value[key] : void 0;
15
+ const decodeProbabilities = (value) => {
16
+ if (!isFieldObject(value)) return Result.fail("invalid_probability");
17
+ const entries = [];
18
+ for (const key of Object.keys(value)) {
19
+ const probability = ownField(value, key);
20
+ if (!isProbability(probability)) return Result.fail("invalid_probability");
21
+ entries.push([key, probability]);
22
+ }
23
+ return Result.succeed(Object.fromEntries(entries));
24
+ };
25
+ const decodeConfidence = (raw, fields) => {
26
+ if (!Object.hasOwn(raw, "confidence")) return void 0;
27
+ const confidence = ownField(raw, "confidence");
28
+ if (!isProbability(confidence)) return "invalid_confidence";
29
+ fields.confidence = confidence;
30
+ };
31
+ /**
32
+ * Decode one raw provider answer against the question it answers. The answer must be an object
33
+ * whose `type` is the question's; probabilities and confidence must be finite numbers in `[0, 1]`
34
+ * and are kept exactly as given (never renormalized); a choice must name one of the question's
35
+ * options; a score must be finite. Only the contract fields are kept.
36
+ */
37
+ const decodeClassifierAnswer = (question, raw) => {
38
+ if (!isFieldObject(raw)) return Result.fail("malformed_answer");
39
+ if (ownField(raw, "type") !== question.type) return Result.fail("type_mismatch");
40
+ if (question.type === "boolean") {
41
+ const probability = ownField(raw, "probability");
42
+ return isProbability(probability) ? Result.succeed({
43
+ type: "boolean",
44
+ probability
45
+ }) : Result.fail("invalid_probability");
46
+ }
47
+ const probabilities = decodeProbabilities(ownField(raw, "probabilities"));
48
+ if (Result.isFailure(probabilities)) return Result.fail(probabilities.failure);
49
+ if (question.type === "choice") {
50
+ const choice = ownField(raw, "choice");
51
+ if (!Predicate.isString(choice) || !Object.hasOwn(question.criteria, choice)) return Result.fail("invalid_choice");
52
+ const fields = {
53
+ type: "choice",
54
+ choice,
55
+ probabilities: probabilities.success
56
+ };
57
+ const issue = decodeConfidence(raw, fields);
58
+ return issue === void 0 ? Result.succeed(fields) : Result.fail(issue);
59
+ }
60
+ const score = ownField(raw, "score");
61
+ if (!Predicate.isNumber(score) || !Number.isFinite(score)) return Result.fail("invalid_score");
62
+ const fields = {
63
+ type: "score",
64
+ score,
65
+ probabilities: probabilities.success
66
+ };
67
+ const issue = decodeConfidence(raw, fields);
68
+ return issue === void 0 ? Result.succeed(fields) : Result.fail(issue);
69
+ };
70
+ /**
71
+ * Decode raw provider answers (a JSON object keyed by question id) against the questions asked:
72
+ * every question needs exactly one answer of its type, and no answer may name a question that was
73
+ * not asked. Fails with the first issue, in question order (then unexpected answers); answers that
74
+ * are not an object fail as the first question's `malformed_answer`.
75
+ */
76
+ const decodeClassifierAnswers = (questions, raw) => {
77
+ const questionIds = Object.keys(questions);
78
+ if (!isFieldObject(raw)) return Result.fail({
79
+ reason: "malformed_answer",
80
+ questionId: questionIds[0] ?? ""
81
+ });
82
+ const entries = [];
83
+ for (const [questionId, question] of Object.entries(questions)) {
84
+ if (!Object.hasOwn(raw, questionId)) return Result.fail({
85
+ reason: "missing_answer",
86
+ questionId
87
+ });
88
+ const answer = decodeClassifierAnswer(question, ownField(raw, questionId));
89
+ if (Result.isFailure(answer)) return Result.fail({
90
+ reason: answer.failure,
91
+ questionId
92
+ });
93
+ entries.push([questionId, answer.success]);
94
+ }
95
+ const answers = Object.fromEntries(entries);
96
+ for (const questionId of Object.keys(raw)) if (!Object.hasOwn(questions, questionId)) return Result.fail({
97
+ reason: "unexpected_answer",
98
+ questionId
99
+ });
100
+ return Result.succeed(answers);
101
+ };
102
+ /** The first way `answers` leaves `questions`, or undefined when every answer fits its question. */
103
+ const classificationAnswersIssue = (questions, answers) => {
104
+ const decoded = decodeClassifierAnswers(questions, answers);
105
+ return Result.isFailure(decoded) ? decoded.failure : void 0;
106
+ };
107
+ /** Narrow a result to the answer types its questions infer, after checking every answer. */
108
+ const isClassificationResultFor = (questions, result) => classificationAnswersIssue(questions, result.answers) === void 0;
109
+ /**
110
+ * Validate a request against the classification contract before anything is sent. Fails with
111
+ * `ClassificationRequestInvalid` (for example a choice with more than 255 options, or a score with
112
+ * more than 10 levels).
113
+ */
114
+ const decodeClassificationRequest = (request) => Schema$1.decodeUnknownEffect(ClassificationRequest)(request).pipe(Effect.mapError((error) => ClassificationRequestInvalid.make({ message: `Invalid classification request: ${error.message}` })));
115
+ /**
116
+ * Classify with the `ClassifierModel` in context, typing each answer from its question: a choice
117
+ * answer's `choice` is the union of that question's option keys. Every answer is checked against
118
+ * its question; a provider that returns a mismatching answer fails with
119
+ * `ClassificationResponseInvalid` (keeping usage).
120
+ */
121
+ const classify = (request) => Effect.gen(function* () {
122
+ const result = yield* (yield* ClassifierModel).classify(request);
123
+ if (isClassificationResultFor(request.questions, result)) return result;
124
+ const issue = classificationAnswersIssue(request.questions, result.answers);
125
+ const reason = issue?.reason ?? "malformed_answer";
126
+ return yield* Effect.fail(ClassificationResponseInvalid.make({
127
+ message: `Classification answers do not fit their questions: ${reason}`,
128
+ reason,
129
+ questionId: issue?.questionId,
130
+ usage: result.usage
131
+ }));
132
+ });
133
+ //#endregion
134
+ export { ClassifierModel, classificationAnswersIssue, classify, decodeClassificationRequest, decodeClassifierAnswer, decodeClassifierAnswers, isClassificationResultFor };
135
+
136
+ //# sourceMappingURL=model.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model.mjs","names":["Schema"],"sources":["../../src/classification/model.ts"],"sourcesContent":["import { Context, Effect, Predicate, Result } from 'effect'\nimport * as Schema from 'effect/Schema'\nimport {\n ClassificationRequestInvalid,\n ClassificationResponseInvalid,\n type ClassificationAnswerIssueReason,\n type ClassificationError\n} from './errors.ts'\nimport {\n ClassificationRequest,\n type BooleanClassifierAnswer,\n type ChoiceClassifierAnswer,\n type ClassificationResult,\n type ClassifierAnswer,\n type ClassifierProbabilities,\n type ClassifierQuestion,\n type ScoreClassifierAnswer\n} from './schema.ts'\n\n/**\n * Answers typed questions about one state. Classification is a read: it has no side effects.\n * Providers supply layers; `classify` is the typed entry point.\n */\nexport class ClassifierModel extends Context.Service<\n ClassifierModel,\n {\n readonly classify: (\n request: ClassificationRequest\n ) => Effect.Effect<ClassificationResult, ClassificationError>\n }\n>()('@yolk-sdk/agent/classification/ClassifierModel') {}\n\n/** Named questions, typed for inference. */\nexport type ClassifierQuestionsInput = { readonly [questionId: string]: ClassifierQuestion }\n\n/** The answer type a question gets; a choice answer's `choice` is the union of its option keys. */\nexport type ClassifierAnswerFor<Q extends ClassifierQuestion> = Q extends {\n readonly type: 'boolean'\n}\n ? BooleanClassifierAnswer\n : Q extends { readonly type: 'choice'; readonly criteria: infer Criteria }\n ? ChoiceClassifierAnswer & { readonly choice: Extract<keyof Criteria, string> }\n : ScoreClassifierAnswer\n\nexport type ClassifierAnswersFor<Q extends ClassifierQuestionsInput> = {\n readonly [K in keyof Q]: ClassifierAnswerFor<Q[K]>\n}\n\nexport type ClassificationRequestFor<Q extends ClassifierQuestionsInput> = Omit<\n ClassificationRequest,\n 'questions'\n> & { readonly questions: Q }\n\nexport type ClassificationResultFor<Q extends ClassifierQuestionsInput> = ClassificationResult & {\n readonly answers: ClassifierAnswersFor<Q>\n}\n\n/** Where an answer leaves its question. */\nexport type ClassificationAnswerIssue = {\n readonly reason: ClassificationAnswerIssueReason\n readonly questionId: string\n}\n\nconst isProbability = (value: unknown): value is number =>\n Predicate.isNumber(value) && Number.isFinite(value) && value >= 0 && value <= 1\n\nconst isFieldObject = (value: unknown): value is object =>\n Predicate.isObject(value) && !Array.isArray(value)\n\n/** An own field of a JSON object, never an inherited one (`toString`, `__proto__`). */\nconst ownField = (value: object, key: string): unknown =>\n Object.hasOwn(value, key) && Predicate.hasProperty(value, key) ? value[key] : undefined\n\nconst decodeProbabilities = (\n value: unknown\n): Result.Result<ClassifierProbabilities, ClassificationAnswerIssueReason> => {\n if (!isFieldObject(value)) return Result.fail('invalid_probability')\n\n const entries: Array<readonly [string, number]> = []\n\n for (const key of Object.keys(value)) {\n const probability = ownField(value, key)\n\n if (!isProbability(probability)) return Result.fail('invalid_probability')\n\n entries.push([key, probability])\n }\n\n // `Object.fromEntries` defines own data properties, so keys such as `__proto__` are kept.\n return Result.succeed(Object.fromEntries(entries))\n}\n\ntype ConfidenceField = { confidence?: number }\n\nconst decodeConfidence = (\n raw: object,\n fields: ConfidenceField\n): ClassificationAnswerIssueReason | undefined => {\n if (!Object.hasOwn(raw, 'confidence')) return undefined\n\n const confidence = ownField(raw, 'confidence')\n\n if (!isProbability(confidence)) return 'invalid_confidence'\n\n fields.confidence = confidence\n\n return undefined\n}\n\n/**\n * Decode one raw provider answer against the question it answers. The answer must be an object\n * whose `type` is the question's; probabilities and confidence must be finite numbers in `[0, 1]`\n * and are kept exactly as given (never renormalized); a choice must name one of the question's\n * options; a score must be finite. Only the contract fields are kept.\n */\nexport const decodeClassifierAnswer = (\n question: ClassifierQuestion,\n raw: unknown\n): Result.Result<ClassifierAnswer, ClassificationAnswerIssueReason> => {\n if (!isFieldObject(raw)) return Result.fail('malformed_answer')\n\n if (ownField(raw, 'type') !== question.type) return Result.fail('type_mismatch')\n\n if (question.type === 'boolean') {\n const probability = ownField(raw, 'probability')\n\n return isProbability(probability)\n ? Result.succeed({ type: 'boolean', probability })\n : Result.fail('invalid_probability')\n }\n\n const probabilities = decodeProbabilities(ownField(raw, 'probabilities'))\n\n if (Result.isFailure(probabilities)) return Result.fail(probabilities.failure)\n\n if (question.type === 'choice') {\n const choice = ownField(raw, 'choice')\n\n if (!Predicate.isString(choice) || !Object.hasOwn(question.criteria, choice)) {\n return Result.fail('invalid_choice')\n }\n\n const fields: ChoiceClassifierAnswer & ConfidenceField = {\n type: 'choice',\n choice,\n probabilities: probabilities.success\n }\n\n const issue = decodeConfidence(raw, fields)\n\n return issue === undefined ? Result.succeed(fields) : Result.fail(issue)\n }\n\n const score = ownField(raw, 'score')\n\n if (!Predicate.isNumber(score) || !Number.isFinite(score)) return Result.fail('invalid_score')\n\n const fields: ScoreClassifierAnswer & ConfidenceField = {\n type: 'score',\n score,\n probabilities: probabilities.success\n }\n\n const issue = decodeConfidence(raw, fields)\n\n return issue === undefined ? Result.succeed(fields) : Result.fail(issue)\n}\n\n/**\n * Decode raw provider answers (a JSON object keyed by question id) against the questions asked:\n * every question needs exactly one answer of its type, and no answer may name a question that was\n * not asked. Fails with the first issue, in question order (then unexpected answers); answers that\n * are not an object fail as the first question's `malformed_answer`.\n */\nexport const decodeClassifierAnswers = (\n questions: ClassifierQuestionsInput,\n raw: unknown\n): Result.Result<Record<string, ClassifierAnswer>, ClassificationAnswerIssue> => {\n const questionIds = Object.keys(questions)\n\n if (!isFieldObject(raw)) {\n return Result.fail({ reason: 'malformed_answer', questionId: questionIds[0] ?? '' })\n }\n\n const entries: Array<readonly [string, ClassifierAnswer]> = []\n\n for (const [questionId, question] of Object.entries(questions)) {\n if (!Object.hasOwn(raw, questionId)) {\n return Result.fail({ reason: 'missing_answer', questionId })\n }\n\n const answer = decodeClassifierAnswer(question, ownField(raw, questionId))\n\n if (Result.isFailure(answer)) return Result.fail({ reason: answer.failure, questionId })\n\n entries.push([questionId, answer.success])\n }\n\n // Own data properties: question ids such as `__proto__` stay answers, not prototypes.\n const answers: Record<string, ClassifierAnswer> = Object.fromEntries(entries)\n\n for (const questionId of Object.keys(raw)) {\n if (!Object.hasOwn(questions, questionId)) {\n return Result.fail({ reason: 'unexpected_answer', questionId })\n }\n }\n\n return Result.succeed(answers)\n}\n\n/** The first way `answers` leaves `questions`, or undefined when every answer fits its question. */\nexport const classificationAnswersIssue = (\n questions: ClassifierQuestionsInput,\n answers: { readonly [questionId: string]: ClassifierAnswer }\n): ClassificationAnswerIssue | undefined => {\n const decoded = decodeClassifierAnswers(questions, answers)\n\n return Result.isFailure(decoded) ? decoded.failure : undefined\n}\n\n/** Narrow a result to the answer types its questions infer, after checking every answer. */\nexport const isClassificationResultFor = <const Q extends ClassifierQuestionsInput>(\n questions: Q,\n result: ClassificationResult\n): result is ClassificationResultFor<Q> =>\n classificationAnswersIssue(questions, result.answers) === undefined\n\n/**\n * Validate a request against the classification contract before anything is sent. Fails with\n * `ClassificationRequestInvalid` (for example a choice with more than 255 options, or a score with\n * more than 10 levels).\n */\nexport const decodeClassificationRequest = (\n request: unknown\n): Effect.Effect<ClassificationRequest, ClassificationRequestInvalid> =>\n Schema.decodeUnknownEffect(ClassificationRequest)(request).pipe(\n Effect.mapError(error =>\n ClassificationRequestInvalid.make({\n message: `Invalid classification request: ${error.message}`\n })\n )\n )\n\n/**\n * Classify with the `ClassifierModel` in context, typing each answer from its question: a choice\n * answer's `choice` is the union of that question's option keys. Every answer is checked against\n * its question; a provider that returns a mismatching answer fails with\n * `ClassificationResponseInvalid` (keeping usage).\n */\nexport const classify = <const Q extends ClassifierQuestionsInput>(\n request: ClassificationRequestFor<Q>\n): Effect.Effect<ClassificationResultFor<Q>, ClassificationError, ClassifierModel> =>\n Effect.gen(function* () {\n const model = yield* ClassifierModel\n const result = yield* model.classify(request)\n\n if (isClassificationResultFor(request.questions, result)) return result\n\n const issue = classificationAnswersIssue(request.questions, result.answers)\n const reason = issue?.reason ?? 'malformed_answer'\n\n return yield* Effect.fail(\n ClassificationResponseInvalid.make({\n message: `Classification answers do not fit their questions: ${reason}`,\n reason,\n questionId: issue?.questionId,\n usage: result.usage\n })\n )\n })\n"],"mappings":";;;;;;;;;AAuBA,IAAa,kBAAb,cAAqC,QAAQ,QAO3C,EAAE,gDAAgD,EAAE,CAAC;AAiCvD,MAAM,iBAAiB,UACrB,UAAU,SAAS,KAAK,KAAK,OAAO,SAAS,KAAK,KAAK,SAAS,KAAK,SAAS;AAEhF,MAAM,iBAAiB,UACrB,UAAU,SAAS,KAAK,KAAK,CAAC,MAAM,QAAQ,KAAK;;AAGnD,MAAM,YAAY,OAAe,QAC/B,OAAO,OAAO,OAAO,GAAG,KAAK,UAAU,YAAY,OAAO,GAAG,IAAI,MAAM,OAAO,KAAA;AAEhF,MAAM,uBACJ,UAC4E;CAC5E,IAAI,CAAC,cAAc,KAAK,GAAG,OAAO,OAAO,KAAK,qBAAqB;CAEnE,MAAM,UAA4C,CAAC;CAEnD,KAAK,MAAM,OAAO,OAAO,KAAK,KAAK,GAAG;EACpC,MAAM,cAAc,SAAS,OAAO,GAAG;EAEvC,IAAI,CAAC,cAAc,WAAW,GAAG,OAAO,OAAO,KAAK,qBAAqB;EAEzE,QAAQ,KAAK,CAAC,KAAK,WAAW,CAAC;CACjC;CAGA,OAAO,OAAO,QAAQ,OAAO,YAAY,OAAO,CAAC;AACnD;AAIA,MAAM,oBACJ,KACA,WACgD;CAChD,IAAI,CAAC,OAAO,OAAO,KAAK,YAAY,GAAG,OAAO,KAAA;CAE9C,MAAM,aAAa,SAAS,KAAK,YAAY;CAE7C,IAAI,CAAC,cAAc,UAAU,GAAG,OAAO;CAEvC,OAAO,aAAa;AAGtB;;;;;;;AAQA,MAAa,0BACX,UACA,QACqE;CACrE,IAAI,CAAC,cAAc,GAAG,GAAG,OAAO,OAAO,KAAK,kBAAkB;CAE9D,IAAI,SAAS,KAAK,MAAM,MAAM,SAAS,MAAM,OAAO,OAAO,KAAK,eAAe;CAE/E,IAAI,SAAS,SAAS,WAAW;EAC/B,MAAM,cAAc,SAAS,KAAK,aAAa;EAE/C,OAAO,cAAc,WAAW,IAC5B,OAAO,QAAQ;GAAE,MAAM;GAAW;EAAY,CAAC,IAC/C,OAAO,KAAK,qBAAqB;CACvC;CAEA,MAAM,gBAAgB,oBAAoB,SAAS,KAAK,eAAe,CAAC;CAExE,IAAI,OAAO,UAAU,aAAa,GAAG,OAAO,OAAO,KAAK,cAAc,OAAO;CAE7E,IAAI,SAAS,SAAS,UAAU;EAC9B,MAAM,SAAS,SAAS,KAAK,QAAQ;EAErC,IAAI,CAAC,UAAU,SAAS,MAAM,KAAK,CAAC,OAAO,OAAO,SAAS,UAAU,MAAM,GACzE,OAAO,OAAO,KAAK,gBAAgB;EAGrC,MAAM,SAAmD;GACvD,MAAM;GACN;GACA,eAAe,cAAc;EAC/B;EAEA,MAAM,QAAQ,iBAAiB,KAAK,MAAM;EAE1C,OAAO,UAAU,KAAA,IAAY,OAAO,QAAQ,MAAM,IAAI,OAAO,KAAK,KAAK;CACzE;CAEA,MAAM,QAAQ,SAAS,KAAK,OAAO;CAEnC,IAAI,CAAC,UAAU,SAAS,KAAK,KAAK,CAAC,OAAO,SAAS,KAAK,GAAG,OAAO,OAAO,KAAK,eAAe;CAE7F,MAAM,SAAkD;EACtD,MAAM;EACN;EACA,eAAe,cAAc;CAC/B;CAEA,MAAM,QAAQ,iBAAiB,KAAK,MAAM;CAE1C,OAAO,UAAU,KAAA,IAAY,OAAO,QAAQ,MAAM,IAAI,OAAO,KAAK,KAAK;AACzE;;;;;;;AAQA,MAAa,2BACX,WACA,QAC+E;CAC/E,MAAM,cAAc,OAAO,KAAK,SAAS;CAEzC,IAAI,CAAC,cAAc,GAAG,GACpB,OAAO,OAAO,KAAK;EAAE,QAAQ;EAAoB,YAAY,YAAY,MAAM;CAAG,CAAC;CAGrF,MAAM,UAAsD,CAAC;CAE7D,KAAK,MAAM,CAAC,YAAY,aAAa,OAAO,QAAQ,SAAS,GAAG;EAC9D,IAAI,CAAC,OAAO,OAAO,KAAK,UAAU,GAChC,OAAO,OAAO,KAAK;GAAE,QAAQ;GAAkB;EAAW,CAAC;EAG7D,MAAM,SAAS,uBAAuB,UAAU,SAAS,KAAK,UAAU,CAAC;EAEzE,IAAI,OAAO,UAAU,MAAM,GAAG,OAAO,OAAO,KAAK;GAAE,QAAQ,OAAO;GAAS;EAAW,CAAC;EAEvF,QAAQ,KAAK,CAAC,YAAY,OAAO,OAAO,CAAC;CAC3C;CAGA,MAAM,UAA4C,OAAO,YAAY,OAAO;CAE5E,KAAK,MAAM,cAAc,OAAO,KAAK,GAAG,GACtC,IAAI,CAAC,OAAO,OAAO,WAAW,UAAU,GACtC,OAAO,OAAO,KAAK;EAAE,QAAQ;EAAqB;CAAW,CAAC;CAIlE,OAAO,OAAO,QAAQ,OAAO;AAC/B;;AAGA,MAAa,8BACX,WACA,YAC0C;CAC1C,MAAM,UAAU,wBAAwB,WAAW,OAAO;CAE1D,OAAO,OAAO,UAAU,OAAO,IAAI,QAAQ,UAAU,KAAA;AACvD;;AAGA,MAAa,6BACX,WACA,WAEA,2BAA2B,WAAW,OAAO,OAAO,MAAM,KAAA;;;;;;AAO5D,MAAa,+BACX,YAEAA,SAAO,oBAAoB,qBAAqB,EAAE,OAAO,EAAE,KACzD,OAAO,UAAS,UACd,6BAA6B,KAAK,EAChC,SAAS,mCAAmC,MAAM,UACpD,CAAC,CACH,CACF;;;;;;;AAQF,MAAa,YACX,YAEA,OAAO,IAAI,aAAa;CAEtB,MAAM,SAAS,QAAO,OADD,iBACO,SAAS,OAAO;CAE5C,IAAI,0BAA0B,QAAQ,WAAW,MAAM,GAAG,OAAO;CAEjE,MAAM,QAAQ,2BAA2B,QAAQ,WAAW,OAAO,OAAO;CAC1E,MAAM,SAAS,OAAO,UAAU;CAEhC,OAAO,OAAO,OAAO,KACnB,8BAA8B,KAAK;EACjC,SAAS,sDAAsD;EAC/D;EACA,YAAY,OAAO;EACnB,OAAO,OAAO;CAChB,CAAC,CACH;AACF,CAAC"}