@theoremjs/agents 0.0.0-stage → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (514) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +1264 -2
  3. package/esm/_dnt.polyfills.d.ts +66 -0
  4. package/esm/_dnt.polyfills.js +51 -0
  5. package/esm/mod.d.ts +65 -0
  6. package/esm/mod.js +42 -0
  7. package/esm/package.json +3 -0
  8. package/esm/src/cli/bin.d.ts +7 -0
  9. package/esm/src/cli/bin.js +9 -0
  10. package/esm/src/cli/commands/bench.d.ts +6 -0
  11. package/esm/src/cli/commands/bench.js +458 -0
  12. package/esm/src/cli/commands/egress-compile.d.ts +17 -0
  13. package/esm/src/cli/commands/egress-compile.js +25 -0
  14. package/esm/src/cli/commands/eval.d.ts +37 -0
  15. package/esm/src/cli/commands/eval.js +190 -0
  16. package/esm/src/cli/commands/fuzz-canary.d.ts +15 -0
  17. package/esm/src/cli/commands/fuzz-canary.js +202 -0
  18. package/esm/src/cli/commands/fuzz-guardrails.d.ts +2 -0
  19. package/esm/src/cli/commands/fuzz-guardrails.js +5 -0
  20. package/esm/src/cli/commands/profile.d.ts +2 -0
  21. package/esm/src/cli/commands/profile.js +80 -0
  22. package/esm/src/cli/commands/run.d.ts +13 -0
  23. package/esm/src/cli/commands/run.js +45 -0
  24. package/esm/src/cli/commands/test.d.ts +25 -0
  25. package/esm/src/cli/commands/test.js +143 -0
  26. package/esm/src/cli/event-log.d.ts +15 -0
  27. package/esm/src/cli/event-log.js +136 -0
  28. package/esm/src/cli/index.d.ts +10 -0
  29. package/esm/src/cli/index.js +267 -0
  30. package/esm/src/cli/matrix/fixtures.d.ts +10 -0
  31. package/esm/src/cli/matrix/fixtures.js +72 -0
  32. package/esm/src/cli/matrix/synthesizer.d.ts +18 -0
  33. package/esm/src/cli/matrix/synthesizer.js +103 -0
  34. package/esm/src/evals/attachments.d.ts +4 -0
  35. package/esm/src/evals/attachments.js +53 -0
  36. package/esm/src/evals/breakdown.d.ts +28 -0
  37. package/esm/src/evals/breakdown.js +68 -0
  38. package/esm/src/evals/graders/answer.d.ts +13 -0
  39. package/esm/src/evals/graders/answer.js +133 -0
  40. package/esm/src/evals/graders/code.d.ts +64 -0
  41. package/esm/src/evals/graders/code.js +205 -0
  42. package/esm/src/evals/graders/judge.d.ts +20 -0
  43. package/esm/src/evals/graders/judge.js +365 -0
  44. package/esm/src/evals/graders/latency.d.ts +5 -0
  45. package/esm/src/evals/graders/latency.js +81 -0
  46. package/esm/src/evals/graders/live.d.ts +11 -0
  47. package/esm/src/evals/graders/live.js +40 -0
  48. package/esm/src/evals/graders/media.d.ts +18 -0
  49. package/esm/src/evals/graders/media.js +92 -0
  50. package/esm/src/evals/graders/shared.d.ts +11 -0
  51. package/esm/src/evals/graders/shared.js +62 -0
  52. package/esm/src/evals/graders/transcript.d.ts +17 -0
  53. package/esm/src/evals/graders/transcript.js +200 -0
  54. package/esm/src/evals/mod.d.ts +42 -0
  55. package/esm/src/evals/mod.js +30 -0
  56. package/esm/src/evals/record.d.ts +35 -0
  57. package/esm/src/evals/record.js +105 -0
  58. package/esm/src/evals/rubrics/catalog.d.ts +148 -0
  59. package/esm/src/evals/rubrics/catalog.js +846 -0
  60. package/esm/src/evals/rubrics/mod.d.ts +24 -0
  61. package/esm/src/evals/rubrics/mod.js +55 -0
  62. package/esm/src/evals/rubrics/mustache.d.ts +23 -0
  63. package/esm/src/evals/rubrics/mustache.js +154 -0
  64. package/esm/src/evals/rubrics/types.d.ts +54 -0
  65. package/esm/src/evals/rubrics/types.js +74 -0
  66. package/esm/src/evals/run.d.ts +118 -0
  67. package/esm/src/evals/run.js +452 -0
  68. package/esm/src/evals/suite.d.ts +19 -0
  69. package/esm/src/evals/suite.js +92 -0
  70. package/esm/src/evals/summary.d.ts +32 -0
  71. package/esm/src/evals/summary.js +30 -0
  72. package/esm/src/evals/trial.d.ts +27 -0
  73. package/esm/src/evals/trial.js +158 -0
  74. package/esm/src/evals/types.d.ts +260 -0
  75. package/esm/src/evals/types.js +126 -0
  76. package/esm/src/evals/verdict.d.ts +18 -0
  77. package/esm/src/evals/verdict.js +45 -0
  78. package/esm/src/guardrails/canary-gate.d.ts +21 -0
  79. package/esm/src/guardrails/canary-gate.js +40 -0
  80. package/esm/src/guardrails/canary.d.ts +112 -0
  81. package/esm/src/guardrails/canary.js +901 -0
  82. package/esm/src/guardrails/compile-egress.d.ts +11 -0
  83. package/esm/src/guardrails/compile-egress.js +11 -0
  84. package/esm/src/guardrails/corpus/canary-egress-attacks.d.ts +22 -0
  85. package/esm/src/guardrails/corpus/canary-egress-attacks.js +303 -0
  86. package/esm/src/guardrails/corpus/fuzz-inbound.d.ts +5 -0
  87. package/esm/src/guardrails/corpus/fuzz-inbound.js +202 -0
  88. package/esm/src/guardrails/corpus/inbound-payloads.d.ts +3 -0
  89. package/esm/src/guardrails/corpus/inbound-payloads.js +118 -0
  90. package/esm/src/guardrails/corpus/live-attacks.d.ts +13 -0
  91. package/esm/src/guardrails/corpus/live-attacks.js +224 -0
  92. package/esm/src/guardrails/corpus/mod.d.ts +7 -0
  93. package/esm/src/guardrails/corpus/mod.js +4 -0
  94. package/esm/src/guardrails/corpus/secrets.d.ts +12 -0
  95. package/esm/src/guardrails/corpus/secrets.js +16 -0
  96. package/esm/src/guardrails/corpus/strings.d.ts +23 -0
  97. package/esm/src/guardrails/corpus/strings.js +29 -0
  98. package/esm/src/guardrails/corpus/types.d.ts +32 -0
  99. package/esm/src/guardrails/corpus/types.js +1 -0
  100. package/esm/src/guardrails/egress-automata.d.ts +14 -0
  101. package/esm/src/guardrails/egress-automata.js +6059 -0
  102. package/esm/src/guardrails/egress-compiler.d.ts +33 -0
  103. package/esm/src/guardrails/egress-compiler.js +237 -0
  104. package/esm/src/guardrails/egress-patterns.d.ts +24 -0
  105. package/esm/src/guardrails/egress-patterns.js +32 -0
  106. package/esm/src/guardrails/egress-policy.d.ts +27 -0
  107. package/esm/src/guardrails/egress-policy.js +76 -0
  108. package/esm/src/guardrails/egress-rules.d.ts +54 -0
  109. package/esm/src/guardrails/egress-rules.js +49 -0
  110. package/esm/src/guardrails/egress-stream.d.ts +105 -0
  111. package/esm/src/guardrails/egress-stream.js +645 -0
  112. package/esm/src/guardrails/egress-urls.d.ts +83 -0
  113. package/esm/src/guardrails/egress-urls.js +917 -0
  114. package/esm/src/guardrails/egress.d.ts +106 -0
  115. package/esm/src/guardrails/egress.js +374 -0
  116. package/esm/src/guardrails/error.d.ts +26 -0
  117. package/esm/src/guardrails/error.js +91 -0
  118. package/esm/src/guardrails/event-schemas.d.ts +57 -0
  119. package/esm/src/guardrails/event-schemas.js +41 -0
  120. package/esm/src/guardrails/events.d.ts +9 -0
  121. package/esm/src/guardrails/events.js +42 -0
  122. package/esm/src/guardrails/hits.d.ts +8 -0
  123. package/esm/src/guardrails/hits.js +19 -0
  124. package/esm/src/guardrails/injection-patterns.d.ts +15 -0
  125. package/esm/src/guardrails/injection-patterns.js +94 -0
  126. package/esm/src/guardrails/injection.d.ts +14 -0
  127. package/esm/src/guardrails/injection.js +237 -0
  128. package/esm/src/guardrails/lexicon.d.ts +30 -0
  129. package/esm/src/guardrails/lexicon.js +478 -0
  130. package/esm/src/guardrails/live-outbound-gate.d.ts +54 -0
  131. package/esm/src/guardrails/live-outbound-gate.js +305 -0
  132. package/esm/src/guardrails/mod.d.ts +46 -0
  133. package/esm/src/guardrails/mod.js +29 -0
  134. package/esm/src/guardrails/network.d.ts +42 -0
  135. package/esm/src/guardrails/network.js +328 -0
  136. package/esm/src/guardrails/normalize.d.ts +6 -0
  137. package/esm/src/guardrails/normalize.js +132 -0
  138. package/esm/src/guardrails/policy.d.ts +19 -0
  139. package/esm/src/guardrails/policy.js +50 -0
  140. package/esm/src/guardrails/progressive-yield.d.ts +69 -0
  141. package/esm/src/guardrails/progressive-yield.js +237 -0
  142. package/esm/src/guardrails/prompt-echo.d.ts +38 -0
  143. package/esm/src/guardrails/prompt-echo.js +225 -0
  144. package/esm/src/guardrails/quota.d.ts +20 -0
  145. package/esm/src/guardrails/quota.js +80 -0
  146. package/esm/src/guardrails/rules.d.ts +56 -0
  147. package/esm/src/guardrails/rules.js +54 -0
  148. package/esm/src/guardrails/sanitize.d.ts +23 -0
  149. package/esm/src/guardrails/sanitize.js +184 -0
  150. package/esm/src/guardrails/sensitive.d.ts +29 -0
  151. package/esm/src/guardrails/sensitive.js +113 -0
  152. package/esm/src/guardrails/serialize.d.ts +14 -0
  153. package/esm/src/guardrails/serialize.js +37 -0
  154. package/esm/src/guardrails/testing.d.ts +9 -0
  155. package/esm/src/guardrails/testing.js +8 -0
  156. package/esm/src/guardrails/theorem-error.d.ts +18 -0
  157. package/esm/src/guardrails/theorem-error.js +53 -0
  158. package/esm/src/guardrails/thought-guard.d.ts +55 -0
  159. package/esm/src/guardrails/thought-guard.js +464 -0
  160. package/esm/src/guardrails/tool-directives.d.ts +19 -0
  161. package/esm/src/guardrails/tool-directives.js +109 -0
  162. package/esm/src/guardrails/tool-result.d.ts +61 -0
  163. package/esm/src/guardrails/tool-result.js +248 -0
  164. package/esm/src/guardrails/types.d.ts +242 -0
  165. package/esm/src/guardrails/types.js +54 -0
  166. package/esm/src/host/client-turn.d.ts +9 -0
  167. package/esm/src/host/client-turn.js +38 -0
  168. package/esm/src/host/mint-trace.d.ts +28 -0
  169. package/esm/src/host/mint-trace.js +59 -0
  170. package/esm/src/host/mod.d.ts +13 -0
  171. package/esm/src/host/mod.js +11 -0
  172. package/esm/src/host/readStreamingJsonStringField.d.ts +2 -0
  173. package/esm/src/host/readStreamingJsonStringField.js +68 -0
  174. package/esm/src/host/reply.d.ts +7 -0
  175. package/esm/src/host/reply.js +35 -0
  176. package/esm/src/interface/blocks.d.ts +8 -0
  177. package/esm/src/interface/blocks.js +213 -0
  178. package/esm/src/interface/composer-actions.d.ts +20 -0
  179. package/esm/src/interface/composer-actions.js +31 -0
  180. package/esm/src/interface/draft.d.ts +14 -0
  181. package/esm/src/interface/draft.js +28 -0
  182. package/esm/src/interface/from-profile.d.ts +12 -0
  183. package/esm/src/interface/from-profile.js +144 -0
  184. package/esm/src/interface/history.d.ts +40 -0
  185. package/esm/src/interface/history.js +269 -0
  186. package/esm/src/interface/inputs.d.ts +10 -0
  187. package/esm/src/interface/inputs.js +64 -0
  188. package/esm/src/interface/mod.d.ts +31 -0
  189. package/esm/src/interface/mod.js +21 -0
  190. package/esm/src/interface/models.d.ts +19 -0
  191. package/esm/src/interface/models.js +45 -0
  192. package/esm/src/interface/pending.d.ts +48 -0
  193. package/esm/src/interface/pending.js +146 -0
  194. package/esm/src/interface/profile-interface.d.ts +4 -0
  195. package/esm/src/interface/profile-interface.js +223 -0
  196. package/esm/src/interface/session.d.ts +64 -0
  197. package/esm/src/interface/session.js +121 -0
  198. package/esm/src/interface/tool-calls.d.ts +20 -0
  199. package/esm/src/interface/tool-calls.js +73 -0
  200. package/esm/src/interface/tool-invoke.d.ts +4 -0
  201. package/esm/src/interface/tool-invoke.js +20 -0
  202. package/esm/src/interface/tool-media.d.ts +9 -0
  203. package/esm/src/interface/tool-media.js +112 -0
  204. package/esm/src/interface/types.d.ts +213 -0
  205. package/esm/src/interface/types.js +4 -0
  206. package/esm/src/kernel/auth/credential-source.d.ts +23 -0
  207. package/esm/src/kernel/auth/credential-source.js +11 -0
  208. package/esm/src/kernel/auth/crypto.d.ts +51 -0
  209. package/esm/src/kernel/auth/crypto.js +161 -0
  210. package/esm/src/kernel/auth/mod.d.ts +5 -0
  211. package/esm/src/kernel/auth/mod.js +5 -0
  212. package/esm/src/kernel/auth/oauth.d.ts +17 -0
  213. package/esm/src/kernel/auth/oauth.js +438 -0
  214. package/esm/src/kernel/auth/scope-refusal.d.ts +9 -0
  215. package/esm/src/kernel/auth/scope-refusal.js +8 -0
  216. package/esm/src/kernel/auth/typed-secret.d.ts +13 -0
  217. package/esm/src/kernel/auth/typed-secret.js +23 -0
  218. package/esm/src/kernel/auth/types.d.ts +139 -0
  219. package/esm/src/kernel/auth/types.js +1 -0
  220. package/esm/src/kernel/default-scope.d.ts +34 -0
  221. package/esm/src/kernel/default-scope.js +72 -0
  222. package/esm/src/kernel/engine/compaction.d.ts +70 -0
  223. package/esm/src/kernel/engine/compaction.js +202 -0
  224. package/esm/src/kernel/engine/decision.d.ts +41 -0
  225. package/esm/src/kernel/engine/decision.js +412 -0
  226. package/esm/src/kernel/engine/hash.d.ts +6 -0
  227. package/esm/src/kernel/engine/hash.js +22 -0
  228. package/esm/src/kernel/engine/live-inbound.d.ts +9 -0
  229. package/esm/src/kernel/engine/live-inbound.js +19 -0
  230. package/esm/src/kernel/engine/live-ingress.d.ts +9 -0
  231. package/esm/src/kernel/engine/live-ingress.js +37 -0
  232. package/esm/src/kernel/engine/media-probe/audio.d.ts +7 -0
  233. package/esm/src/kernel/engine/media-probe/audio.js +342 -0
  234. package/esm/src/kernel/engine/media-probe/bytes.d.ts +6 -0
  235. package/esm/src/kernel/engine/media-probe/bytes.js +26 -0
  236. package/esm/src/kernel/engine/media-probe/image.d.ts +5 -0
  237. package/esm/src/kernel/engine/media-probe/image.js +171 -0
  238. package/esm/src/kernel/engine/media-probe/iso-bmff.d.ts +19 -0
  239. package/esm/src/kernel/engine/media-probe/iso-bmff.js +48 -0
  240. package/esm/src/kernel/engine/media-probe/matroska.d.ts +35 -0
  241. package/esm/src/kernel/engine/media-probe/matroska.js +226 -0
  242. package/esm/src/kernel/engine/media-probe/mp4.d.ts +22 -0
  243. package/esm/src/kernel/engine/media-probe/mp4.js +279 -0
  244. package/esm/src/kernel/engine/media-probe/opus.d.ts +4 -0
  245. package/esm/src/kernel/engine/media-probe/opus.js +23 -0
  246. package/esm/src/kernel/engine/media-probe/pdf.d.ts +5 -0
  247. package/esm/src/kernel/engine/media-probe/pdf.js +117 -0
  248. package/esm/src/kernel/engine/media-probe/video.d.ts +15 -0
  249. package/esm/src/kernel/engine/media-probe/video.js +49 -0
  250. package/esm/src/kernel/engine/record.d.ts +3 -0
  251. package/esm/src/kernel/engine/record.js +11 -0
  252. package/esm/src/kernel/engine/repair.d.ts +7 -0
  253. package/esm/src/kernel/engine/repair.js +36 -0
  254. package/esm/src/kernel/engine/runner/gates.d.ts +5 -0
  255. package/esm/src/kernel/engine/runner/gates.js +322 -0
  256. package/esm/src/kernel/engine/runner/mod.d.ts +15 -0
  257. package/esm/src/kernel/engine/runner/mod.js +574 -0
  258. package/esm/src/kernel/engine/runner/schema-validation.d.ts +14 -0
  259. package/esm/src/kernel/engine/runner/schema-validation.js +105 -0
  260. package/esm/src/kernel/engine/runner/stages.d.ts +28 -0
  261. package/esm/src/kernel/engine/runner/stages.js +48 -0
  262. package/esm/src/kernel/engine/runner/state.d.ts +76 -0
  263. package/esm/src/kernel/engine/runner/state.js +40 -0
  264. package/esm/src/kernel/engine/runner/steps.d.ts +14 -0
  265. package/esm/src/kernel/engine/runner/steps.js +360 -0
  266. package/esm/src/kernel/engine/runner/stream.d.ts +40 -0
  267. package/esm/src/kernel/engine/runner/stream.js +225 -0
  268. package/esm/src/kernel/engine/runner/usage.d.ts +45 -0
  269. package/esm/src/kernel/engine/runner/usage.js +150 -0
  270. package/esm/src/kernel/engine/session/mod.d.ts +31 -0
  271. package/esm/src/kernel/engine/session/mod.js +951 -0
  272. package/esm/src/kernel/engine/session/session-trace.d.ts +115 -0
  273. package/esm/src/kernel/engine/session/session-trace.js +489 -0
  274. package/esm/src/kernel/engine/token-estimate.d.ts +77 -0
  275. package/esm/src/kernel/engine/token-estimate.js +218 -0
  276. package/esm/src/kernel/engine/tool-trace.d.ts +58 -0
  277. package/esm/src/kernel/engine/tool-trace.js +131 -0
  278. package/esm/src/kernel/engine/tree.d.ts +2 -0
  279. package/esm/src/kernel/engine/tree.js +17 -0
  280. package/esm/src/kernel/engine/turn-trace.d.ts +118 -0
  281. package/esm/src/kernel/engine/turn-trace.js +863 -0
  282. package/esm/src/kernel/engine/usage.d.ts +30 -0
  283. package/esm/src/kernel/engine/usage.js +134 -0
  284. package/esm/src/kernel/interaction-parts.d.ts +10 -0
  285. package/esm/src/kernel/interaction-parts.js +22 -0
  286. package/esm/src/kernel/mod.d.ts +47 -0
  287. package/esm/src/kernel/mod.js +30 -0
  288. package/esm/src/kernel/profile-graph.d.ts +140 -0
  289. package/esm/src/kernel/profile-graph.js +151 -0
  290. package/esm/src/kernel/profile-presence.d.ts +9 -0
  291. package/esm/src/kernel/profile-presence.js +143 -0
  292. package/esm/src/kernel/profile-scope.d.ts +36 -0
  293. package/esm/src/kernel/profile-scope.js +262 -0
  294. package/esm/src/kernel/registry/attachments.d.ts +35 -0
  295. package/esm/src/kernel/registry/attachments.js +211 -0
  296. package/esm/src/kernel/registry/catalog.d.ts +19 -0
  297. package/esm/src/kernel/registry/catalog.js +78 -0
  298. package/esm/src/kernel/registry/ingress.d.ts +8 -0
  299. package/esm/src/kernel/registry/ingress.js +134 -0
  300. package/esm/src/kernel/registry/kernel-registry.d.ts +12 -0
  301. package/esm/src/kernel/registry/kernel-registry.js +8 -0
  302. package/esm/src/kernel/registry/profile-outputs.d.ts +3 -0
  303. package/esm/src/kernel/registry/profile-outputs.js +7 -0
  304. package/esm/src/kernel/registry/profiles.d.ts +92 -0
  305. package/esm/src/kernel/registry/profiles.js +698 -0
  306. package/esm/src/kernel/registry/provider-request.d.ts +6 -0
  307. package/esm/src/kernel/registry/provider-request.js +42 -0
  308. package/esm/src/kernel/registry/resolve.d.ts +14 -0
  309. package/esm/src/kernel/registry/resolve.js +237 -0
  310. package/esm/src/kernel/registry/schemas.d.ts +9 -0
  311. package/esm/src/kernel/registry/schemas.js +25 -0
  312. package/esm/src/kernel/registry/sole-model.d.ts +2 -0
  313. package/esm/src/kernel/registry/sole-model.js +4 -0
  314. package/esm/src/kernel/registry/system-prompt.d.ts +8 -0
  315. package/esm/src/kernel/registry/system-prompt.js +33 -0
  316. package/esm/src/kernel/registry/system-role.d.ts +3 -0
  317. package/esm/src/kernel/registry/system-role.js +9 -0
  318. package/esm/src/kernel/registry/vault.d.ts +13 -0
  319. package/esm/src/kernel/registry/vault.js +14 -0
  320. package/esm/src/kernel/schema.d.ts +172 -0
  321. package/esm/src/kernel/schema.js +653 -0
  322. package/esm/src/kernel/scope.d.ts +22 -0
  323. package/esm/src/kernel/scope.js +25 -0
  324. package/esm/src/kernel/stages.d.ts +141 -0
  325. package/esm/src/kernel/stages.js +388 -0
  326. package/esm/src/kernel/stop.d.ts +93 -0
  327. package/esm/src/kernel/stop.js +125 -0
  328. package/esm/src/kernel/system-parts.d.ts +26 -0
  329. package/esm/src/kernel/system-parts.js +98 -0
  330. package/esm/src/kernel/tools/activity-label.d.ts +16 -0
  331. package/esm/src/kernel/tools/activity-label.js +209 -0
  332. package/esm/src/kernel/tools/events.d.ts +51 -0
  333. package/esm/src/kernel/tools/events.js +149 -0
  334. package/esm/src/kernel/tools/execute.d.ts +64 -0
  335. package/esm/src/kernel/tools/execute.js +801 -0
  336. package/esm/src/kernel/tools/gate-answer.d.ts +50 -0
  337. package/esm/src/kernel/tools/gate-answer.js +54 -0
  338. package/esm/src/kernel/tools/harness.d.ts +16 -0
  339. package/esm/src/kernel/tools/harness.js +42 -0
  340. package/esm/src/kernel/tools/invoke.d.ts +10 -0
  341. package/esm/src/kernel/tools/invoke.js +129 -0
  342. package/esm/src/kernel/tools/mcp-sessions.d.ts +20 -0
  343. package/esm/src/kernel/tools/mcp-sessions.js +64 -0
  344. package/esm/src/kernel/tools/mod.d.ts +9 -0
  345. package/esm/src/kernel/tools/mod.js +6 -0
  346. package/esm/src/kernel/tools/model-text.d.ts +11 -0
  347. package/esm/src/kernel/tools/model-text.js +25 -0
  348. package/esm/src/kernel/tools/permission.d.ts +6 -0
  349. package/esm/src/kernel/tools/permission.js +38 -0
  350. package/esm/src/kernel/tools/project.d.ts +8 -0
  351. package/esm/src/kernel/tools/project.js +25 -0
  352. package/esm/src/kernel/tools/registry.d.ts +20 -0
  353. package/esm/src/kernel/tools/registry.js +84 -0
  354. package/esm/src/kernel/tools/remote.d.ts +110 -0
  355. package/esm/src/kernel/tools/remote.js +998 -0
  356. package/esm/src/kernel/tools/resolve.d.ts +28 -0
  357. package/esm/src/kernel/tools/resolve.js +259 -0
  358. package/esm/src/kernel/tools/schema.d.ts +10 -0
  359. package/esm/src/kernel/tools/schema.js +174 -0
  360. package/esm/src/kernel/tools/signed-in-fetch.d.ts +18 -0
  361. package/esm/src/kernel/tools/signed-in-fetch.js +45 -0
  362. package/esm/src/kernel/tools/stage-run.d.ts +93 -0
  363. package/esm/src/kernel/tools/stage-run.js +140 -0
  364. package/esm/src/kernel/tools/types.d.ts +287 -0
  365. package/esm/src/kernel/tools/types.js +1 -0
  366. package/esm/src/kernel/turn-events.d.ts +599 -0
  367. package/esm/src/kernel/turn-events.js +425 -0
  368. package/esm/src/kernel/types.d.ts +884 -0
  369. package/esm/src/kernel/types.js +1 -0
  370. package/esm/src/kernel/util/base64.d.ts +2 -0
  371. package/esm/src/kernel/util/base64.js +13 -0
  372. package/esm/src/kernel/util/exact-type.d.ts +31 -0
  373. package/esm/src/kernel/util/exact-type.js +1 -0
  374. package/esm/src/kernel/util/find-last.d.ts +3 -0
  375. package/esm/src/kernel/util/find-last.js +9 -0
  376. package/esm/src/kernel/util/mime.d.ts +2 -0
  377. package/esm/src/kernel/util/mime.js +4 -0
  378. package/esm/src/kernel/util/record.d.ts +1 -0
  379. package/esm/src/kernel/util/record.js +3 -0
  380. package/esm/src/observability/destinations.d.ts +9 -0
  381. package/esm/src/observability/destinations.js +38 -0
  382. package/esm/src/observability/jsonl.d.ts +18 -0
  383. package/esm/src/observability/jsonl.js +117 -0
  384. package/esm/src/observability/mod.d.ts +22 -0
  385. package/esm/src/observability/mod.js +16 -0
  386. package/esm/src/observability/openinference.d.ts +11 -0
  387. package/esm/src/observability/openinference.js +205 -0
  388. package/esm/src/observability/otlp.d.ts +68 -0
  389. package/esm/src/observability/otlp.js +98 -0
  390. package/esm/src/observability/phoenix.d.ts +29 -0
  391. package/esm/src/observability/phoenix.js +71 -0
  392. package/esm/src/observability/policy.d.ts +14 -0
  393. package/esm/src/observability/policy.js +69 -0
  394. package/esm/src/observability/resolve-policy.d.ts +8 -0
  395. package/esm/src/observability/resolve-policy.js +58 -0
  396. package/esm/src/observability/spans.d.ts +16 -0
  397. package/esm/src/observability/spans.js +56 -0
  398. package/esm/src/observability/trace-catalog.d.ts +111 -0
  399. package/esm/src/observability/trace-catalog.js +865 -0
  400. package/esm/src/observability/trace-record.d.ts +23 -0
  401. package/esm/src/observability/trace-record.js +223 -0
  402. package/esm/src/observability/trace-schema.d.ts +54 -0
  403. package/esm/src/observability/trace-schema.js +59 -0
  404. package/esm/src/observability/trace-sink.d.ts +13 -0
  405. package/esm/src/observability/trace-sink.js +3 -0
  406. package/esm/src/observability/trace-span.d.ts +92 -0
  407. package/esm/src/observability/trace-span.js +199 -0
  408. package/esm/src/observability/trace.d.ts +11 -0
  409. package/esm/src/observability/trace.js +35 -0
  410. package/esm/src/observability/types.d.ts +85 -0
  411. package/esm/src/observability/types.js +3 -0
  412. package/esm/src/presets/google/speech-voices.d.ts +8 -0
  413. package/esm/src/presets/google/speech-voices.js +38 -0
  414. package/esm/src/presets/google-limits.d.ts +12 -0
  415. package/esm/src/presets/google-limits.js +18 -0
  416. package/esm/src/presets/google.d.ts +104 -0
  417. package/esm/src/presets/google.js +188 -0
  418. package/esm/src/presets/mod.d.ts +10 -0
  419. package/esm/src/presets/mod.js +9 -0
  420. package/esm/src/presets/openrouter.d.ts +13 -0
  421. package/esm/src/presets/openrouter.js +13 -0
  422. package/esm/src/presets/typesafe.d.ts +2 -0
  423. package/esm/src/presets/typesafe.js +2 -0
  424. package/esm/src/providers/create-provider.d.ts +21 -0
  425. package/esm/src/providers/create-provider.js +90 -0
  426. package/esm/src/providers/decision/usage.d.ts +3 -0
  427. package/esm/src/providers/decision/usage.js +25 -0
  428. package/esm/src/providers/google/api-error.d.ts +8 -0
  429. package/esm/src/providers/google/api-error.js +123 -0
  430. package/esm/src/providers/google/grounding.d.ts +5 -0
  431. package/esm/src/providers/google/grounding.js +226 -0
  432. package/esm/src/providers/google/interactions/framing.d.ts +15 -0
  433. package/esm/src/providers/google/interactions/framing.js +263 -0
  434. package/esm/src/providers/google/interactions/mod.d.ts +2 -0
  435. package/esm/src/providers/google/interactions/mod.js +2 -0
  436. package/esm/src/providers/google/interactions/steps.d.ts +12 -0
  437. package/esm/src/providers/google/interactions/steps.js +200 -0
  438. package/esm/src/providers/google/interactions/stream.d.ts +24 -0
  439. package/esm/src/providers/google/interactions/stream.js +297 -0
  440. package/esm/src/providers/google/keys.d.ts +20 -0
  441. package/esm/src/providers/google/keys.js +87 -0
  442. package/esm/src/providers/google/live/framing.d.ts +51 -0
  443. package/esm/src/providers/google/live/framing.js +597 -0
  444. package/esm/src/providers/google/live/mod.d.ts +7 -0
  445. package/esm/src/providers/google/live/mod.js +7 -0
  446. package/esm/src/providers/google/live/openapi-schema.d.ts +1 -0
  447. package/esm/src/providers/google/live/openapi-schema.js +42 -0
  448. package/esm/src/providers/google/live/session.d.ts +14 -0
  449. package/esm/src/providers/google/live/session.js +150 -0
  450. package/esm/src/providers/google/live/stream.d.ts +51 -0
  451. package/esm/src/providers/google/live/stream.js +263 -0
  452. package/esm/src/providers/google/thinking.d.ts +3 -0
  453. package/esm/src/providers/google/thinking.js +8 -0
  454. package/esm/src/providers/google/urls.d.ts +6 -0
  455. package/esm/src/providers/google/urls.js +6 -0
  456. package/esm/src/providers/google/usage.d.ts +7 -0
  457. package/esm/src/providers/google/usage.js +49 -0
  458. package/esm/src/providers/local/local.d.ts +12 -0
  459. package/esm/src/providers/local/local.js +186 -0
  460. package/esm/src/providers/local/mod.d.ts +8 -0
  461. package/esm/src/providers/local/mod.js +8 -0
  462. package/esm/src/providers/mod.d.ts +11 -0
  463. package/esm/src/providers/mod.js +7 -0
  464. package/esm/src/providers/openrouter/cache-control.d.ts +5 -0
  465. package/esm/src/providers/openrouter/cache-control.js +4 -0
  466. package/esm/src/providers/openrouter/chat.d.ts +64 -0
  467. package/esm/src/providers/openrouter/chat.js +490 -0
  468. package/esm/src/providers/openrouter/image.d.ts +24 -0
  469. package/esm/src/providers/openrouter/image.js +187 -0
  470. package/esm/src/providers/openrouter/openai/compat.d.ts +19 -0
  471. package/esm/src/providers/openrouter/openai/compat.js +162 -0
  472. package/esm/src/providers/openrouter/openai/image-payload.d.ts +9 -0
  473. package/esm/src/providers/openrouter/openai/image-payload.js +115 -0
  474. package/esm/src/providers/openrouter/openai/sdk-messages.d.ts +10 -0
  475. package/esm/src/providers/openrouter/openai/sdk-messages.js +99 -0
  476. package/esm/src/providers/openrouter/openai/usage.d.ts +8 -0
  477. package/esm/src/providers/openrouter/openai/usage.js +56 -0
  478. package/esm/src/providers/openrouter/resolve-api-key.d.ts +3 -0
  479. package/esm/src/providers/openrouter/resolve-api-key.js +8 -0
  480. package/esm/src/providers/openrouter/speech.d.ts +18 -0
  481. package/esm/src/providers/openrouter/speech.js +109 -0
  482. package/esm/src/providers/probe.d.ts +5 -0
  483. package/esm/src/providers/probe.js +15 -0
  484. package/esm/src/providers/shared/builtin-wire.d.ts +4 -0
  485. package/esm/src/providers/shared/builtin-wire.js +9 -0
  486. package/esm/src/providers/shared/pcm.d.ts +14 -0
  487. package/esm/src/providers/shared/pcm.js +78 -0
  488. package/esm/src/providers/shared/response-identity.d.ts +11 -0
  489. package/esm/src/providers/shared/response-identity.js +12 -0
  490. package/esm/src/providers/shared/sse.d.ts +10 -0
  491. package/esm/src/providers/shared/sse.js +79 -0
  492. package/esm/src/providers/shared/structured-output.d.ts +4 -0
  493. package/esm/src/providers/shared/structured-output.js +11 -0
  494. package/esm/src/providers/shared/tool-args.d.ts +25 -0
  495. package/esm/src/providers/shared/tool-args.js +84 -0
  496. package/esm/src/providers/shared/upstream-tap.d.ts +8 -0
  497. package/esm/src/providers/shared/upstream-tap.js +85 -0
  498. package/esm/src/providers/shared/upstream-tape.d.ts +6 -0
  499. package/esm/src/providers/shared/upstream-tape.js +88 -0
  500. package/esm/src/providers/shared/vault.d.ts +13 -0
  501. package/esm/src/providers/shared/vault.js +41 -0
  502. package/esm/src/providers/types.d.ts +19 -0
  503. package/esm/src/providers/types.js +1 -0
  504. package/esm/src/surface/formats.d.ts +28 -0
  505. package/esm/src/surface/formats.js +139 -0
  506. package/esm/src/surface/mod.d.ts +14 -0
  507. package/esm/src/surface/mod.js +10 -0
  508. package/esm/src/surface/runtime.d.ts +40 -0
  509. package/esm/src/surface/runtime.js +439 -0
  510. package/esm/src/surface/tools.d.ts +15 -0
  511. package/esm/src/surface/tools.js +80 -0
  512. package/esm/src/surface/types.d.ts +104 -0
  513. package/esm/src/surface/types.js +4 -0
  514. package/package.json +108 -4
