nvidia-nat 1.1.0a20251020__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 (480) hide show
  1. aiq/__init__.py +66 -0
  2. nat/agent/__init__.py +0 -0
  3. nat/agent/base.py +265 -0
  4. nat/agent/dual_node.py +72 -0
  5. nat/agent/prompt_optimizer/__init__.py +0 -0
  6. nat/agent/prompt_optimizer/prompt.py +68 -0
  7. nat/agent/prompt_optimizer/register.py +149 -0
  8. nat/agent/react_agent/__init__.py +0 -0
  9. nat/agent/react_agent/agent.py +394 -0
  10. nat/agent/react_agent/output_parser.py +104 -0
  11. nat/agent/react_agent/prompt.py +44 -0
  12. nat/agent/react_agent/register.py +168 -0
  13. nat/agent/reasoning_agent/__init__.py +0 -0
  14. nat/agent/reasoning_agent/reasoning_agent.py +227 -0
  15. nat/agent/register.py +23 -0
  16. nat/agent/rewoo_agent/__init__.py +0 -0
  17. nat/agent/rewoo_agent/agent.py +593 -0
  18. nat/agent/rewoo_agent/prompt.py +107 -0
  19. nat/agent/rewoo_agent/register.py +175 -0
  20. nat/agent/tool_calling_agent/__init__.py +0 -0
  21. nat/agent/tool_calling_agent/agent.py +246 -0
  22. nat/agent/tool_calling_agent/register.py +129 -0
  23. nat/authentication/__init__.py +14 -0
  24. nat/authentication/api_key/__init__.py +14 -0
  25. nat/authentication/api_key/api_key_auth_provider.py +96 -0
  26. nat/authentication/api_key/api_key_auth_provider_config.py +124 -0
  27. nat/authentication/api_key/register.py +26 -0
  28. nat/authentication/credential_validator/__init__.py +14 -0
  29. nat/authentication/credential_validator/bearer_token_validator.py +557 -0
  30. nat/authentication/exceptions/__init__.py +14 -0
  31. nat/authentication/exceptions/api_key_exceptions.py +38 -0
  32. nat/authentication/http_basic_auth/__init__.py +0 -0
  33. nat/authentication/http_basic_auth/http_basic_auth_provider.py +81 -0
  34. nat/authentication/http_basic_auth/register.py +30 -0
  35. nat/authentication/interfaces.py +96 -0
  36. nat/authentication/oauth2/__init__.py +14 -0
  37. nat/authentication/oauth2/oauth2_auth_code_flow_provider.py +140 -0
  38. nat/authentication/oauth2/oauth2_auth_code_flow_provider_config.py +39 -0
  39. nat/authentication/oauth2/oauth2_resource_server_config.py +124 -0
  40. nat/authentication/oauth2/register.py +25 -0
  41. nat/authentication/register.py +20 -0
  42. nat/builder/__init__.py +0 -0
  43. nat/builder/builder.py +317 -0
  44. nat/builder/component_utils.py +320 -0
  45. nat/builder/context.py +321 -0
  46. nat/builder/embedder.py +24 -0
  47. nat/builder/eval_builder.py +166 -0
  48. nat/builder/evaluator.py +29 -0
  49. nat/builder/framework_enum.py +25 -0
  50. nat/builder/front_end.py +73 -0
  51. nat/builder/function.py +714 -0
  52. nat/builder/function_base.py +380 -0
  53. nat/builder/function_info.py +625 -0
  54. nat/builder/intermediate_step_manager.py +206 -0
  55. nat/builder/llm.py +25 -0
  56. nat/builder/retriever.py +25 -0
  57. nat/builder/user_interaction_manager.py +78 -0
  58. nat/builder/workflow.py +160 -0
  59. nat/builder/workflow_builder.py +1365 -0
  60. nat/cli/__init__.py +14 -0
  61. nat/cli/cli_utils/__init__.py +0 -0
  62. nat/cli/cli_utils/config_override.py +231 -0
  63. nat/cli/cli_utils/validation.py +37 -0
  64. nat/cli/commands/__init__.py +0 -0
  65. nat/cli/commands/configure/__init__.py +0 -0
  66. nat/cli/commands/configure/channel/__init__.py +0 -0
  67. nat/cli/commands/configure/channel/add.py +28 -0
  68. nat/cli/commands/configure/channel/channel.py +34 -0
  69. nat/cli/commands/configure/channel/remove.py +30 -0
  70. nat/cli/commands/configure/channel/update.py +30 -0
  71. nat/cli/commands/configure/configure.py +33 -0
  72. nat/cli/commands/evaluate.py +139 -0
  73. nat/cli/commands/info/__init__.py +14 -0
  74. nat/cli/commands/info/info.py +47 -0
  75. nat/cli/commands/info/list_channels.py +32 -0
  76. nat/cli/commands/info/list_components.py +128 -0
  77. nat/cli/commands/mcp/__init__.py +14 -0
  78. nat/cli/commands/mcp/mcp.py +986 -0
  79. nat/cli/commands/object_store/__init__.py +14 -0
  80. nat/cli/commands/object_store/object_store.py +227 -0
  81. nat/cli/commands/optimize.py +90 -0
  82. nat/cli/commands/registry/__init__.py +14 -0
  83. nat/cli/commands/registry/publish.py +88 -0
  84. nat/cli/commands/registry/pull.py +118 -0
  85. nat/cli/commands/registry/registry.py +36 -0
  86. nat/cli/commands/registry/remove.py +108 -0
  87. nat/cli/commands/registry/search.py +153 -0
  88. nat/cli/commands/sizing/__init__.py +14 -0
  89. nat/cli/commands/sizing/calc.py +297 -0
  90. nat/cli/commands/sizing/sizing.py +27 -0
  91. nat/cli/commands/start.py +257 -0
  92. nat/cli/commands/uninstall.py +81 -0
  93. nat/cli/commands/validate.py +47 -0
  94. nat/cli/commands/workflow/__init__.py +14 -0
  95. nat/cli/commands/workflow/templates/__init__.py.j2 +0 -0
  96. nat/cli/commands/workflow/templates/config.yml.j2 +17 -0
  97. nat/cli/commands/workflow/templates/pyproject.toml.j2 +25 -0
  98. nat/cli/commands/workflow/templates/register.py.j2 +4 -0
  99. nat/cli/commands/workflow/templates/workflow.py.j2 +50 -0
  100. nat/cli/commands/workflow/workflow.py +37 -0
  101. nat/cli/commands/workflow/workflow_commands.py +403 -0
  102. nat/cli/entrypoint.py +141 -0
  103. nat/cli/main.py +60 -0
  104. nat/cli/register_workflow.py +522 -0
  105. nat/cli/type_registry.py +1069 -0
  106. nat/control_flow/__init__.py +0 -0
  107. nat/control_flow/register.py +20 -0
  108. nat/control_flow/router_agent/__init__.py +0 -0
  109. nat/control_flow/router_agent/agent.py +329 -0
  110. nat/control_flow/router_agent/prompt.py +48 -0
  111. nat/control_flow/router_agent/register.py +91 -0
  112. nat/control_flow/sequential_executor.py +166 -0
  113. nat/data_models/__init__.py +14 -0
  114. nat/data_models/agent.py +34 -0
  115. nat/data_models/api_server.py +843 -0
  116. nat/data_models/authentication.py +245 -0
  117. nat/data_models/common.py +171 -0
  118. nat/data_models/component.py +60 -0
  119. nat/data_models/component_ref.py +179 -0
  120. nat/data_models/config.py +434 -0
  121. nat/data_models/dataset_handler.py +169 -0
  122. nat/data_models/discovery_metadata.py +305 -0
  123. nat/data_models/embedder.py +27 -0
  124. nat/data_models/evaluate.py +130 -0
  125. nat/data_models/evaluator.py +26 -0
  126. nat/data_models/front_end.py +26 -0
  127. nat/data_models/function.py +64 -0
  128. nat/data_models/function_dependencies.py +80 -0
  129. nat/data_models/gated_field_mixin.py +242 -0
  130. nat/data_models/interactive.py +246 -0
  131. nat/data_models/intermediate_step.py +302 -0
  132. nat/data_models/invocation_node.py +38 -0
  133. nat/data_models/llm.py +27 -0
  134. nat/data_models/logging.py +26 -0
  135. nat/data_models/memory.py +27 -0
  136. nat/data_models/object_store.py +44 -0
  137. nat/data_models/optimizable.py +119 -0
  138. nat/data_models/optimizer.py +149 -0
  139. nat/data_models/profiler.py +54 -0
  140. nat/data_models/registry_handler.py +26 -0
  141. nat/data_models/retriever.py +30 -0
  142. nat/data_models/retry_mixin.py +35 -0
  143. nat/data_models/span.py +228 -0
  144. nat/data_models/step_adaptor.py +64 -0
  145. nat/data_models/streaming.py +33 -0
  146. nat/data_models/swe_bench_model.py +54 -0
  147. nat/data_models/telemetry_exporter.py +26 -0
  148. nat/data_models/temperature_mixin.py +44 -0
  149. nat/data_models/thinking_mixin.py +86 -0
  150. nat/data_models/top_p_mixin.py +44 -0
  151. nat/data_models/ttc_strategy.py +30 -0
  152. nat/embedder/__init__.py +0 -0
  153. nat/embedder/azure_openai_embedder.py +46 -0
  154. nat/embedder/nim_embedder.py +59 -0
  155. nat/embedder/openai_embedder.py +42 -0
  156. nat/embedder/register.py +22 -0
  157. nat/eval/__init__.py +14 -0
  158. nat/eval/config.py +62 -0
  159. nat/eval/dataset_handler/__init__.py +0 -0
  160. nat/eval/dataset_handler/dataset_downloader.py +106 -0
  161. nat/eval/dataset_handler/dataset_filter.py +52 -0
  162. nat/eval/dataset_handler/dataset_handler.py +431 -0
  163. nat/eval/evaluate.py +565 -0
  164. nat/eval/evaluator/__init__.py +14 -0
  165. nat/eval/evaluator/base_evaluator.py +77 -0
  166. nat/eval/evaluator/evaluator_model.py +58 -0
  167. nat/eval/intermediate_step_adapter.py +99 -0
  168. nat/eval/rag_evaluator/__init__.py +0 -0
  169. nat/eval/rag_evaluator/evaluate.py +178 -0
  170. nat/eval/rag_evaluator/register.py +143 -0
  171. nat/eval/register.py +26 -0
  172. nat/eval/remote_workflow.py +133 -0
  173. nat/eval/runners/__init__.py +14 -0
  174. nat/eval/runners/config.py +39 -0
  175. nat/eval/runners/multi_eval_runner.py +54 -0
  176. nat/eval/runtime_evaluator/__init__.py +14 -0
  177. nat/eval/runtime_evaluator/evaluate.py +123 -0
  178. nat/eval/runtime_evaluator/register.py +100 -0
  179. nat/eval/runtime_event_subscriber.py +52 -0
  180. nat/eval/swe_bench_evaluator/__init__.py +0 -0
  181. nat/eval/swe_bench_evaluator/evaluate.py +215 -0
  182. nat/eval/swe_bench_evaluator/register.py +36 -0
  183. nat/eval/trajectory_evaluator/__init__.py +0 -0
  184. nat/eval/trajectory_evaluator/evaluate.py +75 -0
  185. nat/eval/trajectory_evaluator/register.py +40 -0
  186. nat/eval/tunable_rag_evaluator/__init__.py +0 -0
  187. nat/eval/tunable_rag_evaluator/evaluate.py +242 -0
  188. nat/eval/tunable_rag_evaluator/register.py +52 -0
  189. nat/eval/usage_stats.py +41 -0
  190. nat/eval/utils/__init__.py +0 -0
  191. nat/eval/utils/eval_trace_ctx.py +89 -0
  192. nat/eval/utils/output_uploader.py +140 -0
  193. nat/eval/utils/tqdm_position_registry.py +40 -0
  194. nat/eval/utils/weave_eval.py +193 -0
  195. nat/experimental/__init__.py +0 -0
  196. nat/experimental/decorators/__init__.py +0 -0
  197. nat/experimental/decorators/experimental_warning_decorator.py +154 -0
  198. nat/experimental/test_time_compute/__init__.py +0 -0
  199. nat/experimental/test_time_compute/editing/__init__.py +0 -0
  200. nat/experimental/test_time_compute/editing/iterative_plan_refinement_editor.py +147 -0
  201. nat/experimental/test_time_compute/editing/llm_as_a_judge_editor.py +204 -0
  202. nat/experimental/test_time_compute/editing/motivation_aware_summarization.py +107 -0
  203. nat/experimental/test_time_compute/functions/__init__.py +0 -0
  204. nat/experimental/test_time_compute/functions/execute_score_select_function.py +105 -0
  205. nat/experimental/test_time_compute/functions/plan_select_execute_function.py +228 -0
  206. nat/experimental/test_time_compute/functions/ttc_tool_orchestration_function.py +205 -0
  207. nat/experimental/test_time_compute/functions/ttc_tool_wrapper_function.py +146 -0
  208. nat/experimental/test_time_compute/models/__init__.py +0 -0
  209. nat/experimental/test_time_compute/models/editor_config.py +132 -0
  210. nat/experimental/test_time_compute/models/scoring_config.py +112 -0
  211. nat/experimental/test_time_compute/models/search_config.py +120 -0
  212. nat/experimental/test_time_compute/models/selection_config.py +154 -0
  213. nat/experimental/test_time_compute/models/stage_enums.py +43 -0
  214. nat/experimental/test_time_compute/models/strategy_base.py +67 -0
  215. nat/experimental/test_time_compute/models/tool_use_config.py +41 -0
  216. nat/experimental/test_time_compute/models/ttc_item.py +48 -0
  217. nat/experimental/test_time_compute/register.py +35 -0
  218. nat/experimental/test_time_compute/scoring/__init__.py +0 -0
  219. nat/experimental/test_time_compute/scoring/llm_based_agent_scorer.py +168 -0
  220. nat/experimental/test_time_compute/scoring/llm_based_plan_scorer.py +168 -0
  221. nat/experimental/test_time_compute/scoring/motivation_aware_scorer.py +111 -0
  222. nat/experimental/test_time_compute/search/__init__.py +0 -0
  223. nat/experimental/test_time_compute/search/multi_llm_planner.py +128 -0
  224. nat/experimental/test_time_compute/search/multi_query_retrieval_search.py +122 -0
  225. nat/experimental/test_time_compute/search/single_shot_multi_plan_planner.py +128 -0
  226. nat/experimental/test_time_compute/selection/__init__.py +0 -0
  227. nat/experimental/test_time_compute/selection/best_of_n_selector.py +63 -0
  228. nat/experimental/test_time_compute/selection/llm_based_agent_output_selector.py +131 -0
  229. nat/experimental/test_time_compute/selection/llm_based_output_merging_selector.py +157 -0
  230. nat/experimental/test_time_compute/selection/llm_based_plan_selector.py +128 -0
  231. nat/experimental/test_time_compute/selection/threshold_selector.py +58 -0
  232. nat/front_ends/__init__.py +14 -0
  233. nat/front_ends/console/__init__.py +14 -0
  234. nat/front_ends/console/authentication_flow_handler.py +285 -0
  235. nat/front_ends/console/console_front_end_config.py +32 -0
  236. nat/front_ends/console/console_front_end_plugin.py +108 -0
  237. nat/front_ends/console/register.py +25 -0
  238. nat/front_ends/cron/__init__.py +14 -0
  239. nat/front_ends/fastapi/__init__.py +14 -0
  240. nat/front_ends/fastapi/auth_flow_handlers/__init__.py +0 -0
  241. nat/front_ends/fastapi/auth_flow_handlers/http_flow_handler.py +27 -0
  242. nat/front_ends/fastapi/auth_flow_handlers/websocket_flow_handler.py +142 -0
  243. nat/front_ends/fastapi/dask_client_mixin.py +65 -0
  244. nat/front_ends/fastapi/fastapi_front_end_config.py +272 -0
  245. nat/front_ends/fastapi/fastapi_front_end_controller.py +68 -0
  246. nat/front_ends/fastapi/fastapi_front_end_plugin.py +247 -0
  247. nat/front_ends/fastapi/fastapi_front_end_plugin_worker.py +1257 -0
  248. nat/front_ends/fastapi/html_snippets/__init__.py +14 -0
  249. nat/front_ends/fastapi/html_snippets/auth_code_grant_success.py +35 -0
  250. nat/front_ends/fastapi/intermediate_steps_subscriber.py +80 -0
  251. nat/front_ends/fastapi/job_store.py +602 -0
  252. nat/front_ends/fastapi/main.py +64 -0
  253. nat/front_ends/fastapi/message_handler.py +344 -0
  254. nat/front_ends/fastapi/message_validator.py +351 -0
  255. nat/front_ends/fastapi/register.py +25 -0
  256. nat/front_ends/fastapi/response_helpers.py +195 -0
  257. nat/front_ends/fastapi/step_adaptor.py +319 -0
  258. nat/front_ends/fastapi/utils.py +57 -0
  259. nat/front_ends/mcp/__init__.py +14 -0
  260. nat/front_ends/mcp/introspection_token_verifier.py +73 -0
  261. nat/front_ends/mcp/mcp_front_end_config.py +90 -0
  262. nat/front_ends/mcp/mcp_front_end_plugin.py +113 -0
  263. nat/front_ends/mcp/mcp_front_end_plugin_worker.py +268 -0
  264. nat/front_ends/mcp/memory_profiler.py +320 -0
  265. nat/front_ends/mcp/register.py +27 -0
  266. nat/front_ends/mcp/tool_converter.py +290 -0
  267. nat/front_ends/register.py +21 -0
  268. nat/front_ends/simple_base/__init__.py +14 -0
  269. nat/front_ends/simple_base/simple_front_end_plugin_base.py +56 -0
  270. nat/llm/__init__.py +0 -0
  271. nat/llm/aws_bedrock_llm.py +69 -0
  272. nat/llm/azure_openai_llm.py +57 -0
  273. nat/llm/litellm_llm.py +69 -0
  274. nat/llm/nim_llm.py +58 -0
  275. nat/llm/openai_llm.py +54 -0
  276. nat/llm/register.py +27 -0
  277. nat/llm/utils/__init__.py +14 -0
  278. nat/llm/utils/env_config_value.py +93 -0
  279. nat/llm/utils/error.py +17 -0
  280. nat/llm/utils/thinking.py +215 -0
  281. nat/memory/__init__.py +20 -0
  282. nat/memory/interfaces.py +183 -0
  283. nat/memory/models.py +112 -0
  284. nat/meta/pypi.md +58 -0
  285. nat/object_store/__init__.py +20 -0
  286. nat/object_store/in_memory_object_store.py +76 -0
  287. nat/object_store/interfaces.py +84 -0
  288. nat/object_store/models.py +38 -0
  289. nat/object_store/register.py +19 -0
  290. nat/observability/__init__.py +14 -0
  291. nat/observability/exporter/__init__.py +14 -0
  292. nat/observability/exporter/base_exporter.py +449 -0
  293. nat/observability/exporter/exporter.py +78 -0
  294. nat/observability/exporter/file_exporter.py +33 -0
  295. nat/observability/exporter/processing_exporter.py +550 -0
  296. nat/observability/exporter/raw_exporter.py +52 -0
  297. nat/observability/exporter/span_exporter.py +308 -0
  298. nat/observability/exporter_manager.py +335 -0
  299. nat/observability/mixin/__init__.py +14 -0
  300. nat/observability/mixin/batch_config_mixin.py +26 -0
  301. nat/observability/mixin/collector_config_mixin.py +23 -0
  302. nat/observability/mixin/file_mixin.py +288 -0
  303. nat/observability/mixin/file_mode.py +23 -0
  304. nat/observability/mixin/redaction_config_mixin.py +42 -0
  305. nat/observability/mixin/resource_conflict_mixin.py +134 -0
  306. nat/observability/mixin/serialize_mixin.py +61 -0
  307. nat/observability/mixin/tagging_config_mixin.py +62 -0
  308. nat/observability/mixin/type_introspection_mixin.py +496 -0
  309. nat/observability/processor/__init__.py +14 -0
  310. nat/observability/processor/batching_processor.py +308 -0
  311. nat/observability/processor/callback_processor.py +42 -0
  312. nat/observability/processor/falsy_batch_filter_processor.py +55 -0
  313. nat/observability/processor/intermediate_step_serializer.py +28 -0
  314. nat/observability/processor/processor.py +74 -0
  315. nat/observability/processor/processor_factory.py +70 -0
  316. nat/observability/processor/redaction/__init__.py +24 -0
  317. nat/observability/processor/redaction/contextual_redaction_processor.py +125 -0
  318. nat/observability/processor/redaction/contextual_span_redaction_processor.py +66 -0
  319. nat/observability/processor/redaction/redaction_processor.py +177 -0
  320. nat/observability/processor/redaction/span_header_redaction_processor.py +92 -0
  321. nat/observability/processor/span_tagging_processor.py +68 -0
  322. nat/observability/register.py +114 -0
  323. nat/observability/utils/__init__.py +14 -0
  324. nat/observability/utils/dict_utils.py +236 -0
  325. nat/observability/utils/time_utils.py +31 -0
  326. nat/plugins/.namespace +1 -0
  327. nat/profiler/__init__.py +0 -0
  328. nat/profiler/calc/__init__.py +14 -0
  329. nat/profiler/calc/calc_runner.py +626 -0
  330. nat/profiler/calc/calculations.py +288 -0
  331. nat/profiler/calc/data_models.py +188 -0
  332. nat/profiler/calc/plot.py +345 -0
  333. nat/profiler/callbacks/__init__.py +0 -0
  334. nat/profiler/callbacks/agno_callback_handler.py +295 -0
  335. nat/profiler/callbacks/base_callback_class.py +20 -0
  336. nat/profiler/callbacks/langchain_callback_handler.py +297 -0
  337. nat/profiler/callbacks/llama_index_callback_handler.py +205 -0
  338. nat/profiler/callbacks/semantic_kernel_callback_handler.py +238 -0
  339. nat/profiler/callbacks/token_usage_base_model.py +27 -0
  340. nat/profiler/data_frame_row.py +51 -0
  341. nat/profiler/data_models.py +24 -0
  342. nat/profiler/decorators/__init__.py +0 -0
  343. nat/profiler/decorators/framework_wrapper.py +180 -0
  344. nat/profiler/decorators/function_tracking.py +411 -0
  345. nat/profiler/forecasting/__init__.py +0 -0
  346. nat/profiler/forecasting/config.py +18 -0
  347. nat/profiler/forecasting/model_trainer.py +75 -0
  348. nat/profiler/forecasting/models/__init__.py +22 -0
  349. nat/profiler/forecasting/models/forecasting_base_model.py +42 -0
  350. nat/profiler/forecasting/models/linear_model.py +197 -0
  351. nat/profiler/forecasting/models/random_forest_regressor.py +269 -0
  352. nat/profiler/inference_metrics_model.py +28 -0
  353. nat/profiler/inference_optimization/__init__.py +0 -0
  354. nat/profiler/inference_optimization/bottleneck_analysis/__init__.py +0 -0
  355. nat/profiler/inference_optimization/bottleneck_analysis/nested_stack_analysis.py +460 -0
  356. nat/profiler/inference_optimization/bottleneck_analysis/simple_stack_analysis.py +258 -0
  357. nat/profiler/inference_optimization/data_models.py +386 -0
  358. nat/profiler/inference_optimization/experimental/__init__.py +0 -0
  359. nat/profiler/inference_optimization/experimental/concurrency_spike_analysis.py +468 -0
  360. nat/profiler/inference_optimization/experimental/prefix_span_analysis.py +404 -0
  361. nat/profiler/inference_optimization/llm_metrics.py +212 -0
  362. nat/profiler/inference_optimization/prompt_caching.py +163 -0
  363. nat/profiler/inference_optimization/token_uniqueness.py +107 -0
  364. nat/profiler/inference_optimization/workflow_runtimes.py +72 -0
  365. nat/profiler/intermediate_property_adapter.py +102 -0
  366. nat/profiler/parameter_optimization/__init__.py +0 -0
  367. nat/profiler/parameter_optimization/optimizable_utils.py +93 -0
  368. nat/profiler/parameter_optimization/optimizer_runtime.py +67 -0
  369. nat/profiler/parameter_optimization/parameter_optimizer.py +153 -0
  370. nat/profiler/parameter_optimization/parameter_selection.py +107 -0
  371. nat/profiler/parameter_optimization/pareto_visualizer.py +380 -0
  372. nat/profiler/parameter_optimization/prompt_optimizer.py +384 -0
  373. nat/profiler/parameter_optimization/update_helpers.py +66 -0
  374. nat/profiler/profile_runner.py +478 -0
  375. nat/profiler/utils.py +186 -0
  376. nat/registry_handlers/__init__.py +0 -0
  377. nat/registry_handlers/local/__init__.py +0 -0
  378. nat/registry_handlers/local/local_handler.py +176 -0
  379. nat/registry_handlers/local/register_local.py +37 -0
  380. nat/registry_handlers/metadata_factory.py +60 -0
  381. nat/registry_handlers/package_utils.py +570 -0
  382. nat/registry_handlers/pypi/__init__.py +0 -0
  383. nat/registry_handlers/pypi/pypi_handler.py +248 -0
  384. nat/registry_handlers/pypi/register_pypi.py +40 -0
  385. nat/registry_handlers/register.py +20 -0
  386. nat/registry_handlers/registry_handler_base.py +157 -0
  387. nat/registry_handlers/rest/__init__.py +0 -0
  388. nat/registry_handlers/rest/register_rest.py +56 -0
  389. nat/registry_handlers/rest/rest_handler.py +236 -0
  390. nat/registry_handlers/schemas/__init__.py +0 -0
  391. nat/registry_handlers/schemas/headers.py +42 -0
  392. nat/registry_handlers/schemas/package.py +68 -0
  393. nat/registry_handlers/schemas/publish.py +68 -0
  394. nat/registry_handlers/schemas/pull.py +82 -0
  395. nat/registry_handlers/schemas/remove.py +36 -0
  396. nat/registry_handlers/schemas/search.py +91 -0
  397. nat/registry_handlers/schemas/status.py +47 -0
  398. nat/retriever/__init__.py +0 -0
  399. nat/retriever/interface.py +41 -0
  400. nat/retriever/milvus/__init__.py +14 -0
  401. nat/retriever/milvus/register.py +81 -0
  402. nat/retriever/milvus/retriever.py +228 -0
  403. nat/retriever/models.py +77 -0
  404. nat/retriever/nemo_retriever/__init__.py +14 -0
  405. nat/retriever/nemo_retriever/register.py +60 -0
  406. nat/retriever/nemo_retriever/retriever.py +190 -0
  407. nat/retriever/register.py +21 -0
  408. nat/runtime/__init__.py +14 -0
  409. nat/runtime/loader.py +220 -0
  410. nat/runtime/runner.py +292 -0
  411. nat/runtime/session.py +223 -0
  412. nat/runtime/user_metadata.py +130 -0
  413. nat/settings/__init__.py +0 -0
  414. nat/settings/global_settings.py +329 -0
  415. nat/test/.namespace +1 -0
  416. nat/tool/__init__.py +0 -0
  417. nat/tool/chat_completion.py +77 -0
  418. nat/tool/code_execution/README.md +151 -0
  419. nat/tool/code_execution/__init__.py +0 -0
  420. nat/tool/code_execution/code_sandbox.py +267 -0
  421. nat/tool/code_execution/local_sandbox/.gitignore +1 -0
  422. nat/tool/code_execution/local_sandbox/Dockerfile.sandbox +60 -0
  423. nat/tool/code_execution/local_sandbox/__init__.py +13 -0
  424. nat/tool/code_execution/local_sandbox/local_sandbox_server.py +198 -0
  425. nat/tool/code_execution/local_sandbox/sandbox.requirements.txt +6 -0
  426. nat/tool/code_execution/local_sandbox/start_local_sandbox.sh +50 -0
  427. nat/tool/code_execution/register.py +74 -0
  428. nat/tool/code_execution/test_code_execution_sandbox.py +414 -0
  429. nat/tool/code_execution/utils.py +100 -0
  430. nat/tool/datetime_tools.py +82 -0
  431. nat/tool/document_search.py +141 -0
  432. nat/tool/github_tools.py +450 -0
  433. nat/tool/memory_tools/__init__.py +0 -0
  434. nat/tool/memory_tools/add_memory_tool.py +79 -0
  435. nat/tool/memory_tools/delete_memory_tool.py +66 -0
  436. nat/tool/memory_tools/get_memory_tool.py +72 -0
  437. nat/tool/nvidia_rag.py +95 -0
  438. nat/tool/register.py +31 -0
  439. nat/tool/retriever.py +95 -0
  440. nat/tool/server_tools.py +66 -0
  441. nat/utils/__init__.py +0 -0
  442. nat/utils/callable_utils.py +70 -0
  443. nat/utils/data_models/__init__.py +0 -0
  444. nat/utils/data_models/schema_validator.py +58 -0
  445. nat/utils/debugging_utils.py +43 -0
  446. nat/utils/decorators.py +210 -0
  447. nat/utils/dump_distro_mapping.py +32 -0
  448. nat/utils/exception_handlers/__init__.py +0 -0
  449. nat/utils/exception_handlers/automatic_retries.py +342 -0
  450. nat/utils/exception_handlers/schemas.py +114 -0
  451. nat/utils/io/__init__.py +0 -0
  452. nat/utils/io/model_processing.py +28 -0
  453. nat/utils/io/yaml_tools.py +119 -0
  454. nat/utils/log_levels.py +25 -0
  455. nat/utils/log_utils.py +37 -0
  456. nat/utils/metadata_utils.py +74 -0
  457. nat/utils/optional_imports.py +142 -0
  458. nat/utils/producer_consumer_queue.py +178 -0
  459. nat/utils/reactive/__init__.py +0 -0
  460. nat/utils/reactive/base/__init__.py +0 -0
  461. nat/utils/reactive/base/observable_base.py +65 -0
  462. nat/utils/reactive/base/observer_base.py +55 -0
  463. nat/utils/reactive/base/subject_base.py +79 -0
  464. nat/utils/reactive/observable.py +59 -0
  465. nat/utils/reactive/observer.py +76 -0
  466. nat/utils/reactive/subject.py +131 -0
  467. nat/utils/reactive/subscription.py +49 -0
  468. nat/utils/settings/__init__.py +0 -0
  469. nat/utils/settings/global_settings.py +195 -0
  470. nat/utils/string_utils.py +38 -0
  471. nat/utils/type_converter.py +299 -0
  472. nat/utils/type_utils.py +488 -0
  473. nat/utils/url_utils.py +27 -0
  474. nvidia_nat-1.1.0a20251020.dist-info/METADATA +195 -0
  475. nvidia_nat-1.1.0a20251020.dist-info/RECORD +480 -0
  476. nvidia_nat-1.1.0a20251020.dist-info/WHEEL +5 -0
  477. nvidia_nat-1.1.0a20251020.dist-info/entry_points.txt +22 -0
  478. nvidia_nat-1.1.0a20251020.dist-info/licenses/LICENSE-3rd-party.txt +5478 -0
  479. nvidia_nat-1.1.0a20251020.dist-info/licenses/LICENSE.md +201 -0
  480. nvidia_nat-1.1.0a20251020.dist-info/top_level.txt +2 -0
