gatewaysdk 0.3.2__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 (376) hide show
  1. gatewaysdk/__init__.py +540 -0
  2. gatewaysdk/adapter/__init__.py +15 -0
  3. gatewaysdk/adapter/base.py +94 -0
  4. gatewaysdk/adapter/messages.py +270 -0
  5. gatewaysdk/adapter/triplet.py +1026 -0
  6. gatewaysdk/algorithm/__init__.py +39 -0
  7. gatewaysdk/algorithm/apo/__init__.py +5 -0
  8. gatewaysdk/algorithm/apo/apo.py +898 -0
  9. gatewaysdk/algorithm/apo/prompts/apply_edit_variant01.poml +22 -0
  10. gatewaysdk/algorithm/apo/prompts/apply_edit_variant02.poml +18 -0
  11. gatewaysdk/algorithm/apo/prompts/text_gradient_variant01.poml +18 -0
  12. gatewaysdk/algorithm/apo/prompts/text_gradient_variant02.poml +16 -0
  13. gatewaysdk/algorithm/apo/prompts/text_gradient_variant03.poml +107 -0
  14. gatewaysdk/algorithm/base.py +262 -0
  15. gatewaysdk/algorithm/decorator.py +264 -0
  16. gatewaysdk/algorithm/evals/__init__.py +7 -0
  17. gatewaysdk/algorithm/evals/evals.py +217 -0
  18. gatewaysdk/algorithm/fast.py +250 -0
  19. gatewaysdk/algorithm/gepa/__init__.py +61 -0
  20. gatewaysdk/algorithm/gepa/adapter.py +495 -0
  21. gatewaysdk/algorithm/gepa/gepa.py +570 -0
  22. gatewaysdk/algorithm/gepa/lib/__init__.py +18 -0
  23. gatewaysdk/algorithm/gepa/lib/adapters/README.md +12 -0
  24. gatewaysdk/algorithm/gepa/lib/adapters/__init__.py +0 -0
  25. gatewaysdk/algorithm/gepa/lib/adapters/anymaths_adapter/README.md +341 -0
  26. gatewaysdk/algorithm/gepa/lib/adapters/anymaths_adapter/__init__.py +1 -0
  27. gatewaysdk/algorithm/gepa/lib/adapters/anymaths_adapter/anymaths_adapter.py +174 -0
  28. gatewaysdk/algorithm/gepa/lib/adapters/anymaths_adapter/requirements.txt +1 -0
  29. gatewaysdk/algorithm/gepa/lib/adapters/default_adapter/README.md +0 -0
  30. gatewaysdk/algorithm/gepa/lib/adapters/default_adapter/__init__.py +0 -0
  31. gatewaysdk/algorithm/gepa/lib/adapters/default_adapter/default_adapter.py +209 -0
  32. gatewaysdk/algorithm/gepa/lib/adapters/dspy_adapter/README.md +7 -0
  33. gatewaysdk/algorithm/gepa/lib/adapters/dspy_adapter/__init__.py +0 -0
  34. gatewaysdk/algorithm/gepa/lib/adapters/dspy_adapter/dspy_adapter.py +307 -0
  35. gatewaysdk/algorithm/gepa/lib/adapters/dspy_full_program_adapter/README.md +99 -0
  36. gatewaysdk/algorithm/gepa/lib/adapters/dspy_full_program_adapter/dspy_program_proposal_signature.py +137 -0
  37. gatewaysdk/algorithm/gepa/lib/adapters/dspy_full_program_adapter/full_program_adapter.py +268 -0
  38. gatewaysdk/algorithm/gepa/lib/adapters/generic_rag_adapter/GEPA_RAG.md +621 -0
  39. gatewaysdk/algorithm/gepa/lib/adapters/generic_rag_adapter/__init__.py +56 -0
  40. gatewaysdk/algorithm/gepa/lib/adapters/generic_rag_adapter/evaluation_metrics.py +226 -0
  41. gatewaysdk/algorithm/gepa/lib/adapters/generic_rag_adapter/generic_rag_adapter.py +496 -0
  42. gatewaysdk/algorithm/gepa/lib/adapters/generic_rag_adapter/rag_pipeline.py +238 -0
  43. gatewaysdk/algorithm/gepa/lib/adapters/generic_rag_adapter/vector_store_interface.py +212 -0
  44. gatewaysdk/algorithm/gepa/lib/adapters/generic_rag_adapter/vector_stores/__init__.py +2 -0
  45. gatewaysdk/algorithm/gepa/lib/adapters/generic_rag_adapter/vector_stores/chroma_store.py +196 -0
  46. gatewaysdk/algorithm/gepa/lib/adapters/generic_rag_adapter/vector_stores/lancedb_store.py +422 -0
  47. gatewaysdk/algorithm/gepa/lib/adapters/generic_rag_adapter/vector_stores/milvus_store.py +409 -0
  48. gatewaysdk/algorithm/gepa/lib/adapters/generic_rag_adapter/vector_stores/qdrant_store.py +368 -0
  49. gatewaysdk/algorithm/gepa/lib/adapters/generic_rag_adapter/vector_stores/weaviate_store.py +418 -0
  50. gatewaysdk/algorithm/gepa/lib/adapters/mcp_adapter/README.md +552 -0
  51. gatewaysdk/algorithm/gepa/lib/adapters/mcp_adapter/__init__.py +37 -0
  52. gatewaysdk/algorithm/gepa/lib/adapters/mcp_adapter/mcp_adapter.py +699 -0
  53. gatewaysdk/algorithm/gepa/lib/adapters/mcp_adapter/mcp_client.py +364 -0
  54. gatewaysdk/algorithm/gepa/lib/adapters/terminal_bench_adapter/README.md +9 -0
  55. gatewaysdk/algorithm/gepa/lib/adapters/terminal_bench_adapter/__init__.py +0 -0
  56. gatewaysdk/algorithm/gepa/lib/adapters/terminal_bench_adapter/terminal_bench_adapter.py +217 -0
  57. gatewaysdk/algorithm/gepa/lib/api.py +382 -0
  58. gatewaysdk/algorithm/gepa/lib/core/__init__.py +0 -0
  59. gatewaysdk/algorithm/gepa/lib/core/adapter.py +180 -0
  60. gatewaysdk/algorithm/gepa/lib/core/data_loader.py +74 -0
  61. gatewaysdk/algorithm/gepa/lib/core/engine.py +379 -0
  62. gatewaysdk/algorithm/gepa/lib/core/result.py +233 -0
  63. gatewaysdk/algorithm/gepa/lib/core/state.py +636 -0
  64. gatewaysdk/algorithm/gepa/lib/examples/__init__.py +0 -0
  65. gatewaysdk/algorithm/gepa/lib/examples/aime.py +24 -0
  66. gatewaysdk/algorithm/gepa/lib/examples/anymaths-bench/eval_default.py +111 -0
  67. gatewaysdk/algorithm/gepa/lib/examples/anymaths-bench/prompt-templates/instruction_prompt.txt +9 -0
  68. gatewaysdk/algorithm/gepa/lib/examples/anymaths-bench/prompt-templates/optimal_prompt.txt +24 -0
  69. gatewaysdk/algorithm/gepa/lib/examples/anymaths-bench/train_anymaths.py +177 -0
  70. gatewaysdk/algorithm/gepa/lib/examples/dspy_full_program_evolution/arc_agi.ipynb +25705 -0
  71. gatewaysdk/algorithm/gepa/lib/examples/dspy_full_program_evolution/example.ipynb +348 -0
  72. gatewaysdk/algorithm/gepa/lib/examples/mcp_adapter/__init__.py +4 -0
  73. gatewaysdk/algorithm/gepa/lib/examples/mcp_adapter/mcp_optimization_example.py +456 -0
  74. gatewaysdk/algorithm/gepa/lib/examples/rag_adapter/RAG_GUIDE.md +613 -0
  75. gatewaysdk/algorithm/gepa/lib/examples/rag_adapter/__init__.py +9 -0
  76. gatewaysdk/algorithm/gepa/lib/examples/rag_adapter/rag_optimization.py +820 -0
  77. gatewaysdk/algorithm/gepa/lib/examples/rag_adapter/requirements-rag.txt +29 -0
  78. gatewaysdk/algorithm/gepa/lib/examples/terminal-bench/prompt-templates/instruction_prompt.txt +16 -0
  79. gatewaysdk/algorithm/gepa/lib/examples/terminal-bench/prompt-templates/terminus.txt +9 -0
  80. gatewaysdk/algorithm/gepa/lib/examples/terminal-bench/train_terminus.py +161 -0
  81. gatewaysdk/algorithm/gepa/lib/gepa_utils.py +117 -0
  82. gatewaysdk/algorithm/gepa/lib/logging/__init__.py +0 -0
  83. gatewaysdk/algorithm/gepa/lib/logging/experiment_tracker.py +187 -0
  84. gatewaysdk/algorithm/gepa/lib/logging/logger.py +75 -0
  85. gatewaysdk/algorithm/gepa/lib/logging/utils.py +103 -0
  86. gatewaysdk/algorithm/gepa/lib/proposer/__init__.py +0 -0
  87. gatewaysdk/algorithm/gepa/lib/proposer/base.py +31 -0
  88. gatewaysdk/algorithm/gepa/lib/proposer/merge.py +357 -0
  89. gatewaysdk/algorithm/gepa/lib/proposer/reflective_mutation/__init__.py +0 -0
  90. gatewaysdk/algorithm/gepa/lib/proposer/reflective_mutation/base.py +49 -0
  91. gatewaysdk/algorithm/gepa/lib/proposer/reflective_mutation/reflective_mutation.py +176 -0
  92. gatewaysdk/algorithm/gepa/lib/py.typed +0 -0
  93. gatewaysdk/algorithm/gepa/lib/strategies/__init__.py +0 -0
  94. gatewaysdk/algorithm/gepa/lib/strategies/batch_sampler.py +77 -0
  95. gatewaysdk/algorithm/gepa/lib/strategies/candidate_selector.py +50 -0
  96. gatewaysdk/algorithm/gepa/lib/strategies/component_selector.py +36 -0
  97. gatewaysdk/algorithm/gepa/lib/strategies/eval_policy.py +64 -0
  98. gatewaysdk/algorithm/gepa/lib/strategies/instruction_proposal.py +126 -0
  99. gatewaysdk/algorithm/gepa/lib/utils/__init__.py +10 -0
  100. gatewaysdk/algorithm/gepa/lib/utils/stop_condition.py +196 -0
  101. gatewaysdk/algorithm/gepa/tracing.py +105 -0
  102. gatewaysdk/algorithm/utils.py +177 -0
  103. gatewaysdk/algorithm/verl/__init__.py +5 -0
  104. gatewaysdk/algorithm/verl/interface.py +202 -0
  105. gatewaysdk/automations.py +111 -0
  106. gatewaysdk/benchmark_hub/README.md +88 -0
  107. gatewaysdk/benchmark_hub/__init__.py +119 -0
  108. gatewaysdk/benchmark_hub/_archive.py +189 -0
  109. gatewaysdk/benchmark_hub/_tar.py +6 -0
  110. gatewaysdk/benchmark_hub/client.py +992 -0
  111. gatewaysdk/benchmark_hub/dispatch_shard.py +34 -0
  112. gatewaysdk/benchmark_hub/eval_config.py +20 -0
  113. gatewaysdk/benchmark_hub/evals.py +351 -0
  114. gatewaysdk/benchmark_hub/harbor_adapter.py +673 -0
  115. gatewaysdk/benchmark_hub/path_utils.py +81 -0
  116. gatewaysdk/benchmark_hub/save_utils.py +101 -0
  117. gatewaysdk/benchmark_hub/verifiers_adapter.py +327 -0
  118. gatewaysdk/benchmark_hub/versioning.py +72 -0
  119. gatewaysdk/build.py +515 -0
  120. gatewaysdk/cli/__init__.py +58 -0
  121. gatewaysdk/cli/agent_runner.py +132 -0
  122. gatewaysdk/cli/http_client.py +115 -0
  123. gatewaysdk/cli/platform.py +4086 -0
  124. gatewaysdk/cli/prometheus.py +115 -0
  125. gatewaysdk/cli/release_gate.py +215 -0
  126. gatewaysdk/cli/store.py +131 -0
  127. gatewaysdk/cli/vllm.py +29 -0
  128. gatewaysdk/client.py +406 -0
  129. gatewaysdk/config.py +348 -0
  130. gatewaysdk/connectors/__init__.py +25 -0
  131. gatewaysdk/connectors/client.py +203 -0
  132. gatewaysdk/connectors/skill.py +25 -0
  133. gatewaysdk/connectors/template.py +106 -0
  134. gatewaysdk/context.py +606 -0
  135. gatewaysdk/emitter/__init__.py +43 -0
  136. gatewaysdk/emitter/annotation.py +370 -0
  137. gatewaysdk/emitter/exception.py +54 -0
  138. gatewaysdk/emitter/message.py +61 -0
  139. gatewaysdk/emitter/object.py +117 -0
  140. gatewaysdk/emitter/reward.py +320 -0
  141. gatewaysdk/env_var.py +156 -0
  142. gatewaysdk/environment/__init__.py +108 -0
  143. gatewaysdk/environment/_bundle.py +281 -0
  144. gatewaysdk/environment/_harbor.py +276 -0
  145. gatewaysdk/environment/_materialize.py +97 -0
  146. gatewaysdk/environment/_tar.py +33 -0
  147. gatewaysdk/environment/_world.py +346 -0
  148. gatewaysdk/environment/core.py +527 -0
  149. gatewaysdk/environment/errors.py +58 -0
  150. gatewaysdk/environment/runtime.py +150 -0
  151. gatewaysdk/environment/schema/__init__.py +35 -0
  152. gatewaysdk/environment/schema/__main__.py +225 -0
  153. gatewaysdk/environment/schema/_slack_fidelity.py +116 -0
  154. gatewaysdk/environment/schema/_slack_scenario.py +183 -0
  155. gatewaysdk/environment/schema/api.py +1628 -0
  156. gatewaysdk/environment/schema/batch.py +755 -0
  157. gatewaysdk/environment/schema/compiler.py +615 -0
  158. gatewaysdk/environment/schema/conform.py +428 -0
  159. gatewaysdk/environment/schema/connector.py +777 -0
  160. gatewaysdk/environment/schema/connectors/apple-business-manager/handlers.py +17 -0
  161. gatewaysdk/environment/schema/connectors/apple-business-manager/parity.json +28 -0
  162. gatewaysdk/environment/schema/connectors/apple-business-manager/provenance.json +233 -0
  163. gatewaysdk/environment/schema/connectors/apple-business-manager/scope.toml +112 -0
  164. gatewaysdk/environment/schema/connectors/apple-business-manager/world.json +1380 -0
  165. gatewaysdk/environment/schema/connectors/base.json +28 -0
  166. gatewaysdk/environment/schema/connectors/custom/handlers.py +18 -0
  167. gatewaysdk/environment/schema/connectors/custom/world.json +123 -0
  168. gatewaysdk/environment/schema/connectors/github/handlers.py +81 -0
  169. gatewaysdk/environment/schema/connectors/github/parity.json +37 -0
  170. gatewaysdk/environment/schema/connectors/github/provenance.json +134 -0
  171. gatewaysdk/environment/schema/connectors/github/scope.toml +158 -0
  172. gatewaysdk/environment/schema/connectors/github/world.json +5869 -0
  173. gatewaysdk/environment/schema/connectors/google-calendar/handlers.py +23 -0
  174. gatewaysdk/environment/schema/connectors/google-calendar/world.json +209 -0
  175. gatewaysdk/environment/schema/connectors/google-drive/handlers.py +18 -0
  176. gatewaysdk/environment/schema/connectors/google-drive/world.json +286 -0
  177. gatewaysdk/environment/schema/connectors/jamf/handlers.py +34 -0
  178. gatewaysdk/environment/schema/connectors/jamf/parity.json +49 -0
  179. gatewaysdk/environment/schema/connectors/jamf/provenance.json +181 -0
  180. gatewaysdk/environment/schema/connectors/jamf/scope.toml +128 -0
  181. gatewaysdk/environment/schema/connectors/jamf/world.json +2218 -0
  182. gatewaysdk/environment/schema/connectors/jira/handlers.py +28 -0
  183. gatewaysdk/environment/schema/connectors/jira/world.json +389 -0
  184. gatewaysdk/environment/schema/connectors/kandji/handlers.py +38 -0
  185. gatewaysdk/environment/schema/connectors/kandji/parity.json +29 -0
  186. gatewaysdk/environment/schema/connectors/kandji/provenance.json +152 -0
  187. gatewaysdk/environment/schema/connectors/kandji/scope.toml +120 -0
  188. gatewaysdk/environment/schema/connectors/kandji/world.json +765 -0
  189. gatewaysdk/environment/schema/connectors/linear/handlers.py +20 -0
  190. gatewaysdk/environment/schema/connectors/linear/world.json +363 -0
  191. gatewaysdk/environment/schema/connectors/microsoft-teams/fidelity.json +45 -0
  192. gatewaysdk/environment/schema/connectors/microsoft-teams/handlers.py +1 -0
  193. gatewaysdk/environment/schema/connectors/microsoft-teams/provenance.json +851 -0
  194. gatewaysdk/environment/schema/connectors/microsoft-teams/scope.md +231 -0
  195. gatewaysdk/environment/schema/connectors/microsoft-teams/teams-types.json +1710 -0
  196. gatewaysdk/environment/schema/connectors/microsoft-teams/world.json +858 -0
  197. gatewaysdk/environment/schema/connectors/netsuite/handlers.py +32 -0
  198. gatewaysdk/environment/schema/connectors/netsuite/parity.json +50 -0
  199. gatewaysdk/environment/schema/connectors/netsuite/provenance.json +137 -0
  200. gatewaysdk/environment/schema/connectors/netsuite/scope.toml +78 -0
  201. gatewaysdk/environment/schema/connectors/netsuite/world.json +16243 -0
  202. gatewaysdk/environment/schema/connectors/salesforce/handlers.py +806 -0
  203. gatewaysdk/environment/schema/connectors/salesforce/parity.json +46 -0
  204. gatewaysdk/environment/schema/connectors/salesforce/provenance.json +143 -0
  205. gatewaysdk/environment/schema/connectors/salesforce/scope.toml +174 -0
  206. gatewaysdk/environment/schema/connectors/salesforce/world.json +4695 -0
  207. gatewaysdk/environment/schema/connectors/slack/MODEL.md +236 -0
  208. gatewaysdk/environment/schema/connectors/slack/capabilities.json +1039 -0
  209. gatewaysdk/environment/schema/connectors/slack/handlers.py +762 -0
  210. gatewaysdk/environment/schema/connectors/slack/parity.json +65 -0
  211. gatewaysdk/environment/schema/connectors/slack/provenance.json +294 -0
  212. gatewaysdk/environment/schema/connectors/slack/scope.toml +44 -0
  213. gatewaysdk/environment/schema/connectors/slack/world.json +4993 -0
  214. gatewaysdk/environment/schema/connectors/workday/handlers.py +75 -0
  215. gatewaysdk/environment/schema/connectors/workday/parity.json +36 -0
  216. gatewaysdk/environment/schema/connectors/workday/provenance.json +179 -0
  217. gatewaysdk/environment/schema/connectors/workday/scope.toml +180 -0
  218. gatewaysdk/environment/schema/connectors/workday/world.json +806 -0
  219. gatewaysdk/environment/schema/data.py +593 -0
  220. gatewaysdk/environment/schema/extract.py +263 -0
  221. gatewaysdk/environment/schema/host.py +2437 -0
  222. gatewaysdk/environment/schema/host_surfaces.py +275 -0
  223. gatewaysdk/environment/schema/platform.py +1272 -0
  224. gatewaysdk/environment/schema/scaffold.py +250 -0
  225. gatewaysdk/environment/schema/skill.py +118 -0
  226. gatewaysdk/environment/schema/skills/agents/connector-template-author.md +202 -0
  227. gatewaysdk/environment/schema/skills/connector-schema-authoring/CONNECTORS.md +331 -0
  228. gatewaysdk/environment/schema/skills/connector-schema-authoring/CONVENTIONS.md +100 -0
  229. gatewaysdk/environment/schema/skills/connector-schema-authoring/SKILL.md +313 -0
  230. gatewaysdk/environment/schema/skills/world-data-ingestion/ROWS.md +223 -0
  231. gatewaysdk/environment/schema/skills/world-data-ingestion/SKILL.md +293 -0
  232. gatewaysdk/environment/schema/skills/worlds-getting-started/SKILL.md +390 -0
  233. gatewaysdk/environment/schema/slack.py +757 -0
  234. gatewaysdk/environment/schema/snapshot.py +479 -0
  235. gatewaysdk/environment/schema/store.py +904 -0
  236. gatewaysdk/environment/schema/tasks.py +525 -0
  237. gatewaysdk/environment/schema/tools_world.py +322 -0
  238. gatewaysdk/environment/schema/validation.py +577 -0
  239. gatewaysdk/environment/schema/worker.py +78 -0
  240. gatewaysdk/environment/schema/workers.py +500 -0
  241. gatewaysdk/environment/schema/world_tests.py +336 -0
  242. gatewaysdk/environments/__init__.py +24 -0
  243. gatewaysdk/environments/client.py +486 -0
  244. gatewaysdk/environments/types.py +318 -0
  245. gatewaysdk/execution/__init__.py +15 -0
  246. gatewaysdk/execution/base.py +64 -0
  247. gatewaysdk/execution/client_server.py +443 -0
  248. gatewaysdk/execution/events.py +69 -0
  249. gatewaysdk/execution/inter_process.py +16 -0
  250. gatewaysdk/execution/shared_memory.py +282 -0
  251. gatewaysdk/experiments/__init__.py +90 -0
  252. gatewaysdk/experiments/assignment.py +177 -0
  253. gatewaysdk/experiments/client.py +877 -0
  254. gatewaysdk/experiments/exposure.py +222 -0
  255. gatewaysdk/experiments/types.py +81 -0
  256. gatewaysdk/importers/__init__.py +49 -0
  257. gatewaysdk/importers/_normalize.py +91 -0
  258. gatewaysdk/importers/builder.py +173 -0
  259. gatewaysdk/importers/client.py +95 -0
  260. gatewaysdk/importers/langsmith.py +196 -0
  261. gatewaysdk/importers/recipes.py +249 -0
  262. gatewaysdk/instrumentation/__init__.py +300 -0
  263. gatewaysdk/instrumentation/agentops.py +314 -0
  264. gatewaysdk/instrumentation/agentops_langchain.py +45 -0
  265. gatewaysdk/instrumentation/base.py +119 -0
  266. gatewaysdk/instrumentation/litellm.py +83 -0
  267. gatewaysdk/instrumentation/registry.py +273 -0
  268. gatewaysdk/instrumentation/vllm.py +81 -0
  269. gatewaysdk/instrumentation/weave.py +500 -0
  270. gatewaysdk/integrations/__init__.py +15 -0
  271. gatewaysdk/integrations/gateway/__init__.py +11 -0
  272. gatewaysdk/integrations/gateway/client.py +171 -0
  273. gatewaysdk/integrations/tool_access.py +549 -0
  274. gatewaysdk/litagent/__init__.py +11 -0
  275. gatewaysdk/litagent/decorator.py +536 -0
  276. gatewaysdk/litagent/litagent.py +252 -0
  277. gatewaysdk/llm_proxy.py +1742 -0
  278. gatewaysdk/logging.py +370 -0
  279. gatewaysdk/memory.py +278 -0
  280. gatewaysdk/personas.py +186 -0
  281. gatewaysdk/platform/__init__.py +17 -0
  282. gatewaysdk/platform/builder.py +221 -0
  283. gatewaysdk/platform/compatibility.py +67 -0
  284. gatewaysdk/platform/manifest.py +185 -0
  285. gatewaysdk/platform/orchestrator.py +901 -0
  286. gatewaysdk/platform/registry.py +122 -0
  287. gatewaysdk/platform/worker.py +864 -0
  288. gatewaysdk/replay/__init__.py +1032 -0
  289. gatewaysdk/replay/pytest.py +56 -0
  290. gatewaysdk/reward.py +7 -0
  291. gatewaysdk/run.py +1781 -0
  292. gatewaysdk/runner/__init__.py +11 -0
  293. gatewaysdk/runner/agent.py +878 -0
  294. gatewaysdk/runner/base.py +182 -0
  295. gatewaysdk/runner/legacy.py +309 -0
  296. gatewaysdk/security.py +700 -0
  297. gatewaysdk/semconv.py +170 -0
  298. gatewaysdk/server.py +399 -0
  299. gatewaysdk/sessions.py +282 -0
  300. gatewaysdk/store/__init__.py +45 -0
  301. gatewaysdk/store/base.py +908 -0
  302. gatewaysdk/store/client_server.py +2093 -0
  303. gatewaysdk/store/collection/__init__.py +30 -0
  304. gatewaysdk/store/collection/base.py +587 -0
  305. gatewaysdk/store/collection/memory.py +970 -0
  306. gatewaysdk/store/collection/mongo.py +1412 -0
  307. gatewaysdk/store/collection_based.py +1823 -0
  308. gatewaysdk/store/gateway.py +983 -0
  309. gatewaysdk/store/gateway_listener.py +465 -0
  310. gatewaysdk/store/listener.py +58 -0
  311. gatewaysdk/store/memory.py +396 -0
  312. gatewaysdk/store/mongo.py +165 -0
  313. gatewaysdk/store/redis_stream.py +517 -0
  314. gatewaysdk/store/sqlite.py +3 -0
  315. gatewaysdk/store/threading.py +370 -0
  316. gatewaysdk/store/utils.py +142 -0
  317. gatewaysdk/tracer/__init__.py +14 -0
  318. gatewaysdk/tracer/base.py +286 -0
  319. gatewaysdk/tracer/dummy.py +106 -0
  320. gatewaysdk/tracer/otel.py +559 -0
  321. gatewaysdk/tracing/__init__.py +110 -0
  322. gatewaysdk/tracing/api.py +808 -0
  323. gatewaysdk/tracing/attributes.py +9 -0
  324. gatewaysdk/tracing/context.py +272 -0
  325. gatewaysdk/tracing/exporters/__init__.py +10 -0
  326. gatewaysdk/tracing/exporters/gateway.py +228 -0
  327. gatewaysdk/tracing/identity.py +288 -0
  328. gatewaysdk/tracing/init.py +620 -0
  329. gatewaysdk/tracing/instrumentors/__init__.py +15 -0
  330. gatewaysdk/tracing/instrumentors/claude_agent_sdk.py +766 -0
  331. gatewaysdk/tracing/instrumentors/instrumentation_principles.md +294 -0
  332. gatewaysdk/tracing/instrumentors/registry.py +352 -0
  333. gatewaysdk/tracing/mapping.py +729 -0
  334. gatewaysdk/tracing/processors.py +393 -0
  335. gatewaysdk/tracing/push.py +617 -0
  336. gatewaysdk/tracing/push_models.py +247 -0
  337. gatewaysdk/tracing/semconv.py +294 -0
  338. gatewaysdk/tracing/span_builder.py +356 -0
  339. gatewaysdk/trainer/__init__.py +6 -0
  340. gatewaysdk/trainer/init_utils.py +263 -0
  341. gatewaysdk/trainer/legacy.py +359 -0
  342. gatewaysdk/trainer/registry.py +12 -0
  343. gatewaysdk/trainer/trainer.py +638 -0
  344. gatewaysdk/types/__init__.py +63 -0
  345. gatewaysdk/types/core.py +556 -0
  346. gatewaysdk/types/resources.py +204 -0
  347. gatewaysdk/types/tracer.py +515 -0
  348. gatewaysdk/types/tracing.py +162 -0
  349. gatewaysdk/users.py +251 -0
  350. gatewaysdk/utils/__init__.py +1 -0
  351. gatewaysdk/utils/id.py +18 -0
  352. gatewaysdk/utils/metrics.py +1025 -0
  353. gatewaysdk/utils/otel.py +550 -0
  354. gatewaysdk/utils/otlp.py +556 -0
  355. gatewaysdk/utils/redact.py +22 -0
  356. gatewaysdk/utils/server_launcher.py +1045 -0
  357. gatewaysdk/utils/system_snapshot.py +90 -0
  358. gatewaysdk/verl/__init__.py +8 -0
  359. gatewaysdk/verl/__main__.py +6 -0
  360. gatewaysdk/verl/async_server.py +46 -0
  361. gatewaysdk/verl/config.yaml +27 -0
  362. gatewaysdk/verl/daemon.py +1154 -0
  363. gatewaysdk/verl/dataset.py +44 -0
  364. gatewaysdk/verl/entrypoint.py +248 -0
  365. gatewaysdk/verl/trainer.py +549 -0
  366. gatewaysdk/world_browser.py +748 -0
  367. gatewaysdk/world_data.py +453 -0
  368. gatewaysdk/world_sessions.py +978 -0
  369. gatewaysdk/world_tasks.py +285 -0
  370. gatewaysdk/world_tools.py +115 -0
  371. gatewaysdk/worlds.py +639 -0
  372. gatewaysdk-0.3.2.dist-info/METADATA +236 -0
  373. gatewaysdk-0.3.2.dist-info/RECORD +376 -0
  374. gatewaysdk-0.3.2.dist-info/WHEEL +4 -0
  375. gatewaysdk-0.3.2.dist-info/entry_points.txt +5 -0
  376. gatewaysdk-0.3.2.dist-info/licenses/LICENSE +19 -0
