nvidia-nat 1.4.0a20251112__py3-none-any.whl → 1.4.0a20260113__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 (492) hide show
  1. aiq/__init__.py +1 -1
  2. nat/{front_ends/mcp → agent/auto_memory_wrapper}/__init__.py +1 -1
  3. nat/agent/auto_memory_wrapper/agent.py +278 -0
  4. nat/agent/auto_memory_wrapper/register.py +227 -0
  5. nat/agent/auto_memory_wrapper/state.py +30 -0
  6. nat/agent/base.py +1 -1
  7. nat/agent/dual_node.py +1 -1
  8. nat/agent/prompt_optimizer/prompt.py +1 -1
  9. nat/agent/prompt_optimizer/register.py +1 -1
  10. nat/agent/react_agent/agent.py +16 -9
  11. nat/agent/react_agent/output_parser.py +2 -2
  12. nat/agent/react_agent/prompt.py +3 -2
  13. nat/agent/react_agent/register.py +2 -2
  14. nat/agent/react_agent/register_per_user_agent.py +104 -0
  15. nat/agent/reasoning_agent/reasoning_agent.py +1 -1
  16. nat/agent/register.py +3 -1
  17. nat/agent/responses_api_agent/__init__.py +1 -1
  18. nat/agent/responses_api_agent/register.py +1 -1
  19. nat/agent/rewoo_agent/agent.py +9 -4
  20. nat/agent/rewoo_agent/prompt.py +1 -1
  21. nat/agent/rewoo_agent/register.py +1 -1
  22. nat/agent/tool_calling_agent/agent.py +5 -4
  23. nat/agent/tool_calling_agent/register.py +1 -1
  24. nat/authentication/__init__.py +1 -1
  25. nat/authentication/api_key/__init__.py +1 -1
  26. nat/authentication/api_key/api_key_auth_provider.py +1 -1
  27. nat/authentication/api_key/api_key_auth_provider_config.py +22 -7
  28. nat/authentication/api_key/register.py +1 -1
  29. nat/authentication/credential_validator/__init__.py +1 -1
  30. nat/authentication/credential_validator/bearer_token_validator.py +1 -1
  31. nat/authentication/exceptions/__init__.py +1 -1
  32. nat/authentication/exceptions/api_key_exceptions.py +1 -1
  33. nat/authentication/http_basic_auth/http_basic_auth_provider.py +1 -1
  34. nat/authentication/http_basic_auth/register.py +1 -1
  35. nat/authentication/interfaces.py +1 -1
  36. nat/authentication/oauth2/__init__.py +1 -1
  37. nat/authentication/oauth2/oauth2_auth_code_flow_provider.py +1 -1
  38. nat/authentication/oauth2/oauth2_auth_code_flow_provider_config.py +1 -1
  39. nat/authentication/oauth2/oauth2_resource_server_config.py +1 -1
  40. nat/authentication/oauth2/register.py +1 -1
  41. nat/authentication/register.py +1 -1
  42. nat/builder/builder.py +563 -1
  43. nat/builder/child_builder.py +385 -0
  44. nat/builder/component_utils.py +34 -4
  45. nat/builder/context.py +34 -1
  46. nat/builder/embedder.py +1 -1
  47. nat/builder/eval_builder.py +19 -7
  48. nat/builder/evaluator.py +1 -1
  49. nat/builder/framework_enum.py +3 -1
  50. nat/builder/front_end.py +1 -1
  51. nat/builder/function.py +113 -5
  52. nat/builder/function_base.py +1 -1
  53. nat/builder/function_info.py +1 -1
  54. nat/builder/intermediate_step_manager.py +1 -1
  55. nat/builder/llm.py +1 -1
  56. nat/builder/per_user_workflow_builder.py +843 -0
  57. nat/builder/retriever.py +1 -1
  58. nat/builder/sync_builder.py +571 -0
  59. nat/builder/user_interaction_manager.py +1 -1
  60. nat/builder/workflow.py +5 -3
  61. nat/builder/workflow_builder.py +619 -378
  62. nat/cli/__init__.py +1 -1
  63. nat/cli/cli_utils/config_override.py +1 -1
  64. nat/cli/cli_utils/validation.py +32 -1
  65. nat/cli/commands/configure/channel/add.py +1 -1
  66. nat/cli/commands/configure/channel/channel.py +1 -1
  67. nat/cli/commands/configure/channel/remove.py +1 -1
  68. nat/cli/commands/configure/channel/update.py +1 -1
  69. nat/cli/commands/configure/configure.py +1 -1
  70. nat/cli/commands/evaluate.py +87 -13
  71. nat/cli/commands/finetune.py +132 -0
  72. nat/cli/commands/info/__init__.py +1 -1
  73. nat/cli/commands/info/info.py +1 -1
  74. nat/cli/commands/info/list_channels.py +1 -1
  75. nat/cli/commands/info/list_components.py +1 -1
  76. nat/cli/commands/object_store/__init__.py +1 -1
  77. nat/cli/commands/object_store/object_store.py +1 -1
  78. nat/cli/commands/optimize.py +1 -1
  79. nat/cli/commands/{mcp → red_teaming}/__init__.py +1 -1
  80. nat/cli/commands/red_teaming/red_teaming.py +138 -0
  81. nat/cli/commands/red_teaming/red_teaming_utils.py +73 -0
  82. nat/cli/commands/registry/__init__.py +1 -1
  83. nat/cli/commands/registry/publish.py +1 -1
  84. nat/cli/commands/registry/pull.py +1 -1
  85. nat/cli/commands/registry/registry.py +1 -1
  86. nat/cli/commands/registry/remove.py +1 -1
  87. nat/cli/commands/registry/search.py +1 -1
  88. nat/cli/commands/sizing/__init__.py +1 -1
  89. nat/cli/commands/sizing/calc.py +1 -1
  90. nat/cli/commands/sizing/sizing.py +1 -1
  91. nat/cli/commands/start.py +1 -1
  92. nat/cli/commands/uninstall.py +1 -1
  93. nat/cli/commands/validate.py +1 -1
  94. nat/cli/commands/workflow/__init__.py +1 -1
  95. nat/cli/commands/workflow/workflow.py +1 -1
  96. nat/cli/commands/workflow/workflow_commands.py +3 -2
  97. nat/cli/entrypoint.py +15 -37
  98. nat/cli/main.py +2 -2
  99. nat/cli/plugin_loader.py +69 -0
  100. nat/cli/register_workflow.py +233 -5
  101. nat/cli/type_registry.py +237 -3
  102. nat/control_flow/register.py +1 -1
  103. nat/control_flow/router_agent/agent.py +1 -1
  104. nat/control_flow/router_agent/prompt.py +1 -1
  105. nat/control_flow/router_agent/register.py +1 -1
  106. nat/control_flow/sequential_executor.py +28 -7
  107. nat/data_models/__init__.py +1 -1
  108. nat/data_models/agent.py +1 -1
  109. nat/data_models/api_server.py +38 -3
  110. nat/data_models/authentication.py +1 -1
  111. nat/data_models/common.py +1 -1
  112. nat/data_models/component.py +9 -1
  113. nat/data_models/component_ref.py +45 -1
  114. nat/data_models/config.py +78 -1
  115. nat/data_models/dataset_handler.py +15 -2
  116. nat/data_models/discovery_metadata.py +1 -1
  117. nat/data_models/embedder.py +1 -1
  118. nat/data_models/evaluate.py +6 -1
  119. nat/data_models/evaluator.py +1 -1
  120. nat/data_models/finetuning.py +260 -0
  121. nat/data_models/front_end.py +1 -1
  122. nat/data_models/function.py +15 -2
  123. nat/data_models/function_dependencies.py +1 -1
  124. nat/data_models/gated_field_mixin.py +1 -1
  125. nat/data_models/interactive.py +1 -1
  126. nat/data_models/intermediate_step.py +29 -2
  127. nat/data_models/invocation_node.py +1 -1
  128. nat/data_models/llm.py +1 -1
  129. nat/data_models/logging.py +1 -1
  130. nat/data_models/memory.py +1 -1
  131. nat/data_models/middleware.py +37 -0
  132. nat/data_models/object_store.py +1 -1
  133. nat/data_models/openai_mcp.py +1 -1
  134. nat/data_models/optimizable.py +1 -1
  135. nat/data_models/optimizer.py +1 -1
  136. nat/data_models/profiler.py +1 -1
  137. nat/data_models/registry_handler.py +1 -1
  138. nat/data_models/retriever.py +1 -1
  139. nat/data_models/retry_mixin.py +1 -1
  140. nat/data_models/runtime_enum.py +26 -0
  141. nat/data_models/span.py +1 -1
  142. nat/data_models/step_adaptor.py +1 -1
  143. nat/data_models/streaming.py +1 -1
  144. nat/data_models/swe_bench_model.py +1 -1
  145. nat/data_models/telemetry_exporter.py +1 -1
  146. nat/data_models/thinking_mixin.py +1 -1
  147. nat/data_models/ttc_strategy.py +1 -1
  148. nat/embedder/azure_openai_embedder.py +1 -1
  149. nat/embedder/nim_embedder.py +1 -1
  150. nat/embedder/openai_embedder.py +1 -1
  151. nat/embedder/register.py +1 -1
  152. nat/eval/__init__.py +1 -1
  153. nat/eval/config.py +8 -1
  154. nat/eval/dataset_handler/dataset_downloader.py +1 -1
  155. nat/eval/dataset_handler/dataset_filter.py +1 -1
  156. nat/eval/dataset_handler/dataset_handler.py +4 -2
  157. nat/eval/evaluate.py +226 -81
  158. nat/eval/evaluator/__init__.py +1 -1
  159. nat/eval/evaluator/base_evaluator.py +2 -2
  160. nat/eval/evaluator/evaluator_model.py +3 -2
  161. nat/eval/intermediate_step_adapter.py +1 -1
  162. nat/eval/llm_validator.py +336 -0
  163. nat/eval/rag_evaluator/evaluate.py +17 -10
  164. nat/eval/rag_evaluator/register.py +1 -1
  165. nat/eval/red_teaming_evaluator/__init__.py +14 -0
  166. nat/eval/red_teaming_evaluator/data_models.py +66 -0
  167. nat/eval/red_teaming_evaluator/evaluate.py +327 -0
  168. nat/eval/red_teaming_evaluator/filter_conditions.py +75 -0
  169. nat/eval/red_teaming_evaluator/register.py +55 -0
  170. nat/eval/register.py +2 -1
  171. nat/eval/remote_workflow.py +1 -1
  172. nat/eval/runners/__init__.py +1 -1
  173. nat/eval/runners/config.py +1 -1
  174. nat/eval/runners/multi_eval_runner.py +1 -1
  175. nat/eval/runners/red_teaming_runner/__init__.py +24 -0
  176. nat/eval/runners/red_teaming_runner/config.py +282 -0
  177. nat/eval/runners/red_teaming_runner/report_utils.py +707 -0
  178. nat/eval/runners/red_teaming_runner/runner.py +867 -0
  179. nat/eval/runtime_evaluator/__init__.py +1 -1
  180. nat/eval/runtime_evaluator/evaluate.py +1 -1
  181. nat/eval/runtime_evaluator/register.py +1 -1
  182. nat/eval/runtime_event_subscriber.py +1 -1
  183. nat/eval/swe_bench_evaluator/evaluate.py +1 -1
  184. nat/eval/swe_bench_evaluator/register.py +1 -1
  185. nat/eval/trajectory_evaluator/evaluate.py +2 -2
  186. nat/eval/trajectory_evaluator/register.py +1 -1
  187. nat/eval/tunable_rag_evaluator/evaluate.py +5 -5
  188. nat/eval/tunable_rag_evaluator/register.py +1 -1
  189. nat/eval/usage_stats.py +1 -1
  190. nat/eval/utils/eval_trace_ctx.py +1 -1
  191. nat/eval/utils/output_uploader.py +1 -1
  192. nat/eval/utils/tqdm_position_registry.py +1 -1
  193. nat/eval/utils/weave_eval.py +1 -1
  194. nat/experimental/decorators/experimental_warning_decorator.py +1 -1
  195. nat/experimental/test_time_compute/editing/iterative_plan_refinement_editor.py +1 -1
  196. nat/experimental/test_time_compute/editing/llm_as_a_judge_editor.py +1 -1
  197. nat/experimental/test_time_compute/editing/motivation_aware_summarization.py +1 -1
  198. nat/experimental/test_time_compute/functions/execute_score_select_function.py +1 -1
  199. nat/experimental/test_time_compute/functions/multi_llm_judge_function.py +88 -0
  200. nat/experimental/test_time_compute/functions/plan_select_execute_function.py +1 -1
  201. nat/experimental/test_time_compute/functions/ttc_tool_orchestration_function.py +1 -1
  202. nat/experimental/test_time_compute/functions/ttc_tool_wrapper_function.py +1 -1
  203. nat/experimental/test_time_compute/models/editor_config.py +1 -1
  204. nat/experimental/test_time_compute/models/scoring_config.py +1 -1
  205. nat/experimental/test_time_compute/models/search_config.py +20 -2
  206. nat/experimental/test_time_compute/models/selection_config.py +33 -2
  207. nat/experimental/test_time_compute/models/stage_enums.py +1 -1
  208. nat/experimental/test_time_compute/models/strategy_base.py +1 -1
  209. nat/experimental/test_time_compute/models/tool_use_config.py +1 -1
  210. nat/experimental/test_time_compute/models/ttc_item.py +1 -1
  211. nat/experimental/test_time_compute/register.py +4 -1
  212. nat/experimental/test_time_compute/scoring/llm_based_agent_scorer.py +1 -1
  213. nat/experimental/test_time_compute/scoring/llm_based_plan_scorer.py +1 -1
  214. nat/experimental/test_time_compute/scoring/motivation_aware_scorer.py +1 -1
  215. nat/experimental/test_time_compute/search/multi_llm_generation.py +115 -0
  216. nat/experimental/test_time_compute/search/multi_llm_planner.py +1 -1
  217. nat/experimental/test_time_compute/search/multi_query_retrieval_search.py +1 -1
  218. nat/experimental/test_time_compute/search/single_shot_multi_plan_planner.py +1 -1
  219. nat/experimental/test_time_compute/selection/best_of_n_selector.py +1 -1
  220. nat/experimental/test_time_compute/selection/llm_based_agent_output_selector.py +1 -1
  221. nat/experimental/test_time_compute/selection/llm_based_output_merging_selector.py +1 -1
  222. nat/experimental/test_time_compute/selection/llm_based_plan_selector.py +1 -1
  223. nat/experimental/test_time_compute/selection/llm_judge_selection.py +127 -0
  224. nat/experimental/test_time_compute/selection/threshold_selector.py +1 -1
  225. nat/finetuning/__init__.py +24 -0
  226. nat/finetuning/finetuning_runtime.py +143 -0
  227. nat/finetuning/interfaces/__init__.py +24 -0
  228. nat/finetuning/interfaces/finetuning_runner.py +261 -0
  229. nat/finetuning/interfaces/trainer_adapter.py +103 -0
  230. nat/finetuning/interfaces/trajectory_builder.py +115 -0
  231. nat/finetuning/utils/__init__.py +15 -0
  232. nat/finetuning/utils/parsers/__init__.py +15 -0
  233. nat/finetuning/utils/parsers/adk_parser.py +141 -0
  234. nat/finetuning/utils/parsers/base_parser.py +238 -0
  235. nat/finetuning/utils/parsers/common.py +91 -0
  236. nat/finetuning/utils/parsers/langchain_parser.py +267 -0
  237. nat/finetuning/utils/parsers/llama_index_parser.py +218 -0
  238. nat/front_ends/__init__.py +1 -1
  239. nat/front_ends/console/__init__.py +1 -1
  240. nat/front_ends/console/authentication_flow_handler.py +1 -1
  241. nat/front_ends/console/console_front_end_config.py +4 -1
  242. nat/front_ends/console/console_front_end_plugin.py +5 -4
  243. nat/front_ends/console/register.py +1 -1
  244. nat/front_ends/cron/__init__.py +1 -1
  245. nat/front_ends/fastapi/__init__.py +1 -1
  246. nat/front_ends/fastapi/async_job.py +128 -0
  247. nat/front_ends/fastapi/auth_flow_handlers/http_flow_handler.py +1 -1
  248. nat/front_ends/fastapi/auth_flow_handlers/websocket_flow_handler.py +13 -9
  249. nat/front_ends/fastapi/dask_client_mixin.py +1 -1
  250. nat/front_ends/fastapi/fastapi_front_end_config.py +23 -1
  251. nat/front_ends/fastapi/fastapi_front_end_controller.py +1 -1
  252. nat/front_ends/fastapi/fastapi_front_end_plugin.py +25 -30
  253. nat/front_ends/fastapi/fastapi_front_end_plugin_worker.py +318 -59
  254. nat/front_ends/fastapi/html_snippets/__init__.py +1 -1
  255. nat/front_ends/fastapi/html_snippets/auth_code_grant_success.py +1 -1
  256. nat/front_ends/fastapi/intermediate_steps_subscriber.py +12 -1
  257. nat/front_ends/fastapi/job_store.py +23 -11
  258. nat/front_ends/fastapi/main.py +1 -1
  259. nat/front_ends/fastapi/message_handler.py +27 -4
  260. nat/front_ends/fastapi/message_validator.py +54 -2
  261. nat/front_ends/fastapi/register.py +1 -1
  262. nat/front_ends/fastapi/response_helpers.py +16 -15
  263. nat/front_ends/fastapi/step_adaptor.py +1 -1
  264. nat/front_ends/fastapi/utils.py +1 -1
  265. nat/front_ends/register.py +1 -2
  266. nat/front_ends/simple_base/__init__.py +1 -1
  267. nat/front_ends/simple_base/simple_front_end_plugin_base.py +6 -4
  268. nat/llm/aws_bedrock_llm.py +1 -1
  269. nat/llm/azure_openai_llm.py +10 -1
  270. nat/llm/dynamo_llm.py +363 -0
  271. nat/llm/huggingface_llm.py +177 -0
  272. nat/llm/litellm_llm.py +1 -1
  273. nat/llm/nim_llm.py +1 -1
  274. nat/llm/openai_llm.py +1 -1
  275. nat/llm/register.py +3 -1
  276. nat/llm/utils/__init__.py +1 -1
  277. nat/llm/utils/env_config_value.py +1 -1
  278. nat/llm/utils/error.py +1 -1
  279. nat/llm/utils/thinking.py +1 -1
  280. nat/memory/__init__.py +1 -1
  281. nat/memory/interfaces.py +1 -1
  282. nat/memory/models.py +1 -1
  283. nat/meta/pypi.md +1 -1
  284. nat/middleware/__init__.py +35 -0
  285. nat/middleware/cache/__init__.py +14 -0
  286. nat/middleware/cache/cache_middleware.py +253 -0
  287. nat/middleware/cache/cache_middleware_config.py +44 -0
  288. nat/middleware/cache/register.py +33 -0
  289. nat/middleware/defense/__init__.py +14 -0
  290. nat/middleware/defense/defense_middleware.py +362 -0
  291. nat/middleware/defense/defense_middleware_content_guard.py +455 -0
  292. nat/middleware/defense/defense_middleware_data_models.py +91 -0
  293. nat/middleware/defense/defense_middleware_output_verifier.py +440 -0
  294. nat/middleware/defense/defense_middleware_pii.py +356 -0
  295. nat/middleware/defense/register.py +82 -0
  296. nat/middleware/dynamic/__init__.py +14 -0
  297. nat/middleware/dynamic/dynamic_function_middleware.py +962 -0
  298. nat/middleware/dynamic/dynamic_middleware_config.py +132 -0
  299. nat/middleware/dynamic/register.py +34 -0
  300. nat/middleware/function_middleware.py +370 -0
  301. nat/middleware/logging/__init__.py +14 -0
  302. nat/middleware/logging/logging_middleware.py +67 -0
  303. nat/middleware/logging/logging_middleware_config.py +28 -0
  304. nat/middleware/logging/register.py +33 -0
  305. nat/middleware/middleware.py +298 -0
  306. nat/middleware/red_teaming/__init__.py +14 -0
  307. nat/middleware/red_teaming/red_teaming_middleware.py +344 -0
  308. nat/middleware/red_teaming/red_teaming_middleware_config.py +112 -0
  309. nat/middleware/red_teaming/register.py +47 -0
  310. nat/middleware/register.py +22 -0
  311. nat/middleware/utils/__init__.py +14 -0
  312. nat/middleware/utils/workflow_inventory.py +155 -0
  313. nat/object_store/__init__.py +1 -1
  314. nat/object_store/in_memory_object_store.py +1 -1
  315. nat/object_store/interfaces.py +1 -1
  316. nat/object_store/models.py +1 -1
  317. nat/object_store/register.py +1 -1
  318. nat/observability/__init__.py +1 -1
  319. nat/observability/exporter/__init__.py +1 -1
  320. nat/observability/exporter/base_exporter.py +1 -1
  321. nat/observability/exporter/exporter.py +1 -1
  322. nat/observability/exporter/file_exporter.py +1 -1
  323. nat/observability/exporter/processing_exporter.py +1 -1
  324. nat/observability/exporter/raw_exporter.py +1 -1
  325. nat/observability/exporter/span_exporter.py +7 -1
  326. nat/observability/exporter_manager.py +1 -1
  327. nat/observability/mixin/__init__.py +1 -1
  328. nat/observability/mixin/batch_config_mixin.py +1 -1
  329. nat/observability/mixin/collector_config_mixin.py +1 -1
  330. nat/observability/mixin/file_mixin.py +1 -1
  331. nat/observability/mixin/file_mode.py +1 -1
  332. nat/observability/mixin/redaction_config_mixin.py +1 -1
  333. nat/observability/mixin/resource_conflict_mixin.py +1 -1
  334. nat/observability/mixin/serialize_mixin.py +1 -1
  335. nat/observability/mixin/tagging_config_mixin.py +1 -1
  336. nat/observability/mixin/type_introspection_mixin.py +1 -1
  337. nat/observability/processor/__init__.py +1 -1
  338. nat/observability/processor/batching_processor.py +1 -1
  339. nat/observability/processor/callback_processor.py +1 -1
  340. nat/observability/processor/falsy_batch_filter_processor.py +1 -1
  341. nat/observability/processor/intermediate_step_serializer.py +1 -1
  342. nat/observability/processor/processor.py +1 -1
  343. nat/observability/processor/processor_factory.py +1 -1
  344. nat/observability/processor/redaction/__init__.py +1 -1
  345. nat/observability/processor/redaction/contextual_redaction_processor.py +1 -1
  346. nat/observability/processor/redaction/contextual_span_redaction_processor.py +1 -1
  347. nat/observability/processor/redaction/redaction_processor.py +1 -1
  348. nat/observability/processor/redaction/span_header_redaction_processor.py +1 -1
  349. nat/observability/processor/span_tagging_processor.py +1 -1
  350. nat/observability/register.py +1 -1
  351. nat/observability/utils/__init__.py +1 -1
  352. nat/observability/utils/dict_utils.py +1 -1
  353. nat/observability/utils/time_utils.py +1 -1
  354. nat/profiler/calc/__init__.py +1 -1
  355. nat/profiler/calc/calc_runner.py +3 -3
  356. nat/profiler/calc/calculations.py +1 -1
  357. nat/profiler/calc/data_models.py +1 -1
  358. nat/profiler/calc/plot.py +30 -3
  359. nat/profiler/callbacks/agno_callback_handler.py +1 -1
  360. nat/profiler/callbacks/base_callback_class.py +1 -1
  361. nat/profiler/callbacks/langchain_callback_handler.py +33 -3
  362. nat/profiler/callbacks/llama_index_callback_handler.py +13 -10
  363. nat/profiler/callbacks/semantic_kernel_callback_handler.py +1 -1
  364. nat/profiler/callbacks/token_usage_base_model.py +1 -1
  365. nat/profiler/data_frame_row.py +1 -1
  366. nat/profiler/data_models.py +1 -1
  367. nat/profiler/decorators/framework_wrapper.py +32 -1
  368. nat/profiler/decorators/function_tracking.py +1 -1
  369. nat/profiler/forecasting/config.py +1 -1
  370. nat/profiler/forecasting/model_trainer.py +1 -1
  371. nat/profiler/forecasting/models/__init__.py +1 -1
  372. nat/profiler/forecasting/models/forecasting_base_model.py +1 -1
  373. nat/profiler/forecasting/models/linear_model.py +1 -1
  374. nat/profiler/forecasting/models/random_forest_regressor.py +1 -1
  375. nat/profiler/inference_metrics_model.py +1 -1
  376. nat/profiler/inference_optimization/bottleneck_analysis/nested_stack_analysis.py +1 -1
  377. nat/profiler/inference_optimization/bottleneck_analysis/simple_stack_analysis.py +1 -1
  378. nat/profiler/inference_optimization/data_models.py +1 -1
  379. nat/profiler/inference_optimization/experimental/concurrency_spike_analysis.py +1 -1
  380. nat/profiler/inference_optimization/experimental/prefix_span_analysis.py +1 -1
  381. nat/profiler/inference_optimization/llm_metrics.py +1 -1
  382. nat/profiler/inference_optimization/prompt_caching.py +1 -1
  383. nat/profiler/inference_optimization/token_uniqueness.py +1 -1
  384. nat/profiler/inference_optimization/workflow_runtimes.py +1 -1
  385. nat/profiler/intermediate_property_adapter.py +1 -1
  386. nat/profiler/parameter_optimization/optimizable_utils.py +1 -1
  387. nat/profiler/parameter_optimization/optimizer_runtime.py +1 -1
  388. nat/profiler/parameter_optimization/parameter_optimizer.py +1 -1
  389. nat/profiler/parameter_optimization/parameter_selection.py +1 -1
  390. nat/profiler/parameter_optimization/pareto_visualizer.py +1 -1
  391. nat/profiler/parameter_optimization/prompt_optimizer.py +1 -1
  392. nat/profiler/parameter_optimization/update_helpers.py +1 -1
  393. nat/profiler/profile_runner.py +1 -1
  394. nat/profiler/utils.py +1 -1
  395. nat/registry_handlers/local/local_handler.py +1 -1
  396. nat/registry_handlers/local/register_local.py +1 -1
  397. nat/registry_handlers/metadata_factory.py +1 -1
  398. nat/registry_handlers/package_utils.py +1 -1
  399. nat/registry_handlers/pypi/pypi_handler.py +1 -1
  400. nat/registry_handlers/pypi/register_pypi.py +1 -1
  401. nat/registry_handlers/register.py +1 -1
  402. nat/registry_handlers/registry_handler_base.py +1 -1
  403. nat/registry_handlers/rest/register_rest.py +1 -1
  404. nat/registry_handlers/rest/rest_handler.py +1 -1
  405. nat/registry_handlers/schemas/headers.py +1 -1
  406. nat/registry_handlers/schemas/package.py +1 -1
  407. nat/registry_handlers/schemas/publish.py +1 -1
  408. nat/registry_handlers/schemas/pull.py +1 -1
  409. nat/registry_handlers/schemas/remove.py +1 -1
  410. nat/registry_handlers/schemas/search.py +1 -1
  411. nat/registry_handlers/schemas/status.py +1 -1
  412. nat/retriever/interface.py +1 -1
  413. nat/retriever/milvus/__init__.py +1 -1
  414. nat/retriever/milvus/register.py +12 -4
  415. nat/retriever/milvus/retriever.py +103 -41
  416. nat/retriever/models.py +1 -1
  417. nat/retriever/nemo_retriever/__init__.py +1 -1
  418. nat/retriever/nemo_retriever/register.py +1 -1
  419. nat/retriever/nemo_retriever/retriever.py +5 -5
  420. nat/retriever/register.py +1 -1
  421. nat/runtime/__init__.py +1 -1
  422. nat/runtime/loader.py +10 -3
  423. nat/runtime/metrics.py +180 -0
  424. nat/runtime/runner.py +13 -6
  425. nat/runtime/session.py +458 -32
  426. nat/runtime/user_metadata.py +1 -1
  427. nat/settings/global_settings.py +1 -1
  428. nat/tool/chat_completion.py +1 -1
  429. nat/tool/code_execution/README.md +1 -1
  430. nat/tool/code_execution/code_sandbox.py +2 -2
  431. nat/tool/code_execution/local_sandbox/Dockerfile.sandbox +1 -1
  432. nat/tool/code_execution/local_sandbox/__init__.py +1 -1
  433. nat/tool/code_execution/local_sandbox/local_sandbox_server.py +1 -1
  434. nat/tool/code_execution/local_sandbox/start_local_sandbox.sh +1 -1
  435. nat/tool/code_execution/register.py +1 -1
  436. nat/tool/code_execution/utils.py +1 -1
  437. nat/tool/datetime_tools.py +1 -1
  438. nat/tool/document_search.py +1 -1
  439. nat/tool/github_tools.py +1 -1
  440. nat/tool/memory_tools/add_memory_tool.py +1 -1
  441. nat/tool/memory_tools/delete_memory_tool.py +1 -1
  442. nat/tool/memory_tools/get_memory_tool.py +1 -1
  443. nat/tool/nvidia_rag.py +2 -2
  444. nat/tool/register.py +1 -1
  445. nat/tool/retriever.py +1 -1
  446. nat/tool/server_tools.py +1 -1
  447. nat/utils/__init__.py +8 -5
  448. nat/utils/callable_utils.py +1 -1
  449. nat/utils/data_models/schema_validator.py +1 -1
  450. nat/utils/debugging_utils.py +1 -1
  451. nat/utils/decorators.py +1 -1
  452. nat/utils/dump_distro_mapping.py +1 -1
  453. nat/utils/exception_handlers/automatic_retries.py +3 -3
  454. nat/utils/exception_handlers/schemas.py +1 -1
  455. nat/utils/io/model_processing.py +1 -1
  456. nat/utils/io/supress_logs.py +33 -0
  457. nat/utils/io/yaml_tools.py +1 -1
  458. nat/utils/log_levels.py +1 -1
  459. nat/utils/log_utils.py +13 -1
  460. nat/utils/metadata_utils.py +1 -1
  461. nat/utils/optional_imports.py +1 -1
  462. nat/utils/producer_consumer_queue.py +1 -1
  463. nat/utils/reactive/base/observable_base.py +1 -1
  464. nat/utils/reactive/base/observer_base.py +1 -1
  465. nat/utils/reactive/base/subject_base.py +1 -1
  466. nat/utils/reactive/observable.py +1 -1
  467. nat/utils/reactive/observer.py +1 -1
  468. nat/utils/reactive/subject.py +1 -1
  469. nat/utils/reactive/subscription.py +1 -1
  470. nat/utils/responses_api.py +1 -1
  471. nat/utils/settings/global_settings.py +1 -1
  472. nat/utils/string_utils.py +1 -1
  473. nat/utils/type_converter.py +18 -5
  474. nat/utils/type_utils.py +1 -1
  475. nat/utils/url_utils.py +1 -1
  476. {nvidia_nat-1.4.0a20251112.dist-info → nvidia_nat-1.4.0a20260113.dist-info}/METADATA +46 -15
  477. nvidia_nat-1.4.0a20260113.dist-info/RECORD +547 -0
  478. nvidia_nat-1.4.0a20260113.dist-info/entry_points.txt +38 -0
  479. nat/cli/commands/mcp/mcp.py +0 -986
  480. nat/front_ends/mcp/introspection_token_verifier.py +0 -73
  481. nat/front_ends/mcp/mcp_front_end_config.py +0 -109
  482. nat/front_ends/mcp/mcp_front_end_plugin.py +0 -151
  483. nat/front_ends/mcp/mcp_front_end_plugin_worker.py +0 -362
  484. nat/front_ends/mcp/memory_profiler.py +0 -320
  485. nat/front_ends/mcp/register.py +0 -27
  486. nat/front_ends/mcp/tool_converter.py +0 -321
  487. nvidia_nat-1.4.0a20251112.dist-info/RECORD +0 -481
  488. nvidia_nat-1.4.0a20251112.dist-info/entry_points.txt +0 -22
  489. {nvidia_nat-1.4.0a20251112.dist-info → nvidia_nat-1.4.0a20260113.dist-info}/WHEEL +0 -0
  490. {nvidia_nat-1.4.0a20251112.dist-info → nvidia_nat-1.4.0a20260113.dist-info}/licenses/LICENSE-3rd-party.txt +0 -0
  491. {nvidia_nat-1.4.0a20251112.dist-info → nvidia_nat-1.4.0a20260113.dist-info}/licenses/LICENSE.md +0 -0
  492. {nvidia_nat-1.4.0a20251112.dist-info → nvidia_nat-1.4.0a20260113.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,91 @@
1
+ # SPDX-FileCopyrightText: Copyright (c) 2025-2026, NVIDIA CORPORATION & AFFILIATES.
2
+ # All rights reserved.
3
+ # SPDX-License-Identifier: Apache-2.0
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+ """Common utilities shared across all parser implementations."""
17
+
18
+ import json
19
+ from typing import Any
20
+
21
+ from nat.data_models.intermediate_step import IntermediateStep
22
+
23
+
24
+ def extract_content(data: Any) -> str:
25
+ """Extract string content from various data formats.
26
+
27
+ This is a shared utility used by all parser implementations.
28
+
29
+ Args:
30
+ data: The data to extract content from. Can be a string, dict, list,
31
+ or object with content/text attributes.
32
+
33
+ Returns:
34
+ The extracted content as a string.
35
+ """
36
+ if isinstance(data, str):
37
+ return data
38
+ elif isinstance(data, dict):
39
+ # Try common content fields
40
+ for key in ["content", "text", "message", "output"]:
41
+ if key in data:
42
+ return str(data[key])
43
+ # Check for blocks format
44
+ if "blocks" in data:
45
+ blocks = data["blocks"]
46
+ if isinstance(blocks, list):
47
+ return ''.join(block.get('text', '') if isinstance(block, dict) else str(block) for block in blocks)
48
+ # Fallback to JSON representation
49
+ return json.dumps(data)
50
+ elif isinstance(data, list):
51
+ # Join list items if they're strings
52
+ if all(isinstance(item, str) for item in data):
53
+ return "\n".join(data)
54
+ # Otherwise convert to JSON
55
+ return json.dumps(data)
56
+ elif hasattr(data, 'content'):
57
+ return str(data.content)
58
+ elif hasattr(data, 'text'):
59
+ return str(data.text)
60
+ else:
61
+ return str(data)
62
+
63
+
64
+ def parse_generic_message(message: IntermediateStep) -> dict:
65
+ """Parse messages that don't fit standard patterns.
66
+
67
+ This is a shared utility used by all parser implementations for handling
68
+ event types that don't have specialized parsers.
69
+
70
+ Args:
71
+ message: An IntermediateStep object representing a message.
72
+
73
+ Returns:
74
+ A dictionary with 'role' and 'content' keys.
75
+ """
76
+ result = {"role": "user"} # Default to user role
77
+
78
+ # Try to extract content from various fields
79
+ if message.data:
80
+ if message.data.output:
81
+ result["content"] = extract_content(message.data.output)
82
+ elif message.data.input:
83
+ result["content"] = extract_content(message.data.input)
84
+ elif message.data.chunk:
85
+ result["content"] = extract_content(message.data.chunk)
86
+ else:
87
+ result["content"] = ""
88
+ else:
89
+ result["content"] = ""
90
+
91
+ return result
@@ -0,0 +1,267 @@
1
+ # SPDX-FileCopyrightText: Copyright (c) 2025-2026, NVIDIA CORPORATION & AFFILIATES.
2
+ # All rights reserved.
3
+ # SPDX-License-Identifier: Apache-2.0
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ from langchain_core.messages import AIMessage
18
+ from langchain_core.messages import AIMessageChunk
19
+ from langchain_core.messages import BaseMessage
20
+ from langchain_core.messages import FunctionMessage
21
+ from langchain_core.messages import HumanMessage
22
+ from langchain_core.messages import SystemMessage
23
+ from langchain_core.messages import ToolMessage
24
+
25
+ from nat.data_models.intermediate_step import IntermediateStep
26
+ from nat.data_models.intermediate_step import IntermediateStepType
27
+ from nat.finetuning.utils.parsers.common import extract_content
28
+ from nat.finetuning.utils.parsers.common import parse_generic_message
29
+
30
+ # Re-export for backwards compatibility and internal use
31
+ _extract_content = extract_content
32
+ _parse_generic_message = parse_generic_message
33
+
34
+
35
+ def parse_to_openai_message(message: IntermediateStep) -> dict | list[dict]:
36
+ """
37
+ Convert IntermediateStep to OpenAI-compatible message dictionary.
38
+
39
+ Args:
40
+ message: An IntermediateStep object representing a single message.
41
+ previous_message: Previous message for context (reserved for future).
42
+
43
+ Returns:
44
+ A dictionary formatted for OpenAI API consumption.
45
+ """
46
+
47
+ # Handle different event types to determine role and extract content
48
+ if message.event_type == IntermediateStepType.LLM_END:
49
+ # Assistant message with potential tool calls
50
+ result = _parse_assistant_message(message)
51
+ elif message.event_type == IntermediateStepType.TOOL_END:
52
+ # Tool response message
53
+ result = _parse_tool_message(message)
54
+ elif message.event_type == IntermediateStepType.LLM_START:
55
+ # Extract user/system messages from the input
56
+ result = _parse_input_message(message)
57
+ # drop logprobs field if exists
58
+ if "logprobs" in result:
59
+ del result["logprobs"]
60
+ else:
61
+ # For other types, try to infer from the data
62
+ result = _parse_generic_message(message)
63
+
64
+ return result
65
+
66
+
67
+ def _parse_assistant_message(message: IntermediateStep) -> dict:
68
+ """Parse an assistant message from LLM_END event."""
69
+ result = {"role": "assistant"}
70
+ # Get the generation from payload if available
71
+ if message.data and message.data.payload:
72
+ payload = message.data.payload
73
+ msg = None
74
+ if isinstance(payload, dict) and "message" in payload:
75
+ # Handle dict payloads
76
+ try:
77
+ msg = AIMessage(**payload["message"])
78
+ except Exception as _:
79
+ try:
80
+ msg = AIMessageChunk(**payload["message"])
81
+ except Exception as _:
82
+ msg = None
83
+
84
+ # Handle ChatGeneration objects from LangChain
85
+ if hasattr(payload, 'message'):
86
+ msg = payload.message
87
+ if msg:
88
+ # Extract content
89
+ if isinstance(msg, AIMessage):
90
+ result["content"] = msg.content or ""
91
+
92
+ # Extract tool calls if present
93
+ if hasattr(msg, 'tool_calls') and msg.tool_calls:
94
+ result["tool_calls"] = msg.tool_calls
95
+ elif 'tool_calls' in msg.additional_kwargs:
96
+ tool_calls = msg.additional_kwargs['tool_calls']
97
+ result["tool_calls"] = tool_calls
98
+
99
+ # Extract function call if present
100
+ if hasattr(msg, 'function_call') and msg.function_call:
101
+ result["function_call"] = msg.function_call
102
+ elif 'function_call' in msg.additional_kwargs:
103
+ func_call = msg.additional_kwargs['function_call']
104
+ result["function_call"] = func_call
105
+ else:
106
+ # Fallback to extracting content as string
107
+ result["content"] = str(getattr(msg, 'content', msg))
108
+
109
+ # Extract logprobs if available
110
+ gen_info = getattr(msg, 'response_metadata', None)
111
+ if gen_info and 'logprobs' in gen_info:
112
+ result["logprobs"] = gen_info['logprobs']
113
+
114
+ elif message.data and message.data.output:
115
+ # Fallback to output field
116
+ result["content"] = _extract_content(message.data.output)
117
+ else:
118
+ result["content"] = ""
119
+
120
+ # Check for logprobs in data field
121
+ logprobs = (getattr(message.data, 'logprobs', None) if message.data else None)
122
+ if logprobs:
123
+ result["logprobs"] = logprobs
124
+
125
+ # if not logprobs, set to empty dict to avoid issues downstream
126
+ if "logprobs" not in result:
127
+ result["logprobs"] = {}
128
+
129
+ return result
130
+
131
+
132
+ def _parse_tool_message(message: IntermediateStep) -> dict:
133
+ """Parse a tool response message from TOOL_END event."""
134
+ result = {"role": "tool"}
135
+
136
+ # Extract tool output as content
137
+ if message.data:
138
+ if message.data.output:
139
+ result["content"] = _extract_content(message.data.output)
140
+ elif message.data.payload:
141
+ result["content"] = _extract_content(message.data.payload)
142
+ else:
143
+ result["content"] = ""
144
+ else:
145
+ result["content"] = ""
146
+
147
+ # Add tool_call_id if available from metadata or UUID
148
+ if message.metadata and hasattr(message.metadata, 'tool_call_id'):
149
+ result["tool_call_id"] = message.metadata.tool_call_id
150
+ else:
151
+ result["tool_call_id"] = 0
152
+
153
+ return result
154
+
155
+
156
+ def _parse_input_message(message: IntermediateStep) -> dict | list[dict]:
157
+ """Parse user or system messages from LLM_START event."""
158
+ if not message.data or not message.data.input:
159
+ return {"role": "user", "content": ""}
160
+
161
+ input_data = message.data.input
162
+
163
+ # Handle list of messages
164
+ if isinstance(input_data, list) and len(input_data) > 0:
165
+ # Get the last message in the list
166
+ messages = []
167
+ for msg in input_data:
168
+ last_msg = msg
169
+ # Handle BaseMessage objects
170
+ if isinstance(last_msg, BaseMessage):
171
+ messages.append(_parse_langchain_message(last_msg))
172
+ # Handle dict messages
173
+ elif isinstance(last_msg, dict):
174
+ messages.append(_parse_dict_message(last_msg))
175
+ # Handle string messages
176
+ elif isinstance(last_msg, str):
177
+ messages.append({"role": "user", "content": last_msg})
178
+ else:
179
+ messages.append({"role": "user", "content": str(last_msg)})
180
+ return messages
181
+ # Handle single message
182
+ elif isinstance(input_data, BaseMessage):
183
+ return _parse_langchain_message(input_data)
184
+ elif isinstance(input_data, dict):
185
+ return _parse_dict_message(input_data)
186
+ else:
187
+ return {"role": "user", "content": _extract_content(input_data)}
188
+
189
+
190
+ def _parse_langchain_message(msg: BaseMessage) -> dict:
191
+ """Parse a LangChain BaseMessage object."""
192
+ result = {}
193
+
194
+ # Determine role based on message type
195
+ if isinstance(msg, HumanMessage):
196
+ result["role"] = "user"
197
+ elif isinstance(msg, AIMessage):
198
+ result["role"] = "assistant"
199
+ elif isinstance(msg, SystemMessage):
200
+ result["role"] = "system"
201
+ elif isinstance(msg, ToolMessage):
202
+ result["role"] = "tool"
203
+ # Add tool_call_id if present
204
+ if hasattr(msg, 'tool_call_id'):
205
+ result["tool_call_id"] = msg.tool_call_id
206
+ elif isinstance(msg, FunctionMessage):
207
+ result["role"] = "function"
208
+ # Add name if present
209
+ if hasattr(msg, 'name'):
210
+ result["name"] = msg.name
211
+ else:
212
+ # Default to user role for unknown message types
213
+ result["role"] = "user"
214
+
215
+ # Extract content
216
+ result["content"] = msg.content or ""
217
+
218
+ # Handle tool calls for AI messages
219
+ if isinstance(msg, AIMessage):
220
+ if hasattr(msg, 'tool_calls') and msg.tool_calls:
221
+ result["tool_calls"] = msg.tool_calls
222
+ elif 'tool_calls' in msg.additional_kwargs:
223
+ result["tool_calls"] = msg.additional_kwargs['tool_calls']
224
+
225
+ if hasattr(msg, 'function_call') and msg.function_call:
226
+ result["function_call"] = msg.function_call
227
+ elif 'function_call' in msg.additional_kwargs:
228
+ result["function_call"] = msg.additional_kwargs['function_call']
229
+
230
+ return result
231
+
232
+
233
+ def _parse_dict_message(msg_dict: dict) -> dict:
234
+ """Parse a dictionary-based message."""
235
+ result = {}
236
+
237
+ # Extract role
238
+ #result["role"] = msg_dict.get("role", "user")
239
+ if "role" in msg_dict:
240
+ role = msg_dict["role"]
241
+ elif "type" in msg_dict:
242
+ role = msg_dict["type"]
243
+ else:
244
+ role = "user"
245
+
246
+ if role == 'ai':
247
+ role = 'assistant'
248
+ elif role == 'human':
249
+ role = 'user'
250
+
251
+ result["role"] = role
252
+
253
+ # Extract content
254
+ if "content" in msg_dict:
255
+ result["content"] = msg_dict["content"]
256
+ elif "text" in msg_dict:
257
+ result["content"] = msg_dict["text"]
258
+ else:
259
+ result["content"] = ""
260
+
261
+ # Copy over optional fields
262
+ optional_fields = ["tool_calls", "tool_call_id", "function_call", "name", "logprobs"]
263
+ for field in optional_fields:
264
+ if field in msg_dict:
265
+ result[field] = msg_dict[field]
266
+
267
+ return result
@@ -0,0 +1,218 @@
1
+ # SPDX-FileCopyrightText: Copyright (c) 2025-2026, NVIDIA CORPORATION & AFFILIATES.
2
+ # All rights reserved.
3
+ # SPDX-License-Identifier: Apache-2.0
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ from llama_index.core.llms import ChatResponse
18
+
19
+ from nat.data_models.intermediate_step import IntermediateStep
20
+ from nat.data_models.intermediate_step import IntermediateStepType
21
+ from nat.finetuning.utils.parsers.common import extract_content
22
+ from nat.finetuning.utils.parsers.common import parse_generic_message
23
+
24
+ # Re-export for backwards compatibility and internal use
25
+ _extract_content = extract_content
26
+ _parse_generic_message = parse_generic_message
27
+
28
+
29
+ def parse_to_openai_message(message: IntermediateStep) -> dict: # noqa: ARG001
30
+ """
31
+ Convert IntermediateStep to OpenAI-compatible message dictionary.
32
+
33
+ Args:
34
+ message: An IntermediateStep object representing a single message.
35
+ previous_message: Previous message for context (reserved for future).
36
+
37
+ Returns:
38
+ A dictionary formatted for OpenAI API consumption.
39
+ """
40
+ result = {}
41
+
42
+ # Handle different event types to determine role and extract content
43
+ if message.event_type == IntermediateStepType.LLM_END:
44
+ # Assistant message from ChatResponse
45
+ result = _parse_assistant_message(message)
46
+ elif message.event_type == IntermediateStepType.TOOL_END:
47
+ # Tool/Function response message
48
+ result = _parse_tool_message(message)
49
+ elif message.event_type == IntermediateStepType.LLM_START:
50
+ # Extract user/system messages from the input
51
+ result = _parse_input_message(message)
52
+ else:
53
+ # For other types, try to infer from the data
54
+ result = _parse_generic_message(message)
55
+
56
+ return result
57
+
58
+
59
+ def _parse_assistant_message(message: IntermediateStep) -> dict:
60
+ """Parse an assistant message from LLM_END event."""
61
+ result = {"role": "assistant"}
62
+
63
+ # Get the ChatResponse from payload if available
64
+ if message.data and message.data.payload:
65
+ payload = message.data.payload
66
+
67
+ # Handle ChatResponse objects from LlamaIndex
68
+ if isinstance(payload, ChatResponse):
69
+ # Extract content from message blocks
70
+ content = ""
71
+ msg = getattr(payload, 'message', None)
72
+ if msg and hasattr(msg, 'blocks'):
73
+ try:
74
+ content = ''.join(block.text for block in msg.blocks)
75
+ except (AttributeError, TypeError):
76
+ # Fallback to str representation
77
+ content = str(msg) if msg else ""
78
+ elif msg:
79
+ # Direct message content
80
+ content = str(msg)
81
+ result["content"] = content
82
+
83
+ # Check for tool calls in additional_kwargs
84
+ if (hasattr(payload, 'message') and hasattr(payload.message, 'additional_kwargs')):
85
+ additional_kwargs = payload.message.additional_kwargs
86
+ if 'tool_calls' in additional_kwargs:
87
+ result["tool_calls"] = additional_kwargs['tool_calls']
88
+ if 'function_call' in additional_kwargs:
89
+ func_call = additional_kwargs['function_call']
90
+ result["function_call"] = func_call
91
+
92
+ # Extract logprobs if available
93
+ raw_attr = getattr(payload, 'raw', None)
94
+ try:
95
+ choice = raw_attr.choices[0] if raw_attr and hasattr(raw_attr, 'choices') else None
96
+ if choice and hasattr(choice, 'logprobs') and choice.logprobs:
97
+ result["logprobs"] = choice.logprobs
98
+ except (AttributeError, IndexError):
99
+ pass
100
+
101
+ elif message.data and message.data.output:
102
+ # Fallback to output field
103
+ result["content"] = _extract_content(message.data.output)
104
+ else:
105
+ result["content"] = ""
106
+
107
+ # if not logprobs, set to empty dict to avoid issues downstream
108
+ if "logprobs" not in result:
109
+ result["logprobs"] = {}
110
+
111
+ return result
112
+
113
+
114
+ def _parse_tool_message(message: IntermediateStep) -> dict:
115
+ """Parse a tool/function response message from TOOL_END event."""
116
+ result = {"role": "function"}
117
+
118
+ # Extract function output as content
119
+ if message.data:
120
+ if message.data.output:
121
+ result["content"] = _extract_content(message.data.output)
122
+ elif message.data.payload:
123
+ result["content"] = _extract_content(message.data.payload)
124
+ else:
125
+ result["content"] = ""
126
+ else:
127
+ result["content"] = ""
128
+
129
+ # Add function name if available
130
+ if message.name:
131
+ result["name"] = message.name
132
+
133
+ return result
134
+
135
+
136
+ def _parse_input_message(message: IntermediateStep) -> dict:
137
+ """Parse user or system messages from LLM_START event."""
138
+ if not message.data or not message.data.input:
139
+ return {"role": "user", "content": ""}
140
+
141
+ input_data = message.data.input
142
+
143
+ # LlamaIndex typically stores messages as strings in the input
144
+ if isinstance(input_data, str):
145
+ # Check if it looks like a system message (heuristic)
146
+ lower_input = input_data.lower()
147
+ if (lower_input.startswith("system:") or "system prompt" in lower_input):
148
+ return {"role": "system", "content": input_data}
149
+ else:
150
+ return {"role": "user", "content": input_data}
151
+
152
+ # Handle list of messages (from EventPayload.MESSAGES)
153
+ elif isinstance(input_data, list) and len(input_data) > 0:
154
+ # Get the last message in the list
155
+ last_msg = input_data[-1]
156
+
157
+ # Try to parse the message
158
+ if hasattr(last_msg, 'role') and hasattr(last_msg, 'content'):
159
+ # LlamaIndex ChatMessage object
160
+ role = str(last_msg.role).lower()
161
+ # Map LlamaIndex roles to OpenAI roles
162
+ role_mapping = {
163
+ 'user': 'user',
164
+ 'assistant': 'assistant',
165
+ 'system': 'system',
166
+ 'human': 'user',
167
+ 'ai': 'assistant',
168
+ 'chatbot': 'assistant'
169
+ }
170
+ role = role_mapping.get(role, 'user')
171
+ return {"role": role, "content": str(last_msg.content)}
172
+ else:
173
+ # Convert to string if not a message object
174
+ return {"role": "user", "content": str(last_msg)}
175
+
176
+ # Handle dict messages
177
+ elif isinstance(input_data, dict):
178
+ return _parse_dict_message(input_data)
179
+
180
+ else:
181
+ return {"role": "user", "content": _extract_content(input_data)}
182
+
183
+
184
+ def _parse_dict_message(msg_dict: dict) -> dict:
185
+ """Parse a dictionary-based message."""
186
+ result = {}
187
+
188
+ # Extract role
189
+ result["role"] = msg_dict.get("role", "user")
190
+
191
+ # Extract content
192
+ if "content" in msg_dict:
193
+ result["content"] = msg_dict["content"]
194
+ elif "text" in msg_dict:
195
+ result["content"] = msg_dict["text"]
196
+ elif "blocks" in msg_dict:
197
+ # Handle LlamaIndex block format
198
+ blocks = msg_dict["blocks"]
199
+ if isinstance(blocks, list):
200
+ content_parts = []
201
+ for block in blocks:
202
+ if isinstance(block, dict) and "text" in block:
203
+ content_parts.append(block["text"])
204
+ elif hasattr(block, 'text'):
205
+ content_parts.append(block.text)
206
+ result["content"] = ''.join(content_parts)
207
+ else:
208
+ result["content"] = ""
209
+ else:
210
+ result["content"] = ""
211
+
212
+ # Copy over optional fields
213
+ optional_fields = ["tool_calls", "function_call", "name", "logprobs"]
214
+ for field in optional_fields:
215
+ if field in msg_dict:
216
+ result[field] = msg_dict[field]
217
+
218
+ return result
@@ -1,4 +1,4 @@
1
- # SPDX-FileCopyrightText: Copyright (c) 2024-2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
1
+ # SPDX-FileCopyrightText: Copyright (c) 2024-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2
2
  # SPDX-License-Identifier: Apache-2.0
3
3
  #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -1,4 +1,4 @@
1
- # SPDX-FileCopyrightText: Copyright (c) 2024-2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
1
+ # SPDX-FileCopyrightText: Copyright (c) 2024-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2
2
  # SPDX-License-Identifier: Apache-2.0
3
3
  #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -1,4 +1,4 @@
1
- # SPDX-FileCopyrightText: Copyright (c) 2024-2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
1
+ # SPDX-FileCopyrightText: Copyright (c) 2024-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2
2
  # SPDX-License-Identifier: Apache-2.0
3
3
  #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -1,4 +1,4 @@
1
- # SPDX-FileCopyrightText: Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
1
+ # SPDX-FileCopyrightText: Copyright (c) 2025-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2
2
  # SPDX-License-Identifier: Apache-2.0
3
3
  #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -30,3 +30,6 @@ class ConsoleFrontEndConfig(FrontEndBaseConfig, name="console"):
30
30
  description="A single input to submit the the workflow.")
