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,111 @@
1
+ """Automations client for Gateway public REST API."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Any, Dict, List, Mapping, MutableMapping, Optional
6
+ from urllib import parse
7
+
8
+ import requests
9
+
10
+
11
+ class AutomationClientError(RuntimeError):
12
+ """Raised when the Gateway automations API returns an error response."""
13
+
14
+ def __init__(self, message: str, *, status_code: Optional[int] = None, body: Optional[str] = None) -> None:
15
+ super().__init__(message)
16
+ self.status_code = status_code
17
+ self.body = body
18
+
19
+
20
+ class AutomationClient:
21
+ """HTTP client for project-scoped automations endpoints (Basic auth)."""
22
+
23
+ def __init__(self, base_url: str, public_key: str, secret_key: str, *, timeout_seconds: float = 60.0) -> None:
24
+ self._base = base_url.rstrip("/")
25
+ self._timeout = timeout_seconds
26
+ self._session = requests.Session()
27
+ self._session.auth = (public_key, secret_key)
28
+ self._session.headers.update({"Accept": "application/json"})
29
+
30
+ def _request(
31
+ self,
32
+ method: str,
33
+ path: str,
34
+ *,
35
+ query: Optional[Mapping[str, Any]] = None,
36
+ json_body: Optional[MutableMapping[str, Any]] = None,
37
+ ) -> Any:
38
+ url = f"{self._base}{path}"
39
+ params = {k: v for k, v in (query or {}).items() if v is not None}
40
+ try:
41
+ resp = self._session.request(
42
+ method,
43
+ url,
44
+ params=params or None,
45
+ json=json_body,
46
+ timeout=self._timeout,
47
+ )
48
+ except requests.RequestException as exc:
49
+ raise AutomationClientError(f"Automations HTTP request failed for {path}: {exc}") from exc
50
+
51
+ try:
52
+ out = resp.json() if resp.content else {}
53
+ except ValueError:
54
+ out = {}
55
+
56
+ if not resp.ok:
57
+ msg = str(out.get("message", resp.reason or resp.text))
58
+ raise AutomationClientError(
59
+ f"Gateway automations API error {resp.status_code} on {path}: {msg}",
60
+ status_code=resp.status_code,
61
+ body=resp.text,
62
+ )
63
+ return out
64
+
65
+ def list(self) -> List[Dict[str, Any]]:
66
+ """GET /api/public/automations — list automations for the authenticated project."""
67
+ out = self._request("GET", "/api/public/automations")
68
+ if not isinstance(out, dict):
69
+ raise AutomationClientError(f"Unexpected list() response shape: {type(out).__name__}")
70
+ data = out.get("automations")
71
+ if not isinstance(data, list):
72
+ raise AutomationClientError("Response missing 'automations' array")
73
+ return [dict(x) for x in data if isinstance(x, dict)]
74
+
75
+ def create(
76
+ self,
77
+ name: str,
78
+ trigger_config: Mapping[str, Any],
79
+ action_config: Mapping[str, Any],
80
+ ) -> Dict[str, Any]:
81
+ """POST /api/public/automations — create trigger, action, and automation."""
82
+ body = {"name": name, "trigger": dict(trigger_config), "action": dict(action_config)}
83
+ out = self._request("POST", "/api/public/automations", json_body=body)
84
+ if not isinstance(out, dict):
85
+ raise AutomationClientError(f"Unexpected create() response shape: {type(out).__name__}")
86
+ return dict(out)
87
+
88
+ def trigger(self, automation_id: str, payload: Optional[Mapping[str, Any]] = None) -> Dict[str, Any]:
89
+ """POST /api/public/automations/{id}/trigger — enqueue a manual run; optional JSON body becomes execution input."""
90
+ path = f"/api/public/automations/{parse.quote(automation_id, safe='')}/trigger"
91
+ out = self._request("POST", path, json_body=dict(payload) if payload is not None else {})
92
+ if not isinstance(out, dict):
93
+ raise AutomationClientError(f"Unexpected trigger() response shape: {type(out).__name__}")
94
+ return dict(out)
95
+
96
+ def get_executions(
97
+ self,
98
+ automation_id: str,
99
+ *,
100
+ limit: int = 50,
101
+ offset: int = 0,
102
+ ) -> List[Dict[str, Any]]:
103
+ """GET /api/public/automations/{id}/executions — paginated execution history."""
104
+ path = f"/api/public/automations/{parse.quote(automation_id, safe='')}/executions"
105
+ out = self._request("GET", path, query={"limit": limit, "offset": offset})
106
+ if not isinstance(out, dict):
107
+ raise AutomationClientError(f"Unexpected get_executions() response shape: {type(out).__name__}")
108
+ data = out.get("executions")
109
+ if not isinstance(data, list):
110
+ raise AutomationClientError("Response missing 'executions' array")
111
+ return [dict(x) for x in data if isinstance(x, dict)]
@@ -0,0 +1,88 @@
1
+ # benchmark_hub — Gateway benchmark container hub SDK
2
+
3
+ Push, version, browse, and evaluate benchmark **containers** (verifiers-format
4
+ environments) on Gateway. This is Prime Intellect's hub model ported onto the
5
+ Gateway stack: the **source bundle is the versioned, browsable source of truth**;
6
+ an OCI image is built per version for execution.
7
+
8
+ Everything here talks **only to a Gateway host** — never to `app.primeintellect.ai`.
9
+
10
+ ## Auth + config (env)
11
+
12
+ | Env var | Purpose |
13
+ |---|---|
14
+ | `GATEWAY_HOST` | Gateway base URL, e.g. `https://withgateway.ai` |
15
+ | `GATEWAY_PUBLIC_KEY` / `GATEWAY_SECRET_KEY` | project API key pair — **writes require the secret key** (Basic auth) |
16
+
17
+ Bundle storage is flexible/enterprise-overridable server-side via
18
+ `LANGFUSE_S3_BENCHMARK_UPLOAD_*` (falls back to the media-upload bucket under a
19
+ `benchmark-containers/` prefix — zero-config by default).
20
+
21
+ ## Push a container
22
+
23
+ ```python
24
+ from gatewaysdk.benchmark_hub import GatewayBenchmarkClient
25
+
26
+ client = GatewayBenchmarkClient.from_env() # GATEWAY_HOST/PUBLIC_KEY/SECRET_KEY
27
+ result = client.push("./automationbench", visibility="PUBLIC")
28
+ # resolve -> versions (presigned PUT) -> finalize
29
+ print(result) # {containerId, versionId, contentHash, state, slug, alreadyUploaded}
30
+ ```
31
+
32
+ CLI: `python -m gatewaysdk.benchmark_hub.client push ./automationbench --visibility PUBLIC`
33
+
34
+ The push computes a **source-only `content_hash`** (vendored byte-compatible with
35
+ Prime's hub) as the logical version id, builds a deterministic source tarball,
36
+ and sends the tarball's real sha256 as the S3 checksum (distinct from the content
37
+ hash — this is what makes the presigned upload succeed). The **full file tree** is
38
+ recorded separately for the browser.
39
+
40
+ ## Harvest a version-pinned evaluation
41
+
42
+ ```python
43
+ from gatewaysdk.benchmark_hub import GatewayEvalsClient
44
+
45
+ evals = GatewayEvalsClient.from_env()
46
+ eval_id = evals.create_evaluation(version_id, model="gpt-4o-mini")
47
+ evals.push_samples(eval_id, samples) # batched; multi-reward per sample
48
+ evals.finalize_evaluation(eval_id, metrics={"pass_rate": 0.87}, cost={"total_usd": 0.42})
49
+ ```
50
+
51
+ An evaluation is **pinned to the immutable container version**, so scores stay
52
+ reproducible and diffable across re-pushes. Each sample carries the overall score
53
+ **and** the named sub-reward breakdown (`rewards`), never just an average.
54
+ `normalize_sample` accepts prime-evals snake_case (`example_id`, `rollout_index`)
55
+ so a verifiers/prime `Sample` harvests unchanged.
56
+
57
+ ## Server API (under `/api/public/benchmark-containers`)
58
+
59
+ | Route | Auth | Purpose |
60
+ |---|---|---|
61
+ | `POST /resolve` | write | get-or-create a container |
62
+ | `POST /versions` | write | create/dedup a version + presigned upload |
63
+ | `POST /versions/{id}/finalize` | write | mark the source READY |
64
+ | `GET /` | read | list containers + versions |
65
+ | `GET /versions/{id}/files` | read | full file tree (browser) |
66
+ | `GET /versions/{id}/download` | read | signed URL to the source tarball |
67
+ | `POST /evaluations` | write | create a version-pinned evaluation |
68
+ | `POST /evaluations/{id}/samples` | write | append multi-reward sample batches |
69
+ | `POST /evaluations/{id}/finalize` | write | metrics + cost + status |
70
+
71
+ ## What's vendored vs ours (per the integration strategy)
72
+
73
+ - **Vendored (MIT, Prime):** the four content-hash helpers in `_archive.py` —
74
+ byte-compatible hashing for hub interop. There is no library to wrap; the rest
75
+ of Prime's hub is a CLI welded to Typer/Rich.
76
+ - **Ours:** the hub backend (schema, routes, storage), the reimplemented push +
77
+ eval clients (Prime's `prime-sandboxes`/`prime env`/hosted eval all terminate
78
+ at `api.primeintellect.ai` and aren't self-hostable).
79
+ - **Borrowed shape:** the eval client mirrors prime-evals' create→push→finalize,
80
+ harvesting into Gateway's own store.
81
+
82
+ ## Not yet wired
83
+
84
+ - **`verifiers` scoring** — for verifiers-format containers, `Environment.evaluate()`
85
+ produces the sample rows for free (the one genuinely reusable open Prime lib);
86
+ the worker that runs a finalized container should feed the eval routes from it.
87
+ - **Per-version OCI image build** — `content_hash`-tagged image so the runner can
88
+ execute the container (`generic --image`); `image_ref` stays null until then.
@@ -0,0 +1,119 @@
1
+ """Gateway benchmark-container hub SDK.
2
+
3
+ Client-side helpers for packaging a benchmark "container" (a verifiers-format
4
+ environment: ``pyproject.toml`` + source modules + README) and pushing it to the
5
+ Gateway hub for content-addressed version control.
6
+
7
+ The content-hash helpers in :mod:`._archive` are vendored verbatim from Prime
8
+ Intellect's ``prime`` CLI (MIT) so our ``content_hash`` is byte-compatible with
9
+ theirs — see that module's header for attribution.
10
+ """
11
+
12
+ from ._archive import collect_archive_files, compute_content_hash
13
+ from ._tar import safe_tar_extract
14
+ from .client import (
15
+ BenchmarkPushError,
16
+ DEFAULT_BRANCH,
17
+ GatewayBenchmarkClient,
18
+ build_file_manifest,
19
+ build_source_tarball,
20
+ build_wheel,
21
+ normalize_package_name,
22
+ parse_wheel_requires_dist,
23
+ local_tree_state,
24
+ read_local_meta,
25
+ read_pyproject,
26
+ sha256_base64,
27
+ write_local_meta,
28
+ )
29
+ from .eval_config import EvalConfig
30
+ from .evals import (
31
+ EvalHarvestError,
32
+ GatewayEvalsClient,
33
+ normalize_sample,
34
+ )
35
+ from .path_utils import (
36
+ count_saved_rollouts,
37
+ find_latest_incomplete_eval_results_path,
38
+ get_results_path,
39
+ is_valid_eval_results_path,
40
+ )
41
+ from .save_utils import (
42
+ load_metadata,
43
+ load_outputs,
44
+ save_metadata,
45
+ save_outputs,
46
+ validate_resume_metadata,
47
+ )
48
+ from .harbor_adapter import (
49
+ detect_env_kind,
50
+ find_mcp_config,
51
+ harvest_job_dir,
52
+ resolve_harbor_model,
53
+ run_harbor_job,
54
+ samples_from_job_dir,
55
+ tasks_root,
56
+ )
57
+ from .verifiers_adapter import (
58
+ metrics_from_generate_outputs,
59
+ run_and_harvest,
60
+ run_local_eval,
61
+ samples_from_generate_outputs,
62
+ score_environment,
63
+ write_results_artifact,
64
+ )
65
+ from .versioning import (
66
+ bump_post_version,
67
+ bump_rc_version,
68
+ bump_version,
69
+ update_pyproject_version,
70
+ )
71
+
72
+ __all__ = [
73
+ "compute_content_hash",
74
+ "collect_archive_files",
75
+ "safe_tar_extract",
76
+ "bump_version",
77
+ "bump_rc_version",
78
+ "bump_post_version",
79
+ "update_pyproject_version",
80
+ "GatewayBenchmarkClient",
81
+ "DEFAULT_BRANCH",
82
+ "local_tree_state",
83
+ "read_local_meta",
84
+ "write_local_meta",
85
+ "BenchmarkPushError",
86
+ "build_source_tarball",
87
+ "build_file_manifest",
88
+ "build_wheel",
89
+ "parse_wheel_requires_dist",
90
+ "normalize_package_name",
91
+ "sha256_base64",
92
+ "read_pyproject",
93
+ "GatewayEvalsClient",
94
+ "EvalHarvestError",
95
+ "normalize_sample",
96
+ "samples_from_generate_outputs",
97
+ "metrics_from_generate_outputs",
98
+ "score_environment",
99
+ "run_and_harvest",
100
+ "run_local_eval",
101
+ "write_results_artifact",
102
+ "detect_env_kind",
103
+ "tasks_root",
104
+ "run_harbor_job",
105
+ "harvest_job_dir",
106
+ "samples_from_job_dir",
107
+ "find_mcp_config",
108
+ "resolve_harbor_model",
109
+ "EvalConfig",
110
+ "save_outputs",
111
+ "load_outputs",
112
+ "save_metadata",
113
+ "load_metadata",
114
+ "validate_resume_metadata",
115
+ "get_results_path",
116
+ "is_valid_eval_results_path",
117
+ "count_saved_rollouts",
118
+ "find_latest_incomplete_eval_results_path",
119
+ ]
@@ -0,0 +1,189 @@
1
+ """Deterministic content hashing for benchmark-container source bundles.
2
+
3
+ Vendored verbatim (with only docstring/typing cosmetics) from Prime Intellect's
4
+ ``prime`` CLI so that the ``content_hash`` we compute for a container is
5
+ byte-for-byte identical to the one their Environments Hub computes for the same
6
+ files. That byte-compatibility is the whole point of copying rather than
7
+ reimplementing: a container hashed here and on hub.primeintellect.ai resolves to
8
+ the same logical version id.
9
+
10
+ Source: https://github.com/PrimeIntellect-ai/prime
11
+ packages/prime/src/prime_cli/commands/env.py (functions at L575-L689)
12
+ License: MIT (c) Prime Intellect. See THIRD_PARTY_LICENSES for the full text.
13
+
14
+ IMPORTANT: this is the *source-only* collection. Prime-compatible bundles hash
15
+ only ``README.md``, ``pyproject.toml`` and ``*.py`` at the root (plus nested
16
+ package dirs). Gateway-only bundles hash every non-hidden root file as well:
17
+ mock-tools bundles (root ``gateway-env.toml``) carry their executable contract
18
+ in root ``tasks.jsonl`` and ``tool-schemas.json``, and api worlds (root
19
+ ``gateway-api-world.toml``) carry theirs in the marker itself plus root
20
+ ``openapi.json`` — omitting any of these produced a READY bundle the platform
21
+ could not detect or execute. Dotfiles, ``__pycache__``, build outputs and
22
+ ``.gitignore``-d paths are still dropped.
23
+ The hash is the version primary key. The *full* file tree shown in the
24
+ GitHub-style browser is collected and stored separately and must NOT feed this
25
+ function, or hashes would diverge from Prime's.
26
+ """
27
+
28
+ import hashlib
29
+ import os
30
+ from pathlib import Path
31
+ from typing import Callable, Dict, List, Optional
32
+
33
+ try: # optional: only needed when a container actually ships a .gitignore
34
+ from gitignore_parser import parse_gitignore
35
+ except ImportError: # pragma: no cover - exercised only when the dep is absent
36
+ parse_gitignore = None # type: ignore[assignment]
37
+
38
+
39
+ def should_include_file_in_archive(file_path: Path, base_path: Path) -> bool:
40
+ """Return True if ``file_path`` belongs in the hashed source archive."""
41
+ if not file_path.is_file():
42
+ return False
43
+
44
+ # Skip symlinks - they cause extraction failures on the server side.
45
+ if file_path.is_symlink():
46
+ return False
47
+
48
+ rel_path = file_path.relative_to(base_path)
49
+
50
+ # Skip hidden files.
51
+ if file_path.name.startswith("."):
52
+ return False
53
+
54
+ # Skip files in __pycache__ directories.
55
+ if "__pycache__" in rel_path.parts:
56
+ return False
57
+
58
+ return True
59
+
60
+
61
+ def should_include_directory_in_archive(dir_path: Path) -> bool:
62
+ """Return True if ``dir_path`` should be traversed into the archive."""
63
+ if not dir_path.is_dir():
64
+ return False
65
+
66
+ # Skip hidden directories (includes .prime/, .git/, etc.).
67
+ if dir_path.name.startswith("."):
68
+ return False
69
+
70
+ # Skip build artifacts, cache directories, and outputs.
71
+ if dir_path.name in ["dist", "__pycache__", "build", "outputs"]:
72
+ return False
73
+
74
+ # Skip egg-info directories.
75
+ if dir_path.name.endswith(".egg-info"):
76
+ return False
77
+
78
+ return True
79
+
80
+
81
+ def _build_gitignore_matcher(env_path: Path) -> Optional[Callable[[str], bool]]:
82
+ """Build a matcher for the root .gitignore file, if present."""
83
+ gitignore_path = env_path / ".gitignore"
84
+ if not gitignore_path.exists():
85
+ return None
86
+ if parse_gitignore is None:
87
+ # Explicit failure rather than silently producing a hash that would
88
+ # diverge from Prime's by including .gitignore-d files.
89
+ raise RuntimeError(
90
+ "A .gitignore is present but 'gitignore_parser' is not installed. "
91
+ "Install it (it is a declared dependency of gatewaysdk) so the "
92
+ "content hash stays compatible with the hub."
93
+ )
94
+ return parse_gitignore(str(gitignore_path), base_dir=str(env_path))
95
+
96
+
97
+ def collect_archive_files(env_path: Path) -> List[Path]:
98
+ """Collect archive file paths in deterministic order, honoring .gitignore."""
99
+ env_path = Path(env_path) # accept str paths (CLI passes a string)
100
+ ignore_matcher = _build_gitignore_matcher(env_path)
101
+ files_by_rel_path: Dict[str, Path] = {}
102
+
103
+ def maybe_add_file(file_path: Path) -> None:
104
+ if not should_include_file_in_archive(file_path, env_path):
105
+ return
106
+ if ignore_matcher is not None and ignore_matcher(str(file_path)):
107
+ return
108
+
109
+ rel_path = str(file_path.relative_to(env_path)).replace("\\", "/")
110
+ files_by_rel_path[rel_path] = file_path
111
+
112
+ # Prime bundles keep Prime's root globs. A Gateway-only root marker widens
113
+ # them to every ordinary root file, because those kinds keep executable
114
+ # contract at the root: mock-tools (``gateway-env.toml``) in ``tasks.jsonl``
115
+ # / ``tool-schemas.json``, api worlds (``gateway-api-world.toml``) in the
116
+ # marker itself and ``openapi.json``. Include them so the archive and its
117
+ # content hash describe the complete runnable source rather than a
118
+ # READY-but-broken subset — an api world whose marker never reached the
119
+ # bundle was detected as harbor and surfaced zero tools.
120
+ #
121
+ # The manifest MUST be hashed or a manifest-only edit — changing the served
122
+ # tool list, the kind, the db, or the dependency pins — produces an identical
123
+ # hash, dedups into the previous version, and is silently discarded while
124
+ # reporting success. That made every such edit a no-op.
125
+ #
126
+ # This does not break Prime compatibility: a Prime-compatible bundle has no
127
+ # Gateway marker, so it continues to use the original globs unchanged.
128
+ root_patterns = ["README.md", "pyproject.toml", "*.py"]
129
+ if (env_path / "gateway-env.toml").is_file() or (
130
+ env_path / "gateway-api-world.toml"
131
+ ).is_file():
132
+ root_patterns.append("*")
133
+ for pattern in root_patterns:
134
+ for file_path in sorted(env_path.glob(pattern), key=lambda p: p.name):
135
+ maybe_add_file(file_path)
136
+
137
+ def is_nested_dir_ignored(dir_path: Path) -> bool:
138
+ """Check if a nested directory should be pruned from traversal."""
139
+ if not should_include_directory_in_archive(dir_path):
140
+ return True
141
+ if ignore_matcher is not None and ignore_matcher(str(dir_path)):
142
+ return True
143
+ return False
144
+
145
+ for subdir in sorted(env_path.iterdir(), key=lambda path: path.name):
146
+ if not should_include_directory_in_archive(subdir):
147
+ continue
148
+ if is_nested_dir_ignored(subdir):
149
+ continue
150
+
151
+ for root, dirnames, filenames in os.walk(subdir):
152
+ root_path = Path(root)
153
+ dirnames[:] = sorted(
154
+ dirname for dirname in dirnames if not is_nested_dir_ignored(root_path / dirname)
155
+ )
156
+ for filename in sorted(filenames):
157
+ maybe_add_file(root_path / filename)
158
+
159
+ return [files_by_rel_path[rel_path] for rel_path in sorted(files_by_rel_path)]
160
+
161
+
162
+ def compute_content_hash(env_path: Path) -> str:
163
+ """Compute a deterministic, cross-platform content hash for a container.
164
+
165
+ SHA-256 over each included file's normalized relative path (prefixed with
166
+ ``file:``) followed by its raw bytes, in sorted path order. This is a
167
+ *logical* digest of the source set — NOT the sha256 of any tarball object,
168
+ so it cannot double as an S3 upload checksum.
169
+
170
+ Args:
171
+ env_path: Path to the container directory.
172
+
173
+ Returns:
174
+ SHA-256 hexdigest of the container content.
175
+ """
176
+ env_path = Path(env_path) # accept str paths (CLI passes a string)
177
+ content_hasher = hashlib.sha256()
178
+
179
+ for file_path in collect_archive_files(env_path):
180
+ normalized_path = str(file_path.relative_to(env_path)).replace("\\", "/")
181
+ content_hasher.update(f"file:{normalized_path}".encode("utf-8"))
182
+ try:
183
+ with open(file_path, "rb") as f:
184
+ content_hasher.update(f.read())
185
+ except IOError:
186
+ # Skip files that can't be read.
187
+ pass
188
+
189
+ return content_hasher.hexdigest()
@@ -0,0 +1,6 @@
1
+ """Guarded tar extraction; the implementation lives in ``gatewaysdk.environment._tar``
2
+ so the World Host image, which ships the environment package alone, has it too."""
3
+
4
+ from ..environment._tar import safe_tar_extract
5
+
6
+ __all__ = ["safe_tar_extract"]