@@ -0,0 +1,81 @@
1
+ """Eval-results dir layout + resume matching.
2
+
3
+ Ported (stdlib-only) from Prime Intellect's ``verifiers`` (MIT). A run's results
4
+ live at ``<output_dir>/evals/<env_id>--<model>/<run_id>/`` holding
5
+ ``results.jsonl`` + ``metadata.json``. Resume finds the newest *incomplete* run
6
+ whose saved config matches, counting completed rollouts per example (clamped to
7
+ ``rollouts_per_example``) — so a crashed run continues instead of restarting.
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ import uuid
13
+ from pathlib import Path
14
+ from typing import Any, Dict, Optional, Union
15
+
16
+ from .save_utils import (
17
+ METADATA_FILE,
18
+ RESULTS_FILE,
19
+ load_metadata,
20
+ load_outputs,
21
+ )
22
+
23
+
24
+ def _model_slug(model: str) -> str:
25
+ return model.replace("/", "--")
26
+
27
+
28
+ def get_results_path(output_dir: Union[str, Path], env_id: str, model: str) -> Path:
29
+ """A fresh results dir for a run: ``<output_dir>/evals/<env>--<model>/<uuid8>``."""
30
+ run_id = uuid.uuid4().hex[:8]
31
+ return Path(output_dir) / "evals" / f"{env_id}--{_model_slug(model)}" / run_id
32
+
33
+
34
+ def is_valid_eval_results_path(path: Union[str, Path]) -> bool:
35
+ """A results dir is valid iff it has BOTH results.jsonl and metadata.json."""
36
+ p = Path(path)
37
+ return (p / RESULTS_FILE).exists() and (p / METADATA_FILE).exists()
38
+
39
+
40
+ def count_saved_rollouts(results_path: Union[str, Path], rollouts_per_example: int) -> Dict[Any, int]:
41
+ """Completed rollouts per ``example_id``, clamped to ``rollouts_per_example``."""
42
+ counts: Dict[Any, int] = {}
43
+ rpe = rollouts_per_example if rollouts_per_example > 0 else 1
44
+ for row in load_outputs(results_path):
45
+ eid = row.get("example_id")
46
+ if eid is None:
47
+ continue
48
+ counts[eid] = min(counts.get(eid, 0) + 1, rpe)
49
+ return counts
50
+
51
+
52
+ def find_latest_incomplete_eval_results_path(
53
+ output_dir: Union[str, Path],
54
+ env_id: str,
55
+ model: str,
56
+ num_examples: int,
57
+ rollouts_per_example: int,
58
+ shuffle: bool = False,
59
+ shuffle_seed: Optional[int] = None,
60
+ ) -> Optional[Path]:
61
+ """Newest results dir (by mtime) whose saved metadata matches this config AND
62
+ that still has fewer saved rollouts than requested — or None."""
63
+ root = Path(output_dir) / "evals" / f"{env_id}--{_model_slug(model)}"
64
+ if not root.exists():
65
+ return None
66
+ candidates = [d for d in root.iterdir() if d.is_dir() and is_valid_eval_results_path(d)]
67
+ candidates.sort(key=lambda d: d.stat().st_mtime, reverse=True)
68
+
69
+ total = num_examples * rollouts_per_example if num_examples > 0 else None
70
+ for c in candidates:
71
+ meta = load_metadata(c)
72
+ if meta.get("env_id") != env_id or meta.get("model") != model:
73
+ continue
74
+ if meta.get("rollouts_per_example") != rollouts_per_example:
75
+ continue
76
+ if meta.get("shuffle") != shuffle or meta.get("shuffle_seed") != (shuffle_seed):
77
+ continue
78
+ saved = sum(count_saved_rollouts(c, rollouts_per_example).values())
79
+ if total is None or saved < total:
80
+ return c
81
+ return None
@@ -0,0 +1,101 @@
1
+ """Local eval-results persistence: ``results.jsonl`` + ``metadata.json``.
2
+
3
+ Ported (stdlib-only) from Prime Intellect's ``verifiers`` (MIT) save layer so a
4
+ ``bench eval`` run writes the same on-disk contract that powers resume + upload.
5
+ ``save_metadata`` is atomic (temp file in the same dir + ``os.replace``) and drops
6
+ the non-serializable ``path_to_save``/``date`` keys, matching verifiers.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ import json
12
+ import os
13
+ import tempfile
14
+ from pathlib import Path
15
+ from typing import Any, Dict, List, Union
16
+
17
+ RESULTS_FILE = "results.jsonl"
18
+ METADATA_FILE = "metadata.json"
19
+
20
+
21
+ def make_serializable(obj: Any) -> Any:
22
+ """Best-effort JSON-serializable copy: recurse dict/list, stringify the rest."""
23
+ try:
24
+ json.dumps(obj)
25
+ return obj
26
+ except (TypeError, ValueError):
27
+ if isinstance(obj, dict):
28
+ return {k: make_serializable(v) for k, v in obj.items()}
29
+ if isinstance(obj, (list, tuple)):
30
+ return [make_serializable(v) for v in obj]
31
+ return str(obj)
32
+
33
+
34
+ def save_outputs(
35
+ results_path: Union[str, Path],
36
+ rows: List[Dict[str, Any]],
37
+ mode: str = "a",
38
+ ) -> None:
39
+ """Append (or overwrite) rollout rows to ``results.jsonl``, one per line."""
40
+ f = Path(results_path) / RESULTS_FILE
41
+ f.parent.mkdir(parents=True, exist_ok=True)
42
+ with open(f, mode) as fh:
43
+ for row in rows:
44
+ fh.write(json.dumps(make_serializable(row)) + "\n")
45
+
46
+
47
+ def load_outputs(results_path: Union[str, Path]) -> List[Dict[str, Any]]:
48
+ """Read ``results.jsonl``, skipping blank/malformed/non-dict lines (a torn last
49
+ line from a crash is silently ignored — resume-safe)."""
50
+ f = Path(results_path) / RESULTS_FILE
51
+ if not f.exists():
52
+ return []
53
+ out: List[Dict[str, Any]] = []
54
+ for line in f.read_text().splitlines():
55
+ line = line.strip()
56
+ if not line:
57
+ continue
58
+ try:
59
+ row = json.loads(line)
60
+ except Exception:
61
+ continue
62
+ if isinstance(row, dict):
63
+ out.append(row)
64
+ return out
65
+
66
+
67
+ def save_metadata(results_path: Union[str, Path], metadata: Dict[str, Any]) -> None:
68
+ """Atomically write ``metadata.json`` (temp in same dir + ``os.replace``),
69
+ dropping ``path_to_save``/``date`` (non-serializable, per verifiers)."""
70
+ p = Path(results_path)
71
+ p.mkdir(parents=True, exist_ok=True)
72
+ meta = dict(metadata)
73
+ meta.pop("path_to_save", None)
74
+ meta.pop("date", None)
75
+ fd, tmp = tempfile.mkstemp(dir=str(p), suffix=".tmp")
76
+ try:
77
+ with os.fdopen(fd, "w") as fh:
78
+ json.dump(make_serializable(meta), fh, indent=2)
79
+ os.replace(tmp, str(p / METADATA_FILE))
80
+ finally:
81
+ if os.path.exists(tmp):
82
+ os.unlink(tmp)
83
+
84
+
85
+ def load_metadata(results_path: Union[str, Path]) -> Dict[str, Any]:
86
+ """Read ``metadata.json`` ({} if absent/malformed)."""
87
+ f = Path(results_path) / METADATA_FILE
88
+ if not f.exists():
89
+ return {}
90
+ try:
91
+ data = json.loads(f.read_text())
92
+ return data if isinstance(data, dict) else {}
93
+ except Exception:
94
+ return {}
95
+
96
+
97
+ def validate_resume_metadata(saved_metadata: Dict[str, Any], requested_num_examples: int) -> None:
98
+ """On resume, ``num_examples`` may only grow — a smaller request is an error."""
99
+ saved_n = saved_metadata.get("num_examples")
100
+ if isinstance(saved_n, int) and saved_n > 0 and requested_num_examples > 0 and requested_num_examples < saved_n:
101
+ raise ValueError(f"cannot resume: requested num_examples {requested_num_examples} " f"< saved {saved_n}")
@@ -0,0 +1,327 @@
1
+ """Score a verifiers-format container and harvest into Gateway.
2
+
3
+ `verifiers` (MIT) is the one genuinely open, self-hostable piece of Prime's eval
4
+ stack: ``Environment.evaluate_sync()`` runs the rollout loop against ANY
5
+ OpenAI-compatible client (ours) and scores via the rubric — so we don't reimplement
6
+ rollouts/parsers/scoring. This adapter maps its ``GenerateOutputs`` into our
7
+ version-pinned eval sample shape and pushes it through ``GatewayEvalsClient``.
8
+
9
+ Verified against verifiers ``Environment.evaluate`` →
10
+ ``GenerateOutputs{outputs: list[RolloutOutput], metadata}``; each ``RolloutOutput``
11
+ carries ``prompt / completion / answer / reward`` and the named sub-rewards in
12
+ ``metrics: dict[str, float]``. ``example_id`` is declared on ``RolloutOutput`` but
13
+ may be absent on rows produced by ``evaluate_sync``; the mapper falls back to a
14
+ positional example index derived from ``metadata.rollouts_per_example``.
15
+
16
+ The verifiers import is lazy (optional dependency); the mappers are pure + tested.
17
+
18
+ NOTE (verifiers v1): this adapter drives the LEGACY v0 API (`load_environment` +
19
+ `Environment.evaluate_sync`), which the v1 release froze — it only keeps working
20
+ with `verifiers<1.0.0` installed. v1 Taskset packages (`verifiers.v1` namespace,
21
+ detected as kind "verifiers-v1" by `detect_env_kind`) are run by the platform
22
+ benchmark runner's verifiers-v1 engine (deploy/benchmark-runner/engines/
23
+ verifiers_v1.py); a v1 in-process path here is a deliberate non-goal until the
24
+ v1 API settles.
25
+ """
26
+
27
+ from __future__ import annotations
28
+
29
+ import json
30
+ from typing import Any, Dict, List, Optional
31
+
32
+ from .evals import EvalHarvestError, GatewayEvalsClient
33
+
34
+
35
+ def _get(obj: Any, key: str, default: Any = None) -> Any:
36
+ """Read a field from a dict (TypedDict) or an attribute object."""
37
+ if isinstance(obj, dict):
38
+ return obj.get(key, default)
39
+ return getattr(obj, key, default)
40
+
41
+
42
+ def _as_text(value: Any) -> Optional[str]:
43
+ if value is None:
44
+ return None
45
+ if isinstance(value, str):
46
+ return value
47
+ try:
48
+ return json.dumps(value, default=str)
49
+ except Exception:
50
+ return str(value)
51
+
52
+
53
+ def _rollouts(outputs: Any) -> List[Any]:
54
+ return _get(outputs, "outputs", []) or []
55
+
56
+
57
+ def samples_from_generate_outputs(outputs: Any) -> List[Dict[str, Any]]:
58
+ """Map verifiers ``GenerateOutputs`` → our eval-sample dicts. The per-rollout
59
+ ``metrics`` (named rubric components) become the multi-reward ``rewards`` map.
60
+
61
+ ``rolloutIndex`` is the occurrence of a rollout *within its example*. verifiers'
62
+ ``RolloutOutput`` lists ``example_id`` as a field, but rows produced by
63
+ ``evaluate_sync`` are not guaranteed to carry it as a top-level key — so when it
64
+ is missing we fall back to the positional example index
65
+ (``i // rollouts_per_example``) instead of letting every id collapse to the string
66
+ ``"None"``, which would flatten all rollout indices into one monotonic run across
67
+ the whole batch."""
68
+ rollouts = _rollouts(outputs)
69
+ rpe = int(_get(_get(outputs, "metadata", {}) or {}, "rollouts_per_example", 1) or 1)
70
+ if rpe <= 0:
71
+ rpe = 1
72
+ seen: Dict[str, int] = {}
73
+ samples: List[Dict[str, Any]] = []
74
+ for i, r in enumerate(rollouts):
75
+ raw_example_id = _get(r, "example_id")
76
+ example_id = str(raw_example_id if raw_example_id is not None else i // rpe)
77
+ idx = seen.get(example_id, 0)
78
+ seen[example_id] = idx + 1
79
+
80
+ reward = _get(r, "reward")
81
+ answer = _get(r, "answer")
82
+ sample: Dict[str, Any] = {
83
+ "exampleId": example_id,
84
+ "rolloutIndex": idx,
85
+ "prompt": _as_text(_get(r, "prompt")),
86
+ "completion": _as_text(_get(r, "completion")),
87
+ "answer": answer if isinstance(answer, str) else _as_text(answer),
88
+ "reward": float(reward) if reward is not None else None,
89
+ "score": float(reward) if reward is not None else None,
90
+ "rewards": _get(r, "metrics") or {}, # named sub-rewards
91
+ "info": _get(r, "info") or {},
92
+ }
93
+ samples.append({k: v for k, v in sample.items() if v is not None})
94
+ return samples
95
+
96
+
97
+ def metrics_from_generate_outputs(outputs: Any) -> Dict[str, Any]:
98
+ """Aggregate metrics: average reward + average of each named sub-reward."""
99
+ rollouts = _rollouts(outputs)
100
+ rewards = [float(_get(r, "reward")) for r in rollouts if _get(r, "reward") is not None]
101
+ by_metric: Dict[str, List[float]] = {}
102
+ for r in rollouts:
103
+ for name, value in (_get(r, "metrics") or {}).items():
104
+ if isinstance(value, (int, float)):
105
+ by_metric.setdefault(name, []).append(float(value))
106
+
107
+ def _mean(xs: List[float]) -> Optional[float]:
108
+ return sum(xs) / len(xs) if xs else None
109
+
110
+ return {
111
+ "n": len(rollouts),
112
+ "avg_reward": _mean(rewards),
113
+ "metrics": {name: _mean(vals) for name, vals in by_metric.items()},
114
+ }
115
+
116
+
117
+ def write_results_artifact(outputs: Any, config: Any, results_path: Any) -> Dict[str, Any]:
118
+ """Write the verifiers-compatible on-disk artifact for a completed run —
119
+ ``results.jsonl`` (raw rollout rows, keyed on ``example_id`` for resume) +
120
+ ``metadata.json`` (config + aggregates). ``config`` is an ``EvalConfig``.
121
+ Returns the metadata dict."""
122
+ from .save_utils import save_metadata, save_outputs
123
+
124
+ save_outputs(results_path, _rollouts(outputs), mode="w")
125
+ agg = metrics_from_generate_outputs(outputs)
126
+ metadata: Dict[str, Any] = {
127
+ "env_id": config.env_id,
128
+ "model": config.model,
129
+ "num_examples": config.num_examples,
130
+ "rollouts_per_example": config.rollouts_per_example,
131
+ "shuffle": config.shuffle,
132
+ "shuffle_seed": config.shuffle_seed,
133
+ "n": agg.get("n"),
134
+ "avg_reward": agg.get("avg_reward"),
135
+ "avg_metrics": agg.get("metrics"),
136
+ }
137
+ save_metadata(results_path, metadata)
138
+ return metadata
139
+
140
+
141
+ def _adapt_client(client: Any) -> Any:
142
+ """Bridge verifiers' client API drift. Older releases take a raw (Async)OpenAI
143
+ client; 0.1.14+ requires its own Client/ClientConfig ("Unsupported client
144
+ type"). Map a raw client's base_url onto a ClientConfig, keyed by the env
145
+ var that holds the matching API key (ClientConfig reads the key from the
146
+ environment by NAME)."""
147
+ try:
148
+ from verifiers.clients import Client # noqa: WPS433 — new-style verifiers only
149
+ from verifiers.types import ClientConfig # noqa: WPS433
150
+ except Exception: # noqa: BLE001 — old verifiers: raw clients accepted
151
+ return client
152
+ if isinstance(client, (Client, ClientConfig)):
153
+ return client
154
+ base_url = str(getattr(client, "base_url", "") or "")
155
+ api_key_var = (
156
+ "OPENAI_API_KEY" if "api.openai.com" in base_url else "OPENROUTER_API_KEY"
157
+ )
158
+ return ClientConfig(
159
+ client_type="openai_chat_completions",
160
+ api_base_url=base_url or "https://openrouter.ai/api/v1",
161
+ api_key_var=api_key_var,
162
+ )
163
+
164
+
165
+ def score_environment(
166
+ env: Any,
167
+ *,
168
+ client: Any,
169
+ model: str,
170
+ num_examples: int = -1,
171
+ rollouts_per_example: int = 1,
172
+ **kwargs: Any,
173
+ ) -> Any:
174
+ """Run a verifiers environment and return its ``GenerateOutputs``. `env` is an
175
+ already-loaded Environment, or an env id/name resolvable by
176
+ ``verifiers.load_environment`` (a local container must be installed first)."""
177
+ if isinstance(env, str):
178
+ try:
179
+ import verifiers as vf
180
+ except ImportError as e: # pragma: no cover - optional dep
181
+ raise EvalHarvestError(
182
+ 'verifiers is not installed — `pip install "verifiers<1.0.0"` to '
183
+ "score environments (this adapter drives the legacy v0 "
184
+ "Environment API, which v1 froze), or pass an already-loaded "
185
+ "Environment."
186
+ ) from e
187
+ if not hasattr(vf, "load_environment"):
188
+ # verifiers v1 dropped the frozen v0 loader — this adapter is v0-only.
189
+ raise EvalHarvestError(
190
+ "the installed verifiers has no load_environment — it looks like "
191
+ "verifiers v1, whose Taskset API this v0 adapter does not drive. "
192
+ 'Pin `verifiers<1.0.0` for v0 environments, or run v1 Taskset '
193
+ "packages through the platform runner's verifiers-v1 engine."
194
+ )
195
+ env = vf.load_environment(env)
196
+ if not hasattr(env, "evaluate_sync"):
197
+ if callable(getattr(env, "load", None)):
198
+ # v1 Tasksets expose load() -> list[Task] instead of evaluate_sync.
199
+ raise EvalHarvestError(
200
+ "env looks like a verifiers v1 Taskset (has load(), no "
201
+ "evaluate_sync). This adapter drives the legacy v0 Environment "
202
+ "API only — run v1 Taskset packages through the platform "
203
+ "runner's verifiers-v1 engine, or pin `verifiers<1.0.0` and "
204
+ "expose a v0 load_environment()."
205
+ )
206
+ raise EvalHarvestError("env is not a verifiers Environment (no evaluate_sync method).")
207
+ return env.evaluate_sync(
208
+ client=_adapt_client(client),
209
+ model=model,
210
+ num_examples=num_examples,
211
+ rollouts_per_example=rollouts_per_example,
212
+ **kwargs,
213
+ )
214
+
215
+
216
+ def run_and_harvest(
217
+ env: Any,
218
+ version_id: str,
219
+ evals_client: GatewayEvalsClient,
220
+ *,
221
+ client: Any,
222
+ model: str,
223
+ num_examples: int = -1,
224
+ rollouts_per_example: int = 1,
225
+ run_id: Optional[str] = None,
226
+ **kwargs: Any,
227
+ ) -> Dict[str, Any]:
228
+ """Score a verifiers container version and harvest a version-pinned evaluation
229
+ into Gateway: evaluate → create → push samples → finalize with metrics."""
230
+ outputs = score_environment(
231
+ env,
232
+ client=client,
233
+ model=model,
234
+ num_examples=num_examples,
235
+ rollouts_per_example=rollouts_per_example,
236
+ **kwargs,
237
+ )
238
+ samples = samples_from_generate_outputs(outputs)
239
+ metrics = metrics_from_generate_outputs(outputs)
240
+
241
+ evaluation_id = evals_client.create_evaluation(
242
+ version_id,
243
+ model=model,
244
+ run_id=run_id,
245
+ # Samples are one row PER ROLLOUT — count distinct examples, not rows,
246
+ # or the UI's "N examples × k rollouts" double-counts by k.
247
+ num_examples=(num_examples if num_examples > 0 else len({s.get("exampleId") for s in samples})),
248
+ rollouts_per_example=rollouts_per_example,
249
+ )
250
+ inserted = evals_client.push_samples(evaluation_id, samples)
251
+ evals_client.finalize_evaluation(evaluation_id, metrics=metrics)
252
+
253
+ return {
254
+ "evaluationId": evaluation_id,
255
+ "samples": inserted,
256
+ "metrics": metrics,
257
+ }
258
+
259
+
260
+ def run_local_eval(
261
+ env: Any,
262
+ version_id: str,
263
+ evals_client: GatewayEvalsClient,
264
+ *,
265
+ client: Any,
266
+ config: Any,
267
+ run_id: Optional[str] = None,
268
+ ) -> Dict[str, Any]:
269
+ """Run a local verifiers eval driven by an ``EvalConfig``, writing a resumable
270
+ on-disk artifact (``results.jsonl`` + ``metadata.json``) when
271
+ ``config.save_results`` and harvesting a version-pinned evaluation into Gateway.
272
+
273
+ Resume: ``config.resume_path`` uses that dir; otherwise, when saving, it reuses
274
+ the newest matching incomplete run (or starts a fresh one). NOTE: v1 saves the
275
+ whole run at the end (resume across runs), not mid-``evaluate_sync``.
276
+ """
277
+ from pathlib import Path
278
+
279
+ from .path_utils import (
280
+ find_latest_incomplete_eval_results_path,
281
+ get_results_path,
282
+ )
283
+
284
+ results_path = None
285
+ if config.resume_path:
286
+ results_path = Path(config.resume_path)
287
+ elif config.save_results:
288
+ results_path = find_latest_incomplete_eval_results_path(
289
+ config.output_dir,
290
+ config.env_id,
291
+ config.model,
292
+ config.num_examples,
293
+ config.rollouts_per_example,
294
+ config.shuffle,
295
+ config.shuffle_seed,
296
+ ) or get_results_path(config.output_dir, config.env_id, config.model)
297
+
298
+ outputs = score_environment(
299
+ env,
300
+ client=client,
301
+ model=config.model,
302
+ num_examples=config.num_examples,
303
+ rollouts_per_example=config.rollouts_per_example,
304
+ )
305
+
306
+ if results_path is not None:
307
+ write_results_artifact(outputs, config, results_path)
308
+
309
+ samples = samples_from_generate_outputs(outputs)
310
+ metrics = metrics_from_generate_outputs(outputs)
311
+ evaluation_id = evals_client.create_evaluation(
312
+ version_id,
313
+ model=config.model,
314
+ run_id=run_id,
315
+ # Distinct examples, not rollout rows (see run_and_harvest).
316
+ num_examples=(config.num_examples if config.num_examples > 0 else len({s.get("exampleId") for s in samples})),
317
+ rollouts_per_example=config.rollouts_per_example,
318
+ )
319
+ inserted = evals_client.push_samples(evaluation_id, samples)
320
+ evals_client.finalize_evaluation(evaluation_id, metrics=metrics)
321
+
322
+ return {
323
+ "evaluationId": evaluation_id,
324
+ "samples": inserted,
325
+ "metrics": metrics,
326
+ "resultsPath": str(results_path) if results_path else None,
327
+ }
@@ -0,0 +1,72 @@
1
+ """Semantic-version bump helpers for `bench push --auto-bump/--rc/--post`.
2
+
3
+ The bump functions and the pyproject rewrite are ported verbatim from Prime
4
+ Intellect's ``prime`` CLI (``packages/prime/src/prime_cli/commands/env.py``,
5
+ MIT (c) 2025 Prime Intellect) — see ``_archive.py`` for the same attribution. The
6
+ rewrite is a raw-text regex substitution (not a TOML re-dump) so comments and
7
+ formatting in ``pyproject.toml`` are preserved.
8
+
9
+ Stdlib only (``re``).
10
+ """
11
+
12
+ from __future__ import annotations
13
+
14
+ import re
15
+ from pathlib import Path
16
+
17
+
18
+ def bump_version(version: str) -> str:
19
+ """Patch bump: ``1.2.3`` -> ``1.2.4``. Strips a ``-``/``+`` pre-release/build
20
+ suffix to find the numeric patch; a non-numeric patch appends ``.1``."""
21
+ parts = version.split(".")
22
+ if len(parts) >= 3:
23
+ patch_part = parts[2]
24
+ if "-" in patch_part:
25
+ patch_num = patch_part.split("-")[0]
26
+ elif "+" in patch_part:
27
+ patch_num = patch_part.split("+")[0]
28
+ else:
29
+ patch_num = patch_part
30
+ try:
31
+ parts[2] = str(int(patch_num) + 1)
32
+ return ".".join(parts)
33
+ except ValueError:
34
+ return f"{version}.1"
35
+ elif len(parts) == 2:
36
+ return f"{version}.1"
37
+ else:
38
+ return f"{version}.0.1"
39
+
40
+
41
+ def bump_rc_version(version: str) -> str:
42
+ """Release-candidate bump: ``1.2.3`` -> ``1.2.3.rc0``, ``1.2.3.rc0`` ->
43
+ ``1.2.3.rc1`` (Prime's docstring wrongly says ``.post``; the code does ``.rc``)."""
44
+ m = re.match(r"^(?P<base>.*?)(?:\.rc|rc)(?P<num>\d+)$", version)
45
+ if m:
46
+ return f"{m.group('base')}.rc{int(m.group('num')) + 1}"
47
+ return f'{re.sub(r"([+-].*)$", "", version)}.rc0'
48
+
49
+
50
+ def bump_post_version(version: str) -> str:
51
+ """Post-release bump: ``1.2.3`` -> ``1.2.3.post0``, ``1.2.3.post0`` ->
52
+ ``1.2.3.post1``."""
53
+ m = re.match(r"^(?P<base>.*?)(?:\.post|post)(?P<num>\d+)$", version)
54
+ if m:
55
+ return f"{m.group('base')}.post{int(m.group('num')) + 1}"
56
+ return f'{re.sub(r"([+-].*)$", "", version)}.post0'
57
+
58
+
59
+ def update_pyproject_version(pyproject_path: Path, new_version: str) -> None:
60
+ """Rewrite the ``version = "..."`` line in pyproject.toml via regex (preserving
61
+ formatting/comments). Raises ``ValueError`` if no version line is present."""
62
+ pyproject_path = Path(pyproject_path)
63
+ content = pyproject_path.read_text()
64
+ updated = re.sub(
65
+ r'(\s*)version\s*=\s*["\'][^"\']*["\']',
66
+ rf'\1version = "{new_version}"',
67
+ content,
68
+ flags=re.MULTILINE,
69
+ )
70
+ if updated == content:
71
+ raise ValueError("version line not found or unchanged in pyproject.toml")
72
+ pyproject_path.write_text(updated)