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,300 @@
1
+ # Copyright (c) Microsoft. All rights reserved.
2
+
3
+ """
4
+ Instrumentation module for gatewaysdk.
5
+
6
+ Provides automatic metric collection and tracing for various libraries.
7
+ Uses a plugin architecture with an InstrumentorRegistry.
8
+
9
+ Usage:
10
+ # Enable specific instrumentors
11
+ gatewaysdk.instrument("openai")
12
+ gatewaysdk.instrument("openai", "anthropic", "langchain")
13
+
14
+ # Enable all available instrumentors
15
+ gatewaysdk.instrument_all()
16
+
17
+ # Disable instrumentors
18
+ gatewaysdk.uninstrument("openai")
19
+ gatewaysdk.uninstrument_all()
20
+ """
21
+
22
+ import warnings
23
+ from typing import List, Optional
24
+
25
+ # Export base classes and registry
26
+ from .base import Instrumentor, MetricSchema
27
+ from .registry import (
28
+ InstrumentorRegistry,
29
+ )
30
+ from .registry import instrument as registry_instrument
31
+ from .registry import uninstrument as registry_uninstrument
32
+
33
+ __all__ = [
34
+ "Instrumentor",
35
+ "MetricSchema",
36
+ "InstrumentorRegistry",
37
+ "instrument",
38
+ "uninstrument",
39
+ "instrument_all",
40
+ "uninstrument_all",
41
+ ]
42
+
43
+ # Legacy instrumentor availability flags
44
+ AGENTOPS_INSTALLED: bool = False
45
+ AGENTOPS_LANGCHAIN_INSTALLED: bool = False
46
+ LITELLM_INSTALLED: bool = False
47
+ VLLM_INSTALLED: bool = False
48
+ WEAVE_INSTALLED: bool = False
49
+ OPENAI_OTEL_INSTALLED: bool = False
50
+
51
+ try:
52
+ from . import agentops # type: ignore
53
+
54
+ AGENTOPS_INSTALLED = True # type: ignore
55
+ except ImportError:
56
+ pass
57
+
58
+ try:
59
+ from . import litellm # type: ignore
60
+
61
+ LITELLM_INSTALLED = True # type: ignore
62
+ except ImportError:
63
+ pass
64
+
65
+ try:
66
+ from opentelemetry.instrumentation.openai import OpenAIInstrumentor # type: ignore
67
+
68
+ OPENAI_OTEL_INSTALLED = True
69
+ except ImportError:
70
+ pass
71
+
72
+
73
+ def instrument(*names: str, **kwargs) -> List[Optional[Instrumentor]]:
74
+ """
75
+ Activate one or more instrumentors by name.
76
+
77
+ Uses the InstrumentorRegistry to activate instrumentors.
78
+ For legacy instrumentors not yet migrated to the registry,
79
+ falls back to direct activation.
80
+
81
+ Args:
82
+ *names: Instrumentor names to activate
83
+ **kwargs: Additional arguments passed to instrumentor constructors
84
+
85
+ Returns:
86
+ List of activated instrumentor instances (None for failed activations)
87
+
88
+ Examples:
89
+ # Enable OpenAI instrumentation
90
+ gatewaysdk.instrument("openai")
91
+
92
+ # Enable multiple instrumentors
93
+ gatewaysdk.instrument("openai", "anthropic", "langchain")
94
+
95
+ # Enable all available instrumentors
96
+ gatewaysdk.instrument_all()
97
+ """
98
+ results = []
99
+ for name in names:
100
+ # Try registry first
101
+ try:
102
+ result = InstrumentorRegistry.instrument(name, **kwargs)
103
+ results.append(result)
104
+ except ValueError:
105
+ # Fall back to legacy instrumentors
106
+ result = _instrument_legacy(name)
107
+ results.append(result)
108
+ return results
109
+
110
+
111
+ def uninstrument(*names: str) -> None:
112
+ """
113
+ Deactivate one or more instrumentors by name.
114
+
115
+ Args:
116
+ *names: Instrumentor names to deactivate
117
+ """
118
+ for name in names:
119
+ # Try registry first
120
+ if InstrumentorRegistry.is_active(name):
121
+ InstrumentorRegistry.uninstrument(name)
122
+ else:
123
+ # Fall back to legacy uninstrument
124
+ _uninstrument_legacy(name)
125
+
126
+
127
+ def _instrument_legacy(name: str) -> Optional[Instrumentor]:
128
+ """Activate a legacy instrumentor by name."""
129
+ name_lower = name.lower()
130
+
131
+ if name_lower == "agentops" and AGENTOPS_INSTALLED:
132
+ from .agentops import instrument_agentops
133
+
134
+ instrument_agentops()
135
+ return None # Legacy doesn't return instance
136
+
137
+ if name_lower == "litellm" and LITELLM_INSTALLED:
138
+ from .litellm import instrument_litellm
139
+
140
+ instrument_litellm()
141
+ return None
142
+
143
+ if name_lower == "vllm" and VLLM_INSTALLED:
144
+ from .vllm import instrument_vllm
145
+
146
+ instrument_vllm()
147
+ return None
148
+
149
+ if name_lower in ("openai", "openai-otel") and OPENAI_OTEL_INSTALLED:
150
+ try:
151
+ OpenAIInstrumentor().instrument() # type: ignore
152
+ except Exception as e:
153
+ warnings.warn(f"Failed to instrument OpenAI SDK: {e}")
154
+ return None
155
+
156
+ warnings.warn(f"Unknown or unavailable instrumentor: {name}")
157
+ return None
158
+
159
+
160
+ def _uninstrument_legacy(name: str) -> None:
161
+ """Deactivate a legacy instrumentor by name."""
162
+ name_lower = name.lower()
163
+
164
+ if name_lower == "agentops" and AGENTOPS_INSTALLED:
165
+ try:
166
+ from .agentops import uninstrument_agentops
167
+
168
+ uninstrument_agentops()
169
+ except ImportError:
170
+ pass
171
+
172
+ elif name_lower == "litellm" and LITELLM_INSTALLED:
173
+ try:
174
+ from .litellm import uninstrument_litellm
175
+
176
+ uninstrument_litellm()
177
+ except ImportError:
178
+ pass
179
+
180
+ elif name_lower == "vllm" and VLLM_INSTALLED:
181
+ try:
182
+ from .vllm import uninstrument_vllm
183
+
184
+ uninstrument_vllm()
185
+ except ImportError:
186
+ pass
187
+
188
+ elif name_lower in ("openai", "openai-otel") and OPENAI_OTEL_INSTALLED:
189
+ try:
190
+ OpenAIInstrumentor().uninstrument() # type: ignore
191
+ except Exception:
192
+ pass
193
+
194
+
195
+ def instrument_all():
196
+ """
197
+ Instrument all available instrumentation libraries.
198
+
199
+ This includes both registry-based instrumentors and legacy instrumentors.
200
+ """
201
+ # First, activate all registry-based instrumentors
202
+ for name in InstrumentorRegistry.list_available():
203
+ try:
204
+ InstrumentorRegistry.instrument(name)
205
+ except Exception as e:
206
+ warnings.warn(f"Failed to instrument {name}: {e}")
207
+
208
+ # Then activate legacy instrumentors
209
+ if AGENTOPS_INSTALLED:
210
+ from .agentops import instrument_agentops
211
+
212
+ instrument_agentops()
213
+ else:
214
+ warnings.warn("agentops is not installed. It's therefore not instrumented.")
215
+
216
+ if LITELLM_INSTALLED:
217
+ from .litellm import instrument_litellm
218
+
219
+ instrument_litellm()
220
+ else:
221
+ warnings.warn("litellm is not installed. It's therefore not instrumented.")
222
+
223
+ if VLLM_INSTALLED:
224
+ from .vllm import instrument_vllm
225
+
226
+ instrument_vllm()
227
+ else:
228
+ warnings.warn("vllm is not installed. It's therefore not instrumented.")
229
+
230
+ if AGENTOPS_LANGCHAIN_INSTALLED:
231
+ from .agentops_langchain import instrument_agentops_langchain
232
+
233
+ instrument_agentops_langchain()
234
+ else:
235
+ warnings.warn("Agentops-langchain integration is not installed. It's therefore not instrumented.")
236
+
237
+ # Enable standard OpenAI instrumentation if available
238
+ # This allows client-side spans to be generated for OpenAI SDK calls
239
+ if OPENAI_OTEL_INSTALLED:
240
+ try:
241
+ OpenAIInstrumentor().instrument() # type: ignore
242
+ except Exception as e:
243
+ warnings.warn(f"Failed to instrument OpenAI SDK: {e}")
244
+
245
+
246
+ def uninstrument_all():
247
+ """
248
+ Uninstrument all active instrumentation libraries.
249
+
250
+ This includes both registry-based instrumentors and legacy instrumentors.
251
+ """
252
+ # First, deactivate all registry-based instrumentors
253
+ InstrumentorRegistry.uninstrument_all()
254
+
255
+ # Then deactivate legacy instrumentors
256
+ if AGENTOPS_INSTALLED:
257
+ try:
258
+ from .agentops import uninstrument_agentops
259
+
260
+ uninstrument_agentops()
261
+ except ImportError:
262
+ warnings.warn("agentops is installed but uninstrument_agentops could not be imported.")
263
+ else:
264
+ warnings.warn("agentops is not installed. It's therefore not uninstrumented.")
265
+
266
+ if LITELLM_INSTALLED:
267
+ try:
268
+ from .litellm import uninstrument_litellm
269
+
270
+ uninstrument_litellm()
271
+ except ImportError:
272
+ warnings.warn("litellm is installed but uninstrument_litellm could not be imported.")
273
+ else:
274
+ warnings.warn("litellm is not installed. It's therefore not uninstrumented.")
275
+
276
+ if VLLM_INSTALLED:
277
+ try:
278
+ from .vllm import uninstrument_vllm
279
+
280
+ uninstrument_vllm()
281
+ except ImportError:
282
+ warnings.warn("vllm is installed but uninstrument_vllm could not be imported.")
283
+ else:
284
+ warnings.warn("vllm is not installed. It's therefore not uninstrumented.")
285
+
286
+ if AGENTOPS_LANGCHAIN_INSTALLED:
287
+ try:
288
+ from .agentops_langchain import uninstrument_agentops_langchain
289
+
290
+ uninstrument_agentops_langchain()
291
+ except ImportError:
292
+ warnings.warn("agentops_langchain is installed but uninstrument_agentops_langchain could not be imported.")
293
+ else:
294
+ warnings.warn("Agentops-langchain integration is not installed. It's therefore not uninstrumented.")
295
+
296
+ if OPENAI_OTEL_INSTALLED:
297
+ try:
298
+ OpenAIInstrumentor().uninstrument() # type: ignore
299
+ except Exception:
300
+ pass
@@ -0,0 +1,314 @@
1
+ # Copyright (c) Microsoft. All rights reserved.
2
+
3
+ from __future__ import annotations
4
+
5
+ import json
6
+ import logging
7
+ from typing import Any, Callable, no_type_check
8
+
9
+ import requests
10
+ from agentops.client.api import V3Client, V4Client
11
+ from agentops.client.api.types import AuthTokenResponse
12
+ from agentops.sdk.exporters import AuthenticatedOTLPExporter
13
+ from opentelemetry.exporter.otlp.proto.http.metric_exporter import OTLPMetricExporter
14
+ from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
15
+ from opentelemetry.sdk.metrics.export import MetricExportResult
16
+
17
+ from gatewaysdk.utils.otlp import LightningStoreOTLPExporter
18
+
19
+ logger = logging.getLogger(__name__)
20
+
21
+ __all__ = [
22
+ "instrument_agentops",
23
+ "uninstrument_agentops",
24
+ ]
25
+
26
+ # Module-level storage for originals
27
+ _original_handle_chat_attributes: Callable[..., Any] | None = None
28
+ _original_handle_response: Callable[..., Any] | None = None
29
+ _agentops_service_enabled = False
30
+
31
+
32
+ def enable_agentops_service(enabled: bool = True) -> None:
33
+ """
34
+ Enable or disable communication with the AgentOps service.
35
+
36
+ By default, AgentOps exporters and clients will run in local mode
37
+ and will NOT attempt to communicate with the remote AgentOps service.
38
+
39
+ Args:
40
+ enabled: If True, enable all AgentOps exporters and clients.
41
+ All exporters and clients will operate in normal mode and send data
42
+ to the [AgentOps service](https://www.agentops.ai).
43
+ """
44
+ global _agentops_service_enabled
45
+ _agentops_service_enabled = enabled
46
+ logger.info(f"AgentOps service enabled is set to {enabled}.")
47
+
48
+
49
+ def _patch_exporters():
50
+ import agentops.client.api
51
+ import agentops.sdk.core
52
+
53
+ agentops.sdk.core.AuthenticatedOTLPExporter = BypassableAuthenticatedOTLPExporter # type: ignore
54
+ agentops.sdk.core.OTLPMetricExporter = BypassableOTLPMetricExporter
55
+ if hasattr(agentops.sdk.core, "OTLPSpanExporter"):
56
+ agentops.sdk.core.OTLPSpanExporter = BypassableOTLPSpanExporter # type: ignore
57
+ agentops.client.api.V3Client = BypassableV3Client
58
+ agentops.client.api.V4Client = BypassableV4Client
59
+
60
+
61
+ def _unpatch_exporters():
62
+ import agentops.client.api
63
+ import agentops.sdk.core
64
+
65
+ agentops.sdk.core.AuthenticatedOTLPExporter = AuthenticatedOTLPExporter # type: ignore
66
+ agentops.sdk.core.OTLPMetricExporter = OTLPMetricExporter
67
+ if hasattr(agentops.sdk.core, "OTLPSpanExporter"):
68
+ agentops.sdk.core.OTLPSpanExporter = OTLPSpanExporter # type: ignore
69
+ agentops.client.api.V3Client = V3Client
70
+ agentops.client.api.V4Client = V4Client
71
+
72
+
73
+ def _unwrap_legacy_response(response: Any) -> Any:
74
+ if hasattr(response, "parse") and callable(response.parse):
75
+ return response.parse()
76
+ return response
77
+
78
+
79
+ def _patch_new_agentops():
80
+ import agentops.instrumentation.providers.openai.stream_wrapper
81
+ import agentops.instrumentation.providers.openai.wrappers.chat
82
+ from agentops.instrumentation.providers.openai.wrappers.chat import handle_chat_attributes # type: ignore
83
+
84
+ global _original_handle_chat_attributes
85
+
86
+ if _original_handle_chat_attributes is not None:
87
+ logger.warning("AgentOps already patched. Skipping.")
88
+ return True
89
+
90
+ _original_handle_chat_attributes = handle_chat_attributes # type: ignore
91
+
92
+ @no_type_check
93
+ def _handle_chat_attributes_with_tokens(args=None, kwargs=None, return_value=None, **kws): # type: ignore
94
+ attributes = _original_handle_chat_attributes(args=args, kwargs=kwargs, return_value=return_value, **kws)
95
+
96
+ # In some cases, response is a openai._legacy_response.LegacyAPIResponse (e.g., LiteLLM, or LangChain),
97
+ # This is created by client.with_raw_response.create()
98
+ return_value = _unwrap_legacy_response(return_value)
99
+
100
+ if (
101
+ return_value is not None
102
+ and hasattr(return_value, "prompt_token_ids")
103
+ and return_value.prompt_token_ids is not None
104
+ ):
105
+ attributes["prompt_token_ids"] = list(return_value.prompt_token_ids)
106
+ if (
107
+ return_value is not None
108
+ and hasattr(return_value, "response_token_ids")
109
+ and return_value.response_token_ids is not None
110
+ ):
111
+ attributes["response_token_ids"] = list(return_value.response_token_ids[0])
112
+
113
+ # For LiteLLM Proxy (v0.2) with vLLM return_token_ids, response_token_ids now lives in choices
114
+ if (
115
+ return_value is not None
116
+ and hasattr(return_value, "choices")
117
+ and return_value.choices
118
+ and isinstance(return_value.choices, list)
119
+ and len(return_value.choices) > 0
120
+ ):
121
+ first_choice = return_value.choices[0]
122
+ # Token IDs from "choices[0].token_ids"
123
+ if "response_token_ids" not in attributes:
124
+ if hasattr(first_choice, "token_ids") and first_choice.token_ids is not None:
125
+ attributes["response_token_ids"] = list(first_choice.token_ids)
126
+ # newer versions of OpenAI client SDK
127
+ elif (
128
+ hasattr(first_choice, "provider_specific_fields")
129
+ and first_choice.provider_specific_fields.get("token_ids") is not None
130
+ ):
131
+ attributes["response_token_ids"] = list(first_choice.provider_specific_fields["token_ids"])
132
+
133
+ # log probability
134
+ # This is temporary. We need a unified convention for classifying and naming logprobs.
135
+ if hasattr(first_choice, "logprobs") and first_choice.logprobs is not None:
136
+ if hasattr(first_choice.logprobs, "content") and first_choice.logprobs.content is not None:
137
+ attributes["logprobs.content"] = json.dumps(
138
+ [logprob.model_dump() for logprob in first_choice.logprobs.content]
139
+ )
140
+ if hasattr(first_choice.logprobs, "refusal") and first_choice.logprobs.refusal is not None:
141
+ attributes["logprobs.refusal"] = json.dumps(
142
+ [logprob.model_dump() for logprob in first_choice.logprobs.refusal]
143
+ )
144
+
145
+ return attributes
146
+
147
+ agentops.instrumentation.providers.openai.wrappers.chat.handle_chat_attributes = _handle_chat_attributes_with_tokens
148
+ agentops.instrumentation.providers.openai.stream_wrapper.handle_chat_attributes = (
149
+ _handle_chat_attributes_with_tokens
150
+ )
151
+ logger.info("Patched newer version of agentops using handle_chat_attributes")
152
+ return True
153
+
154
+
155
+ def _unpatch_new_agentops():
156
+ import agentops.instrumentation.providers.openai.stream_wrapper
157
+ import agentops.instrumentation.providers.openai.wrappers.chat
158
+
159
+ global _original_handle_chat_attributes
160
+ if _original_handle_chat_attributes is not None:
161
+ agentops.instrumentation.providers.openai.wrappers.chat.handle_chat_attributes = (
162
+ _original_handle_chat_attributes
163
+ )
164
+ agentops.instrumentation.providers.openai.stream_wrapper.handle_chat_attributes = (
165
+ _original_handle_chat_attributes
166
+ )
167
+ _original_handle_chat_attributes = None
168
+ logger.info("Unpatched newer version of agentops using handle_chat_attributes")
169
+
170
+
171
+ def _patch_old_agentops():
172
+ import opentelemetry.instrumentation.openai.shared.chat_wrappers # type: ignore
173
+ from opentelemetry.instrumentation.openai.shared.chat_wrappers import _handle_response, dont_throw # type: ignore
174
+
175
+ global _original_handle_response
176
+ _original_handle_response = _handle_response # type: ignore
177
+
178
+ @dont_throw # type: ignore
179
+ def _handle_response_with_tokens(response, span, *args, **kwargs): # type: ignore
180
+ _original_handle_response(response, span, *args, **kwargs) # type: ignore
181
+ if hasattr(response, "prompt_token_ids"): # type: ignore
182
+ span.set_attribute("prompt_token_ids", list(response.prompt_token_ids)) # type: ignore
183
+ if hasattr(response, "response_token_ids"): # type: ignore
184
+ span.set_attribute("response_token_ids", list(response.response_token_ids[0])) # type: ignore
185
+
186
+ # For LiteLLM, response is a openai._legacy_response.LegacyAPIResponse
187
+ if hasattr(response, "http_response") and hasattr(response.http_response, "json"): # type: ignore
188
+ json_data = response.http_response.json() # type: ignore
189
+ if isinstance(json_data, dict):
190
+ if "prompt_token_ids" in json_data:
191
+ span.set_attribute("prompt_token_ids", list(json_data["prompt_token_ids"])) # type: ignore
192
+ if "response_token_ids" in json_data:
193
+ span.set_attribute("response_token_ids", list(json_data["response_token_ids"][0])) # type: ignore
194
+
195
+ opentelemetry.instrumentation.openai.shared.chat_wrappers._handle_response = _handle_response_with_tokens # type: ignore
196
+ logger.info("Patched earlier version of agentops using _handle_response")
197
+ return True
198
+
199
+
200
+ def _unpatch_old_agentops():
201
+ import opentelemetry.instrumentation.openai.shared.chat_wrappers # type: ignore
202
+
203
+ global _original_handle_response
204
+ if _original_handle_response is not None:
205
+ opentelemetry.instrumentation.openai.shared.chat_wrappers._handle_response = _original_handle_response # type: ignore
206
+ _original_handle_response = None
207
+ logger.info("Unpatched earlier version of agentops using _handle_response")
208
+
209
+
210
+ def instrument_agentops():
211
+ """
212
+ Instrument agentops to capture token IDs.
213
+ Automatically detects and uses the appropriate patching method based on the installed agentops version.
214
+ """
215
+ _patch_exporters()
216
+
217
+ # Try newest version first (tested for 0.4.16)
218
+ try:
219
+ return _patch_new_agentops()
220
+ except ImportError as e:
221
+ logger.debug(f"Couldn't patch newer version of agentops: {str(e)}")
222
+
223
+ # Note: 0.4.15 needs another patching method, but it's too shortlived to be worth handling separately.
224
+
225
+ # Try older version (tested for 0.4.13)
226
+ try:
227
+ return _patch_old_agentops()
228
+ except ImportError as e:
229
+ logger.warning(f"Couldn't patch older version of agentops: {str(e)}")
230
+ logger.error("Failed to instrument agentops - neither patching method was successful")
231
+ return False
232
+
233
+
234
+ def uninstrument_agentops():
235
+ """Uninstrument agentops to stop capturing token IDs."""
236
+ _unpatch_exporters()
237
+
238
+ try:
239
+ _unpatch_new_agentops()
240
+ except Exception:
241
+ pass
242
+ try:
243
+ _unpatch_old_agentops()
244
+ except Exception:
245
+ pass
246
+
247
+
248
+ class BypassableAuthenticatedOTLPExporter(LightningStoreOTLPExporter, AuthenticatedOTLPExporter):
249
+ """
250
+ AuthenticatedOTLPExporter with switchable service control.
251
+
252
+ When `_agentops_service_enabled` is False, skip export and return success.
253
+ """
254
+
255
+ def should_bypass(self) -> bool:
256
+ return not _agentops_service_enabled
257
+
258
+
259
+ class BypassableOTLPMetricExporter(OTLPMetricExporter):
260
+ """
261
+ OTLPMetricExporter with switchable service control.
262
+ When `_agentops_service_enabled` is False, skip export and return success.
263
+ """
264
+
265
+ def export(self, *args: Any, **kwargs: Any) -> MetricExportResult:
266
+ if _agentops_service_enabled:
267
+ return super().export(*args, **kwargs) # type: ignore[reportUnknownMemberType]
268
+ else:
269
+ logger.debug("SwitchableOTLPMetricExporter is switched off, skipping export.")
270
+ return MetricExportResult.SUCCESS
271
+
272
+
273
+ class BypassableOTLPSpanExporter(LightningStoreOTLPExporter):
274
+ """
275
+ OTLPSpanExporter with switchable service control.
276
+ When `_agentops_service_enabled` is False, skip export and return success.
277
+
278
+ This is used instead of BypassableAuthenticatedOTLPExporter on legacy AgentOps versions.
279
+ """
280
+
281
+ def should_bypass(self) -> bool:
282
+ return not _agentops_service_enabled
283
+
284
+
285
+ class BypassableV3Client(V3Client):
286
+ """
287
+ V3Client with toggleable authentication calls.
288
+ Returns dummy auth response when `_agentops_service_enabled` is False.
289
+ """
290
+
291
+ # Temporary synchronous override of fetch_auth_token for mock purposes.
292
+ def fetch_auth_token(self, *args: Any, **kwargs: Any) -> AuthTokenResponse: # type: ignore[override]
293
+ if _agentops_service_enabled:
294
+ return super().fetch_auth_token(*args, **kwargs) # type: ignore[override]
295
+ else:
296
+ logger.debug("SwitchableV3Client is switched off, skipping fetch_auth_token request.")
297
+ return AuthTokenResponse(token="dummy", project_id="dummy")
298
+
299
+
300
+ class BypassableV4Client(V4Client):
301
+ """
302
+ V4Client with toggleable post requests.
303
+ Returns dummy response when `_agentops_service_enabled` is False.
304
+ """
305
+
306
+ def post(self, *args: Any, **kwargs: Any) -> requests.Response:
307
+ if _agentops_service_enabled:
308
+ return super().post(*args, **kwargs)
309
+ else:
310
+ logger.debug("SwitchableV4Client is switched off, skipping post request.")
311
+ response = requests.Response()
312
+ response.status_code = 200
313
+ response._content = b"{}"
314
+ return response
@@ -0,0 +1,45 @@
1
+ # Copyright (c) Microsoft. All rights reserved.
2
+
3
+ from typing import Any, Dict
4
+
5
+ from agentops import instrumentation
6
+ from agentops.integration.callbacks.langchain import LangchainCallbackHandler
7
+
8
+ original_on_chain_start = LangchainCallbackHandler.on_chain_start
9
+ langgraph_entry = None
10
+
11
+ __all__ = [
12
+ "instrument_agentops_langchain",
13
+ "uninstrument_agentops_langchain",
14
+ ]
15
+
16
+
17
+ def on_chain_start(self: Any, serialized: Dict[str, Any], inputs: Dict[str, Any], **kwargs: Any) -> None:
18
+ if "name" in kwargs:
19
+ if serialized is None: # type: ignore
20
+ serialized = {}
21
+ serialized = serialized.copy()
22
+ serialized["name"] = kwargs["name"]
23
+ if "run_id" in kwargs:
24
+ if serialized is None: # type: ignore
25
+ serialized = {}
26
+ serialized = serialized.copy()
27
+ if "id" not in serialized:
28
+ serialized["id"] = kwargs["run_id"]
29
+ return original_on_chain_start(self, serialized, inputs, **kwargs)
30
+
31
+
32
+ def instrument_agentops_langchain():
33
+ """Bypass AgentOp's native support for Langchain."""
34
+ global langgraph_entry
35
+ langgraph_entry = instrumentation.AGENTIC_LIBRARIES.pop("langgraph", None)
36
+ LangchainCallbackHandler.on_chain_start = on_chain_start
37
+
38
+
39
+ def uninstrument_agentops_langchain():
40
+ """Restore AgentOp's native support for Langchain."""
41
+ global langgraph_entry
42
+ if langgraph_entry is not None:
43
+ instrumentation.AGENTIC_LIBRARIES["langgraph"] = langgraph_entry
44
+ langgraph_entry = None
45
+ LangchainCallbackHandler.on_chain_start = original_on_chain_start