evalkit-py 0.2.0.dev12__py3-none-any.whl

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 (371) hide show
  1. evalkit/__init__.py +0 -0
  2. evalkit/api/__init__.py +0 -0
  3. evalkit/api/access.py +74 -0
  4. evalkit/api/agents.py +159 -0
  5. evalkit/api/app.py +360 -0
  6. evalkit/api/auth.py +225 -0
  7. evalkit/api/cli_dist.py +10 -0
  8. evalkit/api/datasets.py +169 -0
  9. evalkit/api/deps.py +79 -0
  10. evalkit/api/download.py +15 -0
  11. evalkit/api/evaluators.py +121 -0
  12. evalkit/api/experiments.py +616 -0
  13. evalkit/api/fixtures.py +95 -0
  14. evalkit/api/harness_check.py +48 -0
  15. evalkit/api/imports.py +180 -0
  16. evalkit/api/limits.py +84 -0
  17. evalkit/api/llm_providers.py +120 -0
  18. evalkit/api/mcp/__init__.py +0 -0
  19. evalkit/api/mcp/auth.py +100 -0
  20. evalkit/api/mcp/descriptions.py +336 -0
  21. evalkit/api/mcp/models.py +259 -0
  22. evalkit/api/mcp/server.py +101 -0
  23. evalkit/api/mcp/tools.py +844 -0
  24. evalkit/api/meta.py +19 -0
  25. evalkit/api/otel.py +350 -0
  26. evalkit/api/pull.py +197 -0
  27. evalkit/api/review.py +271 -0
  28. evalkit/api/runs.py +555 -0
  29. evalkit/api/server_keys.py +44 -0
  30. evalkit/api/tokens.py +51 -0
  31. evalkit/api/trace_imports.py +173 -0
  32. evalkit/api/trace_sources.py +49 -0
  33. evalkit/api/traces.py +196 -0
  34. evalkit/api/users.py +72 -0
  35. evalkit/api/workspaces.py +131 -0
  36. evalkit/bundled/contracts/atif-accepted.json +5 -0
  37. evalkit/bundled/contracts/custom-evaluator-api-v1.json +243 -0
  38. evalkit/bundled/contracts/harness-api-v1.json +938 -0
  39. evalkit/bundled/contracts/span-mapping-v1.json +314 -0
  40. evalkit/bundled/docs/concepts.md +26 -0
  41. evalkit/bundled/docs/config.md +38 -0
  42. evalkit/bundled/docs/harness-api.md +44 -0
  43. evalkit/bundled/docs/install.md +60 -0
  44. evalkit/bundled/docs/login.md +36 -0
  45. evalkit/bundled/docs/mappings.md +136 -0
  46. evalkit/bundled/docs/mcp.md +44 -0
  47. evalkit/bundled/docs/quickstart.md +142 -0
  48. evalkit/bundled/docs/sdk-runs.md +171 -0
  49. evalkit/bundled/docs/tracing.md +171 -0
  50. evalkit/bundled/docs/try-locally.md +288 -0
  51. evalkit/bundled/docs/workspaces.md +45 -0
  52. evalkit/bundled/skills/authoring-eval-cases/SKILL.md +387 -0
  53. evalkit/bundled/skills/authoring-eval-cases/references/overlays.md +83 -0
  54. evalkit/bundled/skills/authoring-eval-cases/references/tool-checks.md +71 -0
  55. evalkit/bundled/skills/connect-traces/SKILL.md +296 -0
  56. evalkit/bundled/skills/connect-traces/references/gen_ai.json +42 -0
  57. evalkit/bundled/skills/connect-traces/references/openinference.json +35 -0
  58. evalkit/bundled/skills/connect-traces/references/span-mapping-schema.md +88 -0
  59. evalkit/bundled/skills/eval-driven-development/SKILL.md +458 -0
  60. evalkit/bundled/skills/eval-driven-development/references/analyze-run.md +97 -0
  61. evalkit/bundled/skills/eval-driven-development/references/diagnose.md +130 -0
  62. evalkit/bundled/skills/eval-driven-development/references/synthesize-cases.md +87 -0
  63. evalkit/bundled/skills/eval-driven-development/references/synthesize.md +165 -0
  64. evalkit/bundled/skills/evalkit-deployment/SKILL.md +332 -0
  65. evalkit/bundled/skills/evalkit-deployment/config.example.yaml +49 -0
  66. evalkit/bundled/skills/evalkit-deployment/docker-compose.yml +51 -0
  67. evalkit/bundled/skills/evalkit-deployment/references/config-and-deploy.md +333 -0
  68. evalkit/bundled/skills/evalkit-deployment/references/harness-api.md +139 -0
  69. evalkit/bundled/skills/evalkit-deployment/try/.env.example +11 -0
  70. evalkit/bundled/skills/evalkit-deployment/try/agent.py +131 -0
  71. evalkit/bundled/skills/evalkit-deployment/try/cases/acme/balance-sheet/cases.yaml +25 -0
  72. evalkit/bundled/skills/evalkit-deployment/try/cases/acme/income-statement/cases.yaml +43 -0
  73. evalkit/bundled/skills/evalkit-deployment/try/config.yaml +17 -0
  74. evalkit/bundled/skills/evalkit-deployment/try/docker-compose.yml +82 -0
  75. evalkit/bundled/skills/evalkit-deployment/try/evalkit.yaml +4 -0
  76. evalkit/bundled/skills/evalkit-deployment/try/mapping.json +42 -0
  77. evalkit/bundled/skills/evalkit-deployment/try/run.py +33 -0
  78. evalkit/bundled/skills/evalkit-usage/SKILL.md +509 -0
  79. evalkit/bundled/skills/evalkit-usage/references/suite-fixtures.md +42 -0
  80. evalkit/bundled/ui/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
  81. evalkit/bundled/ui/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
  82. evalkit/bundled/ui/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
  83. evalkit/bundled/ui/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
  84. evalkit/bundled/ui/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
  85. evalkit/bundled/ui/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
  86. evalkit/bundled/ui/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
  87. evalkit/bundled/ui/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
  88. evalkit/bundled/ui/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
  89. evalkit/bundled/ui/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
  90. evalkit/bundled/ui/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
  91. evalkit/bundled/ui/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
  92. evalkit/bundled/ui/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
  93. evalkit/bundled/ui/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
  94. evalkit/bundled/ui/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
  95. evalkit/bundled/ui/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
  96. evalkit/bundled/ui/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
  97. evalkit/bundled/ui/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
  98. evalkit/bundled/ui/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
  99. evalkit/bundled/ui/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
  100. evalkit/bundled/ui/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
  101. evalkit/bundled/ui/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
  102. evalkit/bundled/ui/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
  103. evalkit/bundled/ui/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
  104. evalkit/bundled/ui/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
  105. evalkit/bundled/ui/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
  106. evalkit/bundled/ui/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
  107. evalkit/bundled/ui/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
  108. evalkit/bundled/ui/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
  109. evalkit/bundled/ui/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
  110. evalkit/bundled/ui/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
  111. evalkit/bundled/ui/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
  112. evalkit/bundled/ui/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
  113. evalkit/bundled/ui/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
  114. evalkit/bundled/ui/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
  115. evalkit/bundled/ui/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
  116. evalkit/bundled/ui/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
  117. evalkit/bundled/ui/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
  118. evalkit/bundled/ui/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
  119. evalkit/bundled/ui/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
  120. evalkit/bundled/ui/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
  121. evalkit/bundled/ui/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
  122. evalkit/bundled/ui/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
  123. evalkit/bundled/ui/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
  124. evalkit/bundled/ui/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
  125. evalkit/bundled/ui/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
  126. evalkit/bundled/ui/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
  127. evalkit/bundled/ui/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
  128. evalkit/bundled/ui/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
  129. evalkit/bundled/ui/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
  130. evalkit/bundled/ui/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
  131. evalkit/bundled/ui/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
  132. evalkit/bundled/ui/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
  133. evalkit/bundled/ui/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
  134. evalkit/bundled/ui/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
  135. evalkit/bundled/ui/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
  136. evalkit/bundled/ui/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
  137. evalkit/bundled/ui/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
  138. evalkit/bundled/ui/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
  139. evalkit/bundled/ui/assets/abap-08VXUWAP.js +1 -0
  140. evalkit/bundled/ui/assets/apex-BWPQTe0t.js +1 -0
  141. evalkit/bundled/ui/assets/azcli-Bc_sGQ0U.js +1 -0
  142. evalkit/bundled/ui/assets/bat-i0X4ZdIN.js +1 -0
  143. evalkit/bundled/ui/assets/bicep-B5-_aFwp.js +2 -0
  144. evalkit/bundled/ui/assets/cameligo-DMUM7wLl.js +1 -0
  145. evalkit/bundled/ui/assets/clojure-Cm7r79vr.js +1 -0
  146. evalkit/bundled/ui/assets/codicon-DF1abBS2.ttf +0 -0
  147. evalkit/bundled/ui/assets/coffee-Ba7i2nA0.js +1 -0
  148. evalkit/bundled/ui/assets/cpp-C7h46wYY.js +1 -0
  149. evalkit/bundled/ui/assets/csharp-BKxtCVv1.js +1 -0
  150. evalkit/bundled/ui/assets/csp-bTuwJoIa.js +1 -0
  151. evalkit/bundled/ui/assets/css-DIMkf-bt.js +3 -0
  152. evalkit/bundled/ui/assets/css.worker-DwfUZ3fB.js +96 -0
  153. evalkit/bundled/ui/assets/cssMode-C97l1pbB.js +1 -0
  154. evalkit/bundled/ui/assets/cypher-CVaqCwHa.js +1 -0
  155. evalkit/bundled/ui/assets/dart-onAF5SnQ.js +1 -0
  156. evalkit/bundled/ui/assets/dockerfile-DZFCIeNp.js +1 -0
  157. evalkit/bundled/ui/assets/ecl-94qehhXe.js +1 -0
  158. evalkit/bundled/ui/assets/editor-DjpsE8to.css +1 -0
  159. evalkit/bundled/ui/assets/editor.api-NTesIxw5.js +908 -0
  160. evalkit/bundled/ui/assets/editor.worker-CRz__AKW.js +33 -0
  161. evalkit/bundled/ui/assets/elixir-6RTg0lbw.js +1 -0
  162. evalkit/bundled/ui/assets/flow9-C5_-GSwl.js +1 -0
  163. evalkit/bundled/ui/assets/freemarker2-BWqEFagp.js +3 -0
  164. evalkit/bundled/ui/assets/fsharp-C8Ef5oNN.js +1 -0
  165. evalkit/bundled/ui/assets/go-C-y9NEjX.js +1 -0
  166. evalkit/bundled/ui/assets/graphql-fmXr3nnJ.js +1 -0
  167. evalkit/bundled/ui/assets/handlebars-DkIF-whN.js +1 -0
  168. evalkit/bundled/ui/assets/hcl-CpzslTdj.js +1 -0
  169. evalkit/bundled/ui/assets/html-C_rpeQXJ.js +1 -0
  170. evalkit/bundled/ui/assets/html.worker-D9ugpX4y.js +509 -0
  171. evalkit/bundled/ui/assets/htmlMode-B0YIq3DF.js +1 -0
  172. evalkit/bundled/ui/assets/index-Cw-jBH6M.js +736 -0
  173. evalkit/bundled/ui/assets/index-DKtoQZtm.css +1 -0
  174. evalkit/bundled/ui/assets/ini-sBoK_t0W.js +1 -0
  175. evalkit/bundled/ui/assets/java-BEtHBSE6.js +1 -0
  176. evalkit/bundled/ui/assets/javascript-D4EGhYA6.js +1 -0
  177. evalkit/bundled/ui/assets/jetbrains-mono-cyrillic-wght-normal-D73BlboJ.woff2 +0 -0
  178. evalkit/bundled/ui/assets/jetbrains-mono-greek-wght-normal-Bw9x6K1M.woff2 +0 -0
  179. evalkit/bundled/ui/assets/jetbrains-mono-latin-ext-wght-normal-DBQx-q_a.woff2 +0 -0
  180. evalkit/bundled/ui/assets/jetbrains-mono-latin-wght-normal-B9CIFXIH.woff2 +0 -0
  181. evalkit/bundled/ui/assets/jetbrains-mono-vietnamese-wght-normal-Bt-aOZkq.woff2 +0 -0
  182. evalkit/bundled/ui/assets/json.worker-CV9fqkUp.js +65 -0
  183. evalkit/bundled/ui/assets/jsonMode-pQjSfIH6.js +7 -0
  184. evalkit/bundled/ui/assets/julia-Bri6UV-V.js +1 -0
  185. evalkit/bundled/ui/assets/kotlin-BOotOW0E.js +1 -0
  186. evalkit/bundled/ui/assets/less-B9JPFI3C.js +2 -0
  187. evalkit/bundled/ui/assets/lexon-CfSJPG6W.js +1 -0
  188. evalkit/bundled/ui/assets/liquid-DbrvoYjD.js +1 -0
  189. evalkit/bundled/ui/assets/lspLanguageFeatures-D0B7cH6y.js +4 -0
  190. evalkit/bundled/ui/assets/lua-CsQS60Ue.js +1 -0
  191. evalkit/bundled/ui/assets/m3-D-oSqn_W.js +1 -0
  192. evalkit/bundled/ui/assets/markdown-Cimd5fb3.js +1 -0
  193. evalkit/bundled/ui/assets/mdx-B0HrujLR.js +1 -0
  194. evalkit/bundled/ui/assets/mips-CIPQ_RoX.js +1 -0
  195. evalkit/bundled/ui/assets/monacoEditor-DsoPncxW.js +68 -0
  196. evalkit/bundled/ui/assets/monacoEditor-n7clI0si.css +1 -0
  197. evalkit/bundled/ui/assets/msdax-DauUninz.js +1 -0
  198. evalkit/bundled/ui/assets/mysql-SOo6toE5.js +1 -0
  199. evalkit/bundled/ui/assets/objective-c-FvmIjYaQ.js +1 -0
  200. evalkit/bundled/ui/assets/pascal-DrH0SRf2.js +1 -0
  201. evalkit/bundled/ui/assets/pascaligo-D-ptJ9y-.js +1 -0
  202. evalkit/bundled/ui/assets/perl-oz_6vUea.js +1 -0
  203. evalkit/bundled/ui/assets/pgsql-DTj74zXo.js +1 -0
  204. evalkit/bundled/ui/assets/php-nr791fC2.js +1 -0
  205. evalkit/bundled/ui/assets/pla-CopQ2nXW.js +1 -0
  206. evalkit/bundled/ui/assets/postiats-43DmfD33.js +1 -0
  207. evalkit/bundled/ui/assets/powerquery-D3hlyOfw.js +1 -0
  208. evalkit/bundled/ui/assets/powershell-DmHpPYUd.js +1 -0
  209. evalkit/bundled/ui/assets/protobuf-C531GsRP.js +2 -0
  210. evalkit/bundled/ui/assets/pug-Z5eAx3Zn.js +1 -0
  211. evalkit/bundled/ui/assets/python-CieHVM9n.js +1 -0
  212. evalkit/bundled/ui/assets/qsharp-DkqhCAOL.js +1 -0
  213. evalkit/bundled/ui/assets/r-BwWrilGY.js +1 -0
  214. evalkit/bundled/ui/assets/razor-sLewSMyp.js +1 -0
  215. evalkit/bundled/ui/assets/redis-ClamHrr6.js +1 -0
  216. evalkit/bundled/ui/assets/redshift-DT7zqm-g.js +1 -0
  217. evalkit/bundled/ui/assets/restructuredtext-BYgofb2h.js +1 -0
  218. evalkit/bundled/ui/assets/ruby-DezsRK8O.js +1 -0
  219. evalkit/bundled/ui/assets/rust-DdL9SqIa.js +1 -0
  220. evalkit/bundled/ui/assets/sb-CcwsVR0C.js +1 -0
  221. evalkit/bundled/ui/assets/scala-DHpiXF5c.js +1 -0
  222. evalkit/bundled/ui/assets/scheme-BeGwcela.js +1 -0
  223. evalkit/bundled/ui/assets/scss-gp-XZpBa.js +3 -0
  224. evalkit/bundled/ui/assets/shell-CC2rA5mh.js +1 -0
  225. evalkit/bundled/ui/assets/solidity-BEEn4gHE.js +1 -0
  226. evalkit/bundled/ui/assets/sophia-CRfGWb83.js +1 -0
  227. evalkit/bundled/ui/assets/sparql-D_Lu-MrJ.js +1 -0
  228. evalkit/bundled/ui/assets/sql-NEE52Syq.js +1 -0
  229. evalkit/bundled/ui/assets/st-DbInun42.js +1 -0
  230. evalkit/bundled/ui/assets/swift-Bxkupp3x.js +1 -0
  231. evalkit/bundled/ui/assets/systemverilog-Bz4Y3fRF.js +1 -0
  232. evalkit/bundled/ui/assets/tcl-DISqw1ZD.js +1 -0
  233. evalkit/bundled/ui/assets/ts.worker-DIAQkoB3.js +67741 -0
  234. evalkit/bundled/ui/assets/tsMode-BcVQ1nu0.js +11 -0
  235. evalkit/bundled/ui/assets/twig-De2hgUGE.js +1 -0
  236. evalkit/bundled/ui/assets/typescript-CUvNWd9p.js +1 -0
  237. evalkit/bundled/ui/assets/typespec-B8J7ngcE.js +1 -0
  238. evalkit/bundled/ui/assets/vb-DV3o63ZY.js +1 -0
  239. evalkit/bundled/ui/assets/wgsl-DpFanUEy.js +298 -0
  240. evalkit/bundled/ui/assets/workers-CwpYQtzp.js +1 -0
  241. evalkit/bundled/ui/assets/xml-C1HnXMdF.js +1 -0
  242. evalkit/bundled/ui/assets/yaml-D7Ey3HQu.js +1 -0
  243. evalkit/bundled/ui/favicon.svg +6 -0
  244. evalkit/bundled/ui/index.html +14 -0
  245. evalkit/cli/__init__.py +0 -0
  246. evalkit/cli/admin_commands.py +590 -0
  247. evalkit/cli/client.py +67 -0
  248. evalkit/cli/init_server.py +165 -0
  249. evalkit/cli/local_run.py +195 -0
  250. evalkit/cli/main.py +1365 -0
  251. evalkit/cli/runs_commands.py +539 -0
  252. evalkit/cli/server_commands.py +130 -0
  253. evalkit/cli/skill_targets.py +43 -0
  254. evalkit/cli/tokens_commands.py +52 -0
  255. evalkit/cli/traces_commands.py +332 -0
  256. evalkit/cli/update.py +85 -0
  257. evalkit/client/__init__.py +0 -0
  258. evalkit/client/agents.py +25 -0
  259. evalkit/client/api.py +193 -0
  260. evalkit/client/blob.py +104 -0
  261. evalkit/client/connection.py +88 -0
  262. evalkit/client/evaluators.py +11 -0
  263. evalkit/client/sessions.py +17 -0
  264. evalkit/client/store.py +139 -0
  265. evalkit/client/summary.py +46 -0
  266. evalkit/client/sync.py +198 -0
  267. evalkit/config.py +227 -0
  268. evalkit/contracts/__init__.py +0 -0
  269. evalkit/contracts/atif.py +115 -0
  270. evalkit/contracts/cases.py +456 -0
  271. evalkit/contracts/custom_evaluator.py +58 -0
  272. evalkit/contracts/enums.py +86 -0
  273. evalkit/contracts/esf.py +120 -0
  274. evalkit/contracts/harness.py +281 -0
  275. evalkit/contracts/notes.json +4 -0
  276. evalkit/contracts/notes.py +7 -0
  277. evalkit/contracts/settings.py +41 -0
  278. evalkit/core/__init__.py +0 -0
  279. evalkit/core/access.py +75 -0
  280. evalkit/core/agents.py +65 -0
  281. evalkit/core/blob.py +46 -0
  282. evalkit/core/capabilities.py +36 -0
  283. evalkit/core/costmap.py +90 -0
  284. evalkit/core/custom_eval.py +50 -0
  285. evalkit/core/data/cost_map.json +81546 -0
  286. evalkit/core/endpoints.py +31 -0
  287. evalkit/core/evaluators/__init__.py +29 -0
  288. evalkit/core/evaluators/base.py +121 -0
  289. evalkit/core/evaluators/gauges.py +84 -0
  290. evalkit/core/evaluators/presentation.py +166 -0
  291. evalkit/core/evaluators/response_time.py +21 -0
  292. evalkit/core/evaluators/rubrics.py +494 -0
  293. evalkit/core/evaluators/tool_trajectory.py +187 -0
  294. evalkit/core/evaluators/trajectory_rubrics.py +198 -0
  295. evalkit/core/fixtures.py +57 -0
  296. evalkit/core/harness.py +227 -0
  297. evalkit/core/harness_check.py +191 -0
  298. evalkit/core/importer.py +257 -0
  299. evalkit/core/judge.py +78 -0
  300. evalkit/core/lint.py +265 -0
  301. evalkit/core/overlays.py +76 -0
  302. evalkit/core/paths.py +25 -0
  303. evalkit/core/promotion.py +94 -0
  304. evalkit/core/pull.py +198 -0
  305. evalkit/core/python_eval.py +59 -0
  306. evalkit/core/remote_evaluators.py +32 -0
  307. evalkit/core/review.py +220 -0
  308. evalkit/core/run_digest.py +421 -0
  309. evalkit/core/runner.py +995 -0
  310. evalkit/core/scorecard.py +255 -0
  311. evalkit/core/traces/__init__.py +0 -0
  312. evalkit/core/traces/convert.py +336 -0
  313. evalkit/core/traces/importer.py +113 -0
  314. evalkit/core/traces/mapping.py +385 -0
  315. evalkit/core/traces/poll.py +38 -0
  316. evalkit/core/traces/raw.py +21 -0
  317. evalkit/core/traces/sessions.py +172 -0
  318. evalkit/core/traces/settle.py +14 -0
  319. evalkit/core/traces/sources/__init__.py +19 -0
  320. evalkit/core/traces/sources/base.py +25 -0
  321. evalkit/core/traces/sources/phoenix.py +121 -0
  322. evalkit/core/trajectory.py +248 -0
  323. evalkit/core/workspace.py +30 -0
  324. evalkit/credentials.py +119 -0
  325. evalkit/db/__init__.py +0 -0
  326. evalkit/db/agents.py +289 -0
  327. evalkit/db/alembic/env.py +90 -0
  328. evalkit/db/alembic/script.py.mako +28 -0
  329. evalkit/db/alembic/versions/0011_baseline.py +1002 -0
  330. evalkit/db/alembic/versions/0012_ticket_token_kind.py +27 -0
  331. evalkit/db/alembic/versions/0013_keys_and_llm_providers.py +67 -0
  332. evalkit/db/cases.py +608 -0
  333. evalkit/db/crypto.py +12 -0
  334. evalkit/db/evaluators.py +156 -0
  335. evalkit/db/experiments.py +363 -0
  336. evalkit/db/fixture_blobs.py +91 -0
  337. evalkit/db/keys.py +78 -0
  338. evalkit/db/llm_providers.py +176 -0
  339. evalkit/db/locks.py +6 -0
  340. evalkit/db/mappings.py +168 -0
  341. evalkit/db/models.py +567 -0
  342. evalkit/db/promotion.py +271 -0
  343. evalkit/db/rekey.py +46 -0
  344. evalkit/db/review.py +250 -0
  345. evalkit/db/review_state.py +50 -0
  346. evalkit/db/runs.py +533 -0
  347. evalkit/db/scorecard.py +300 -0
  348. evalkit/db/session.py +71 -0
  349. evalkit/db/sessions.py +90 -0
  350. evalkit/db/spans.py +360 -0
  351. evalkit/db/store.py +209 -0
  352. evalkit/db/tokens.py +100 -0
  353. evalkit/db/trace_imports.py +308 -0
  354. evalkit/db/trace_sources.py +131 -0
  355. evalkit/db/users.py +186 -0
  356. evalkit/db/workspaces.py +232 -0
  357. evalkit/paths.py +33 -0
  358. evalkit/sdk/__init__.py +29 -0
  359. evalkit/sdk/binding.py +69 -0
  360. evalkit/sdk/evaluators.py +56 -0
  361. evalkit/sdk/runner.py +957 -0
  362. evalkit/sdk/tracing.py +166 -0
  363. evalkit/store/__init__.py +0 -0
  364. evalkit/store/base.py +354 -0
  365. evalkit/store/blob.py +69 -0
  366. evalkit/version.py +44 -0
  367. evalkit_py-0.2.0.dev12.dist-info/METADATA +205 -0
  368. evalkit_py-0.2.0.dev12.dist-info/RECORD +371 -0
  369. evalkit_py-0.2.0.dev12.dist-info/WHEEL +4 -0
  370. evalkit_py-0.2.0.dev12.dist-info/entry_points.txt +2 -0
  371. evalkit_py-0.2.0.dev12.dist-info/licenses/LICENSE +661 -0