31
31
  input_file: Path | None = Field(default=None,
32
32
  description="Path to a json file of inputs to submit to the workflow.")
33
+ user_id: str = Field(default="nat_run_user_id",
34
+ description="User ID to use for the workflow session. "
35
+ "Defaults to 'nat_run_user_id' for single-user CLI execution.")
@@ -1,4 +1,4 @@
1
- # SPDX-FileCopyrightText: Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
1
+ # SPDX-FileCopyrightText: Copyright (c) 2025-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2
2
  # SPDX-License-Identifier: Apache-2.0
3
3
  #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -70,6 +70,7 @@ class ConsoleFrontEndPlugin(SimpleFrontEndPluginBase[ConsoleFrontEndConfig]):
70
70
  async def run_single_query(query):
71
71
 
72
72
  async with session_manager.session(
73
+ user_id=self.front_end_config.user_id,
73
74
  user_input_callback=prompt_for_input_cli,
74
75
  user_authentication_callback=self.auth_flow_handler.authenticate) as session:
75
76
  async with session.run(query) as runner:
@@ -89,9 +90,9 @@ class ConsoleFrontEndPlugin(SimpleFrontEndPluginBase[ConsoleFrontEndConfig]):
89
90
 
90
91
  # Run the workflow
91
92
  with open(self.front_end_config.input_file, encoding="utf-8") as f:
