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,570 @@
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 base64
17
+ import importlib.metadata
18
+ import logging
19
+ import os
20
+ import subprocess
21
+ from functools import lru_cache
22
+
23
+ from packaging.requirements import Requirement
24
+
25
+ from nat.data_models.component import ComponentEnum
26
+ from nat.data_models.discovery_metadata import DiscoveryMetadata
27
+ from nat.registry_handlers.schemas.package import WheelData
28
+ from nat.registry_handlers.schemas.publish import Artifact
29
+ from nat.runtime.loader import PluginTypes
30
+ from nat.runtime.loader import discover_entrypoints
31
+
32
+ logger = logging.getLogger(__name__)
33
+
34
+
35
+ @lru_cache
36
+ def get_module_name_from_distribution(distro_name: str) -> str | None:
37
+ """Return the first top-level module name for a given distribution name."""
38
+ if not distro_name:
39
+ return None
40
+
41
+ try:
42
+ # Read 'top_level.txt' which contains the module(s) provided by the package
43
+ dist = importlib.metadata.distribution(distro_name)
44
+ # will reading a file set of vun scan?
45
+ top_level = dist.read_text('top_level.txt')
46
+
47
+ if top_level:
48
+ module_names = top_level.strip().split()
49
+ # return firs module name
50
+ return module_names[0]
51
+ except importlib.metadata.PackageNotFoundError:
52
+ # Distribution not found
53
+ return None
54
+ except FileNotFoundError:
55
+ # 'top_level.txt' might be missing
56
+ return None
57
+
58
+ return None
59
+
60
+
61
+ def parse_requirement(requirement: str) -> str:
62
+ """Extract the base package name from a requirement string.
63
+
64
+ This function extracts only the package name, ignoring extras, version specifiers,
65
+ and environment markers.
66
+
67
+ Args:
68
+ requirement (str): A requirement string like 'numpy>=1.20.0' or 'requests[security]~=2.28.0'
69
+
70
+ Returns:
71
+ str: The base package name (e.g., 'numpy' from 'numpy>=1.20.0',
72
+ 'requests' from 'requests[security]~=2.28.0')
73
+ """
74
+ # Handle inline comments by splitting on '#' and taking the first part
75
+ clean_requirement = requirement.split('#')[0].strip()
76
+ if not clean_requirement:
77
+ return ""
78
+
79
+ try:
80
+ parsed = Requirement(clean_requirement)
81
+ return parsed.name.lower()
82
+ except Exception as e:
83
+ logger.warning("Failed to parse requirement '%s': %s. Skipping this dependency.", requirement, e)
84
+ return ""
85
+
86
+
87
+ def resolve_extras_to_packages(package_name: str, extras: list[str]) -> set[str]:
88
+ """Resolve package extras to their actual package dependencies.
89
+
90
+ Args:
91
+ package_name (str): The base package name (e.g., 'nvidia-nat')
92
+ extras (list[str]): List of extra names (e.g., ['langchain', 'telemetry'])
93
+
94
+ Returns:
95
+ set[str]: Set of additional package names that the extras resolve to
96
+ (e.g., {'nvidia-nat-langchain', 'nvidia-nat-opentelemetry', 'nvidia-nat-phoenix',
97
+ 'nvidia-nat-weave', 'nvidia-nat-ragaai'})
98
+ """
99
+ resolved_packages = set()
100
+
101
+ try:
102
+ # Get the distribution metadata for the package
103
+ dist = importlib.metadata.distribution(package_name)
104
+
105
+ # Parse all requirements to find optional dependencies
106
+ requires = dist.requires or []
107
+
108
+ for requirement_str in requires:
109
+ try:
110
+ req = Requirement(requirement_str)
111
+
112
+ # Check if this requirement has a marker that matches our extras
113
+ if req.marker:
114
+ for extra in extras:
115
+ # Try marker evaluation first
116
+ try:
117
+ if req.marker.evaluate({'extra': extra}):
118
+ resolved_packages.add(req.name.lower())
119
+ break
120
+ except Exception:
121
+ # Fallback to simple string check
122
+ marker_str = str(req.marker)
123
+ if f'extra == "{extra}"' in marker_str or f"extra == '{extra}'" in marker_str:
124
+ resolved_packages.add(req.name.lower())
125
+ break
126
+
127
+ except Exception as e:
128
+ logger.warning("Failed to parse requirement '%s' for extras resolution: %s", requirement_str, e)
129
+
130
+ except importlib.metadata.PackageNotFoundError:
131
+ logger.warning("Package '%s' not found for extras resolution", package_name)
132
+ except Exception as e:
133
+ logger.warning("Failed to resolve extras for package '%s': %s", package_name, e)
134
+
135
+ return resolved_packages
136
+
137
+
138
+ def extract_dependencies_with_extras_resolved(pyproject_path: str) -> set[str]:
139
+ """Extract dependency names from pyproject.toml with extras properly resolved.
140
+
141
+ This function not only extracts the base package names but also resolves
142
+ any extras (e.g., package[extra1,extra2]) to their actual package dependencies.
143
+
144
+ Args:
145
+ pyproject_path (str): Path to the pyproject.toml file
146
+
147
+ Returns:
148
+ set[str]: Set of all dependency names including those resolved from extras
149
+
150
+ Example:
151
+ For a dependency like "nat[langchain,telemetry]~=1.2", this will return:
152
+ {'nvidia-nat', 'nvidia-nat-langchain', 'nvidia-nat-opentelemetry', 'nvidia-nat-phoenix', ...}
153
+
154
+ Raises:
155
+ FileNotFoundError: If the pyproject.toml file doesn't exist
156
+ ValueError: If the file cannot be parsed
157
+ """
158
+ import tomllib
159
+
160
+ if not os.path.exists(pyproject_path):
161
+ raise FileNotFoundError(f"pyproject.toml not found at {pyproject_path}")
162
+
163
+ try:
164
+ with open(pyproject_path, "rb") as f:
165
+ data = tomllib.load(f)
166
+ except Exception as e:
167
+ raise ValueError(f"Failed to parse pyproject.toml: {e}") from e
168
+
169
+ project_data = data.get("project", {})
170
+ all_dependencies = set()
171
+
172
+ def _process_dependency(dep_spec: str):
173
+ """Process a single dependency specification and resolve extras."""
174
+ # Handle inline comments
175
+ clean_req = dep_spec.split('#')[0].strip()
176
+ if not clean_req:
177
+ return
178
+
179
+ try:
180
+ parsed = Requirement(clean_req)
181
+ base_name = parsed.name.lower()
182
+ all_dependencies.add(base_name)
183
+
184
+ # If there are extras, try to resolve them
185
+ if parsed.extras:
186
+ resolved_extras = resolve_extras_to_packages(base_name, list(parsed.extras))
187
+ all_dependencies.update(resolved_extras)
188
+
189
+ except Exception as e:
190
+ logger.warning("Failed to process dependency '%s': %s", dep_spec, e)
191
+
192
+ # Process main dependencies
193
+ for dep_spec in project_data.get("dependencies", []):
194
+ _process_dependency(dep_spec)
195
+
196
+ # Process optional dependencies
197
+ optional_deps = project_data.get("optional-dependencies", {})
198
+ for _group_name, group_deps in optional_deps.items():
199
+ for dep_spec in group_deps:
200
+ _process_dependency(dep_spec)
201
+
202
+ return all_dependencies
203
+
204
+
205
+ @lru_cache
206
+ def get_distributions() -> list[importlib.metadata.Distribution]:
207
+ """Get all installed distributions. This is an expensive operation and should be cached."""
208
+ return list(importlib.metadata.distributions())
209
+
210
+
211
+ def find_distribution_name(name: str) -> str | None:
212
+ """Try to find the correct distribution name for a given package name.
213
+
214
+ Uses dynamic discovery through importlib.metadata to find distributions
215
+ that provide the requested module/package name.
216
+
217
+ Args:
218
+ name (str): Package name to search for.
219
+
220
+ Returns:
221
+ str | None: The correct distribution name if found, None otherwise.
222
+ """
223
+ # First try the name as-is
224
+ try:
225
+ importlib.metadata.distribution(name)
226
+ return name
227
+ except importlib.metadata.PackageNotFoundError:
228
+ pass
229
+
230
+ # Try common case variations
231
+ variations = [
232
+ name.lower(),
233
+ name.upper(),
234
+ name.replace('-', '_'),
235
+ name.replace('_', '-'),
236
+ ]
237
+
238
+ # Try each variation
239
+ for variation in variations:
240
+ if variation != name: # Skip the original name we already tried
241
+ try:
242
+ importlib.metadata.distribution(variation)
243
+ return variation
244
+ except importlib.metadata.PackageNotFoundError:
245
+ continue
246
+
247
+ # Search through all installed distributions to find one that provides this module
248
+ try:
249
+ for dist in get_distributions():
250
+ dist_name = dist.metadata['Name']
251
+
252
+ # Check top-level packages provided by this distribution
253
+ try:
254
+ # Try to get top-level packages from metadata
255
+ top_level_txt = dist.read_text('top_level.txt')
256
+ if top_level_txt:
257
+ top_level_packages = set(top_level_txt.strip().split('\n'))
258
+ if name in top_level_packages:
259
+ return dist_name
260
+ except (FileNotFoundError, AttributeError):
261
+ # top_level.txt doesn't exist, try alternative method
262
+ pass
263
+
264
+ # Fallback: check file paths for top-level modules
265
+ try:
266
+ if hasattr(dist, 'files') and dist.files:
267
+ top_level_from_files = {
268
+ f.parts[0]
269
+ for f in dist.files if len(f.parts) > 0 and not f.parts[0].endswith('.dist-info')
270
+ }
271
+ if name in top_level_from_files:
272
+ return dist_name
273
+ except Exception:
274
+ # Some distributions might not have files info or it might be inaccessible
275
+ continue
276
+
277
+ except Exception as e:
278
+ logger.debug("Error searching distributions for %s: %s", name, e)
279
+
280
+ return None
281
+
282
+
283
+ def get_transitive_dependencies(distribution_names: list[str]) -> dict[str, set[str]]:
284
+ """Get transitive dependencies from a list of Python distribution names.
285
+
286
+ This function recursively resolves all dependencies for the given distribution names,
287
+ returning a mapping of each package to its complete set of transitive dependencies.
288
+ This is useful when publishing plugins to remote registries that contain with nested dependencies,
289
+ ensuring that all dependencies are included in the Artifact's metadata.
290
+
291
+ Args:
292
+ distribution_names (list[str]): List of Python distribution names (package names) to analyze.
293
+
294
+ Returns:
295
+ dict[str, set[str]]: Dictionary mapping each distribution name to its set of transitive dependencies.
296
+ The dependencies include both direct and indirect dependencies.
297
+ """
298
+ result: dict[str, set[str]] = {}
299
+ processing: set[str] = set() # Track packages currently being processed (cycle detection)
300
+ completed: set[str] = set() # Track packages that have been fully processed
301
+
302
+ def _get_dependencies_recursive(dist_name: str, path: set[str]) -> set[str]:
303
+ """Recursively get all dependencies for a distribution.
304
+
305
+ Args:
306
+ dist_name: The distribution name to process
307
+ path: Set of packages in the current dependency path (for cycle detection)
308
+ """
309
+ # If we've already computed this package's dependencies, return them
310
+ if dist_name in completed:
311
+ return result.get(dist_name, set())
312
+
313
+ # If we encounter this package in the current path, we have a cycle
314
+ if dist_name in path:
315
+ logger.debug("Cycle detected in dependency chain: %s", " -> ".join(list(path) + [dist_name]))
316
+ return set()
317
+
318
+ # If we're currently processing this package in another branch, return empty
319
+ # to avoid duplicate work (we'll get the full result when that branch completes)
320
+ if dist_name in processing:
321
+ return set()
322
+
323
+ processing.add(dist_name)
324
+ new_path = path | {dist_name}
325
+ dependencies = set()
326
+
327
+ try:
328
+ dist = importlib.metadata.distribution(dist_name)
329
+ requires = dist.requires or []
330
+
331
+ for requirement in requires:
332
+ # Skip requirements with extra markers (optional dependencies)
333
+ # These should only be included if the extra is explicitly requested
334
+ if 'extra ==' in requirement:
335
+ continue
336
+
337
+ # Parse the requirement to get the package name
338
+ dep_name = parse_requirement(requirement)
339
+
340
+ # Skip self-references and empty names
341
+ if not dep_name or dep_name == dist_name.lower():
342
+ continue
343
+
344
+ dependencies.add(dep_name)
345
+
346
+ # Recursively get dependencies of this dependency
347
+ try:
348
+ transitive_deps = _get_dependencies_recursive(dep_name, new_path)
349
+ dependencies.update(transitive_deps)
350
+ except importlib.metadata.PackageNotFoundError:
351
+ # Check if this is likely a conditional dependency (has markers)
352
+ is_conditional = any(marker in requirement for marker in [
353
+ 'python_version', 'sys_platform', 'platform_system', 'platform_machine', 'implementation_name',
354
+ 'implementation_version'
355
+ ])
356
+
357
+ if is_conditional:
358
+ # This is expected - conditional dependencies aren't always installed
359
+ logger.debug("Conditional dependency %s of %s is not installed: %s",
360
+ dep_name,
361
+ dist_name,
362
+ requirement)
363
+ else:
364
+ # This might be a real issue - a non-conditional dependency is missing
365
+ logger.warning("Dependency %s of %s is not installed", dep_name, dist_name)
366
+ continue
367
+
368
+ except importlib.metadata.PackageNotFoundError:
369
+ # Transitive dependencies that aren't found are usually conditional (platform/version specific)
370
+ # and this is expected behavior
371
+ logger.debug("Distribution %s not found (likely conditional dependency)", dist_name)
372
+ # Don't raise - just return empty dependencies for missing distributions
373
+ finally:
374
+ processing.remove(dist_name)
375
+
376
+ result[dist_name] = dependencies
377
+ completed.add(dist_name)
378
+ return dependencies
379
+
380
+ # Process each distribution name
381
+ for dist_name in distribution_names:
382
+ if dist_name not in completed:
383
+ try:
384
+ _get_dependencies_recursive(dist_name.lower(), set())
385
+ except importlib.metadata.PackageNotFoundError:
386
+ # Try to find the correct distribution name
387
+ correct_name = find_distribution_name(dist_name)
388
+ if correct_name:
389
+ logger.debug("Found distribution '%s' for requested name '%s'", correct_name, dist_name)
390
+ try:
391
+ _get_dependencies_recursive(correct_name.lower(), set())
392
+ # Map the original name to the results of the correct name
393
+ if correct_name.lower() in result:
394
+ result[dist_name] = result[correct_name.lower()]
395
+ continue
396
+ except importlib.metadata.PackageNotFoundError:
397
+ pass
398
+
399
+ logger.error("Distribution %s not found (tried common variations)", dist_name, exc_info=True)
400
+ result[dist_name] = set()
401
+
402
+ return result
403
+
404
+
405
+ def get_all_transitive_dependencies(distribution_names: list[str]) -> set[str]:
406
+ """Get all unique transitive dependencies from a list of Python distribution names.
407
+
408
+ Returns a flattened set of all unique dependencies across all the provided distribution names.
409
+ This is useful when publishing plugins to remote registries that contain with nested dependencies,
410
+ ensuring that all dependencies are included in the Artifact's metadata.
411
+
412
+ Args:
413
+ distribution_names: List of Python distribution names (package names) to analyze
414
+
415
+ Returns:
416
+ set[str]: Set of all unique transitive dependency names
417
+ """
418
+ deps_map = get_transitive_dependencies(distribution_names)
419
+ all_deps = set()
420
+
421
+ for deps in deps_map.values():
422
+ all_deps.update(deps)
423
+
424
+ return all_deps
425
+
426
+
427
+ def build_wheel(package_root: str) -> WheelData:
428
+ """Builds a Python .whl for the specified package and saves to disk, sets self._whl_path, and returned as bytes.
429
+
430
+ Args:
431
+ package_root (str): Path to the local package repository.
432
+
433
+ Returns:
434
+ WheelData: Data model containing a built python wheel and its corresponding metadata.
435
+ """
436
+
437
+ import tomllib
438
+
439
+ from pkginfo import Wheel
440
+
441
+ pyproject_toml_path = os.path.join(package_root, "pyproject.toml")
442
+
443
+ if not os.path.exists(pyproject_toml_path):
444
+ raise ValueError("Invalid package path, does not contain a pyproject.toml file.")
445
+
446
+ with open(pyproject_toml_path, "rb") as f:
447
+ data = tomllib.load(f)
448
+
449
+ toml_project: dict = data.get("project", {})
450
+ toml_project_name = toml_project.get("name", None)
451
+ toml_packages = set(i for i in data.get("project", {}).get("entry-points", {}).get("nat.plugins", {}))
452
+
453
+ # Extract dependencies using the robust requirement parser with extras resolution
454
+ try:
455
+ toml_dependencies = extract_dependencies_with_extras_resolved(pyproject_toml_path)
456
+ logger.debug("Extracted dependencies with extras resolved: %s", toml_dependencies)
457
+ except Exception as e:
458
+ logger.warning("Failed to extract dependencies with extras resolution, falling back to basic extraction: %s", e)
459
+ # Fallback to basic extraction
460
+ toml_dependencies = set()
461
+ for dep_spec in toml_project.get("dependencies", []):
462
+ try:
463
+ dep_name = parse_requirement(dep_spec)
464
+ if dep_name:
465
+ toml_dependencies.add(dep_name)
466
+ except Exception as e:
467
+ logger.warning("Failed to parse dependency '%s': %s", dep_spec, e)
468
+
469
+ toml_dependencies_transitive = get_all_transitive_dependencies(list(toml_dependencies))
470
+ union_dependencies = toml_dependencies.union(toml_packages)
471
+ union_dependencies.update(toml_dependencies_transitive)
472
+
473
+ working_dir = os.getcwd()
474
+ os.chdir(package_root)
475
+
476
+ result = subprocess.run(["uv", "build", "--wheel"], check=True)
477
+ result.check_returncode()
478
+
479
+ whl_file = sorted(os.listdir("dist"), reverse=True)[0]
480
+ whl_file_path = os.path.join("dist", whl_file)
481
+
482
+ with open(whl_file_path, "rb") as whl:
483
+ whl_bytes = whl.read()
484
+ whl_base64 = base64.b64encode(whl_bytes).decode("utf-8")
485
+
486
+ whl_path = os.path.join(os.getcwd(), whl_file_path)
487
+
488
+ os.chdir(working_dir)
489
+
490
+ whl_version = Wheel(whl_path).version or "unknown"
491
+
492
+ return WheelData(package_root=package_root,
493
+ package_name=toml_project_name,
494
+ toml_project=toml_project,
495
+ toml_dependencies=toml_dependencies,
496
+ toml_nat_packages=toml_packages,
497
+ union_dependencies=union_dependencies,
498
+ whl_path=whl_path,
499
+ whl_base64=whl_base64,
500
+ whl_version=whl_version)
501
+
502
+
503
+ def build_package_metadata(wheel_data: WheelData | None) -> dict[ComponentEnum, list[dict | DiscoveryMetadata]]:
504
+ """Loads discovery metadata for all registered NAT components included in this Python package.
505
+
506
+ Args:
507
+ wheel_data (WheelData): Data model containing a built python wheel and its corresponding metadata.
508
+
509
+ Returns:
510
+ dict[ComponentEnum, list[typing.Union[dict, DiscoveryMetadata]]]: List containing each components discovery
511
+ metadata.
512
+ """
513
+
514
+ from nat.cli.type_registry import GlobalTypeRegistry
515
+ from nat.registry_handlers.metadata_factory import ComponentDiscoveryMetadata
516
+ from nat.runtime.loader import discover_and_register_plugins
517
+
518
+ discover_and_register_plugins(PluginTypes.ALL)
519
+
520
+ registry = GlobalTypeRegistry.get()
521
+
522
+ nat_plugins = discover_entrypoints(PluginTypes.ALL)
523
+
524
+ if (wheel_data is not None):
525
+ registry.register_package(package_name=wheel_data.package_name, package_version=wheel_data.whl_version)
526
+ for entry_point in nat_plugins:
527
+ package_name = entry_point.dist.name
528
+ if (package_name == wheel_data.package_name):
529
+ continue
530
+ if (package_name in wheel_data.union_dependencies):
531
+ registry.register_package(package_name=package_name)
532
+
533
+ else:
534
+ for entry_point in nat_plugins:
535
+ registry.register_package(package_name=entry_point.dist.name)
536
+
537
+ discovery_metadata = {}
538
+ for component_type in ComponentEnum:
539
+
540
+ if (component_type == ComponentEnum.UNDEFINED):
541
+ continue
542
+ component_metadata = ComponentDiscoveryMetadata.from_package_component_type(wheel_data=wheel_data,
543
+ component_type=component_type)
544
+ component_metadata.load_metadata()
545
+ discovery_metadata[component_type] = component_metadata.get_metadata_items()
546
+
547
+ return discovery_metadata
548
+
549
+
550
+ def build_artifact(package_root: str) -> Artifact:
551
+ """Builds a complete NeMo Agent toolkit Artifact that can be published for discovery and reuse.
552
+
553
+ Args:
554
+ package_root (str): Path to root of python package
555
+
556
+ Returns:
557
+ Artifact: A publishable Artifact containing package wheel and discovery metadata.
558
+ """
559
+
560
+ from nat.registry_handlers.schemas.publish import BuiltArtifact
561
+
562
+ wheel_data = build_wheel(package_root=package_root)
563
+ metadata = build_package_metadata(wheel_data=wheel_data)
564
+ built_artifact = BuiltArtifact(whl=wheel_data.whl_base64, metadata=metadata)
565
+
566
+ return Artifact(artifact=built_artifact, whl_path=wheel_data.whl_path)
567
+
568
+
569
+ # Compatibility alias
570
+ build_aiq_artifact = build_artifact
File without changes