@@ -0,0 +1,210 @@
1
+ # SPDX-FileCopyrightText: Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2
+ # SPDX-License-Identifier: Apache-2.0
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ """Deprecation utilities.
16
+
17
+ This module provides helpers to standardize deprecation signaling across the
18
+ codebase:
19
+
20
+ - ``issue_deprecation_warning``: Builds and emits a single deprecation message
21
+ per function using the standard logging pipeline.
22
+ - ``deprecated``: A decorator that wraps sync/async functions and generators to
23
+ log a one-time deprecation message upon first use. It supports optional
24
+ metadata, a planned removal version, a suggested replacement, and an
25
+ optional feature name label.
26
+
27
+ Messages are emitted via ``logging.getLogger(__name__).warning`` (not
28
+ ``warnings.warn``) so they appear in normal application logs and respect global
29
+ logging configuration. Each unique function logs at most once per process.
30
+ """
31
+
32
+ import functools
33
+ import inspect
34
+ import logging
35
+ from collections.abc import AsyncGenerator
36
+ from collections.abc import Callable
37
+ from collections.abc import Generator
38
+ from typing import Any
39
+ from typing import TypeVar
40
+ from typing import overload
41
+
42
+ logger = logging.getLogger(__name__)
43
+
44
+ _warning_issued = set()
45
+
46
+ # Type variables for overloads
47
+ F = TypeVar('F', bound=Callable[..., Any])
48
+
49
+
50
+ def issue_deprecation_warning(function_name: str,
51
+ removal_version: str | None = None,
52
+ replacement: str | None = None,
53
+ reason: str | None = None,
54
+ feature_name: str | None = None,
55
+ metadata: dict[str, Any] | None = None) -> None:
56
+ """
57
+ Log a deprecation warning message for the function.
58
+
59
+ A warning is emitted only once per function. When a ``metadata`` dict
60
+ is supplied, it is appended to the log entry to provide extra context
61
+ (e.g., version, author, feature flag).
62
+
63
+ Args:
64
+ function_name: The name of the deprecated function
65
+ removal_version: The version when the function will be removed
66
+ replacement: What to use instead of this function
67
+ reason: Why the function is being deprecated
68
+ feature_name: Optional name of the feature that is deprecated
69
+ metadata: Optional dictionary of metadata to log with the warning
70
+ """
71
+ if function_name not in _warning_issued:
72
+ # Build the deprecation message
73
+ if feature_name:
74
+ warning_message = f"{feature_name} is deprecated"
75
+ else:
76
+ warning_message = f"Function {function_name} is deprecated"
77
+
78
+ if removal_version:
79
+ warning_message += f" and will be removed in version {removal_version}"
80
+ else:
81
+ warning_message += " and will be removed in a future release"
82
+
83
+ warning_message += "."
84
+
85
+ if reason:
86
+ warning_message += f" Reason: {reason}."
87
+
88
+ if replacement:
89
+ warning_message += f" Use '{replacement}' instead."
90
+
91
+ if metadata:
92
+ warning_message += f" | Metadata: {metadata}"
93
+
94
+ # Issue warning and save function name to avoid duplicate warnings
95
+ logger.warning(warning_message)
96
+ _warning_issued.add(function_name)
97
+
98
+
99
+ # Overloads for different function types
100
+ @overload
101
+ def deprecated(func: F,
102
+ *,
103
+ removal_version: str | None = None,
104
+ replacement: str | None = None,
105
+ reason: str | None = None,
106
+ feature_name: str | None = None,
107
+ metadata: dict[str, Any] | None = None) -> F:
108
+ """Overload for direct decorator usage (when called without parentheses)."""
109
+ ...
110
+
111
+
112
+ @overload
113
+ def deprecated(*,
114
+ removal_version: str | None = None,
115
+ replacement: str | None = None,
116
+ reason: str | None = None,
117
+ feature_name: str | None = None,
118
+ metadata: dict[str, Any] | None = None) -> Callable[[F], F]:
119
+ """Overload for decorator factory usage (when called with parentheses)."""
120
+ ...
121
+
122
+
123
+ def deprecated(func: Any = None,
124
+ *,
125
+ removal_version: str | None = None,
126
+ replacement: str | None = None,
127
+ reason: str | None = None,
128
+ feature_name: str | None = None,
129
+ metadata: dict[str, Any] | None = None) -> Any:
130
+ """
131
+ Decorator that can wrap any type of function (sync, async, generator,
132
+ async generator) and logs a deprecation warning.
133
+
134
+ Args:
135
+ func: The function to be decorated.
136
+ removal_version: The version when the function will be removed
137
+ replacement: What to use instead of this function
138
+ reason: Why the function is being deprecated
139
+ feature_name: Optional name of the feature that is deprecated. If provided, the warning will be
140
+ prefixed with "The <feature_name> feature is deprecated".
141
+ metadata: Optional dictionary of metadata to log with the warning. This can include information
142
+ like version, author, etc. If provided, the metadata will be
143
+ logged alongside the deprecation warning.
144
+ """
145
+ function_name: str = f"{func.__module__}.{func.__qualname__}" if func else "<unknown_function>"
146
+
147
+ # If called as @deprecated(...) but not immediately passed a function
148
+ if func is None:
149
+
150
+ def decorator_wrapper(actual_func):
151
+ return deprecated(actual_func,
152
+ removal_version=removal_version,
153
+ replacement=replacement,
154
+ reason=reason,
155
+ feature_name=feature_name,
156
+ metadata=metadata)
157
+
158
+ return decorator_wrapper
159
+
160
+ # --- Validate metadata ---
161
+ if metadata is not None:
162
+ if not isinstance(metadata, dict):
163
+ raise TypeError("metadata must be a dict[str, Any].")
164
+ if any(not isinstance(k, str) for k in metadata.keys()):
165
+ raise TypeError("All metadata keys must be strings.")
166
+
167
+ # --- Now detect the function type and wrap accordingly ---
168
+ if inspect.isasyncgenfunction(func):
169
+ # ---------------------
170
+ # ASYNC GENERATOR
171
+ # ---------------------
172
+
173
+ @functools.wraps(func)
174
+ async def async_gen_wrapper(*args, **kwargs) -> AsyncGenerator[Any, Any]:
175
+ issue_deprecation_warning(function_name, removal_version, replacement, reason, feature_name, metadata)
176
+ async for item in func(*args, **kwargs):
177
+ yield item # yield the original item
178
+
179
+ return async_gen_wrapper
180
+
181
+ if inspect.iscoroutinefunction(func):
182
+ # ---------------------
183
+ # ASYNC FUNCTION
184
+ # ---------------------
185
+ @functools.wraps(func)
186
+ async def async_wrapper(*args, **kwargs) -> Any:
187
+ issue_deprecation_warning(function_name, removal_version, replacement, reason, feature_name, metadata)
188
+ result = await func(*args, **kwargs)
189
+ return result
190
+
191
+ return async_wrapper
192
+
193
+ if inspect.isgeneratorfunction(func):
194
+ # ---------------------
195
+ # SYNC GENERATOR
196
+ # ---------------------
197
+ @functools.wraps(func)
198
+ def sync_gen_wrapper(*args, **kwargs) -> Generator[Any, Any, Any]:
199
+ issue_deprecation_warning(function_name, removal_version, replacement, reason, feature_name, metadata)
200
+ yield from func(*args, **kwargs) # yield the original item
201
+
202
+ return sync_gen_wrapper
203
+
204
+ @functools.wraps(func)
205
+ def sync_wrapper(*args, **kwargs) -> Any:
206
+ issue_deprecation_warning(function_name, removal_version, replacement, reason, feature_name, metadata)
207
+ result = func(*args, **kwargs)
208
+ return result
209
+
210
+ return sync_wrapper
@@ -0,0 +1,32 @@
1
+ # SPDX-FileCopyrightText: Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2
+ # SPDX-License-Identifier: Apache-2.0
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+ import argparse
17
+ import json
18
+
19
+ from nat.runtime.loader import get_all_entrypoints_distro_mapping
20
+
21
+
22
+ def dump_distro_mapping(path: str):
23
+ mapping = get_all_entrypoints_distro_mapping()
24
+ with open(path, "w", encoding="utf-8") as f:
25
+ json.dump(mapping, f, indent=4)
26
+
27
+
28
+ if __name__ == "__main__":
29
+ parser = argparse.ArgumentParser()
30
+ parser.add_argument("--path", type=str, required=True)
31
+ args = parser.parse_args()
32
+ dump_distro_mapping(args.path)
File without changes
@@ -0,0 +1,342 @@
1
+ # SPDX-FileCopyrightText: Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2
+ # SPDX-License-Identifier: Apache-2.0
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ import asyncio
16
+ import copy
17
+ import functools
18
+ import inspect
19
+ import logging
20
+ import re
21
+ import time
22
+ import types
23
+ from collections.abc import Callable
24
+ from collections.abc import Iterable
25
+ from collections.abc import Sequence
26
+ from typing import Any
27
+ from typing import TypeVar
28
+
29
+ T = TypeVar("T")
30
+ Exc = tuple[type[BaseException], ...] # exception classes
31
+ CodePattern = int | str | range # for retry_codes argument
32
+ logger = logging.getLogger(__name__)
33
+
34
+ # ──────────────────────────────────────────────────────────────────────────────
35
+ # Helpers: status-code extraction & pattern matching
36
+ # ──────────────────────────────────────────────────────────────────────────────
37
+ _CODE_ATTRS = ("code", "status", "status_code", "http_status")
38
+
39
+
40
+ def _extract_status_code(exc: BaseException) -> int | None:
41
+ """Return a numeric status code found inside *exc*, else None."""
42
+ for attr in _CODE_ATTRS:
43
+ if hasattr(exc, attr):
44
+ try:
45
+ return int(getattr(exc, attr))
46
+ except (TypeError, ValueError):
47
+ pass
48
+ if exc.args:
49
+ try:
50
+ return int(exc.args[0])
51
+ except (TypeError, ValueError):
52
+ pass
53
+ return None
54
+
55
+
56
+ def _pattern_to_regex(pat: str) -> re.Pattern[str]:
57
+ """
58
+ Convert simple wildcard pattern (“4xx”, “5*”, “40x”) to a ^regex$.
59
+ Rule: ‘x’ or ‘*’ ⇒ any digit.
60
+ """
61
+ escaped = re.escape(pat)
62
+ return re.compile("^" + escaped.replace(r"\*", r"\d").replace("x", r"\d") + "$")
63
+
64
+
65
+ def _code_matches(code: int, pat: CodePattern) -> bool:
66
+ if isinstance(pat, int):
67
+ return code == pat
68
+ if isinstance(pat, range):
69
+ return code in pat
70
+ return bool(_pattern_to_regex(pat).match(str(code)))
71
+
72
+
73
+ # ──────────────────────────────────────────────────────────────────────────────
74
+ # Unified retry-decision helper
75
+ # ──────────────────────────────────────────────────────────────────────────────
76
+ def _want_retry(
77
+ exc: BaseException,
78
+ *,
79
+ code_patterns: Sequence[CodePattern] | None,
80
+ msg_substrings: Sequence[str] | None,
81
+ ) -> bool:
82
+ """
83
+ Return True if the exception satisfies *either* (when provided):
84
+ • code_patterns – matches status-code pattern(s)
85
+ • msg_substrings – contains any of the substrings (case-insensitive)
86
+ """
87
+
88
+ if not code_patterns and not msg_substrings:
89
+ logger.info("Retrying on exception %s without extra filters", exc)
90
+ return True
91
+
92
+ # -------- status-code filter --------
93
+ if code_patterns is not None:
94
+ code = _extract_status_code(exc)
95
+ if any(_code_matches(code, p) for p in code_patterns):
96
+ logger.info("Retrying on exception %s with matched code %s", exc, code)
97
+ return True
98
+
99
+ # -------- message filter -----------
100
+ if msg_substrings is not None:
101
+ msg = str(exc).lower()
102
+ if any(s.lower() in msg for s in msg_substrings):
103
+ logger.info("Retrying on exception %s with matched message %s", exc, msg)
104
+ return True
105
+
106
+ return False
107
+
108
+
109
+ # ──────────────────────────────────────────────────────────────────────────────
110
+ # Core decorator factory (sync / async / (a)gen)
111
+ # ──────────────────────────────────────────────────────────────────────────────
112
+ def _retry_decorator(
113
+ *,
114
+ retries: int = 3,
115
+ base_delay: float = 0.25,
116
+ backoff: float = 2.0,
117
+ retry_on: Exc = (Exception, ),
118
+ retry_codes: Sequence[CodePattern] | None = None,
119
+ retry_on_messages: Sequence[str] | None = None,
120
+ deepcopy: bool = False,
121
+ instance_context_aware: bool = False,
122
+ ) -> Callable[[Callable[..., T]], Callable[..., T]]:
123
+ """
124
+ Build a decorator that retries with exponential back-off *iff*:
125
+
126
+ • the raised exception is an instance of one of `retry_on`
127
+ • AND `_want_retry()` returns True (i.e. matches codes/messages filters)
128
+
129
+ If both `retry_codes` and `retry_on_messages` are None, all exceptions are retried.
130
+
131
+ deepcopy:
132
+ If True, each retry receives deep‑copied *args and **kwargs* to avoid
133
+ mutating shared state between attempts.
134
+
135
+ instance_context_aware:
136
+ If True, the decorator will check for a retry context flag on the first
137
+ argument (assumed to be 'self'). If the flag is set, retries are skipped
138
+ to prevent retry storms in nested method calls.
139
+ """
140
+
141
+ def decorate(fn: Callable[..., T]) -> Callable[..., T]:
142
+ use_deepcopy = deepcopy
143
+ use_context_aware = instance_context_aware
144
+
145
+ class _RetryContext:
146
+ """Context manager for instance-level retry gating."""
147
+
148
+ __slots__ = ("_obj", "_enabled", "_active")
149
+
150
+ def __init__(self, args: tuple[Any, ...]):
151
+ self._obj = args[0] if (use_context_aware and args) else None
152
+ self._enabled = bool(self._obj)
153
+ self._active = False
154
+
155
+ def __enter__(self):
156
+ if not self._enabled:
157
+ return False
158
+ try:
159
+ # If already in retry context, signal caller to skip retries
160
+ if getattr(self._obj, "_in_retry_context", False):
161
+ return True
162
+ object.__setattr__(self._obj, "_in_retry_context", True)
163
+ self._active = True
164
+ return False
165
+ except Exception:
166
+ # If we cannot set the attribute, behave as if context isn't enabled
167
+ self._enabled = False
168
+ return False
169
+
170
+ def __exit__(self, _exc_type, _exc, _tb):
171
+ if self._enabled and self._active:
172
+ try:
173
+ object.__setattr__(self._obj, "_in_retry_context", False)
174
+ except Exception:
175
+ pass
176
+
177
+ async def _call_with_retry_async(*args, **kw) -> T:
178
+ with _RetryContext(args) as already_in_context:
179
+ if already_in_context:
180
+ return await fn(*args, **kw)
181
+ delay = base_delay
182
+ for attempt in range(retries):
183
+ call_args = copy.deepcopy(args) if use_deepcopy else args
184
+ call_kwargs = copy.deepcopy(kw) if use_deepcopy else kw
185
+ try:
186
+ return await fn(*call_args, **call_kwargs)
187
+ except retry_on as exc:
188
+ if (not _want_retry(exc, code_patterns=retry_codes, msg_substrings=retry_on_messages)
189
+ or attempt == retries - 1):
190
+ raise
191
+ await asyncio.sleep(delay)
192
+ delay *= backoff
193
+
194
+ async def _agen_with_retry(*args, **kw):
195
+ with _RetryContext(args) as already_in_context:
196
+ if already_in_context:
197
+ async for item in fn(*args, **kw):
198
+ yield item
199
+ return
200
+ delay = base_delay
201
+ for attempt in range(retries):
202
+ call_args = copy.deepcopy(args) if use_deepcopy else args
203
+ call_kwargs = copy.deepcopy(kw) if use_deepcopy else kw
204
+ try:
205
+ async for item in fn(*call_args, **call_kwargs):
206
+ yield item
207
+ return
208
+ except retry_on as exc:
209
+ if (not _want_retry(exc, code_patterns=retry_codes, msg_substrings=retry_on_messages)
210
+ or attempt == retries - 1):
211
+ raise
212
+ await asyncio.sleep(delay)
213
+ delay *= backoff
214
+
215
+ def _gen_with_retry(*args, **kw) -> Iterable[Any]:
216
+ with _RetryContext(args) as already_in_context:
217
+ if already_in_context:
218
+ yield from fn(*args, **kw)
219
+ return
220
+ delay = base_delay
221
+ for attempt in range(retries):
222
+ call_args = copy.deepcopy(args) if use_deepcopy else args
223
+ call_kwargs = copy.deepcopy(kw) if use_deepcopy else kw
224
+ try:
225
+ yield from fn(*call_args, **call_kwargs)
226
+ return
227
+ except retry_on as exc:
228
+ if (not _want_retry(exc, code_patterns=retry_codes, msg_substrings=retry_on_messages)
229
+ or attempt == retries - 1):
230
+ raise
231
+ time.sleep(delay)
232
+ delay *= backoff
233
+
234
+ def _sync_with_retry(*args, **kw) -> T:
235
+ with _RetryContext(args) as already_in_context:
236
+ if already_in_context:
237
+ return fn(*args, **kw)
238
+ delay = base_delay
239
+ for attempt in range(retries):
240
+ call_args = copy.deepcopy(args) if use_deepcopy else args
241
+ call_kwargs = copy.deepcopy(kw) if use_deepcopy else kw
242
+ try:
243
+ return fn(*call_args, **call_kwargs)
244
+ except retry_on as exc:
245
+ if (not _want_retry(exc, code_patterns=retry_codes, msg_substrings=retry_on_messages)
246
+ or attempt == retries - 1):
247
+ raise
248
+ time.sleep(delay)
249
+ delay *= backoff
250
+
251
+ # Decide which wrapper to return
252
+ if inspect.iscoroutinefunction(fn):
253
+ wrapper = _call_with_retry_async
254
+ elif inspect.isasyncgenfunction(fn):
255
+ wrapper = _agen_with_retry
256
+ elif inspect.isgeneratorfunction(fn):
257
+ wrapper = _gen_with_retry
258
+ else:
259
+ wrapper = _sync_with_retry
260
+
261
+ return functools.wraps(fn)(wrapper) # type: ignore[return-value]
262
+
263
+ return decorate
264
+
265
+
266
+ # ──────────────────────────────────────────────────────────────────────────────
267
+ # Public helper : patch_with_retry
268
+ # ──────────────────────────────────────────────────────────────────────────────
269
+ def patch_with_retry(
270
+ obj: Any,
271
+ *,
272
+ retries: int = 3,
273
+ base_delay: float = 0.25,
274
+ backoff: float = 2.0,
275
+ retry_on: Exc = (Exception, ),
276
+ retry_codes: Sequence[CodePattern] | None = None,
277
+ retry_on_messages: Sequence[str] | None = None,
278
+ deepcopy: bool = False,
279
+ ) -> Any:
280
+ """
281
+ Patch *obj* instance-locally so **every public method** retries on failure.
282
+
283
+ Extra filters
284
+ -------------
285
+ retry_codes
286
+ Same as before – ints, ranges, or wildcard strings (“4xx”, “5*”…).
287
+ retry_on_messages
288
+ List of *substring* patterns. We retry only if **any** pattern
289
+ appears (case-insensitive) in `str(exc)`.
290
+ deepcopy:
291
+ If True, each retry receives deep‑copied *args and **kwargs* to avoid
292
+ mutating shared state between attempts.
293
+ """
294
+ deco = _retry_decorator(
295
+ retries=retries,
296
+ base_delay=base_delay,
297
+ backoff=backoff,
298
+ retry_on=retry_on,
299
+ retry_codes=retry_codes,
300
+ retry_on_messages=retry_on_messages,
301
+ deepcopy=deepcopy,
302
+ instance_context_aware=True, # Prevent retry storms
303
+ )
304
+
305
+ # Choose attribute source: the *class* to avoid triggering __getattr__
306
+ cls = obj if inspect.isclass(obj) else type(obj)
307
+ cls_name = getattr(cls, "__name__", str(cls))
308
+
309
+ for name, _ in inspect.getmembers(cls, callable):
310
+ descriptor = inspect.getattr_static(cls, name)
311
+
312
+ # Skip dunders, privates and all descriptors we must not wrap
313
+ if (name.startswith("_") or isinstance(descriptor, property | staticmethod | classmethod)):
314
+ continue
315
+
316
+ original = descriptor.__func__ if isinstance(descriptor, types.MethodType) else descriptor
317
+ wrapped = deco(original)
318
+
319
+ try: # instance‑level first
320
+ if not inspect.isclass(obj):
321
+ object.__setattr__(obj, name, types.MethodType(wrapped, obj))
322
+ continue
323
+ except Exception as exc:
324
+ logger.info(
325
+ "Instance‑level patch failed for %s.%s (%s); "
326
+ "falling back to class‑level patch.",
327
+ cls_name,
328
+ name,
329
+ exc,
330
+ )
331
+
332
+ try: # class‑level fallback
333
+ setattr(cls, name, wrapped)
334
+ except Exception as exc:
335
+ logger.info(
336
+ "Cannot patch method %s.%s with automatic retries: %s",
337
+ cls_name,
338
+ name,
339
+ exc,
340
+ )
341
+
342
+ return obj