synth-ai 0.1.9__py3-none-any.whl → 0.2.1.dev0__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 (266) hide show
  1. synth_ai/__init__.py +28 -2
  2. synth_ai/core/system.py +4 -0
  3. synth_ai/environments/__init__.py +35 -0
  4. synth_ai/environments/environment/__init__.py +1 -0
  5. synth_ai/environments/environment/artifacts/__init__.py +1 -0
  6. synth_ai/environments/environment/artifacts/base.py +50 -0
  7. synth_ai/environments/environment/core.py +22 -0
  8. synth_ai/environments/environment/db/__init__.py +1 -0
  9. synth_ai/environments/environment/db/sqlite.py +45 -0
  10. synth_ai/environments/environment/registry.py +24 -0
  11. synth_ai/environments/environment/resources/sqlite.py +46 -0
  12. synth_ai/environments/environment/results.py +1 -0
  13. synth_ai/environments/environment/rewards/__init__.py +1 -0
  14. synth_ai/environments/environment/rewards/core.py +28 -0
  15. synth_ai/environments/environment/shared_engine.py +26 -0
  16. synth_ai/environments/environment/tools/__init__.py +34 -0
  17. synth_ai/environments/examples/__init__.py +1 -0
  18. synth_ai/environments/examples/crafter_classic/__init__.py +8 -0
  19. synth_ai/environments/examples/crafter_classic/agent_demos/crafter_comprehensive_evaluation.py +58 -0
  20. synth_ai/environments/examples/crafter_classic/agent_demos/crafter_evaluation_browser.py +152 -0
  21. synth_ai/environments/examples/crafter_classic/agent_demos/crafter_evaluation_framework.py +1194 -0
  22. synth_ai/environments/examples/crafter_classic/agent_demos/crafter_quick_evaluation.py +51 -0
  23. synth_ai/environments/examples/crafter_classic/agent_demos/crafter_react_agent.py +872 -0
  24. synth_ai/environments/examples/crafter_classic/agent_demos/crafter_trace_evaluation.py +1412 -0
  25. synth_ai/environments/examples/crafter_classic/agent_demos/test_crafter_react_agent.py +1110 -0
  26. synth_ai/environments/examples/crafter_classic/config_logging.py +111 -0
  27. synth_ai/environments/examples/crafter_classic/engine.py +502 -0
  28. synth_ai/environments/examples/crafter_classic/engine_deterministic_patch.py +63 -0
  29. synth_ai/environments/examples/crafter_classic/engine_helpers/action_map.py +5 -0
  30. synth_ai/environments/examples/crafter_classic/engine_helpers/serialization.py +74 -0
  31. synth_ai/environments/examples/crafter_classic/environment.py +255 -0
  32. synth_ai/environments/examples/crafter_classic/taskset.py +228 -0
  33. synth_ai/environments/examples/enron/agent_demos/test_synth_react.py +535 -0
  34. synth_ai/environments/examples/enron/art_helpers/email_search_tools.py +156 -0
  35. synth_ai/environments/examples/enron/art_helpers/local_email_db.py +280 -0
  36. synth_ai/environments/examples/enron/art_helpers/types_enron.py +24 -0
  37. synth_ai/environments/examples/enron/engine.py +291 -0
  38. synth_ai/environments/examples/enron/environment.py +165 -0
  39. synth_ai/environments/examples/enron/taskset.py +112 -0
  40. synth_ai/environments/examples/enron/units/keyword_stats.py +111 -0
  41. synth_ai/environments/examples/enron/units/test_email_index.py +8 -0
  42. synth_ai/environments/examples/minigrid/__init__.py +48 -0
  43. synth_ai/environments/examples/minigrid/agent_demos/minigrid_evaluation_framework.py +1188 -0
  44. synth_ai/environments/examples/minigrid/agent_demos/minigrid_quick_evaluation.py +47 -0
  45. synth_ai/environments/examples/minigrid/agent_demos/minigrid_react_agent.py +562 -0
  46. synth_ai/environments/examples/minigrid/agent_demos/minigrid_trace_evaluation.py +220 -0
  47. synth_ai/environments/examples/minigrid/agent_demos/test_minigrid_react_agent.py +393 -0
  48. synth_ai/environments/examples/minigrid/engine.py +589 -0
  49. synth_ai/environments/examples/minigrid/environment.py +274 -0
  50. synth_ai/environments/examples/minigrid/environment_mapping.py +242 -0
  51. synth_ai/environments/examples/minigrid/puzzle_loader.py +416 -0
  52. synth_ai/environments/examples/minigrid/taskset.py +583 -0
  53. synth_ai/environments/examples/minigrid/units/test_action_behavior.py +226 -0
  54. synth_ai/environments/examples/minigrid/units/test_debug_messages.py +83 -0
  55. synth_ai/environments/examples/minigrid/units/test_exploration.py +120 -0
  56. synth_ai/environments/examples/minigrid/units/test_minigrid_engine.py +214 -0
  57. synth_ai/environments/examples/minigrid/units/test_minigrid_environment.py +238 -0
  58. synth_ai/environments/examples/minigrid/units/test_minigrid_environment_mapping.py +301 -0
  59. synth_ai/environments/examples/minigrid/units/test_minigrid_taskset.py +210 -0
  60. synth_ai/environments/examples/nethack/__init__.py +7 -0
  61. synth_ai/environments/examples/nethack/achievements.py +337 -0
  62. synth_ai/environments/examples/nethack/agent_demos/nethack_evaluation_framework.py +981 -0
  63. synth_ai/environments/examples/nethack/agent_demos/nethack_quick_evaluation.py +74 -0
  64. synth_ai/environments/examples/nethack/agent_demos/nethack_react_agent.py +832 -0
  65. synth_ai/environments/examples/nethack/agent_demos/test_nethack_react_agent.py +1112 -0
  66. synth_ai/environments/examples/nethack/engine.py +738 -0
  67. synth_ai/environments/examples/nethack/environment.py +255 -0
  68. synth_ai/environments/examples/nethack/helpers/__init__.py +42 -0
  69. synth_ai/environments/examples/nethack/helpers/action_mapping.py +301 -0
  70. synth_ai/environments/examples/nethack/helpers/nle_wrapper.py +401 -0
  71. synth_ai/environments/examples/nethack/helpers/observation_utils.py +433 -0
  72. synth_ai/environments/examples/nethack/helpers/recording_wrapper.py +201 -0
  73. synth_ai/environments/examples/nethack/helpers/trajectory_recorder.py +268 -0
  74. synth_ai/environments/examples/nethack/helpers/visualization/replay_viewer.py +308 -0
  75. synth_ai/environments/examples/nethack/helpers/visualization/visualizer.py +430 -0
  76. synth_ai/environments/examples/nethack/taskset.py +323 -0
  77. synth_ai/environments/examples/nethack/units/test_nethack_engine.py +277 -0
  78. synth_ai/environments/examples/nethack/units/test_nethack_environment.py +281 -0
  79. synth_ai/environments/examples/nethack/units/test_nethack_taskset.py +213 -0
  80. synth_ai/environments/examples/nethack/units/test_recording.py +307 -0
  81. synth_ai/environments/examples/red/__init__.py +7 -0
  82. synth_ai/environments/examples/red/agent_demos/__init__.py +1 -0
  83. synth_ai/environments/examples/red/agent_demos/test_synth_react.py +1471 -0
  84. synth_ai/environments/examples/red/config_logging.py +110 -0
  85. synth_ai/environments/examples/red/engine.py +693 -0
  86. synth_ai/environments/examples/red/engine_helpers/__init__.py +1 -0
  87. synth_ai/environments/examples/red/engine_helpers/memory_map.py +28 -0
  88. synth_ai/environments/examples/red/engine_helpers/reward_components.py +275 -0
  89. synth_ai/environments/examples/red/engine_helpers/reward_library/__init__.py +142 -0
  90. synth_ai/environments/examples/red/engine_helpers/reward_library/adaptive_rewards.py +56 -0
  91. synth_ai/environments/examples/red/engine_helpers/reward_library/battle_rewards.py +283 -0
  92. synth_ai/environments/examples/red/engine_helpers/reward_library/composite_rewards.py +149 -0
  93. synth_ai/environments/examples/red/engine_helpers/reward_library/economy_rewards.py +137 -0
  94. synth_ai/environments/examples/red/engine_helpers/reward_library/efficiency_rewards.py +56 -0
  95. synth_ai/environments/examples/red/engine_helpers/reward_library/exploration_rewards.py +330 -0
  96. synth_ai/environments/examples/red/engine_helpers/reward_library/novelty_rewards.py +120 -0
  97. synth_ai/environments/examples/red/engine_helpers/reward_library/pallet_town_rewards.py +558 -0
  98. synth_ai/environments/examples/red/engine_helpers/reward_library/pokemon_rewards.py +312 -0
  99. synth_ai/environments/examples/red/engine_helpers/reward_library/social_rewards.py +147 -0
  100. synth_ai/environments/examples/red/engine_helpers/reward_library/story_rewards.py +246 -0
  101. synth_ai/environments/examples/red/engine_helpers/screen_analysis.py +367 -0
  102. synth_ai/environments/examples/red/engine_helpers/state_extraction.py +139 -0
  103. synth_ai/environments/examples/red/environment.py +235 -0
  104. synth_ai/environments/examples/red/taskset.py +77 -0
  105. synth_ai/environments/examples/red/test_fixes.py +125 -0
  106. synth_ai/environments/examples/red/test_fixes_mock.py +148 -0
  107. synth_ai/environments/examples/red/units/__init__.py +1 -0
  108. synth_ai/environments/examples/red/units/test_basic_functionality.py +97 -0
  109. synth_ai/environments/examples/red/units/test_button_press_requirements.py +217 -0
  110. synth_ai/environments/examples/red/units/test_engine.py +192 -0
  111. synth_ai/environments/examples/red/units/test_environment.py +455 -0
  112. synth_ai/environments/examples/red/units/test_exploration_strategy.py +227 -0
  113. synth_ai/environments/examples/red/units/test_integration.py +217 -0
  114. synth_ai/environments/examples/red/units/test_memory_extraction.py +111 -0
  115. synth_ai/environments/examples/red/units/test_menu_bug_reproduction.py +1100 -0
  116. synth_ai/environments/examples/red/units/test_movement_debug.py +255 -0
  117. synth_ai/environments/examples/red/units/test_pokemon_mcts_debug.py +163 -0
  118. synth_ai/environments/examples/red/units/test_pokemon_mcts_verbose.py +117 -0
  119. synth_ai/environments/examples/red/units/test_red_basic.py +145 -0
  120. synth_ai/environments/examples/red/units/test_red_comprehensive.py +323 -0
  121. synth_ai/environments/examples/red/units/test_retry_movement.py +195 -0
  122. synth_ai/environments/examples/red/units/test_reward_components.py +186 -0
  123. synth_ai/environments/examples/red/units/test_rom_integration.py +260 -0
  124. synth_ai/environments/examples/red/units/test_taskset.py +116 -0
  125. synth_ai/environments/examples/red/units/test_tree.py +448 -0
  126. synth_ai/environments/examples/sokoban/__init__.py +1 -0
  127. synth_ai/environments/examples/sokoban/agent_demos/sokoban_full_eval.py +900 -0
  128. synth_ai/environments/examples/sokoban/agent_demos/test_dspy_react.py +1 -0
  129. synth_ai/environments/examples/sokoban/agent_demos/test_sokoban_react_agent.py +498 -0
  130. synth_ai/environments/examples/sokoban/agent_demos/test_synth_lats.py +1 -0
  131. synth_ai/environments/examples/sokoban/agent_demos/test_synth_react_locally.py +748 -0
  132. synth_ai/environments/examples/sokoban/agent_demos/test_synth_react_service.py +296 -0
  133. synth_ai/environments/examples/sokoban/engine.py +675 -0
  134. synth_ai/environments/examples/sokoban/engine_helpers/__init__.py +1 -0
  135. synth_ai/environments/examples/sokoban/engine_helpers/room_utils.py +656 -0
  136. synth_ai/environments/examples/sokoban/engine_helpers/vendored/__init__.py +17 -0
  137. synth_ai/environments/examples/sokoban/engine_helpers/vendored/envs/__init__.py +3 -0
  138. synth_ai/environments/examples/sokoban/engine_helpers/vendored/envs/boxoban_env.py +129 -0
  139. synth_ai/environments/examples/sokoban/engine_helpers/vendored/envs/render_utils.py +370 -0
  140. synth_ai/environments/examples/sokoban/engine_helpers/vendored/envs/room_utils.py +331 -0
  141. synth_ai/environments/examples/sokoban/engine_helpers/vendored/envs/sokoban_env.py +305 -0
  142. synth_ai/environments/examples/sokoban/engine_helpers/vendored/envs/sokoban_env_fixed_targets.py +66 -0
  143. synth_ai/environments/examples/sokoban/engine_helpers/vendored/envs/sokoban_env_pull.py +114 -0
  144. synth_ai/environments/examples/sokoban/engine_helpers/vendored/envs/sokoban_env_two_player.py +122 -0
  145. synth_ai/environments/examples/sokoban/engine_helpers/vendored/envs/sokoban_env_variations.py +394 -0
  146. synth_ai/environments/examples/sokoban/environment.py +228 -0
  147. synth_ai/environments/examples/sokoban/generate_verified_puzzles.py +438 -0
  148. synth_ai/environments/examples/sokoban/puzzle_loader.py +311 -0
  149. synth_ai/environments/examples/sokoban/taskset.py +425 -0
  150. synth_ai/environments/examples/sokoban/units/astar_common.py +94 -0
  151. synth_ai/environments/examples/sokoban/units/test_building_task_set.py +49 -0
  152. synth_ai/environments/examples/sokoban/units/test_false_positive.py +120 -0
  153. synth_ai/environments/examples/sokoban/units/test_simple_run_through_environment.py +119 -0
  154. synth_ai/environments/examples/sokoban/units/test_sokoban_environment.py +98 -0
  155. synth_ai/environments/examples/sokoban/units/test_tree.py +364 -0
  156. synth_ai/environments/examples/tictactoe/__init__.py +1 -0
  157. synth_ai/environments/examples/tictactoe/agent_demos/test_synth_react.py +266 -0
  158. synth_ai/environments/examples/tictactoe/agent_demos/test_tictactoe_react_agent.py +470 -0
  159. synth_ai/environments/examples/tictactoe/engine.py +368 -0
  160. synth_ai/environments/examples/tictactoe/environment.py +239 -0
  161. synth_ai/environments/examples/tictactoe/taskset.py +214 -0
  162. synth_ai/environments/examples/tictactoe/units/test_tictactoe_engine.py +393 -0
  163. synth_ai/environments/examples/tictactoe/units/test_tictactoe_environment.py +493 -0
  164. synth_ai/environments/examples/tictactoe/units/test_tictactoe_taskset.py +191 -0
  165. synth_ai/environments/examples/verilog/__init__.py +10 -0
  166. synth_ai/environments/examples/verilog/agent_demos/test_synth_react.py +520 -0
  167. synth_ai/environments/examples/verilog/engine.py +328 -0
  168. synth_ai/environments/examples/verilog/environment.py +349 -0
  169. synth_ai/environments/examples/verilog/taskset.py +418 -0
  170. synth_ai/environments/examples/verilog/units/test_verilog_engine.py +466 -0
  171. synth_ai/environments/examples/verilog/units/test_verilog_environment.py +585 -0
  172. synth_ai/environments/examples/verilog/units/test_verilog_integration.py +383 -0
  173. synth_ai/environments/examples/verilog/units/test_verilog_taskset.py +457 -0
  174. synth_ai/environments/reproducibility/core.py +42 -0
  175. synth_ai/environments/reproducibility/tree.py +364 -0
  176. synth_ai/environments/service/app.py +78 -0
  177. synth_ai/environments/service/core_routes.py +775 -0
  178. synth_ai/environments/service/external_registry.py +57 -0
  179. synth_ai/environments/service/registry.py +9 -0
  180. synth_ai/environments/stateful/__init__.py +1 -0
  181. synth_ai/environments/stateful/core.py +28 -0
  182. synth_ai/environments/stateful/engine.py +21 -0
  183. synth_ai/environments/stateful/state.py +7 -0
  184. synth_ai/environments/tasks/api.py +19 -0
  185. synth_ai/environments/tasks/core.py +78 -0
  186. synth_ai/environments/tasks/filters.py +39 -0
  187. synth_ai/environments/tasks/utils.py +89 -0
  188. synth_ai/environments/v0_observability/history.py +3 -0
  189. synth_ai/environments/v0_observability/log.py +2 -0
  190. synth_ai/lm/caching/constants.py +1 -0
  191. synth_ai/{zyk/lms → lm}/caching/ephemeral.py +4 -8
  192. synth_ai/{zyk/lms → lm}/caching/handler.py +15 -15
  193. synth_ai/{zyk/lms → lm}/caching/initialize.py +2 -4
  194. synth_ai/{zyk/lms → lm}/caching/persistent.py +4 -10
  195. synth_ai/{zyk/lms → lm}/config.py +2 -1
  196. synth_ai/{zyk/lms → lm}/constants.py +2 -2
  197. synth_ai/{zyk/lms → lm}/core/all.py +10 -10
  198. synth_ai/{zyk/lms → lm}/core/main.py +57 -33
  199. synth_ai/{zyk/lms → lm}/core/vendor_clients.py +12 -10
  200. synth_ai/lm/cost/monitor.py +1 -0
  201. synth_ai/lm/cost/statefulness.py +1 -0
  202. synth_ai/lm/provider_support/__init__.py +8 -0
  203. synth_ai/lm/provider_support/anthropic.py +945 -0
  204. synth_ai/lm/provider_support/openai.py +1115 -0
  205. synth_ai/lm/provider_support/suppress_logging.py +31 -0
  206. synth_ai/{zyk/lms → lm}/structured_outputs/handler.py +58 -80
  207. synth_ai/{zyk/lms → lm}/structured_outputs/inject.py +6 -20
  208. synth_ai/{zyk/lms → lm}/structured_outputs/rehabilitate.py +6 -12
  209. synth_ai/{zyk/lms → lm}/vendors/core/anthropic_api.py +21 -30
  210. synth_ai/{zyk/lms → lm}/vendors/core/gemini_api.py +37 -32
  211. synth_ai/{zyk/lms → lm}/vendors/core/mistral_api.py +19 -28
  212. synth_ai/{zyk/lms → lm}/vendors/core/openai_api.py +26 -36
  213. synth_ai/{zyk/lms → lm}/vendors/openai_standard.py +29 -33
  214. synth_ai/{zyk/lms → lm}/vendors/retries.py +1 -1
  215. synth_ai/lm/vendors/supported/__init__.py +0 -0
  216. synth_ai/{zyk/lms → lm}/vendors/supported/custom_endpoint.py +131 -118
  217. synth_ai/{zyk/lms → lm}/vendors/supported/deepseek.py +4 -8
  218. synth_ai/{zyk/lms → lm}/vendors/supported/grok.py +6 -8
  219. synth_ai/{zyk/lms → lm}/vendors/supported/groq.py +1 -1
  220. synth_ai/{zyk/lms → lm}/vendors/supported/ollama.py +2 -2
  221. synth_ai/{zyk/lms → lm}/vendors/supported/openrouter.py +18 -16
  222. synth_ai/{zyk/lms → lm}/vendors/supported/together.py +1 -1
  223. synth_ai/tracing/__init__.py +0 -0
  224. synth_ai/tracing/abstractions.py +224 -0
  225. synth_ai/tracing/base_client.py +91 -0
  226. synth_ai/tracing/client_manager.py +131 -0
  227. synth_ai/tracing/config.py +140 -0
  228. synth_ai/tracing/context.py +146 -0
  229. synth_ai/tracing/decorators.py +679 -0
  230. synth_ai/tracing/events/__init__.py +0 -0
  231. synth_ai/tracing/events/manage.py +147 -0
  232. synth_ai/tracing/events/scope.py +86 -0
  233. synth_ai/tracing/events/store.py +227 -0
  234. synth_ai/tracing/immediate_client.py +152 -0
  235. synth_ai/tracing/local.py +18 -0
  236. synth_ai/tracing/log_client_base.py +74 -0
  237. synth_ai/tracing/retry_queue.py +187 -0
  238. synth_ai/tracing/trackers.py +515 -0
  239. synth_ai/tracing/upload.py +504 -0
  240. synth_ai/tracing/utils.py +9 -0
  241. synth_ai/zyk/__init__.py +28 -2
  242. synth_ai-0.2.1.dev0.dist-info/METADATA +349 -0
  243. synth_ai-0.2.1.dev0.dist-info/RECORD +261 -0
  244. synth_ai/zyk/lms/caching/constants.py +0 -1
  245. synth_ai/zyk/lms/cost/monitor.py +0 -1
  246. synth_ai/zyk/lms/cost/statefulness.py +0 -1
  247. synth_ai-0.1.9.dist-info/METADATA +0 -37
  248. synth_ai-0.1.9.dist-info/RECORD +0 -50
  249. /synth_ai/{zyk/lms/__init__.py → environments/reproducibility/helpers.py} +0 -0
  250. /synth_ai/{zyk/lms/caching → lm}/__init__.py +0 -0
  251. /synth_ai/{zyk/lms/core → lm/caching}/__init__.py +0 -0
  252. /synth_ai/{zyk/lms → lm}/caching/dbs.py +0 -0
  253. /synth_ai/{zyk/lms/cost → lm/core}/__init__.py +0 -0
  254. /synth_ai/{zyk/lms → lm}/core/exceptions.py +0 -0
  255. /synth_ai/{zyk/lms/structured_outputs → lm/cost}/__init__.py +0 -0
  256. /synth_ai/{zyk/lms/vendors → lm/structured_outputs}/__init__.py +0 -0
  257. /synth_ai/{zyk/lms → lm}/tools/__init__.py +0 -0
  258. /synth_ai/{zyk/lms → lm}/tools/base.py +0 -0
  259. /synth_ai/{zyk/lms/vendors/core → lm/vendors}/__init__.py +0 -0
  260. /synth_ai/{zyk/lms → lm}/vendors/base.py +0 -0
  261. /synth_ai/{zyk/lms/vendors/local → lm/vendors/core}/__init__.py +0 -0
  262. /synth_ai/{zyk/lms/vendors/supported → lm/vendors/local}/__init__.py +0 -0
  263. /synth_ai/{zyk/lms → lm}/vendors/local/ollama.py +0 -0
  264. {synth_ai-0.1.9.dist-info → synth_ai-0.2.1.dev0.dist-info}/WHEEL +0 -0
  265. {synth_ai-0.1.9.dist-info → synth_ai-0.2.1.dev0.dist-info}/licenses/LICENSE +0 -0
  266. {synth_ai-0.1.9.dist-info → synth_ai-0.2.1.dev0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,679 @@
1
+ # synth_sdk/tracing/decorators.py
2
+ import inspect
3
+ import logging
4
+ import os
5
+ import time
6
+ from functools import wraps
7
+ from typing import TYPE_CHECKING, Any, Callable, Dict, List, Literal, ParamSpec, TypeVar, Union
8
+
9
+ if TYPE_CHECKING:
10
+ from synth_ai.tracing.trackers import SynthTrackerAsync, SynthTrackerSync
11
+
12
+ from synth_ai.tracing.abstractions import (
13
+ AgentComputeStep,
14
+ ArbitraryInputs,
15
+ ArbitraryOutputs,
16
+ EnvironmentComputeStep,
17
+ Event,
18
+ MessageInputs,
19
+ MessageOutputs,
20
+ )
21
+ from synth_ai.tracing.config import EventManagement, LoggingMode, Origin, TracingConfig
22
+ from synth_ai.tracing.context import (
23
+ get_current_context,
24
+ trace_context,
25
+ )
26
+ from synth_ai.tracing.events.manage import set_current_event
27
+ from synth_ai.tracing.events.store import event_store
28
+ from synth_ai.tracing.immediate_client import (
29
+ AsyncImmediateLogClient,
30
+ ImmediateLogClient,
31
+ )
32
+ from synth_ai.tracing.local import (
33
+ _local,
34
+ active_events_var,
35
+ logger,
36
+ )
37
+ from synth_ai.tracing.retry_queue import initialize_retry_queue, retry_queue
38
+ from synth_ai.tracing.trackers import (
39
+ synth_tracker_async,
40
+ synth_tracker_sync,
41
+ )
42
+ from synth_ai.tracing.utils import get_system_id
43
+
44
+ logger = logging.getLogger(__name__)
45
+
46
+ P = ParamSpec("P") # For capturing any parameters
47
+ R = TypeVar("R") # For capturing return type
48
+
49
+
50
+ def clear_current_event(event_type: str) -> None:
51
+ """Clear the current event from the appropriate storage based on context.
52
+
53
+ Args:
54
+ event_type: The type of event to clear
55
+ """
56
+ try:
57
+ # Check if we're in an async context
58
+ import asyncio
59
+
60
+ asyncio.get_running_loop()
61
+ # We're in async context
62
+ active_events = active_events_var.get()
63
+ if event_type in active_events:
64
+ del active_events[event_type]
65
+ active_events_var.set(active_events)
66
+ except RuntimeError:
67
+ # We're in sync context
68
+ if hasattr(_local, "active_events") and event_type in _local.active_events:
69
+ del _local.active_events[event_type]
70
+
71
+
72
+ # Cache the config to avoid repeated env lookups
73
+ def get_tracing_config() -> TracingConfig:
74
+ config = TracingConfig(
75
+ mode=LoggingMode.INSTANT
76
+ if os.getenv("SYNTH_LOGGING_MODE") == "instant"
77
+ else LoggingMode.DEFERRED,
78
+ api_key=os.getenv("SYNTH_API_KEY", ""),
79
+ base_url=os.getenv("SYNTH_ENDPOINT_OVERRIDE", "https://agent-learning.onrender.com"),
80
+ )
81
+ # Initialize retry queue with config if needed
82
+ initialize_retry_queue(config)
83
+ return config
84
+
85
+
86
+ def process_retry_queue_sync() -> None:
87
+ """Process the retry queue synchronously."""
88
+ try:
89
+ success, failure = retry_queue.process_sync()
90
+ if success or failure:
91
+ logger.info(f"Processed retry queue: {success} succeeded, {failure} failed")
92
+ except Exception as e:
93
+ logger.error(f"Error processing retry queue: {e}")
94
+
95
+
96
+ async def process_retry_queue_async() -> None:
97
+ """Process the retry queue asynchronously."""
98
+ try:
99
+ success, failure = await retry_queue.process_async()
100
+ if success or failure:
101
+ logger.info(f"Processed retry queue: {success} succeeded, {failure} failed")
102
+ except Exception as e:
103
+ logger.error(f"Error processing retry queue: {e}")
104
+
105
+
106
+ def trace_event_sync(
107
+ event_type: str,
108
+ finetune_step: bool = True,
109
+ origin: Origin = Origin.AGENT,
110
+ log_result: bool = False,
111
+ manage_event: EventManagement = EventManagement.CREATE_AND_END,
112
+ increment_partition: bool = True,
113
+ verbose: bool = False,
114
+ ) -> Callable[[Callable[P, R]], Callable[P, R]]:
115
+ """Decorator for tracing synchronous function execution.
116
+
117
+ Args:
118
+ event_type: Type of event being traced (e.g., "inference", "training")
119
+ finetune_step: Whether this step should be used for fine-tuning
120
+ origin: Source of computation (AI/model or external system)
121
+ log_result: Whether to log the function's return value
122
+ manage_event: Controls the lifecycle of the event
123
+ increment_partition: Whether to increment the partition index
124
+ verbose: Whether to print debug information
125
+
126
+ Example:
127
+ >>> @trace_event_sync("inference")
128
+ ... def process_input(self, text: str) -> str:
129
+ ... return f"Processed: {text}"
130
+
131
+ Returns:
132
+ A decorator that wraps the function and traces its execution
133
+ """
134
+
135
+ def decorator(func: Callable[P, R]) -> Callable[P, R]:
136
+ @wraps(func)
137
+ def wrapper(*args, **kwargs):
138
+ # Determine the instance (self) if it's a method
139
+ if not hasattr(func, "__self__") or not func.__self__:
140
+ if not args:
141
+ raise ValueError("Instance method expected, but no arguments were passed.")
142
+ self_instance = args[0]
143
+ else:
144
+ self_instance = func.__self__
145
+
146
+ # Ensure required attributes are present
147
+ required_attrs = ["system_instance_id", "system_name"]
148
+ for attr in required_attrs:
149
+ if not hasattr(self_instance, attr):
150
+ raise ValueError(
151
+ f"Instance of class '{self_instance.__class__.__name__}' missing required attribute '{attr}'"
152
+ )
153
+
154
+ # Use context manager for setup/cleanup
155
+ with trace_context(
156
+ system_name=self_instance.system_name,
157
+ system_id=get_system_id(self_instance.system_name),
158
+ system_instance_id=self_instance.system_instance_id,
159
+ system_instance_metadata=getattr(self_instance, "system_instance_metadata", None),
160
+ ):
161
+ # Initialize Trace
162
+ synth_tracker_sync.initialize()
163
+
164
+ event = None
165
+ compute_began = time.time()
166
+ try:
167
+ if manage_event in ["create", "create_and_end"]:
168
+ # Create new event
169
+ context = get_current_context()
170
+ event = Event(
171
+ system_instance_id=context["system_instance_id"],
172
+ event_type=event_type,
173
+ opened=compute_began,
174
+ closed=None,
175
+ partition_index=0,
176
+ agent_compute_step=None,
177
+ environment_compute_steps=[],
178
+ system_name=context["system_name"],
179
+ system_id=context["system_id"],
180
+ )
181
+ if increment_partition:
182
+ event.partition_index = event_store.increment_partition(
183
+ context["system_name"],
184
+ context["system_id"],
185
+ context["system_instance_id"],
186
+ )
187
+ logger.debug(f"Incremented partition to: {event.partition_index}")
188
+ set_current_event(event, decorator_type="sync")
189
+
190
+ # Automatically trace function inputs
191
+ bound_args = inspect.signature(func).bind(*args, **kwargs)
192
+ bound_args.apply_defaults()
193
+ for param, value in bound_args.arguments.items():
194
+ if param == "self":
195
+ continue
196
+ # print("Tracking state - 178")
197
+ # synth_tracker_sync.track_state(
198
+ # variable_name=param, variable_value=value, origin=origin
199
+ # )
200
+
201
+ # Execute the function
202
+ result = func(*args, **kwargs)
203
+
204
+ # Automatically trace function output
205
+ # track_result(result, synth_tracker_sync, origin)
206
+
207
+ # Collect traced inputs and outputs
208
+ traced_inputs, traced_outputs = synth_tracker_sync.get_traced_data()
209
+
210
+ compute_steps_by_origin: Dict[
211
+ Literal["agent", "environment"], Dict[str, List[Any]]
212
+ ] = {
213
+ "agent": {"inputs": [], "outputs": []},
214
+ "environment": {"inputs": [], "outputs": []},
215
+ }
216
+
217
+ # Organize traced data by origin
218
+ # print("N items in traced inputs: ", len(traced_inputs), ["messages" in item for item in traced_inputs], [item.keys() for item in traced_inputs])
219
+ for item in traced_inputs:
220
+ # print("Item: ", item)
221
+ var_origin = item["origin"]
222
+ if "variable_value" in item and "variable_name" in item:
223
+ # Standard variable input
224
+ compute_steps_by_origin[var_origin]["inputs"].append(
225
+ ArbitraryInputs(
226
+ inputs={item["variable_name"]: item["variable_value"]}
227
+ )
228
+ )
229
+ compute_steps_by_origin[var_origin]["finetune"] = (
230
+ item["finetune"] if "finetune" in item else False
231
+ )
232
+ compute_steps_by_origin[var_origin]["model_name"] = (
233
+ item["model_name"] if "model_name" in item else None
234
+ )
235
+ compute_steps_by_origin[var_origin]["model_params"] = (
236
+ item["model_params"] if "model_params" in item else None
237
+ )
238
+ elif "messages" in item:
239
+ # Message input from track_lm
240
+ compute_steps_by_origin[var_origin]["inputs"].append(
241
+ MessageInputs(messages=item["messages"])
242
+ )
243
+ finetune = finetune_step or item["finetune"]
244
+ compute_steps_by_origin[var_origin]["finetune"] = finetune
245
+
246
+ model_name = item["model_name"]
247
+ model_params = item["model_params"]
248
+ compute_steps_by_origin[var_origin]["model_name"] = model_name
249
+ compute_steps_by_origin[var_origin]["model_params"] = model_params
250
+ else:
251
+ logger.warning(f"Unhandled traced input item: {item}")
252
+
253
+ # print("N items in traced outputs: ", len(traced_outputs), ["messages" in item for item in traced_outputs], [item.keys() for item in traced_outputs])
254
+
255
+ # Temporary Kludge
256
+ for item in [i for i in traced_outputs if "messages" in i]:
257
+ var_origin = item["origin"]
258
+ if "variable_value" in item and "variable_name" in item:
259
+ # Standard variable output
260
+ compute_steps_by_origin[var_origin]["outputs"].append(
261
+ ArbitraryOutputs(
262
+ outputs={item["variable_name"]: item["variable_value"]}
263
+ )
264
+ )
265
+ elif "messages" in item:
266
+ # Message output from track_lm
267
+ compute_steps_by_origin[var_origin]["outputs"].append(
268
+ MessageOutputs(messages=item["messages"])
269
+ )
270
+ else:
271
+ logger.warning(f"Unhandled traced output item: {item}")
272
+
273
+ # Capture compute end time
274
+ compute_ended = time.time()
275
+
276
+ # Create compute steps grouped by origin
277
+ for var_origin in ["agent", "environment"]:
278
+ inputs = compute_steps_by_origin[var_origin]["inputs"]
279
+ outputs = compute_steps_by_origin[var_origin]["outputs"]
280
+ should_learn = (
281
+ compute_steps_by_origin[var_origin]["finetune"]
282
+ if "finetune" in compute_steps_by_origin[var_origin]
283
+ else False
284
+ )
285
+ model_name = (
286
+ compute_steps_by_origin[var_origin]["model_name"]
287
+ if "model_name" in compute_steps_by_origin[var_origin]
288
+ else None
289
+ )
290
+ model_params = (
291
+ compute_steps_by_origin[var_origin]["model_params"]
292
+ if "model_params" in compute_steps_by_origin[var_origin]
293
+ else None
294
+ )
295
+ if inputs or outputs:
296
+ event_order = (
297
+ 1 + len(event.environment_compute_steps) + 1 if event else 1
298
+ )
299
+ compute_step = (
300
+ AgentComputeStep(
301
+ model_name=model_name,
302
+ model_params=model_params,
303
+ should_learn=should_learn,
304
+ event_order=event_order,
305
+ compute_began=compute_began,
306
+ compute_ended=compute_ended,
307
+ compute_input=inputs,
308
+ compute_output=outputs,
309
+ )
310
+ if var_origin == "agent"
311
+ else EnvironmentComputeStep(
312
+ event_order=event_order,
313
+ compute_began=compute_began,
314
+ compute_ended=compute_ended,
315
+ compute_input=inputs,
316
+ compute_output=outputs,
317
+ )
318
+ )
319
+ if event:
320
+ if var_origin == "agent":
321
+ event.agent_compute_step = compute_step
322
+ else:
323
+ event.environment_compute_steps.append(compute_step)
324
+
325
+ # Optionally log the function result
326
+ if log_result:
327
+ logger.info(f"Function result: {result}")
328
+
329
+ # Handle event management after function execution
330
+ if manage_event in ("end", "create_and_end"):
331
+ context = get_current_context()
332
+ current_event = _local.active_events.get(event_type)
333
+ if current_event:
334
+ current_event.closed = compute_ended
335
+ config = get_tracing_config()
336
+ if config.mode == LoggingMode.INSTANT:
337
+ client = ImmediateLogClient(config)
338
+ client.send_event(current_event, context)
339
+ # print("Adding this event: ", current_event)
340
+ event_store.add_event(
341
+ context["system_name"],
342
+ context["system_id"],
343
+ context["system_instance_id"],
344
+ current_event,
345
+ )
346
+
347
+ # Process retry queue after successful execution
348
+ process_retry_queue_sync()
349
+
350
+ return result
351
+ except Exception as e:
352
+ logger.error(f"Exception in traced function '{func.__name__}': {e}")
353
+ raise
354
+
355
+ return wrapper
356
+
357
+ return decorator
358
+
359
+
360
+ def trace_event_async(
361
+ event_type: str,
362
+ finetune_step: bool = True,
363
+ origin: Origin = Origin.AGENT,
364
+ log_result: bool = False,
365
+ manage_event: EventManagement = EventManagement.CREATE_AND_END,
366
+ increment_partition: bool = True,
367
+ verbose: bool = False,
368
+ ) -> Callable[[Callable[P, R]], Callable[P, R]]:
369
+ """Decorator for tracing asynchronous function execution.
370
+
371
+ Args:
372
+ event_type: Type of event being traced (e.g., "inference", "training")
373
+ finetune_step: Whether this step should be used for fine-tuning
374
+ origin: Source of computation (AI/model or external system)
375
+ log_result: Whether to log the function's return value
376
+ manage_event: Controls the lifecycle of the event
377
+ increment_partition: Whether to increment the partition index
378
+ verbose: Whether to print debug information
379
+
380
+ Example:
381
+ >>> @trace_event_async("inference")
382
+ ... async def process_input(self, text: str) -> str:
383
+ ... return f"Processed: {text}"
384
+
385
+ Returns:
386
+ A decorator that wraps the async function and traces its execution
387
+ """
388
+
389
+ def decorator(func: Callable[P, R]) -> Callable[P, R]:
390
+ @wraps(func)
391
+ async def async_wrapper(*args, **kwargs):
392
+ # Determine the instance (self) if it's a method
393
+ if not hasattr(func, "__self__") or not func.__self__:
394
+ if not args:
395
+ raise ValueError("Instance method expected, but no arguments were passed.")
396
+ self_instance = args[0]
397
+ else:
398
+ self_instance = func.__self__
399
+
400
+ # Ensure required attributes are present
401
+ required_attrs = ["system_instance_id", "system_name"]
402
+ for attr in required_attrs:
403
+ if not hasattr(self_instance, attr):
404
+ raise ValueError(
405
+ f"Instance of class '{self_instance.__class__.__name__}' missing required attribute '{attr}'"
406
+ )
407
+
408
+ # Use context manager for setup/cleanup
409
+ with trace_context(
410
+ system_name=self_instance.system_name,
411
+ system_id=get_system_id(self_instance.system_name),
412
+ system_instance_id=self_instance.system_instance_id,
413
+ system_instance_metadata=getattr(self_instance, "system_instance_metadata", None),
414
+ ):
415
+ # Initialize AsyncTrace
416
+ synth_tracker_async.initialize()
417
+
418
+ event = None
419
+ compute_began = time.time()
420
+ try:
421
+ if manage_event in ["create", "create_and_end"]:
422
+ # Create new event
423
+ context = get_current_context()
424
+ event = Event(
425
+ system_instance_id=context["system_instance_id"],
426
+ event_type=event_type,
427
+ opened=compute_began,
428
+ closed=None,
429
+ partition_index=0,
430
+ agent_compute_step=None,
431
+ environment_compute_steps=[],
432
+ system_name=context["system_name"],
433
+ system_id=context["system_id"],
434
+ )
435
+ if increment_partition:
436
+ event.partition_index = event_store.increment_partition(
437
+ context["system_name"],
438
+ context["system_id"],
439
+ context["system_instance_id"],
440
+ )
441
+ logger.debug(f"Incremented partition to: {event.partition_index}")
442
+ set_current_event(event, decorator_type="async")
443
+
444
+ # Automatically trace function inputs
445
+ bound_args = inspect.signature(func).bind(*args, **kwargs)
446
+ bound_args.apply_defaults()
447
+ for param, value in bound_args.arguments.items():
448
+ if param == "self":
449
+ continue
450
+ # print("Tracking state - 412")
451
+ # synth_tracker_async.track_state(
452
+ # variable_name=param,
453
+ # variable_value=value,
454
+ # origin=origin,
455
+ # io_type="input",
456
+ # )
457
+
458
+ # Execute the coroutine
459
+ result = await func(*args, **kwargs)
460
+
461
+ # Automatically trace function output
462
+ # track_result(result, synth_tracker_async, origin)
463
+
464
+ # Collect traced inputs and outputs
465
+ traced_inputs, traced_outputs = synth_tracker_async.get_traced_data()
466
+
467
+ compute_steps_by_origin: Dict[
468
+ Literal["agent", "environment"], Dict[str, List[Any]]
469
+ ] = {
470
+ "agent": {"inputs": [], "outputs": []},
471
+ "environment": {"inputs": [], "outputs": []},
472
+ }
473
+
474
+ # Organize traced data by origin
475
+ for item in traced_inputs:
476
+ var_origin = item["origin"]
477
+ if "variable_value" in item and "variable_name" in item:
478
+ # Standard variable input
479
+ compute_steps_by_origin[var_origin]["inputs"].append(
480
+ ArbitraryInputs(
481
+ inputs={item["variable_name"]: item["variable_value"]}
482
+ )
483
+ )
484
+ elif "messages" in item:
485
+ # Message input from track_lm
486
+ compute_steps_by_origin[var_origin]["inputs"].append(
487
+ MessageInputs(messages=item["messages"])
488
+ )
489
+ # compute_steps_by_origin[var_origin]["inputs"].append(
490
+ # ArbitraryInputs(
491
+ # inputs={"model_name": item["model_name"]}
492
+ # )
493
+ # )
494
+ finetune = finetune_step or item["finetune"]
495
+ compute_steps_by_origin[var_origin]["finetune"] = finetune
496
+
497
+ model_name = item["model_name"]
498
+ model_params = item["model_params"]
499
+ compute_steps_by_origin[var_origin]["model_name"] = model_name
500
+ compute_steps_by_origin[var_origin]["model_params"] = model_params
501
+ else:
502
+ logger.warning(f"Unhandled traced input item: {item}")
503
+
504
+ for item in traced_outputs:
505
+ var_origin = item["origin"]
506
+ if "variable_value" in item and "variable_name" in item:
507
+ # Standard variable output
508
+ compute_steps_by_origin[var_origin]["outputs"].append(
509
+ ArbitraryOutputs(
510
+ outputs={item["variable_name"]: item["variable_value"]}
511
+ )
512
+ )
513
+ elif "messages" in item:
514
+ # Message output from track_lm
515
+ compute_steps_by_origin[var_origin]["outputs"].append(
516
+ MessageOutputs(messages=item["messages"])
517
+ )
518
+ else:
519
+ logger.warning(f"Unhandled traced output item: {item}")
520
+
521
+ compute_ended = time.time()
522
+ # Create compute steps grouped by origin
523
+ for var_origin in ["agent", "environment"]:
524
+ inputs = compute_steps_by_origin[var_origin]["inputs"]
525
+ outputs = compute_steps_by_origin[var_origin]["outputs"]
526
+ model_name = (
527
+ compute_steps_by_origin[var_origin]["model_name"]
528
+ if "model_name" in compute_steps_by_origin[var_origin]
529
+ else None
530
+ )
531
+ model_params = (
532
+ compute_steps_by_origin[var_origin]["model_params"]
533
+ if "model_params" in compute_steps_by_origin[var_origin]
534
+ else None
535
+ )
536
+ should_learn = (
537
+ compute_steps_by_origin[var_origin]["finetune"]
538
+ if "finetune" in compute_steps_by_origin[var_origin]
539
+ else False
540
+ )
541
+ if inputs or outputs:
542
+ event_order = (
543
+ 1 + len(event.environment_compute_steps) + 1 if event else 1
544
+ )
545
+ compute_step = (
546
+ AgentComputeStep(
547
+ model_name=model_name,
548
+ model_params=model_params,
549
+ should_learn=should_learn,
550
+ event_order=event_order,
551
+ compute_began=compute_began,
552
+ compute_ended=compute_ended,
553
+ compute_input=inputs,
554
+ compute_output=outputs,
555
+ )
556
+ if var_origin == "agent"
557
+ else EnvironmentComputeStep(
558
+ event_order=event_order,
559
+ compute_began=compute_began,
560
+ compute_ended=compute_ended,
561
+ compute_input=inputs,
562
+ compute_output=outputs,
563
+ )
564
+ )
565
+ if event:
566
+ if var_origin == "agent":
567
+ event.agent_compute_step = compute_step
568
+ else:
569
+ event.environment_compute_steps.append(compute_step)
570
+
571
+ # Optionally log the function result
572
+ if log_result:
573
+ logger.info(f"Function result: {result}")
574
+
575
+ # Handle event management after function execution
576
+ if manage_event in ["end", "create_and_end"]:
577
+ context = get_current_context()
578
+ current_event = active_events_var.get().get(event_type)
579
+ if current_event:
580
+ current_event.closed = compute_ended
581
+
582
+ # Get the config to determine logging mode
583
+ config = get_tracing_config()
584
+
585
+ # If immediate logging is enabled, send the event now
586
+ if config.mode == LoggingMode.INSTANT:
587
+ client = AsyncImmediateLogClient(config)
588
+ await client.send_event(current_event, context)
589
+
590
+ # Always store in event_store as backup
591
+ event_store.add_event(
592
+ context["system_name"],
593
+ context["system_id"],
594
+ context["system_instance_id"],
595
+ current_event,
596
+ )
597
+ active_events = active_events_var.get()
598
+ del active_events[event_type]
599
+ active_events_var.set(active_events)
600
+
601
+ # Process retry queue after successful execution
602
+ await process_retry_queue_async()
603
+
604
+ return result
605
+ except Exception as e:
606
+ logger.error(f"Exception in traced function '{func.__name__}': {e}")
607
+ raise
608
+
609
+ return async_wrapper
610
+
611
+ return decorator
612
+
613
+
614
+ def trace_system(
615
+ origin: Literal["agent", "environment"],
616
+ event_type: str,
617
+ log_result: bool = False,
618
+ manage_event: Literal["create", "end", "lazy_end", None] = None,
619
+ increment_partition: bool = False,
620
+ verbose: bool = False,
621
+ ) -> Callable:
622
+ """
623
+ Decorator that chooses the correct tracing method (sync or async) based on
624
+ whether the wrapped function is synchronous or asynchronous.
625
+
626
+ Purpose is to keep track of inputs and outputs for compute steps for both sync and async functions.
627
+ """
628
+
629
+ def decorator(func: Callable) -> Callable:
630
+ # Check if the function is async or sync
631
+ if inspect.iscoroutinefunction(func) or inspect.isasyncgenfunction(func):
632
+ # Use async tracing
633
+ # logger.debug("Using async tracing")
634
+ async_decorator = trace_event_async(
635
+ origin,
636
+ event_type,
637
+ log_result,
638
+ manage_event,
639
+ increment_partition,
640
+ verbose,
641
+ )
642
+ return async_decorator(func)
643
+ else:
644
+ # Use sync tracing
645
+ # logger.debug("Using sync tracing")
646
+ sync_decorator = trace_event_sync(
647
+ origin,
648
+ event_type,
649
+ log_result,
650
+ manage_event,
651
+ increment_partition,
652
+ verbose,
653
+ )
654
+ return sync_decorator(func)
655
+
656
+ return decorator
657
+
658
+
659
+ def track_result(
660
+ result: Any,
661
+ tracker: Union["SynthTrackerSync", "SynthTrackerAsync"],
662
+ origin: Literal["agent", "environment"],
663
+ ) -> None:
664
+ # Helper function to track results, including tuple unpacking
665
+ if isinstance(result, tuple):
666
+ # Track each element of the tuple that matches valid types
667
+ for i, item in enumerate(result):
668
+ try:
669
+ print("Tracking state - 631")
670
+ tracker.track_state(variable_name=f"result_{i}", variable_value=item, origin=origin)
671
+ except Exception as e:
672
+ logger.warning(f"Could not track tuple element {i}: {str(e)}")
673
+ else:
674
+ # Track single result as before
675
+ try:
676
+ print("Tracking state - 640")
677
+ tracker.track_state(variable_name="result", variable_value=result, origin=origin)
678
+ except Exception as e:
679
+ logger.warning(f"Could not track result: {str(e)}")
File without changes