@@ -0,0 +1,103 @@
1
+ import { profileInputs } from '../../kernel/registry/catalog.js';
2
+ import { FIXTURE_PNG_BASE64, FIXTURE_WAV_BASE64, getFixtureForMime } from './fixtures.js';
3
+ export function synthesizeLiteCombo(profile) {
4
+ const model = profile.allowModelSelect && profile.models.fast ? 'fast' : undefined;
5
+ return {
6
+ profile: profile.id,
7
+ model,
8
+ input: {
9
+ text: `Ping test for profile ${profile.id}. Respond concisely with confirmation.`,
10
+ },
11
+ };
12
+ }
13
+ function resolveStressModel(profile) {
14
+ if (!profile.allowModelSelect) {
15
+ return undefined;
16
+ }
17
+ if (profile.models.smart) {
18
+ return 'smart';
19
+ }
20
+ const ids = Object.keys(profile.models);
21
+ return ids.length > 1 ? ids[ids.length - 1] : undefined;
22
+ }
23
+ function resolveStressAttachments(profile) {
24
+ const inputs = profileInputs(profile);
25
+ if (!inputs) {
26
+ return [];
27
+ }
28
+ const attachments = [];
29
+ const accept = inputs.attachments?.accept;
30
+ if (accept && accept.length > 0) {
31
+ const preferredMimes = ['image/png', 'application/pdf', 'text/plain'];
32
+ const chosenMime = preferredMimes.find((m) => accept.includes(m)) ?? accept[0];
33
+ const fixture = getFixtureForMime(chosenMime);
34
+ if (fixture) {
35
+ attachments.push(fixture);
36
+ }
37
+ else {
38
+ attachments.push({ mimeType: 'image/png', data: FIXTURE_PNG_BASE64 });
39
+ }
40
+ }
41
+ return attachments;
42
+ }
43
+ function resolveStressVoice(profile) {
44
+ const inputs = profileInputs(profile);
45
+ if (!inputs) {
46
+ return [];
47
+ }
48
+ const voice = [];
49
+ if (inputs.voice?.accept && inputs.voice.accept.length > 0) {
50
+ voice.push({ mimeType: 'audio/wav', data: FIXTURE_WAV_BASE64 });
51
+ }
52
+ return voice;
53
+ }
54
+ export function synthesizeStressCombo(profile) {
55
+ const model = resolveStressModel(profile);
56
+ const attachments = resolveStressAttachments(profile);
57
+ const voice = resolveStressVoice(profile);
58
+ const promptText = `Execute comprehensive test turn for profile ${profile.id}. Validate all instructions and produce required outputs.`;
59
+ return {
60
+ profile: profile.id,
61
+ model,
62
+ input: {
63
+ text: promptText,
64
+ attachments: attachments.length > 0 ? attachments : undefined,
65
+ voice: voice.length > 0 ? voice : undefined,
66
+ },
67
+ };
68
+ }
69
+ export function synthesizeMatrixCombos(profile) {
70
+ return [
71
+ {
72
+ name: 'Lite (connectivity)',
73
+ req: synthesizeLiteCombo(profile),
74
+ },
75
+ {
76
+ name: 'Stress (all modalities + primary tools)',
77
+ req: synthesizeStressCombo(profile),
78
+ },
79
+ ];
80
+ }
81
+ function assertGroundingFlagsOnModel(profile, options) {
82
+ const modelId = options.mode && profile.models[options.mode] ? options.mode : profile.defaultModel;
83
+ const builtins = new Set(profile.models[modelId]?.builtInTools ?? []);
84
+ if (options.search === true && !builtins.has('googleSearch')) {
85
+ throw new Error(`--search requires googleSearch on models.${modelId}.builtInTools`);
86
+ }
87
+ if (options.map === true && !builtins.has('googleMaps')) {
88
+ throw new Error(`--map requires googleMaps on models.${modelId}.builtInTools`);
89
+ }
90
+ }
91
+ export function buildCustomTurnRequest(profile, options) {
92
+ if (options.lite) {
93
+ return synthesizeLiteCombo(profile);
94
+ }
95
+ const base = synthesizeStressCombo(profile);
96
+ if (options.mode) {
97
+ base.model = options.mode;
98
+ }
99
+ if (options.search !== undefined || options.map !== undefined) {
100
+ assertGroundingFlagsOnModel(profile, options);
101
+ }
102
+ return base;
103
+ }
@@ -0,0 +1,4 @@
1
+ import type { EvalAttachment, EvalCase } from './types.js';
2
+ declare function attachmentData(attachment: EvalAttachment): Promise<string>;
3
+ declare function pinCaseFiles(cases: EvalCase[], casesPath: string): Promise<EvalCase[]>;
4
+ export { attachmentData, pinCaseFiles };
@@ -0,0 +1,53 @@
1
+ // A file attachment is read when its trial runs, not when the suite loads, so thousands of photos are never held at once.
2
+ import { createHash } from 'node:crypto';
3
+ import { readFile } from 'node:fs/promises';
4
+ import { dirname, resolve } from 'node:path';
5
+ import { TheoremError } from '../guardrails/error.js';
6
+ async function hashedFile(path) {
7
+ let bytes;
8
+ try {
9
+ bytes = await readFile(path);
10
+ }
11
+ catch (error) {
12
+ throw new TheoremError('config', `attachment ${path} cannot be read: ${error instanceof Error ? error.message : String(error)}`);
13
+ }
14
+ return { bytes, sha256: createHash('sha256').update(bytes).digest('hex') };
15
+ }
16
+ async function fileBytes(attachment) {
17
+ const { bytes, sha256 } = await hashedFile(attachment.path);
18
+ if (sha256 !== attachment.sha256) {
19
+ throw new TheoremError('config', `attachment ${attachment.path} hashes to ${sha256}, not the ${attachment.sha256} its case pins`);
20
+ }
21
+ return bytes;
22
+ }
23
+ async function attachmentData(attachment) {
24
+ return 'data' in attachment ? attachment.data : (await fileBytes(attachment)).toString('base64');
25
+ }
26
+ async function pinCaseFiles(cases, casesPath) {
27
+ const pinned = [];
28
+ for (const evalCase of cases) {
29
+ const { input } = evalCase;
30
+ if (!('attachments' in input) || input.attachments === undefined) {
31
+ pinned.push(evalCase);
32
+ continue;
33
+ }
34
+ const attachments = [];
35
+ for (const attachment of input.attachments) {
36
+ if ('data' in attachment) {
37
+ attachments.push(attachment);
38
+ continue;
39
+ }
40
+ const path = resolve(dirname(casesPath), attachment.path);
41
+ try {
42
+ await fileBytes({ ...attachment, path });
43
+ }
44
+ catch (error) {
45
+ throw new TheoremError('config', `case ${evalCase.id}: ${error instanceof Error ? error.message : String(error)}`);
46
+ }
47
+ attachments.push({ ...attachment, path });
48
+ }
49
+ pinned.push({ ...evalCase, input: { ...input, attachments } });
50
+ }
51
+ return pinned;
52
+ }
53
+ export { attachmentData, pinCaseFiles };
@@ -0,0 +1,28 @@
1
+ import type { SuiteRun } from './run.js';
2
+ /** Nearest-rank percentiles, so each is a value some trial had. */
3
+ interface Spread {
4
+ median: number;
5
+ p90: number;
6
+ }
7
+ interface GroupSummary {
8
+ group: string;
9
+ cases: number;
10
+ casesPassed: number;
11
+ casesUndecided: number;
12
+ trials: number;
13
+ trialsPassed: number;
14
+ trialsErrored: number;
15
+ answers?: {
16
+ accepted: number;
17
+ partial: number;
18
+ wrong: number;
19
+ none: number;
20
+ };
21
+ stops: Record<string, number>;
22
+ durationMs?: Spread;
23
+ modelCalls?: Spread;
24
+ toolCalls?: Spread;
25
+ }
26
+ declare function groupSummaries(run: Pick<SuiteRun, 'trials' | 'verdicts'>): GroupSummary[];
27
+ export type { GroupSummary, Spread };
28
+ export { groupSummaries };
@@ -0,0 +1,68 @@
1
+ const MEDIAN = 0.5;
2
+ const P90 = 0.9;
3
+ function rank(sorted, quantile) {
4
+ return sorted[Math.max(0, Math.ceil(quantile * sorted.length) - 1)] ?? 0;
5
+ }
6
+ function spread(values) {
7
+ if (values.length === 0)
8
+ return undefined;
9
+ const sorted = values.toSorted((a, b) => a - b);
10
+ return { median: rank(sorted, MEDIAN), p90: rank(sorted, P90) };
11
+ }
12
+ function answerLabel(report) {
13
+ return report.results.find((result) => result.name === 'answer')?.score?.label;
14
+ }
15
+ function groupOf(group, verdicts, trials, gradesAnswers) {
16
+ const turns = trials.flatMap((report) => report.turn ?? []);
17
+ const of = (key) => spread(turns.map((turn) => turn[key]));
18
+ const labels = trials.map(answerLabel);
19
+ const count = (label) => labels.filter((each) => each === label).length;
20
+ const stops = {};
21
+ for (const turn of turns) {
22
+ const stop = turn.stop ?? 'unrecorded';
23
+ stops[stop] = (stops[stop] ?? 0) + 1;
24
+ }
25
+ const durationMs = of('durationMs');
26
+ const modelCalls = of('modelCalls');
27
+ const toolCalls = of('toolCalls');
28
+ return {
29
+ group,
30
+ cases: verdicts.length,
31
+ casesPassed: verdicts.filter((verdict) => verdict.passed).length,
32
+ casesUndecided: verdicts.filter((verdict) => !verdict.decided).length,
33
+ trials: trials.length,
34
+ trialsPassed: trials.filter((report) => report.outcome === 'passed').length,
35
+ trialsErrored: trials.filter((report) => report.outcome === 'errored').length,
36
+ ...(gradesAnswers
37
+ ? {
38
+ answers: {
39
+ accepted: count('accepted'),
40
+ partial: count('partial'),
41
+ wrong: count('wrong'),
42
+ none: count(undefined),
43
+ },
44
+ }
45
+ : {}),
46
+ stops,
47
+ ...(durationMs ? { durationMs } : {}),
48
+ ...(modelCalls ? { modelCalls } : {}),
49
+ ...(toolCalls ? { toolCalls } : {}),
50
+ };
51
+ }
52
+ function groupSummaries(run) {
53
+ const gradesAnswers = run.trials.some((report) => report.results.some((result) => result.name === 'answer'));
54
+ const tags = [...new Set(run.trials.flatMap((report) => report.case?.tags ?? []))].sort();
55
+ const tagged = (tag) => run.trials.filter((report) => report.case?.tags?.includes(tag) === true);
56
+ const verdictsOf = (trials) => {
57
+ const ids = new Set(trials.map((report) => report.case?.id));
58
+ return run.verdicts.filter((verdict) => ids.has(verdict.case));
59
+ };
60
+ return [
61
+ groupOf('all', run.verdicts, run.trials, gradesAnswers),
62
+ ...tags.map((tag) => {
63
+ const trials = tagged(tag);
64
+ return groupOf(tag, verdictsOf(trials), trials, gradesAnswers);
65
+ }),
66
+ ];
67
+ }
68
+ export { groupSummaries };
@@ -0,0 +1,13 @@
1
+ import type { EvalGrader } from '../types.js';
2
+ type AnswerSource = {
3
+ json: string;
4
+ } | {
5
+ tool: string;
6
+ arg: string;
7
+ };
8
+ type AnswerLabel = 'accepted' | 'partial' | 'wrong';
9
+ declare function answer(options?: {
10
+ from?: AnswerSource;
11
+ }): EvalGrader;
12
+ export type { AnswerLabel, AnswerSource };
13
+ export { answer };
@@ -0,0 +1,133 @@
1
+ import { isRecord } from '../../kernel/util/record.js';
2
+ import { codeGrader, deliveredJson, deliveredText, listOf } from './shared.js';
3
+ import { toolSteps } from './transcript.js';
4
+ function normalized(text) {
5
+ return text
6
+ .normalize('NFKD')
7
+ .replace(/\p{M}/gu, '')
8
+ .toLowerCase()
9
+ .replace(/[^\p{L}\p{N}]+/gu, ' ')
10
+ .trim();
11
+ }
12
+ /** A name said only inside a longer one of them is not said: `Calathea` in `Calathea orbifolia` is the species. */
13
+ function namedIn(text, names) {
14
+ const words = normalized(text).split(' ');
15
+ const spans = names.flatMap((name) => {
16
+ const key = normalized(name);
17
+ if (!key)
18
+ return [];
19
+ const parts = key.split(' ');
20
+ return words.flatMap((_, start) => parts.every((part, i) => words[start + i] === part)
21
+ ? [{ name, start, end: start + parts.length }]
22
+ : []);
23
+ });
24
+ const said = new Set(spans
25
+ .filter((span) => !spans.some((other) => other.start <= span.start &&
26
+ other.end >= span.end &&
27
+ other.end - other.start > span.end - span.start))
28
+ .map((span) => span.name));
29
+ return (among) => among.find((name) => said.has(name));
30
+ }
31
+ function at(value, path) {
32
+ let current = value;
33
+ for (const key of path.split('.')) {
34
+ if (!isRecord(current))
35
+ return undefined;
36
+ current = current[key];
37
+ }
38
+ return current;
39
+ }
40
+ function parsedArguments(text) {
41
+ try {
42
+ return JSON.parse(text);
43
+ }
44
+ catch {
45
+ return undefined;
46
+ }
47
+ }
48
+ function readAnswer(trial, source) {
49
+ if ('json' in source) {
50
+ const where = `JSON key ${source.json}`;
51
+ const value = at(deliveredJson(trial), source.json);
52
+ return typeof value === 'string' ? { value, where } : { missing: `no string at ${where}` };
53
+ }
54
+ const where = `${source.tool} argument ${source.arg}`;
55
+ const call = toolSteps(trial)
56
+ .filter((step) => step.name === source.tool)
57
+ .at(-1);
58
+ if (!call)
59
+ return { missing: `${source.tool} was not called` };
60
+ const value = at(parsedArguments(call.arguments), source.arg);
61
+ return typeof value === 'string' ? { value, where } : { missing: `no string at ${where}` };
62
+ }
63
+ function result(label, explanation) {
64
+ const passed = label === 'accepted';
65
+ return {
66
+ name: 'answer',
67
+ source: 'code',
68
+ score: { value: passed ? 1 : 0, label },
69
+ explanation,
70
+ passed,
71
+ };
72
+ }
73
+ /** A turn the provider failed before it answered: the agent never had its say, so the trial errors instead of counting as wrong. */
74
+ function unanswered(trial, why) {
75
+ if (trial.root.attributes['theorem.stop.kind'] !== 'provider_error')
76
+ return undefined;
77
+ const kind = trial.root.status.message ? ` (${trial.root.status.message})` : '';
78
+ return {
79
+ name: 'answer',
80
+ source: 'code',
81
+ errorType: 'provider_error',
82
+ explanation: `${why}; the turn stopped provider_error${kind} before it answered`,
83
+ };
84
+ }
85
+ function answer(options = {}) {
86
+ const { from } = options;
87
+ const identity = `answer:${from ? JSON.stringify(from) : 'reply'}`;
88
+ return codeGrader('answer', identity, true, (trial) => {
89
+ const expected = trial.case?.expect?.answer;
90
+ if (!expected)
91
+ return result('wrong', 'case has no expect.answer');
92
+ const accepted = expected.accepted;
93
+ const partial = expected.partial ?? [];
94
+ const rejected = expected.rejected ?? [];
95
+ if (from) {
96
+ const read = readAnswer(trial, from);
97
+ if ('missing' in read) {
98
+ return (unanswered(trial, read.missing) ??
99
+ result('wrong', `${read.missing}; accepted ${listOf(accepted)}`));
100
+ }
101
+ const said = normalized(read.value);
102
+ const quoted = JSON.stringify(read.value);
103
+ if (accepted.some((name) => normalized(name) === said)) {
104
+ return result('accepted', `answered ${quoted} (${read.where})`);
105
+ }
106
+ if (rejected.some((name) => normalized(name) === said)) {
107
+ return result('wrong', `answered ${quoted} (${read.where}), which the case rejects; accepted ${listOf(accepted)}`);
108
+ }
109
+ if (partial.some((name) => normalized(name) === said)) {
110
+ return result('partial', `answered ${quoted} (${read.where}); accepted ${listOf(accepted)}`);
111
+ }
112
+ return result('wrong', `answered ${quoted} (${read.where}); accepted ${listOf(accepted)}`);
113
+ }
114
+ const found = namedIn(deliveredText(trial, undefined), [...accepted, ...partial, ...rejected]);
115
+ const hit = found(accepted);
116
+ const miss = found(rejected);
117
+ if (hit && miss) {
118
+ return result('partial', `reply names ${JSON.stringify(hit)} and ${JSON.stringify(miss)}, which the case rejects`);
119
+ }
120
+ if (hit)
121
+ return result('accepted', `reply names ${JSON.stringify(hit)}`);
122
+ if (miss) {
123
+ return result('wrong', `reply names ${JSON.stringify(miss)}, which the case rejects; accepted ${listOf(accepted)}`);
124
+ }
125
+ const near = found(partial);
126
+ if (near) {
127
+ return result('partial', `reply names ${JSON.stringify(near)}; accepted ${listOf(accepted)}`);
128
+ }
129
+ return (unanswered(trial, 'the reply names no answer') ??
130
+ result('wrong', `reply names none of ${listOf(accepted)}`));
131
+ });
132
+ }
133
+ export { answer };
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Code graders: deterministic checks over a trial's trace. Each returns one
3
+ * pass/fail result with the reason in plain words. Outcome first: what was
4
+ * delivered and what it cost matter more than the path taken.
5
+ *
6
+ * @module
7
+ */
8
+ import type { EvalGrader, EvalResult, Trial } from '../types.js';
9
+ /** Graders over what the host received: the model's own text and JSON. */
10
+ interface DeliveredGraders {
11
+ /** The delivered text contains `text`. */
12
+ includes: (text: string) => EvalGrader;
13
+ /** The delivered text matches `pattern` (a JavaScript regular expression source). */
14
+ regex: (pattern: string, flags?: string) => EvalGrader;
15
+ /** The delivered text equals `text` exactly. */
16
+ equals: (text: string) => EvalGrader;
17
+ /**
18
+ * The delivered JSON validates against a JSON Schema object (required
19
+ * fields present, recursively). The structured part is read when the
20
+ * profile has one; otherwise the text is parsed.
21
+ */
22
+ jsonSchema: (schema: Record<string, unknown>) => EvalGrader;
23
+ /** Every field of the case's `expect.json` is present in the delivered JSON with the same value. */
24
+ json: () => EvalGrader;
25
+ }
26
+ declare const delivered: DeliveredGraders;
27
+ /**
28
+ * How the called tools are compared with the expected list:
29
+ * - `exact`: the same tools in the same order, nothing more;
30
+ * - `in_order`: the expected tools appear in that order, others may interleave;
31
+ * - `any_order`: the same tools, order ignored;
32
+ * - `subset`: every tool called is one that was expected (none unexpected; some may be missing).
33
+ */
34
+ type TrajectoryMode = 'exact' | 'in_order' | 'any_order' | 'subset';
35
+ /** The tools the agent called, in start order, against `expect` or the case's `expect.tools`. */
36
+ declare function toolTrajectory(options: {
37
+ expect?: string[];
38
+ mode: TrajectoryMode;
39
+ }): EvalGrader;
40
+ /** The turn stopped for one of these reasons (`theorem.stop.kind`). */
41
+ declare function stopKind(kind: string | string[]): EvalGrader;
42
+ /** A guardrail did (`fired: true`) or did not (`fired: false`) act on any span; `allow` does not count as acting. */
43
+ declare function guardrail(options: {
44
+ fired: boolean;
45
+ action?: 'redact' | 'flag' | 'block';
46
+ }): EvalGrader;
47
+ /** Ceilings the trial must stay under; every one that is crossed is named. */
48
+ interface BudgetOptions {
49
+ maxCostUsd?: number;
50
+ maxTokens?: number;
51
+ maxSteps?: number;
52
+ maxDurationMs?: number;
53
+ /** The slowest model call's time to first chunk. */
54
+ maxTimeToFirstChunkMs?: number;
55
+ }
56
+ /** The trial stayed within every ceiling given; a ceiling with no reading in the trace fails, since it cannot be shown. */
57
+ declare function budget(options: BudgetOptions): EvalGrader;
58
+ /**
59
+ * The host's own check of the end state (a booking exists, a row changed):
60
+ * "host decides". Return a boolean, or a full result to score and explain.
61
+ */
62
+ declare function outcome(name: string, check: (trial: Trial) => boolean | EvalResult | Promise<boolean | EvalResult>): EvalGrader;
63
+ export type { BudgetOptions, DeliveredGraders, TrajectoryMode };
64
+ export { budget, delivered, guardrail, outcome, stopKind, toolTrajectory };
@@ -0,0 +1,205 @@
1
+ /**
2
+ * Code graders: deterministic checks over a trial's trace. Each returns one
3
+ * pass/fail result with the reason in plain words. Outcome first: what was
4
+ * delivered and what it cost matter more than the path taken.
5
+ *
6
+ * @module
7
+ */
8
+ import { collectValidationFailures } from '../../kernel/engine/runner/schema-validation.js';
9
+ import { isRecord } from '../../kernel/util/record.js';
10
+ import { codeGrader, deliveredJson, deliveredText, listOf, modelCalls, passFail, spanDurationMs, } from './shared.js';
11
+ const MS_PER_S = 1000;
12
+ function stringAttribute(span, key) {
13
+ const value = span.attributes[key];
14
+ return typeof value === 'string' ? value : undefined;
15
+ }
16
+ function numberAttribute(span, key) {
17
+ const value = span.attributes[key];
18
+ return typeof value === 'number' ? value : undefined;
19
+ }
20
+ /** Deep structural equality over JSON values. */
21
+ function sameJson(left, right) {
22
+ return JSON.stringify(left) === JSON.stringify(right);
23
+ }
24
+ function quote(text) {
25
+ return JSON.stringify(text);
26
+ }
27
+ const delivered = {
28
+ /** The delivered text contains `text`. */
29
+ includes(text) {
30
+ return codeGrader('delivered_includes', `delivered.includes:${text}`, false, (trial) => {
31
+ const actual = deliveredText(trial, undefined);
32
+ const passed = actual.includes(text);
33
+ return passFail('delivered_includes', passed, passed ? `delivered text includes ${quote(text)}` : `delivered text lacks ${quote(text)}`);
34
+ });
35
+ },
36
+ /** The delivered text matches `pattern` (a JavaScript regular expression source). */
37
+ regex(pattern, flags = '') {
38
+ const re = new RegExp(pattern, flags);
39
+ return codeGrader('delivered_regex', `delivered.regex:/${pattern}/${flags}`, false, (trial) => {
40
+ const passed = re.test(deliveredText(trial, undefined));
41
+ return passFail('delivered_regex', passed, passed
42
+ ? `delivered text matches /${pattern}/${flags}`
43
+ : `delivered text does not match /${pattern}/${flags}`);
44
+ });
45
+ },
46
+ /** The delivered text equals `text` exactly. */
47
+ equals(text) {
48
+ return codeGrader('delivered_equals', `delivered.equals:${text}`, false, (trial) => {
49
+ const actual = deliveredText(trial, undefined);
50
+ const passed = actual === text;
51
+ return passFail('delivered_equals', passed, passed ? 'delivered text is exactly as expected' : `delivered text was ${quote(actual)}`);
52
+ });
53
+ },
54
+ /**
55
+ * The delivered JSON validates against a JSON Schema object (required
56
+ * fields present, recursively). The structured part is read when the
57
+ * profile has one; otherwise the text is parsed.
58
+ */
59
+ jsonSchema(schema) {
60
+ return codeGrader('delivered_json_schema', `delivered.jsonSchema:${JSON.stringify(schema)}`, false, async (trial) => {
61
+ const value = deliveredJson(trial);
62
+ if (value === undefined) {
63
+ return passFail('delivered_json_schema', false, 'delivered output is not JSON');
64
+ }
65
+ const failures = await collectValidationFailures(schema, value, undefined);
66
+ const passed = failures.length === 0;
67
+ return passFail('delivered_json_schema', passed, passed ? 'delivered JSON fits the schema' : failures.map((f) => f.error).join('; '));
68
+ });
69
+ },
70
+ /** Every field of the case's `expect.json` is present in the delivered JSON with the same value. */
71
+ json() {
72
+ return codeGrader('delivered_json', 'delivered.json', true, (trial) => {
73
+ const expected = trial.case?.expect?.json;
74
+ if (!expected) {
75
+ return passFail('delivered_json', false, 'case has no expect.json');
76
+ }
77
+ const actual = deliveredJson(trial);
78
+ if (!isRecord(actual)) {
79
+ return passFail('delivered_json', false, 'delivered output is not a JSON object');
80
+ }
81
+ const wrong = Object.entries(expected).filter(([key, want]) => !sameJson(actual[key], want));
82
+ const passed = wrong.length === 0;
83
+ return passFail('delivered_json', passed, passed
84
+ ? 'delivered JSON carries every expected field'
85
+ : `fields differ: ${wrong.map(([key, want]) => `${key} expected ${JSON.stringify(want)} got ${JSON.stringify(actual[key])}`).join('; ')}`);
86
+ });
87
+ },
88
+ };
89
+ function inOrder(expected, actual) {
90
+ let at = 0;
91
+ for (const name of actual) {
92
+ if (name === expected[at])
93
+ at += 1;
94
+ }
95
+ return at === expected.length;
96
+ }
97
+ function anyOrder(expected, actual) {
98
+ return sameJson([...expected].sort(), [...actual].sort());
99
+ }
100
+ function trajectoryMatches(mode, expected, actual) {
101
+ switch (mode) {
102
+ case 'exact':
103
+ return sameJson(expected, actual);
104
+ case 'in_order':
105
+ return inOrder(expected, actual);
106
+ case 'any_order':
107
+ return anyOrder(expected, actual);
108
+ case 'subset':
109
+ return actual.every((name) => expected.includes(name));
110
+ default:
111
+ return false;
112
+ }
113
+ }
114
+ /** The tools the agent called, in start order, against `expect` or the case's `expect.tools`. */
115
+ function toolTrajectory(options) {
116
+ const identity = `toolTrajectory:${options.mode}:${options.expect ? JSON.stringify(options.expect) : 'case'}`;
117
+ return codeGrader('tool_trajectory', identity, options.expect === undefined, (trial) => {
118
+ const expected = options.expect ?? trial.case?.expect?.tools;
119
+ if (!expected) {
120
+ return passFail('tool_trajectory', false, 'case has no expect.tools');
121
+ }
122
+ const actual = trial
123
+ .spans('execute_tool')
124
+ .flatMap((span) => stringAttribute(span, 'gen_ai.tool.name') ?? []);
125
+ const passed = trajectoryMatches(options.mode, expected, actual);
126
+ return passFail('tool_trajectory', passed, `called ${listOf(actual)}; expected ${listOf(expected)} (${options.mode})`);
127
+ });
128
+ }
129
+ // ── stop, guardrail, budget ─────────────────────────
130
+ /** The turn stopped for one of these reasons (`theorem.stop.kind`). */
131
+ function stopKind(kind) {
132
+ const kinds = Array.isArray(kind) ? kind : [kind];
133
+ return codeGrader('stop_kind', `stopKind:${kinds.join('|')}`, false, (trial) => {
134
+ const actual = stringAttribute(trial.root, 'theorem.stop.kind');
135
+ const passed = actual !== undefined && kinds.includes(actual);
136
+ return passFail('stop_kind', passed, `stopped ${actual ?? 'without a stop'}; expected ${listOf(kinds)}`);
137
+ });
138
+ }
139
+ /** A guardrail did (`fired: true`) or did not (`fired: false`) act on any span; `allow` does not count as acting. */
140
+ function guardrail(options) {
141
+ const identity = `guardrail:${options.fired}:${options.action ?? 'any'}`;
142
+ return codeGrader('guardrail', identity, false, (trial) => {
143
+ const actions = trial.records
144
+ .flatMap((record) => record.spans)
145
+ .flatMap((span) => span.events)
146
+ .filter((event) => event.name === 'theorem.guardrail')
147
+ .flatMap((event) => typeof event.attributes.action === 'string' ? [event.attributes.action] : [])
148
+ .filter((action) => (options.action ? action === options.action : action !== 'allow'));
149
+ const fired = actions.length > 0;
150
+ const passed = fired === options.fired;
151
+ return passFail('guardrail', passed, fired ? `guardrail acted: ${listOf(actions)}` : 'no guardrail acted');
152
+ });
153
+ }
154
+ const BUDGET_KEYS = [
155
+ 'maxCostUsd',
156
+ 'maxTokens',
157
+ 'maxSteps',
158
+ 'maxDurationMs',
159
+ 'maxTimeToFirstChunkMs',
160
+ ];
161
+ function budgetReadings(trial) {
162
+ const usage = trial.usage();
163
+ const firstChunks = modelCalls(trial).flatMap((span) => numberAttribute(span, 'gen_ai.response.time_to_first_chunk') ?? []);
164
+ return {
165
+ maxCostUsd: usage.costUsd,
166
+ maxTokens: usage.tokens.total,
167
+ maxSteps: numberAttribute(trial.root, 'theorem.steps'),
168
+ maxDurationMs: spanDurationMs(trial.top),
169
+ maxTimeToFirstChunkMs: firstChunks.length > 0 ? Math.max(...firstChunks) * MS_PER_S : undefined,
170
+ };
171
+ }
172
+ /** The trial stayed within every ceiling given; a ceiling with no reading in the trace fails, since it cannot be shown. */
173
+ function budget(options) {
174
+ return codeGrader('budget', `budget:${JSON.stringify(options)}`, false, (trial) => {
175
+ const readings = budgetReadings(trial);
176
+ const over = [];
177
+ for (const key of BUDGET_KEYS) {
178
+ const limit = options[key];
179
+ if (limit === undefined)
180
+ continue;
181
+ const reading = readings[key];
182
+ if (reading === undefined)
183
+ over.push(`${key}: not recorded`);
184
+ else if (reading > limit)
185
+ over.push(`${key}: ${reading} over ${limit}`);
186
+ }
187
+ const passed = over.length === 0;
188
+ return passFail('budget', passed, passed ? 'within budget' : over.join('; '));
189
+ });
190
+ }
191
+ // ── outcome ─────────────────────────────────────────
192
+ /**
193
+ * The host's own check of the end state (a booking exists, a row changed):
194
+ * "host decides". Return a boolean, or a full result to score and explain.
195
+ */
196
+ function outcome(name, check) {
197
+ return codeGrader(name, `outcome:${name}`, false, async (trial) => {
198
+ const verdict = await check(trial);
199
+ if (typeof verdict === 'boolean') {
200
+ return passFail(name, verdict, verdict ? 'outcome check passed' : 'outcome check failed');
201
+ }
202
+ return verdict;
203
+ });
204
+ }
205
+ export { budget, delivered, guardrail, outcome, stopKind, toolTrajectory };