@@ -0,0 +1,421 @@
1
+ import json
2
+ import math
3
+ from collections import defaultdict
4
+ from collections.abc import Callable, Iterable
5
+ from datetime import datetime, tzinfo
6
+ from typing import Any, Literal, get_args
7
+
8
+ from pydantic import BaseModel
9
+
10
+ from evalkit.contracts.atif import ContentPart, ObservationResult, Step, Trajectory
11
+ from evalkit.core.trajectory import TrajectoryView, derive_metrics, trajectory_model
12
+
13
+ CostSource = Literal["reported", "estimated", "mixed"]
14
+ TurnStatus = Literal["ok", "failed", "no_answer"]
15
+
16
+ QUESTION_CHARS = 300
17
+ ANSWER_CHARS = 600
18
+ ERROR_CHARS = 300
19
+
20
+
21
+ def clip(text: str | None, limit: int) -> str | None:
22
+ if text is None or len(text) <= limit:
23
+ return text
24
+ return f"{text[:limit]}…[+{len(text) - limit} chars]"
25
+
26
+
27
+ def content_text(content: str | list[ContentPart] | None) -> str:
28
+ if content is None:
29
+ return ""
30
+ if isinstance(content, str):
31
+ return content
32
+ return " ".join(part.text for part in content if part.type == "text" and part.text)
33
+
34
+
35
+ def _parse_ts(value: str | None) -> datetime | None:
36
+ if not value:
37
+ return None
38
+ return datetime.fromisoformat(value.replace("Z", "+00:00"))
39
+
40
+
41
+ def _seconds(start: datetime | None, end: datetime | None) -> float | None:
42
+ if start is None or end is None:
43
+ return None
44
+ return round((end - start).total_seconds(), 3)
45
+
46
+
47
+ def _step_extra(step: Step) -> dict:
48
+ return step.model_extra.get("extra") or {} if step.model_extra else {}
49
+
50
+
51
+ def _is_error(result: ObservationResult) -> bool:
52
+ return (result.extra or {}).get("is_error") is True
53
+
54
+
55
+ class ToolErrors(BaseModel):
56
+ tool: str
57
+ count: int
58
+ message: str | None = None
59
+
60
+
61
+ class ModelCost(BaseModel):
62
+ model: str
63
+ cost_usd: float
64
+ input_tokens: int
65
+ output_tokens: int
66
+ cached_tokens: int
67
+ steps: int
68
+
69
+
70
+ class ToolCallGroup(BaseModel):
71
+ tool: str
72
+ count: int
73
+ arguments: dict[str, Any]
74
+
75
+
76
+ class Turn(BaseModel):
77
+ index: int
78
+ started_at: datetime | None
79
+ ended_at: datetime | None
80
+ duration_seconds: float | None
81
+ status: TurnStatus
82
+ error: str | None = None
83
+ question: str | None
84
+ answer: str | None
85
+ cost_usd: float | None
86
+ agent_steps: int
87
+ tool_calls: int
88
+ tool_errors: int
89
+
90
+
91
+ class RunDigest(BaseModel):
92
+ run_id: str
93
+ started_at: datetime | None
94
+ ended_at: datetime | None
95
+ duration_seconds: float | None
96
+ wall_seconds: float | None
97
+ turns: int
98
+ failed_turns: int
99
+ failures: int
100
+ agent_steps: int
101
+ cost_usd: float | None
102
+ cost_source: CostSource | None
103
+ input_tokens: int | None
104
+ output_tokens: int | None
105
+ cached_tokens: int | None
106
+ tool_calls: int
107
+ tool_errors: int
108
+ tool_errors_by_tool: list[ToolErrors]
109
+ tool_call_groups: list[ToolCallGroup]
110
+ cost_by_model: list[ModelCost]
111
+ models: list[str]
112
+ subagents: int
113
+ opening_question: str | None
114
+ final_answer: str | None
115
+
116
+
117
+ def _turn_groups(steps: list[Step]) -> list[list[Step]]:
118
+ groups: list[list[Step]] = []
119
+ for step in steps:
120
+ if step.source == "user" or not groups:
121
+ groups.append([step])
122
+ else:
123
+ groups[-1].append(step)
124
+ return groups
125
+
126
+
127
+ def _turn(index: int, steps: list[Step]) -> Turn:
128
+ question = next((content_text(s.message) for s in steps if s.source == "user"), None)
129
+ answers = [
130
+ content_text(s.message)
131
+ for s in steps
132
+ if s.source == "agent" and not s.tool_calls and content_text(s.message)
133
+ ]
134
+ failing = next((s for s in steps if _step_extra(s).get("is_error") is True), None)
135
+ error = None
136
+ if failing is not None:
137
+ error = _step_extra(failing).get("error") or content_text(failing.message) or "error"
138
+ status: TurnStatus = "failed" if failing is not None else "ok" if answers else "no_answer"
139
+ costs = [s.metrics.cost_usd for s in steps if s.metrics and s.metrics.cost_usd is not None]
140
+ stamps = [t for t in (_parse_ts(s.timestamp) for s in steps) if t is not None]
141
+ started = stamps[0] if stamps else None
142
+ ended = stamps[-1] if stamps else None
143
+ return Turn(
144
+ index=index,
145
+ started_at=started,
146
+ ended_at=ended,
147
+ duration_seconds=_seconds(started, ended),
148
+ status=status,
149
+ error=clip(error, ERROR_CHARS),
150
+ question=clip(question, QUESTION_CHARS),
151
+ answer=clip(answers[-1] if answers else None, ANSWER_CHARS),
152
+ cost_usd=round(sum(costs), 10) if costs else None,
153
+ agent_steps=sum(1 for s in steps if s.source == "agent"),
154
+ tool_calls=sum(len(s.tool_calls or []) for s in steps),
155
+ tool_errors=sum(
156
+ sum(1 for r in s.observation.results if _is_error(r)) for s in steps if s.observation
157
+ ),
158
+ )
159
+
160
+
161
+ def turns(trajectory: Trajectory) -> list[Turn]:
162
+ return [_turn(i, group) for i, group in enumerate(_turn_groups(trajectory.steps), 1)]
163
+
164
+
165
+ def _all_steps(trajectory: Trajectory) -> Iterable[Step]:
166
+ yield from trajectory.steps
167
+ for sub in trajectory.subagent_trajectories or []:
168
+ yield from _all_steps(sub)
169
+
170
+
171
+ TOOL_ARGUMENT_CHARS = 120
172
+ TOOL_CALL_GROUPS_MAX = 100
173
+
174
+
175
+ def _short(value: Any) -> Any:
176
+ # Strings keep both ends: a path's file extension and a command's head both matter.
177
+ if isinstance(value, str):
178
+ if len(value) <= TOOL_ARGUMENT_CHARS:
179
+ return value
180
+ half = TOOL_ARGUMENT_CHARS // 2
181
+ return f"{value[:half]}…{value[-half:]}"
182
+ text = json.dumps(value, default=str)
183
+ return value if len(text) <= TOOL_ARGUMENT_CHARS else clip(text, TOOL_ARGUMENT_CHARS)
184
+
185
+
186
+ # A step without a model counts under its trajectory's, the rule the cost
187
+ # backfill prices it by; the sum misses a run whose harness reported only a total.
188
+ def cost_by_model(trajectory: Trajectory) -> list[ModelCost]:
189
+ totals: dict[str, ModelCost] = {}
190
+
191
+ def walk(t: Trajectory, inherited: str | None) -> None:
192
+ default = trajectory_model(t) or inherited
193
+ for step in t.steps:
194
+ if step.metrics is None or step.metrics.cost_usd is None:
195
+ continue
196
+ model = step.model_name or default or "unknown"
197
+ row = totals.setdefault(
198
+ model,
199
+ ModelCost(
200
+ model=model,
201
+ cost_usd=0.0,
202
+ input_tokens=0,
203
+ output_tokens=0,
204
+ cached_tokens=0,
205
+ steps=0,
206
+ ),
207
+ )
208
+ row.cost_usd += step.metrics.cost_usd
209
+ row.input_tokens += step.metrics.prompt_tokens or 0
210
+ row.output_tokens += step.metrics.completion_tokens or 0
211
+ row.cached_tokens += step.metrics.cached_tokens or 0
212
+ row.steps += 1
213
+ for sub in t.subagent_trajectories or []:
214
+ walk(sub, default)
215
+
216
+ walk(trajectory, None)
217
+ for row in totals.values():
218
+ row.cost_usd = round(row.cost_usd, 10)
219
+ return sorted(totals.values(), key=lambda r: -r.cost_usd)
220
+
221
+
222
+ def tool_call_groups(trajectory: Trajectory) -> list[ToolCallGroup]:
223
+ counts: dict[str, int] = defaultdict(int)
224
+ shapes: dict[str, tuple[str, dict[str, Any]]] = {}
225
+ for step in _all_steps(trajectory):
226
+ for call in step.tool_calls or []:
227
+ arguments = {k: _short(v) for k, v in (call.arguments or {}).items()}
228
+ key = json.dumps([call.function_name, arguments], sort_keys=True, default=str)
229
+ counts[key] += 1
230
+ shapes[key] = (call.function_name, arguments)
231
+ ranked = sorted(counts, key=lambda k: -counts[k])[:TOOL_CALL_GROUPS_MAX]
232
+ return [
233
+ ToolCallGroup(tool=shapes[k][0], count=counts[k], arguments=shapes[k][1]) for k in ranked
234
+ ]
235
+
236
+
237
+ def tool_errors_by_tool(trajectory: Trajectory) -> list[ToolErrors]:
238
+ counts: dict[str, int] = defaultdict(int)
239
+ messages: dict[str, str] = {}
240
+ for step in _all_steps(trajectory):
241
+ if step.observation is None:
242
+ continue
243
+ names = {call.tool_call_id: call.function_name for call in step.tool_calls or []}
244
+ for result in step.observation.results:
245
+ if not _is_error(result):
246
+ continue
247
+ tool = names.get(result.source_call_id or "", "unknown")
248
+ counts[tool] += 1
249
+ if tool not in messages:
250
+ error_type = (result.extra or {}).get("error_type")
251
+ text = content_text(result.content) or error_type or ""
252
+ messages[tool] = clip(text, ERROR_CHARS) or ""
253
+ return [
254
+ ToolErrors(tool=tool, count=count, message=messages.get(tool) or None)
255
+ for tool, count in sorted(counts.items(), key=lambda kv: (-kv[1], kv[0]))
256
+ ]
257
+
258
+
259
+ def priced_steps(trajectory: Trajectory) -> set[int]:
260
+ return {
261
+ id(step)
262
+ for step in _all_steps(trajectory)
263
+ if step.metrics is not None and step.metrics.cost_usd
264
+ }
265
+
266
+
267
+ def cost_source(trajectory: Trajectory, reported: set[int]) -> CostSource | None:
268
+ priced = priced_steps(trajectory)
269
+ final = trajectory.final_metrics
270
+ if final is not None and final.total_cost_usd:
271
+ return "reported"
272
+ if not priced:
273
+ return None
274
+ if priced <= reported:
275
+ return "reported"
276
+ if reported & priced:
277
+ return "mixed"
278
+ return "estimated"
279
+
280
+
281
+ def digest(run_id: str, trajectory: Trajectory, reported: set[int]) -> RunDigest:
282
+ view = TrajectoryView(trajectory)
283
+ metrics = derive_metrics(view, None)
284
+ run_turns = turns(trajectory)
285
+ durations = [t.duration_seconds for t in run_turns if t.duration_seconds is not None]
286
+ stamps = [t for t in (_parse_ts(s.timestamp) for s in trajectory.steps) if t is not None]
287
+ agent_model = trajectory.agent.model_name if trajectory.agent else None
288
+ models = sorted(
289
+ {s.model_name for s in _all_steps(trajectory) if s.model_name}
290
+ | ({agent_model} if agent_model else set())
291
+ )
292
+ final_answer = next((t.answer for t in reversed(run_turns) if t.answer), None)
293
+ return RunDigest(
294
+ run_id=run_id,
295
+ started_at=stamps[0] if stamps else None,
296
+ ended_at=stamps[-1] if stamps else None,
297
+ duration_seconds=round(sum(durations), 3) if durations else None,
298
+ wall_seconds=_seconds(stamps[0], stamps[-1]) if stamps else None,
299
+ turns=sum(1 for s in trajectory.steps if s.source == "user"),
300
+ failed_turns=sum(1 for t in run_turns if t.status == "failed"),
301
+ failures=sum(1 for s in trajectory.steps if _step_extra(s).get("is_error") is True),
302
+ agent_steps=metrics.turns,
303
+ cost_usd=metrics.cost_usd,
304
+ cost_source=cost_source(trajectory, reported),
305
+ input_tokens=metrics.input_tokens,
306
+ output_tokens=metrics.output_tokens,
307
+ cached_tokens=metrics.cached_tokens,
308
+ tool_calls=metrics.total_tool_calls,
309
+ tool_errors=metrics.errored_tool_calls,
310
+ tool_errors_by_tool=tool_errors_by_tool(trajectory),
311
+ tool_call_groups=tool_call_groups(trajectory),
312
+ cost_by_model=cost_by_model(trajectory),
313
+ models=models,
314
+ subagents=metrics.subagents,
315
+ opening_question=run_turns[0].question if run_turns else None,
316
+ final_answer=final_answer,
317
+ )
318
+
319
+
320
+ def percentile(values: list[float], q: float) -> float | None:
321
+ if not values:
322
+ return None
323
+ ordered = sorted(values)
324
+ return ordered[max(0, math.ceil(q * len(ordered)) - 1)]
325
+
326
+
327
+ GroupBy = Literal["none", "day", "tool", "user", "source"]
328
+ GROUP_BY_VALUES: tuple[str, ...] = get_args(GroupBy)
329
+
330
+
331
+ class StatsInput(BaseModel):
332
+ digest: RunDigest
333
+ turn_durations: list[float]
334
+ source: str
335
+ user_id: str | None
336
+ created_at: datetime | None
337
+
338
+
339
+ class GroupStats(BaseModel):
340
+ group: dict[str, str]
341
+ runs: int
342
+ runs_with_failure: int
343
+ turns: int
344
+ failed_turns: int
345
+ failures: int
346
+ cost_usd: float
347
+ runs_with_estimated_cost: int
348
+ runs_without_cost: int
349
+ turn_p50_seconds: float | None
350
+ turn_p90_seconds: float | None
351
+ tool_errors: int
352
+ runs_with_tool_errors: int
353
+ sample_error: str | None = None
354
+
355
+
356
+ def _day(moment: datetime | None, zone: tzinfo) -> str:
357
+ return moment.astimezone(zone).date().isoformat() if moment else "unknown"
358
+
359
+
360
+ def _summarize(
361
+ group: dict[str, str], items: list[StatsInput], tool_errors: Callable[[RunDigest], int]
362
+ ) -> GroupStats:
363
+ digests = [i.digest for i in items]
364
+ durations = [d for i in items for d in i.turn_durations]
365
+ return GroupStats(
366
+ group=group,
367
+ runs=len(items),
368
+ runs_with_failure=sum(1 for d in digests if d.failures),
369
+ turns=sum(d.turns for d in digests),
370
+ failed_turns=sum(d.failed_turns for d in digests),
371
+ failures=sum(d.failures for d in digests),
372
+ cost_usd=round(sum(d.cost_usd or 0.0 for d in digests), 10),
373
+ runs_with_estimated_cost=sum(1 for d in digests if d.cost_source in ("estimated", "mixed")),
374
+ runs_without_cost=sum(1 for d in digests if d.cost_usd is None),
375
+ turn_p50_seconds=percentile(durations, 0.5),
376
+ turn_p90_seconds=percentile(durations, 0.9),
377
+ tool_errors=sum(tool_errors(d) for d in digests),
378
+ runs_with_tool_errors=sum(1 for d in digests if tool_errors(d)),
379
+ )
380
+
381
+
382
+ def _all_tool_errors(digest: RunDigest) -> int:
383
+ return digest.tool_errors
384
+
385
+
386
+ def _tool_rows(items: list[StatsInput]) -> list[GroupStats]:
387
+ by_tool: dict[str, list[StatsInput]] = defaultdict(list)
388
+ messages: dict[str, str | None] = {}
389
+ for item in items:
390
+ for entry in item.digest.tool_errors_by_tool:
391
+ by_tool[entry.tool].append(item)
392
+ messages.setdefault(entry.tool, entry.message)
393
+ rows = []
394
+ for tool, tool_items in by_tool.items():
395
+
396
+ def count(digest: RunDigest, tool: str = tool) -> int:
397
+ return sum(e.count for e in digest.tool_errors_by_tool if e.tool == tool)
398
+
399
+ row = _summarize({"tool": tool}, tool_items, count)
400
+ row.sample_error = messages[tool]
401
+ rows.append(row)
402
+ return sorted(rows, key=lambda r: (-r.tool_errors, r.group["tool"]))
403
+
404
+
405
+ def group_stats(items: list[StatsInput], zone: tzinfo, group_by: GroupBy) -> list[GroupStats]:
406
+ if group_by == "none":
407
+ return [_summarize({}, items, _all_tool_errors)]
408
+ if group_by == "tool":
409
+ return _tool_rows(items)
410
+ keys: dict[str, Callable[[StatsInput], str]] = {
411
+ "day": lambda i: _day(i.created_at or i.digest.started_at, zone),
412
+ "user": lambda i: i.user_id or "unknown",
413
+ "source": lambda i: i.source,
414
+ }
415
+ groups: dict[str, list[StatsInput]] = defaultdict(list)
416
+ for item in items:
417
+ groups[keys[group_by](item)].append(item)
418
+ rows = [_summarize({group_by: k}, v, _all_tool_errors) for k, v in groups.items()]
419
+ if group_by == "day":
420
+ return sorted(rows, key=lambda r: r.group["day"])
421
+ return sorted(rows, key=lambda r: (-r.runs, r.group[group_by]))