nvidia-nat 1.3.0a20250925__py3-none-any.whl → 1.3.0a20250928__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.
@@ -152,11 +152,8 @@ async def react_agent_workflow(config: ReActAgentWorkflowConfig, builder: Builde
152
152
  return ChatResponse.from_string(str(output_message.content))
153
153
 
154
154
  except Exception as ex:
155
- logger.exception("%s ReAct Agent failed with exception: %s", AGENT_LOG_PREFIX, ex)
156
- # here, we can implement custom error messages
157
- if config.verbose:
158
- return ChatResponse.from_string(str(ex))
159
- return ChatResponse.from_string("I seem to be having a problem.")
155
+ logger.exception("%s ReAct Agent failed with exception: %s", AGENT_LOG_PREFIX, str(ex))
156
+ raise RuntimeError
160
157
 
161
158
  if (config.use_openai_api):
162
159
  yield FunctionInfo.from_fn(_response_fn, description=config.description)
@@ -158,10 +158,7 @@ async def rewoo_agent_workflow(config: ReWOOAgentWorkflowConfig, builder: Builde
158
158
 
159
159
  except Exception as ex:
160
160
  logger.exception("ReWOO Agent failed with exception: %s", ex)
161
- # here, we can implement custom error messages
162
- if config.verbose:
163
- return ChatResponse.from_string(str(ex))
164
- return ChatResponse.from_string("I seem to be having a problem.")
161
+ raise RuntimeError
165
162
 
166
163
  if (config.use_openai_api):
167
164
  yield FunctionInfo.from_fn(_response_fn, description=config.description)
@@ -115,9 +115,7 @@ async def tool_calling_agent_workflow(config: ToolCallAgentWorkflowConfig, build
115
115
  return str(output_message.content)
116
116
  except Exception as ex:
117
117
  logger.exception("%s Tool Calling Agent failed with exception: %s", AGENT_LOG_PREFIX, ex)
118
- if config.verbose:
119
- return str(ex)
120
- return "I seem to be having a problem."
118
+ raise RuntimeError
121
119
 
122
120
  try:
123
121
  yield FunctionInfo.from_fn(_response_fn, description=config.description)
@@ -80,7 +80,7 @@ class APIKeyAuthProvider(AuthProviderBase[APIKeyAuthProviderConfig]):
80
80
 
81
81
  raise ValueError(f"Unsupported header auth scheme: {header_auth_scheme}")
82
82
 
83
- async def authenticate(self, user_id: str | None = None) -> AuthResult | None:
83
+ async def authenticate(self, user_id: str | None = None, **kwargs) -> AuthResult | None:
84
84
  """
85
85
  Authenticate the user using the API key credentials.
86
86
 
@@ -38,7 +38,7 @@ class HTTPBasicAuthProvider(AuthProviderBase):
38
38
 
39
39
  self._authenticated_tokens: dict[str, AuthResult] = {}
40
40
 
41
- async def authenticate(self, user_id: str | None = None) -> AuthResult:
41
+ async def authenticate(self, user_id: str | None = None, **kwargs) -> AuthResult:
42
42
  """
43
43
  Performs simple HTTP Authentication using the provided user ID.
44
44
  """
@@ -54,7 +54,7 @@ class AuthProviderBase(typing.Generic[AuthProviderBaseConfigT], ABC):
54
54
  return self._config
55
55
 
56
56
  @abstractmethod
57
- async def authenticate(self, user_id: str | None = None) -> AuthResult:
57
+ async def authenticate(self, user_id: str | None = None, **kwargs) -> AuthResult:
58
58
  """
59
59
  Perform the authentication process for the client.
60
60
 
@@ -62,6 +62,9 @@ class AuthProviderBase(typing.Generic[AuthProviderBaseConfigT], ABC):
62
62
  target API service, which may include obtaining tokens, refreshing credentials,
63
63
  or completing multi-step authentication flows.
64
64
 
65
+ Args:
66
+ user_id: Optional user identifier for authentication
67
+ kwargs: Additional authentication parameters for example: http response (typically from a 401)
65
68
  Raises:
66
69
  NotImplementedError: Must be implemented by subclasses.
67
70
  """
@@ -71,7 +74,7 @@ class AuthProviderBase(typing.Generic[AuthProviderBaseConfigT], ABC):
71
74
 
72
75
  class FlowHandlerBase(ABC):
73
76
  """
74
- Handles front-end specifc flows for authentication clients.
77
+ Handles front-end specific flows for authentication clients.
75
78
 
76
79
  Each front end will define a FlowHandler that will implement the authenticate method.
77
80
 
@@ -15,6 +15,7 @@
15
15
 
16
16
  from datetime import datetime
17
17
  from datetime import timezone
18
+ from typing import Callable
18
19
 
19
20
  from authlib.integrations.httpx_client import OAuth2Client as AuthlibOAuth2Client
20
21
  from pydantic import SecretStr
@@ -22,6 +23,7 @@ from pydantic import SecretStr
22
23
  from nat.authentication.interfaces import AuthProviderBase
23
24
  from nat.authentication.oauth2.oauth2_auth_code_flow_provider_config import OAuth2AuthCodeFlowProviderConfig
24
25
  from nat.builder.context import Context
26
+ from nat.data_models.authentication import AuthenticatedContext
25
27
  from nat.data_models.authentication import AuthFlowType
26
28
  from nat.data_models.authentication import AuthResult
27
29
  from nat.data_models.authentication import BearerTokenCred
@@ -32,7 +34,7 @@ class OAuth2AuthCodeFlowProvider(AuthProviderBase[OAuth2AuthCodeFlowProviderConf
32
34
  def __init__(self, config: OAuth2AuthCodeFlowProviderConfig):
33
35
  super().__init__(config)
34
36
  self._authenticated_tokens: dict[str, AuthResult] = {}
35
- self._context = Context.get()
37
+ self._auth_callback = None
36
38
 
37
39
  async def _attempt_token_refresh(self, user_id: str, auth_result: AuthResult) -> AuthResult | None:
38
40
  refresh_token = auth_result.raw.get("refresh_token")
@@ -62,7 +64,12 @@ class OAuth2AuthCodeFlowProvider(AuthProviderBase[OAuth2AuthCodeFlowProviderConf
62
64
 
63
65
  return new_auth_result
64
66
 
65
- async def authenticate(self, user_id: str | None = None) -> AuthResult:
67
+ def _set_custom_auth_callback(self,
68
+ auth_callback: Callable[[OAuth2AuthCodeFlowProviderConfig, AuthFlowType],
69
+ AuthenticatedContext]):
70
+ self._auth_callback = auth_callback
71
+
72
+ async def authenticate(self, user_id: str | None = None, **kwargs) -> AuthResult:
66
73
  if user_id is None and hasattr(Context.get(), "metadata") and hasattr(
67
74
  Context.get().metadata, "cookies") and Context.get().metadata.cookies is not None:
68
75
  session_id = Context.get().metadata.cookies.get("nat-session", None)
@@ -80,7 +87,12 @@ class OAuth2AuthCodeFlowProvider(AuthProviderBase[OAuth2AuthCodeFlowProviderConf
80
87
  if refreshed_auth_result:
81
88
  return refreshed_auth_result
82
89
 
83
- auth_callback = self._context.user_auth_callback
90
+ # Try getting callback from the context if that's not set, use the default callback
91
+ try:
92
+ auth_callback = Context.get().user_auth_callback
93
+ except RuntimeError:
94
+ auth_callback = self._auth_callback
95
+
84
96
  if not auth_callback:
85
97
  raise RuntimeError("Authentication callback not set on Context.")
86
98
 
nat/builder/function.py CHANGED
@@ -159,7 +159,8 @@ class Function(FunctionBase[InputT, StreamingOutputT, SingleOutputT], ABC):
159
159
 
160
160
  return result
161
161
  except Exception as e:
162
- logger.error("Error with ainvoke in function with input: %s. Error: %s", value, e)
162
+ err_msg = f"Error: {e}" if str(e).strip() else ""
163
+ logger.error("Error with ainvoke in function with input: %s. %s", value, err_msg)
163
164
  raise
164
165
 
165
166
  @typing.final
@@ -157,6 +157,66 @@ def print_tool(tool_dict: dict[str, str | None], detail: bool = False) -> None:
157
157
  click.echo("-" * 60)
158
158
 
159
159
 
160
+ def _set_auth_defaults(auth: bool,
161
+ url: str | None,
162
+ auth_redirect_uri: str | None,
163
+ auth_user_id: str | None,
164
+ auth_scopes: str | None) -> tuple[str | None, str | None, list[str] | None]:
165
+ """Set default auth values when --auth flag is used.
166
+
167
+ Args:
168
+ auth: Whether --auth flag was used
169
+ url: MCP server URL
170
+ auth_redirect_uri: OAuth2 redirect URI
171
+ auth_user_id: User ID for authentication
172
+ auth_scopes: OAuth2 scopes (comma-separated string)
173
+
174
+ Returns:
175
+ Tuple of (auth_redirect_uri, auth_user_id, auth_scopes_list) with defaults applied
176
+ """
177
+ if auth:
178
+ auth_redirect_uri = auth_redirect_uri or "http://localhost:8000/auth/redirect"
179
+ auth_user_id = auth_user_id or url
180
+ auth_scopes = auth_scopes or ""
181
+
182
+ # Convert comma-separated string to list, stripping whitespace
183
+ auth_scopes_list = [scope.strip() for scope in auth_scopes.split(',')] if auth_scopes else None
184
+
185
+ return auth_redirect_uri, auth_user_id, auth_scopes_list
186
+
187
+
188
+ async def _create_mcp_client_config(
189
+ builder,
190
+ server_cfg,
191
+ url: str | None,
192
+ transport: str,
193
+ auth_redirect_uri: str | None,
194
+ auth_user_id: str | None,
195
+ auth_scopes: list[str] | None,
196
+ ):
197
+ from nat.plugins.mcp.client_impl import MCPClientConfig
198
+
199
+ if url and transport == "streamable-http" and auth_redirect_uri:
200
+ try:
201
+ from nat.plugins.mcp.auth.auth_provider_config import MCPOAuth2ProviderConfig
202
+ auth_config = MCPOAuth2ProviderConfig(
203
+ server_url=url,
204
+ redirect_uri=auth_redirect_uri,
205
+ default_user_id=auth_user_id or url,
206
+ scopes=auth_scopes or [],
207
+ )
208
+ auth_provider_name = "mcp_oauth2_cli"
209
+ await builder.add_auth_provider(auth_provider_name, auth_config)
210
+ server_cfg.auth_provider = auth_provider_name
211
+ except ImportError:
212
+ click.echo(
213
+ "[WARNING] MCP OAuth2 authentication requires nvidia-nat-mcp package.",
214
+ err=True,
215
+ )
216
+
217
+ return MCPClientConfig(server=server_cfg)
218
+
219
+
160
220
  async def list_tools_via_function_group(
161
221
  command: str | None,
162
222
  url: str | None,
@@ -164,6 +224,9 @@ async def list_tools_via_function_group(
164
224
  transport: str = 'sse',
165
225
  args: list[str] | None = None,
166
226
  env: dict[str, str] | None = None,
227
+ auth_redirect_uri: str | None = None,
228
+ auth_user_id: str | None = None,
229
+ auth_scopes: list[str] | None = None,
167
230
  ) -> list[dict[str, str | None]]:
168
231
  """List tools by constructing the mcp_client function group and introspecting functions.
169
232
 
@@ -192,15 +255,24 @@ async def list_tools_via_function_group(
192
255
  args=args if transport == 'stdio' else None,
193
256
  env=env if transport == 'stdio' else None,
194
257
  )
258
+
195
259
  group_cfg = MCPClientConfig(server=server_cfg)
196
260
 
197
261
  tools: list[dict[str, str | None]] = []
198
262
 
199
263
  async with WorkflowBuilder() as builder: # type: ignore
264
+ # Add auth provider if url is provided and auth_redirect_uri is given (only for streamable-http)
265
+ group_cfg = await _create_mcp_client_config(builder,
266
+ server_cfg,
267
+ url,
268
+ transport,
269
+ auth_redirect_uri,
270
+ auth_user_id,
271
+ auth_scopes)
200
272
  group = await builder.add_function_group("mcp_client", group_cfg)
201
273
 
202
274
  # Access functions exposed by the group
203
- fns = group.get_accessible_functions()
275
+ fns = await group.get_accessible_functions()
204
276
 
205
277
  def to_tool_entry(full_name: str, fn_obj) -> dict[str, str | None]:
206
278
  # full_name like "mcp_client.<tool>"
@@ -324,7 +396,10 @@ async def ping_mcp_server(url: str,
324
396
  transport: str = 'streamable-http',
325
397
  command: str | None = None,
326
398
  args: list[str] | None = None,
327
- env: dict[str, str] | None = None) -> MCPPingResult:
399
+ env: dict[str, str] | None = None,
400
+ auth_redirect_uri: str | None = None,
401
+ auth_user_id: str | None = None,
402
+ auth_scopes: list[str] | None = None) -> MCPPingResult:
328
403
  """Ping an MCP server to check if it's responsive.
329
404
 
330
405
  Args:
@@ -383,7 +458,13 @@ def mcp_client_command():
383
458
  """
384
459
  MCP client commands.
385
460
  """
386
- return None
461
+ try:
462
+ from nat.runtime.loader import PluginTypes
463
+ from nat.runtime.loader import discover_and_register_plugins
464
+ discover_and_register_plugins(PluginTypes.CONFIG_OBJECT)
465
+ except ImportError:
466
+ click.echo("[WARNING] MCP client functionality requires nvidia-nat-mcp package.", err=True)
467
+ pass
387
468
 
388
469
 
389
470
  @mcp_client_command.group(name="tool", invoke_without_command=False, help="Inspect and call MCP tools.")
@@ -412,14 +493,36 @@ def mcp_client_tool_group():
412
493
  @click.option('--tool', default=None, help='Get details for a specific tool by name')
413
494
  @click.option('--detail', is_flag=True, help='Show full details for all tools')
414
495
  @click.option('--json-output', is_flag=True, help='Output tool metadata in JSON format')
496
+ @click.option('--auth',
497
+ is_flag=True,
498
+ help='Enable OAuth2 authentication with default settings (streamable-http only, not with --direct)')
499
+ @click.option('--auth-redirect-uri',
500
+ help='OAuth2 redirect URI for authentication (streamable-http only, not with --direct)')
501
+ @click.option('--auth-user-id', help='User ID for authentication (streamable-http only, not with --direct)')
502
+ @click.option('--auth-scopes', help='OAuth2 scopes (comma-separated, streamable-http only, not with --direct)')
415
503
  @click.pass_context
416
- def mcp_client_tool_list(ctx, direct, url, transport, command, args, env, tool, detail, json_output):
504
+ def mcp_client_tool_list(ctx,
505
+ direct,
506
+ url,
507
+ transport,
508
+ command,
509
+ args,
510
+ env,
511
+ tool,
512
+ detail,
513
+ json_output,
514
+ auth,
515
+ auth_redirect_uri,
516
+ auth_user_id,
517
+ auth_scopes):
417
518
  """List MCP tool names (default) or show detailed tool information.
418
519
 
419
520
  Use --detail for full output including descriptions and input schemas.
420
521
  If --tool is provided, always shows full output for that specific tool.
421
522
  Use --direct to bypass MCPBuilder and use raw MCP protocol.
422
523
  Use --json-output to get structured JSON data instead of formatted text.
524
+ Use --auth to enable auth with default settings (streamable-http only, not with --direct).
525
+ Use --auth-redirect-uri to enable auth for protected MCP servers (streamable-http only, not with --direct).
423
526
 
424
527
  Args:
425
528
  ctx (click.Context): Click context object for command invocation
@@ -428,13 +531,22 @@ def mcp_client_tool_list(ctx, direct, url, transport, command, args, env, tool,
428
531
  tool (str | None): Optional specific tool name to retrieve detailed info for
429
532
  detail (bool): Whether to show full details (description + schema) for all tools
430
533
  json_output (bool): Whether to output tool metadata in JSON format instead of text
534
+ auth (bool): Whether to enable OAuth2 authentication (streamable-http only, not with --direct)
535
+ auth_redirect_uri (str | None): redirect URI for auth (streamable-http only, not with --direct)
536
+ auth_user_id (str | None): User ID for authentication (streamable-http only, not with --direct)
537
+ auth_scopes (str | None): OAuth2 scopes (comma-separated, streamable-http only, not with --direct)
431
538
 
432
539
  Examples:
433
540
  nat mcp client tool list # List tool names only
434
541
  nat mcp client tool list --detail # Show all tools with full details
435
542
  nat mcp client tool list --tool my_tool # Show details for specific tool
436
543
  nat mcp client tool list --json-output # Get JSON format output
437
- nat mcp client tool list --direct --url http://... # Use direct protocol with custom URL
544
+ nat mcp client tool list --direct --url http://... # Use direct protocol with custom URL (no auth)
545
+ nat mcp client tool list --url https://example.com/mcp/ --auth # With auth using defaults
546
+ nat mcp client tool list --url https://example.com/mcp/ --transport streamable-http \
547
+ --auth-redirect-uri http://localhost:8000/auth/redirect # With custom auth settings
548
+ nat mcp client tool list --url https://example.com/mcp/ --transport streamable-http \
549
+ --auth-redirect-uri http://localhost:8000/auth/redirect --auth-user-id myuser # With auth and user ID
438
550
  """
439
551
  if ctx.invoked_subcommand is not None:
440
552
  return
@@ -447,11 +559,28 @@ def mcp_client_tool_list(ctx, direct, url, transport, command, args, env, tool,
447
559
  click.echo("[ERROR] --url is required when using sse or streamable-http client type", err=True)
448
560
  return
449
561
 
562
+ # Set auth defaults if --auth flag is used
563
+ auth_redirect_uri, auth_user_id, auth_scopes_list = _set_auth_defaults(
564
+ auth, url, auth_redirect_uri, auth_user_id, auth_scopes
565
+ )
566
+
450
567
  stdio_args = args.split() if args else []
451
568
  stdio_env = dict(var.split('=', 1) for var in env.split()) if env else None
452
569
 
453
- fetcher = list_tools_direct if direct else list_tools_via_function_group
454
- tools = asyncio.run(fetcher(command, url, tool, transport, stdio_args, stdio_env))
570
+ if direct:
571
+ tools = asyncio.run(
572
+ list_tools_direct(command, url, tool_name=tool, transport=transport, args=stdio_args, env=stdio_env))
573
+ else:
574
+ tools = asyncio.run(
575
+ list_tools_via_function_group(command,
576
+ url,
577
+ tool_name=tool,
578
+ transport=transport,
579
+ args=stdio_args,
580
+ env=stdio_env,
581
+ auth_redirect_uri=auth_redirect_uri,
582
+ auth_user_id=auth_user_id,
583
+ auth_scopes=auth_scopes_list))
455
584
 
456
585
  if json_output:
457
586
  click.echo(json.dumps(tools, indent=2))
@@ -482,13 +611,20 @@ def mcp_client_tool_list(ctx, direct, url, transport, command, args, env, tool,
482
611
  @click.option('--env', help='For stdio: Environment variables in KEY=VALUE format (space-separated)')
483
612
  @click.option('--timeout', default=60, show_default=True, help='Timeout in seconds for ping request')
484
613
  @click.option('--json-output', is_flag=True, help='Output ping result in JSON format')
614
+ @click.option('--auth-redirect-uri',
615
+ help='OAuth2 redirect URI for authentication (streamable-http only, not with --direct)')
616
+ @click.option('--auth-user-id', help='User ID for authentication (streamable-http only, not with --direct)')
617
+ @click.option('--auth-scopes', help='OAuth2 scopes (comma-separated, streamable-http only, not with --direct)')
485
618
  def mcp_client_ping(url: str,
486
619
  transport: str,
487
620
  command: str | None,
488
621
  args: str | None,
489
622
  env: str | None,
490
623
  timeout: int,
491
- json_output: bool) -> None:
624
+ json_output: bool,
625
+ auth_redirect_uri: str | None,
626
+ auth_user_id: str | None,
627
+ auth_scopes: str | None) -> None:
492
628
  """Ping an MCP server to check if it's responsive.
493
629
 
494
630
  This command sends a ping request to the MCP server and measures the response time.
@@ -498,12 +634,16 @@ def mcp_client_ping(url: str,
498
634
  url (str): MCP server URL to ping (default: http://localhost:9901/mcp)
499
635
  timeout (int): Timeout in seconds for the ping request (default: 60)
500
636
  json_output (bool): Whether to output the result in JSON format
637
+ auth_redirect_uri (str | None): redirect URI for auth (streamable-http only, not with --direct)
638
+ auth_user_id (str | None): User ID for auth (streamable-http only, not with --direct)
639
+ auth_scopes (str | None): OAuth2 scopes (comma-separated, streamable-http only, not with --direct)
501
640
 
502
641
  Examples:
503
642
  nat mcp client ping # Ping default server
504
643
  nat mcp client ping --url http://custom-server:9901/mcp # Ping custom server
505
644
  nat mcp client ping --timeout 10 # Use 10 second timeout
506
645
  nat mcp client ping --json-output # Get JSON format output
646
+ nat mcp client ping --url https://example.com/mcp/ --transport streamable-http --auth # With auth
507
647
  """
508
648
  # Validate combinations similar to list command
509
649
  if not validate_transport_cli_args(transport, command, args, env):
@@ -512,7 +652,24 @@ def mcp_client_ping(url: str,
512
652
  stdio_args = args.split() if args else []
513
653
  stdio_env = dict(var.split('=', 1) for var in env.split()) if env else None
514
654
 
515
- result = asyncio.run(ping_mcp_server(url, timeout, transport, command, stdio_args, stdio_env))
655
+ # Auth validation: if user_id or scopes provided, require redirect_uri
656
+ if (auth_user_id or auth_scopes) and not auth_redirect_uri:
657
+ click.echo("[ERROR] --auth-redirect-uri is required when using --auth-user-id or --auth-scopes", err=True)
658
+ return
659
+
660
+ # Parse auth scopes, stripping whitespace
661
+ auth_scopes_list = [scope.strip() for scope in auth_scopes.split(',')] if auth_scopes else None
662
+
663
+ result = asyncio.run(
664
+ ping_mcp_server(url,
665
+ timeout,
666
+ transport,
667
+ command,
668
+ stdio_args,
669
+ stdio_env,
670
+ auth_redirect_uri,
671
+ auth_user_id,
672
+ auth_scopes_list))
516
673
 
517
674
  if json_output:
518
675
  click.echo(result.model_dump_json(indent=2))
@@ -635,7 +792,10 @@ async def call_tool_and_print(command: str | None,
635
792
  args: list[str] | None,
636
793
  env: dict[str, str] | None,
637
794
  tool_args: dict[str, Any] | None,
638
- direct: bool) -> str:
795
+ direct: bool,
796
+ auth_redirect_uri: str | None = None,
797
+ auth_user_id: str | None = None,
798
+ auth_scopes: list[str] | None = None) -> str:
639
799
  """Call an MCP tool either directly or via the function group and return output.
640
800
 
641
801
  When ``direct`` is True, uses the raw MCP protocol client (bypassing the
@@ -681,11 +841,25 @@ async def call_tool_and_print(command: str | None,
681
841
  args=args if transport == 'stdio' else None,
682
842
  env=env if transport == 'stdio' else None,
683
843
  )
844
+
684
845
  group_cfg = MCPClientConfig(server=server_cfg)
685
846
 
686
847
  async with WorkflowBuilder() as builder: # type: ignore
848
+ # Add auth provider if url is provided and auth_redirect_uri is given (only for streamable-http)
849
+ if url and transport == 'streamable-http' and auth_redirect_uri:
850
+ try:
851
+ group_cfg = await _create_mcp_client_config(builder,
852
+ server_cfg,
853
+ url,
854
+ transport,
855
+ auth_redirect_uri,
856
+ auth_user_id,
857
+ auth_scopes)
858
+ except ImportError:
859
+ click.echo("[WARNING] MCP OAuth2 authentication requires nvidia-nat-mcp package.", err=True)
860
+
687
861
  group = await builder.add_function_group("mcp_client", group_cfg)
688
- fns = group.get_accessible_functions()
862
+ fns = await group.get_accessible_functions()
689
863
  full = f"mcp_client.{tool_name}"
690
864
  fn = fns.get(full)
691
865
  if fn is None:
@@ -713,6 +887,13 @@ async def call_tool_and_print(command: str | None,
713
887
  @click.option('--args', help='For stdio: Additional arguments for the command (space-separated)')
714
888
  @click.option('--env', help='For stdio: Environment variables in KEY=VALUE format (space-separated)')
715
889
  @click.option('--json-args', default=None, help='Pass tool args as a JSON object string')
890
+ @click.option('--auth',
891
+ is_flag=True,
892
+ help='Enable OAuth2 authentication with default settings (streamable-http only, not with --direct)')
893
+ @click.option('--auth-redirect-uri',
894
+ help='OAuth2 redirect URI for authentication (streamable-http only, not with --direct)')
895
+ @click.option('--auth-user-id', help='User ID for authentication (streamable-http only, not with --direct)')
896
+ @click.option('--auth-scopes', help='OAuth2 scopes (comma-separated, streamable-http only, not with --direct)')
716
897
  def mcp_client_tool_call(tool_name: str,
717
898
  direct: bool,
718
899
  url: str | None,
@@ -720,7 +901,11 @@ def mcp_client_tool_call(tool_name: str,
720
901
  command: str | None,
721
902
  args: str | None,
722
903
  env: str | None,
723
- json_args: str | None) -> None:
904
+ json_args: str | None,
905
+ auth: bool,
906
+ auth_redirect_uri: str | None,
907
+ auth_user_id: str | None,
908
+ auth_scopes: str | None) -> None:
724
909
  """Call an MCP tool by name with optional JSON arguments.
725
910
 
726
911
  Validates transport parameters, parses ``--json-args`` into a dictionary,
@@ -737,13 +922,20 @@ def mcp_client_tool_call(tool_name: str,
737
922
  args (str | None): For ``stdio`` transport, space-separated command arguments.
738
923
  env (str | None): For ``stdio`` transport, space-separated ``KEY=VALUE`` pairs.
739
924
  json_args (str | None): JSON object string with tool arguments (e.g. '{"q": "hello"}').
925
+ auth_redirect_uri (str | None): redirect URI for auth (streamable-http only, not with --direct)
926
+ auth_user_id (str | None): User ID for authentication (streamable-http only, not with --direct)
927
+ auth_scopes (str | None): OAuth2 scopes (comma-separated, streamable-http only, not with --direct)
740
928
 
741
929
  Examples:
742
930
  nat mcp client tool call echo --json-args '{"text": "Hello"}'
743
931
  nat mcp client tool call search --direct --url http://localhost:9901/mcp \
744
- --json-args '{"query": "NVIDIA"}'
932
+ --json-args '{"query": "NVIDIA"}' # Direct mode (no auth)
745
933
  nat mcp client tool call run --transport stdio --command mcp-server \
746
934
  --args "--flag1 --flag2" --env "ENV1=V1 ENV2=V2" --json-args '{}'
935
+ nat mcp client tool call search --url https://example.com/mcp/ --auth \
936
+ --json-args '{"query": "test"}' # With auth using defaults
937
+ nat mcp client tool call search --url https://example.com/mcp/ \
938
+ --transport streamable-http --json-args '{"query": "test"}' --auth
747
939
  """
748
940
  # Validate transport args
749
941
  if not validate_transport_cli_args(transport, command, args, env):
@@ -753,6 +945,11 @@ def mcp_client_tool_call(tool_name: str,
753
945
  stdio_args = args.split() if args else []
754
946
  stdio_env = dict(var.split('=', 1) for var in env.split()) if env else None
755
947
 
948
+ # Set auth defaults if --auth flag is used
949
+ auth_redirect_uri, auth_user_id, auth_scopes_list = _set_auth_defaults(
950
+ auth, url, auth_redirect_uri, auth_user_id, auth_scopes
951
+ )
952
+
756
953
  # Parse tool args
757
954
  arg_obj: dict[str, Any] = {}
758
955
  if json_args:
@@ -777,6 +974,9 @@ def mcp_client_tool_call(tool_name: str,
777
974
  env=stdio_env,
778
975
  tool_args=arg_obj,
779
976
  direct=direct,
977
+ auth_redirect_uri=auth_redirect_uri,
978
+ auth_user_id=auth_user_id,
979
+ auth_scopes=auth_scopes_list,
780
980
  ))
781
981
  if output:
782
982
  click.echo(output)
@@ -249,21 +249,3 @@ class AuthResult(BaseModel):
249
249
  target_kwargs.setdefault(k, {}).update(v)
250
250
  else:
251
251
  target_kwargs[k] = v
252
-
253
-
254
- class AuthReason(str, Enum):
255
- """
256
- Why the caller is asking for auth now.
257
- """
258
- NORMAL = "normal"
259
- RETRY_AFTER_401 = "retry_after_401"
260
-
261
-
262
- class AuthRequest(BaseModel):
263
- """
264
- Authentication request payload for provider.authenticate(...).
265
- """
266
- model_config = ConfigDict(extra="forbid")
267
-
268
- reason: AuthReason = Field(default=AuthReason.NORMAL, description="Purpose of this auth attempt.")
269
- www_authenticate: str | None = Field(default=None, description="Raw WWW-Authenticate header from a 401 response.")
@@ -81,7 +81,9 @@ class ConsoleFrontEndPlugin(SimpleFrontEndPluginBase[ConsoleFrontEndConfig]):
81
81
  input_list = list(self.front_end_config.input_query)
82
82
  logger.debug("Processing input: %s", self.front_end_config.input_query)
83
83
 
84
- runner_outputs = await asyncio.gather(*[run_single_query(query) for query in input_list])
84
+ # Make `return_exceptions=False` explicit; all exceptions are raised instead of being silenced
85
+ runner_outputs = await asyncio.gather(*[run_single_query(query) for query in input_list],
86
+ return_exceptions=False)
85
87
 
86
88
  elif (self.front_end_config.input_file):
87
89
 
nat/llm/litellm_llm.py CHANGED
@@ -1,4 +1,4 @@
1
- # SPDX-FileCopyrightText: Copyright (c) 2024-2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
1
+ # SPDX-FileCopyrightText: Copyright (c) 2025, 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");
nat/llm/register.py CHANGED
@@ -22,6 +22,6 @@ This module is imported by the NeMo Agent Toolkit runtime to ensure providers ar
22
22
  # Import any providers which need to be automatically registered here
23
23
  from . import aws_bedrock_llm
24
24
  from . import azure_openai_llm
25
+ from . import litellm_llm
25
26
  from . import nim_llm
26
27
  from . import openai_llm
27
- from . import litellm_llm
nat/runtime/runner.py CHANGED
@@ -149,7 +149,8 @@ class Runner:
149
149
 
150
150
  return result
151
151
  except Exception as e:
152
- logger.error("Error running workflow: %s", e)
152
+ err_msg = f": {e}" if str(e).strip() else "."
153
+ logger.error("Error running workflow%s", err_msg)
153
154
  event_stream = self._context_state.event_stream.get()
154
155
  if event_stream:
155
156
  event_stream.on_complete()
nat/runtime/session.py CHANGED
@@ -111,7 +111,7 @@ class SessionManager:
111
111
  token_user_authentication = self._context_state.user_auth_callback.set(user_authentication_callback)
112
112
 
113
113
  if isinstance(http_connection, WebSocket):
114
- self.set_metadata_from_websocket(user_message_id, conversation_id)
114
+ self.set_metadata_from_websocket(http_connection, user_message_id, conversation_id)
115
115
 
116
116
  if isinstance(http_connection, Request):
117
117
  self.set_metadata_from_http_request(http_connection)
@@ -161,11 +161,31 @@ class SessionManager:
161
161
  if request.headers.get("user-message-id"):
162
162
  self._context_state.user_message_id.set(request.headers["user-message-id"])
163
163
 
164
- def set_metadata_from_websocket(self, user_message_id: str | None, conversation_id: str | None) -> None:
164
+ def set_metadata_from_websocket(self,
165
+ websocket: WebSocket,
166
+ user_message_id: str | None,
167
+ conversation_id: str | None) -> None:
165
168
  """
166
169
  Extracts and sets user metadata for Websocket connections.
167
170
  """
168
171
 
172
+ # Extract cookies from WebSocket headers (similar to HTTP request)
173
+ if websocket and hasattr(websocket, 'scope') and 'headers' in websocket.scope:
174
+ cookies = {}
175
+ for header_name, header_value in websocket.scope.get('headers', []):
176
+ if header_name == b'cookie':
177
+ cookie_header = header_value.decode('utf-8')
178
+ # Parse cookie header: "name1=value1; name2=value2"
179
+ for cookie in cookie_header.split(';'):
180
+ cookie = cookie.strip()
181
+ if '=' in cookie:
182
+ name, value = cookie.split('=', 1)
183
+ cookies[name.strip()] = value.strip()
184
+
185
+ # Set cookies in metadata (same as HTTP request)
186
+ self._context.metadata._request.cookies = cookies
187
+ self._context_state.metadata.set(self._context.metadata)
188
+
169
189
  if conversation_id is not None:
170
190
  self._context_state.conversation_id.set(conversation_id)
171
191
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nvidia-nat
3
- Version: 1.3.0a20250925
3
+ Version: 1.3.0a20250928
4
4
  Summary: NVIDIA NeMo Agent toolkit
5
5
  Author: NVIDIA Corporation
6
6
  Maintainer: NVIDIA Corporation
@@ -305,6 +305,7 @@ Requires-Dist: nat_router_agent; extra == "examples"
305
305
  Requires-Dist: nat_semantic_kernel_demo; extra == "examples"
306
306
  Requires-Dist: nat_sequential_executor; extra == "examples"
307
307
  Requires-Dist: nat_simple_auth; extra == "examples"
308
+ Requires-Dist: nat_simple_auth_mcp; extra == "examples"
308
309
  Requires-Dist: nat_simple_web_query; extra == "examples"
309
310
  Requires-Dist: nat_simple_web_query_eval; extra == "examples"
310
311
  Requires-Dist: nat_simple_calculator; extra == "examples"
@@ -323,6 +324,10 @@ Requires-Dist: aiosqlite~=0.21; extra == "async-endpoints"
323
324
  Requires-Dist: dask==2023.6; extra == "async-endpoints"
324
325
  Requires-Dist: distributed==2023.6; extra == "async-endpoints"
325
326
  Requires-Dist: sqlalchemy[asyncio]~=2.0; extra == "async-endpoints"
327
+ Provides-Extra: litellm
328
+ Requires-Dist: litellm==1.74.9; extra == "litellm"
329
+ Provides-Extra: openai
330
+ Requires-Dist: openai~=1.106; extra == "openai"
326
331
  Dynamic: license-file
327
332
 
328
333
  <!--
@@ -10,21 +10,21 @@ nat/agent/react_agent/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3h
10
10
  nat/agent/react_agent/agent.py,sha256=sWrg9WrglTKQQyG3EcjNm2JTEchCPEo9li-Po7TJKss,21294
11
11
  nat/agent/react_agent/output_parser.py,sha256=m7K6wRwtckBBpAHqOf3BZ9mqZLwrP13Kxz5fvNxbyZE,4219
12
12
  nat/agent/react_agent/prompt.py,sha256=N47JJrT6xwYQCv1jedHhlul2AE7EfKsSYfAbgJwWRew,1758
13
- nat/agent/react_agent/register.py,sha256=IYd6VAsgK8lwT78ScmSrGv2QOyB5d_bh-L3MwlHVN1A,9004
13
+ nat/agent/react_agent/register.py,sha256=b97dfNtA0I3bNBOGdr9_akQ89UDwPHPPb7LqpsZNaWI,8815
14
14
  nat/agent/reasoning_agent/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
15
  nat/agent/reasoning_agent/reasoning_agent.py,sha256=k_0wEDqACQn1Rn1MAKxoXyqOKsthHCQ1gt990YYUqHU,9575
16
16
  nat/agent/rewoo_agent/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
17
  nat/agent/rewoo_agent/agent.py,sha256=ogTtUsNqbAjEprBKp2ZEoYfuHvgxnjV7NgygvSgMz7M,19264
18
18
  nat/agent/rewoo_agent/prompt.py,sha256=nFMav3Zl_vmKPLzAIhbQHlldWnurPJb1GlwnekUuxDs,3720
19
- nat/agent/rewoo_agent/register.py,sha256=C1dUBg53QVhdniiURyWGzbi5y4GvzCIOtErH2Q0zSbQ,9148
19
+ nat/agent/rewoo_agent/register.py,sha256=668zAag6eqajX_PIfh6c-0I0UQN5D-lRiz_mNKHXXjM,8954
20
20
  nat/agent/tool_calling_agent/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
21
21
  nat/agent/tool_calling_agent/agent.py,sha256=4SIp29I56oznPRQu7B3HCoX53Ri3_o3BRRYNJjeBkF8,11006
22
- nat/agent/tool_calling_agent/register.py,sha256=Jll3Trb4rF7yYxNbZhkcRbW1sEsZ6tZkBdGN-Qw0Hb8,6905
22
+ nat/agent/tool_calling_agent/register.py,sha256=ijiRfgDVtt2p7_q1YbIQZmUVV8-jf3yT18HwtKyReUI,6822
23
23
  nat/authentication/__init__.py,sha256=Xs1JQ16L9btwreh4pdGKwskffAw1YFO48jKrU4ib_7c,685
24
- nat/authentication/interfaces.py,sha256=FAYM-QXVUn3a_8bmAZ7kP-lmN_BrLW8mo6krZJ3e0ME,3314
24
+ nat/authentication/interfaces.py,sha256=1J2CWEJ_n6CLA3_HD3XV28CSbyfxrPAHzr7Q4kKDFdc,3511
25
25
  nat/authentication/register.py,sha256=lFhswYUk9iZ53mq33fClR9UfjJPdjGIivGGNHQeWiYo,915
26
26
  nat/authentication/api_key/__init__.py,sha256=GUJrgGtpvyMUCjUBvR3faAdv-tZzbU9W-izgx9aMEQg,680
27
- nat/authentication/api_key/api_key_auth_provider.py,sha256=DoN1MoeB_uOWQMHUz2OiyhwbFxQkj0FOifN2TFr4sds,4022
27
+ nat/authentication/api_key/api_key_auth_provider.py,sha256=QGRZZilD2GryhRJoODfKqypH54IwQp0I-Cck40Dc7dM,4032
28
28
  nat/authentication/api_key/api_key_auth_provider_config.py,sha256=zfkxH3yvUSKKldRf1K4PPm0rJLXGH0GDH8xj7anPYGQ,5472
29
29
  nat/authentication/api_key/register.py,sha256=Mhv3WyZ9H7C2JN8VuPvwlsJEZrwXJCLXCIokkN9RrP0,1147
30
30
  nat/authentication/credential_validator/__init__.py,sha256=GUJrgGtpvyMUCjUBvR3faAdv-tZzbU9W-izgx9aMEQg,680
@@ -32,10 +32,10 @@ nat/authentication/credential_validator/bearer_token_validator.py,sha256=cwGENd_
32
32
  nat/authentication/exceptions/__init__.py,sha256=Xs1JQ16L9btwreh4pdGKwskffAw1YFO48jKrU4ib_7c,685
33
33
  nat/authentication/exceptions/api_key_exceptions.py,sha256=6wnz951BI77rFYuHxoHOthz-y5oE08uxsuM6G5EvOyM,1545
34
34
  nat/authentication/http_basic_auth/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
35
- nat/authentication/http_basic_auth/http_basic_auth_provider.py,sha256=vmukbeI32aK6Ulc-yoaFHszr6BqmCvZHIpKr4-arMhs,3442
35
+ nat/authentication/http_basic_auth/http_basic_auth_provider.py,sha256=OXr5TV87SiZtzSK9i_E6WXWyVhWq2MfqO_SS1aZ3p6U,3452
36
36
  nat/authentication/http_basic_auth/register.py,sha256=N2VD0vw7cYABsLxsGXl5yw0htc8adkrB0Y_EMxKwFfk,1235
37
37
  nat/authentication/oauth2/__init__.py,sha256=Xs1JQ16L9btwreh4pdGKwskffAw1YFO48jKrU4ib_7c,685
38
- nat/authentication/oauth2/oauth2_auth_code_flow_provider.py,sha256=iFp_kImFwDrweFHGTg4n9RGybH3-wRSJkyh-FPOxwDA,4538
38
+ nat/authentication/oauth2/oauth2_auth_code_flow_provider.py,sha256=TDZvGbpCLW6EDCI-a4Z9KnQyUEcRaJ5hBCPVyIuy-KY,5099
39
39
  nat/authentication/oauth2/oauth2_auth_code_flow_provider_config.py,sha256=e165ysd2pX2WTbV3_FQKEjEaa4TAXkJ7B98WUGbqnGE,2204
40
40
  nat/authentication/oauth2/oauth2_resource_server_config.py,sha256=ltcNp8Dwb2Q4tlwMN5Cl0B5pouTLtXRoV-QopfqV45M,5314
41
41
  nat/authentication/oauth2/register.py,sha256=7rXhf-ilgSS_bUJsd9pOOCotL1FM8dKUt3ke1TllKkQ,1228
@@ -48,7 +48,7 @@ nat/builder/eval_builder.py,sha256=I-ScvupmorClYoVBIs_PhSsB7Xf9e2nGWe0rCZp3txo,6
48
48
  nat/builder/evaluator.py,sha256=xWHMND2vcAUkdFP7FU3jnVki1rUHeTa0-9saFh2hWKs,1162
49
49
  nat/builder/framework_enum.py,sha256=n7IaTQBxhFozIQqRMcX9kXntw28JhFzCj82jJ0C5tNU,901
50
50
  nat/builder/front_end.py,sha256=mHooS1M7mVo1swSgbYoqbzQENXkuG7_Es9q4gFiuL8E,2175
51
- nat/builder/function.py,sha256=udq0pUpaQss8Fr-EzPnJ4aahvCK298xXNYyf4jceFfg,27698
51
+ nat/builder/function.py,sha256=RrfKSCt9WunPhwn5fk8X7wuvb9A21iO8T-IySHUi3KM,27763
52
52
  nat/builder/function_base.py,sha256=0Eg8RtjWhEU3Yme0CVxcRutobA0Qo8-YHZLI6L2qAgM,13116
53
53
  nat/builder/function_info.py,sha256=7Rmrn-gOFrT2TIJklJwA_O-ycx_oimwZ0-qMYpbuZrU,25161
54
54
  nat/builder/intermediate_step_manager.py,sha256=iOuMLWTaES0J0XzaLxhTUqFvuoCAChJu3V69T43K0k0,7599
@@ -83,7 +83,7 @@ nat/cli/commands/info/info.py,sha256=BGqshIEDpNRH9hM-06k-Gq-QX-qNddPICSWCN-ReC-g
83
83
  nat/cli/commands/info/list_channels.py,sha256=K97TE6wtikgImY-wAbFNi0HHUGtkvIFd2woaG06VkT0,1277
84
84
  nat/cli/commands/info/list_components.py,sha256=QlAJVONBA77xW8Lx6Autw5NTAZNy_VrJGr1GL9MfnHM,4532
85
85
  nat/cli/commands/mcp/__init__.py,sha256=GUJrgGtpvyMUCjUBvR3faAdv-tZzbU9W-izgx9aMEQg,680
86
- nat/cli/commands/mcp/mcp.py,sha256=CrpOOZZGq1nSsuFU_6h_VBL5ZE92Yr30WV9c5iirtzY,33332
86
+ nat/cli/commands/mcp/mcp.py,sha256=Phtxegf0Ww89NHrwj4dEZh3vaHxjm7RV7NZMByUGhpM,43860
87
87
  nat/cli/commands/object_store/__init__.py,sha256=GUJrgGtpvyMUCjUBvR3faAdv-tZzbU9W-izgx9aMEQg,680
88
88
  nat/cli/commands/object_store/object_store.py,sha256=_ivB-R30a-66fNy-fUzi58HQ0Ay0gYsGz7T1xXoRa3Y,8576
89
89
  nat/cli/commands/registry/__init__.py,sha256=GUJrgGtpvyMUCjUBvR3faAdv-tZzbU9W-izgx9aMEQg,680
@@ -113,7 +113,7 @@ nat/control_flow/router_agent/register.py,sha256=p15Jy05PjJhXRrjqWiEgy47zmc-CFCu
113
113
  nat/data_models/__init__.py,sha256=Xs1JQ16L9btwreh4pdGKwskffAw1YFO48jKrU4ib_7c,685
114
114
  nat/data_models/agent.py,sha256=IwDyb9Zc3R4Zd5rFeqt7q0EQswczAl5focxV9KozIzs,1625
115
115
  nat/data_models/api_server.py,sha256=Zl0eAd-yV9PD8vUH8eWRvXFcUBdY2tENKe73q-Uxxgg,25699
116
- nat/data_models/authentication.py,sha256=t9-2CQaIfk74DM3CLaJU5NAYGs7m6BjdFFm1hj8WwtY,9064
116
+ nat/data_models/authentication.py,sha256=wpH8tpy_wt1aA3eKIgbc8HfYdr_g6AfM7-NfWBZh-KA,8528
117
117
  nat/data_models/common.py,sha256=nXXfGrjpxebzBUa55mLdmzePLt7VFHvTAc6Znj3yEv0,5875
118
118
  nat/data_models/component.py,sha256=b_hXOA8Gm5UNvlFkAhsR6kEvf33ST50MKtr5kWf75Ao,1894
119
119
  nat/data_models/component_ref.py,sha256=KFDWFVCcvJCfBBcXTh9f3R802EVHBtHXh9OdbRqFmdM,4747
@@ -234,7 +234,7 @@ nat/front_ends/register.py,sha256=_C6AFpsQ8hUXavKHaBMy0g137fOcLfEjyU0EAuYqtao,85
234
234
  nat/front_ends/console/__init__.py,sha256=Xs1JQ16L9btwreh4pdGKwskffAw1YFO48jKrU4ib_7c,685
235
235
  nat/front_ends/console/authentication_flow_handler.py,sha256=Q1A7dv-pUlzsGZ8NXu8r-aGCqRiFqadPPBOw2TmyUNk,9566
236
236
  nat/front_ends/console/console_front_end_config.py,sha256=wkMXk-RCdlEj3303kB1gh47UKJnubX2R-vzBzhedpS4,1318
237
- nat/front_ends/console/console_front_end_plugin.py,sha256=wVsc8CVpphT2Tq0UJJF_a2tAoE1yuZbnkA7VgHki5CA,4133
237
+ nat/front_ends/console/console_front_end_plugin.py,sha256=euUxC794jhZgODNMfxriCkeHn9eluU1UwWYUnyDh-iU,4315
238
238
  nat/front_ends/console/register.py,sha256=2Kf6Mthx6jzWzU8YdhYIR1iABmZDvs1UXM_20npXWXs,1153
239
239
  nat/front_ends/cron/__init__.py,sha256=Xs1JQ16L9btwreh4pdGKwskffAw1YFO48jKrU4ib_7c,685
240
240
  nat/front_ends/fastapi/__init__.py,sha256=Xs1JQ16L9btwreh4pdGKwskffAw1YFO48jKrU4ib_7c,685
@@ -269,10 +269,10 @@ nat/front_ends/simple_base/simple_front_end_plugin_base.py,sha256=py_yA9XAw-yHfK
269
269
  nat/llm/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
270
270
  nat/llm/aws_bedrock_llm.py,sha256=-P6OltFz8CPHmKmgUipFaIpROLGdnnRmd-q5BfjY7lM,3219
271
271
  nat/llm/azure_openai_llm.py,sha256=30JWbNyscHhuRjFdWF2yLAEcKurY0q2BSMVFTdtSv9g,2649
272
- nat/llm/litellm_llm.py,sha256=8dy5TGK6Oz8XU1epzUFdgfO1fxDhjkt3QTU4e7tEFrE,2775
272
+ nat/llm/litellm_llm.py,sha256=3XtAKdI4lmbbuiEGKSJob0mqAp8RvYRpxK6t0GQk0UE,2770
273
273
  nat/llm/nim_llm.py,sha256=9sU3FUOedx5jY3He3qiN0T-AC48F5maIpz87NxP7Q0Q,2696
274
274
  nat/llm/openai_llm.py,sha256=AMf8Xxzo3kYVi7XfyqatuU1-CH0-8QGmshDbSHHREXY,2487
275
- nat/llm/register.py,sha256=0cA_tYB2auDeq7mMlVFe47H_A5Trh8XommsygOeR96Y,1090
275
+ nat/llm/register.py,sha256=7xDYdK4w4opAwIjzDM5x7moJXT3QeEGaGGc_nDfY0i4,1090
276
276
  nat/llm/utils/__init__.py,sha256=GUJrgGtpvyMUCjUBvR3faAdv-tZzbU9W-izgx9aMEQg,680
277
277
  nat/llm/utils/env_config_value.py,sha256=kBVsv0pEokIAfDQx5omR7_FevFv_5fTPswcbnvhVT2c,3548
278
278
  nat/llm/utils/error.py,sha256=gFFDG_v_3hBZVWpcD7HWkno-NBHDjXae7qDGnfiCNwA,820
@@ -406,8 +406,8 @@ nat/retriever/nemo_retriever/register.py,sha256=3XdrvEJzX2Zc8wpdm__4YYlEWBW-FK3t
406
406
  nat/retriever/nemo_retriever/retriever.py,sha256=gi3_qJFqE-iqRh3of_cmJg-SwzaQ3z24zA9LwY_MSLY,6930
407
407
  nat/runtime/__init__.py,sha256=Xs1JQ16L9btwreh4pdGKwskffAw1YFO48jKrU4ib_7c,685
408
408
  nat/runtime/loader.py,sha256=obUdAgZVYCPGC0R8u3wcoKFJzzSPQgJvrbU4OWygtog,7953
409
- nat/runtime/runner.py,sha256=CVC8F6D3cm4kNCzFSzl36G9F6rWgmGGMcMoN5IlFeTo,6388
410
- nat/runtime/session.py,sha256=U3UHQpdCBkCiJetsWdq9r6wUEVDBa2gv1VQedE64kY8,6959
409
+ nat/runtime/runner.py,sha256=Kzm5GRrGUFMQ_fbLOCJumYc4R-JXdTm5tUw2yMMDJpE,6450
410
+ nat/runtime/session.py,sha256=DG4cpVg6GCVFY0cGzZnz55eLj0LoK5Q9Vg3NgbTqOHM,8029
411
411
  nat/runtime/user_metadata.py,sha256=ce37NRYJWnMOWk6A7VAQ1GQztjMmkhMOq-uYf2gNCwo,3692
412
412
  nat/settings/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
413
413
  nat/settings/global_settings.py,sha256=JSlYnW3CeGJYGxlaXLz5F9xXf72I5TUz-w6qngG5di0,12476
@@ -469,10 +469,10 @@ nat/utils/reactive/base/observer_base.py,sha256=6BiQfx26EMumotJ3KoVcdmFBYR_fnAss
469
469
  nat/utils/reactive/base/subject_base.py,sha256=UQOxlkZTIeeyYmG5qLtDpNf_63Y7p-doEeUA08_R8ME,2521
470
470
  nat/utils/settings/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
471
471
  nat/utils/settings/global_settings.py,sha256=9JaO6pxKT_Pjw6rxJRsRlFCXdVKCl_xUKU2QHZQWWNM,7294
472
- nvidia_nat-1.3.0a20250925.dist-info/licenses/LICENSE-3rd-party.txt,sha256=fOk5jMmCX9YoKWyYzTtfgl-SUy477audFC5hNY4oP7Q,284609
473
- nvidia_nat-1.3.0a20250925.dist-info/licenses/LICENSE.md,sha256=QwcOLU5TJoTeUhuIXzhdCEEDDvorGiC6-3YTOl4TecE,11356
474
- nvidia_nat-1.3.0a20250925.dist-info/METADATA,sha256=jnLQD_533roNyYOS9lke0wyztEHmR6vZLvP6t3QVkHU,22716
475
- nvidia_nat-1.3.0a20250925.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
476
- nvidia_nat-1.3.0a20250925.dist-info/entry_points.txt,sha256=4jCqjyETMpyoWbCBf4GalZU8I_wbstpzwQNezdAVbbo,698
477
- nvidia_nat-1.3.0a20250925.dist-info/top_level.txt,sha256=lgJWLkigiVZuZ_O1nxVnD_ziYBwgpE2OStdaCduMEGc,8
478
- nvidia_nat-1.3.0a20250925.dist-info/RECORD,,
472
+ nvidia_nat-1.3.0a20250928.dist-info/licenses/LICENSE-3rd-party.txt,sha256=fOk5jMmCX9YoKWyYzTtfgl-SUy477audFC5hNY4oP7Q,284609
473
+ nvidia_nat-1.3.0a20250928.dist-info/licenses/LICENSE.md,sha256=QwcOLU5TJoTeUhuIXzhdCEEDDvorGiC6-3YTOl4TecE,11356
474
+ nvidia_nat-1.3.0a20250928.dist-info/METADATA,sha256=wgL7swlr3yFBn22PDRQ4CdjY7nIE_q2IgV_bKmiuZVc,22918
475
+ nvidia_nat-1.3.0a20250928.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
476
+ nvidia_nat-1.3.0a20250928.dist-info/entry_points.txt,sha256=4jCqjyETMpyoWbCBf4GalZU8I_wbstpzwQNezdAVbbo,698
477
+ nvidia_nat-1.3.0a20250928.dist-info/top_level.txt,sha256=lgJWLkigiVZuZ_O1nxVnD_ziYBwgpE2OStdaCduMEGc,8
478
+ nvidia_nat-1.3.0a20250928.dist-info/RECORD,,