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
gatewaysdk/build.py ADDED
@@ -0,0 +1,515 @@
1
+ """Agent build identity — "the agent IS the manifest."
2
+
3
+ There is no build file and no lockfile. As the agent constructs itself, the
4
+ SDK observes everything that defines a build: tools registered through
5
+ :func:`define_tool` (name, declared version, effects, auto schema hash,
6
+ source location), prompts registered through :func:`register_prompt`, the
7
+ code ref from CI/env, and the SDK's own version. ``tracing.init(agent=...,
8
+ version=...)`` assembles the canonical manifest, computes the
9
+ content-addressed build hash, stamps ``gateway.build.hash`` on every span,
10
+ and auto-registers the build with Gateway (idempotent on hash — every
11
+ replica of the same code is one build). Releases are label moves on the
12
+ platform, never mutations here.
13
+
14
+ v1 versioning is developer-declared: you bump ``version`` on the agent and
15
+ on tools; Gateway records schema hashes as evidence alongside.
16
+
17
+ Mirrors ``@withgateway/sdk``'s ``src/build`` 1:1.
18
+ """
19
+
20
+ from __future__ import annotations
21
+
22
+ import functools
23
+ import hashlib
24
+ import inspect
25
+ import json
26
+ import logging
27
+ import os
28
+ import re
29
+ import threading
30
+ from typing import Any, Callable, Optional, TypeVar
31
+
32
+ logger = logging.getLogger("gatewaysdk.build")
33
+
34
+ F = TypeVar("F", bound=Callable[..., Any])
35
+
36
+ _registered_tools: dict[str, dict[str, Any]] = {}
37
+ _registered_prompts: dict[str, str] = {}
38
+ _registered_skills: dict[str, str] = {}
39
+ _registered_artifacts: dict[str, dict[str, Any]] = {}
40
+ _active_build_hash: Optional[str] = None
41
+
42
+ # Late registration: agents often build tool maps AFTER init. Registered
43
+ # contexts get a debounced re-registration whenever the registry changes —
44
+ # content-addressed and idempotent; traces keep the init-time hash.
45
+ _active_contexts: list[dict[str, Any]] = []
46
+ _reregister_timer: Optional[threading.Timer] = None
47
+ _RE_REGISTER_DEBOUNCE_S = 3.0
48
+
49
+
50
+ def _notify_registry_changed() -> None:
51
+ global _reregister_timer
52
+ if not _active_contexts:
53
+ return
54
+ if _reregister_timer is not None:
55
+ _reregister_timer.cancel()
56
+
57
+ def _rerun() -> None:
58
+ global _reregister_timer
59
+ _reregister_timer = None
60
+ for context in list(_active_contexts):
61
+ manifest = assemble_manifest(context["agent_id"])
62
+ build_hash = compute_build_hash(manifest)
63
+ if build_hash == context.get("last_hash"):
64
+ continue
65
+ context["last_hash"] = build_hash
66
+ _post_build(context, manifest, build_hash)
67
+
68
+ _reregister_timer = threading.Timer(_RE_REGISTER_DEBOUNCE_S, _rerun)
69
+ _reregister_timer.daemon = True
70
+ _reregister_timer.start()
71
+
72
+
73
+ def canonical_json(value: Any) -> str:
74
+ """Deterministic JSON: keys sorted recursively, arrays kept in order."""
75
+ # ensure_ascii=False matches JavaScript JSON.stringify (no \uXXXX escapes),
76
+ # so the SAME agent hashes identically from either SDK.
77
+ return json.dumps(
78
+ value, sort_keys=True, separators=(",", ":"), ensure_ascii=False, default=str
79
+ )
80
+
81
+
82
+ def _sha256(text: str) -> str:
83
+ return "sha256:" + hashlib.sha256(text.encode("utf-8")).hexdigest()
84
+
85
+
86
+ def _capture_source() -> Optional[str]:
87
+ """First app-code frame ("src/tools/checkout.py:42").
88
+
89
+ Skips only the SDK's OWN frames (this module, installed package) — not
90
+ every path containing "gatewaysdk", or apps developed inside a monorepo
91
+ next to the SDK would never resolve a source.
92
+ """
93
+ for frame_info in inspect.stack()[1:]:
94
+ filename = frame_info.filename.replace("\\", "/")
95
+ if filename.endswith("gatewaysdk/build.py"):
96
+ continue
97
+ if "site-packages/gatewaysdk/" in filename:
98
+ continue
99
+ if filename.startswith("<"):
100
+ continue
101
+ parts = filename.split("/")
102
+ short = "/".join(parts[-4:]) if len(parts) > 4 else filename
103
+ return f"{short}:{frame_info.lineno}"
104
+ return None
105
+
106
+
107
+ # Ambient environment interception (gatewaysdk.environment, spec §4.4): the
108
+ # environment package installs ONE process-wide interceptor; the define_tool
109
+ # wrapper consults it per call. Returning the sentinel means "not intercepted —
110
+ # run the original function" (the identity path; also taken whenever no
111
+ # interceptor is installed or no world is active).
112
+ _TOOL_INTERCEPT_MISS = object()
113
+ _tool_call_interceptor: Optional[Callable[[str, Callable[..., Any], tuple, dict], Any]] = None
114
+
115
+
116
+ def set_tool_call_interceptor(
117
+ interceptor: Optional[Callable[[str, Callable[..., Any], tuple, dict], Any]],
118
+ ) -> None:
119
+ """Install (or clear, with ``None``) the ambient tool-call interceptor.
120
+
121
+ Called by ``gatewaysdk.environment`` — not user-facing. The interceptor
122
+ receives ``(tool_name, original_fn, args, kwargs)`` and returns either the
123
+ call's result or :data:`_TOOL_INTERCEPT_MISS` to fall through.
124
+ """
125
+ global _tool_call_interceptor
126
+ _tool_call_interceptor = interceptor
127
+
128
+
129
+ def define_tool(
130
+ name: str,
131
+ *,
132
+ version: Optional[str] = None,
133
+ effects: Optional[str] = None, # "read" | "write" | "irreversible"
134
+ schema: Optional[Any] = None,
135
+ description: Optional[str] = None,
136
+ ) -> Callable[[F], F]:
137
+ """Register a tool's identity; usable as a decorator.
138
+
139
+ Example::
140
+
141
+ @define_tool("checkout", version="2.1", effects="write",
142
+ schema=CHECKOUT_SCHEMA, description="Complete a purchase")
143
+ def checkout(cart_id: str) -> str: ...
144
+
145
+ Or imperatively: ``define_tool("checkout", version="2.1", schema=...)(fn)``.
146
+
147
+ The returned callable behaves identically to ``fn`` (``functools.wraps``
148
+ preserves its attributes) — EXCEPT inside an active mock environment
149
+ (``with env:`` from ``gatewaysdk.environment``), where calls routed to the
150
+ env execute against the mock world instead of the original function. This
151
+ ambient seam is spec §4.4; outside an active world the wrapper is a
152
+ zero-behavior-change passthrough.
153
+ """
154
+ source = _capture_source()
155
+ identity: dict[str, Any] = {
156
+ "name": name,
157
+ "schemaHash": _sha256(
158
+ canonical_json({"schema": schema, "description": description or ""})
159
+ ),
160
+ }
161
+ if version is not None:
162
+ identity["version"] = version
163
+ if effects is not None:
164
+ identity["effects"] = effects
165
+ if description is not None:
166
+ identity["description"] = description[:500]
167
+ if source is not None:
168
+ identity["source"] = source
169
+ _registered_tools[name] = identity
170
+ _notify_registry_changed()
171
+
172
+ def _decorator(fn: F) -> F:
173
+ @functools.wraps(fn)
174
+ def _tool_wrapper(*args: Any, **kwargs: Any) -> Any:
175
+ interceptor = _tool_call_interceptor
176
+ if interceptor is not None:
177
+ outcome = interceptor(name, fn, args, kwargs)
178
+ if outcome is not _TOOL_INTERCEPT_MISS:
179
+ return outcome
180
+ return fn(*args, **kwargs)
181
+
182
+ return _tool_wrapper # type: ignore[return-value]
183
+
184
+ return _decorator
185
+
186
+
187
+ def register_prompt(
188
+ name: str, content: str, *, version: Optional[str] = None
189
+ ) -> str:
190
+ """Register a code-shipped prompt so it joins the build identity.
191
+
192
+ ``SYSTEM = register_prompt("system", "You are…")`` — returns the content
193
+ unchanged. Platform-served prompts don't need this; pin them by label.
194
+ """
195
+ _registered_prompts[name] = _sha256(content)
196
+ register_artifact("prompt", name, version=version, content=content)
197
+ return content
198
+
199
+
200
+ def register_artifact(
201
+ kind: str,
202
+ name: str,
203
+ *,
204
+ version: Optional[str] = None,
205
+ content: Optional[str] = None,
206
+ ref: Optional[str] = None,
207
+ metadata: Optional[dict[str, str]] = None,
208
+ ) -> dict[str, Any]:
209
+ """Version ANY artifact the agent is built from — the generic primitive
210
+ behind register_prompt/register_skill. ``content`` hashes locally
211
+ (off-platform); ``ref`` pins a platform-hosted artifact
212
+ ("prompt/system@label:production")."""
213
+ source = _capture_source()
214
+ identity: dict[str, Any] = {"kind": kind, "name": name}
215
+ if version is not None:
216
+ identity["version"] = version
217
+ if content is not None:
218
+ identity["contentHash"] = _sha256(content)
219
+ if ref is not None:
220
+ identity["ref"] = ref
221
+ if source is not None:
222
+ identity["source"] = source
223
+ if metadata:
224
+ identity["metadata"] = metadata
225
+ _registered_artifacts[f"{kind}:{name}"] = identity
226
+ _notify_registry_changed()
227
+ return identity
228
+
229
+
230
+ def get_registered_artifacts() -> list[dict[str, Any]]:
231
+ return sorted(
232
+ _registered_artifacts.values(), key=lambda a: (a["kind"], a["name"])
233
+ )
234
+
235
+
236
+ def register_skill(
237
+ name: str,
238
+ version: str,
239
+ *,
240
+ content: Optional[str] = None,
241
+ ref: Optional[str] = None,
242
+ ) -> None:
243
+ """Register a skill's identity — ``register_skill("triage", "1.0")`` —
244
+ so skills are versioned in the build like tools and prompts."""
245
+ _registered_skills[name] = version
246
+ register_artifact("skill", name, version=version, content=content, ref=ref)
247
+
248
+
249
+ def get_registered_skills() -> dict[str, str]:
250
+ return dict(sorted(_registered_skills.items()))
251
+
252
+
253
+ def get_registered_tools() -> list[dict[str, Any]]:
254
+ return sorted(_registered_tools.values(), key=lambda t: t["name"])
255
+
256
+
257
+ def get_registered_prompts() -> dict[str, str]:
258
+ return dict(sorted(_registered_prompts.items()))
259
+
260
+
261
+ def reset_build_registry() -> None:
262
+ """Test hook."""
263
+ global _active_build_hash, _reregister_timer
264
+ _registered_tools.clear()
265
+ _registered_prompts.clear()
266
+ _registered_skills.clear()
267
+ _registered_artifacts.clear()
268
+ _active_contexts.clear()
269
+ if _reregister_timer is not None:
270
+ _reregister_timer.cancel()
271
+ _reregister_timer = None
272
+ _active_build_hash = None
273
+
274
+
275
+ def _sdk_version() -> str:
276
+ try:
277
+ from importlib.metadata import version
278
+
279
+ return f"gatewaysdk=={version('gatewaysdk')}"
280
+ except Exception:
281
+ return "gatewaysdk"
282
+
283
+
284
+ def _paas_git_context() -> Optional[dict[str, Any]]:
285
+ """Git context most PaaS runtimes inject automatically (Vercel, Render,
286
+ Railway, Netlify, Heroku). On those hosts attribution is fully
287
+ zero-config — no GATEWAY_* or GITHUB_* env plumbing needed. Explicit
288
+ env vars always win; this only fills gaps."""
289
+ if os.getenv("VERCEL_GIT_COMMIT_SHA"):
290
+ # Only surface the repo when it's GitHub-shaped — enrichment is
291
+ # GitHub-only; a GitLab/Bitbucket repo would just 404 over there.
292
+ is_github = (os.getenv("VERCEL_GIT_PROVIDER") or "github") == "github"
293
+ owner = os.getenv("VERCEL_GIT_REPO_OWNER")
294
+ slug = os.getenv("VERCEL_GIT_REPO_SLUG")
295
+ return {
296
+ "provider": "vercel",
297
+ "sha": os.getenv("VERCEL_GIT_COMMIT_SHA"),
298
+ "repo": f"{owner}/{slug}" if is_github and owner and slug else None,
299
+ "branch": os.getenv("VERCEL_GIT_COMMIT_REF"),
300
+ "login": os.getenv("VERCEL_GIT_COMMIT_AUTHOR_LOGIN"),
301
+ }
302
+ if os.getenv("RENDER_GIT_COMMIT"):
303
+ return {
304
+ "provider": "render",
305
+ "sha": os.getenv("RENDER_GIT_COMMIT"),
306
+ "repo": os.getenv("RENDER_GIT_REPO_SLUG"), # already "owner/repo"
307
+ "branch": os.getenv("RENDER_GIT_BRANCH"),
308
+ }
309
+ if os.getenv("RAILWAY_GIT_COMMIT_SHA"):
310
+ owner = os.getenv("RAILWAY_GIT_REPO_OWNER")
311
+ name = os.getenv("RAILWAY_GIT_REPO_NAME")
312
+ return {
313
+ "provider": "railway",
314
+ "sha": os.getenv("RAILWAY_GIT_COMMIT_SHA"),
315
+ "repo": f"{owner}/{name}" if owner and name else None,
316
+ "branch": os.getenv("RAILWAY_GIT_BRANCH"),
317
+ "login": os.getenv("RAILWAY_GIT_AUTHOR"),
318
+ }
319
+ if os.getenv("NETLIFY") and os.getenv("COMMIT_REF"):
320
+ repo_match = re.search(
321
+ r"github\.com[/:]([^/]+/[^/.]+)", os.getenv("REPOSITORY_URL") or ""
322
+ )
323
+ return {
324
+ "provider": "netlify",
325
+ "sha": os.getenv("COMMIT_REF"),
326
+ "repo": repo_match.group(1) if repo_match else None,
327
+ "branch": os.getenv("BRANCH"),
328
+ }
329
+ # Heroku (dyno metadata) and common bare conventions: sha only — the
330
+ # platform resolves the repo server-side via the GitHub connection.
331
+ heroku_sha = os.getenv("HEROKU_SLUG_COMMIT") or os.getenv("SOURCE_VERSION")
332
+ bare_sha = heroku_sha or os.getenv("GIT_COMMIT") or os.getenv("COMMIT_SHA")
333
+ if bare_sha:
334
+ return {"provider": "heroku" if heroku_sha else "generic", "sha": bare_sha}
335
+ return None
336
+
337
+
338
+ def _code_ref() -> Optional[str]:
339
+ paas = _paas_git_context() or {}
340
+ sha = (
341
+ os.getenv("GATEWAY_COMMIT")
342
+ or os.getenv("GITHUB_SHA")
343
+ or os.getenv("CI_COMMIT_SHA") # GitLab
344
+ or os.getenv("CIRCLE_SHA1")
345
+ or paas.get("sha")
346
+ )
347
+ if not sha:
348
+ return None
349
+ repo = (
350
+ os.getenv("GITHUB_REPOSITORY")
351
+ or os.getenv("CI_PROJECT_PATH")
352
+ or paas.get("repo")
353
+ )
354
+ return f"git:{repo}@{sha}" if repo else f"git:{sha}"
355
+
356
+
357
+ def assemble_manifest(agent_id: str) -> dict[str, Any]:
358
+ manifest: dict[str, Any] = {
359
+ "agentId": agent_id,
360
+ "sdk": _sdk_version(),
361
+ "tools": get_registered_tools(),
362
+ "prompts": get_registered_prompts(),
363
+ "skills": get_registered_skills(),
364
+ "artifacts": get_registered_artifacts(),
365
+ }
366
+ code_ref = _code_ref()
367
+ if code_ref:
368
+ manifest["codeRef"] = code_ref
369
+ return manifest
370
+
371
+
372
+ def compute_build_hash(manifest: dict[str, Any]) -> str:
373
+ """Content-addressed identity. Source locations are display metadata, not
374
+ identity — the same tool declared on a different line is the same tool."""
375
+ identity = dict(manifest)
376
+ identity["tools"] = [
377
+ {k: v for k, v in tool.items() if k != "source"}
378
+ for tool in manifest.get("tools", [])
379
+ ]
380
+ identity["artifacts"] = [
381
+ {k: v for k, v in artifact.items() if k != "source"}
382
+ for artifact in manifest.get("artifacts", [])
383
+ ]
384
+ return _sha256(canonical_json(identity))
385
+
386
+
387
+ def get_active_build_hash() -> Optional[str]:
388
+ return _active_build_hash
389
+
390
+
391
+ def _attribution_from_env() -> dict[str, Any]:
392
+ attribution: dict[str, Any] = {"source": "runtime"}
393
+ if os.getenv("GITHUB_ACTIONS"):
394
+ attribution["source"] = "ci"
395
+ if os.getenv("GITHUB_ACTOR"):
396
+ attribution["githubLogin"] = os.getenv("GITHUB_ACTOR")
397
+ sha = os.getenv("GATEWAY_COMMIT") or os.getenv("GITHUB_SHA")
398
+ if sha:
399
+ attribution["commitSha"] = sha
400
+ if os.getenv("GITHUB_REPOSITORY"):
401
+ attribution["repo"] = os.getenv("GITHUB_REPOSITORY")
402
+ branch = os.getenv("GITHUB_HEAD_REF") or os.getenv("GITHUB_REF_NAME")
403
+ if branch:
404
+ attribution["branch"] = branch
405
+ # PaaS-injected git context (Vercel/Render/Railway/Netlify/Heroku) fills
406
+ # any gaps — zero-config attribution on those hosts. Explicit env wins.
407
+ paas = _paas_git_context()
408
+ if paas:
409
+ if attribution["source"] == "runtime":
410
+ attribution["source"] = f"paas:{paas['provider']}"
411
+ if not attribution.get("commitSha") and paas.get("sha"):
412
+ attribution["commitSha"] = paas["sha"]
413
+ if not attribution.get("repo") and paas.get("repo"):
414
+ attribution["repo"] = paas["repo"]
415
+ if not attribution.get("branch") and paas.get("branch"):
416
+ attribution["branch"] = paas["branch"]
417
+ if not attribution.get("githubLogin") and paas.get("login"):
418
+ attribution["githubLogin"] = paas["login"]
419
+ pr_match = re.search(r"refs/pull/(\d+)/", os.getenv("GITHUB_REF") or "")
420
+ if pr_match:
421
+ attribution["prNumber"] = int(pr_match.group(1))
422
+ # PR title/body are NOT in the default Actions env — workflows pass them
423
+ # through: GATEWAY_PR_TITLE/GATEWAY_PR_BODY from github.event.pull_request.
424
+ if os.getenv("GATEWAY_PR_TITLE"):
425
+ attribution["prTitle"] = (os.getenv("GATEWAY_PR_TITLE") or "")[:300]
426
+ if os.getenv("GATEWAY_PR_BODY"):
427
+ attribution["prDescription"] = (os.getenv("GATEWAY_PR_BODY") or "")[:2000]
428
+ if attribution.get("repo") and attribution.get("prNumber") and "prUrl" not in attribution:
429
+ attribution["prUrl"] = (
430
+ f"https://github.com/{attribution['repo']}/pull/{attribution['prNumber']}"
431
+ )
432
+ return attribution
433
+
434
+
435
+ def activate_build(
436
+ agent_id: str,
437
+ *,
438
+ version: Optional[str] = None,
439
+ host: Optional[str] = None,
440
+ public_key: Optional[str] = None,
441
+ secret_key: Optional[str] = None,
442
+ register: bool = True,
443
+ ) -> str:
444
+ """Assemble + hash the manifest, mark it active (spans stamp it), and
445
+ fire-and-forget registration with Gateway. Returns the build hash."""
446
+ global _active_build_hash
447
+ manifest = assemble_manifest(agent_id)
448
+ build_hash = compute_build_hash(manifest)
449
+ _active_build_hash = build_hash
450
+ logger.debug(
451
+ "Agent build identity: %s @ %s (%d tools, %d prompts)",
452
+ agent_id,
453
+ build_hash[:15],
454
+ len(manifest["tools"]),
455
+ len(manifest["prompts"]),
456
+ )
457
+
458
+ resolved_host = host or os.getenv("GATEWAY_HOST")
459
+ resolved_public = public_key or os.getenv("GATEWAY_PUBLIC_KEY")
460
+ resolved_secret = secret_key or os.getenv("GATEWAY_SECRET_KEY")
461
+ if not register or not (resolved_host and resolved_public and resolved_secret):
462
+ return build_hash
463
+
464
+ context = {
465
+ "host": resolved_host,
466
+ "public_key": resolved_public,
467
+ "secret_key": resolved_secret,
468
+ "agent_id": agent_id,
469
+ "version": version,
470
+ "last_hash": build_hash,
471
+ }
472
+ # Track so tools/prompts/skills registered AFTER init re-register the
473
+ # fullest manifest (debounced, content-addressed, idempotent).
474
+ _active_contexts.append(context)
475
+ _post_build(context, manifest, build_hash)
476
+ return build_hash
477
+
478
+
479
+ def _post_build(
480
+ context: dict[str, Any], manifest: dict[str, Any], build_hash: str
481
+ ) -> None:
482
+ """Fire-and-forget POST of one build registration (daemon thread)."""
483
+
484
+ def _register() -> None:
485
+ import base64
486
+ from urllib import request as urllib_request
487
+
488
+ payload = {
489
+ "agentId": context["agent_id"],
490
+ "buildHash": build_hash,
491
+ "manifest": manifest,
492
+ "attribution": _attribution_from_env(),
493
+ }
494
+ if context.get("version"):
495
+ payload["semanticVer"] = context["version"]
496
+ try:
497
+ req = urllib_request.Request(
498
+ f"{str(context['host']).rstrip('/')}/api/public/agent-builds",
499
+ data=json.dumps(payload).encode("utf-8"),
500
+ headers={
501
+ "Authorization": "Basic "
502
+ + base64.b64encode(
503
+ f"{context['public_key']}:{context['secret_key']}".encode()
504
+ ).decode(),
505
+ "Content-Type": "application/json",
506
+ },
507
+ method="POST",
508
+ )
509
+ with urllib_request.urlopen(req, timeout=15):
510
+ pass
511
+ logger.debug("Registered agent build %s", build_hash[:15])
512
+ except Exception as exc: # noqa: BLE001 — fail-soft by design
513
+ logger.debug("Build registration failed (agent keeps running): %s", exc)
514
+
515
+ threading.Thread(target=_register, name="gateway-build-register", daemon=True).start()
@@ -0,0 +1,58 @@
1
+ # Copyright (c) Microsoft. All rights reserved.
2
+
3
+ """GatewaySDK command line interface entry point."""
4
+
5
+ from __future__ import annotations
6
+
7
+ import argparse
8
+ import importlib
9
+ import sys
10
+ from typing import Dict, Iterable, Tuple
11
+
12
+ _SUBCOMMANDS: Dict[str, Tuple[str, str]] = {
13
+ "vllm": ("gatewaysdk.cli.vllm", "Run the vLLM CLI with GatewaySDK instrumentation."),
14
+ "store": ("gatewaysdk.cli.store", "Run a LightningStore server."),
15
+ "prometheus": ("gatewaysdk.cli.prometheus", "Serve Prometheus metrics from the multiprocess registry."),
16
+ # "agentops" was removed: it dispatched to gatewaysdk.cli.agentops_server,
17
+ # a module that never existed, so the subcommand always crashed with
18
+ # ModuleNotFoundError. tests/test_cli_dispatch.py guards against repeats.
19
+ }
20
+
21
+ _DESCRIPTION = "GatewaySDK CLI entry point.\n\nAvailable subcommands:\n" + "\n".join(
22
+ f" {name:<10}{desc}" for name, (_, desc) in _SUBCOMMANDS.items()
23
+ )
24
+
25
+
26
+ def main(argv: Iterable[str] | None = None) -> int:
27
+ """Dispatch to the requested GatewaySDK subcommand."""
28
+ parser = argparse.ArgumentParser(
29
+ prog="msk",
30
+ description=_DESCRIPTION,
31
+ formatter_class=argparse.RawDescriptionHelpFormatter,
32
+ )
33
+ parser.add_argument("subcommand", choices=_SUBCOMMANDS.keys(), help="Subcommand to run.")
34
+ parser.add_argument("args", nargs=argparse.REMAINDER, help=argparse.SUPPRESS)
35
+
36
+ parsed = parser.parse_args(list(argv) if argv is not None else None)
37
+ module_name, _ = _SUBCOMMANDS[parsed.subcommand]
38
+ module = importlib.import_module(module_name)
39
+
40
+ entry_point = getattr(module, "main", None)
41
+ if entry_point is None:
42
+ parser.error(f"Subcommand '{parsed.subcommand}' does not define a callable 'main'")
43
+
44
+ dispatch_args = parsed.args
45
+ original_argv = sys.argv
46
+ sys.argv = [f"{parser.prog} {parsed.subcommand}", *dispatch_args]
47
+ try:
48
+ result = entry_point(dispatch_args or None)
49
+ finally:
50
+ sys.argv = original_argv
51
+
52
+ if isinstance(result, int):
53
+ return result
54
+ return 0
55
+
56
+
57
+ if __name__ == "__main__":
58
+ raise SystemExit(main())