92
-
93
- async with session_manager.workflow.run(f) as runner:
94
- runner_outputs = await runner.result(to_type=str)
93
+ async with session_manager.session(user_id=self.front_end_config.user_id) as session:
94
+ async with session.run(f) as runner:
95
+ runner_outputs = await runner.result(to_type=str)
95
96
  else:
96
97
  assert False, "Should not reach here. Should have been caught by pre_run"
97
98
 
@@ -1,4 +1,4 @@
1
- # SPDX-FileCopyrightText: Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
1
+ # SPDX-FileCopyrightText: Copyright (c) 2025-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2
2
  # SPDX-License-Identifier: Apache-2.0
3
3
  #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -1,4 +1,4 @@
1
- # SPDX-FileCopyrightText: Copyright (c) 2024-2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
1
+ # SPDX-FileCopyrightText: Copyright (c) 2024-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2
2
  # SPDX-License-Identifier: Apache-2.0
3
3
  #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -1,4 +1,4 @@
1
- # SPDX-FileCopyrightText: Copyright (c) 2024-2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
1
+ # SPDX-FileCopyrightText: Copyright (c) 2024-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2
2
  # SPDX-License-Identifier: Apache-2.0
3
3
  #
4
4
  # Licensed under the Apache License, Version 2.0 (the "License");